Skip to content

MCP API

Model Context Protocol (MCP) client support. Build MCP server toolsets and attach them to an agent via the mcp_servers parameter of create_deep_agent. See MCP servers for the conceptual overview.

build_mcp_server

pydantic_deep.mcp.build_mcp_server(config, resolver=None, *, oauth_token_storage=None)

Build a connected pydantic-ai MCP toolset from a config.

Resolves the auth secret (if any) and injects it as an HTTP header (for bearer/header auth) or a subprocess env var (for env auth). Wraps the toolset in a PrefixedToolset when tool_prefix is set. When config.init_timeout is set it is forwarded to the MCPToolset, raising the connect/initialize deadline above pydantic-ai's 5s default for servers that are slow to become ready.

Only the server's tools are built here. To also expose its resources or skill:// skills to the model, set include_resources / include_skills on the config and build via :meth:MCPRegistry.build_active.

For stdio servers, the subprocess receives config.env (plus any env-kind auth var) layered on top of the MCP SDK's safe default environment (PATH, HOME, …) — the parent process's full environment is intentionally not inherited, so secrets like API keys are never leaked to a third-party server. Add anything else a server needs (proxies, NODE_EXTRA_CA_CERTS, …) explicitly via config.env.

Parameters:

Name Type Description Default
oauth_token_storage Any | None

A persistent AsyncKeyValue store for OAuth tokens (e.g. a disk-backed store). When provided for an oauth server, the token survives restarts and is shared between the connection test and the agent (FastMCP keys tokens by server URL). When None, FastMCP uses in-memory storage (token re-auth per client/restart).

None

Raises:

Type Description
MCPNotInstalledError

if the mcp optional dependency is missing.

probe_mcp_server

pydantic_deep.mcp.probe_mcp_server(server, timeout=10.0) async

Connect to a built MCP server and list its tools, with a timeout.

Returns a :class:MCPProbeResult capturing success + tool names, or the error string on failure. Never raises.

create_mcp_resources_toolset

Most MCP servers are used for their tools, but a server can also publish resources — docs, templates, or FastMCP skill://.../SKILL.md skills. pydantic-ai surfaces only the tools to the model, so set include_resources=True (or include_skills=True for skills specifically) on an MCPServerConfig and build with MCPRegistry.build_active to attach a second toolset that lets the model discover and read them:

Python
from pydantic_deep.mcp import MCPRegistry, MCPServerConfig

registry = MCPRegistry([
    MCPServerConfig(
        name="service",
        transport="http",
        url="https://example.com/mcp/",
        include_skills=True,  # exposes list_mcp_skills / load_mcp_skill
    ),
])
mcp_servers = registry.build_active()  # tools toolset + resources toolset

The resources toolset adds list_mcp_resources / read_mcp_resource, plus list_mcp_skills / load_mcp_skill when include_skills is set. It binds to the same underlying MCPToolset, so tools and resources share one connection.

Every server's tools carry a prefix, so the example above registers service_list_mcp_skills, service_load_mcp_skill and so on. The prefix is the server's tool_prefix when set, otherwise its name — without it, two servers exposing their resources would register identical tool names and pydantic-ai would reject the collision and fail the run.

With include_skills the toolset also lists the server's skills in the system prompt, so the model knows the guidance exists before it reaches for the server's operational tools rather than having to go looking for it.

A server that is unreachable degrades the same way its tools do: these tools return the error as text instead of raising out of agent.run().

Use create_mcp_resources_toolset directly to wrap a server you built yourself — pass tool_prefix if more than one server will expose its resources.

pydantic_deep.mcp.create_mcp_resources_toolset(provider, *, server_name, id=None, include_skills=True, tool_prefix=None)

Build a toolset that exposes an MCP server's resources to the model.

Parameters:

Name Type Description Default
provider MCPResourceProvider

The connected MCP server (anything with list_resources / read_resource). MCPToolset manages its own connection, so the tools work whether or not the toolset is currently entered.

required
server_name str

Server identifier, used in the toolset id, the tool descriptions and the skill error text.

required
id str | None

Explicit toolset id (defaults to mcp-resources-<server_name>).

None
include_skills bool

Also register list_mcp_skills / load_mcp_skill for skill:// resources, and announce the server's skills in the system prompt so the model knows they exist before using the server's tools.

True
tool_prefix str | None

Prepended to every tool name as <prefix>_<name>. Needed when more than one server exposes its resources — the tool names are otherwise identical and pydantic-ai rejects the collision, failing the whole run. :meth:MCPRegistry.build_active always passes one.

None

Returns:

Type Description
FunctionToolset[Any]

A FunctionToolset with list_mcp_resources, read_mcp_resource, and

FunctionToolset[Any]

(when include_skills) the two skill tools.

builtin_mcp_servers

pydantic_deep.mcp.builtin_mcp_servers()

Return fresh :class:MCPServerConfig instances for the built-in servers.

All are disabled by default — the user opts in via /mcp.

auth_satisfied

pydantic_deep.mcp.auth_satisfied(config, resolver=None)

True when the server needs no pre-stored secret, or its secret resolves.

oauth servers are always considered satisfied here — they authorize interactively at connect time, with no token to enter up front.

parse_mcp_servers

pydantic_deep.mcp.parse_mcp_servers(servers, *, enabled=True)

Convert a mcpServers mapping to :class:MCPServerConfig list.

Recognises stdio (command), HTTP (type: http/streamable-http or a bare url) and SSE (type: sse). WebSocket (type: ws) and malformed entries are skipped. ${VAR} references in command/args/env/url/headers are expanded. Tokens already present in env/headers are carried over.

MCPServerConfig

pydantic_deep.mcp.MCPServerConfig dataclass

Connection + auth description for a single MCP server.

A stdio server requires command; http/sse servers require url.

init_timeout = None class-attribute instance-attribute

Seconds to wait for the initial connection + initialize handshake.

None uses pydantic-ai's default (5s). Raise it for servers that are slow to become ready (e.g. one that opens a database connection on startup), which would otherwise fail with "Failed to initialize server session".

include_resources = False class-attribute instance-attribute

Expose the server's MCP resources to the model via list_mcp_resources / read_mcp_resource. Off by default — most servers are used for tools only.

include_skills = False class-attribute instance-attribute

Expose the server's skill://.../SKILL.md resources via list_mcp_skills / load_mcp_skill (and enables resource reading). See issue #178.

requires_auth property

True when a pre-stored secret must be provided before use.

oauth returns False: there's no token to enter up front — the client runs the OAuth flow interactively at connect time.

MCPAuth

pydantic_deep.mcp.MCPAuth dataclass

Describes how to authenticate to an MCP server using a stored secret.

Parameters:

Name Type Description Default
secret_key str

Name under which the token is stored (keystore / env var), e.g. "GITHUB_MCP_PAT". Not required for oauth/none.

''
kind MCPAuthKind

How auth is performed (see :data:MCPAuthKind).

'bearer'
header str

Header name for bearer/header auth.

'Authorization'
env_var str | None

Environment variable name for env auth (defaults to secret_key when omitted).

None
value_template str

Template formatted with token=<secret> to produce the header/env value. Defaults to "Bearer {token}".

'Bearer {token}'
instructions str

Human-readable hint on how to obtain the token, shown in the CLI login flow.

''
client_name str | None

OAuth client name advertised during dynamic client registration (oauth only). Some servers (e.g. Figma's hosted MCP during beta) allowlist this; leave None to use the default.

None

render_value(token)

Format value_template with the resolved token.

MCPRegistry

pydantic_deep.mcp.MCPRegistry

A mutable collection of MCP server configs with secret-aware building.

build_active(on_degraded=None)

Build toolsets for every server that is enabled and authenticated.

Each is wrapped via :func:make_resilient so that a configured server which turns out to be unreachable at runtime contributes no tools rather than failing the entire agent run. on_degraded(name, reason) is forwarded to each wrapper.

A server with include_resources / include_skills set contributes a second toolset exposing its MCP resources (and skill:// skills) to the model. It binds to the same underlying MCPToolset so tools and resources share one connection, and its tools are prefixed per server so several such servers can be active at once.

MCPProbeResult

pydantic_deep.mcp.MCPProbeResult dataclass

Outcome of a connection probe against an MCP server.

MCPNotInstalledError

pydantic_deep.mcp.MCPNotInstalledError

Bases: ImportError

Raised when building an MCP server but the optional dependency is absent.