Skip to content

Remove dead dict branch in _handle_call_tool and fix call_tool return type#2863

Open
agaonker wants to merge 1 commit into
modelcontextprotocol:mainfrom
agaonker:fix/2695-dead-call-tool-dict-branch
Open

Remove dead dict branch in _handle_call_tool and fix call_tool return type#2863
agaonker wants to merge 1 commit into
modelcontextprotocol:mainfrom
agaonker:fix/2695-dead-call-tool-dict-branch

Conversation

@agaonker

Copy link
Copy Markdown

Closes #2695

What

MCPServer._handle_call_tool contained a dead isinstance(result, dict) branch, already marked # pragma: no cover with an inline TODO documenting both the dead code and the related incorrect return-type annotation on MCPServer.call_tool.

FuncMetadata.convert_result returns exactly three shapes:

  1. CallToolResult — when the tool function returned one directly
  2. Sequence[ContentBlock] — no output schema
  3. (unstructured_content, structured_content) tuple — output schema set

It never returns a raw dict, so the branch was unreachable.

Changes

  • Remove the dead isinstance(result, dict) branch.
  • Correct call_tool's return annotation from Sequence[ContentBlock] | dict[str, Any] (claims a dict it never returns, omits the two shapes it does) to CallToolResult | Sequence[ContentBlock] | tuple[Sequence[ContentBlock], dict[str, Any]].
  • Drop the now-orphaned import json (used only inside the removed branch).

The existing len(result) == 2 check and the two pre-existing # type: ignore[arg-type] comments on the tuple branch are left untouched — they silence a real pyright Sequence/tuple overlap and are out of scope here.

Validation

  • pyright — clean
  • ruff check / ruff format — clean
  • ./scripts/test — full suite passes at 100% coverage; strict-no-cover clean (confirms the removed branch was genuinely dead — its removal drops no coverage)

🤖 Generated with Claude Code

… type

`FuncMetadata.convert_result` only ever returns one of three shapes:
a `CallToolResult`, a `Sequence[ContentBlock]`, or a
`(unstructured_content, structured_content)` tuple. It never returns a
raw `dict`, so the `isinstance(result, dict)` branch in
`_handle_call_tool` was unreachable (already marked `# pragma: no cover`
with a TODO).

Remove the dead branch, correct `call_tool`'s return annotation to
reflect the three real shapes, and drop the now-orphaned `json` import
(used only inside the removed branch).

Closes modelcontextprotocol#2695

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Dead code path in MCPServer._handle_call_tool and incorrect call_tool return type

1 participant