You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
@@ -252,6 +261,13 @@ public async Task<ChatResponse> SampleAsync(
252
261
/// <param name="serializerOptions">The <see cref="JsonSerializerOptions"/> to use for serialization. If <see langword="null"/>, <see cref="McpJsonUtilities.DefaultOptions"/> is used.</param>
253
262
/// <returns>The <see cref="IChatClient"/> that can be used to issue sampling requests to the client.</returns>
254
263
/// <exception cref="InvalidOperationException">The client does not support sampling.</exception>
264
+
/// <remarks>
265
+
/// When the server is using the Streamable HTTP transport, prefer obtaining this chat client from the
266
+
/// <see cref="McpServer"/> instance available via <c>RequestContext</c> from inside a tool, prompt,
267
+
/// or resource handler. That routes sampling requests through the originating POST response stream via
268
+
/// <see cref="JsonRpcMessageContext.RelatedTransport"/>, which is always open for the duration of
269
+
/// the request, rather than relying on the optional standalone GET SSE stream.
@@ -234,9 +262,32 @@ public async Task SendMessageAsync(JsonRpcMessage message, CancellationToken can
234
262
235
263
if(!_getHttpRequestStarted)
236
264
{
237
-
// Clients are not required to make a GET request for unsolicited messages.
238
-
// If no GET request has been made, drop the message.
239
-
return;
265
+
switch(message)
266
+
{
267
+
caseJsonRpcRequestrequest:
268
+
thrownewInvalidOperationException(
269
+
$"Cannot send server-to-client JSON-RPC request '{request.Method}' because no GET SSE stream has been opened on this session "+
270
+
$"(SessionId: '{SessionId}'). "+
271
+
"Inside a tool, prompt, or resource handler, use the IMcpServer instance from RequestContext (or any IMcpServer obtained via DI from a request-scoped service provider) so the request is routed through the originating POST response stream via JsonRpcMessageContext.RelatedTransport. "+
272
+
"The standalone GET SSE stream is optional for clients and is not a reliable channel for server-to-client requests.");
273
+
274
+
caseJsonRpcNotificationnotification:
275
+
// Clients are not required to make a GET request for unsolicited messages.
276
+
// If no GET request has been made, drop the notification (best-effort).
@@ -323,4 +377,18 @@ public async ValueTask DisposeAsync()
323
377
324
378
returnsseEventStreamWriter;
325
379
}
380
+
381
+
[LoggerMessage(Level=LogLevel.Warning,
382
+
Message="Sending server-to-client JSON-RPC request '{Method}' over the standalone GET SSE stream (SessionId: '{SessionId}'). "+
383
+
"Consider using the IMcpServer instance from RequestContext inside a tool, prompt, or resource handler so the request is routed through the originating POST response stream via JsonRpcMessageContext.RelatedTransport, which is more reliable than the optional GET SSE stream.")]
Message="Dropping server-to-client JSON-RPC notification '{Method}' because no GET SSE stream has been opened on this session (SessionId: '{SessionId}').")]
Message="Dropping unexpected server-to-client {MessageType} (Id: '{MessageId}') because no GET SSE stream has been opened on this session (SessionId: '{SessionId}'). "+
392
+
"Responses normally flow through the originating POST response stream via JsonRpcMessageContext.RelatedTransport.")]
0 commit comments