Skip to content

Conversation

aishwaryabh
Copy link
Contributor

Issue describing the changes in this PR

resolves #26

Pull request checklist

  • My changes do not require documentation changes
    • Otherwise: Documentation issue linked to PR
  • My changes should not be added to the release notes for the next release
    • Otherwise: I've added my notes to release_notes.md
  • I have added all required tests (Unit tests, E2E tests)

Additional information

Adding support to the extension to support the following format:

{
  "isFunctionsMcpResult": true,
  "content": <JSON-RPC message payload>
}

}

var message = await context.Request.ReadFromJsonAsync<JsonRpcMessage>(McpJsonSerializerOptions.DefaultOptions, context.RequestAborted);
var message = await McpHttpUtility.ExtractJsonRpcMessageSseAsync(context.Request, McpJsonSerializerOptions.DefaultOptions, context.RequestAborted);
Copy link
Member

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)
Copy link
Member

@liliankasem liliankasem Sep 22, 2025

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
Copy link
Member

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)
Copy link
Member

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?

Copy link
Member

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();
Copy link
Member

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();
Copy link
Member

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?

Copy link
Member

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 &&
Copy link
Member

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

Copy link
Member

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);
Copy link
Member

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);
Copy link
Member

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?

@liliankasem liliankasem closed this Oct 9, 2025
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Support raw messages from workers
2 participants