-
Notifications
You must be signed in to change notification settings - Fork 530
Description
Describe the bug
I am registering my subscribe handler like this:
builder.Services.AddMcpServer()
.WithHttpTransport(options =>
// Configure session timeout
options.IdleTimeout = Timeout.InfiniteTimeSpan // Never timeout
)
.WithResources<LiveResources>()
.WithSubscribeToResourcesHandler((context, token) =>
{
if (context.Params?.Uri is string uri)
{
ResourceManager.Subscriptions.Add(uri, context.Server);
}
return ValueTask.FromResult(new EmptyResult());
}
);
The client is sending a subscribe request like this:
await mcpClient.SubscribeToResourceAsync(resourceUri);
I can see in the server logs that this request is received and processed:
info: ModelContextProtocol.Server.McpServer[570385771]
Server (ResourceNotifications 1.0.0.0), Client (ResourceNotificationUpdateClient 1.0.0) method 'resources/subscribe' request handler called.
ModelContextProtocol.Server.McpServer: Information: Server (ResourceNotifications 1.0.0.0), Client (ResourceNotificationUpdateClient 1.0.0) method 'resources/subscribe' request handler completed.
info: ModelContextProtocol.Server.McpServer[1867955179]
Server (ResourceNotifications 1.0.0.0), Client (ResourceNotificationUpdateClient 1.0.0) method 'resources/subscribe' request handler completed.
By setting break points in the server, I can see that the server is sending the notifications, but the client is not getting them.
To Reproduce
A project that reproduces the problem is in this GitHub repo/branch:
https://github.com/mikekistler/mcp-howto/tree/resource-notifications
Expected behavior
Resource notifications work.
Additional context
@stephentoub debugged this problem and reported the following:
Mike is stashing away the IMcpServer to send notifications to it in the background, but those notifications aren't getting through. The problem is that the SseWriter is getting disposed as part of the StreamableHttpServerTransport.HandlePostRequest disposing of the StreamableHttpPostTransport. The SseWriter then has logic in it that silently ignores all data written to it once disposed.
Discussion in the squad Teams channel ensued with the conclusion seeming to be:
In the default stateful mode, we could consider falling back to sending the message over the long-running GET SSE response if you try using the IMcpServer injected in a handler after the handler completes.