1+ using Microsoft . Extensions . AI ;
12using Microsoft . Extensions . DependencyInjection ;
23using ModelContextProtocol . Client ;
34using ModelContextProtocol . Configuration ;
45using ModelContextProtocol . Protocol . Transport ;
6+ using ModelContextProtocol . Protocol . Types ;
57using ModelContextProtocol . Server ;
68using ModelContextProtocol . Tests . Transport ;
9+ using Moq ;
710using System . IO . Pipelines ;
811
912namespace ModelContextProtocol . Tests . Client ;
@@ -29,6 +32,153 @@ public McpClientExtensionsTests()
2932 _server = sc . BuildServiceProvider ( ) . GetRequiredService < IMcpServer > ( ) ;
3033 }
3134
35+ [ Theory ]
36+ [ InlineData ( null , null ) ]
37+ [ InlineData ( 0.7f , 50 ) ]
38+ [ InlineData ( 1.0f , 100 ) ]
39+ public async Task CreateSamplingHandler_ShouldHandleTextMessages ( float ? temperature , int ? maxTokens )
40+ {
41+ // Arrange
42+ var mockChatClient = new Mock < IChatClient > ( ) ;
43+ var requestParams = new CreateMessageRequestParams
44+ {
45+ Messages =
46+ [
47+ new SamplingMessage
48+ {
49+ Role = Role . User ,
50+ Content = new Content { Type = "text" , Text = "Hello" }
51+ }
52+ ] ,
53+ Temperature = temperature ,
54+ MaxTokens = maxTokens
55+ } ;
56+
57+ var cancellationToken = CancellationToken . None ;
58+ var expectedResponse = new ChatResponse
59+ {
60+ Messages = { new ChatMessage { Role = ChatRole . Assistant , Contents = { new TextContent ( "Hi there!" ) } } } ,
61+ ModelId = "test-model" ,
62+ FinishReason = ChatFinishReason . Stop
63+ } ;
64+
65+ mockChatClient
66+ . Setup ( client => client . GetResponseAsync ( It . IsAny < IList < ChatMessage > > ( ) , It . IsAny < ChatOptions > ( ) , cancellationToken ) )
67+ . ReturnsAsync ( expectedResponse ) ;
68+
69+ var handler = McpClientExtensions . CreateSamplingHandler ( mockChatClient . Object ) ;
70+
71+ // Act
72+ var result = await handler ( requestParams , cancellationToken ) ;
73+
74+ // Assert
75+ Assert . NotNull ( result ) ;
76+ Assert . Equal ( "Hi there!" , result . Content . Text ) ;
77+ Assert . Equal ( "test-model" , result . Model ) ;
78+ Assert . Equal ( "assistant" , result . Role ) ;
79+ Assert . Equal ( "endTurn" , result . StopReason ) ;
80+ }
81+
82+ [ Fact ]
83+ public async Task CreateSamplingHandler_ShouldHandleImageMessages ( )
84+ {
85+ // Arrange
86+ var mockChatClient = new Mock < IChatClient > ( ) ;
87+ var requestParams = new CreateMessageRequestParams
88+ {
89+ Messages = new [ ]
90+ {
91+ new SamplingMessage
92+ {
93+ Role = Role . User ,
94+ Content = new Content
95+ {
96+ Type = "image" ,
97+ MimeType = "image/png" ,
98+ Data = Convert . ToBase64String ( new byte [ ] { 1 , 2 , 3 } )
99+ }
100+ }
101+ } ,
102+ MaxTokens = 100
103+ } ;
104+ var cancellationToken = CancellationToken . None ;
105+
106+ var expectedResponse = new ChatResponse
107+ {
108+ Messages = { new ChatMessage { Role = ChatRole . Assistant , Contents = new [ ] { new TextContent ( "Image received!" ) } } } ,
109+ ModelId = "test-model" ,
110+ FinishReason = ChatFinishReason . Stop
111+ } ;
112+
113+ mockChatClient
114+ . Setup ( client => client . GetResponseAsync ( It . IsAny < IList < ChatMessage > > ( ) , It . IsAny < ChatOptions > ( ) , cancellationToken ) )
115+ . ReturnsAsync ( expectedResponse ) ;
116+
117+ var handler = McpClientExtensions . CreateSamplingHandler ( mockChatClient . Object ) ;
118+
119+ // Act
120+ var result = await handler ( requestParams , cancellationToken ) ;
121+
122+ // Assert
123+ Assert . NotNull ( result ) ;
124+ Assert . Equal ( "Image received!" , result . Content . Text ) ;
125+ Assert . Equal ( "test-model" , result . Model ) ;
126+ Assert . Equal ( "assistant" , result . Role ) ;
127+ Assert . Equal ( "endTurn" , result . StopReason ) ;
128+ }
129+
130+ [ Fact ]
131+ public async Task CreateSamplingHandler_ShouldHandleResourceMessages ( )
132+ {
133+ // Arrange
134+ var mockChatClient = new Mock < IChatClient > ( ) ;
135+ var requestParams = new CreateMessageRequestParams
136+ {
137+ Messages = new [ ]
138+ {
139+ new SamplingMessage
140+ {
141+ Role = Role . User ,
142+ Content = new Content
143+ {
144+ Type = "resource" ,
145+ Resource = new ResourceContents
146+ {
147+ Text = "Resource text" ,
148+ Blob = Convert . ToBase64String ( new byte [ ] { 4 , 5 , 6 } ) ,
149+ MimeType = "application/octet-stream"
150+ }
151+ }
152+ }
153+ } ,
154+ MaxTokens = 100
155+ } ;
156+ var cancellationToken = CancellationToken . None ;
157+
158+ var expectedResponse = new ChatResponse
159+ {
160+ Messages = { new ChatMessage { Role = ChatRole . Assistant , Contents = new [ ] { new TextContent ( "Resource processed!" ) } } } ,
161+ ModelId = "test-model" ,
162+ FinishReason = ChatFinishReason . Stop
163+ } ;
164+
165+ mockChatClient
166+ . Setup ( client => client . GetResponseAsync ( It . IsAny < IList < ChatMessage > > ( ) , It . IsAny < ChatOptions > ( ) , cancellationToken ) )
167+ . ReturnsAsync ( expectedResponse ) ;
168+
169+ var handler = McpClientExtensions . CreateSamplingHandler ( mockChatClient . Object ) ;
170+
171+ // Act
172+ var result = await handler ( requestParams , cancellationToken ) ;
173+
174+ // Assert
175+ Assert . NotNull ( result ) ;
176+ Assert . Equal ( "Resource processed!" , result . Content . Text ) ;
177+ Assert . Equal ( "test-model" , result . Model ) ;
178+ Assert . Equal ( "assistant" , result . Role ) ;
179+ Assert . Equal ( "endTurn" , result . StopReason ) ;
180+ }
181+
32182 public ValueTask DisposeAsync ( )
33183 {
34184 _clientToServerPipe . Writer . Complete ( ) ;
0 commit comments