FazBrowse GitHub Viewer | Trending |
URL:
| Home
Tools: [Download Repo ZIP]   [Original HTTPS Page]

fix(server): surface structured validation errors in CallToolResult._meta (#3351) by linhongyu510 · Pull Request #3383 · modelcontextprotocol/python-sdk · GitHub

fix(server): surface structured validation errors in CallToolResult._meta (#3351) - #3383

Closed
linhongyu510 wants to merge 1 commit into
modelcontextprotocol:v1.xfrom
linhongyu510:fix/3351-structured-validation-error
Closed

fix(server): surface structured validation errors in CallToolResult._meta (#3351)#3383
linhongyu510 wants to merge 1 commit into
modelcontextprotocol:v1.xfrom
linhongyu510:fix/3351-structured-validation-error

Conversation

Copy link
Copy Markdown

Summary

Fixes #3351.

When Server.call_tool() (low-level) fails schema validation, it currently returns a CallToolResult(isError=True) whose content is only the interpolated jsonschema.ValidationError.message, e.g. "Input validation error: 'b' is a required property". As #3351 points out, jsonschema.ValidationError already carries stable structured fields (validator, validator_value, schema_path, json_path) — but they are all discarded before crossing the transport, forcing clients to regex-match brittle wording (whose exact form is not guaranteed by upstream jsonschema) just to distinguish required vs type vs enum failures.

Change

Forward the structured jsonschema fields into CallToolResult._meta under the MCP-namespaced key io.modelcontextprotocol/schema-validation-error, for both input- and output-schema failures. isError=True and the existing free-text message stay unchanged, so no existing client breaks.

Example payload on _meta after a missing-required failure:

{
  "io.modelcontextprotocol/schema-validation-error": {
    "kind": "input",
    "validator": "required",
    "validator_value": ["a", "b"],
    "schema_path": ["required"],
    "json_path": "$",
    "message": "'b' is a required property"
  }
}

Implementation notes

  • _make_error_result now takes an optional structured_data keyword and attaches it under the namespaced _meta key.
  • New _validation_error_data(...) staticmethod extracts the stable fields from jsonschema.ValidationError.
  • New module-level _jsonable(...) helper coerces non-JSON schema fragments (deques, sets, callables that live in validator_value for custom formats/keywords) into JSON-safe values before they cross the JSON-RPC transport, so the addition can't crash the response.
  • Both call sites (inputSchema and outputSchema validation) forward kind="input" / kind="output" accordingly.

Tests

  • test_input_validation_error_carries_structured_meta — asserts validator, validator_value, json_path for both missing-required and wrong-type failures.
  • test_enum_validation_error_carries_structured_meta — asserts enum classification exposes the allowed values in validator_value.
  • All existing test_lowlevel_input_validation.py and test_lowlevel_output_validation.py cases keep passing.

Backport target

Opened against v1.x since the issue is labeled v1 + v2; happy to also cherry-pick to main (v2) if maintainers prefer.

…_meta

Fixes modelcontextprotocol#3351. When a tool call fails schema validation, the low-level
Server previously returned only the interpolated free-text message,
forcing clients to regex-match brittle wording to classify failures.

This change forwards jsonschema.ValidationError's stable machine-readable
fields (validator, validator_value, schema_path, json_path, message) into
CallToolResult._meta under the MCP-namespaced key
'io.modelcontextprotocol/schema-validation-error', for both input- and
output-schema failures. The human-readable message and isError=True stay
unchanged, so existing clients keep working.

- _make_error_result now accepts optional structured_data
- new _validation_error_data helper extracts jsonschema fields
- new _jsonable helper coerces non-JSON schema fragments (deques, sets,
  callables) to JSON-safe values before they cross the transport
- added tests covering required/type/enum classification via _meta
github-actions Bot added the missing-issue-link Auto-closed: PR needs a linked issue assigned to its author (see CONTRIBUTING.md) label Aug 25, 2026

Copy link
Copy Markdown
Contributor

Thanks for the contribution. This repository only keeps pull requests open when they're linked to an issue that a maintainer has assigned to the author — CONTRIBUTING.md explains why and how we work. This PR has been closed for now because you aren't currently assigned to #3351.

If a maintainer would like this change as a PR from you, they'll assign you to #3351 and this PR will reopen automatically — there's nothing more you need to do. (If you opened the issue, this PR already shows up on its timeline.)

There's no need to open a new PR — this one will be reopened. While it's closed, please push any updates as new commits rather than force-pushing, since GitHub can't reopen a PR whose branch has been rewritten.

Maintainers: reopening this PR, removing the missing-issue-link label, or adding bypass-issue-check bypasses the check.

github-actions Bot closed this Aug 25, 2026
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

Labels

missing-issue-link Auto-closed: PR needs a linked issue assigned to its author (see CONTRIBUTING.md)

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant


Back | FazBrowse Home | New Git URL