Every AI agent needs context. Before an agent can answer a question, write code, or make a decision, it needs access to the right data. MCP resources are how agents get that access without improvising.
If you have worked with MCP servers before, you have probably used tools — functions an agent can call to take an action or fetch a result. Resources solve a different problem. They represent data that already exists and that the agent can read directly, without executing a function call.
The core idea
An MCP resource is a piece of data exposed by an MCP server that a client can read. Each resource has a URI (like file:///src/app.ts or postgres://db/users/schema) and returns content in a known format, typically text or binary encoded as base64.
Think of resources as the “read” side of an MCP server. Tools are the “do” side. A weather MCP server might expose a get_forecast tool that takes a city and returns a prediction. That same server might also expose a weather://stations resource that lists every monitoring station it knows about. The tool runs logic. The resource just returns data.
This separation matters because agents and the humans supervising them treat reads and writes differently. Reading a file is low-risk. Executing a database query that modifies rows is not. Resources make it possible for MCP clients to pull context into a conversation without triggering any side effects.
How resources work
An MCP server declares its resources through two mechanisms: direct resources and resource templates.
Direct resources. A server can list specific resources it makes available, each with a URI, a human-readable name, an optional description, and a MIME type. A file system server might list every file in a project directory. A database server might list every table schema. The client calls resources/list and gets back the full catalog.
Resource templates. For data that would be impractical to enumerate upfront, servers expose URI templates following RFC 6570. Instead of listing every user record individually, a database server might expose postgres://db/users/{user_id} as a template. The client fills in the parameter and calls resources/read with the completed URI.
When a client reads a resource, the server returns one or more content blocks. Text content comes back as a string with a MIME type. Binary content (images, PDFs, compiled files) comes back as base64-encoded data. A single resource URI can return multiple content blocks if the data is naturally composed of several parts.
Subscriptions. Resources can change over time. A log file grows. A database table gets new rows. MCP supports a subscription model where the client subscribes to a resource URI, and the server sends notifications/resources/updated whenever the underlying data changes. The client can then re-read the resource to get the latest version.
Resources vs tools: when to use each
Both resources and tools can return data, which raises an obvious question: when should a server expose something as a resource instead of a tool?
Use a resource when:
- The data already exists and does not need computation to produce
- Reading it has no side effects
- The client might want to browse what is available before deciding what to read
Use a tool when:
- Producing the result requires running logic, calling an API, or transforming inputs
- The operation has side effects (writing to a database, sending a message)
- The inputs are dynamic and do not map cleanly to a URI structure
- The agent needs to decide at runtime whether and how to call it
Either one can support subscriptions or change over time. The real dividing line is side effects.
In practice, many MCP servers in the directory use both. A GitHub MCP server might expose repository file trees as resources (browsable, read-only) while offering tools for creating issues, opening pull requests, and pushing commits.
Resources in practice
Here is what a simple resource declaration looks like from a server’s perspective. A file system server exposes project files:
{
"resources": [
{
"uri": "file:///project/src/index.ts",
"name": "index.ts",
"description": "Main entry point",
"mimeType": "text/typescript"
},
{
"uri": "file:///project/package.json",
"name": "package.json",
"mimeType": "application/json"
}
]
}
A client reads a resource by calling resources/read with the URI:
{
"method": "resources/read",
"params": {
"uri": "file:///project/src/index.ts"
}
}
The server responds with the file contents:
{
"contents": [
{
"uri": "file:///project/src/index.ts",
"mimeType": "text/typescript",
"text": "import express from 'express';\n..."
}
]
}
No function execution. No side effects. Ask for data, get data back.
Why resources matter
As the number of MCP servers grows, resources start pulling more weight.
The obvious win is context before action. An agent connected to a database MCP server can browse table schemas as resources, understand the data model, and then use tools to run queries. Without resources, the agent has to guess at the schema or make exploratory tool calls — which is roughly how a junior developer behaves on day one.
Resources also create a useful permission boundary. An MCP client can let agents freely read resources while gating tool calls behind human approval. Full read access, controlled writes. If you have worked with HTTP APIs, the instinct is the same: GET is safe, POST and DELETE need more thought.
For developers building or choosing MCP servers, this is the practical takeaway: a server that exposes its data as resources gives agents more to work with and gives you more control over what they do.
FAQ
Q: Do all MCP servers support resources? A: No. Resources are an optional part of the MCP specification. Many servers only expose tools. Whether a server offers resources depends on what kind of data it works with and whether that data benefits from being browsable.
Q: Can resources return dynamic data? A: Yes. A resource does not have to be a static file. A database server can expose a resource that returns the current row count of a table, and that number changes every time the client reads it. The distinction is that reading the resource does not cause a side effect — not that the data is frozen.
Q: How are resources different from MCP prompts?
A: Prompts are pre-written templates that structure how an agent approaches a task. Resources are raw data. A code review MCP server might expose a review-checklist prompt alongside the source files under review as resources. Different jobs: prompts shape the conversation, resources supply the material.