Resources & Prompts
Application-controlled context and user-controlled templates — the two server primitives that aren't tools, and how all three compose
Resources & Prompts
TL;DR
Resources are application-controlled, read-only data — file contents, database schemas, API responses — exposed as direct URIs or parameterized templates. Prompts are user-controlled, reusable templates requiring explicit invocation, like a slash command. Together with tools, they're MCP's three server primitives, and each is controlled by a different party — the single most important distinction to internalize about all three.
| Property | Value |
|---|---|
| Level | Intermediate |
| Reading time | ~19 minutes |
| Prerequisites | Tools |
| You will understand | How resources and prompts work, and who controls each of MCP's three primitives |
Who Controls What
The distinction that matters most
Tools — model-controlled
The model decides when to call one, based on the conversation. Covered in full on the Tools page.
Resources — application-controlled
The host application decides how to retrieve, filter, and present them — the model doesn't directly request a resource the way it requests a tool call.
Prompts — user-controlled
A person explicitly invokes one, typically by name — nothing about a prompt template triggers automatically.
Getting this straight up front makes the rest of this page (and a lot of MCP server design) much easier to reason about: if you're building a server and asking "should this be a tool, a resource, or a prompt," the answer usually falls out of asking who should be deciding when it's used.
Resources: Application-Controlled Context
Resources expose data the AI application can retrieve and hand to the model as context — a file's contents, a calendar's events, a knowledge base article. Each resource has a unique URI and a declared MIME type.
Direct resources vs resource templates
// Direct resource — a fixed URI
{ "uri": "calendar://events/2026", "name": "calendar-2026" }
// Resource template — a parameterized URI
{
"uriTemplate": "weather://forecast/{city}/{date}",
"name": "weather-forecast",
"title": "Weather Forecast",
"description": "Get weather forecast for any city and date",
"mimeType": "application/json"
}A direct resource points at one specific, known thing — calendar://events/2026 always means the same thing. A resource template is parameterized — travel://activities/{city}/{category} can resolve to travel://activities/barcelona/museums, travel://activities/tokyo/food, or any other combination, discovered as one template rather than an unbounded list of direct resources.
Templates support parameter completion: as a user types "Par" into a {city} parameter, the system can suggest "Paris" or "Park City" — the same discoverability UX a form autocomplete gives you, driven by the server rather than hardcoded into the client.
The four protocol operations
| Method | Purpose |
|---|---|
resources/list | List available direct resources |
resources/templates/list | Discover resource templates |
resources/read | Retrieve a resource's actual contents |
subscriptions/listen | Open a stream to monitor specific resources for changes |
To watch particular resources, a client sends subscriptions/listen with a resourceSubscriptions filter naming the URIs it cares about. When a watched resource changes, the server delivers notifications/resources/updated on that stream — the same opt-in, filtered notification pattern used for tool-list changes.
How applications actually use resources
Resources are application-driven, which means the host has real latitude in how it surfaces them:
- Tree or list views for browsing, like a familiar file browser
- Search and filter interfaces for finding a specific one
- Automatic inclusion or smart suggestions based on conversation context
- Manual or bulk selection for including one or several at once
The protocol deliberately doesn't mandate any of these UI patterns. A resource picker with live previews, a smart "here's what's probably relevant" suggestion, and a plain file-tree browser are all equally valid implementations of the same resources/list and resources/read operations underneath.
Prompts: User-Controlled Templates
Prompts are structured, reusable templates — a server author's way of saying "here's a good way to use my tools and resources together for this common task."
{
"name": "plan-vacation",
"title": "Plan a vacation",
"description": "Guide through vacation planning process",
"arguments": [
{ "name": "destination", "type": "string", "required": true },
{ "name": "duration", "type": "number", "description": "days" },
{ "name": "budget", "type": "number", "required": false },
{ "name": "interests", "type": "array", "items": { "type": "string" } }
]
}Protocol operations: prompts/list to discover, prompts/get to retrieve a full definition with its arguments. Prompts require explicit invocation — nothing about them fires automatically the way a tool call can. Hosts typically surface them as:
- Slash commands (
/plan-vacation) - Command palettes for searchable access
- Dedicated UI buttons for frequently used prompts
- Context menus suggesting a relevant one
Like resource templates, prompt arguments support parameter completion — typing a partial destination name can surface valid suggestions before the user finishes typing.
How the Three Compose
None of the three primitives is meant to work alone. A single well-designed workflow typically threads through all three, each doing the part it's suited for:
User invokes /plan-vacation (a PROMPT, explicitly chosen)
│
▼
User selects relevant context: calendar://my-calendar/June-2026,
travel://preferences/europe (RESOURCES, application-surfaced, user-picked)
│
▼
Model reads that context, then decides to call
searchFlights(), checkWeather(), bookHotel() (TOOLS, model-controlled)
│
▼
A booked trip, grounded in real calendar availability and live flight dataThe prompt gave structure to the request. The resources gave the model facts it couldn't have known otherwise (this user's actual calendar, actual preferences). The tools let it act on that information. Each primitive did the job that matches who's supposed to be in control of it — and this is exactly why the three-way distinction from the top of this page is worth holding onto: get it backwards (say, exposing a resource as a tool) and you've handed control to the wrong party.
Concept Checks
Check yourself
A server author wants users to explicitly trigger a guided, multi-step workflow by name. Should this be a tool or a prompt?
A prompt. Tools are model-controlled — the model decides when to call one based on conversation context, with no guarantee of explicit user action. A prompt requires explicit invocation by design, which matches "users trigger this by name" exactly. Building it as a tool would hand control of when it fires to the model instead of the user.
What's the difference between a direct resource and a resource template, and when would you use each?
A direct resource is a fixed URI pointing at one specific, known thing (calendar://events/2026), useful when there's a bounded, known set of resources to expose. A resource template is a parameterized URI (weather://forecast/{city}/{date}) that can resolve to effectively unlimited combinations, useful when the space of possible resources is too large or dynamic to enumerate as direct resources — you expose the pattern instead of every instance.
Why does `subscriptions/listen` require a filter naming specific resource URIs, rather than just subscribing to 'all resource changes'?
Because notifications are opt-in and scoped deliberately — a resourceSubscriptions filter lets a client ask only for the specific resources it actually cares about, rather than being flooded with change notifications for every resource on a server it happens to be connected to. This mirrors the same opt-in, filtered pattern used for tool-list-change notifications.
Key Concepts Recap
| Concept | One-line summary |
|---|---|
| Who controls what | Tools: the model. Resources: the application. Prompts: the user. |
| Direct resource | A fixed URI pointing at one known thing |
| Resource template | A parameterized URI covering a dynamic space of possible resources |
| Parameter completion | Both resource templates and prompt arguments support autocomplete-style suggestions |
resources/list / resources/templates/list / resources/read | Discover direct resources, discover templates, retrieve contents |
subscriptions/listen (resources) | Opt-in, filtered watching via resourceSubscriptions, delivering notifications/resources/updated |
prompts/list / prompts/get | Discover and retrieve prompt definitions |
| Explicit invocation | Prompts never fire automatically — a defining property, unlike tools |
| Composition | Prompts structure a task, resources supply facts, tools take action — each primitive doing the job matched to who controls it |
Next
Some client-side primitives that used to sit alongside elicitation no longer belong in new work — read this before you build anything that touches them: Deprecated Primitives.