3
3
using Microsoft . Extensions . Logging ;
4
4
using ModelContextProtocol . Client ;
5
5
using ModelContextProtocol . Protocol . Messages ;
6
- using ModelContextProtocol . Protocol . Transport ;
7
6
using ModelContextProtocol . Protocol . Types ;
8
7
using ModelContextProtocol . Server ;
9
- using ModelContextProtocol . Tests . Utils ;
10
8
using Moq ;
11
- using System . IO . Pipelines ;
12
9
using System . Text . Json ;
13
10
using System . Text . Json . Serialization . Metadata ;
14
11
using System . Threading . Channels ;
15
12
16
13
namespace ModelContextProtocol . Tests . Client ;
17
14
18
- public class McpClientExtensionsTests : LoggedTest
15
+ public class McpClientExtensionsTests : ClientServerTestBase
19
16
{
20
- private readonly Pipe _clientToServerPipe = new ( ) ;
21
- private readonly Pipe _serverToClientPipe = new ( ) ;
22
- private readonly ServiceProvider _serviceProvider ;
23
- private readonly CancellationTokenSource _cts ;
24
- private readonly IMcpServer _server ;
25
- private readonly Task _serverTask ;
26
-
27
17
public McpClientExtensionsTests ( ITestOutputHelper outputHelper )
28
18
: base ( outputHelper )
29
19
{
30
- ServiceCollection sc = new ( ) ;
31
- sc . AddSingleton ( LoggerFactory ) ;
32
- sc . AddMcpServer ( ) . WithStreamServerTransport ( _clientToServerPipe . Reader . AsStream ( ) , _serverToClientPipe . Writer . AsStream ( ) ) ;
20
+ }
21
+
22
+ protected override void ConfigureServices ( ServiceCollection services , IMcpServerBuilder mcpServerBuilder )
23
+ {
33
24
for ( int f = 0 ; f < 10 ; f ++ )
34
25
{
35
26
string name = $ "Method{ f } ";
36
- sc . AddSingleton ( McpServerTool . Create ( ( int i ) => $ "{ name } Result { i } ", new ( ) { Name = name } ) ) ;
27
+ services . AddSingleton ( McpServerTool . Create ( ( int i ) => $ "{ name } Result { i } ", new ( ) { Name = name } ) ) ;
37
28
}
38
- sc . AddSingleton ( McpServerTool . Create ( [ McpServerTool ( Destructive = false , OpenWorld = true ) ] ( string i ) => $ "{ i } Result", new ( ) { Name = "ValuesSetViaAttr" } ) ) ;
39
- sc . AddSingleton ( McpServerTool . Create ( [ McpServerTool ( Destructive = false , OpenWorld = true ) ] ( string i ) => $ "{ i } Result", new ( ) { Name = "ValuesSetViaOptions" , Destructive = true , OpenWorld = false , ReadOnly = true } ) ) ;
40
- _serviceProvider = sc . BuildServiceProvider ( ) ;
29
+ services . AddSingleton ( McpServerTool . Create ( [ McpServerTool ( Destructive = false , OpenWorld = true ) ] ( string i ) => $ "{ i } Result", new ( ) { Name = "ValuesSetViaAttr" } ) ) ;
30
+ services . AddSingleton ( McpServerTool . Create ( [ McpServerTool ( Destructive = false , OpenWorld = true ) ] ( string i ) => $ "{ i } Result", new ( ) { Name = "ValuesSetViaOptions" , Destructive = true , OpenWorld = false , ReadOnly = true } ) ) ;
41
31
42
- _server = _serviceProvider . GetRequiredService < IMcpServer > ( ) ;
43
- _cts = CancellationTokenSource . CreateLinkedTokenSource ( TestContext . Current . CancellationToken ) ;
44
- _serverTask = _server . RunAsync ( cancellationToken : _cts . Token ) ;
45
32
}
46
33
47
34
[ Theory ]
@@ -218,30 +205,6 @@ public async Task CreateSamplingHandler_ShouldHandleResourceMessages()
218
205
Assert . Equal ( "endTurn" , result . StopReason ) ;
219
206
}
220
207
221
- public async ValueTask DisposeAsync ( )
222
- {
223
- await _cts . CancelAsync ( ) ;
224
-
225
- _clientToServerPipe . Writer . Complete ( ) ;
226
- _serverToClientPipe . Writer . Complete ( ) ;
227
-
228
- await _serverTask ;
229
-
230
- await _serviceProvider . DisposeAsync ( ) ;
231
- _cts . Dispose ( ) ;
232
- }
233
-
234
- private async Task < IMcpClient > CreateMcpClientForServer ( )
235
- {
236
- return await McpClientFactory . CreateAsync (
237
- new StreamClientTransport (
238
- serverInput : _clientToServerPipe . Writer . AsStream ( ) ,
239
- serverOutput : _serverToClientPipe . Reader . AsStream ( ) ,
240
- LoggerFactory ) ,
241
- loggerFactory : LoggerFactory ,
242
- cancellationToken : TestContext . Current . CancellationToken ) ;
243
- }
244
-
245
208
[ Fact ]
246
209
public async Task ListToolsAsync_AllToolsReturned ( )
247
210
{
@@ -377,15 +340,15 @@ public async Task AsClientLoggerProvider_MessagesSentToClient()
377
340
{
378
341
IMcpClient client = await CreateMcpClientForServer ( ) ;
379
342
380
- ILoggerProvider loggerProvider = _server . AsClientLoggerProvider ( ) ;
343
+ ILoggerProvider loggerProvider = Server . AsClientLoggerProvider ( ) ;
381
344
Assert . Throws < ArgumentNullException > ( "categoryName" , ( ) => loggerProvider . CreateLogger ( null ! ) ) ;
382
345
383
346
ILogger logger = loggerProvider . CreateLogger ( "TestLogger" ) ;
384
347
Assert . NotNull ( logger ) ;
385
348
386
349
Assert . Null ( logger . BeginScope ( "" ) ) ;
387
350
388
- Assert . Null ( _server . LoggingLevel ) ;
351
+ Assert . Null ( Server . LoggingLevel ) ;
389
352
Assert . False ( logger . IsEnabled ( LogLevel . Trace ) ) ;
390
353
Assert . False ( logger . IsEnabled ( LogLevel . Debug ) ) ;
391
354
Assert . False ( logger . IsEnabled ( LogLevel . Information ) ) ;
@@ -396,13 +359,13 @@ public async Task AsClientLoggerProvider_MessagesSentToClient()
396
359
await client . SetLoggingLevel ( LoggingLevel . Info , TestContext . Current . CancellationToken ) ;
397
360
398
361
DateTime start = DateTime . UtcNow ;
399
- while ( _server . LoggingLevel is null )
362
+ while ( Server . LoggingLevel is null )
400
363
{
401
364
await Task . Delay ( 1 , TestContext . Current . CancellationToken ) ;
402
365
Assert . True ( DateTime . UtcNow - start < TimeSpan . FromSeconds ( 10 ) , "Timed out waiting for logging level to be set" ) ;
403
366
}
404
367
405
- Assert . Equal ( LoggingLevel . Info , _server . LoggingLevel ) ;
368
+ Assert . Equal ( LoggingLevel . Info , Server . LoggingLevel ) ;
406
369
Assert . False ( logger . IsEnabled ( LogLevel . Trace ) ) ;
407
370
Assert . False ( logger . IsEnabled ( LogLevel . Debug ) ) ;
408
371
Assert . True ( logger . IsEnabled ( LogLevel . Information ) ) ;
0 commit comments