MCP Resource vs Tool: When to Use Which
MCP resources and tools can live on the same server, but they diverge on who chooses them and whether there are side effects. In the spec, Resources are application-driven, URI-addressed data the host pulls in as context; Tools are model-invoked functions with schemas. Cursor supports both (Tools, Resources, Prompts).
Adjacent posts stay on other axes. mcp-tool-schema is tool description · required · error text. mcp-auth-fail is needsAuth and reconnect. This post is only resource vs tool selection. No pricing, plans, tokens, or affiliate links. Grounded in MCP Resources, MCP Tools, and Cursor MCP.
When resource?
One-line answer: Choose a resource when the data is read into context and the model should reference it more than “execute” it. It is identified by URI and fetched with resources/list and resources/read.
The spec describes Resources as application-driven: the host decides which slices reach the model; the server exposes passive sources such as files, schemas, docs, or app state.
Signals to prefer a resource:
| Signal | Why resource |
|---|---|
| Read-oriented | Fetch content, snapshot, or spec to understand it |
| URI-stable | Addressable as file://…, docs://guide, or a template URI |
| Minimal side effects | A read does not mutate DB or send mail |
| Context supply | Attach “this doc/schema” to the agent prompt |
| Subscribe / refresh | subscribe / listChanged notifications matter |
Practical cases:
- OpenAPI or DB schema — read once to match call shapes.
- Policy, runbook, ADR — long text as context.
- Fixed config snapshot — “current feature-flag list,” read-only.
- Resource templates —
ticket://{id}for the same kind of document.
Avoid:
- Complex filters and a different query every time → still a tool, even if read-only.
- Hiding writes / deletes / sends inside
resources/read→ approval UI cannot see the side effect.
Prefer resource when:
- Data is addressable by URI
- Host/user should choose what enters context
- Effect is read / snapshot / reference
When tool?
One-line answer: Choose a tool when the model picks timing, takes JSON Schema arguments, and must perform an action. Discover with tools/list, invoke with tools/call.
Tools let models talk to external systems (query, API, compute, write). Cursor docs label Tools as what the “AI model [can] execute” and Resources as data that can be “read and referenced.” Default approval UI and Run Mode attach to the tool-call axis.
Signals to prefer a tool:
| Signal | Why tool |
|---|---|
| Model chooses | Agent decides whether to call from the user request |
| Argument schema | inputSchema with required, enums, ranges |
| Side effects possible | Create, update, delete, send, deploy |
| Recoverable failure | isError, retry, different args |
| Needs approval | Human expands args and Allow/Deny |
Practical cases:
- Create or transition issues —
create_ticket,transition_issue. - Search with filters —
jql,query,limitchange every call. - Write or share files/drives — do not fake this as a read-only resource.
- Trigger build/test — logs and artifacts come back as the result.
Sentence-level schema and required design belong in mcp-tool-schema. Here you only pick action vs reference.
Prefer tool when:
- Model should decide timing and arguments
- Side effects or parameterized queries
- Approval / Run Mode should see the call
When both?
One-line answer: Put catalogs and bodies on resources, search / mutate / actions on tools, or return resource links / embedded resources from tool results for a follow-up read. Do not mirror the same surface on both without a reason.
The Tools spec allows results to include Resource Links or Embedded Resources. Common patterns:
| Pattern | Resource role | Tool role |
|---|---|---|
| Catalog + action | resources/list for doc/ticket URIs | search_* / update_* to find and change |
| Action → link | Follow-up resources/read on the URI | create_* returns a new URI |
| Template + complete | URI templates for addressing | Tool picks or creates the id |
| Read-only mirror | Policy PDF / spec | No write tool (or a different server) |
Selection checklist:
[ ] Fixed name opens by URI → resource
[ ] Args/filters/pages change every request → tool
[ ] Any write → must be a tool (never hide in resource read)
[ ] Tool returns huge bodies every time → return a link/URI, then resource read
[ ] Side effect invisible to approval UI? → expose as tool
[ ] Tools empty because needsAuth → mcp-auth-fail (out of scope here)
One-liner for practice: wrap context as resources; let tools decide. You can also split servers—“read the spec URI” vs “create the ticket.” Cursor’s Available Tools list is mostly tools; a resources-only server may lean on host UI or explicit @ references—check your Cursor build.
One-liner: resource = URI context (read); tool = model execution (action); both = catalog/body + action/link. Different axis from schema-design and auth-fail posts.
FAQ
Names look similar—how do I tell them apart?
Use protocol methods. resources/* means context data; tools/* means callable functions. Do not trust UI labels alone.
Must a read-only (GET) API be a resource?
If arguments change every time and the model chooses timing, a tool is natural. Fixed docs or schema snapshots fit resources. “Read = always resource” is false.
How does this differ from mcp-tool-schema and mcp-auth-fail?
mcp-tool-schema = description, required, error wording. mcp-auth-fail = needsAuth and OAuth reconnect. This post is the resource vs tool selection axis.
How do resources show up in Cursor?
Cursor documents Resources as supported. The server must declare the resources capability and implement list/read. Chat “Available Tools” is tool-centric; resource UX varies by host version—confirm via logs and the Customize card.
Sources
- MCP Resources — URI, list/read, application-driven
- MCP Tools — list/call, schema, resource link/embed
- MCP server concepts — tools vs resources summary
- Cursor MCP — Tools/Resources support, Available Tools, approval
- Adjacent: mcp-tool-schema (schema design), mcp-auth-fail (needsAuth)