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:

SignalWhy resource
Read-orientedFetch content, snapshot, or spec to understand it
URI-stableAddressable as file://…, docs://guide, or a template URI
Minimal side effectsA read does not mutate DB or send mail
Context supplyAttach “this doc/schema” to the agent prompt
Subscribe / refreshsubscribe / listChanged notifications matter

Practical cases:

  1. OpenAPI or DB schema — read once to match call shapes.
  2. Policy, runbook, ADR — long text as context.
  3. Fixed config snapshot — “current feature-flag list,” read-only.
  4. 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:

SignalWhy tool
Model choosesAgent decides whether to call from the user request
Argument schemainputSchema with required, enums, ranges
Side effects possibleCreate, update, delete, send, deploy
Recoverable failureisError, retry, different args
Needs approvalHuman expands args and Allow/Deny

Practical cases:

  1. Create or transition issues — create_ticket, transition_issue.
  2. Search with filters — jql, query, limit change every call.
  3. Write or share files/drives — do not fake this as a read-only resource.
  4. 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:

PatternResource roleTool role
Catalog + actionresources/list for doc/ticket URIssearch_* / update_* to find and change
Action → linkFollow-up resources/read on the URIcreate_* returns a new URI
Template + completeURI templates for addressingTool picks or creates the id
Read-only mirrorPolicy PDF / specNo 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)