Register ping handler in McpSessionHandler to support server-initiated pings (#1391)
Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com> Co-authored-by: stephentoub <2642209+stephentoub@users.noreply.github.com> Co-authored-by: Stephen Toub <stoub@microsoft.com>
This commit is contained in:
parent
1108117d6f
commit
919e8383f0
3 changed files with 20 additions and 9 deletions
|
|
@ -132,6 +132,14 @@ internal sealed partial class McpSessionHandler : IAsyncDisposable
|
||||||
_incomingMessageFilter = incomingMessageFilter ?? (next => next);
|
_incomingMessageFilter = incomingMessageFilter ?? (next => next);
|
||||||
_outgoingMessageFilter = outgoingMessageFilter ?? (next => next);
|
_outgoingMessageFilter = outgoingMessageFilter ?? (next => next);
|
||||||
_logger = logger;
|
_logger = logger;
|
||||||
|
|
||||||
|
// Per the MCP spec, ping may be initiated by either party and must always be handled.
|
||||||
|
_requestHandlers.Set(
|
||||||
|
RequestMethods.Ping,
|
||||||
|
(request, _, cancellationToken) => new ValueTask<PingResult>(new PingResult()),
|
||||||
|
McpJsonUtilities.JsonContext.Default.JsonNode,
|
||||||
|
McpJsonUtilities.JsonContext.Default.PingResult);
|
||||||
|
|
||||||
LogSessionCreated(EndpointName, _sessionId, _transportKind);
|
LogSessionCreated(EndpointName, _sessionId, _transportKind);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -91,7 +91,6 @@ internal sealed partial class McpServerImpl : McpServer
|
||||||
ConfigureLogging(options);
|
ConfigureLogging(options);
|
||||||
ConfigureCompletion(options);
|
ConfigureCompletion(options);
|
||||||
ConfigureExperimental(options);
|
ConfigureExperimental(options);
|
||||||
ConfigurePing();
|
|
||||||
|
|
||||||
// Register any notification handlers that were provided.
|
// Register any notification handlers that were provided.
|
||||||
if (options.Handlers.NotificationHandlers is { } notificationHandlers)
|
if (options.Handlers.NotificationHandlers is { } notificationHandlers)
|
||||||
|
|
@ -204,14 +203,6 @@ internal sealed partial class McpServerImpl : McpServer
|
||||||
await _sessionHandler.DisposeAsync().ConfigureAwait(false);
|
await _sessionHandler.DisposeAsync().ConfigureAwait(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void ConfigurePing()
|
|
||||||
{
|
|
||||||
SetHandler(RequestMethods.Ping,
|
|
||||||
async (request, _) => new PingResult(),
|
|
||||||
McpJsonUtilities.JsonContext.Default.JsonNode,
|
|
||||||
McpJsonUtilities.JsonContext.Default.PingResult);
|
|
||||||
}
|
|
||||||
|
|
||||||
private void ConfigureInitialize(McpServerOptions options)
|
private void ConfigureInitialize(McpServerOptions options)
|
||||||
{
|
{
|
||||||
_requestHandlers.Set(RequestMethods.Initialize,
|
_requestHandlers.Set(RequestMethods.Initialize,
|
||||||
|
|
|
||||||
|
|
@ -782,4 +782,16 @@ public class McpClientTests : ClientServerTestBase
|
||||||
await Assert.ThrowsAsync<ArgumentNullException>("requestParams",
|
await Assert.ThrowsAsync<ArgumentNullException>("requestParams",
|
||||||
() => client.SetLoggingLevelAsync((SetLevelRequestParams)null!, TestContext.Current.CancellationToken));
|
() => client.SetLoggingLevelAsync((SetLevelRequestParams)null!, TestContext.Current.CancellationToken));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public async Task ServerCanPingClient()
|
||||||
|
{
|
||||||
|
await using McpClient client = await CreateMcpClientForServer();
|
||||||
|
|
||||||
|
var pingRequest = new JsonRpcRequest { Method = RequestMethods.Ping };
|
||||||
|
var response = await Server.SendRequestAsync(pingRequest, TestContext.Current.CancellationToken);
|
||||||
|
|
||||||
|
Assert.NotNull(response);
|
||||||
|
Assert.NotNull(response.Result);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue