Description
Bug Report: MCP Python SDK Client Appends sessionId as Query Parameter
Issue Description
The MCP Python SDK client (mcp.client.sse
) incorrectly appends the session ID as a query parameter when sending messages to the /messages
endpoint, which violates the Model Context Protocol schema specification. This causes standard-compliant servers to return a 400 Bad Request error.
Environment
- MCP Python SDK Version: 1.3.0
- Python Version: 3.12.9
- Node.js Version: v22.14.0 (server)
- HTTP Libraries:
- httpx: 0.28.1
- httpx-sse: 0.4.0
- aiohttp: 3.11.13
- aiohttp-sse-client: 0.2.1
- Server Type: Express.js with MCP SDK (TypeScript)
- Date Reported: 2025-02-28
Server Configuration
The server used in this environment is the perplexity-mcp
service, a TypeScript implementation using:
- Express.js web framework
- MCP TypeScript SDK for Server implementation
SSEServerTransport
from the official MCP SDK- Endpoints:
/sse
- For establishing SSE connections/messages
- For receiving JSON-RPC messages/tools/:toolName
and/execute-tool
- Alternative direct API endpoints
The server is configured to expect standard MCP messages according to the protocol specification, with the message endpoint expecting messages at /messages
without query parameters.
Steps to Reproduce
- Establish an SSE connection with Python client to an TypeScript MCP server at
/sse
endpoint - Successfully receive a session ID from the server during the connection initialization
- Attempt to execute a tool using
client_session.call_tool()
or directly via thewrite_stream
- Observe that the request is made to
/messages?sessionId=<session_id>
instead of just/messages
Observed Behavior
2025-02-28 01:56:33 2025-02-27 23:56:33.646 - INFO - httpx - [-] - HTTP Request: POST http://perplexity-mcp:3000/messages?sessionId=57ce9ed6-e453-4e1d-b515-7943e7341270 "HTTP/1.1 400 Bad Request"
2025-02-28 01:56:33 2025-02-27 23:56:33.647 - ERROR - mcp.client.sse - [-] - Error in post_writer: Client error '400 Bad Request' for url 'http://perplexity-mcp:3000/messages?sessionId=57ce9ed6-e453-4e1d-b515-7943e7341270'
The SDK attempts to send the message to /messages?sessionId=<session_id>
rather than following the MCP specification which requires messages to be sent to /messages
.
Expected Behavior
According to the MCP specification, the client should:
- Establish a connection to
/sse
- Receive a session ID from the server
- Send messages to
/messages
without any query parameters - Include any session identification in the message body if needed according to the JSON-RPC format
Specifically, the Base Protocol section of the specification defines:
"The protocol uses JSON-RPC 2.0 messages to establish communication between hosts, clients, and servers."
Per the Messages section of the specification, all messages should follow the JSON-RPC 2.0 format:
{
"jsonrpc": "2.0",
"id": "unique-request-id",
"method": "method-name",
"params": {
// Method-specific parameters
}
}
The session ID should be managed internally by the client and server, not exposed as a query parameter.
Root Cause Analysis
The MCP Python SDK client has an implementation issue in the SSE client where it:
- Correctly establishes the SSE connection to
/sse
- Receives and stores the session ID internally
- Incorrectly appends the session ID as a query parameter when posting messages
- This appears to be in the
post_writer
method where it builds the URL with the session ID as a query parameter
Looking at the schema in the MCP specification, the tools/call
method should be formatted as:
{
"jsonrpc": "2.0",
"id": "request-id",
"method": "tools/call",
"params": {
"name": "tool-name",
"arguments": {
// Tool-specific arguments
}
}
}
The session ID is not part of this schema and should not be included in the URL.
Recommended Fix for MCP Python SDK
The Python SDK should be modified to send messages to /messages
without appending the session ID as a query parameter. This would likely involve:
- Modifying the
post_writer
method in the SSE client - Ensuring the session ID is managed internally or included in the message body if needed
- Following the JSON-RPC specification for message formatting
Impact
This issue affects all implementations that:
- Use the MCP Python SDK client for communication
- Interact with servers that strictly follow the MCP specification
- Need to execute tools or send messages over the established SSE connection
Without the workaround, tool execution fails with 400 Bad Request errors, preventing the intended functionality from working.
Additional Notes
This bug reveals a common challenge with protocol implementations: even small deviations from specifications can cause interoperability issues. Server implementations should consider being more lenient and accommodating different client behaviors when possible, while client libraries should strive to adhere strictly to specifications.
For now, we recommend implementing the server-side workaround described above. Or sticking with Stdio protocol. Long-term, we hope to see this issue fixed in the official MCP Python SDK.