The Model Context Protocol gives you three ways to put a human checkpoint inside an AI agent: elicitation, sampling review, and out-of-band ask-a-human tools such as ping-a-human, the open-source MCP server Startrise maintains. The first two assume someone is watching the client UI; unattended agents need the third. That checkpoint matters more than it sounds: Gartner predicts over 40% of agentic AI projects will be canceled by the end of 2027, and inadequate risk controls are one of the three reasons it names (Gartner, 2025), and a human checkpoint the agent can actually reach is the most direct risk control there is. Every tutorial on page one covers exactly one of the three patterns and skips its core limitation. This post maps all three, quotes the 2025-06-18 spec directly, and ends with the decision rule we use when shipping agents with approval gates for clients. Fair warning on the third pattern: we built it, so that section comes from the maintainer’s chair.
Key Takeaways
- MCP supports three human-in-the-loop patterns: elicitation, sampling review, and out-of-band ask-a-human tools
- Elicitation and sampling review both assume someone is watching the client UI; unattended agents need an external channel
- The spec itself says there “SHOULD always be a human in the loop” for sampling (MCP spec, 2025)
- ping-a-human (MIT) ships pattern 3 today:
npx ping-a-human setup
Why do AI agents need a human checkpoint?
Gartner attributes coming agentic project cancellations to escalating costs, unclear business value, and inadequate risk controls, forecasting over 40% canceled by end of 2027 (Gartner, 2025). Risk controls are the fixable one, and the fix is a checkpoint the agent can reach at the moment of consequence.
Think about the moment that actually worries you. The agent is about to send the email, run the migration, or issue the refund. Everything before that point is reversible. That step isn’t. In our client work, the question is never whether to add a checkpoint there. It’s which mechanism to use, and MCP standardizes three.
The part the single-tool tutorials miss: the three patterns fail in different places. Two of them quietly assume a human is sitting at the client when the question fires. Long-running agents rarely have that audience. Choosing the wrong pattern means an agent that waits forever, or worse, one that stops asking.
What are the three MCP human-in-the-loop patterns?
The 2025-06-18 MCP specification defines two client features with a human checkpoint built in: elicitation, with its three-action response model (accept, decline, cancel), and sampling, where the client mediates every model call (MCP spec, 2025). The third pattern, an out-of-band ask-a-human tool, exists because the first two require an attended client.
| Pattern | Who initiates | Where the human answers | Best for | Breaks when |
|---|---|---|---|---|
| Elicitation | Server, via elicitation/create | A form in the client UI | Collecting structured input in attended sessions | Nobody is at the client |
| Sampling review | Server, via sampling/createMessage | Approval prompts in the client UI | Overseeing what the model is asked and answers | Same attendance problem, plus patchy client support |
| External-channel tool | Agent, by calling a tool | Telegram, Slack, Discord, wherever they already are | Unattended and long-running agents | The human ignores the ping, which is why timeouts matter |
Keep one distinction straight. Patterns 1 and 3 gate what the agent does. Pattern 2 gates what the model is asked. They’re different checkpoints, and production agents often need more than one.
Pattern 1: how does MCP elicitation work?
Elicitation lets a server request structured input from the user mid-interaction: the server sends elicitation/create with a message and a requestedSchema, and the spec deliberately restricts those schemas to flat objects with primitive properties only (MCP spec, 2025). No nesting, no complex types. That constraint keeps the client’s job simple: render a form, collect an answer.
The response model is where the spec earns its keep. Every elicitation resolves to one of three actions, and servers should handle each differently:
- Accept: the user submitted the form, and the response carries their data
- Decline: the user explicitly said no
- Cancel: the user dismissed the request without choosing
The spec also draws a hard trust boundary. Servers “MUST NOT use elicitation to request sensitive information,” and clients are expected to show which server is asking and let users decline or cancel anything (MCP spec, 2025). One more caveat worth knowing before you build on it: the spec flags elicitation as newly introduced, with a design that may evolve in future protocol versions.
Elicitation fits when a human is present and the agent needs a missing parameter: a deploy target, a date range, a yes-or-no with structure around it. The tutorials that rank for this topic stop there, and that’s the problem.
Here’s when it breaks. The request renders inside the client UI. If nobody is looking at Claude Desktop or Cursor when it fires, the agent just waits. An overnight batch job, a scheduled research agent, a pipeline that hits an edge case at 3 a.m.: none of them has an audience. Elicitation can’t reach a human who isn’t already there.
Pattern 2: what is MCP sampling review?
Sampling flips the direction of model access: servers request LLM completions through the client with sampling/createMessage, so the server never needs its own API keys (MCP spec, 2025). The human-in-the-loop part isn’t an add-on here. It’s the spec’s stated design stance.
The exact words matter, so here they are. For trust and safety, the spec says there “SHOULD always be a human in the loop with the ability to deny sampling requests” (MCP spec, 2025). Clients should let users review and edit prompts before they’re sent, and review completions before they’re delivered back to the server. The spec even defines the rejection case: an error like “User rejected sampling request” when the human says no.
Notice what’s being gated, though. This is oversight of model use: which prompts go out, on whose tokens, and what comes back. It is not approval of actions. A human can approve every sampling request an agent makes and still never see the moment it sends the refund, because that’s a tool call, not a completion. Treating sampling review as your action gate is a category error we see in real architectures.
And the attendance problem returns. Review prompts render in the client UI, so an unattended agent gets no reviewer, and client support for sampling remains uneven across the ecosystem. Useful checkpoint, wrong shape for the unsupervised case.
Pattern 3: out-of-band, reaching the human where they already are
The third pattern accepts what the first two can’t fix: sometimes nobody is watching the client, so the checkpoint must travel to the human. ping-a-human’s ask_human tool blocks until the human replies or a timeout elapses, with a 5-minute default, and reaches that human on Telegram (ping-a-human README, 2026).
This is why ask-a-human MCP servers exist as a category. Some route questions through Discord, like KOBA789’s human-in-the-loop server. Some pop local GUI dialogs, like GongRzhe’s Human-In-the-Loop-MCP-Server. Some post to Slack. The channel varies; the pattern is the same. The agent calls a tool, the question lands where the human already is, and the answer flows back as the tool result.
We built and maintain ping-a-human (MIT, on npm, v0.1.6 at the time of writing), so this is the one pattern we can document from the inside. The tagline on ping-a-human.com is the spec in five words: “Let your AI ask a human.” It exposes two tools over stdio:
notify_human: fire-and-forget. Sends a message and returns immediately, for “I finished the job” or “heads up, I’m about to start.”ask_human: sends a question and blocks until the human replies or the timeout elapses. Pass achoicesarray and the options render as tappable Telegram inline buttons, with the tapped value returned to the agent.
Three design decisions carry the real lessons, and none of them appears anywhere on page one for this query.
First, timeouts return a result, not an error. When the 5-minute default elapses, ask_human hands the agent a clean timed-out result instead of throwing (ping-a-human README, 2026). Why? An error looks like a broken tool. A timed-out result is a signal the agent can branch on: fall back to the safe default, retry later, or escalate. Silence from a human is information, and we wanted agents to treat it that way.
Second, choices beat free text. Tappable buttons constrain the answer to values the agent can parse, and a human on a phone taps in seconds. Approval flows live or die on that friction.
Third, stdout is sacred. In a stdio MCP server, stdout carries the JSON-RPC channel, so every diagnostic ping-a-human prints goes to stderr. One stray console.log corrupts the protocol stream. If you build your own server, this rule will save you an evening.
Setup is one command: npx ping-a-human setup walks you through creating a Telegram bot, validates the token, auto-detects your chat id, and prints the exact config block for Claude Desktop, Cursor, or any MCP client (ping-a-human, 2026). Telegram is live today; Discord, Slack, WhatsApp, Signal, email, SMS, and webhooks are listed as coming soon on the public roadmap, and that’s exactly as much as we’ll claim. It lives with the rest of our open-source work.
How do you choose a pattern (or combine them)?
Two of the three MCP checkpoint patterns assume an attended client, so the first question decides most cases: will a human be at the client UI when the question fires (MCP spec, 2025)? Answer that, and the decision tree collapses fast.
- Human at the client, structured data needed: elicitation. It’s purpose-built for collecting a missing parameter mid-flow.
- Governing model access, cost, or content: sampling review. That’s the checkpoint the spec itself mandates with its “SHOULD always be a human in the loop” language.
- Agent runs unattended, or approval must survive nobody watching: external channel, with explicit timeout semantics.
The production reality is less tidy, and that’s fine. Real agent builds combine patterns: elicitation for setup-time input while the developer is present, then an ask-human tool for runtime approvals once the agent is on its own. The patterns gate different things, so stacking them isn’t redundancy. It’s coverage.
Which actions deserve a gate at all is its own decision, about risk tiers rather than protocol mechanics. Our rule of thumb from client work: gate anything irreversible or externally visible, and let the rest flow.
We wrote up which agent actions need an approval workflow separately, tier by tier.
Where this lands in a production agent build
Startrise ships agents with approval gates on consequential actions, a full audit log of every action and decision, and fallback and escalation paths when the agent is unsure, from $3,500 in 2 to 4 weeks, built on Mastra (Startrise AI Agent Development, 2026). The patterns above are how those gates get wired.
In practice, the human-in-the-loop steps go through the messaging apps your team already uses, which is why we built pattern 3 as an open tool rather than a proprietary feature. Our operating principle is the one from our own service FAQ: “Autonomy is earned per-action, not granted globally.” An agent starts with gates on everything consequential and earns autonomy one action at a time, with the audit log as the evidence.
If you’re still upstream of this decision, choosing between a workflow engine and an agent framework, start with n8n vs Mastra. If you want to try the checkpoint itself, npx ping-a-human setup takes about two minutes. And if you’d rather have the whole thing designed, gates, logs, and escalation included, that’s our AI agent development service within AI automation. Tell us what your agent needs permission to do, and we’ll tell you which pattern we’d gate it with.
Questions we actually get
What is a human-in-the-loop MCP server?
An MCP server that gives an AI agent tools to notify a human, or to ask a human a question and wait for the answer before continuing. ping-a-human, for example, exposes notify_human (fire-and-forget) and ask_human (blocks until the human replies or a timeout elapses) and reaches the person on Telegram.
What's the difference between MCP elicitation and an ask-a-human MCP server?
Elicitation prompts the user inside the AI client's own UI, so it only works when someone is watching the session. An external-channel server reaches the human out-of-band on a messaging app they already use, which is what unattended or long-running agents need.
Can MCP elicitation ask for passwords or API keys?
No. The MCP specification says servers must not use elicitation to request sensitive information, and clients are expected to show which server is asking and let users decline or cancel any request.
What happens if the human never replies?
Design for it explicitly. ping-a-human's ask_human has a default 5-minute timeout and returns a clear timed-out result instead of an error, so the agent gets a clean signal to fall back, retry later, or escalate.
Do I need to build a human-in-the-loop server myself?
No. ping-a-human is open source (MIT) and installs with one command: npx ping-a-human setup walks you through creating a Telegram bot and prints the config for Claude Desktop, Cursor, or any MCP client. If you want approval gates designed into a production agent, that's what Startrise's AI agent development service does.