Building MCP Servers
Exposing Resources
5 min read
While tools let the AI perform actions, resources let the AI read data. Resources are perfect for exposing files, database records, or any read-only data.
Resource vs Tool
| Aspect | Tool | Resource |
|---|---|---|
| Purpose | Perform actions | Read data |
| Side effects | May modify state | Read-only |
| Examples | Send email, create file | Read config, get user profile |
Defining Resources
Resources use URIs to identify content:
from mcp.types import Resource
@server.list_resources()
async def list_resources():
return [
Resource(
uri="config://app/settings",
name="Application Settings",
description="Current application configuration",
mimeType="application/json"
),
Resource(
uri="file:///var/log/app.log",
name="Application Logs",
description="Recent application log entries",
mimeType="text/plain"
)
]
URI Schemes
You can use any URI scheme that makes sense for your data:
| Scheme | Use Case | Example |
|---|---|---|
file:// |
Local files | file:///home/user/doc.txt |
db:// |
Database records | db://users/123 |
config:// |
Configuration | config://app/settings |
api:// |
External APIs | api://weather/london |
Reading Resources
Implement the read handler to return content:
from mcp.types import TextContent, BlobContent
@server.read_resource()
async def read_resource(uri: str):
if uri == "config://app/settings":
settings = load_app_settings()
return [TextContent(
type="text",
text=json.dumps(settings, indent=2)
)]
if uri.startswith("file://"):
path = uri.replace("file://", "")
content = read_file(path)
return [TextContent(type="text", text=content)]
raise ValueError(f"Unknown resource: {uri}")
Binary Resources
For binary data like images, use BlobContent:
import base64
@server.read_resource()
async def read_resource(uri: str):
if uri.startswith("image://"):
image_data = load_image(uri)
return [BlobContent(
type="blob",
data=base64.b64encode(image_data).decode(),
mimeType="image/png"
)]
Dynamic Resources
Resources can be generated dynamically based on parameters:
@server.list_resources()
async def list_resources():
# Generate resources from database
users = await db.get_all_users()
return [
Resource(
uri=f"user://{user.id}",
name=f"User: {user.name}",
description=f"Profile for {user.name}"
)
for user in users
]
Next, let's explore error handling and best practices. :::