feat: forward MCP _meta field through ToolResultBlock#1130
Open
sridhar-3009 wants to merge 1 commit into
Open
Conversation
SDK-defined MCP tools can already receive _meta in tools/list responses (for maxResultSizeChars annotations), but tools/call results silently dropped it: create_sdk_mcp_server's call_tool() only read content and is_error from a handler's return dict, and the Query JSON-RPC bridge never forwarded CallToolResult.meta back to the CLI. On the parsing side, message_parser.py's ToolResultBlock construction discarded any _meta key present on tool_result blocks in the transcript. This wires _meta end-to-end so handlers can return data meant for event handlers/UI without it entering model context, per the MCP spec's intent for _meta. Fixes anthropics#407
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Closes #407. MCP's
_metafield is designed for handler-only data that should not enter model context (record IDs, pagination cursors, etc.), but it was being silently dropped on the tool-result path:create_sdk_mcp_server'scall_tool()only readcontentandis_errorfrom a tool handler's return dict, discarding any_metakey.QueryJSON-RPC bridge (_handle_sdk_mcp_request) built thetools/callresponse without forwardingCallToolResult.metaback to the CLI — even though the siblingtools/listpath already forwardstool.metathe same way (see the existing_metahandling a few lines up in the same method).message_parser.py's twoToolResultBlockconstruction sites parsedcontentandis_erroroff transcripttool_resultblocks but ignored_meta.This change:
meta: dict[str, Any] | None = NonetoToolResultBlock(types.py).block.get("_meta")into bothToolResultBlockconstruction sites inmessage_parser.py._metareturn value intoCallToolResultincreate_sdk_mcp_server'scall_tool().CallToolResult.metainto thetools/callJSON-RPC response inquery.py, mirroring the existingtools/listpattern.Test plan
test_parse_user_message_with_tool_result_meta/test_parse_user_message_with_tool_result_no_metaintests/test_message_parser.py.test_tool_result_meta_reaches_call_tool_resultandtest_tool_result_meta_flows_through_jsonrpc_bridgeintests/test_sdk_mcp_integration.py(the latter mirrors the existingtest_max_result_size_chars_annotation_flows_to_clibridge test, for thetools/callpath instead oftools/list).pytest(1237 passed, 5 pre-existing skips, no new failures)mypy src/(strict mode, clean)ruff check/ruff format --check(clean)🤖 Generated with Claude Code