You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
PydanticAI comes with two ways to connect to MCP servers:
19
+
PydanticAI comes with three ways to connect to MCP servers:
20
20
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
21
-[`MCPServerStreamableHTTP`][pydantic_ai.mcp.MCPServerStreamableHTTP] which connects to an MCP server using the [Streamable HTTP](https://modelcontextprotocol.io/introduction#streamable-http) transport
22
+
-[`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
23
23
-[`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
24
24
25
-
Examples of both are shown below; [mcp-run-python](run-python.md) is used as the MCP server in both examples.
25
+
Examples of all three are shown below; [mcp-run-python](run-python.md) is used as the MCP server in all examples.
26
26
27
-
### SSE Client
27
+
Each MCP server instance is a [toolset](../toolsets.md) and can be registered with an [`Agent`][pydantic_ai.Agent] using the `toolsets` argument.
28
28
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.
29
+
You can use the [`async with agent`][pydantic_ai.Agent.__aenter__] context manager to open and close connections to all registered servers (and in the case of stdio servers, start and stop the subprocesses) around the context where they'll be used in agent runs. You can also use [`async with server`][pydantic_ai.mcp.MCPServer.__aenter__] to manage the connection or subprocess of a specific server, for example if you'd like to use it with multiple agents. If you don't explicitly enter one of these context managers to set up the server, this will be done automatically when it's needed (e.g. to list the available tools or call a specific tool), but it's more efficient to do so around the entire context where you expect the servers to be used.
30
+
31
+
### Streamable HTTP Client
32
+
33
+
[`MCPServerStreamableHTTP`][pydantic_ai.mcp.MCPServerStreamableHTTP] connects over HTTP using the
34
+
[Streamable HTTP](https://modelcontextprotocol.io/introduction#streamable-http) transport to a server.
30
35
31
36
!!! note
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.
37
+
[`MCPServerStreamableHTTP`][pydantic_ai.mcp.MCPServerStreamableHTTP] requires an MCP server to be
38
+
running and accepting HTTP connections before running the agent. Running the server is not
39
+
managed by Pydantic AI.
33
40
34
-
The name "HTTP" is used since this implementation will be adapted in future to use the new
35
-
[Streamable HTTP](https://github.com/modelcontextprotocol/specification/pull/206) currently in development.
41
+
Before creating the Streamable HTTP client, we need to run a server that supports the Streamable HTTP transport.
36
42
37
-
Before creating the SSE client, we need to run the server (docs [here](run-python.md)):
result =await agent.run('How many days between 2000-01-01 and 2025-03-18?')
56
68
print(result.output)
57
69
#> There are 9,208 days between January 1, 2000, and March 18, 2025.
@@ -85,43 +97,34 @@ Will display as follows:
85
97
86
98

87
99
88
-
### Streamable HTTP Client
100
+
### SSE Client
89
101
90
-
[`MCPServerStreamableHTTP`][pydantic_ai.mcp.MCPServerStreamableHTTP] connects over HTTP using the
91
-
[Streamable HTTP](https://modelcontextprotocol.io/introduction#streamable-http) transport to a server.
102
+
[`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.
92
103
93
104
!!! 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.
[`MCPServerSSE`][pydantic_ai.mcp.MCPServerSSE] requires an MCP server to be running and accepting HTTP connections before running the agent. Running the server is not managed by Pydantic AI.
103
106
104
-
app = FastMCP()
107
+
The name "HTTP" is used since this implementation will be adapted in future to use the new
108
+
[Streamable HTTP](https://github.com/modelcontextprotocol/specification/pull/206) currently in development.
105
109
106
-
@app.tool()
107
-
defadd(a: int, b: int) -> int:
108
-
return a + b
110
+
Before creating the SSE client, we need to run the server (docs [here](run-python.md)):
result =await agent.run('How many days between 2000-01-01 and 2025-03-18?')
126
129
print(result.output)
127
130
#> There are 9,208 days between January 1, 2000, and March 18, 2025.
@@ -137,9 +140,6 @@ _(This example is complete, it can be run "as is" with Python 3.10+ — you'll n
137
140
138
141
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.
139
142
140
-
!!! note
141
-
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.
142
-
143
143
```python {title="mcp_stdio_client.py" py="3.10"}
144
144
from pydantic_ai import Agent
145
145
from pydantic_ai.mcp import MCPServerStdio
@@ -156,11 +156,11 @@ server = MCPServerStdio( # (1)!
server = MCPServerStdio('python', ['mcp_server.py'], process_tool_call=process_tool_call)
199
199
agent = Agent(
200
200
model=TestModel(call_tools=['echo_deps']),
201
201
deps_type=int,
202
-
mcp_servers=[server]
202
+
toolsets=[server]
203
203
)
204
204
205
205
206
206
asyncdefmain():
207
-
asyncwith agent.run_mcp_servers():
207
+
asyncwith agent:
208
208
result =await agent.run('Echo with deps set to 42', deps=42)
209
209
print(result.output)
210
210
#> {"echo_deps":{"echo":"This is an echo message","deps":42}}
@@ -214,15 +214,7 @@ async def main():
214
214
215
215
When connecting to multiple MCP servers that might provide tools with the same name, you can use the `tool_prefix` parameter to avoid naming conflicts. This parameter adds a prefix to all tool names from a specific server.
216
216
217
-
### How It Works
218
-
219
-
- If `tool_prefix` is set, all tools from that server will be prefixed with `{tool_prefix}_`
220
-
- When listing tools, the prefixed names are shown to the model
221
-
- When calling tools, the prefix is automatically removed before sending the request to the server
222
-
223
-
This allows you to use multiple servers that might have overlapping tool names without conflicts.
224
-
225
-
### Example with HTTP Server
217
+
This allows you to use multiple servers that might have overlapping tool names without conflicts:
When the model interacts with these servers, it will see the prefixed tool names, but the prefixes will be automatically handled when making tool calls.
279
-
280
240
## MCP Sampling
281
241
282
242
!!! info "What is MCP Sampling?"
@@ -312,6 +272,8 @@ Pydantic AI supports sampling as both a client and server. See the [server](./se
312
272
313
273
Sampling is automatically supported by Pydantic AI agents when they act as a client.
314
274
275
+
To be able to use sampling, an MCP server instance needs to have a [`sampling_model`][pydantic_ai.mcp.MCPServerStdio.sampling_model] set. This can be done either directly on the server using the constructor keyword argument or the property, or by using [`agent.set_mcp_sampling_model()`][pydantic_ai.Agent.set_mcp_sampling_model] to set the agent's model or one specified as an argument as the sampling model on all MCP servers registered with that agent.
276
+
315
277
Let's say we have an MCP server that wants to use sampling (in this case to generate an SVG as per the tool arguments).
316
278
317
279
??? example "Sampling MCP Server"
@@ -359,11 +321,12 @@ from pydantic_ai import Agent
359
321
from pydantic_ai.mcp import MCPServerStdio
360
322
361
323
server = MCPServerStdio(command='python', args=['generate_svg.py'])
Copy file name to clipboardExpand all lines: docs/models/huggingface.md
+1-1Lines changed: 1 addition & 1 deletion
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -69,7 +69,7 @@ agent = Agent(model)
69
69
## Custom Hugging Face client
70
70
71
71
[`HuggingFaceProvider`][pydantic_ai.providers.huggingface.HuggingFaceProvider] also accepts a custom
72
-
[`AsyncInferenceClient`][huggingface_hub.AsyncInferenceClient] client via the `hf_client` parameter, so you can customise
72
+
[`AsyncInferenceClient`](https://huggingface.co/docs/huggingface_hub/v0.29.3/en/package_reference/inference_client#huggingface_hub.AsyncInferenceClient) client via the `hf_client` parameter, so you can customise
73
73
the `headers`, `bill_to` (billing to an HF organization you're a member of), `base_url` etc. as defined in the
74
74
[Hugging Face Hub python library docs](https://huggingface.co/docs/huggingface_hub/package_reference/inference_client).
# Bubble up potentially retryable errors to the router agent
202
-
if (cause := e.__cause__) andhasattr(cause, 'tool_retry'):
203
-
raise ModelRetry(f'SQL agent failed: {cause.tool_retry.content}') from e
202
+
if (cause := e.__cause__) andisinstance(cause, ModelRetry):
203
+
raise ModelRetry(f'SQL agent failed: {cause.message}') from e
204
204
else:
205
205
raise
206
206
@@ -276,6 +276,8 @@ In the default Tool Output mode, the output JSON schema of each output type (or
276
276
277
277
If you'd like to change the name of the output tool, pass a custom description to aid the model, or turn on or off strict mode, you can wrap the type(s) in the [`ToolOutput`][pydantic_ai.output.ToolOutput] marker class and provide the appropriate arguments. Note that by default, the description is taken from the docstring specified on a Pydantic model or output function, so specifying it using the marker class is typically not necessary.
278
278
279
+
To dynamically modify or filter the available output tools during an agent run, you can define an agent-wide `prepare_output_tools` function that will be called ahead of each step of a run. This function should be of type [`ToolsPrepareFunc`][pydantic_ai.tools.ToolsPrepareFunc], which takes the [`RunContext`][pydantic_ai.tools.RunContext] and a list of [`ToolDefinition`][pydantic_ai.tools.ToolDefinition], and returns a new list of tool definitions (or `None` to disable all tools for that step). This is analogous to the [`prepare_tools` function](tools.md#prepare-tools) for non-output tools.
Copy file name to clipboardExpand all lines: docs/testing.md
+1-1Lines changed: 1 addition & 1 deletion
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -10,7 +10,7 @@ Unless you're really sure you know better, you'll probably want to follow roughl
10
10
* If you find yourself typing out long assertions, use [inline-snapshot](https://15r10nk.github.io/inline-snapshot/latest/)
11
11
* Similarly, [dirty-equals](https://dirty-equals.helpmanual.io/latest/) can be useful for comparing large data structures
12
12
* Use [`TestModel`][pydantic_ai.models.test.TestModel] or [`FunctionModel`][pydantic_ai.models.function.FunctionModel] in place of your actual model to avoid the usage, latency and variability of real LLM calls
13
-
* Use [`Agent.override`][pydantic_ai.agent.Agent.override] to replace your model inside your application logic
13
+
* Use [`Agent.override`][pydantic_ai.agent.Agent.override] to replace an agent's model, dependencies, or toolsets inside your application logic
14
14
* Set [`ALLOW_MODEL_REQUESTS=False`][pydantic_ai.models.ALLOW_MODEL_REQUESTS] globally to block any requests from being made to non-test models accidentally
0 commit comments