← Back to blog
MCP·September 11, 2026·8 min read

MCP Sampling: How a Server Asks the Client's Model to Think for It

Tools and resources get all the attention in MCP, but sampling is the primitive that inverts the relationship — letting a server without its own model borrow the client's LLM through a two-gate approval flow.

MCP Sampling: How a Server Asks the Client's Model to Think for It

Most people who have built or used an MCP server know exactly one primitive: tools. You expose a function, the client's LLM decides to call it, the server runs some code and returns a result. A smaller group knows resources — the read-only data a server can expose for the client to pull into context. Almost nobody has touched sampling, and that's a shame, because it's the one primitive that inverts the whole relationship: instead of the client's model calling the server, the server calls back into the client's model.

The primitive nobody uses

The Model Context Protocol splits its capabilities cleanly by which side owns them. Servers own tools, resources, and prompts — the things a host application can pull from or invoke. Clients own roots (which filesystem locations a server is allowed to see) and sampling (the ability to let a server request an LLM completion). That second one is easy to miss because it doesn't fit the mental model most people build from their first MCP integration: "server has data and functions, client has the brain."

Sampling breaks that assumption on purpose. A server can send a sampling/createMessage request back through the client, asking it to run a chat completion — with a system prompt, message history, and model preferences the server supplies — and hand back the result. The server never touches an LLM API key, never picks a specific model, and never sees which provider actually served the request. It just asks, and the host decides whether, how, and with what to answer.

Why a server would want this at all

Consider a document-processing MCP server that indexes a large codebase or file share. A tool call like search_files is deterministic — grep-shaped, no LLM required. But suppose the same server wants to offer summarize_directory, condensing forty files into a two-paragraph overview before handing it back. That's not a job for string matching. The server needs a model.

It has two options. It can bundle its own API key, pick a provider, and eat the cost and latency of a second, invisible LLM call on every request — which means every user of that server is silently paying (in tokens, in trust, in a second vendor relationship) for a model choice they didn't make. Or it can ask the client: "you already have a model connected and a user watching this conversation — you run the completion, I'll just supply the prompt." Sampling is the second option, formalized as a protocol primitive.

This is also why a purely deterministic utility server has no use for sampling at all. A server exposing something like a Luhn checksum validator or an IBAN mod-97 checker doesn't need to think — it needs to return a byte-exact function result, and tools are the right primitive for that. Sampling exists for the opposite case: servers that have context but not judgment, and want to borrow judgment from whoever is already holding the conversation.

The mechanics of a sampling request

A sampling/createMessage request looks a lot like a normal chat completion call, with one deliberate omission: no model name.

{
  "method": "sampling/createMessage",
  "params": {
    "messages": [
      {
        "role": "user",
        "content": {
          "type": "text",
          "text": "Summarize the purpose of these 40 files in two sentences: ..."
        }
      }
    ],
    "modelPreferences": {
      "hints": [{ "name": "claude-3-5-sonnet" }],
      "costPriority": 0.3,
      "speedPriority": 0.5,
      "intelligencePriority": 0.7
    },
    "systemPrompt": "You are a concise codebase summarizer.",
    "maxTokens": 300
  }
}

The server can hint at a model family it thinks would do well, but it can't demand one, because it has no idea which providers the host has configured, what the user's plan covers, or what today's cost budget looks like. Instead it expresses intent through three sliders — cost, speed, intelligence priority — and leaves model selection entirely to the client. This is the same reasoning behind why MCP tool schemas describe capabilities rather than implementations: the protocol assumes the two sides don't share infrastructure, only a contract.

The approval gate is not optional

Here's the part that matters more than the wire format: the spec requires a human in the loop on both ends of a sampling call. The client is expected to show the user what the server wants to ask the model before sending the request, and show the user the model's response before it goes back to the server. This isn't a nice-to-have UX suggestion — it's the only thing standing between "useful protocol primitive" and "a remote server gets a blank check to run arbitrary completions on someone else's model bill and read back whatever comes out."

Think about what sampling would look like without that gate. A compromised or just poorly-written MCP server could quietly send sampling/createMessage requests stuffed with instructions to exfiltrate context the user never intended to share, or burn through a user's token budget on a loop of pointless completions. The approval step turns sampling from "the server can think for itself" into "the server can ask, and a human or a policy decides whether that ask is reasonable" — the same trust boundary that already governs whether a tool call is allowed to run.

Where sampling sits in the request flow

The diagram below contrasts an ordinary tool call, where control flows one direction, with a sampling round-trip, where the server borrows the client's model mid-conversation.

User Client / Host (LLM) MCP Server

Ordinary tool call prompt tools/call result answer

Sampling round-trip "summarize this dir" tools/call

sampling/createMessage server has no model human approval gate 1 client runs completion LLM chosen by client human approval gate 2 completion result tool result

The two approval gates are the load-bearing part of the diagram. Everything else — the JSON-RPC shape, the model-preference hints — is plumbing around those two checkpoints.

Why adoption is still thin

If sampling sounds like it should be everywhere, there's a reason it isn't yet: it's expensive for a host application to implement correctly. A tool call just needs a permission prompt ("allow this server to run search_files?"). A sampling implementation needs to render an arbitrary prompt the server constructed, let the user see and edit it, run the completion against a model the host is willing to pay for, and then show the result before it's released back to a server the user may not fully trust. That's a meaningfully bigger UI surface than a single "Allow" button, and most MCP host applications have prioritized shipping tool support first. So in practice, plenty of production MCP servers are written as if sampling doesn't exist, because for most clients today, it effectively doesn't.

That has a direct design consequence: if you're building an MCP server and want a feature like the directory-summarizer above, don't assume sampling will be available. The safer pattern is to support it opportunistically — try sampling/createMessage, and if the client doesn't declare that capability during initialization, fall back to a deterministic response (or to the server's own API key, if you've decided that tradeoff is acceptable) rather than a hard failure.

What this means if you're building on MCP

  • Sampling isn't a shortcut around needing a model. It's a way to avoid a server needing its own model relationship, at the cost of depending on a client capability that isn't universal yet.
  • Cost accounting flows to the client, not the server. If you're evaluating an MCP server that leans on sampling, remember the token bill lands on whoever's model is running the completion — the host, not the server author. That's a meaningfully different trust and pricing model than a server that calls its own hosted API.
  • The two approval gates are the actual security boundary, not the JSON-RPC schema. A host that skips them isn't implementing sampling — it's giving a remote server unsupervised access to its model.
  • Tools remain the right primitive for anything deterministic. An agent calling a REST API or an MCP tool for something like format validation, checksum computation, or unit conversion shouldn't route through sampling at all; that's paying LLM latency and cost for a problem that doesn't need judgment.

Sampling is the clearest evidence that MCP was designed around a specific philosophy: keep servers dumb and data-shaped, keep the one LLM the user is actually paying for and watching in a single place, and make any request to "borrow" that model an explicit, inspectable event rather than something that happens silently inside a server you didn't write.

#mcp#model-context-protocol#ai-agents#sampling#agent-architecture#tool-calling

Related reading

MCP
What Actually Happens Inside an MCP Tool Call
LLM Tool Calling
Most Tool-Calling Failures Are Schema Failures, Not Model Failures
Prompt Engineering
Prompt Engineering for Agents Is a Different Discipline Than Prompt Engineering for Chat