-
Notifications
You must be signed in to change notification settings - Fork 4
Support raw JSON-RPC messages from workers: Extension changes #107
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
} | ||
|
||
var message = await context.Request.ReadFromJsonAsync<JsonRpcMessage>(McpJsonSerializerOptions.DefaultOptions, context.RequestAborted); | ||
var message = await McpHttpUtility.ExtractJsonRpcMessageSseAsync(context.Request, McpJsonSerializerOptions.DefaultOptions, context.RequestAborted); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
You could implement this as a HttpRequest
extension
context.Features.GetRequiredFeature<IHttpResponseBodyFeature>().DisableBuffering(); | ||
} | ||
|
||
internal static async ValueTask<JsonRpcMessage?> ProcessJsonRpcPayloadAsync(HttpRequest request, JsonSerializerOptions options, CancellationToken cancellationToken, bool unwrapOnly = false) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
What "process" is happeing? Aren't we just reading? Wondering if there is a better name here
|
||
internal static async ValueTask<JsonRpcMessage?> ProcessJsonRpcPayloadAsync(HttpRequest request, JsonSerializerOptions options, CancellationToken cancellationToken, bool unwrapOnly = false) | ||
{ | ||
// Process the incoming request body as JSON. Support both raw JSON-RPC messages and |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This might be better suited for a summary commnet above the method
// containing only the inner content. If no wrapper is present, leave the original body intact. | ||
|
||
// If the body is empty, return null. | ||
if (request.ContentLength == null || request.ContentLength == 0) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
ContentLength null does not necessarily mean that there is no request body. Do we want to check request.Body to be safe?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We can also use CanRead
} | ||
|
||
// Read the request body into a JsonDocument for inspection. | ||
request.EnableBuffering(); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Is this the first point of entry, could this have been set before we got to this method (middleware perhaps?) I don't think there is an issue setting this twice, but I wonder where is the right place
} | ||
|
||
// Read the request body into a JsonDocument for inspection. | ||
request.EnableBuffering(); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Could another component have read the body before we get to this part of the code? If so, do we need to reset the position?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It might be safer to always reset
JsonElement messageElement = root; | ||
bool isWrapped = false; | ||
|
||
if (root.ValueKind == JsonValueKind.Object && |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
bool isWrapped =
root.ValueKind == JsonValueKind.Object &&
root.TryGetProperty("isFunctionsMcpResult", out var marker) &&
marker.ValueKind == JsonValueKind.True &&
root.TryGetProperty("content", out var messageElement);
TryGetProperty is already setting a conent var so we don't really need to assign it again
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Not sure that root.TryGetProperty("content", out var messageElement);
needs to be connected to the result of isFunctionsMcpResult
?
else | ||
{ | ||
// Reset position so downstream readers can consume the original body. | ||
request.Body.Seek(0, SeekOrigin.Begin); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
For extra safety, maybe check CanSeek before doing this
else | ||
{ | ||
var raw = messageElement.GetRawText(); | ||
return JsonSerializer.Deserialize<JsonRpcMessage>(raw, options); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
What are we doing on json exceptions? And do we know that messageElement is json?
Issue describing the changes in this PR
resolves #26
Pull request checklist
release_notes.md
Additional information
Adding support to the extension to support the following format: