-
Notifications
You must be signed in to change notification settings - Fork 571
Description
_meta field not serialized in HTTP transport - blocks ChatGPT Apps SDK
Summary
Issue #856 was closed as complete, but HTTP serialization is an issue. While PR #857 added the API to SET metadata (McpMetaAttribute and Meta properties), the _meta field is not serialized when using HTTP transport (Streamable HTTP/SSE).
This is a critical blocker for ChatGPT Apps SDK integration, as ChatGPT only supports HTTP-based transports (Streamable HTTP and SSE, not stdio).
Impact
- ChatGPT Apps SDK requires HTTP-based transports: Streamable HTTP or SSE (doesn't support stdio)
- ChatGPT requires
_meta.openai/outputTemplatein tool descriptors for custom UI - Issue Tools and resources should support _meta additions #856 closed prematurely - API added but serialization is a problem
- All ChatGPT Apps SDK users that have custom UX are affected
- Both implementation approaches affected:
- Dynamic:
McpServerToolCreateOptions.Meta - Attribute:
[McpMeta("key", "value")]
- Dynamic:
Reproduction
Setup
// Using dynamic approach
var toolOptions = new McpServerToolCreateOptions
{
Meta = new JsonObject
{
["openai/outputTemplate"] = "ui://task.html",
["openai/widgetAccessible"] = true
}
};
var tool = McpServerTool.Create(myFunction, options: toolOptions);
// OR using attribute approach
[McpServerTool]
[McpMeta("openai/outputTemplate", "ui://task.html")]
public static string GetTasks() { }Test with HTTP
curl -X POST http://localhost:5047 \
-H "Content-Type: application/json" \
-H "Accept: application/json, text/event-stream" \
-d '{"jsonrpc":"2.0","id":1,"method":"tools/list"}' | jq '.result.tools[0]._meta'Expected: {"openai/outputTemplate": "ui://task.html", ...}
Actual: null
Debug Logging Confirms Meta Is Set
// Added logging in DynamicToolService.cs
_logger.LogInformation("Meta is {Status}: {Meta}",
tool.ProtocolTool.Meta != null ? "SET" : "NULL",
tool.ProtocolTool.Meta);Output: Meta is SET: {"openai/outputTemplate":"ui://task.html",...}
Conclusion: Meta exists on tool.ProtocolTool.Meta internally, but HTTP serialization strips it.
Root Cause
The SDK uses source-generated JSON serialization (McpJsonUtilities.JsonContext):
- ✅
Tool.csline 125:[JsonPropertyName("_meta")] public JsonObject? Meta { get; set; } - ✅
McpJsonUtilities.csline 134:[JsonSerializable(typeof(ListToolsResult))] - ❌ Missing:
[JsonSerializable(typeof(Tool))]
Source generators use compile-time metadata. When Tool.Meta was added in PR #857, the source generator wasn't updated. The HTTP layer serializes using the source-generated context, which doesn't include metadata for Tool, so _meta gets stripped.
Compare with ResourceContents: Has a custom JsonConverter that explicitly writes _meta (ResourceContents.cs lines 173-178). Tool doesn't have this.
Why Tests Pass But HTTP Fails
PR #857 added extensive lines of tests (McpMetaAttributeTests.cs) - all pass! But:
- Tests serialize directly using
McpJsonUtilities.DefaultOptions - Tests don't go through HTTP transport layer
- HTTP serialization uses the source-generated
JsonContextwhich lacksToolmetadata - Bug only manifests in HTTP transport
Environment
- SDK:
ModelContextProtocol 0.4.0-preview.3,ModelContextProtocol.AspNetCore 0.4.0-preview.3 - .NET: 8.0
- OS: macOS
- Transport: HTTP (Streamable HTTP on port 5047)
- Confirmed via: MCP Inspector, direct curl testing, debug logging
Suggested Fix
Option 1: Add explicit serialization metadata:
[JsonSerializable(typeof(Tool))]
[JsonSerializable(typeof(ListToolsResult))]Option 2: Add custom JsonConverter for Tool (like ResourceContents has) that explicitly writes _meta
Related
- Issue Tools and resources should support _meta additions #856: "Tools and resources should support _meta additions" (closed prematurely)
- PR Add McpMetaAttribute for attaching metadata to tools, prompts, and resources #857: Added API but not serialization fix
- ChatGPT Apps SDK docs: https://developers.openai.com/apps-sdk/build/mcp-server
Additional Context
#856 may have been closed prematurely:
- All tests pass because they don't use HTTP transport
- HTTP serialization bug was never addressed
- Issue closed without testing the only transport ChatGPT supports