* Remove `McpEndpoint` & `IMcpClient` * Revise naming, add abstract classes * Fix missing renames * Move extension methods to instance methods * Add back old API, but obsoleted * Add back obsoleted factory classes * Move deprecation attributes * `SseClientTransport` -> `HttpClientTransport` * Update src/ModelContextProtocol.Core/Server/AugmentedServiceProvider.cs Co-authored-by: Stephen Halter <halter73@gmail.com> * PR feedback * PR feedback * Add back dispose lock * Fix docs projects * PR feedback * Undo `docs/*.md` changes --------- Co-authored-by: Stephen Halter <halter73@gmail.com>
109 lines
No EOL
4 KiB
C#
109 lines
No EOL
4 KiB
C#
using ModelContextProtocol.Client;
|
|
using ModelContextProtocol.Tests.Utils;
|
|
using System.Net;
|
|
|
|
namespace ModelContextProtocol.Tests.Transport;
|
|
|
|
public class HttpClientTransportAutoDetectTests(ITestOutputHelper testOutputHelper) : LoggedTest(testOutputHelper)
|
|
{
|
|
[Fact]
|
|
public async Task AutoDetectMode_UsesStreamableHttp_WhenServerSupportsIt()
|
|
{
|
|
var options = new HttpClientTransportOptions
|
|
{
|
|
Endpoint = new Uri("http://localhost"),
|
|
TransportMode = HttpTransportMode.AutoDetect,
|
|
Name = "AutoDetect test client"
|
|
};
|
|
|
|
using var mockHttpHandler = new MockHttpHandler();
|
|
using var httpClient = new HttpClient(mockHttpHandler);
|
|
await using var transport = new HttpClientTransport(options, httpClient, LoggerFactory);
|
|
|
|
// Simulate successful Streamable HTTP response for initialize
|
|
mockHttpHandler.RequestHandler = (request) =>
|
|
{
|
|
if (request.Method == HttpMethod.Post)
|
|
{
|
|
return Task.FromResult(new HttpResponseMessage
|
|
{
|
|
StatusCode = HttpStatusCode.OK,
|
|
Content = new StringContent("{\"jsonrpc\":\"2.0\",\"id\":\"init-id\",\"result\":{\"protocolVersion\":\"2024-11-05\",\"capabilities\":{\"tools\":{}}}}"),
|
|
Headers =
|
|
{
|
|
{ "Content-Type", "application/json" },
|
|
{ "mcp-session-id", "test-session" }
|
|
}
|
|
});
|
|
}
|
|
|
|
// Shouldn't reach here for successful Streamable HTTP
|
|
throw new InvalidOperationException("Unexpected request");
|
|
};
|
|
|
|
await using var session = await transport.ConnectAsync(TestContext.Current.CancellationToken);
|
|
|
|
// The auto-detecting transport should be returned
|
|
Assert.NotNull(session);
|
|
}
|
|
|
|
[Fact]
|
|
public async Task AutoDetectMode_FallsBackToSse_WhenStreamableHttpFails()
|
|
{
|
|
var options = new HttpClientTransportOptions
|
|
{
|
|
Endpoint = new Uri("http://localhost"),
|
|
TransportMode = HttpTransportMode.AutoDetect,
|
|
Name = "AutoDetect test client"
|
|
};
|
|
|
|
using var mockHttpHandler = new MockHttpHandler();
|
|
using var httpClient = new HttpClient(mockHttpHandler);
|
|
await using var transport = new HttpClientTransport(options, httpClient, LoggerFactory);
|
|
|
|
var requestCount = 0;
|
|
|
|
mockHttpHandler.RequestHandler = (request) =>
|
|
{
|
|
requestCount++;
|
|
|
|
if (request.Method == HttpMethod.Post && requestCount == 1)
|
|
{
|
|
// First POST (Streamable HTTP) fails
|
|
return Task.FromResult(new HttpResponseMessage
|
|
{
|
|
StatusCode = HttpStatusCode.NotFound,
|
|
Content = new StringContent("Streamable HTTP not supported")
|
|
});
|
|
}
|
|
|
|
if (request.Method == HttpMethod.Get)
|
|
{
|
|
// SSE connection request
|
|
return Task.FromResult(new HttpResponseMessage
|
|
{
|
|
StatusCode = HttpStatusCode.OK,
|
|
Content = new StringContent("event: endpoint\r\ndata: /sse-endpoint\r\n\r\n"),
|
|
Headers = { { "Content-Type", "text/event-stream" } }
|
|
});
|
|
}
|
|
|
|
if (request.Method == HttpMethod.Post && requestCount > 1)
|
|
{
|
|
// Subsequent POST to SSE endpoint succeeds
|
|
return Task.FromResult(new HttpResponseMessage
|
|
{
|
|
StatusCode = HttpStatusCode.OK,
|
|
Content = new StringContent("accepted")
|
|
});
|
|
}
|
|
|
|
throw new InvalidOperationException($"Unexpected request: {request.Method}, count: {requestCount}");
|
|
};
|
|
|
|
await using var session = await transport.ConnectAsync(TestContext.Current.CancellationToken);
|
|
|
|
// The auto-detecting transport should be returned
|
|
Assert.NotNull(session);
|
|
}
|
|
} |