Skip to content
Merged
Show file tree
Hide file tree
Changes from 46 commits
Commits
Show all changes
59 commits
Select commit Hold shift + click to select a range
b60efe7
feature: Native MCP support
Artui Oct 7, 2025
20a4a6a
Addressing more comments
Artui Oct 13, 2025
e13791f
cleaning up after bad merge
Artui Oct 13, 2025
1c7f17c
cleaning up after bad merge
Artui Oct 13, 2025
18550b8
cleaning up after bad merge
Artui Oct 13, 2025
d61b13e
cleaning up after bad merge
Artui Oct 13, 2025
ee14592
cleaning up after bad merge
Artui Oct 13, 2025
73d5cdb
cleaning up after bad merge
Artui Oct 13, 2025
1663899
cleaning up after bad merge
Artui Oct 13, 2025
c0c27b3
Merge branch 'main' into feature/native-mcp-support
Artui Oct 14, 2025
830c1a8
Addressing more comments
Artui Oct 14, 2025
07f88ac
Addressing more comments
Artui Oct 14, 2025
0112cd1
Addressing more comments
Artui Oct 14, 2025
4fb69a1
Addressing more comments
Artui Oct 14, 2025
d40dbc1
Addressing more comments
Artui Oct 14, 2025
7fb266e
Addressing more comments
Artui Oct 14, 2025
7c9994e
Addressing more comments
Artui Oct 14, 2025
9ffbf8f
Addressing more comments
Artui Oct 14, 2025
9a188b0
Addressing more comments
Artui Oct 14, 2025
2826e05
Addressing more comments
Artui Oct 14, 2025
4166f67
Addressing more comments
Artui Oct 14, 2025
af4dec3
Addressing more comments
Artui Oct 14, 2025
4a4820c
Merge branch 'main' into feature/native-mcp-support
Artui Oct 14, 2025
6a47839
Addressing more comments
Artui Oct 14, 2025
8b42bb8
Addressing more comments
Artui Oct 14, 2025
48aa03c
Addressing more comments
Artui Oct 14, 2025
0da350b
Merge branch 'main' into feature/native-mcp-support
Artui Oct 14, 2025
128493d
Cleanup and addresing comments
Artui Oct 15, 2025
2f0eccb
Document OpenAI-compatible provider prefixes (#3169)
DouweM Oct 15, 2025
c36e482
Fix `RunUsage.tool_calls` being undercounted due to race condition wh…
certainly-param Oct 15, 2025
3b3ed37
Merge branch 'main' into feature/native-mcp-support
Artui Oct 15, 2025
72123f3
Cleanup and addresing comments
Artui Oct 15, 2025
639ff41
Cleanup and addresing comments
Artui Oct 15, 2025
3d894c1
Merge branch 'main' into feature/native-mcp-support
Artui Oct 15, 2025
3261b1b
Merge branch 'main' into feature/native-mcp-support
Artui Oct 15, 2025
475c063
Addressing comments and adding more tests
Artui Oct 16, 2025
044e4e3
Merge branch 'main' into feature/native-mcp-support
Artui Oct 16, 2025
f6c41e4
Addressing comments and adding more tests
Artui Oct 16, 2025
bf8d516
Addressing comments and adding more tests
Artui Oct 16, 2025
7c81427
Addressing comments and adding more tests
Artui Oct 16, 2025
cc5d0d8
Addressing comments and adding more tests
Artui Oct 16, 2025
42a3f2b
Addressing comments and adding more tests
Artui Oct 16, 2025
7992a57
Addressing comments and adding more tests
Artui Oct 16, 2025
d19d690
Merge branch 'main' into feature/native-mcp-support
Artui Oct 17, 2025
e7e39c5
Merge branch 'main' into feature/native-mcp-support
Artui Oct 21, 2025
bfc0de0
Merge branch 'main' into feature/native-mcp-support
DouweM Oct 21, 2025
a19327d
Addressing comments
Artui Oct 22, 2025
ed324bc
Addressing comments
Artui Oct 22, 2025
d57f74d
Updating tests
Artui Oct 22, 2025
b26bab9
Updating tests
Artui Oct 22, 2025
e4ce8c9
Merge branch 'main' into feature/native-mcp-support
Artui Oct 22, 2025
556f279
Use MCP server without auth in tests, put all relevant args in args r…
DouweM Oct 23, 2025
a497566
Merge branch 'main' into pr/Artui/3101
DouweM Oct 23, 2025
e553740
Use consistent builtin tool name
DouweM Oct 23, 2025
7e8256f
Verify that MCP tool output does not need to be sent back on subseque…
DouweM Oct 23, 2025
067ee58
Update docs
DouweM Oct 24, 2025
4586dfc
coverage
DouweM Oct 24, 2025
4daa268
Merge branch 'main' into pr/Artui/3101
DouweM Oct 24, 2025
b70a9f6
fix docs
DouweM Oct 24, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
132 changes: 132 additions & 0 deletions docs/builtin-tools.md
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ Pydantic AI supports the following built-in tools:
- **[`ImageGenerationTool`][pydantic_ai.builtin_tools.ImageGenerationTool]**: Enables agents to generate images
- **[`UrlContextTool`][pydantic_ai.builtin_tools.UrlContextTool]**: Enables agents to pull URL contents into their context
- **[`MemoryTool`][pydantic_ai.builtin_tools.MemoryTool]**: Enables agents to use memory
- **[`MCPServerTool`][pydantic_ai.builtin_tools.MCPServerTool]**: Enables agents to pass MCP server configuration in context

These tools are passed to the agent via the `builtin_tools` parameter and are executed by the model provider's infrastructure.

Expand Down Expand Up @@ -419,6 +420,137 @@ print(result.output)

_(This example is complete, it can be run "as is")_

## MCP Server Tool

The [`MCPServerTool`][pydantic_ai.builtin_tools.MCPServerTool] allows your agent to pass MCP configurations in context,
so that the agent can offload MCP calls and parsing to the provider.

This requires the MCP server to live at a public URL the provider can reach and does not support many of the advanced features of Pydantic AI's agent-side [MCP support](mcp/client.md),
but can result in optimized context use and caching, and faster performance due to the lack of a round-trip back to Pydantic AI.

### Provider Support

| Provider | Supported | Notes |
|----------|-----------|-----------------------|
| OpenAI Responses | ✅ | Full feature support |
| Anthropic | ✅ | Full feature support |
| Google | ❌ | Not supported |
| Groq | ❌ | Not supported |
| OpenAI Chat Completions | ❌ | Not supported |
| Bedrock | ❌ | Not supported |
| Mistral | ❌ | Not supported |
| Cohere | ❌ | Not supported |
| HuggingFace | ❌ | Not supported |

### Usage

```py {title="mcp_server_anthropic.py"}
from pydantic_ai import Agent, MCPServerTool

agent = Agent(
'anthropic:claude-sonnet-4-5',
builtin_tools=[
MCPServerTool(
id='your-mcp-server',
url='https://api.githubcopilot.com/mcp/',
)
]
)

result = agent.run_sync('Give me some examples of my products.')
print(result.output)
#> Here are some examples of my data: Pen, Paper, Pencil.
```

_(This example is complete, it can be run "as is")_

With OpenAI, you must use their responses API to access the MCP server tool.

```py {title="mcp_server_openai.py"}
from pydantic_ai import Agent, MCPServerTool

agent = Agent(
'openai-responses:gpt-5',
builtin_tools=[
MCPServerTool(
id='your-mcp-server',
url='https://api.githubcopilot.com/mcp/',
)
]
)

result = agent.run_sync('Give me some examples of my products.')
print(result.output)
#> Here are some examples of my data: Pen, Paper, Pencil.
```

_(This example is complete, it can be run "as is")_

### Configuration Options

The `MCPServerTool` supports several configuration parameters for custom MCP servers:

```py {title="mcp_server_configured_url.py"}
from pydantic_ai import Agent, MCPServerTool

agent = Agent(
'openai-responses:gpt-5',
builtin_tools=[
MCPServerTool(
id='your-mcp-server', # required field
url='https://api.githubcopilot.com/mcp/', # required field
allowed_tools=['search_repositories', 'list_commits'],
description='Your MCP Server',
headers={'X-CUSTOM-HEADER': 'custom-value'},
)
]
)

result = agent.run_sync('Give me some examples of my products.')
print(result.output)
#> Here are some examples of my data: Pen, Paper, Pencil.
```

For OpenAI Responses, you can use a connector by specifying a special `x-openai-connector:` URL:

_(This example is complete, it can be run "as is")_

```py {title="mcp_server_configured_connector_id.py"}
import os

from pydantic_ai import Agent, MCPServerTool

agent = Agent(
'openai-responses:gpt-5',
builtin_tools=[
MCPServerTool(
id='your-mcp-server',
url='x-openai-connector:connector_googlecalendar',
authorization_token=os.getenv('GITHUB_ACCESS_TOKEN', 'mock-access-token'),
allowed_tools=['search_repositories', 'list_commits'],
description='Your MCP Server',
headers={'X-CUSTOM-HEADER': 'custom-value'},
)
]
)

result = agent.run_sync('Give me some examples of my products.')
print(result.output)
#> Here are some examples of my data: Pen, Paper, Pencil.
```

_(This example is complete, it can be run "as is")_

#### Provider Support

| Parameter | OpenAI | Anthropic |
|-----------------------|--------|-----------|
| `url` | ✅ | ✅ |
| `authorization_token` | ✅ | ✅ |
| `allowed_tools` | ✅ | ✅ |
| `description` | ✅ | ❌ |
| `headers` | ✅ | ❌ |

## API Reference

For complete API documentation, see the [API Reference](api/builtin_tools.md).
3 changes: 2 additions & 1 deletion docs/mcp/overview.md
Original file line number Diff line number Diff line change
@@ -1,9 +1,10 @@
# Model Context Protocol (MCP)

Pydantic AI supports [Model Context Protocol (MCP)](https://modelcontextprotocol.io) in two ways:
Pydantic AI supports [Model Context Protocol (MCP)](https://modelcontextprotocol.io) in three ways:

1. [Agents](../agents.md) act as an MCP Client, connecting to MCP servers to use their tools, [learn more …](client.md)
2. Agents can be used within MCP servers, [learn more …](server.md)
3. Agents can pass MCP Servers as built-in tools into supported models, [learn more …](../builtin-tools.md)

## What is MCP?

Expand Down
2 changes: 2 additions & 0 deletions pydantic_ai_slim/pydantic_ai/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
from .builtin_tools import (
CodeExecutionTool,
ImageGenerationTool,
MCPServerTool,
MemoryTool,
UrlContextTool,
WebSearchTool,
Expand Down Expand Up @@ -213,6 +214,7 @@
'CodeExecutionTool',
'ImageGenerationTool',
'MemoryTool',
'MCPServerTool',
# output
'ToolOutput',
'NativeOutput',
Expand Down
62 changes: 62 additions & 0 deletions pydantic_ai_slim/pydantic_ai/builtin_tools.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@
'UrlContextTool',
'ImageGenerationTool',
'MemoryTool',
'MCPServerTool',
)


Expand Down Expand Up @@ -237,3 +238,64 @@ class MemoryTool(AbstractBuiltinTool):

kind: str = 'memory'
"""The kind of tool."""


@dataclass(kw_only=True)
class MCPServerTool(AbstractBuiltinTool):
"""A builtin tool that allows your agent to use MCP servers.

Supported by:

* OpenAI Responses
* Anthropic
"""

id: str
"""The ID of the MCP server."""

url: str
"""The URL of the MCP server to use.

For OpenAI Responses, it is possible to use `connector_id` by providing it as `x-openai-connector:<connector_id>`.
"""

authorization_token: str | None = None
"""Authorization header to use when making requests to the MCP server.

Supported by:

* OpenAI Responses
* Anthropic
"""

description: str | None = None
"""A description of the MCP server.

Supported by:

* OpenAI Responses
"""

allowed_tools: list[str] | None = None
"""A list of tools that the MCP server can use.

Supported by:

* OpenAI Responses
* Anthropic
"""

headers: dict[str, str] | None = None
"""Optional HTTP headers to send to the MCP server.

Use for authentication or other purposes.

Supported by:

* OpenAI Responses
"""

kind: str = 'mcp_server'

LIST_TOOLS_KIND: Literal['mcp_server:mcp_list_tools'] = 'mcp_server:mcp_list_tools'
CALL_TOOL_KIND: Literal['mcp_server:mcp_call_tool'] = 'mcp_server:mcp_call_tool'
20 changes: 20 additions & 0 deletions pydantic_ai_slim/pydantic_ai/messages.py
Original file line number Diff line number Diff line change
Expand Up @@ -830,6 +830,16 @@ class BuiltinToolReturnPart(BaseToolReturnPart):
"""Part type identifier, this is available on all parts as a discriminator."""


@dataclass(repr=False)
class BuiltinMCPToolReturnPart(BuiltinToolReturnPart):
"""A tool return message from an MCP built-in tool."""

mcp_server_id: str | None = None
"""The ID of the MCP server that generated the response."""
mcp_tool_name: str | None = None
"""The name of the MCP tool that generated the response."""


error_details_ta = pydantic.TypeAdapter(list[pydantic_core.ErrorDetails], config=pydantic.ConfigDict(defer_build=True))


Expand Down Expand Up @@ -1121,6 +1131,16 @@ class BuiltinToolCallPart(BaseToolCallPart):
"""Part type identifier, this is available on all parts as a discriminator."""


@dataclass(repr=False)
class BuiltinMCPToolCallPart(BuiltinToolCallPart):
"""A tool call to an MCP built-in tool."""

mcp_server_id: str | None = None
"""The ID of the MCP server that generated the response."""
mcp_tool_name: str | None = None
"""The name of the MCP tool that generated the response."""


ModelResponsePart = Annotated[
TextPart | ToolCallPart | BuiltinToolCallPart | BuiltinToolReturnPart | ThinkingPart | FilePart,
pydantic.Discriminator('part_kind'),
Expand Down
Loading