If an interviewer asks you exactly one MCP question, it will probably be this one: "what's the difference between tools, resources and prompts?" Most candidates guess something about data formats and lose the point. The real answer is one word — control — and once you have it, a surprising number of design and security questions answer themselves.
The control question
Not "what does it return?" — all three can return text. Who decides that it happens? The model decides to call a tool. The application decides which resources to load. The user picks a prompt. Control, not content, is the dividing line.
Tools — the model decides
A tool is an action the model can request during a conversation: create a ticket, search orders, run a query, send a message. It may have side effects, and — crucially — the decision to invoke it is made by the model, not by a human clicking something.
@mcp.tool()
def create_ticket(project: str, title: str, description: str) -> dict:
"""Create a new issue in the given project. Use ONLY after the user has
confirmed the details. Does NOT search existing issues."""
...Everything from ordinary tool calling applies: the description is the prompt the model reads (say when to use it and what it is not for), the type hints become the parameter schema, and validation belongs in the function body. MCP adds annotations — hints such as read-only, destructive or idempotent — which let hosts decide what deserves a confirmation dialog.
Resources — the application decides
A resource is read-only reference data identified by a URI, which the host application chooses to load into context: the text of a document, a list of projects, a configuration file, yesterday's report.
@mcp.resource("policy://shipping")
def shipping_policy() -> str:
"""Current shipping and delivery policy text."""
return load_policy("shipping")The difference from a tool is not the data — it's that the model doesn't decide to fetch it. The application (or the user through the application's UI) attaches it. Think of resources as things you can "@-mention" into a conversation, and tools as things the assistant reaches for on its own.
Prompts — the user decides
A prompt primitive is a reusable template the server offers, which the user explicitly selects — typically from a slash-command or menu in the host: "summarize this PR", "write a release note", "draft a bug report from this log".
The insight behind them: the team that owns a system knows the good prompts for it. Shipping those templates alongside the tools means every AI client gets the well-crafted version instead of each user improvising.
Wait — a customer record could be either. Which is it?
Correct, and this is where the control test earns its keep. The same underlying data can legitimately be exposed as a resource or a tool, depending on who should decide access.
| Situation | Primitive | Why |
|---|---|---|
| The app opens a customer's page and attaches their record | Resource | the application chose it; fixed, read-only context |
| The assistant must look up whichever customer comes up mid-chat | Tool | the model must decide dynamically which record to fetch |
| A curated "write a customer summary" template | Prompt | the user picks it deliberately |
So the design question is never "is this data or an action?" — it's "who should be allowed to decide this happens?"
Sampling — capability in the other direction
One more primitive, on the client side. Sampling lets a server ask the client to run an LLM completion on its behalf. Why? So a server can use model intelligence — summarizing something before returning it, say — without holding its own API keys or budget.
Model access, cost and consent stay with the host, which is why hosts typically require user approval for sampling requests: a server asking for completions is spending the user's tokens.
Why the control split matters for security
Because the three categories map directly onto risk. A model-controlled action can fire without any human deciding, so hosts can require confirmation for it — especially when annotations mark it destructive. An application-controlled resource was deliberately attached, so it can be treated more freely. A user-controlled prompt was explicitly chosen.
That's why the distinction isn't documentation trivia: it's the basis on which a host decides what needs your permission.
Selection-round radar: the highest-frequency MCP question. Answer in this order: control is the dividing line → tools = model-controlled, possibly side-effecting → resources = application-controlled, read-only → prompts = user-selected templates → and mention that the same data can be either depending on who should decide. Add sampling if you want the bonus.
Common mistakes
- Distinguishing the primitives by data type or format instead of by control.
- Exposing everything as tools, so the model must decide things the app already knows.
- Writing thin tool descriptions — they're what the model reads to choose.
- Forgetting annotations on destructive tools, so hosts can't gate them properly.
- Confusing MCP prompt primitives with the model's system prompt.
- Treating sampling as free — it spends the user's tokens and needs consent.
Quick recap
| Primitive | Controlled by | Shape |
|---|---|---|
| Tool | the model | name + description + parameter schema (+ annotations); may act |
| Resource | the application | URI-identified read-only data loaded into context |
| Prompt | the user | reusable template selected from the host's UI |
| Sampling | the server asks, the client (and user) allows | server requests an LLM completion via the client |
| The test | who should be allowed to decide this happens? | |
Practice Zone — PYQs from real selection rounds
Six MCQs and a classification task — sort six Jira capabilities into tools, resources and prompts (two of them look identical and aren't).
The three server primitives in MCP are distinguished mainly by:
Asked in

A server exposes a customer database. Reading a customer record for context should usually be:
Asked in

What is an MCP prompt primitive?
Asked in

A tool definition must include:
Asked in

Why does the control distinction matter for security?
Asked in

Client-side, MCP also defines sampling. What is it?
Asked in

Hands-on task:
For a Jira MCP server, classify each as tool, resource or prompt: 1) create a ticket; 2) the text of ticket PROJ-412; 3) "write a sprint summary" template; 4) search tickets by query; 5) the list of project names; 6) transition a ticket to Done.
Asked in

FAQ
Must a server implement all three primitives?
No — it declares what it supports during the handshake (lesson 2). Plenty of useful servers expose tools only; adding resources and prompts is worthwhile when there's stable reference data or well-known workflows to share.
Can a resource be large, like a whole database table?
It can, but it shouldn't be — whatever is loaded enters the model's limited context and is re-sent on later steps. Expose focused resources, and use a tool with parameters when the client needs to select a subset (lesson 5).
Are tool annotations enforced by the protocol?
They're hints for hosts, not guarantees — a server saying "read-only" doesn't make it so. Hosts use them to decide what to confirm, and you should still enforce real limits inside the tool code (lesson 7).
Next lesson: how these messages actually travel — Lesson 4: MCP Transports →


