Skip to content

Commit 764e957

Browse files
authored
Add MCP Streamable HTTP implementation (#1965)
1 parent 8aa964b commit 764e957

File tree

8 files changed

+512
-82
lines changed

8 files changed

+512
-82
lines changed

docs/mcp/client.md

Lines changed: 55 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -18,17 +18,18 @@ pip/uv-add "pydantic-ai-slim[mcp]"
1818

1919
PydanticAI comes with two ways to connect to MCP servers:
2020

21-
- [`MCPServerHTTP`][pydantic_ai.mcp.MCPServerHTTP] which connects to an MCP server using the [HTTP SSE](https://spec.modelcontextprotocol.io/specification/2024-11-05/basic/transports/#http-with-sse) transport
21+
- [`MCPServerSSE`][pydantic_ai.mcp.MCPServerSSE] which connects to an MCP server using the [HTTP SSE](https://spec.modelcontextprotocol.io/specification/2024-11-05/basic/transports/#http-with-sse) transport
22+
- [`MCPServerStreamableHTTP`][pydantic_ai.mcp.MCPServerStreamableHTTP] which connects to an MCP server using the [Streamable HTTP](https://modelcontextprotocol.io/introduction#streamable-http) transport
2223
- [`MCPServerStdio`][pydantic_ai.mcp.MCPServerStdio] which runs the server as a subprocess and connects to it using the [stdio](https://spec.modelcontextprotocol.io/specification/2024-11-05/basic/transports/#stdio) transport
2324

2425
Examples of both are shown below; [mcp-run-python](run-python.md) is used as the MCP server in both examples.
2526

2627
### SSE Client
2728

28-
[`MCPServerHTTP`][pydantic_ai.mcp.MCPServerHTTP] connects over HTTP using the [HTTP + Server Sent Events transport](https://spec.modelcontextprotocol.io/specification/2024-11-05/basic/transports/#http-with-sse) to a server.
29+
[`MCPServerSSE`][pydantic_ai.mcp.MCPServerSSE] connects over HTTP using the [HTTP + Server Sent Events transport](https://spec.modelcontextprotocol.io/specification/2024-11-05/basic/transports/#http-with-sse) to a server.
2930

3031
!!! note
31-
[`MCPServerHTTP`][pydantic_ai.mcp.MCPServerHTTP] requires an MCP server to be running and accepting HTTP connections before calling [`agent.run_mcp_servers()`][pydantic_ai.Agent.run_mcp_servers]. Running the server is not managed by PydanticAI.
32+
[`MCPServerSSE`][pydantic_ai.mcp.MCPServerSSE] requires an MCP server to be running and accepting HTTP connections before calling [`agent.run_mcp_servers()`][pydantic_ai.Agent.run_mcp_servers]. Running the server is not managed by PydanticAI.
3233

3334
The name "HTTP" is used since this implemented will be adapted in future to use the new
3435
[Streamable HTTP](https://github.com/modelcontextprotocol/specification/pull/206) currently in development.
@@ -43,9 +44,9 @@ deno run \
4344

4445
```python {title="mcp_sse_client.py" py="3.10"}
4546
from pydantic_ai import Agent
46-
from pydantic_ai.mcp import MCPServerHTTP
47+
from pydantic_ai.mcp import MCPServerSSE
4748

48-
server = MCPServerHTTP(url='http://localhost:3001/sse') # (1)!
49+
server = MCPServerSSE(url='http://localhost:3001/sse') # (1)!
4950
agent = Agent('openai:gpt-4o', mcp_servers=[server]) # (2)!
5051

5152

@@ -84,6 +85,52 @@ Will display as follows:
8485

8586
![Logfire run python code](../img/logfire-run-python-code.png)
8687

88+
### Streamable HTTP Client
89+
90+
[`MCPServerStreamableHTTP`][pydantic_ai.mcp.MCPServerStreamableHTTP] connects over HTTP using the
91+
[Streamable HTTP](https://modelcontextprotocol.io/introduction#streamable-http) transport to a server.
92+
93+
!!! note
94+
[`MCPServerStreamableHTTP`][pydantic_ai.mcp.MCPServerStreamableHTTP] requires an MCP server to be
95+
running and accepting HTTP connections before calling
96+
[`agent.run_mcp_servers()`][pydantic_ai.Agent.run_mcp_servers]. Running the server is not
97+
managed by PydanticAI.
98+
99+
Before creating the Streamable HTTP client, we need to run a server that supports the Streamable HTTP transport.
100+
101+
```python {title="streamable_http_server.py" py="3.10" test="skip"}
102+
from mcp.server.fastmcp import FastMCP
103+
104+
app = FastMCP()
105+
106+
@app.tool()
107+
def add(a: int, b: int) -> int:
108+
return a + b
109+
110+
app.run(transport='streamable-http')
111+
```
112+
113+
Then we can create the client:
114+
115+
```python {title="mcp_streamable_http_client.py" py="3.10"}
116+
from pydantic_ai import Agent
117+
from pydantic_ai.mcp import MCPServerStreamableHTTP
118+
119+
server = MCPServerStreamableHTTP('http://localhost:8000/mcp')
120+
agent = Agent('openai:gpt-4o', mcp_servers=[server])
121+
122+
async def main():
123+
async with agent.run_mcp_servers(): # (3)!
124+
result = await agent.run('How many days between 2000-01-01 and 2025-03-18?')
125+
print(result.output)
126+
#> There are 9,208 days between January 1, 2000, and March 18, 2025.
127+
```
128+
129+
1. Create an agent with the MCP server attached.
130+
2. Create a client session to connect to the server.
131+
132+
_(This example is complete, it can be run "as is" with Python 3.10+ — you'll need to add `asyncio.run(main())` to run `main`)_
133+
87134
### MCP "stdio" Server
88135

89136
The other transport offered by MCP is the [stdio transport](https://spec.modelcontextprotocol.io/specification/2024-11-05/basic/transports/#stdio) where the server is run as a subprocess and communicates with the client over `stdin` and `stdout`. In this case, you'd use the [`MCPServerStdio`][pydantic_ai.mcp.MCPServerStdio] class.
@@ -135,15 +182,15 @@ This allows you to use multiple servers that might have overlapping tool names w
135182

136183
```python {title="mcp_tool_prefix_http_client.py" py="3.10"}
137184
from pydantic_ai import Agent
138-
from pydantic_ai.mcp import MCPServerHTTP
185+
from pydantic_ai.mcp import MCPServerSSE
139186

140187
# Create two servers with different prefixes
141-
weather_server = MCPServerHTTP(
188+
weather_server = MCPServerSSE(
142189
url='http://localhost:3001/sse',
143190
tool_prefix='weather' # Tools will be prefixed with 'weather_'
144191
)
145192

146-
calculator_server = MCPServerHTTP(
193+
calculator_server = MCPServerSSE(
147194
url='http://localhost:3002/sse',
148195
tool_prefix='calc' # Tools will be prefixed with 'calc_'
149196
)

0 commit comments

Comments
 (0)