# MCP Primitives: Resources, Prompts, Sampling, and Elicitation

> Deep reference on the six MCP capability primitives beyond tools — who controls each, the exact JSON-RPC method names, and when to use Resources vs Tools — verified against the 2025-06-18 and 2025-11-25 spec revisions.

Category: Reference · Updated: 2026-06-16 · Tags: mcp, protocols, resources, prompts, sampling, elicitation, roots, agents
Canonical: https://changegamer.ai/resources/mcp-primitives

MCP defines six capability primitives in two groups: server-side (Tools, Resources, Prompts) and client-side (Sampling, Roots, Elicitation). Each primitive has a designated controlling party — model, application, or user — which determines how it is invoked and why the separation matters for safety. This page goes deep on the five primitives beyond Tools, which are covered separately in /resources/mcp-vs-a2a and /resources/mcp-server-discovery.

## Control model overview

| Primitive | Side | Controlled by | Who decides to invoke it |
|---|---|---|---|
| Tools | Server | Model | The LLM autonomously decides to call a tool |
| Resources | Server | Application | The host app decides what context to expose and inject |
| Prompts | Server | User | The user explicitly selects a prompt template |
| Sampling | Client | Server (asks client) | The server requests an LLM call from the host |
| Roots | Client | Application | The client app declares filesystem/URI boundaries |
| Elicitation | Client | Server (asks user via client) | The server requests structured user input mid-session |

The three-way split (model / app / user) is not cosmetic. It maps directly to who bears responsibility for an action and what approval is required before it executes. See /resources/agentic-security-checklist and /resources/mcp-server-authentication for the security implications.

## Server-side primitives

### Resources (application-controlled)

Resources are read-only data that the host application exposes to the model as context. Unlike tools, the model never decides to fetch a resource on its own — the application controls what is offered and when it is injected into context.

A resource has a URI (e.g. `file:///workspace/README.md`, `db://customers/42`) and returns either text or binary blob content.

**JSON-RPC methods (verified against 2025-11-25 schema):**

- `resources/list` — enumerate all available resources
- `resources/read` — fetch the content of a specific resource by URI
- `resources/templates/list` — list URI templates (parameterized patterns like `file:///{path}` that clients expand to concrete URIs)
- `resources/subscribe` — subscribe to change notifications for a specific resource URI
- `resources/unsubscribe` — cancel a subscription

Clients receive a `notifications/resources/updated` notification when subscribed resource content changes, and a `notifications/resources/list_changed` notification when the available resource list itself changes.

**Concrete example:** A coding assistant server exposes the current open file as `file:///current-file`. The host app calls `resources/read` when the user opens the file; the model sees the content as context, never having "requested" it.

### Prompts (user-controlled)

Prompts are reusable, parameterized message templates that a server exposes. The user explicitly selects one — typically via a slash command or UI affordance in the host client. The model does not invoke prompts autonomously.

**JSON-RPC methods:**

- `prompts/list` — enumerate available prompt templates (name, description, argument list)
- `prompts/get` — retrieve a rendered prompt for a given name and argument values

A `notifications/prompts/list_changed` notification signals when the prompt catalog updates.

**Concrete example:** A code-review server exposes a `review_pr` prompt with a `pr_url` argument. The user types `/review_pr pr_url=https://github.com/…`; the client calls `prompts/get` and inserts the rendered messages into the conversation.

### Tools (model-controlled, brief)

Tools are executable actions the model invokes autonomously based on context. Listed via `tools/list`, called via `tools/call`. This is the most-used primitive; see /resources/mcp-vs-a2a for the full protocol context.

## Client-side primitives

These primitives invert the direction: the server calls into the client rather than the client calling the server.

### Sampling (server calls client for an LLM completion)

Sampling lets a server request an LLM completion from the host client on its behalf. The server sends a `sampling/createMessage` request containing a message list, an optional system prompt, and optional model preferences (cost/speed/intelligence hints). The client — subject to user approval — forwards the request to its connected LLM and returns the result.

**JSON-RPC method:** `sampling/createMessage` (server → client)

The human-in-the-loop design is deliberate. The spec requires clients to let users review and modify sampling requests before sending them to the model, and to review model responses before returning them to the server. This ensures the server cannot silently use the model to exfiltrate context or generate content the user has not sanctioned.

Note: Sampling is marked deprecated in the draft 2026-07-28 spec revision (SEP-2577). Per the MCP feature lifecycle policy it remains in the 2025-11-25 stable spec and will not be eligible for removal for at least twelve months after that draft ships.

**Concrete example:** A database MCP server receives a `resources/read` call for a large schema blob. Rather than hard-coding a summary, it calls `sampling/createMessage` asking the LLM to condense the schema into a two-sentence description, then returns that summary as the resource content.

### Roots (client declares filesystem/URI boundaries)

Roots are URIs (commonly `file://` paths) that the client declares to tell the server which parts of the filesystem or resource space it is permitted to access. This is a coordination mechanism, not a hard security enforcement: the spec requires servers to respect root boundaries, but cannot enforce it because servers run code outside the client's control.

**JSON-RPC methods:**

- `roots/list` — server requests the current list of roots from the client
- `notifications/roots/list_changed` — client notifies the server when the root list changes

Roots update dynamically: when a user opens a new project folder, the client sends `notifications/roots/list_changed` and the server can call `roots/list` to refresh its scope — no server restart required.

**Concrete example:** A filesystem MCP server starts with roots `[file:///projects/alpha]`. The user opens a second project; the client sends `notifications/roots/list_changed`; the server calls `roots/list` and now has `[file:///projects/alpha, file:///projects/beta]`.

Note: like Sampling, Roots is marked deprecated in the draft 2026-07-28 spec revision (SEP-2577, which deprecates roots, sampling, and logging). It remains in the 2025-11-25 stable spec and stays usable for at least twelve months after that draft ships.

### Elicitation (server requests structured user input)

Elicitation was introduced in the **2025-06-18** spec revision. It lets a server request additional structured input from the user mid-session, without the server needing to implement its own UI.

**JSON-RPC method:** `elicitation/create` (server → client)

The request carries a human-readable `message` and an optional `requestedSchema` — a restricted JSON Schema subset (flat object with primitive-type properties only; no nested objects or arrays). The client renders the schema as a form, the user fills it in (or declines), and the client returns one of three actions:

- `accept` — user submitted the form; response includes the filled content object
- `reject` — user explicitly declined to provide the information
- `cancel` — user dismissed the dialog without taking action

Servers are explicitly prohibited from using elicitation to request sensitive data (passwords, tokens, credentials). The user can always reject an elicitation request.

**Concrete example:** A CI/CD MCP server is about to deploy to production. It calls `elicitation/create` with `message: "Confirm deployment target"` and a schema requiring `{ env: string, confirm: boolean }`. The user fills in the form; the server proceeds only on `action: accept` with `confirm: true`.

## Resources vs Tools: the key design question

The most common MCP server design question is whether to expose something as a Resource or a Tool. The spec's control-model distinction gives a clean answer:

| Use a Resource when... | Use a Tool when... |
|---|---|
| The data is read-only context the app injects | The model needs to trigger an action or side effect |
| The app (not the model) decides what to include | The model decides whether and when to call |
| The content is stable or subscribable | The content depends on model-chosen arguments |
| Example: open file, DB row, live feed | Example: search API, code executor, write operation |

A file viewer is a Resource. A file writer is a Tool. A search endpoint that takes a query the model chooses is a Tool. A configuration blob the app always injects is a Resource.

## Verified sources

- MCP schema 2025-11-25 (method names verified directly): https://github.com/modelcontextprotocol/modelcontextprotocol/blob/main/schema/2025-11-25/schema.ts
- MCP elicitation spec 2025-06-18 (introduction revision confirmed): https://modelcontextprotocol.io/specification/2025-06-18/client/elicitation
- IBM mcp-context-forge issue #234 (elicitation/create confirmed in 2025-06-18): https://github.com/IBM/mcp-context-forge/issues/234
- MCP resources spec (resources/list, resources/read, resources/subscribe confirmed): https://spec.modelcontextprotocol.io/specification/server/resources/
- Speakeasy MCP roots reference (roots/list, notifications/roots/list_changed): https://www.speakeasy.com/mcp/core-concepts/roots
- MCP sampling spec (sampling/createMessage): https://spec.modelcontextprotocol.io/specification/2025-03-26/client/sampling/
- MCP vs A2A protocol comparison: /resources/mcp-vs-a2a
- MCP server discovery guide: /resources/mcp-server-discovery
