How do you keep MCP sampling approval prompts from being rubber-stamped by users?
answer
- Fewer decisions, each worth making
- Approve an exchange, not a message
- Budget per server beats a click per call
- A summary is not the prompt
- The strongest control is not offering it
basics
~20 sAsk less often and ask better. Approve an exchange rather than every message, attach a per-server token budget the user can reason about, show what actually changed since the last approval, and make refusing free — which in MCP it is, since declining is just not retrying.
solid answer
~50 sA dialog that appears on every model call trains people to click through it, so the design goal is fewer, more meaningful decisions. Practical shape: the user approves a *server* and an *exchange* with an explicit budget and iteration cap, the host continues automatically inside those limits, and it re-prompts only when a limit is about to be crossed or the request materially changes. Show the real prompt text, the server identity the host derived from its own configuration rather than the untrusted `io.modelcontextprotocol/serverInfo`, and what is new relative to the last approval. Log every approved request so unattended runs can be audited after the fact. Because MCP cannot enforce any of this — the host is the enforcement boundary — this is a product decision, and for many deployments the right answer is not to advertise the `sampling` capability at all, which is consistent with its deprecation in revision 2026-07-28.
go deeper
Understand that a person can approve or refuse a sampling request, and that asking too often makes people stop reading. Recognise rubber-stamping as a real risk, not a theoretical one.
Explain why the unit of consent should be an exchange with a budget rather than a single completion, and that MCP itself cannot enforce any of it — the host application is where the gate lives.
Describe a shipped design: trust tiers per server, a diff of what changed since the last approval, budget and iteration caps, identity taken from host configuration rather than untrusted serverInfo, and an audit log for unattended runs.
Own the decision of whether to offer sampling at all. Weigh the cost of a genuinely non-fatiguing consent experience against a feature deprecated in 2026-07-28, and be able to defend either investing in it or declining the capability outright.
## The failure mode being designed against MCP's sampling guidance asks the client to let a user review a server's prompt before the model runs and review the completion before it is returned. Implemented naively — a modal per request — this degrades within minutes of real use. Users approve reflexively, and a reflexive approval is worse than no approval, because the system now records consent that was never given in any meaningful sense and everyone downstream believes a human checked. So the question is not "how do we prompt" but "how many decisions can a person actually make well, and what should each one be about". ## Make the unit of consent bigger than a message A single completion is the wrong unit. It is too small for the user to have an opinion about and too frequent to sustain attention. The unit that works is an **exchange with declared limits**: "this server wants to use your model for this operation, up to N round trips and a stated token budget." One decision, made with the information that matters, covering everything that follows inside those bounds. Crossing a bound is what brings the human back. This maps cleanly onto the 2026-07-28 mechanics. Because server-initiated requests were removed, every step of a sampling exchange is the client re-issuing its own request — so the host is already the loop driver and can stop at any boundary it chooses. And because declining is expressed by simply not retrying, aborting is free: there is no error to construct, no cleanup handshake, no penalty for saying no. ## Make each prompt carry decision-relevant information When you do ask, show: - **The actual prompt text**, not a summary. A summary is a second model's opinion of what the first one was asked; the point of review is to see what is really being sent. - **What changed** since the last approval for this server. A diff is scannable; a wall of text is not. If nothing changed, that itself is the useful signal. - **Server identity you can trust.** Use the host's own configuration entry for the server. Revision 2026-07-28 is explicit that `io.modelcontextprotocol/serverInfo` is self-reported and untrusted, so a friendly name from the server is not an identity claim. - **Cost so far** in the current exchange and against the server's budget, so the decision is quantitative rather than vibes. - **Both directions.** The completion returning to the server is the data-egress half of the feature and deserves its own review step, at least for servers that are not fully trusted. ## Tier trust instead of treating all servers alike Different servers earn different defaults: a locally developed server may run inside a generous budget without prompting; an unfamiliar remote one may be restricted to a small budget and prompted every time; some are simply denied sampling. Tiering is what makes prompting rare enough to be meaningful. It should be explicit configuration, revocable, and visible — never an implicit "you approved this once, so it is trusted forever". ## Design for unattended runs honestly A great deal of MCP usage is not interactive. In batch or agent contexts, there is no human to prompt, and a system that silently auto-approves in that mode has quietly removed the control while keeping the appearance of it. Better: make unattended mode a distinct policy where sampling either runs inside a hard pre-authorised budget or is refused outright, and where every request is logged for after-the-fact review. Retrospective audit is a legitimate control when synchronous consent is impossible — but only if someone actually reads it, so pair it with alerting on budget anomalies. ## Accept the protocol's limits None of this is enforceable on the wire. MCP cannot make a host draw a dialog, and no field in a response proves that one appeared. The specification's consistent position is that the host is the enforcement boundary. That is a governance fact, not a gap to be closed with cleverness: if you do not control the host, you do not control sampling consent, and your remaining lever is which servers are installed at all. ## The strategic option Sampling is deprecated as of revision 2026-07-28 — deprecated features remain for at least twelve months, new implementations should not adopt them, and the earliest removal is the first revision released on or after 2027-07-28. The migration guidance is for servers to integrate directly with LLM provider APIs. For an organisation weighing the cost of building a genuinely good approval experience against a feature on its way out, not advertising the `sampling` capability is a defensible and often correct decision. Saying so — rather than designing an elaborate consent UI for a deprecated feature — is the answer that shows judgment.
- What is a legitimate control when there is no human present at all?Pre-authorisation plus audit. Unattended mode should be an explicit policy where sampling either runs inside a hard, pre-agreed budget per server or is refused outright, with every request and completion logged. Retrospective review only counts as a control if someone reads it, so pair the log with alerting on budget or volume anomalies rather than treating the log itself as consent.
- Why not just show a friendly server name from the response metadata in the dialog?Because it is self-reported. Revision 2026-07-28 states plainly that `io.modelcontextprotocol/serverInfo` is untrusted, so a server can name itself anything, including something that impersonates a server the user trusts. The identity shown to a user making a security decision must come from the host's own configuration entry for that server.
- Given sampling's deprecation, is building a good approval UI for it worth the effort?Often not. Sampling was deprecated in revision 2026-07-28 with a migration to direct LLM provider integration, and deprecated features are removable from the first revision on or after 2027-07-28. Many hosts get a better return by not advertising the `sampling` capability and putting the same effort into the consent gate for tool calls, which is not going away.
saying these in an interview costs you the question
- Adds a modal per completion and calls it consent
- Treats one approval as permanent trust for a server
- Shows a model-written summary instead of the real prompt
- Displays the server's self-reported name as its identity
- Auto-approves silently in unattended mode