MCP Tools vs Resources vs Prompts: When to Use Each
Three primitives, one you'll actually use, and two most servers skip on purpose.

MCP tools vs resources vs prompts comes down to who is in control. Tools are model-controlled actions the LLM decides to call; resources are app-controlled data the client attaches to context; prompts are user-controlled templates a human picks from a menu. Almost every server you'll install ships only tools, and that's the right default — but knowing the other two tells you when a server is under-built versus deliberately lean.
If you're new to the protocol itself, start with what an MCP server is and come back. This piece is about the three things a server can expose and which ones matter in practice.
What are MCP tools, resources, and prompts?
The three primitives are the only ways a server can offer capability to a client, and they differ by who triggers them. That control axis is the whole design, so here it is straight:
| Primitive | Controlled by | What it is | Analogy |
|---|---|---|---|
| Tools | Model | Functions the LLM calls to act or fetch live data | POST endpoints |
| Resources | Application | Readable data the client loads into context | GET endpoints / files |
| Prompts | User | Pre-written templates the user invokes | Slash commands |
Tools are the verbs: create_issue, run_query, search_files. The model reads their JSON schemas, decides when to call them, and gets results back. Resources are the nouns: a file, a database row, a doc page — identified by URI, read on demand. Prompts are canned interactions the user selects, usually surfaced as slash commands in the client UI.
The distinction that trips people up: a tool can also return data, so why have resources? Because the initiative differs. A tool call is the model's choice; a resource is the app's or user's choice to pin something into context before the model even reasons. You can see the full inventory a given server declares on its capabilities page.
When to use each primitive
Reach for tools by default; add resources when the client should manage the data, and prompts only when a workflow is common enough to deserve a shortcut. Here's the decision I actually use:
- Use a tool when the model needs to do something or fetch something dynamic — anything with parameters, side effects, or a query. This is the vast majority of real usage.
- Use a resource when there's a stable, addressable blob the user or client should choose to attach — a config file, a schema, a wiki page. The client lists them; a human or the app picks; the model doesn't have to "decide" to read it.
- Use a prompt when a multi-step interaction repeats often enough that typing it every time is waste — "summarize this PR," "write a conventional commit." It's a UX affordance, not new capability.
A concrete tell: if you find yourself writing a read_file tool and exposing files as resources, pick one based on who should initiate. Model decides which file to read next mid-reasoning? Tool. User wants to hand-pick files up front? Resource.
Why almost every server ships only tools
Most servers expose tools and nothing else because tools are the only primitive every major client supports the same way. Resource and prompt support has been uneven across clients, so a server that leans on them risks being half-usable depending on where it's plugged in. Tools are the safe, portable bet.
There's a second reason: tools subsume the other two. Anything a resource does, a list_* plus get_* tool pair can do — less elegantly, but it works everywhere. Anything a prompt does, the user can type. So the marginal payoff of implementing resources and prompts is low unless your data model is genuinely file-like or your workflows are genuinely repetitive.
This is why "tools-only" is not a red flag. When you browse the best MCP servers, the strong ones are frequently tools-only and proud of it. Judge a server by whether its tools are well-scoped, not by how many primitives it checks off.
The tool-count trap
Tools are the primitive that costs you, because every tool's schema is injected into the model's context whether or not it's ever called. Clients like Cursor cap the total at roughly 40 tools across all connected servers, and every tool you add eats that budget and dilutes the model's aim.
This reframes the primitives question. Resources and prompts are nearly free — they're listed lazily and don't bloat the tool schema. A server that dumps 25 tools into your client is a worse citizen than one that exposes 6 tools plus a handful of resources. So when you're comparing servers, count the tools:
- A focused server: 5–12 sharp tools.
- A kitchen-sink server: 20–40+ tools, half of which overlap.
If two servers cover the same ground, prefer the one with fewer, better-named tools. The short version is that context is the scarce resource, and tools spend it, so a server's capabilities list is worth reading before you install.
How this maps to transports and deployment
The three primitives are transport-agnostic — a server declares the same tools, resources, and prompts whether it runs locally or remotely. Where it runs affects trust and setup, not the primitive model. Most servers run locally over stdio, launched as a subprocess by your client, with remote HTTP/SSE servers the minority.
That local-first reality matters for how you read a server's capabilities. A local stdio server exposing file resources is reading your disk; a remote one exposing the same is reading someone else's. Same primitive, very different blast radius. Where a server runs is worth understanding before you trust a resource-heavy one with your filesystem.
One more framing that helps: if you're coming from REST, the mental model in MCP vs API lines up cleanly — tools are your action endpoints, resources are your GETs, and prompts have no real REST analog because they're a client-side UX layer, not a network call.
What to skip
Skip prompts entirely when you're building your own server unless you have a repetitive workflow users have literally asked for. They're the lowest-payoff primitive and the least-supported across clients. Skip resources unless your data is genuinely addressable and stable — otherwise a well-named tool is more portable and easier to reason about.
Spend your effort on tools: fewer of them, each doing one thing, each with a schema and description the model can't misread. That's the entire game. The primitive count on a server's spec sheet is close to noise; the quality and scope of its tools is the signal.