|
1 | 1 | using ModelContextProtocol.Client; |
2 | 2 | using ModelContextProtocol.Protocol.Types; |
3 | 3 | using ModelContextProtocol.Tests.Utils; |
| 4 | +using System.Net; |
| 5 | +using System.Text; |
4 | 6 |
|
5 | 7 | namespace ModelContextProtocol.Tests; |
6 | 8 |
|
@@ -30,6 +32,12 @@ private Task<IMcpClient> GetClientAsync(McpClientOptions? options = null) |
30 | 32 | cancellationToken: TestContext.Current.CancellationToken); |
31 | 33 | } |
32 | 34 |
|
| 35 | + private HttpClient GetHttpClient() => |
| 36 | + new() |
| 37 | + { |
| 38 | + BaseAddress = new(_fixture.DefaultConfig.Location!), |
| 39 | + }; |
| 40 | + |
33 | 41 | [Fact] |
34 | 42 | public async Task ConnectAndPing_Sse_TestServer() |
35 | 43 | { |
@@ -271,4 +279,46 @@ public async Task CallTool_Sse_EchoServer_Concurrently() |
271 | 279 | Assert.Equal($"Echo: Hello MCP! {i}", textContent.Text); |
272 | 280 | } |
273 | 281 | } |
| 282 | + |
| 283 | + [Fact] |
| 284 | + public async Task EventSourceStream_Includes_MessageEventType() |
| 285 | + { |
| 286 | + // Simulate our own MCP client handshake using a plain HttpClient so we can look for "event: message" |
| 287 | + // in the raw SSE response stream which is not exposed by the real MCP client. |
| 288 | + using var httpClient = GetHttpClient(); |
| 289 | + await using var sseResponse = await httpClient.GetStreamAsync("", TestContext.Current.CancellationToken); |
| 290 | + using var streamReader = new StreamReader(sseResponse); |
| 291 | + |
| 292 | + // read event stream from the server |
| 293 | + var endpointEvent = await streamReader.ReadLineAsync(TestContext.Current.CancellationToken); |
| 294 | + Assert.Equal("event: endpoint", endpointEvent); |
| 295 | + |
| 296 | + var endpointData = await streamReader.ReadLineAsync(TestContext.Current.CancellationToken); |
| 297 | + Assert.NotNull(endpointData); |
| 298 | + Assert.StartsWith("data: ", endpointData); |
| 299 | + var messageEndpoint = endpointData["data: ".Length..]; |
| 300 | + |
| 301 | + const string initializeRequest = """ |
| 302 | + {"jsonrpc":"2.0","id":"1","method":"initialize","params":{"protocolVersion":"2024-11-05","capabilities":{},"clientInfo":{"name":"IntegrationTestClient","version":"1.0.0"}}} |
| 303 | + """; |
| 304 | + using (var initializeRequestBody = new StringContent(initializeRequest, Encoding.UTF8, "application/json")) |
| 305 | + { |
| 306 | + var response = await httpClient.PostAsync(messageEndpoint, initializeRequestBody, TestContext.Current.CancellationToken); |
| 307 | + Assert.Equal(HttpStatusCode.Accepted, response.StatusCode); |
| 308 | + } |
| 309 | + |
| 310 | + const string initializeNotification = """ |
| 311 | + {"jsonrpc":"2.0","method":"notifications/initialized"} |
| 312 | + """; |
| 313 | + using (var initializeNotificationBody = new StringContent(initializeNotification, Encoding.UTF8, "application/json")) |
| 314 | + { |
| 315 | + var response = await httpClient.PostAsync(messageEndpoint, initializeNotificationBody, TestContext.Current.CancellationToken); |
| 316 | + Assert.Equal(HttpStatusCode.Accepted, response.StatusCode); |
| 317 | + } |
| 318 | + |
| 319 | + // read event stream from the server |
| 320 | + Assert.Equal("", await streamReader.ReadLineAsync(TestContext.Current.CancellationToken)); |
| 321 | + var messageEvent = await streamReader.ReadLineAsync(TestContext.Current.CancellationToken); |
| 322 | + Assert.Equal("event: message", messageEvent); |
| 323 | + } |
274 | 324 | } |
0 commit comments