Chapter 3 — Server Primitives: Exposing Context and Capabilities

Published on: 2026-04-01 Last updated on: 2026-06-12 Version: 2
Chapter 3 — Server Primitives: Exposing Context and Capabilities

Chapter 3 — Server Primitives: Exposing Context and Capabilities

Third post of the chapter-by-chapter walkthrough of LLM Primer IV: Designing AI Cognition with MCP. In which we learn what an MCP server can actually say — three nouns, three lifecycles, three error models — and why the discipline of picking the right one decides whether a server scales or accretes.


Why this chapter exists

A protocol is only as useful as the things it lets you say. Chapter 2 built the mental model of host, client, and server, and watched a session come alive through capability negotiation. Once the handshake completes and both sides know what the other can do, what is concretely on the table? MCP answers with three nouns: Resources, Prompts, and Tools. They look superficially similar — each is a named, schema-described thing the server can produce or run — but they map to three distinct intentions. Resources are read state. Prompts are reusable scaffolding. Tools are write actions. The chapter walks each in turn: schema, lifecycle, error model, and the places where engineers get it wrong.

One line: Resources let the model browse, Prompts let it start a scripted interaction, Tools let it act — and the discipline of MCP server design is choosing the right primitive for each capability and resisting the temptation to overload one into the others' territory.

3.1 Resources: read-only contextual data

A resource is data the server can hand to the model as context. The defining word is read-only. A resource does not mutate the world; it describes it. If a fetch causes a state change elsewhere — an audit log row, an incremented counter, a webhook fired — it is not a resource, it is a tool wearing a costume. Drawing this line sharply is the first discipline of MCP server design.

Each resource has a stable URI in a scheme the server chooses (file://, postgres://, linear://issue/ENG-1234), plus metadata: name, optional description, MIME type, optional size. None of these fields is decorative. A resource without a description is one the model cannot evaluate. The lifecycle is straightforward: resources/list to enumerate, resources/read to fetch. There is no resources/write — if the server wants writes, it must expose a tool. The asymmetry keeps the trust boundary visible.

Two patterns make resources practical at scale. URI templates let the server expose a parameterized read endpoint (db://orders/{order_id}) instead of enumerating millions of rows. Subscriptions let the host register interest in a URI and receive notifications/resources/updated when the underlying data changes — the alternative is polling at LLM cadence, which is wasteful both directions. The pitfall to avoid is dumping every internal object onto the resource list at session start: a list of three thousand resources eats tens of thousands of tokens before the user has typed anything. Expose a curated top level plus templates, and let the model search the long tail.

3.2 Prompts: reusable templates and workflows

Prompts in MCP have nothing to do with the system prompt of an LLM. They are reusable, server-defined templates a user — or a host on behalf of a user — can invoke to start a particular interaction. A prompt is closer to a slash command than to a personality. The point is to let a server ship known-good interaction patterns alongside the tools and resources it exposes, so the human at the keyboard does not have to remember how to phrase the request.

A prompt has a name, an optional description, and a list of arguments. The host calls prompts/list to discover, then prompts/get to expand a prompt into a sequence of messages the host can feed into its model loop. The prompt may reference resources by URI, in which case the host inlines them before sending. The server scripts the opening turns; the model takes it from there.

The distinction between prompts and system messages matters. A user invoking /review_pr sees, in their conversation log, the assistant beginning to work on a review — they understand what started, they can interrupt, they can audit. If the server instead silently appended instructions to the host's system prompt, the user would have no idea why the assistant suddenly behaved differently. Prompts are user-visible scaffolding; system prompts are the host's framing. The two should not be conflated. The discipline is that any prompt content the user would not approve of if shown explicitly is a defect.

3.3 Tools: actions, structured outputs, idempotency

Tools are where MCP becomes interesting and dangerous in equal measure. Resources are read; prompts are scaffold; tools are write — they create rows, send messages, deploy services, charge cards. Every tool has a name, a description, and an input schema in JSON Schema. The description is the most important field on the entire MCP surface, because it is the text the model uses to decide whether to call the tool, when to call it, and with what arguments. A tool whose description says "sends an email" is one the model will reach for whenever email-shaped intent appears. A tool whose description says "sends a transactional email via the marketing platform, only for verified customer addresses; not for personal correspondence" is one the model uses more discriminately.

The error model has two channels. A protocol error (malformed arguments, unknown tool) returns a JSON-RPC error and is a framing failure. A tool error (recipient bounced, disk full) returns a successful response with isError: true and a content block explaining what happened. The distinction matters: the model should see tool errors and adapt; the host should see protocol errors and recover transport. Conflating them robs the model of the information it needs.

Modern MCP supports structuredContent alongside the prose content array, conforming to a declared outputSchema. The compounding effect across a long trace is real: short, structured tool outputs leave the model with headroom for actual reasoning; long, prose outputs eat the context budget. Two further disciplines deserve naming. Minimality: twelve well-described tools beat sixty in almost every benchmark; expose find_users with a structured filter rather than list_users, get_user, search_users, count_users. Idempotency: retry storms are inevitable; a tool that accepts an idempotency key or uses a deterministic identifier scheme turns network blips into no-ops rather than data-integrity incidents.

3.4 Composition: how the three primitives cooperate

The primitives are most useful when they work together. A well-designed server typically exposes some of each: a few prompts to seed common interactions, a small set of tools for the actions that matter, and a possibly large set of resources that supply the context. A customer support server might expose customer profiles and ticket history as resources, reply_to_ticket and escalate_ticket as tools, and /triage_ticket as a prompt that loads the right resources and asks the model to classify. Prompts seed; resources fill in the situation; tools change the world.

The temptation, once you see how flexible the primitives are, is to push everything through one. You can fake resources with read-only tools, fake tools with prompts that nudge the model into outputting commands, fake prompts with resources containing instructions. Each compresses the design space and loses something. Resources you faked as tools cannot be cached, subscribed to, or inlined into a prompt expansion. Tools you faked as prompts cannot be authorized at the call site and have no structured output channel. The primitives are not arbitrary; they are factored so the host knows how to treat each safely. Honoring the factoring is part of the protocol's contract.

Worth holding onto: the three primitives are factored by intent, not by convenience. Resources for safe browse, Prompts for transparent scaffolds, Tools for consequential action. Tool descriptions are the highest-leverage prose on the entire MCP surface — they are what the model reads to choose. And the order in which a server's primitive surfaces stabilize matters: settle URIs first, tools second, prompts last.

What Chapter 3 sets up

You have walked the server side of the bargain. A server exposes Resources, Prompts, and Tools, each with its own schema, lifecycle, and error model. The discipline is choosing the right primitive for each thing the server can do, naming and describing them carefully, and resisting overload. But MCP is not a one-way street. A host can also expose capabilities back to the server — and that is where the protocol's most interesting and most security-sensitive design choices live.


Next — Chapter 4: Client Primitives — Sampling, Roots, Elicitation. The inverse surface — what the host gives back to the server — and the security implications of every capability handed back across the trust boundary.

Want the full picture? The book walks each primitive with annotated server implementations, develops the composition patterns (aggregator servers, progressive disclosure, server categories) in depth, and treats schema versioning with the operational discipline it deserves. View LLM Primer IV on Amazon →

SHO
SHO
CTO of Receipt Roller Inc., he builds innovative AI solutions and writes to make large language models more understandable, sharing both practical uses and behind-the-scenes insights.