Skip to content

fix: preserve custom results with generic metadata - #1197

Open
jmagar wants to merge 2 commits into
modelcontextprotocol:mainfrom
dinglebear-ai:fix/custom-result-meta-classification-upstream
Open

jmagar wants to merge 2 commits into
modelcontextprotocol:mainfrom
dinglebear-ai:fix/custom-result-meta-classification-upstream

Conversation

@jmagar

@jmagar jmagar commented Aug 20, 2026 •

Copy link
Copy Markdown

Summary

Custom extension responses with _meta can match CallToolResult and lose their extension fields during ServerResult decoding.

Preserve those responses as CustomResult when unknown fields accompany _meta and no tool-specific field identifies the response. Keep legacy _meta-only tool results compatible with #1103.

_meta only                              -> CallToolResult
_meta + custom fields, no tool fields    -> CustomResult
content, structuredContent, or isError   -> CallToolResult

These rules also apply when resultType: complete is present. A present structuredContent: null still identifies a tool result.

Merged current upstream main into this branch. The resulting diff changes only the classifier and regression tests.

Evidence

  • Before: The original patch failed the existing legacy _meta-only test and the new compatibility test: 13 passed, 2 failed.
    After: All 15 wire-compatibility tests passed.
  • Added coverage for legacy and complete results, custom fields with null or false values, and genuine tool results with unknown fields.
  • Rust 1.96.1, all public features except local: 1,434 unit/integration tests and 59 doctests passed; 18 ignored.
  • Rust 1.96.1, all features including local: 1,024 tests and doctests passed; 15 ignored.
  • Strict Clippy passed for all rmcp targets with and without local.
  • Stable formatting and git diff --check passed. Nightly formatting was not verified locally.

The non-local doctest run passed separately after a temporary-storage quota failure. These are local results; GitHub CI is separate.

Merge Danger

Door: Two-way

The change can be reverted. No public types or method signatures change.

Blast Radius: Decoding

Responses that contain _meta and unknown fields now fall through to CustomResult when they lack tool-specific fields. Legacy _meta-only responses remain tool results. Tool-specific fields retain priority, so this change does not preserve custom fields in responses that also match a genuine tool result.

@github-actions

Copy link
Copy Markdown
Contributor

This pull request has had no activity for 60 days and is now marked as stale. It will be closed in 14 days if there is no further activity. Add the keep label to keep it open.

@github-actions github-actions Bot added the Stale label Oct 20, 2026
@jmagar

jmagar commented Oct 20, 2026

Copy link
Copy Markdown
Author

We hit this too: custom results carrying _meta were being decoded as CallToolResult, and this change fixes the core bug for us. One catch: on current main it trips test_result_type_wire::server_result_should_accept_legacy_call_tool_result_when_only_meta_present (added in #1103), which keeps a _meta-only response as a tool result. We have a version that keeps that case and only falls through to a custom result when unrecognized fields come with _meta, with regression tests. Happy to push it here or open it as a separate PR crediting this one, whichever you prefer.

Good catch, no that wasn't intentional. Definitely feel free to push it here. Appreciate your contributions!

@github-actions github-actions Bot removed the Stale label Oct 21, 2026
@github-actions github-actions Bot added the T-test Testing related changes label Oct 24, 2026

This branch has not been deployed

No deployments
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

T-core Core library changes T-test Testing related changes

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant