Skip to main content
Core11 min1825 words

MCP tools vs resources vs prompts: what to use when

A practical comparison of MCP tools, resources, and prompts across control plane, discovery, schemas, permissions, freshness, UX, testing, and safe server design.

Article contents
  1. 01Short answer: action, context, and interaction templates are different contracts
  2. 02The control plane shapes UX but does not grant authorization
  3. 03Tools: a typed operation contract with the highest authority risk
  4. 04Resources: URI, freshness, and context budget must be explicit
  5. 05Prompts: a reusable workflow with visible arguments, not a policy boundary
  6. 06Decision matrix and anti-patterns for one domain workflow
  7. 07Contract tests, canary rollout, and rollback

Short answer: action, context, and interaction templates are different contracts

An MCP tool describes an operation the model may propose calling with typed arguments: find an order, calculate a rate, or create a draft. A resource provides context that the host application can read by URI and add to the conversation: a file, schema, reference, or snapshot. A prompt is a parameterized message template that the user deliberately selects for a repeatable workflow. These are three different control planes, not three ways to publish the same function.

Choose the primitive by who owns the next step. Use a tool for an external operation or authoritative lookup with runtime parameters. Use a resource when the user or application should select and read material as context. Use a prompt when the product needs a visible starter command with arguments and prepared messages. One server can combine all three: a prompt frames the task, a resource supplies policy, and a tool performs an allowed lookup. Prompts or resources must not hide side effects, and tools should not be used only to ship static text.

  • Changes or computes state from runtime input → tool.
  • Provides addressable content for context → resource.
  • Starts a user-selected reusable interaction → prompt.
  • Needs two roles → compose primitives with separate contracts.

The control plane shapes UX but does not grant authorization

The specification describes tools as model-controlled: a client can expose them to the model and let it choose a call. For sensitive operations, the client should show inputs and allow a person to decline. Resources are application-driven: the host decides whether to offer a picker, search, automatic inclusion, or another interface. Prompts are user-controlled and are intended to appear as user-accessible commands or templates, although the protocol does not mandate a particular UI.

Those labels are not authorization. A model choosing a tool does not grant permission for a side effect; selecting a resource does not prove access to every URI; running a prompt does not authorize every action described in its text. Client and server separately validate identity, scopes, tenant, target, and current state. Consequential actions need a preview, confirmation, or policy gate at execution time rather than trust in an earlier prompt selection.

Tools: a typed operation contract with the highest authority risk

A tool definition needs a stable name, clear description, and valid JSON Schema for input. An optional outputSchema lets the client validate structuredContent; that helps downstream automation but does not prove the data is true. The server validates schema and business constraints, checks permission for the concrete object, and returns a tool execution error for recoverable domain failures. Reserve protocol errors for malformed requests or unknown tools.

Separate read and write operations. `orders.get` can be a low-risk lookup, while `orders.refund` should require amount, currency, order version, reason, idempotency key, and approval receipt. Avoid a universal `execute_api` with arbitrary path and body because it hides authority from the model, reviewer, and audit log. Tool annotations are useful UX hints, but a client must not treat them as trusted security policy unless it trusts the server.

A tool result may include text, structured content, a resource link, or an embedded resource. That does not turn the tool into a resource: the invocation remains an operation with inputs, timeout, error semantics, and an audit event. If a large result has a stable URI or is reused, return a concise structured summary plus a resource link instead of copying the whole corpus into every result.

  • Input schema validates shape; policy validates permission and intent.
  • Output schema validates structure; the authoritative system validates the fact.
  • Write tool → exact target, confirmation, idempotency, and postcondition.
  • Ambiguous timeout → reconcile before retry.

Resources: URI, freshness, and context budget must be explicit

A resource has a unique URI and may contain text or binary content with a MIME type. Resource templates publish parameterized URIs, and optional completion can help fill an argument. A client first calls resources/list or templates/list and then resources/read. Subscriptions and listChanged are separate optional capabilities; supporting resources does not imply automatic refresh.

For production, record source owner, data classification, revision or lastModified, allowed audience, size budget, and cache policy. Annotations such as `audience`, `priority`, and `lastModified` are client hints, not access-control decisions. The server checks URI, authorization, and resource permission on every read. Do not put a secret in a predictable URI or assume an unlisted item cannot be read by a direct request.

A resource is good for context but does not guarantee that the model used or cited it correctly. Evaluation should check current revision, passage support, conflict disclosure, no-answer behavior, and cross-scope canaries. For a frequently changing business fact, a read-only tool that performs an authoritative lookup at request time can be better; for browsable documentation with stable identifiers, a resource provides a stronger discovery and cache contract.

  • Stable browsable content → resource or resource template.
  • Live parameterized fact → often a read-only tool.
  • Subscription does not replace a revision check before an important decision.
  • URI visibility is not permission.

Prompts: a reusable workflow with visible arguments, not a policy boundary

A prompt definition has a name, optional title and description, and a list of arguments. prompts/get returns a description and messages with validated arguments substituted by the server. Messages can contain text, image, audio, or an embedded resource. A good prompt explains the outcome and expected inputs: `review_incident` with an incident ID and review depth is more useful than a vague `analyze`.

A prompt works well as a discoverable slash command, onboarding step, or standardized analysis sequence. It is not server-side automation and does not guarantee that the model will follow the instructions. Do not hide an approval, credential, or irreversible action in the template. If a workflow needs a tool, the prompt can prepare messages and ask for analysis, but the client still applies tool policy and the server re-authorizes the call.

Version the template content or at least store its hash in evaluation evidence. listChanged tells the client that the catalog changed, but an active conversation may already contain old messages. Regression tests should cover argument escaping, prompt injection in user-provided fields, missing arguments, locale behavior, embedded-resource permissions, and behavior after a template change.

Decision matrix and anti-patterns for one domain workflow

Consider a support server. `support://policies/refunds/2026-09` is a resource because it is versioned policy content for reading. `draft_refund_review` is a prompt because the user selects a repeatable review template with a ticket ID. `tickets.get` and `refunds.create_draft` are tools because they perform a runtime lookup and create a controlled draft. A final `refunds.submit` should be separated with a stronger scope and confirmation. This composition makes the source, reasoning workflow, and authority visible as distinct boundaries.

Common mistakes include publishing every database row as a tool, hiding a write request in a resource URI, returning stale policy through a tool without revision, using a prompt as system policy, duplicating the same content in a prompt, resource, and tool description, or exposing one mega-tool for every API. These patterns hurt discovery, increase context, blur permissions, and make evaluation unable to localize failures.

Before implementation, fill out a short contract card: user outcome, controller, data owner, freshness, input/output shape, side effects, permission check, audit event, failure semantics, context cost, and rollback. If two entities have different authority or lifecycle, give them different primitives even if they share one backend endpoint.

  • Context failure → check resource revision and selection.
  • Instruction failure → check prompt version and argument handling.
  • Execution failure → check tool schema, policy, effect, and reconciliation.
  • Mixed failure → keep separate receipts for each boundary.

Contract tests, canary rollout, and rollback

Start the contract suite with capability combinations: a server with each primitive alone, all three together, and catalog changes. Test pagination, unknown names or URIs, invalid arguments, MIME handling, structured output, listChanged, and resource subscriptions only when the capability is declared. Negative security cases should swap tenant, target, URI, prompt argument, and tool result, add indirect injection to a resource, and repeat a write after an ambiguous timeout.

Run an end-to-end evaluation on a synthetic support case: the user selects a prompt, the client reads a specific policy revision, the model proposes a read tool, and the write draft requires separate confirmation. The evidence pack should contain protocol version, capability manifest, catalog hashes, resource revision, rendered prompt, tool inputs and results, approval receipt, final state, and reviewer verdict. That makes it possible to identify the failed boundary without trusting a fluent final answer.

Begin rollout with one read-only resource, one prompt, and one read-only tool. After scope and audit are verified, add a reversible draft write; keep irreversible actions outside model authority until they have a separate approval contract. Rollback disables the affected capability or tool, revokes scope, pins the last verified resource or prompt revision, and preserves read-only diagnostics. Reactivation requires regression testing for the changed primitive and the full composition it feeds.

  • Hard gate → cross-tenant read, hidden side effect, or unauthorized write.
  • Quality gate → stale revision, unsupported claim, or ambiguous prompt outcome.
  • Compatibility gate → advertised capability does not match method behavior.
  • Recovery gate → retry does not duplicate the effect or break the audit chain.

Practical examples

Support workflow with three primitives

The user starts a prompt for ticket review. The client reads a versioned refund-policy resource. The model calls a read-only ticket tool, prepares a conclusion, and only after separate confirmation calls a create-draft tool. Evidence keeps revisions and receipts for every boundary.

When a resource is better than a tool

The server publishes a catalog of versioned API schemas as resource templates. The host gives the user a picker and caches unchanged revisions. A tool is needed only for live schema validation against a specific deployment, not for repeatedly sending a static document.

FAQ

What is the main difference between MCP tools, resources, and prompts?

A tool is a model-controlled operation, a resource is application-managed context addressed by URI, and a prompt is a user-selected reusable message template. The concrete client determines the UI, while authority and permissions are always checked separately.

Can a tool return a resource?

Yes. A tool result can contain an embedded resource or resource link. The call still remains an operation contract with inputs, errors, and audit, while the resource keeps its own URI, permission, and freshness semantics.

When should reading data use a tool versus a resource?

Use a resource for browsable, addressable, often versioned content. Use a read-only tool for live parameterized lookup where the result depends on runtime input, authorization, and authoritative current state.

Can a prompt automatically approve a tool call?

No. Running a prompt is not authorization for a later action. The client applies confirmation policy, and the server checks identity, scope, target, and state on every consequential tool call.

Related materials

Sources

  1. Tools — MCP specification 2025-11-25primary
  2. Resources — MCP specification 2025-11-25primary
  3. Prompts — MCP specification 2025-11-25primary
  4. Lifecycle — MCP specification 2025-11-25primary
  5. MCP schema reference 2025-11-25primary