11// Copyright (c) Microsoft Corporation.
22// Licensed under the MIT License.
33
4+ using System . Net ;
45using System . Text . Json ;
56using Microsoft . Mcp . Tests ;
67using Microsoft . Mcp . Tests . Client ;
@@ -62,49 +63,49 @@ public async Task Client_Should_Ping_Server_Successfully()
6263 // The `ping` method was removed in the MCP 2026-07-28 protocol revision. The client
6364 // negotiates the modern protocol, so the server rejects ping as unavailable.
6465 // (Method name is retained so the recorded playback session continues to match.)
65- var ex = await Assert . ThrowsAsync < McpProtocolException > ( async ( ) =>
66- await Client . PingAsync ( cancellationToken : TestContext . Current . CancellationToken ) ) ;
67- Assert . Contains ( "ping" , ex . Message , StringComparison . OrdinalIgnoreCase ) ;
66+ await AssertMethodNotFoundAsync (
67+ async ( ) => await Client . PingAsync ( cancellationToken : TestContext . Current . CancellationToken ) ,
68+ "ping" ) ;
6869 }
6970
7071 [ Fact ]
7172 public async Task Should_Error_When_Resources_List_Not_Supported ( )
7273 {
73- var ex = await Assert . ThrowsAsync < McpProtocolException > ( async ( ) => await Client . ListResourcesAsync ( cancellationToken : TestContext . Current . CancellationToken ) ) ;
74- Assert . Contains ( "Request failed" , ex . Message ) ;
75- Assert . Equal ( McpErrorCode . MethodNotFound , ex . ErrorCode ) ;
74+ await AssertMethodNotFoundAsync (
75+ async ( ) => await Client . ListResourcesAsync ( cancellationToken : TestContext . Current . CancellationToken ) ,
76+ "resources/list" ) ;
7677 }
7778
7879 [ Fact ]
7980 public async Task Should_Error_When_Resources_Read_Not_Supported ( )
8081 {
81- var ex = await Assert . ThrowsAsync < McpProtocolException > ( async ( ) => await Client . ReadResourceAsync ( "test://resource" , cancellationToken : TestContext . Current . CancellationToken ) ) ;
82- Assert . Contains ( "Request failed ", ex . Message ) ;
83- Assert . Equal ( McpErrorCode . MethodNotFound , ex . ErrorCode ) ;
82+ await AssertMethodNotFoundAsync (
83+ async ( ) => await Client . ReadResourceAsync ( "test://resource ", cancellationToken : TestContext . Current . CancellationToken ) ,
84+ "resources/read" ) ;
8485 }
8586
8687 [ Fact ]
8788 public async Task Should_Error_When_Resources_Templates_List_Not_Supported ( )
8889 {
89- var ex = await Assert . ThrowsAsync < McpProtocolException > ( async ( ) => await Client . ListResourceTemplatesAsync ( cancellationToken : TestContext . Current . CancellationToken ) ) ;
90- Assert . Contains ( "Request failed" , ex . Message ) ;
91- Assert . Equal ( McpErrorCode . MethodNotFound , ex . ErrorCode ) ;
90+ await AssertMethodNotFoundAsync (
91+ async ( ) => await Client . ListResourceTemplatesAsync ( cancellationToken : TestContext . Current . CancellationToken ) ,
92+ "resources/templates/list" ) ;
9293 }
9394
9495 [ Fact ]
9596 public async Task Should_Error_When_Resources_Subscribe_Not_Supported ( )
9697 {
97- var ex = await Assert . ThrowsAsync < McpProtocolException > ( async ( ) => await Client . SubscribeToResourceAsync ( "test://resource" , cancellationToken : TestContext . Current . CancellationToken ) ) ;
98- Assert . Contains ( "Request failed ", ex . Message ) ;
99- Assert . Equal ( McpErrorCode . MethodNotFound , ex . ErrorCode ) ;
98+ await AssertMethodNotFoundAsync (
99+ ( ) => Client . SubscribeToResourceAsync ( "test://resource ", cancellationToken : TestContext . Current . CancellationToken ) ,
100+ "resources/subscribe" ) ;
100101 }
101102
102103 [ Fact ]
103104 public async Task Should_Error_When_Resources_Unsubscribe_Not_Supported ( )
104105 {
105- var ex = await Assert . ThrowsAsync < McpProtocolException > ( async ( ) => await Client . UnsubscribeFromResourceAsync ( "test://resource" , cancellationToken : TestContext . Current . CancellationToken ) ) ;
106- Assert . Contains ( "Request failed ", ex . Message ) ;
107- Assert . Equal ( McpErrorCode . MethodNotFound , ex . ErrorCode ) ;
106+ await AssertMethodNotFoundAsync (
107+ ( ) => Client . UnsubscribeFromResourceAsync ( "test://resource ", cancellationToken : TestContext . Current . CancellationToken ) ,
108+ "resources/unsubscribe" ) ;
108109 }
109110
110111 [ Fact ]
@@ -114,27 +115,42 @@ public async Task Should_Not_Hang_On_Logging_SetLevel_Not_Supported()
114115 // The method is no longer supported; per-request log level is now set via
115116 // _meta/io.modelcontextprotocol/logLevel. The call should throw rather than hang.
116117#pragma warning disable MCP9005 // Type or member is obsolete
117- var ex = await Assert . ThrowsAsync < McpProtocolException > (
118- async ( ) => await Client . SetLoggingLevelAsync ( LoggingLevel . Info ,
119- cancellationToken : TestContext . Current . CancellationToken ) ) ;
118+ await AssertMethodNotFoundAsync (
119+ ( ) => Client . SetLoggingLevelAsync ( LoggingLevel . Info ,
120+ cancellationToken : TestContext . Current . CancellationToken ) ,
121+ "logging/setLevel" ) ;
120122#pragma warning restore MCP9005 // Type or member is obsolete
121- Assert . Contains ( "logging/setLevel" , ex . Message , StringComparison . OrdinalIgnoreCase ) ;
122123 }
123124
124125 [ Fact ]
125126 public async Task Should_Error_When_Prompts_List_Not_Supported ( )
126127 {
127- var ex = await Assert . ThrowsAsync < McpProtocolException > ( async ( ) => await Client . ListPromptsAsync ( cancellationToken : TestContext . Current . CancellationToken ) ) ;
128- Assert . Contains ( "Request failed" , ex . Message ) ;
129- Assert . Equal ( McpErrorCode . MethodNotFound , ex . ErrorCode ) ;
128+ await AssertMethodNotFoundAsync (
129+ async ( ) => await Client . ListPromptsAsync ( cancellationToken : TestContext . Current . CancellationToken ) ,
130+ "prompts/list" ) ;
130131 }
131132
132133 [ Fact ]
133134 public async Task Should_Error_When_Prompts_Get_Not_Supported ( )
134135 {
135- var ex = await Assert . ThrowsAsync < McpProtocolException > ( async ( ) => await Client . GetPromptAsync ( "unsupported_prompt" , cancellationToken : TestContext . Current . CancellationToken ) ) ;
136- Assert . Contains ( "Request failed" , ex . Message ) ;
137- Assert . Equal ( McpErrorCode . MethodNotFound , ex . ErrorCode ) ;
136+ await AssertMethodNotFoundAsync (
137+ async ( ) => await Client . GetPromptAsync ( "unsupported_prompt" , cancellationToken : TestContext . Current . CancellationToken ) ,
138+ "prompts/get" ) ;
139+ }
140+
141+ private static async Task AssertMethodNotFoundAsync ( Func < Task > action , string method )
142+ {
143+ if ( string . Equals ( Environment . GetEnvironmentVariable ( "MCP_TEST_TRANSPORT" ) , "http" , StringComparison . OrdinalIgnoreCase ) )
144+ {
145+ var exception = await Assert . ThrowsAsync < HttpRequestException > ( action ) ;
146+ Assert . Equal ( HttpStatusCode . NotFound , exception . StatusCode ) ;
147+ Assert . Contains ( method , exception . Message , StringComparison . OrdinalIgnoreCase ) ;
148+ return ;
149+ }
150+
151+ var protocolException = await Assert . ThrowsAsync < McpProtocolException > ( action ) ;
152+ Assert . Equal ( McpErrorCode . MethodNotFound , protocolException . ErrorCode ) ;
153+ Assert . Contains ( method , protocolException . Message , StringComparison . OrdinalIgnoreCase ) ;
138154 }
139155
140156 public override List < BodyRegexSanitizer > BodyRegexSanitizers =>
0 commit comments