fastmcp/docs/integrations/pydantic-ai.mdx
nate nowack 1e03ce39b1
docs: update the Pydantic AI integration for MCPToolset and the 2.45 floor (#5211)
The page documented FastMCPToolset and the pydantic-ai-slim[fastmcp] extra,
both removed in Pydantic AI 2, and said elicitation was unsupported. It now
uses MCPToolset and the [mcp] extra, covers auth headers, config files and
elicitation, and states the pydantic-ai-slim 2.45 floor: 2.32 through 2.44
import httpx without depending on it, which FastMCP 4 no longer installs.
The upgrade guide gets the same floor.


Claude-Session: https://claude.ai/code/session_01KfHgVhbYEhBCC5eSeqGiuG

Co-authored-by: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-09-22 13:38:25 -05:00

104 lines
3.6 KiB
Text

---
title: Pydantic AI 🤝 FastMCP
sidebarTitle: Pydantic AI
description: Connect FastMCP servers to Pydantic AI agents with MCPToolset
icon: message-code
---
[Pydantic AI](https://pydantic.dev/docs/ai/)'s [`MCPToolset`](https://pydantic.dev/docs/ai/mcp/client/) is built on the [FastMCP Client](/clients/client), so an agent can use any MCP server over any FastMCP [transport](/clients/transports). It covers tools, resources, prompts, and elicitation. This page shows how to point it at a FastMCP server; for the full API, see the [Pydantic AI docs](https://pydantic.dev/docs/ai/mcp/client/).
## Install
```bash
pip install "pydantic-ai-slim[mcp]>=2.45"
```
The `mcp` extra installs the client-only `fastmcp-slim[client]`. Add `fastmcp` if the same environment also runs a FastMCP server.
<Note>
With FastMCP 4, use `pydantic-ai-slim` 2.45 or newer. Releases 2.32 through 2.44 import `httpx` without depending on it, and FastMCP 4 no longer installs `httpx`, so `import pydantic_ai.mcp` fails.
</Note>
## Create a Server
```python server.py
import random
from fastmcp import FastMCP
mcp = FastMCP(name="Dice Roller")
@mcp.tool
def roll_dice(n_dice: int) -> list[int]:
"""Roll `n_dice` 6-sided dice and return the results."""
return [random.randint(1, 6) for _ in range(n_dice)]
if __name__ == "__main__":
mcp.run(transport="http", port=8000)
```
## Connect an Agent
Pass `MCPToolset` anything the FastMCP Client accepts. It infers the transport the same way the client does.
```python
from pathlib import Path
from pydantic_ai import Agent
from pydantic_ai.mcp import MCPToolset
from server import mcp
in_memory = MCPToolset(mcp) # a FastMCP instance in the same process
http = MCPToolset("http://localhost:8000/mcp") # Streamable HTTP; a /sse URL uses SSE
stdio = MCPToolset(Path("server.py")) # launches the script over STDIO
agent = Agent("openai:gpt-5", toolsets=[http])
result = agent.run_sync("Roll 3 dice!")
```
Pass a FastMCP [transport](/clients/transports) such as `StdioTransport` for control over the command, arguments, or environment, or a configured `fastmcp.Client` for full control.
## Authentication
For a bearer token, pass `headers`. For [OAuth](/clients/auth/oauth), pass `auth="oauth"` or build the `Client` yourself.
```python
toolset = MCPToolset(
"https://your-server-url.com/mcp",
headers={"Authorization": "Bearer your-access-token"},
)
```
For server-side token verification, see [Token Verification](/servers/auth/token-verification).
## Multiple Servers
`load_mcp_toolsets` reads an [MCP configuration](/integrations/mcp-json-configuration) file and returns one toolset per server. Tool names are prefixed with the server's key.
```json mcp_config.json
{
"mcpServers": {
"dice": {"command": "python", "args": ["server.py"]},
"weather": {"url": "https://weather.example.com/mcp"}
}
}
```
```python
from pydantic_ai import Agent
from pydantic_ai.mcp import load_mcp_toolsets
agent = Agent("openai:gpt-5", toolsets=load_mcp_toolsets("mcp_config.json"))
```
## Elicitation
Pass an `elicitation_handler` to answer a server's [elicitation](/servers/elicitation) requests. It has the same signature as the FastMCP Client's [elicitation handler](/clients/elicitation).
```python
async def approve(message, response_type, params, context):
return {"approved": True}
toolset = MCPToolset("http://localhost:8000/mcp", elicitation_handler=approve)
```
On 2026-07-28 connections, Pydantic AI may warn that `elicitation_handler` will never be called. The FastMCP Client still calls it for [input-required results](/servers/elicitation#elicitation-on-the-modern-protocol).