MCP Resources
Exposing data and content to AI clients through MCP resources. Covers resource URIs, listing and reading resources, resource templates with URI patterns, MIME types, subscriptions for real-time updates, and patterns for exposing files, database records, and API data as browsable resources.
You are an AI assistant helping developers expose resources through MCP servers. Resources are application-controlled data that clients can read and display — files, database records, API responses, live system data. Unlike tools (which the model invokes), resources are typically selected by the user or client application for inclusion in the conversation context.
## Key Points
- `uri` — unique identifier following URI format. Can use any scheme (`file://`, `db://`, custom schemes).
- `name` — human-readable display name.
- `description` — optional explanation of what the resource contains.
- `mimeType` — optional MIME type to help clients render the content.
- **Using resources for actions** — resources are for reading data, not triggering side effects. If reading a resource sends an email or modifies state, use a tool instead.
- **Listing thousands of resources** — if you have a large dataset, use resource templates instead of listing every item. List a curated subset and let templates handle the rest.
- **Returning enormous content** — resources go into the AI's context window. A 10 MB log file will blow the context. Truncate, summarize, or paginate large content.
- **Custom URI schemes without documentation** — if you invent `myapp://` URIs, document the scheme in the resource description so the model knows what to request.
- **Ignoring MIME types** — setting the correct MIME type helps clients render content appropriately (syntax highlighting, image display, etc.).
- Use standard URI schemes where applicable (`file://`, `https://`). Use custom schemes for domain-specific resources (`db://`, `config://`).
- Set accurate MIME types — `application/json` for JSON, `text/markdown` for Markdown, `text/plain` for generic text.
- Keep resource content concise. Summarize large datasets rather than dumping everything.
## Quick Example
```json
{ "method": "resources/read", "params": { "uri": "db://production/tables/orders/schema" } }
```skilldb get mcp-server-skills/MCP ResourcesFull skill: 238 linesMCP Resources
You are an AI assistant helping developers expose resources through MCP servers. Resources are application-controlled data that clients can read and display — files, database records, API responses, live system data. Unlike tools (which the model invokes), resources are typically selected by the user or client application for inclusion in the conversation context.
Philosophy
Resources represent data the AI can read, not actions it can take. Think of resources as a file browser for AI — the server lists what is available, and the client (or user) selects what to include in the context. Resources should be stable, identifiable by URI, and return content in a format the model can reason about. Use resources for context and tools for actions.
Techniques
Listing Resources
Servers expose resources through the resources/list method:
{
"resources": [
{
"uri": "file:///project/src/main.ts",
"name": "main.ts",
"description": "Application entry point",
"mimeType": "text/typescript"
},
{
"uri": "db://production/users/schema",
"name": "Users Table Schema",
"description": "Column definitions for the users table",
"mimeType": "application/json"
},
{
"uri": "config://app/settings",
"name": "Application Settings",
"description": "Current application configuration",
"mimeType": "application/json"
}
]
}
Each resource has:
uri— unique identifier following URI format. Can use any scheme (file://,db://, custom schemes).name— human-readable display name.description— optional explanation of what the resource contains.mimeType— optional MIME type to help clients render the content.
Reading Resources
Clients read resources via the resources/read method:
// Request
{ "method": "resources/read", "params": { "uri": "db://production/users/schema" } }
// Response
{
"contents": [
{
"uri": "db://production/users/schema",
"mimeType": "application/json",
"text": "{\n \"columns\": [\n {\"name\": \"id\", \"type\": \"integer\", \"primary_key\": true},\n {\"name\": \"email\", \"type\": \"varchar(255)\", \"unique\": true},\n {\"name\": \"created_at\", \"type\": \"timestamp\"}\n ]\n}"
}
]
}
Resources return either text (for text content) or blob (base64-encoded binary):
{
"contents": [
{
"uri": "file:///project/logo.png",
"mimeType": "image/png",
"blob": "iVBORw0KGgoAAAANSUhEUgAA..."
}
]
}
Resource Templates
Resource templates define parameterized URIs using RFC 6570 URI template syntax. They let servers expose dynamic resources without listing every possible instance:
{
"resourceTemplates": [
{
"uriTemplate": "db://production/tables/{table}/schema",
"name": "Table Schema",
"description": "Get the schema for any table in the production database",
"mimeType": "application/json"
},
{
"uriTemplate": "github://repos/{owner}/{repo}/issues/{issue_number}",
"name": "GitHub Issue",
"description": "Fetch a specific GitHub issue by owner, repo, and issue number"
},
{
"uriTemplate": "logs://app/{service}/{date}",
"name": "Service Logs",
"description": "Application logs for a specific service and date (YYYY-MM-DD)"
}
]
}
Clients fill in the template parameters when requesting:
{ "method": "resources/read", "params": { "uri": "db://production/tables/orders/schema" } }
Implementing Resources (TypeScript)
import { McpServer, ResourceTemplate } from "@modelcontextprotocol/sdk/server/mcp.js";
const server = new McpServer({
name: "project-server",
version: "1.0.0",
});
// Static resource
server.resource(
"project-config",
"file:///project/config.json",
"Current project configuration",
async (uri) => ({
contents: [{
uri: uri.href,
mimeType: "application/json",
text: await fs.readFile("/project/config.json", "utf-8"),
}],
})
);
// Dynamic resource using a template
server.resource(
"table-schema",
new ResourceTemplate("db://tables/{tableName}/schema", {
list: async () => {
const tables = await db.query("SELECT table_name FROM information_schema.tables");
return tables.rows.map(row => ({
uri: `db://tables/${row.table_name}/schema`,
name: `${row.table_name} schema`,
}));
},
}),
"Schema for a database table",
async (uri, { tableName }) => {
const schema = await db.query(
"SELECT column_name, data_type FROM information_schema.columns WHERE table_name = $1",
[tableName]
);
return {
contents: [{
uri: uri.href,
mimeType: "application/json",
text: JSON.stringify(schema.rows, null, 2),
}],
};
}
);
Implementing Resources (Python)
from mcp.server.fastmcp import FastMCP
mcp = FastMCP("project-server")
@mcp.resource("file:///project/config.json")
async def get_config() -> str:
"""Current project configuration."""
with open("/project/config.json") as f:
return f.read()
@mcp.resource("db://tables/{table_name}/schema")
async def get_table_schema(table_name: str) -> str:
"""Schema for a database table including column names and types."""
rows = await db.fetch(
"SELECT column_name, data_type FROM information_schema.columns WHERE table_name = $1",
table_name,
)
return json.dumps([dict(row) for row in rows], indent=2)
Subscriptions
Clients can subscribe to resource changes if the server declares subscribe capability:
// Client subscribes
{ "method": "resources/subscribe", "params": { "uri": "file:///project/config.json" } }
// Server notifies when the resource changes
{ "method": "notifications/resources/updated", "params": { "uri": "file:///project/config.json" } }
// Client re-reads the resource to get updated content
{ "method": "resources/read", "params": { "uri": "file:///project/config.json" } }
The server sends a notification when the data changes. It does NOT push the new content — the client must re-read the resource. This keeps the protocol simple and avoids sending large payloads unsolicited.
Choosing Between Resources and Tools
| Use Resources When | Use Tools When |
|---|---|
| Exposing data for context | Performing actions |
| The user/client selects what to include | The model decides when to invoke |
| Content is relatively stable | Operation has side effects |
| Browsing/discovery is important | Specific input parameters needed |
Example: A database server might expose table schemas as resources (for context) and a query tool (for actions).
Anti-Patterns
- Using resources for actions — resources are for reading data, not triggering side effects. If reading a resource sends an email or modifies state, use a tool instead.
- Listing thousands of resources — if you have a large dataset, use resource templates instead of listing every item. List a curated subset and let templates handle the rest.
- Returning enormous content — resources go into the AI's context window. A 10 MB log file will blow the context. Truncate, summarize, or paginate large content.
- Custom URI schemes without documentation — if you invent
myapp://URIs, document the scheme in the resource description so the model knows what to request. - Ignoring MIME types — setting the correct MIME type helps clients render content appropriately (syntax highlighting, image display, etc.).
Best Practices
- Use standard URI schemes where applicable (
file://,https://). Use custom schemes for domain-specific resources (db://,config://). - Set accurate MIME types —
application/jsonfor JSON,text/markdownfor Markdown,text/plainfor generic text. - Keep resource content concise. Summarize large datasets rather than dumping everything.
- Implement the
listcallback on resource templates so clients can discover available instances. - Use subscriptions for resources that change frequently (config files, live metrics) so the AI always has current data.
- Include enough context in resource descriptions for the model to understand when each resource is relevant.
Install this skill directly: skilldb add mcp-server-skills
Related Skills
MCP Auth and Security
Securing MCP servers with authentication, authorization, and defensive practices. Covers OAuth 2.1 integration for remote servers, API key management through environment variables, input validation and sanitization, rate limiting, sandboxing tool execution, path traversal prevention, and the principle of least privilege for tool design.
MCP Deployment
Deploying MCP servers across different environments and transports. Covers local deployment via stdio, remote deployment with SSE and streamable HTTP, Docker containerization, cloud deployment on AWS/GCP/Vercel, npx and uvx distribution for zero-install usage, configuration management, and production hardening.
MCP Fundamentals
Core architecture of the Model Context Protocol (MCP) — the open protocol from Anthropic that connects AI assistants to external tools and data sources. Covers JSON-RPC transport, capabilities negotiation, server lifecycle, the client-server interaction model, and how tools, resources, and prompts fit together.
MCP Patterns
Common architectural patterns for MCP servers — database servers, API wrappers, file system servers, multi-tool orchestration, caching strategies, error recovery, and composition patterns. Practical blueprints for building production-quality MCP servers that handle real-world complexity.
MCP Prompts
Defining prompt templates in MCP servers that AI clients can discover and invoke. Covers prompt definitions with arguments, dynamic prompt generation, multi-turn prompt structures, embedding resources in prompts, prompt discovery, and patterns for building reusable prompt libraries.
MCP Python Server
Building MCP servers in Python using the official mcp SDK and the FastMCP high-level pattern. Covers project setup with uv, defining tools with type hints, async handlers, resources, prompts, stdio and SSE transports, context objects, and deployment strategies including uvx distribution.