Skip to content

Conversation

@crondinini-ant
Copy link
Contributor

Motivation and Context

When an MCP server returns a JSON-RPC response with the request ID as a string (e.g., "id": "0") but the client sent the request with an integer ID (e.g., "id": 0), the response fails to match the pending request. This causes the client to timeout waiting for a response that was already received but couldn't be correlated.

The root cause is in src/mcp/shared/session.py:256-260 where the client stores pending requests using an integer counter:

request_id = self._request_id  # always int

self._request_id = request_id + 1

self._response_streams[request_id] = response_stream  # key is int

When a response arrives, the lookup self._response_streams.pop(response_id, None) fails silently if response_id is "0" (string) because Python dict lookups are type-sensitive (0 != "0").

This is valid per the JSON-RPC spec and the SDK's own type definition at src/mcp/types.py:40:

RequestId = Annotated[int, Field(strict=True)] | str

How Has This Been Tested?

Added three new unit tests in tests/shared/test_session.py:

  • test_response_id_type_mismatch_string_to_int - success responses with string IDs match integer request IDs

  • test_error_response_id_type_mismatch_string_to_int - error responses with string IDs match integer request IDs

  • test_response_id_non_numeric_string_no_match - non-numeric string IDs (like "abc") don't incorrectly match

Breaking Changes

None. This is a backwards-compatible fix that makes the client more tolerant of server responses.

Types of changes

  • Bug fix (non-breaking change which fixes an issue)

  • New feature (non-breaking change which adds functionality)

  • Breaking change (fix or feature that would cause existing functionality to change)

  • Documentation update

Checklist

  • I have read the MCP Documentation

  • My code follows the repository's style guidelines

  • New and existing tests pass locally

  • I have added appropriate error handling

  • I have added or updated documentation as needed

Additional context

The fix adds a _pop_response_stream() helper method that:

  1. First tries an exact match lookup

  2. If the ID is a string, tries converting to int and looks up again

  3. If the ID is an int, tries converting to string and looks up again

This handles the common case where servers echo back IDs in a different but semantically equivalent format.

When an MCP server returns a JSON-RPC response with a string ID (e.g.,
"id": "0") but the client sent an integer ID (e.g., "id": 0), the
response would fail to match the pending request, causing a timeout.

This fix adds ID type normalization when looking up response streams.
If the initial lookup fails, it tries converting:
- String IDs to integers (for "0" -> 0 matching)
- Integer IDs to strings (for 0 -> "0" matching)

This ensures robust handling of servers that may return IDs in a
different but equivalent format.
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.

3 participants