Description
Describe the bug
The MCP Python SDK violates the MCP Specification 2025-03-26 by rejecting JSON-RPC batch requests (arrays of requests), which are explicitly supported by the protocol specification. This is a specification compliance issue that breaks interoperability and performance for multi-agent systems.
To Reproduce
Steps to reproduce the behavior:
- Create a server using FastMCP:
from mcp.server.fastmcp import FastMCP
mcp = FastMCP(
name="batching-server",
description="A simple server to demonstrate MCP batching.",
stateless_http=True
)
@mcp.tool()
def add(a: int, b: int) -> int:
"""Adds two integers together."""
print(f"Server: Executing add({a}, {b})")
return a + b
@mcp.tool()
async def greet(name: str) -> str:
"""Provides a friendly greeting."""
print(f"Server: Executing greet('{name}')")
return f"Hello, {name}!"
# Expose the app for Uvicorn
mcp_app = mcp.streamable_http_app()
# Run with: uvicorn server:app --host 0.0.0.0 --port 8000
- Send a valid JSON-RPC batch request (array):
import httpx
import asyncio
async def main():
print("--- MCP Batch Request Client Demonstration ---")
# --- Batch Request (array of requests) ---
batch_request = [
{
"jsonrpc": "2.0",
"method": "tools/call",
"params": {"name": "add", "arguments": {"a": 5, "b": 10}},
"id": 1
},
{
"jsonrpc": "2.0",
"method": "tools/call",
"params": {"name": "greet", "arguments": {"name": "World"}},
"id": 2
}
]
print(f"\n[Step 1: Sending batch with {len(batch_request)} requests]")
headers = {
"Content-Type": "application/json",
"Accept": "application/json, text/event-stream"
}
async with httpx.AsyncClient() as client:
# Send the batch request to our compliant server
response = await client.post("http://localhost:8000/mcp/", json=batch_request, headers=headers)
# response.raise_for_status()
print(f"\n[Step 2: Received batch response]")
print(f"Status: {response.text}")
print(f"Content-Type: {response.headers.get('content-type')}")
# print(f"\n[Step 3: Successfully received {len(responses)} batch responses]")
print
6413
("✅ JSON-RPC batching works correctly when the server properly implements the spec!")
if __name__ == "__main__":
asyncio.run(main())
- Server returns ValidationError instead of processing the batch
- See error: Cannot validate array as single JSONRPCMessage
Expected behavior
According to MCP Specification 2025-03-26, the server MUST accept "an array batching one or more requests and/or notifications" and return an array of corresponding responses:
[
{"jsonrpc": "2.0", "result": 15, "id": 1},
{"jsonrpc": "2.0", "result": 10, "id": 2}
]
Screenshots
N/A - This is a code/protocol compliance issue
Environment:
- OS: macOS, Linux, Windows (affects all platforms)
- Python Version: 3.12+
- MCP Python SDK: Current version
- Server Framework: FastMCP/streamable_http
Code Location
The issue is in src/mcp/server/streamable_http.py:351
:
# This line only accepts single messages, not arrays
message = JSONRPCMessage.model_validate(raw_message)
Additional context
Specification Violation:
- Source: MCP Specification 2025-03-26 - Transports
- Section 3 states the POST body MUST support "an array batching one or more requests and/or notifications"
- The use of "MUST" indicates this is a protocol requirement, not optional
Impact:
- Performance: Forces N HTTP requests instead of 1 batch request
- Interoperability: Breaks compatibility with JSON-RPC 2.0 clients
- Agent Frameworks: Prevents integration with batch-optimized systems
Suggested Fix:
Update HTTP transport to detect arrays and process each message in the batch:
if isinstance(raw_data, list):
# Batch request - process each message
responses = []
for item in raw_data:
message = JSONRPCMessage.model_validate(item)
response = await self._process_message(message)
if response: # Skip notifications
responses.append(response)
return JSONResponse(responses)
Priority: High - Specification compliance issue blocking adoption and multi-agent system performance.