
How MCP Resources Work — Data Sources for AI Context
Tools let AI do things. Resources let AI know things. A resource is a piece of data — a file, a database schema, a configuration, an API response — that provides context to the AI model.
The AI reads resources to understand the environment before taking action. A database MCP server might expose the schema as a resource, so the AI understands the table structure before writing SQL queries through tools.
Resources vs Tools
| Resource | Tool | |
|---|---|---|
| Purpose | Provide information | Perform actions |
| Direction | Server → AI (read) | AI → Server (execute) |
| Side effects | None (read-only) | May modify state |
| When used | AI needs context | AI needs to act |
| Example | Database schema | Run SQL query |
| Example | README.md contents | Write to file |
| Example | API documentation | Make API call |
The pattern: read resources for context, then call tools to act on that context.
Identifying Resources
Every resource has a URI (Uniform Resource Identifier):
file:///project/src/main.rs — a local file
https://api.example.com/schema — a web resource
git://repo/HEAD/README.md — a git-tracked file
postgres://db/schema/users — a database table schema
custom://my-app/config — application-specific data
The URI scheme tells you what kind of resource it is. Servers can use any URI scheme — standard (file://, https://) or custom (postgres://, jira://, notion://).
Discovering Resources
Clients discover resources through resources/list:
{
"jsonrpc": "2.0",
"id": 1,
"method": "resources/list"
}
Response:
{
"result": {
"resources": [
{
"uri": "file:///project/README.md",
"name": "README.md",
"description": "Project documentation and setup instructions",
"mimeType": "text/markdown"
},
{
"uri": "postgres://localhost/mydb/schema",
"name": "Database Schema",
"description": "Complete schema of the application database",
"mimeType": "application/json"
}
]
}
}
Each resource has a uri, a human-readable name, an optional description, and an optional mimeType. The AI uses the name and description to decide which resources are relevant.
Reading Resources
To get the contents:
{
"jsonrpc": "2.0",
"id": 2,
"method": "resources/read",
"params": {
"uri": "postgres://localhost/mydb/schema"
}
}
Response:
{
"result": {
"contents": [
{
"uri": "postgres://localhost/mydb/schema",
"mimeType": "application/json",
"text": "{\"tables\": [{\"name\": \"users\", \"columns\": [{\"name\": \"id\", \"type\": \"integer\"}, {\"name\": \"email\", \"type\": \"text\"}]}]}"
}
]
}
}
Resources can contain text (text field) or binary data (blob field, base64-encoded). A file resource returns text. An image resource returns a blob.
Resource Templates
Static resource lists don't scale. A filesystem with thousands of files can't list them all. Resource templates solve this with parameterized URIs:
{
"resourceTemplates": [
{
"uriTemplate": "file:///{path}",
"name": "Project Files",
"description": "Access any file in the project directory",
"mimeType": "application/octet-stream"
}
]
}
The {path} parameter is filled in by the AI or user. file:///src/main.rs, file:///Cargo.toml, file:///docs/design.md — all valid URIs matching this template.
Subscriptions
Resources change. A file gets edited. A database schema is migrated. A config is updated. Subscriptions let clients watch for changes:
{
"method": "resources/subscribe",
"params": { "uri": "file:///project/src/main.rs" }
}
When the resource changes, the server sends a notification:
{
"method": "notifications/resources/updated",
"params": { "uri": "file:///project/src/main.rs" }
}
The client can then re-read the resource to get the updated contents. This is event-driven — no polling. The server only notifies when something actually changes.
Subscriptions require the server to declare subscribe: true in its resources capability during initialization.
Annotations
Resources support annotations that help the AI decide how to use them:
audience— who should see this:["user"],["assistant"], or["user", "assistant"]. Some resources are for the human (UI display). Some are for the AI (context). Some are for both.priority— 0.0 to 1.0. Higher priority resources are more important to include in the AI's context. When context is limited, low-priority resources can be dropped.lastModified— ISO 8601 timestamp. The AI can prioritize recent resources over stale ones.
When to Use Resources vs Tools
Use resources when the server has data that provides useful context. The AI reads it passively. Examples: project structure, documentation, schemas, configuration.
Use tools when the AI needs to take action or query dynamically. Examples: search, create, update, delete, run queries.
Some servers expose both. A database server might expose the schema as a resource (read once for context) and a query tool (execute per question). The AI reads the schema to understand the tables, then uses the query tool to answer specific questions.
Next Steps
- How MCP Transports Work — how all these messages travel between client and server.
- How MCP Tools Work — the action primitive that complements resources.