Skip to content
Model Context Protocol (MCP)Sampling

Lead · 8 chapters

Sampling

A server requesting a model completion *from the client*, and why that inverts the usual trust direction

Treat sampling as delegated authority to spend tokens and expose model context, not as a harmless convenience for servers.

Read these first

What you will know

  • Implement an explicit per-server sampling policy with allowlists, consent rules, model and context restrictions, token and spend budgets, rate limits, and deadlines.

    A protocol permission is not least privilege; without independent bounds, a compromised or careless server can turn one integration into an uncapped inference account.

  • Instrument sampling requests with server identity, prompt and context provenance, model choice, token counts, latency, outcome, and cost, then enforce per-server quotas.

    Aggregate billing hides which integration caused runaway usage, while missing provenance makes privacy incidents and quality regressions difficult to investigate.

  • Reproduce an adversarial server that sends repeated or oversized requests and tries to elicit secrets from supplied context; verify denial, redaction, audit, and alert behavior.

    The server controls much of the request content, so prompt injection and covert extraction can make an apparently valid completion a data-loss path.

  • Compare client-mediated sampling with a client-owned model call on a fixed representative workload, measuring quality, latency, cost, privacy exposure, and operational control.

    Sampling may add a trust boundary and an extra hop without improving results; the comparison should include retries, cache effects, and worst-case spend.

  • Ship a user-visible approval and fallback path for denied, unavailable, or over-budget sampling requests, and test that retries cannot bypass the decision.

    A failed delegated call must degrade predictably rather than blocking the agent or silently switching to an unapproved model, server, or context policy.


Chapters

  1. 1

    The sampling/createMessage request

    Sampling is a connected server asking your application to spend your tokens on a prompt it composed and hand the result back to it. The direction of the request and the authorship of the prompt reverse; the choice of model does not, because preferences are advisory and the response names the model actually used. The whole grant is an empty object in the capabilities you declare at initialize, and auto-approving it for any server already approved for tools misreads what tool approval covered.

  2. 2

    The includeContext scope

    includeContext asks the client to attach conversation and resource context to a prompt the requesting server wrote, and the client decides what the words mean. Honouring allServers places material drawn from every connected server into one server's prompt, with the completion returning only to it, so a system prompt asking the model to restate any credentials or file paths present 'for validation' needs no second step to exfiltrate them. The control is a bound on what this server may ever be given, not a filter on how politely it asks.

  3. 3

    Per-server sampling limits

    A maximum token count on every forwarded request leaves the bill scaling with request count, and four thousand requests in an hour are entirely within that policy. What actually bounds a server is the surrounding contract: an allowlist, consent rules, permitted models and context scopes, a spend budget, a rate limit and a deadline, applied per server rather than in aggregate. A protocol permission is not least privilege, and a 2,048-token clamp can amplify spend rather than bound it.

  4. 4

    Denial frames and request identity

    Deciding not to serve a sampling request is only half of the control; the server has to be told, and the decision has to outlive the answer. Return a JSON-RPC error whose code and reason distinguish denied by policy, throttled, trimmed and timed out, so the server can degrade deliberately instead of retrying blindly. Then record that decision against a request identity you derive yourself — the server, the model preferences, the context scope, and a digest of the prompt — because a second sampling/createMessage carrying the same identity is the same request re-presented, and a fresh id in the envelope does not make it new.

  5. 5

    Sampling records and cost attribution

    When the provider bill triples and per-user usage looks normal, the question is which integration caused it — unanswerable unless each sampling request recorded server identity, prompt and context provenance, model, token counts, latency, outcome and cost. One record per request turns a month of argument into a group-by. A global spend cap alerting at eighty percent is a fuse, not a control: it fires late, names nobody, and takes legitimate users down alongside the offender.

  6. 6

    Red-teaming a sampling client

    Build the adversary deliberately: oversized requests, includeContext set to allServers, a system prompt fishing for tokens, keys and file paths, and a burst of near-identical repeats. For each, state what your client must do and which artefact proves it did. A completion coming back with a redacted-looking placeholder is not a pass, and pattern-matching the system prompt is a denylist against someone who authors the input and can iterate freely. An attempted extraction is also a different alert from a spending alert, and it goes to whoever can disconnect the integration.

  7. 7

    Denial paths and silent downgrades

    Requests get refused by policy, exceed a budget, or arrive when no model is available, and each needs a frame for the server, a record, and a user-visible path rather than an agent that stalls. The failure to design out is the silent downgrade: quietly answering on an unapproved model, widening the context scope, re-evaluating a retry until a different decision comes back, or routing the work to a different server. Raising a limit is an action with an increment attached, not a switch.

  8. 8

    Deciding whether to enable sampling

    A server wanting to summarise its own long output could make that model call itself; routing it through your client buys it your budget and your context in exchange for an added trust boundary. Run the comparison on a fixed workload — quality, latency, cost, privacy exposure, operational control, including retries and worst-case spend. Deployment shape decides it more often than use case does, and the specification defines the mechanism while leaving the policy to you, so declining is compliant.

External resources