What are MCP resources?

Quick answer

MCP resources are one of the three primitives the Model Context Protocol defines for what a server can expose to a connected client, specifically representing readable data, a file’s contents, a database record, an API response, that a host application can pull into a model’s context. They’re distinct from MCP tools, which represent actions a model can actively invoke, and from MCP prompts, which represent reusable instruction templates, and understanding that distinction is the key to using resources correctly: a resource is something to be read and referenced, not something to be called or executed.

Summary slides
MCP resources
Why MCP needed a separate concept just for readable data
How a resource actually gets discovered and read
How resources connect to the rest of a host application's context…
Common mistakes teams make around MCP resources

Why MCP needed a separate concept just for readable data

Before this distinction existed clearly, it was easy to conflate every kind of server capability into a single, undifferentiated bucket, a server offers some things and a model uses them, without much structure around what kind of thing is being offered. This conflation causes real, practical problems once a system grows to include many different capabilities, since a host application needs to treat data very differently from an action, a piece of data can be safely shown to a user for review or included in a model’s context without side effects, while an action, once invoked, actually does something in the world and needs a different level of caution around when and how it gets triggered.

MCP resolves this by defining resources specifically as passive, readable content with a stable identifier, typically expressed as a URI, that a client can list, read, and optionally subscribe to for updates, entirely separate from the tools a server also exposes for taking action. This separation gives a host application a clean, structural way to reason about what it’s working with at any given moment, is this a piece of context the model should simply read, or is this an action with consequences that deserves a different kind of scrutiny before it happens.

What a resource actually looks like in practice

A resource in MCP is identified by a URI, the same kind of structured identifier used across the web more broadly, and a server exposing resources can represent almost any kind of readable content this way, a specific file on disk, a specific row in a database, the current output of a log file, a document stored in some external system. Each resource carries metadata alongside its actual content, a name, a description of what it represents, and a MIME type describing what format the content is in, giving a client and the model consuming that content enough structure to understand what they’re looking at without needing to guess.

Some resources are static and simple, a single, fixed file whose content doesn’t change during a session. Others are dynamic, generated on demand when a client requests them, reflecting whatever the underlying data currently is at the moment of the request rather than a fixed, unchanging snapshot. MCP also supports resource templates, where a server exposes a parameterized pattern rather than one fixed resource, letting a client construct a specific resource’s identifier by filling in a variable, requesting a specific customer’s record by ID rather than the server needing to enumerate every possible customer as a separate, individually listed resource upfront.

How a resource actually gets discovered and read

A client connected to an MCP server can list what resources are currently available, receiving back the structured metadata this article already described for each one, without needing to fetch a resource’s actual content just to know it exists. This listing step matters because it lets a host application decide which resources are relevant to a given task before pulling any of their content into a model’s context, since pulling every available resource into context regardless of relevance would waste considerable space and make it harder for the model to focus on what matters for the task at hand.

Once a specific resource has been identified as relevant, the client requests its actual content through a straightforward read operation, and the server returns the resource’s current data along with its declared format. For resources that can change over time, a server can support subscriptions, letting a client register interest in a specific resource and receive a notification when its content changes, rather than needing to repeatedly poll and re-read the same resource just to check whether anything new has appeared.

Why keeping resources separate from tools actually matters for safety

The practical value of this separation becomes clearest once you consider what goes wrong without it. A host application that treats every server capability identically, offering a model an undifferentiated list of things it can invoke, loses the ability to apply different levels of caution to reading a piece of data versus taking a consequential action, connecting directly to the broader discussion of tool-calling security and agent permissions covered elsewhere in this collection. Reading a file’s contents to inform a response is a fundamentally lower-risk operation than sending an email or modifying a database record, and a system that can’t structurally tell these two categories apart has no clean way to apply proportionate scrutiny to each.

MCP’s resource concept gives a host application exactly this structural distinction for free, a well-built host can safely surface every available resource to a model with comparatively little friction, since reading data has no side effects, while still applying the tighter, more deliberate gating this collection describes elsewhere specifically to the tools a server exposes for taking actual, consequential action. This isn’t just a naming convention, it’s what lets a system reason clearly about risk at the protocol level rather than needing every host application to independently invent its own convention for distinguishing data from action.

Why resources still deserve real scrutiny despite being passive

It’s worth being direct that passive doesn’t mean automatically safe. A resource’s content is still external, potentially untrusted input flowing into a model’s context, and this connects directly to the broader discussion of prompt injection covered elsewhere in this collection: a file or a database record that a malicious actor has tampered with can contain text specifically crafted to manipulate the model reading it, even though retrieving that resource itself had no direct side effect. The absence of an action being invoked doesn’t mean the absence of risk, it just means the risk shows up differently, through what the content itself might try to do to the model’s reasoning rather than through an action the server directly performed.

A team building or connecting to MCP resources benefits from treating resource content the same way any other externally sourced context deserves to be treated, applying the same caution about what a retrieved document might contain that the broader discussion of RAG security covers in more depth. The structural separation between resources and tools solves the problem of distinguishing reading from acting, it doesn’t by itself solve the separate problem of a resource’s content being trustworthy, and conflating those two concerns is an easy mistake to make precisely because MCP’s clean structure can create a false sense that the safety question has already been fully handled.

How resources connect to the rest of a host application’s context management

Because resources are meant to be pulled into a model’s context, they sit directly at the intersection of MCP and the broader discipline of context engineering covered elsewhere in this collection. A host application deciding which available resources to actually surface for a given task, and how much of each resource’s content to include, is making exactly the same kind of context-assembly decision that matters regardless of whether the underlying data came through MCP or through some other integration entirely. MCP standardizes how that data gets discovered and retrieved, but the judgment about what belongs in context and what doesn’t still rests with the host application and the harness surrounding it.

This means a host application with poor context-management discipline doesn’t automatically get better just because its data now flows through MCP resources rather than some custom, bespoke integration. The protocol solves the integration and discovery problem cleanly, letting any conforming client connect to any conforming server without custom code, but it doesn’t solve the separate, ongoing problem of deciding what’s actually relevant enough to include for a specific task, and a team still needs the same deliberate curation discipline this collection describes elsewhere regardless of how tidy the underlying data-access layer has become.

What building a server that exposes resources well actually involves

For a team building an MCP server, deciding what to expose as a resource versus what to expose as a tool is the first real design decision, and it comes down to the same passive-versus-active distinction this article has described throughout, if something represents readable content a model might want to reference, it’s a resource, if something represents an action with an effect, it belongs as a tool instead, even when the underlying data involved overlaps considerably between the two. A well-designed server also writes clear, accurate metadata for each resource, its name and description doing real, honest work to help a client and the model using it understand what they’re looking at, rather than vague or misleading descriptions that leave the model to guess.

Supporting resource templates and subscriptions where they genuinely apply is what separates a server that scales well from one that becomes unwieldy as the amount of underlying data grows, since a server exposing thousands of individual, hardcoded resources for what’s really one parameterized pattern, every customer record as its own separately listed resource, for instance, creates exactly the kind of unwieldy sprawl a template was specifically designed to avoid.

Common mistakes teams make around MCP resources

1. Treating a resource’s passive, read-only nature as evidence its content is automatically safe, rather than applying the same scrutiny given to any external, potentially untrusted input.

2. Conflating resources and tools in a host application’s own logic, losing the structural ability to apply proportionate caution to reading data versus taking a consequential action.

3. Surfacing every available resource to a model regardless of relevance to the current task, rather than curating what gets pulled into context for a given piece of work.

4. Exposing what’s really a parameterized pattern as a large, hardcoded set of individually listed resources instead of using a resource template designed for exactly that case.

5. Writing vague or inaccurate resource metadata, leaving a client and the model consuming it to guess at what a resource actually represents.

What connects these mistakes is treating MCP’s clean structural separation between passive data and active tools as though it were also a guarantee of safety and relevance, when the protocol only solves the discovery and integration problem, the ongoing judgment about what content to trust and what to actually include in a model’s context still rests entirely with the host application built around it.

The deeper point about MCP resources is that giving data a clean, standardized shape is only the first half of using it well, the harder and more durable half is the same discipline that’s always mattered for context quality and content trust, applied consistently regardless of how tidy the underlying access layer has become, and a team that treats the protocol’s structure as a substitute for that discipline ends up with data that’s easy to fetch but no more trustworthy or well-curated than it ever was before MCP gave it a standardized name.