# Tool, resource or prompt? Choosing the right MCP primitive

October 15, 2026 · Part 12 of 35

![Tool, resource or prompt? Choosing the right MCP primitive](https://pournasserian.com/_astro/lead.D2TGDcOZ_ZKpwj4.webp)

Most early Model Context Protocol (MCP) servers made everything a tool. That handed the model decisions that belonged to the user or the application, and made those servers harder to use and harder to secure. The way out starts with one question for every capability: who decides when it's used?

This is part 12 of my series on what an MCP server does under the 2026-07-28 specification. [Part 11](https://pournasserian.com/writing/mcp-2026-prompts) covered prompts, the last of the three primitives a server offers. This part puts them side by side with the other mechanisms a server has, and gives a procedure for choosing between them. The facts are as I read them in October 2026.

## In brief

1. **Tools, resources and prompts differ mainly in who decides when they're used:** the model calls a tool, the application attaches a resource, and the user picks a prompt.
2. **Four more mechanisms sit beside them:** server instructions, and the Skills, MCP Apps and Tasks extensions, each with its own trigger and its own point at which it loads.
3. **Two of those four depend on the host:** whether server instructions reach the model is up to it, and a skill loads when it's selected, after an approval step the host may add and must add in a few cases, such as running code.
4. **A short run of yes-or-no questions, asked in order, tells you where a new capability belongs:** the first asks whether the model must always know it, the last whether the result needs interaction to be useful.
5. **Build in layers, because host support is uneven:** the core value in tools with good text output, the guidance in instructions and prompts, and the richer experience in extensions that degrade cleanly.

## Who decides when

Each of the three primitives has a different party deciding when it's used:

- A **tool** is a function with a schema. The model calls it with `tools/call` while it reasons. [Part 8](https://pournasserian.com/writing/mcp-2026-tool-definitions) covers how to define one.
- A **resource** is context identified by a Uniform Resource Identifier (URI). The application reads it with `resources/read`, and the host attaches it as context. [Part 10](https://pournasserian.com/writing/mcp-2026-resources) covers resources.
- A **prompt** is a reusable template. The user usually runs it as a slash command or picks it from a menu, and the host fetches it with `prompts/get`.

```mermaid
flowchart TB
    subgraph model["Model decides"]
        direction TB
        t1["Tools<br/>functions with schemas"] --> t2["tools/call"] --> t3["Model calls it<br/>while reasoning"]
    end
    subgraph app["Application decides"]
        direction TB
        r1["Resources<br/>context by URI"] --> r2["resources/read"] --> r3["Host attaches it<br/>as context"]
    end
    subgraph user["User decides"]
        direction TB
        p1["Prompts<br/>reusable templates"] --> p2["prompts/get"] --> p3["User runs<br/>a slash command"]
    end
```

Some utilities sit underneath all three: pagination, [caching hints](https://pournasserian.com/writing/mcp-2026-caching-and-pagination) and `list_changed` notifications. Completion is narrower: it suggests values for prompt arguments and resource-template arguments.

My advice, when you design a new server: list its capabilities first and put each one in the column of whoever decides. That question, who decides, drives most of the design choices that follow.

## Seven mechanisms side by side

Server instructions and three extensions add further options. Here they are with the three primitives:

| Mechanism | Who triggers it | Loaded when | Side effects | Typical use |
|---|---|---|---|---|
| **Tool** | Model | When the model calls it | Yes, potentially | Queries, actions, computations |
| **Resource** | Application or user | When attached or read | No (read-only) | Documents, schemas, records, large outputs |
| **Prompt** | User | When the user picks it | No (it produces messages) | Workflow starters, expert templates |
| **Server instructions** | The host, with no model or user action | When the host connects, if it loads them | No | Orientation and rules for using the tools together |
| **Skill** (extension) | Model or user | When selected; the host may ask for approval first | Only through the tools it uses | Multi-step procedures with reference files |
| **MCP App** (extension) | Model, through a tool | When the linked tool returns | Through tools the app can call | Interactive user interface: charts, forms, viewers |
| **Task** (extension) | Server, per request | When work is long-running | Yes, potentially | Batch jobs, long research, jobs handed to an external application programming interface |

Two rows need care.

**Server instructions** are an optional field of the [`server/discover` result](https://modelcontextprotocol.io/specification/2026-07-28/server/discover), and calling `server/discover` is itself optional for a client. Hosts that support instructions load them when they connect ([Claude Code](https://code.claude.com/docs/en/mcp) loads them at session start, as of October 2026), but that's host behaviour, not a protocol guarantee. [Part 4](https://pournasserian.com/writing/mcp-2026-server-instructions) covers what to write in them.

**A skill** loads when the model or the user selects it. The [Skills overview](https://modelcontextprotocol.io/extensions/skills/overview) lets a host ask for the user's approval first, and makes approval mandatory only for running code, `allowed-tools` grants, reads across servers and activating nested skills.

## A decision procedure

When a new capability comes along, I ask these questions in order:

```mermaid
flowchart TB
    s(["New capability"])
    q1{"Must the model<br/>always know it,<br/>on every turn?"}
    instr["Server instructions"]
    q2{"Is it a workflow<br/>the user starts<br/>on purpose?"}
    q3{"Is it read-only<br/>context identified<br/>by a URI?"}
    q2b{"Does it need<br/>supporting files<br/>or several steps<br/>the model could also<br/>pick on its own?"}
    res["Resource<br/>+ template,<br/>+ subscription if live"]
    q4{"Should the model<br/>decide when<br/>to do it?"}
    prompt["Prompt"]
    skill["Skill<br/>and a prompt as fallback"]
    rethink["Rethink:<br/>maybe a resource<br/>the host attaches"]
    tool["Tool"]
    q5{"Can it take<br/>longer than<br/>about a minute?"}
    task["Tool returning a Task"]
    q6{"Does the result<br/>need interaction<br/>to be useful?"}
    appx["Tool + MCP App<br/>with text fallback"]
    plain["Plain tool"]

    s --> q1
    q1 -- yes --> instr
    q1 -- no --> q2
    q2 -- yes --> q2b
    q2b -- no --> prompt
    q2b -- yes --> skill
    q2 -- no --> q3
    q3 -- yes --> res
    q3 -- no --> q4
    q4 -- no --> rethink
    q4 -- yes --> tool --> q5
    q5 -- yes --> task
    q5 -- no --> q6
    q6 -- yes --> appx
    q6 -- no --> plain
```

Put as rules, the branches come to this:

- **Server instructions** are for guidance the model needs every time, in the hosts that load them.
- **A prompt** is for a workflow the user starts on purpose and that benefits from your server's expertise. It can also be a reliable entry point into a workflow of several tools: "call `search` with these filters, then `fetch` the top three, then summarize as a table".
- **A skill** is for a procedure of several steps, with supporting files, that the model may also pick on its own. A prompt can stand in for it where skills aren't supported.
- **A resource** is for read-only context identified by a URI, with a template, and a subscription if it's live.
- **A tool** is for anything the model should decide to do, and for anything with side effects.

If a capability isn't a workflow the user starts, isn't read-only context and isn't something the model should decide, take a second look at it: it may be a resource the host attaches after all.

The one-minute question is my rule of thumb, not the specification's. The [Tasks overview](https://modelcontextprotocol.io/extensions/tasks/overview) speaks of long-running operations that take minutes or hours. It also warns that many clients and transport intermediaries impose timeouts that make blocking impractical beyond a few seconds, which suggests a lower bar than a minute.

The last question adds an MCP App on top of a tool when the result only becomes useful through interaction. The tool still returns text, so a host without Apps gets something it can show.

## Worked example: an engineering-docs server

Here is the procedure applied to a server for internal engineering documentation, the same kind of server as the instructions example in part 4:

| Capability | Mechanism | Why |
|---|---|---|
| "Use `search_docs` before `fetch_doc`; content refreshes nightly" | Server instructions | Always relevant, short |
| Search the docs | Tool `search_docs` (read-only) | The model decides when to search |
| Read a full document | Tool `fetch_doc`, plus a `resource_link` / `docs://` resource | The model can fetch, and hosts can attach |
| Browse documents by area | Resource template `docs://{area}/{slug}` | Host-driven browsing with completion |
| "Write an architecture decision record (ADR) from this discussion" | Prompt `write_adr` | The user starts it deliberately |
| Incident-response runbook with checklists and scripts | Skill `incident-runbook` | Multi-step procedure with supporting files |
| Visual dependency graph of services | Tool + MCP App | Interactive exploration |
| Re-index the whole corpus | Tool returning a Task | Takes many minutes |

One capability can use two mechanisms, as reading a full document does.

My advice is to expect uneven host support and build in layers. Tools work everywhere, prompts and resources in most hosts that behave like an integrated development environment, and Skills, Apps and Tasks only where they're negotiated. So the core value goes into tools with good text output, the workflow guidance into instructions and prompts, and the richer experience into extensions that degrade cleanly. A host that supports only tools still gets the core value, and each layer it supports adds to it.

## Method and caveats

- Built from chapter 12 of my guide to MCP servers, with the advice on when to use prompts from chapter 11 and the control model from chapter 3, written against the 2026-07-28 specification. Product facts are as of October 2026.
- The order of the questions, the time threshold for a Task and the layering are my own advice, not the specification's. Skills, MCP Apps and Tasks are opt-in extensions, and each is covered later in this series.
- Where the specification and the extension documentation are more precise than my notes (whether instructions reach the model, and when a skill needs approval), this article follows the `server/discover` page and the Skills overview.

I'm [Amir Pournasserian](https://pournasserian.com/about). I build AI and platform systems for a living, maintain [FluentCMS](https://pournasserian.com/open-source/fluentcms) and [YeSvelte](https://pournasserian.com/open-source/yesvelte), and write here about what I find along the way.
