Skip to content

Commit c79933b

Browse files
authored
rename MCPServerSSE to MCPServerHTTP and more docs (#1176)
1 parent 84fc46a commit c79933b

File tree

9 files changed

+77
-69
lines changed

9 files changed

+77
-69
lines changed

docs/api/mcp.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1 +1,3 @@
1+
# `pydantic_ai.mcp`
2+
13
::: pydantic_ai.mcp

docs/mcp/client.md

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

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

21-
- [`MCPServerSSE`][pydantic_ai.mcp.MCPServerSSE] which connects to an MCP server using the [HTTP SSE](https://modelcontextprotocol.io/docs/concepts/transports#server-sent-events-sse) transport
22-
- [`MCPServerStdio`][pydantic_ai.mcp.MCPServerStdio] which runs the server as a subprocess and connects to it using the [stdio](https://modelcontextprotocol.io/docs/concepts/transports#standard-input%2Foutput-stdio) transport
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
22+
- [`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
2323

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

2626
### SSE Client
2727

28-
[`MCPServerSSE`][pydantic_ai.mcp.MCPServerSSE] connects over HTTP using the [HTTP + Server Sent Events transport](https://modelcontextprotocol.io/docs/concepts/transports#server-sent-events-sse) to a server.
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.
2929

3030
!!! note
31-
[`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.
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+
33+
The name "HTTP" is used since this implemented will be adapted in future to use the new
34+
[Streamable HTTP](https://github.com/modelcontextprotocol/specification/pull/206) currently in development.
3235

3336
Before creating the SSE client, we need to run the server (docs [here](run-python.md)):
3437

35-
```bash {title="run_sse_server.py"}
38+
```bash {title="terminal (run sse server)"}
3639
npx @pydantic/mcp-run-python sse
3740
```
3841

3942
```python {title="mcp_sse_client.py" py="3.10"}
4043
from pydantic_ai import Agent
41-
from pydantic_ai.mcp import MCPServerSSE
44+
from pydantic_ai.mcp import MCPServerHTTP
4245

43-
server = MCPServerSSE(url='http://localhost:3001/sse') # (1)!
46+
server = MCPServerHTTP(url='http://localhost:3001/sse') # (1)!
4447
agent = Agent('openai:gpt-4o', mcp_servers=[server]) # (2)!
4548

4649

@@ -81,7 +84,7 @@ Will display as follows:
8184

8285
### MCP "stdio" Server
8386

84-
The other transport offered by MCP is the [stdio transport](https://modelcontextprotocol.io/docs/concepts/transports#standard-input%2Foutput-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.
87+
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.
8588

8689
!!! note
8790
When using [`MCPServerStdio`][pydantic_ai.mcp.MCPServerStdio] servers, the [`agent.run_mcp_servers()`][pydantic_ai.Agent.run_mcp_servers] context manager is responsible for starting and stopping the server.

docs/mcp/run-python.md

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -20,8 +20,8 @@ npx @pydantic/mcp-run-python [stdio|sse]
2020

2121
Where:
2222

23-
* `stdio`: Runs the server with [stdin/stdout transport](https://modelcontextprotocol.io/docs/concepts/transports#standard-input%2Foutput-stdio) (for subprocess usage)
24-
* `sse`: Runs the server with [HTTP Server-Sent Events transport](https://modelcontextprotocol.io/docs/concepts/transports#server-sent-events-sse) (for remote connections)
23+
* `stdio`: Runs the server with [stdin/stdout transport](https://spec.modelcontextprotocol.io/specification/2024-11-05/basic/transports/#stdio) (for subprocess usage)
24+
* `sse`: Runs the server with [HTTP Server-Sent Events transport](https://spec.modelcontextprotocol.io/specification/2024-11-05/basic/transports/#http-with-sse) (for remote connections)
2525

2626
Usage of `@pydantic/mcp-run-python` with PydanticAI is described in the [client](client.md#mcp-stdio-server) documentation.
2727

@@ -75,6 +75,9 @@ async def main():
7575
"""
7676
```
7777

78+
If an exception occurs, `status` will be `install-error` or `run-error` and `return_value` will be replaced
79+
by `error` which will include the traceback and exception message.
80+
7881
## Dependencies
7982

8083
Dependencies are installed when code is run.

examples/pydantic_ai_examples/mcp_server.py

Lines changed: 0 additions & 37 deletions
This file was deleted.

mcp-run-python/README.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -13,5 +13,5 @@ npx @pydantic/mcp-run-python [stdio|sse]
1313

1414
where:
1515

16-
- `stdio` runs the server with the [Stdio MCP transport](https://modelcontextprotocol.io/docs/concepts/transports#standard-input%2Foutput-stdio) — suitable for running the process as a subprocess locally
17-
- and `sse` runs the server with the [SSE MCP transport](https://modelcontextprotocol.io/docs/concepts/transports#server-sent-events-sse) — running the server as an HTTP server to connect locally or remotely
16+
- `stdio` runs the server with the [Stdio MCP transport](https://spec.modelcontextprotocol.io/specification/2024-11-05/basic/transports/#stdio) — suitable for running the process as a subprocess locally
17+
- and `sse` runs the server with the [SSE MCP transport](https://spec.modelcontextprotocol.io/specification/2024-11-05/basic/transports/#http-with-sse) — running the server as an HTTP server to connect locally or remotely

mkdocs.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -55,6 +55,7 @@ nav:
5555
- api/exceptions.md
5656
- api/settings.md
5757
- api/usage.md
58+
- api/mcp.md
5859
- api/format_as_xml.md
5960
- api/models/base.md
6061
- api/models/openai.md
@@ -69,7 +70,6 @@ nav:
6970
- api/models/function.md
7071
- api/models/fallback.md
7172
- api/providers.md
72-
- api/mcp.md
7373
- api/pydantic_graph/graph.md
7474
- api/pydantic_graph/nodes.md
7575
- api/pydantic_graph/persistence.md

pydantic_ai_slim/pydantic_ai/mcp.py

Lines changed: 53 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,3 @@
1-
"""This module implements the MCP server interface between the agent and the LLM.
2-
3-
See <https://docs.cursor.com/context/model-context-protocol> for more information.
4-
"""
5-
61
from __future__ import annotations
72

83
from abc import ABC, abstractmethod
@@ -29,13 +24,13 @@
2924
"you can use the `mcp` optional group — `pip install 'pydantic-ai-slim[mcp]'`"
3025
) from _import_error
3126

32-
__all__ = ('MCPServer', 'MCPServerStdio', 'MCPServerSSE')
27+
__all__ = 'MCPServer', 'MCPServerStdio', 'MCPServerHTTP'
3328

3429

3530
class MCPServer(ABC):
36-
"""Base class for MCP servers that can be used to run a command or connect to an SSE server.
31+
"""Base class for attaching agents to MCP servers.
3732
38-
See <https://modelcontextprotocol.io/introduction> for more information.
33+
See <https://modelcontextprotocol.io> for more information.
3934
"""
4035

4136
is_running: bool = False
@@ -105,19 +100,30 @@ async def __aexit__(
105100

106101
@dataclass
107102
class MCPServerStdio(MCPServer):
108-
"""An MCP server that runs a subprocess.
103+
"""Runs an MCP server in a subprocess and communicates with it over stdin/stdout.
109104
110105
This class implements the stdio transport from the MCP specification.
111-
See <https://modelcontextprotocol.io/docs/concepts/transports#standard-input%2Foutput-stdio> for more information.
106+
See <https://spec.modelcontextprotocol.io/specification/2024-11-05/basic/transports/#stdio> for more information.
107+
108+
!!! note
109+
Using this class as an async context manager will start the server as a subprocess when entering the context,
110+
and stop it when exiting the context.
112111
113112
Example:
114113
```python {py="3.10"}
115114
from pydantic_ai import Agent
116115
from pydantic_ai.mcp import MCPServerStdio
117116
118-
server = MCPServerStdio('python', ['-m', 'pydantic_ai_examples.mcp_server'])
117+
server = MCPServerStdio('npx', ['-y', '@pydantic/mcp-run-python', 'stdio']) # (1)!
119118
agent = Agent('openai:gpt-4o', mcp_servers=[server])
119+
120+
async def main():
121+
async with agent.run_mcp_servers(): # (2)!
122+
...
120123
```
124+
125+
1. See [MCP Run Python](../mcp/run-python.md) for more information.
126+
2. This will start the server as a subprocess and connect to it.
121127
"""
122128

123129
command: str
@@ -127,7 +133,11 @@ class MCPServerStdio(MCPServer):
127133
"""The arguments to pass to the command."""
128134

129135
env: dict[str, str] | None = None
130-
"""The environment variables the CLI server will have access to."""
136+
"""The environment variables the CLI server will have access to.
137+
138+
By default the subprocess will not inherit any environment variables from the parent process.
139+
If you want to inherit the environment variables from the parent process, use `env=os.environ`.
140+
"""
131141

132142
@asynccontextmanager
133143
async def client_streams(
@@ -141,15 +151,42 @@ async def client_streams(
141151

142152

143153
@dataclass
144-
class MCPServerSSE(MCPServer):
145-
"""An MCP server that connects to a remote server.
154+
class MCPServerHTTP(MCPServer):
155+
"""An MCP server that connects over streamable HTTP connections.
146156
147157
This class implements the SSE transport from the MCP specification.
148-
See <https://modelcontextprotocol.io/docs/concepts/transports#server-sent-events-sse> for more information.
158+
See <https://spec.modelcontextprotocol.io/specification/2024-11-05/basic/transports/#http-with-sse> for more information.
159+
160+
The name "HTTP" is used since this implemented will be adapted in future to use the new
161+
[Streamable HTTP](https://github.com/modelcontextprotocol/specification/pull/206) currently in development.
162+
163+
!!! note
164+
Using this class as an async context manager will create a new pool of HTTP connections to connect
165+
to a server which should already be running.
166+
167+
Example:
168+
```python {py="3.10"}
169+
from pydantic_ai import Agent
170+
from pydantic_ai.mcp import MCPServerHTTP
171+
172+
server = MCPServerHTTP('http://localhost:3001/sse') # (1)!
173+
agent = Agent('openai:gpt-4o', mcp_servers=[server])
174+
175+
async def main():
176+
async with agent.run_mcp_servers(): # (2)!
177+
...
178+
```
179+
180+
1. E.g. you might be connecting to a server run with `npx @pydantic/mcp-run-python sse`,
181+
see [MCP Run Python](../mcp/run-python.md) for more information.
182+
2. This will connect to a server running on `localhost:3001`.
149183
"""
150184

151185
url: str
152-
"""The URL of the remote server."""
186+
"""The URL of the SSE endpoint on the MCP server.
187+
188+
For example for a server running locally, this might be `http://localhost:3001/sse`.
189+
"""
153190

154191
@asynccontextmanager
155192
async def client_streams(

tests/test_examples.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -79,7 +79,7 @@ def test_docs_examples( # noqa: C901
7979
mocker.patch('rich.prompt.Prompt.ask', side_effect=rich_prompt_ask)
8080

8181
if sys.version_info >= (3, 10):
82-
mocker.patch('pydantic_ai.mcp.MCPServerSSE', return_value=MockMCPServer())
82+
mocker.patch('pydantic_ai.mcp.MCPServerHTTP', return_value=MockMCPServer())
8383
mocker.patch('mcp.server.fastmcp.FastMCP')
8484

8585
env.set('OPENAI_API_KEY', 'testing')

tests/test_mcp.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@
1313
with try_import() as imports_successful:
1414
from mcp.types import CallToolResult, TextContent
1515

16-
from pydantic_ai.mcp import MCPServerSSE, MCPServerStdio
16+
from pydantic_ai.mcp import MCPServerHTTP, MCPServerStdio
1717
from pydantic_ai.models.openai import OpenAIModel
1818
from pydantic_ai.providers.openai import OpenAIProvider
1919

@@ -39,7 +39,7 @@ async def test_stdio_server():
3939

4040

4141
def test_sse_server():
42-
sse_server = MCPServerSSE(url='http://localhost:8000/sse')
42+
sse_server = MCPServerHTTP(url='http://localhost:8000/sse')
4343
assert sse_server.url == 'http://localhost:8000/sse'
4444

4545

0 commit comments

Comments
 (0)