Skip to content

fix: invalidate tool schema cache on ToolListChangedNotification; paginate all pages in _validate_tool_result - #2441

Closed
atishay2 wants to merge 2 commits into
modelcontextprotocol:mainfrom
atishay2:fix/tool-schema-cache-invalidation
Closed

atishay2 wants to merge 2 commits into
modelcontextprotocol:mainfrom
atishay2:fix/tool-schema-cache-invalidation

Conversation

@atishay2

Copy link
Copy Markdown

Summary

Two correctness bugs in ClientSession that cause tool output schema validation to silently use stale or missing schemas.

Bug 1: ToolListChangedNotification does not clear the tool schema cache

_received_notification had no handler for ToolListChangedNotification, so _tool_output_schemas was never invalidated when the server signalled a tool list change. The next call_tool invocation would validate structured_content against the old (stale) schema:

  • False negative: a tool whose schema changed from {integer} to {string} would have valid string output rejected against the cached integer schema.
  • Silent acceptance: a tool whose schema became stricter would still pass validation because the old looser schema was still in the cache.

Fix: handle ToolListChangedNotification in _received_notification by clearing _tool_output_schemas. The cache is repopulated lazily on the next call_tool.

Bug 2: _validate_tool_result only fetches the first page of list_tools()

When a tool name was not in _tool_output_schemas, a single await 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 — invalid structured_content was returned to the caller without any error.

Fix: add a pagination loop in _validate_tool_result that 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 it

Test plan

  • uv run --frozen pytest tests/client/test_output_schema_validation.py -v — all 7 tests pass
  • uv run --frozen pytest tests/client/ -v — 190 passed, 1 xfailed, no regressions
  • uv run --frozen pyright src/mcp/client/session.py — 0 errors
  • uv run --frozen ruff check src/mcp/client/session.py tests/client/test_output_schema_validation.py — all checks passed

🤖 Generated with Claude Code

Atishay Tiwari and others added 2 commits April 13, 2026 21:33
…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>
@maxisbey

maxisbey commented Oct 5, 2026

Copy link
Copy Markdown
Contributor

Thanks for the PR, and sorry it sat here without a proper review.

We're closing most of the open PR backlog. v2 is out and changed a lot of the SDK, so many older PRs no longer apply as written, and we're a small team that realistically doesn't have the capacity to work through the rest.

If this still matters to you on v2, the most useful thing you can do is open an issue (or comment on the existing one) with your use case and a repro. Hearing why it matters to you is what we use to decide what to prioritise.

AI Disclaimer

@maxisbey maxisbey closed this Oct 5, 2026
@maxisbey maxisbey added the missing-issue-link Auto-closed: PR needs a linked issue assigned to its author (see CONTRIBUTING.md) label Oct 5, 2026
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.

2 participants