MCP Resources: Engineering Contextual Knowledge for Production AI Agents
What Are MCP Resources
MCP Resources are a core primitive of the Model Context Protocol (MCP) that allow servers to expose read‑only, structured data to AI agents—data that provides context to language models, such as files, database schemas, application‑specific information, or real‑time system metrics. Each resource is uniquely identified by a URI and can contain either text or binary data.
Crucially, resources do not execute logic or generate dynamic outputs. Unlike tools (actions the agent can perform) or prompts (templated workflows), resources are simply retrieved by the client and used as static or semi‑static context. An agent reads a resource; it calls a tool.
The distinction has profound engineering implications: because resources are read‑only and side‑effect‑free, they can be aggressively cached, replicated across regions, and served with far lower latency than tools. They are the mechanism by which an agent grounds itself in your organisation’s knowledge without risk of unintended mutations.
Why MCP Resources Matter
In production AI systems, context is not a luxury—it is the difference between correct action and hallucination. MCP resources address three fundamental problems that plague ad‑hoc context injection:
| Problem | Without MCP Resources | With MCP Resources |
|---|---|---|
| Context bloat | Every prompt includes huge documentation blocks, straining token budgets. | Agents discover and retrieve only what they need, on demand. |
| Stale information | Hardcoded context quickly becomes outdated. | Resources can be updated centrally; clients are notified of changes. |
| No discoverability | The agent has to guess what information exists. | resources/list provides a dynamic catalogue. |
| Inconsistent delivery | Different agents embed context in incompatible ways. | Standardised URI scheme and MIME types. |
| Security blind spots | Context flows through prompts; no audit trail of what was accessed. | Every resources/read is logged and authenticated. |
Practical impact: By serving documentation, policies, database schemas, and configuration as MCP resources, you give agents the data they need—on demand, with full user control, and without bloating prompt templates.
MCP Capability Model: Resources vs Tools vs Prompts
Understanding the MCP capability model is essential to designing a clean, maintainable server. These three primitives serve fundamentally different purposes:
| Component | Purpose | Direction | Side Effects | When to Use |
|---|---|---|---|---|
| Tools | Execute actions, run functions, trigger workflows | Agent → External system | Yes (write, delete, send) | Real‑time queries, state changes, API calls |
| Resources | Provide read‑only context, documentation, facts | External system → Agent | No (read‑only) | Static knowledge, configuration, reference data |
| Prompts | Guide conversation with reusable templates | Agent internal | No (orchestration) | Structured workflows, multi‑step tasks |
Think of the relationship this way: Tools = Actions (what the agent does), Resources = Context (what the agent knows), Prompts = Instructions (how the agent should act).
For example, a customer support agent might:
- Read a
resourcecontaining the company refund policy. - Call a
toolto execute the refund. - Use a
promptto structure the manager approval request.
Mixing these responsibilities leads to brittle architectures. Do not expose a database record as a tool unless the agent must modify it. Do not embed static documentation in tool descriptions. Resources are for information, not action.
MCP Resources in the Agent Architecture
Resources sit at the intersection of the MCP server, the client, and the agent’s memory system.
In this architecture, the agent does not call resources directly in the way it calls tools. Instead:
- The agent’s planner identifies that certain knowledge is required to complete the task.
- The MCP client discovers available resources via
resources/listandresources/templates/list. - The client retrieves relevant resources with
resources/read. - Resource content is injected into the agent’s memory or directly into the LLM context.
- The agent reasons using that context.
Crucially, clients (Claude Desktop, LangGraph agents) decide how and when to use resources. The MCP specification does not mandate a specific user interaction model—different clients may expose resources through UI pickers, heuristic automatic inclusion, or allow the AI model to choose.
MCP Resource Lifecycle
Every MCP resource follows a well‑defined lifecycle from creation to eventual deprecation.
Stage Details
| Stage | Purpose | Failure Mode |
|---|---|---|
| Resource creation | Define URI, name, description, MIME type, and handler logic. | Missing schema; handler not idempotent. |
| Registration | Associate resource with server capability. | Duplicate URI; registration after connection. |
| Discovery | Client calls resources/list after initialisation. | Server doesn’t declare resources capability. |
| Retrieval | Client calls resources/read with URI. | Invalid URI; handler timeout; backend unavailable. |
| Caching | Client caches resource list and content. | Stale cache after server changes. |
| Update notification | Server sends notifications/resources/list_changed or notifications/resources/updated. | Notifications not implemented; client misses updates. |
Types of MCP Resources
Resources can be classified along two independent dimensions: static vs dynamic, and text vs binary.
By Mutability
| Type | URI Pattern | Description | Example |
|---|---|---|---|
| Static resources | Fixed URI | Content never changes; ideal for reference materials, schemas, documentation. | file:///config/schema.json |
| Dynamic resources | URI template with parameters | Content generated on request based on URI parameters. | logs://{service}/{date} |
| Subscribable resources | Any URI | Client can subscribe to be notified of changes. | metrics://cpu/usage |
Static resources are the simplest: a fixed URI, a handler that returns the same content every time. Dynamic resources use URI templates (RFC 6570), allowing clients to construct URIs with parameters. For example, a template file:///logs/{date}.log enables clients to request logs for any date.
By Content Type
| Type | MIME Type | Encoding | Use Case |
|---|---|---|---|
| Text resources | text/plain, text/markdown, application/json, etc. | UTF‑8 string | Source code, config files, API schemas, documentation |
| Binary resources | image/png, application/pdf, audio/mpeg, etc. | Base64‑encoded blob | Screenshots, PDFs, images, compiled assets |
The MCP server declares the mimeType for each resource, and clients can choose how to handle different content formats—for example, rendering an image rather than sending raw binary to an LLM.
By Domain (Examples)
| Domain | Resource Examples |
|---|---|
| Documentation | docs://api/reference, docs://getting-started, policy://security |
| Configuration | config://database/schema, config://deployment/environment |
| Knowledge base | kb://articles/{id}, faq://common-issues |
| Logs & metrics | logs://{service}/{date}, metrics://cpu/{interval} |
| Organisational data | org://directory/{username}, calendar://events/{date} |
MCP Resource Design Principles
1. Bounded Contexts
Design each MCP server as a single, bounded context rather than a catch‑all host for disparate resources. MCP servers should expose well‑defined tools, resources, and prompts that serve a coherent domain—not act as one‑to‑one API wrappers. A single server focused on “order management” (resources: order schemas, status definitions; tools: get_order, update_order) is far more maintainable than a monolithic server that mixes orders, customers, inventory, and shipping.
2. Discoverability First
Every resource must be discoverable via resources/list or resources/templates/list. Clients cannot call resources/read on a URI that was never advertised. Use clear, descriptive resource names and include helpful descriptions to guide LLM understanding.
3. Consistency in URI Design
Use a consistent, hierarchical URI scheme:
[scheme]://[namespace]/[category]/[identifier]
Examples: docs://api/authentication, logs://payment-service/2026-06-01, kb://policies/security.
The protocol and path structure are defined by the MCP server implementation—servers can define their own custom URI schemes. However, consistency within a server is critical for client usability.
4. Idempotent and Pure Handlers
Resource handlers MUST be idempotent: the same URI must always return the same content (given the same underlying data). Resource handlers SHOULD be pure—no side effects, no modifications to external state. If a resource access triggers a mutation, it should be a tool, not a resource.
5. Appropriate MIME Types
Always set the mimeType field. Clients use this to decide how to render or process the content. Common types: text/plain, text/markdown, application/json, image/png, application/pdf.
Resource URI Design
Every resource is uniquely identified by a URI in the format: [protocol]://[host]/[path].
Static URIs
For resources that represent a single, fixed piece of content:
file:///home/user/documents/report.pdf
postgres://database/customers/schema
screen://localhost/display1
The server maintains a mapping from URI to content. When the client requests resources/read with that exact URI, the server returns the content.
URI Templates (Dynamic Resources)
For resources that represent parameterised content, servers expose URI templates using RFC 6570 syntax.
Template example:
"uriTemplate": "file:///logs/{date}.log"
The client can then construct a concrete URI: file:///logs/2026-06-01.log.
Template with multiple parameters:
"uriTemplate": "https://api.example.com/users/{user_id}/orders/{order_id}"
Template Metadata
When exposing templates, servers must provide:
uriTemplate: The RFC 6570 template string.name: Human‑readable name for this type of resource.description: Optional description.mimeType: Optional MIME type for all matching resources.
Practical Example: File System Resource
{
"uriTemplate": "file:///{path*}",
"name": "Project Files",
"description": "Access files in the project directory",
"mimeType": "application/octet-stream"
}
The client can then request file:///src/main.rs or file:///config/settings.json.
Resource Discovery
Clients discover resources in two ways: static listing and template listing.
Static Resource Discovery
Servers expose a concrete list of resources via the resources/list endpoint. This operation supports pagination for large resource sets.
Request:
{
"jsonrpc": "2.0",
"id": 1,
"method": "resources/list",
"params": { "cursor": "optional-cursor-value" }
}
Response:
{
"jsonrpc": "2.0",
"id": 1,
"result": {
"resources": [
{
"uri": "file:///project/src/main.rs",
"name": "main.rs",
"title": "Rust Software Application Main File",
"description": "Primary application entry point",
"mimeType": "text/x-rust"
}
],
"nextCursor": "next-page-cursor"
}
}
Each resource entry includes:
uri(required): Unique identifier.name(required): Human‑readable name.description(optional): Longer description for LLM understanding.mimeType(optional): Helps client handle content correctly.title(optional): Display title for UI presentation.
Resource Template Discovery
Servers expose URI templates via resources/templates/list:
{
"jsonrpc": "2.0",
"id": 2,
"method": "resources/templates/list"
}
Response includes an array of resourceTemplates, each with uriTemplate, name, description, and mimeType.
List Change Notifications
When the list of available resources changes, servers that declared the listChanged capability SHOULD send a notifications/resources/list_changed notification. This notifies clients to re‑fetch the resource list, keeping their cache fresh. Without this, clients may operate with stale resource metadata.
Resource Subscriptions
Servers may support resource subscriptions, allowing clients to be notified of changes to individual resources. If the server declares the subscribe capability, clients can:
- Send
resources/subscribewith a resource URI. - Receive
notifications/resources/updatedwhen content changes. - Fetch fresh content via
resources/read. - Unsubscribe with
resources/unsubscribe.
Resource Retrieval Patterns
Once discovered, agents retrieve resource content using the resources/read method.
Direct Retrieval
The simplest pattern: client calls resources/read with a concrete URI:
Request:
{
"jsonrpc": "2.0",
"id": 2,
"method": "resources/read",
"params": { "uri": "file:///project/src/main.rs" }
}
Response (text resource):
{
"jsonrpc": "2.0",
"id": 2,
"result": {
"contents": [
{
"uri": "file:///project/src/main.rs",
"mimeType": "text/x-rust",
"text": "fn main() { println!(\"Hello world!\"); }"
}
]
}
}
Response (binary resource):
{
"jsonrpc": "2.0",
"id": 2,
"result": {
"contents": [
{
"uri": "screen://localhost/display1",
"mimeType": "image/png",
"blob": "iVBORw0KGgoAAAANSUhEUgAAA..."
}
]
}
}
Batch Retrieval
Servers may return multiple resources in one resources/read response. This is useful when a URI represents a directory or collection:
{
"result": {
"contents": [
{ "uri": "dir://src/main.rs", "text": "..." },
{ "uri": "dir://src/lib.rs", "text": "..." }
]
}
}
Proactive Injection (Application‑Driven)
Resources in MCP are designed to be application‑driven, meaning the host application determines how to incorporate context. Different clients may handle this differently: Claude Desktop currently requires users to explicitly select resources before they can be used; other clients might automatically select resources based on heuristics; some implementations may even allow the AI model itself to determine which resources to use.
For automatic data exposure to models, server authors should use tools, not resources—tools are model‑controlled, resources are application‑controlled.
Retrieval as a Discovery Aid
Agents can use resources as a discovery aid. For example, instead of searching or guessing, the agent can list available resources, read a documentation resource, learn correct usage, and then succeed on the first tool call.
MCP Resources and RAG
A common source of confusion: how do MCP resources relate to Retrieval‑Augmented Generation (RAG)? The simplest answer is that they address different problems at different layers of the stack.
| Aspect | RAG | MCP Resources |
|---|---|---|
| Purpose | Retrieves relevant information from a static knowledge base (documents, manuals, policies) to ground LLM responses. | Provides on‑demand, read‑only access to any data source (files, DB records, API responses, real‑time metrics) via a standardised protocol. |
| Data source | Vectorised document corpus (PDFs, Confluence, helpdesk articles). | Any data: databases, logs, configuration, APIs, screenshots, live system status. |
| Retrieval trigger | Automatic embedding‑based search before each LLM call. | Explicit request from client or agent. |
| Freshness | Depends on re‑indexing frequency (minutes to days). | Can be real‑time, with subscription notifications for updates. |
| Standardisation | Implementation‑specific (LangChain, LlamaIndex). | Standardised protocol across all MCP‑compatible clients and servers. |
They are not competitors—they are complementary. RAG solves the “knowledge gap” problem (the model was not trained on your internal documents). MCP solves the “live data and action” problem (connecting the model to external systems in real time).
In practice, an AI agent might:
- Use RAG to retrieve relevant policy documents from a vector store.
- Use MCP Resources to read a live configuration value or fetch a database record.
- Use MCP Tools to perform an action based on that context.
RAG fills the context window with relevant information from static documents before the model reasons; MCP connects the model to live systems.
MCP Resources and Agent Memory
Resources are not memory—but they work closely with memory systems.
| Aspect | MCP Resources | Agent Memory (Short/Long‑Term) |
|---|---|---|
| Lifetime | Persistent on server; client caches may have TTL. | Per‑session (short‑term) or per‑user (long‑term). |
| Mutability | Server‑controlled updates; clients are notified. | Agent‑controlled writes (memory updates). |
| Source of truth | Server is authoritative. | Agent state is authoritative (for its own session). |
| Typical content | Documentation, schemas, configuration, logs. | Conversation history, user preferences, task outcomes. |
Integration patterns:
- Resource as memory seed – The agent can read a resource containing a user’s long‑term preferences from an external store, then populate its in‑memory state.
- Resource as memory persistence – The agent can write updated memory back via a tool (not a resource—resources are read‑only). The server then updates the underlying resource representation if appropriate.
- Resource versioning for memory consistency – Use resource templates with version parameters (e.g.,
user://{id}/preferences?v=2) to manage memory schema evolution.
Versioned memory for AI agents—exposed as an MCP server—can store facts, detect conflicts, and track how decisions change over time.
MCP Resources in Multi‑Agent Systems
In a multi‑agent system, resources provide a shared, consistent source of truth across agents.
Benefits:
- Consistency – All agents read the same resource definitions. No divergence.
- Single source of truth – Update the resource once; all agents see the change (via
list_changednotifications). - Reduced redundancy – Documentation, schemas, and policies are not duplicated across agent configurations.
Challenge: Resource changes must be coordinated. When a resource is updated, all subscribed clients receive notifications/resources/updated. The multi‑agent system must handle the timing of these updates—some agents may be in the middle of a workflow when the resource changes.
MCP Resource Security
Security for MCP resources is not optional. Every resource exposed by an MCP server is a potential data exfiltration point. As of the June 2025 specification update, MCP servers are formally classified as OAuth 2.0 Resource Servers.
OAuth 2.1 with Resource Indicators
The MCP specification now requires OAuth 2.1 with PKCE for remote servers. Resource Indicators (RFC 8707) prevent token misuse by ensuring the access token is bound to a specific resource server. The MCP server publishes a /.well-known/oauth-protected-resource document that tells clients which authorisation server to use, what scopes are available, and how to request tokens.
Practical implications:
- Every MCP server must validate bearer tokens on every request (not just at session establishment).
- Tokens must be short‑lived (minutes, not hours).
- Resource access is scoped—different resources may require different OAuth scopes.
Least Privilege for Resource Access
Not every resource should be accessible to every client. Implement resource‑level authorisation:
| Resource Type | Example | Access Level |
|---|---|---|
| Public documentation | docs://getting-started | Any authenticated client. |
| User‑specific data | user://{id}/profile | Only the authenticated user (same id). |
| Administrative configuration | config://deployment/secrets | Restricted to admin clients. |
| Compliance‑sensitive logs | logs://audit/{date} | Read‑only access for compliance officers. |
Path Traversal Prevention
When exposing file system resources (e.g., file:///{path*}), validate all URIs. Do not allow arbitrary path traversal—whitelist paths or endpoints for file access. A request for file:///etc/passwd should be rejected.
Gateway‑Enforced Security
For enterprise deployments, a security gateway provides a single place to enforce access control, rate limiting, and audit logging across every MCP server. Stacklok’s gateway uses Cedar and Open Policy Agent (OPA), meaning access rules are declarative, version‑controlled, and auditable—not buried in per‑server configuration files.
Audit Logging
Every resources/read request MUST be logged with:
timestampuser_id(from authenticated token)resource_uriclient_idsession_idoutcome(success/error)
This creates an immutable record of what information was provided to which agent—essential for compliance and security investigations.
MCP Resource Scalability
Resources introduce scalability challenges because they can be large, numerous, and frequently accessed.
Caching Strategy
| Cache Level | Contents | TTL | Invalidation |
|---|---|---|---|
| Client‑side (list) | Resource list | Session | list_changed notification |
| Client‑side (content) | Retrieved resource content | Configurable (30s–1hr) | Content TTL or subscription update |
| Server‑side | Expensive resource computations | Minutes | Backend change events |
Implement caching for compiled prompt templates and frequently read resources, with TTL and invalidation hooks.
Content Distribution
For globally distributed agents, resource content should be served from edge locations. Streamable HTTP transport with CDN caching reduces latency for static resources (documentation, schemas, configuration) from hundreds of milliseconds to single‑digit milliseconds.
Pagination
Resource lists can become extremely large. The resources/list endpoint MUST support pagination using the cursor parameter. Servers should cap the page size (e.g., 50 resources per page) to avoid overwhelming the client.
Resource Partitioning
Instead of a single monolithic resource list, partition resources by domain:
docs://for documentation resourcesmetrics://for performance metricsconfig://for configuration
Each partition can be scaled independently. Some partitions (documentation) may be served from a CDN; others (real‑time metrics) may require direct connection.
Connection Management for Large Resources
When returning large resources (multi‑megabyte JSON, high‑resolution images), consider streaming the response rather than loading the entire content into memory. Streamable HTTP is well‑suited for this use case.
MCP Resource Observability
MCP servers have no built‑in observability. Without instrumentation, resource access patterns, latency, and errors remain invisible.
Metrics to Track
| Metric | Type | Tags |
|---|---|---|
mcp.resource.read.calls | Counter | resource_uri, mime_type, success |
mcp.resource.read.duration | Histogram | resource_uri, outcome |
mcp.resource.list.size | Gauge | None |
mcp.resource.template.calls | Counter | template_uri |
mcp.resource.cache.hit_rate | Gauge | None |
Structured Logging
Each resource handler should log:
{
"level": "info",
"timestamp": "2026-06-09T14:32:01Z",
"request_id": "req_123",
"resource_uri": "postgres://database/customers/schema",
"content_size_bytes": 15234,
"duration_ms": 47,
"cache_status": "miss"
}
Distributed Tracing
Add OpenTelemetry spans around:
resources/listprocessingresources/templates/listprocessing- Each
resources/readexecution
Propagate trace IDs from client to server. This allows tracing a resource access from the agent’s decision through the MCP stack to the backend data source.
Real‑Time Analytics with Elastic APM
The Elastic APM Agent Builder MCP enables the same Claude Desktop session that produced the traces to query them back—the agent analyses its own resource access patterns, identifies slow resources, and explains failures without leaving the chat.
Resource Management Best Practices
-
Design each MCP server as a single, bounded context – Focus resources around one domain (e.g., “order management”, “documentation”, “metrics”).
-
Keep resources focused – Each resource should represent one coherent piece of information. Avoid merging multiple unrelated documents into a single resource.
-
Use URI templates for parameterised access – Instead of creating hundreds of static resources for log files, use a template
logs://{date}/{service}. -
Set appropriate MIME types – Always declare
mimeType. Clients rely on this to handle content correctly. -
Implement
listChangednotifications – When the resource list changes (new files added, schemas updated), sendnotifications/resources/list_changed. Clients depend on this to stay fresh. -
Cache resource lists and content – Reduce network round trips by caching discovery results. Invalidate cache on change notifications.
-
Validate URIs before handler execution – Never trust client‑supplied URIs. Validate path traversal, parameter bounds, and authorisation.
-
Implement resource subscriptions for volatile data – If resources change frequently (log files, metrics, live status), support
resources/subscribeand sendnotifications/resources/updated. -
Version your resources – Use URI templates with version parameters (
config://deployment/environment?v=2) to support backward‑compatible evolution. -
Log every resource access – Record
user_id,resource_uri, timestamp, and outcome. This is your audit trail. -
Monitor resource latency – A slow resource (
resources/read> 100ms) will directly impact agent responsiveness. Alert on anomalies. -
Test resource handlers in isolation – Mock the backend data source. Verify that the correct content is returned for each URI and that error cases are handled gracefully.
Common Resource Design Mistakes
| Mistake | Consequence | Fix |
|---|---|---|
| Using tools for read‑only data | Unnecessary token cost, added latency, no caching. | Expose read‑only data as resources, not tools. |
No listChanged notifications | Clients operate with stale resource lists; new resources are invisible. | Implement and send notifications/resources/list_changed when resources change. |
| Poor URI naming | Clients cannot guess correct URIs; discovery becomes useless. | Use clear, hierarchical, consistent URI schemes. |
| Missing MIME types | Clients mishandle content (e.g., sending binary PDF directly to LLM). | Always declare the mimeType field. |
| Overly large resources | Blows agent context window; slow to transfer. | Paginate, summarise, or split into multiple resources. |
| No authentication | Sensitive resources exposed to unauthorised clients. | Implement OAuth 2.1 with per‑resource scopes. |
| Path traversal vulnerabilities | Attacker reads /etc/passwd via file:/// resource. | Whitelist allowed paths; sanitise all URI parameters. |
| Static resources that change | Clients cache stale content; no update notifications. | Use dynamic resources with templates or implement subscriptions. |
| Too many static resources | Discovery list is huge; clients never browse it. | Use URI templates to reduce static list size. |
| Ignoring resource order | Clients may retrieve resources sequentially, adding latency. | Design resource templates to support batch retrieval where possible. |
Case Study: Enterprise Knowledge MCP Server
Scenario: A multinational company deploys an MCP server that exposes its internal knowledge base—technical documentation, company policies, API schemas, and project wikis—to AI agents used by engineering, support, and compliance teams.
Resource Architecture
Resource Catalogue
| URI Template | Type | MIME Type | Description | Cache TTL |
|---|---|---|---|---|
docs://api/{service} | Static | text/markdown | API documentation for each service | 24h |
policies://security/{name} | Static | text/markdown | Security policies by name | 12h |
schema://database/{table} | Static | application/json | Database table schemas | 6h |
logs://{service}/{date} | Dynamic | text/plain | Service logs for a specific date | 5min |
config://deployment/{environment} | Dynamic | application/json | Live configuration by environment | 30s |
Resource Template Examples
Log retrieval template:
{
"uriTemplate": "logs://{service}/{date}",
"name": "Service Logs by Date",
"description": "Retrieve application logs for a specific service and date (format: YYYY-MM-DD)",
"mimeType": "text/plain"
}
Configuration template:
{
"uriTemplate": "config://deployment/{environment}",
"name": "Environment Configuration",
"description": "Live configuration for a deployment environment (dev, staging, prod)",
"mimeType": "application/json"
}
Security Controls
- OAuth 2.1 with PKCE – Every client authenticates via corporate IdP (Okta).
- Resource scopes:
docs:read– Access to documentation resources.policies:read– Access to security policies.logs:read– Access to operational logs (restricted).config:read– Access to deployment configuration (admin only).
- Per‑request validation – Token is validated on every
resources/readrequest; scope claim is checked against the requested resource. - Path validation – For dynamic templates, parameters are validated against an allowlist before querying backend systems.
- Audit log – Every resource access is logged to a central SIEM with
user_id,resource_uri,timestamp, andhttp_status.
Monitoring Strategy
- Latency SLIs – P95 < 100ms for documentation resources; P95 < 500ms for logs.
- Cache hit ratio – Target > 80% for static resources.
- Error rate – Alert if > 1% of
resources/readrequests return 5xx. - Auth failure rate – Alert if > 5% of requests fail token validation.
Result
After deployment, engineering agents resolved documentation lookup time from 45 seconds (manual search) to 2 seconds (automated resource retrieval). Support agents achieved 92% first‑contact resolution by referencing up‑to‑date policy resources. Compliance audits that previously took days were reduced to hours, thanks to the complete audit trail of resource accesses.
FAQ
1. What is the difference between a Tool and a Resource in MCP?
Tools are actions the agent can execute—they have side effects, modify state, call APIs, and require user approval. Resources are read‑only data sources—they provide context without modifying state. Tools are model‑controlled (the LLM decides when to call them); resources are application‑controlled (the client decides how to present them).
2. When should information be a Resource instead of a Tool?
Use a resource when: the data is read‑only, the agent needs to browse or discover it, side effects are not allowed, caching is desirable, and the same data will be read multiple times. Use a tool when: an action must be performed, the operation has side effects, real‑time processing is required, or the output depends on parameters that change per call.
3. How should resources be organised in a server?
By bounded context—one server per domain (e.g., “order management”, “documentation”, “metrics”). Within a server, use hierarchical URI schemes: domain://category/identifier. Use URI templates for parameterised access rather than hundreds of static URIs.
4. Can resources replace RAG?
No. RAG automatically retrieves relevant information from a vectorised corpus using embeddings. Resources require explicit requests from the client or agent. They serve different purposes: RAG for semantic document retrieval, resources for precise, on‑demand data access. Most production systems use both.
5. How should resources be secured?
Implement OAuth 2.1 with PKCE for remote servers. Use Resource Indicators (RFC 8707) to bind tokens to specific servers. Validate tokens on every resources/read request. Enforce resource‑level authorisation (different scopes for different resources). Never expose sensitive data without authentication.
6. How do resources scale to thousands of entries?
Use pagination on resources/list (cursors). Implement URI templates to avoid enumerating every possible resource. Cache resource lists and content aggressively. Partition resources by category into separate namespaces. Use a gateway for federated discovery across multiple servers.
7. What is resources/templates/list used for?
It exposes URI templates (RFC 6570) that clients can use to construct concrete URIs for dynamic resources. For example, a template logs://{date}/{service} allows the client to request any log file without the server pre‑listing every possible date and service.
8. How do resources interact with agent memory?
Resources provide external data that can be loaded into short‑term memory. The agent’s planner may trigger resource reads to gather context. Resource content can be stored in the agent’s memory cache with TTL. Long‑term user preferences exposed as resources can be retrieved across sessions.
9. What are resource subscriptions?
Subscriptions allow clients to be notified when a specific resource changes. The client sends resources/subscribe; the server sends notifications/resources/updated when the content changes; the client then fetches fresh content with resources/read. Useful for live metrics, logs, and rapidly changing data.
10. Can a resource be binary (image, PDF)?
Yes. Binary resources are encoded in base64 and returned in the blob field. The client should inspect the mimeType to determine how to handle the content (e.g., display an image rather than sending raw binary to the LLM).
11. How do I version resources?
Include a version parameter in the URI template: scheme://domain/resource?v={version} or embed the version in the path: docs://api/v2/authentication. Keep multiple versions active during migration. Deprecate old versions with a warning.
12. What is the difference between resources/list and resources/templates/list?
resources/list returns concrete URIs for static resources. resources/templates/list returns URI templates for dynamic resources where the set of valid URIs is too large to enumerate.
13. How do I test MCP resources?
Unit test resource handlers with mocked backend dependencies. Integration test the full MCP JSON‑RPC flow using a test client. Use resources/list to verify discovery. Use resources/read to verify content. Mock listChanged and updated notifications to test subscription behaviour.
14. What is the typical latency for resources/read?
The MCP protocol itself adds minimal overhead (< 1ms). Most latency comes from: network round trip (5–100ms), handler execution (database query, file read), and content serialisation. Static resources can be cached to achieve < 5ms P95 latency.
15. Can a resource access another resource?
Not directly. A resource handler may internally call other services or databases, but it should not call another MCP resource’s endpoint. That would create a dependency graph invisible to the client. Design resource handlers as self‑contained units.
16. How do I handle large resource responses?
Implement pagination using the contents array to return resources in chunks. Use streaming for very large binary resources. Set reasonable size limits per resource (e.g., 1MB for text, 10MB for binary) and reject requests beyond them.
17. What is the difference between MCP Resources and Roots?
Resources are individual data items identified by URIs. Roots are a list of URIs that the client provides to the server as a hint about where the server should operate. Roots tell the server the location of project files; resources are the actual files. Roots are optional; resources are a core primitive.
18. Do MCP servers need to implement resources?
No. Resources are optional. A server may expose only tools and prompts. However, servers that provide read‑only context should implement resources rather than overloading tools.
19. How do I handle resource update notifications in a client?
After receiving notifications/resources/updated, the client should invalidate the cached content for that URI and optionally re‑fetch it immediately. The next time the agent requests that resource, the client can decide whether to use the stale cached version or fetch fresh content.
20. What is the difference between static and dynamic resources?
Static resources have a fixed URI and return the same content each time (modulo backend changes). Dynamic resources use URI templates with parameters—the content varies based on the parameters provided.
Continue Your Journey
Now that you understand how MCP Resources provide contextual knowledge to AI agents, explore the rest of the MCP ecosystem:
- MCP Basics – MCP Introduction (protocol fundamentals)
- MCP Servers – MCP Server (building and deploying servers)
- MCP Clients – MCP Client (connecting agents to servers)
- MCP Tools – MCP Tools (actions for agents)
- MCP Prompts – MCP Prompts (reusable templates)
- MCP Security – MCP Security (authentication, authorisation)
- Agent Memory – Agent Memory (short‑term and long‑term memory)
- RAG – RAG Systems (retrieval‑augmented generation)
Or return to the Agent Learning Path to see where MCP Resources fit in your overall agent engineering roadmap.
This article is part of the AgentDevPro Production Agent Engineering Handbook. Updated for Q2 2026.