Skip to content

Commit 24e47bf

Browse files
fennbDouweM
andauthored
Add MCP resources support to MCPServer (#3024)
Co-authored-by: Douwe Maan <[email protected]>
1 parent eae558b commit 24e47bf

File tree

7 files changed

+577
-21
lines changed

7 files changed

+577
-21
lines changed

docs/mcp/client.md

Lines changed: 61 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -365,6 +365,67 @@ async def main():
365365

366366
MCP tools can include metadata that provides additional information about the tool's characteristics, which can be useful when [filtering tools][pydantic_ai.toolsets.FilteredToolset]. The `meta`, `annotations`, and `output_schema` fields can be found on the `metadata` dict on the [`ToolDefinition`][pydantic_ai.tools.ToolDefinition] object that's passed to filter functions.
367367

368+
## Resources
369+
370+
MCP servers can provide [resources](https://modelcontextprotocol.io/docs/concepts/resources) - files, data, or content that can be accessed by the client. Resources in MCP are application-driven, with host applications determining how to incorporate context manually, based on their needs. This means they will _not_ be exposed to the LLM automatically (unless a tool returns a `ResourceLink` or `EmbeddedResource`).
371+
372+
Pydantic AI provides methods to discover and read resources from MCP servers:
373+
374+
- [`list_resources()`][pydantic_ai.mcp.MCPServer.list_resources] - List all available resources on the server
375+
- [`list_resource_templates()`][pydantic_ai.mcp.MCPServer.list_resource_templates] - List resource templates with parameter placeholders
376+
- [`read_resource(uri)`][pydantic_ai.mcp.MCPServer.read_resource] - Read the contents of a specific resource by URI
377+
378+
Resources are automatically converted: text content is returned as `str`, and binary content is returned as [`BinaryContent`][pydantic_ai.messages.BinaryContent].
379+
380+
Before consuming resources, we need to run a server that exposes some:
381+
382+
```python {title="mcp_resource_server.py"}
383+
from mcp.server.fastmcp import FastMCP
384+
385+
mcp = FastMCP('Pydantic AI MCP Server')
386+
log_level = 'unset'
387+
388+
389+
@mcp.resource('resource://user_name.txt', mime_type='text/plain')
390+
async def user_name_resource() -> str:
391+
return 'Alice'
392+
393+
394+
if __name__ == '__main__':
395+
mcp.run()
396+
```
397+
398+
Then we can create the client:
399+
400+
```python {title="mcp_resources.py", requires="mcp_resource_server.py"}
401+
import asyncio
402+
403+
from pydantic_ai.mcp import MCPServerStdio
404+
405+
406+
async def main():
407+
server = MCPServerStdio('python', args=['-m', 'mcp_resource_server'])
408+
409+
async with server:
410+
# List all available resources
411+
resources = await server.list_resources()
412+
for resource in resources:
413+
print(f' - {resource.name}: {resource.uri} ({resource.mime_type})')
414+
#> - user_name_resource: resource://user_name.txt (text/plain)
415+
416+
# Read a text resource
417+
user_name = await server.read_resource('resource://user_name.txt')
418+
print(f'Text content: {user_name}')
419+
#> Text content: Alice
420+
421+
422+
if __name__ == '__main__':
423+
asyncio.run(main())
424+
```
425+
426+
_(This example is complete, it can be run "as is")_
427+
428+
368429
## Custom TLS / SSL configuration
369430

370431
In some environments you need to tweak how HTTPS connections are established –

pydantic_ai_slim/pydantic_ai/_mcp.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
1+
from __future__ import annotations
2+
13
import base64
24
from collections.abc import Sequence
35
from typing import Literal

0 commit comments

Comments
 (0)