fix: invalidate tool schema cache on ToolListChangedNotification; paginate all pages in _validate_tool_result#2441
Open
atishay2 wants to merge 2 commits intomodelcontextprotocol:mainfrom
Conversation
…paginate all pages Two related bugs in ClientSession._validate_tool_result: 1. ToolListChangedNotification was not handled in _received_notification, leaving _tool_output_schemas stale after the server updates its tool list. Subsequent call_tool invocations would validate structured content against the old schema, causing false negatives (valid responses rejected) or silently accepting responses that no longer match the current schema. Fix: clear _tool_output_schemas when ToolListChangedNotification arrives. 2. When a tool was not found in the schema cache, only the first page of list_tools() was fetched. Tools on page 2+ were never cached, so their output schema was silently skipped — invalid structured_content was accepted without raising a RuntimeError. Fix: paginate through all pages until the tool is found or the list ends. Tests added for both cases in test_output_schema_validation.py. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
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
Two correctness bugs in
ClientSessionthat cause tool output schema validation to silently use stale or missing schemas.Bug 1:
ToolListChangedNotificationdoes not clear the tool schema cache_received_notificationhad no handler forToolListChangedNotification, so_tool_output_schemaswas never invalidated when the server signalled a tool list change. The nextcall_toolinvocation would validatestructured_contentagainst the old (stale) schema:{integer}to{string}would have valid string output rejected against the cached integer schema.Fix: handle
ToolListChangedNotificationin_received_notificationby clearing_tool_output_schemas. The cache is repopulated lazily on the nextcall_tool.Bug 2:
_validate_tool_resultonly fetches the first page oflist_tools()When a tool name was not in
_tool_output_schemas, a singleawait self.list_tools()call was made (no arguments → first page only). If the tool lived on page 2 or later, it was never found in the cache, the schema lookup fell through to the warning path, and validation was silently skipped — invalidstructured_contentwas returned to the caller without any error.Fix: add a pagination loop in
_validate_tool_resultthat continues fetching pages until the tool is found or all pages are exhausted.Changed files
src/mcp/client/session.py— two targeted fixes (4 new lines each)tests/client/test_output_schema_validation.py— two new test cases that fail without the fix and pass with itTest plan
uv run --frozen pytest tests/client/test_output_schema_validation.py -v— all 7 tests passuv run --frozen pytest tests/client/ -v— 190 passed, 1 xfailed, no regressionsuv run --frozen pyright src/mcp/client/session.py— 0 errorsuv run --frozen ruff check src/mcp/client/session.py tests/client/test_output_schema_validation.py— all checks passed🤖 Generated with Claude Code