Skip to main content
← Back to Articles
mcpspecrootssamplingelicitationarchitecture2026

MCP Roots, Sampling, and Elicitation Explained (2026 Spec Changes)

What MCP's roots, sampling, and elicitation primitives actually do, plus the 2026-07-28 spec deprecation that changes how servers should use them going forward.

By Web MCP Guide•September 12, 2026•11 min read

Most MCP explainers stop at tools, resources, and prompts — the three primitives a server exposes. There's a second set that runs the other direction: roots, sampling, and elicitation, which the client exposes to the server. If you've only worked with the first three, this is the half of the protocol you haven't touched yet, and as of the 2026-07-28 spec revision, it's also the half that just got restructured.

This page covers what each of the three actually does, a real config example for the one you're most likely to use, and the deprecation that changes how you should think about all three going forward. For the server-side primitives, see Tools vs Resources vs Prompts. For the transport layer these primitives ride on, see MCP Architecture Deep Dive.

Why These Three Exist as a Separate Category

Tools, resources, and prompts all flow from server to client — the server declares what it offers, the client (or the AI on the client's behalf) decides whether to use it. Roots, sampling, and elicitation flow the other way. They're things the client offers to the server, or capabilities the server can request from the client, during a session:

  • Roots — the client tells the server which parts of the filesystem it's allowed to look at

  • Sampling — the server asks the client's AI model to generate a completion on the server's behalf

  • Elicitation — the server asks the client to collect additional input from the human user mid-task
  • All three exist because a well-behaved MCP server shouldn't assume unrestricted filesystem access, shouldn't need its own LLM API key, and shouldn't have to guess when it's missing information it needs from the user. They're the client-side half of the protocol's trust model.

    Roots: Telling the Server Where It May Look

    Roots are URIs — almost always file:// paths — that a client exposes to a server to define the filesystem boundaries the server should operate within. If you connect a filesystem-capable server to a project at /Users/alice/projects/myapp, the client can declare that path as a root, which is effectively the client saying "you may look inside this folder, and nowhere else on this machine."

    A server that supports roots can call roots/list to ask the client what boundaries it's working within, and the client can send a notifications/roots/list_changed notification if the user changes which folder is open (switching projects in an IDE, for example).

    The detail worth knowing before you rely on this for anything security-sensitive: roots are an honor-system boundary, not an enforced sandbox. The client declares the root and a well-behaved server respects it, but nothing at the protocol level stops a server from reading a path outside the declared root if its own code doesn't check. If you need an actual hard boundary — not just a declared one — that has to come from OS-level isolation (a container, a restricted service account, filesystem permissions) on top of roots, not instead of checking roots at all. Roots communicate intent and scope between a well-behaved client and a well-behaved server; they aren't a substitute for process isolation with an untrusted one.

    Sampling: Servers Borrowing the Client's Model

    Sampling lets an MCP server ask the client to run a completion through whatever LLM the client's host application has configured, via a sampling/createMessage request, and get the generated text back as the result. The server sends a prompt (and optionally hints about model preferences, temperature, or max tokens), the client's host — Claude Desktop, Cursor, whatever's on the other end — decides whether to honor the request, picks or confirms the actual model, and returns the completion.

    The reason this exists: it lets a server author ship model-independent code. A summarization server, for instance, doesn't need to bundle its own OpenAI or Anthropic SDK, manage its own API key, or hardcode a specific model — it asks the client to do the generation and gets a result back. The client stays in control of cost, which model actually runs, and whether the request is even approved in the first place; a host application is expected to surface sampling requests to the user rather than silently auto-approving them, precisely because an uncontrolled server-initiated LLM call is a cost and prompt-injection surface if it isn't gated.

    In practice, sampling support has been inconsistent across clients — plenty of hosts implement tools and resources fully but don't implement the sampling side of the spec at all, so a server that depends on it should degrade gracefully (or clearly document the requirement) rather than assuming every client honors sampling/createMessage.

    Elicitation: Servers Asking the Human a Question

    Elicitation lets a server pause mid-task and request additional information directly from the user, through the client, via an elicitation/create request with a JSON schema describing the shape of the answer it needs. This is the mechanism behind things like a deployment tool that asks "which environment — staging or production?" before it acts, or a booking server that asks for a missing date, instead of the AI model guessing or the tool call failing outright with a validation error.

    Without elicitation, a server with an incomplete tool call either has to fail loudly, ask the AI to guess (and risk a wrong guess for something that matters, like an environment or a destructive confirmation), or over-specify every possible parameter up front and hope the AI fills them all in correctly. Elicitation gives it a third option: a structured mid-flight question, answered by the actual human, that becomes part of the tool call.

    The 2026-07-28 Spec Change: Roots, Sampling, and Logging Are Deprecated

    This is the part that makes this page worth writing in September 2026 rather than a year ago: the 2026-07-28 MCP specification formally deprecated roots, sampling, and logging as standalone protocol features, under proposal SEP-2577. They still work — the spec commits to keeping them functional for at least twelve months from the deprecation date — but new server and client implementations are told not to adopt the old standalone RPC shape going forward.

    What's actually changing under the hood: the previous design relied on constantly-open bidirectional streams so either side could send a request at any time. The 2026-07-28 spec moves toward a stateless core built around Multi Round-Trip Requests (MRTR), which removes the need for that always-open channel. The standalone RPC methods (sampling/createMessage, roots/list, and the push-style elicitation/create) are being phased out as separate calls, but the underlying payload shapes aren't disappearing — CreateMessageRequest, ListRootsRequest, and ElicitRequest survive, now embedded inside an InputRequiredResult.input_requests structure that a client handles through the same callback pattern it already uses. Functionally, a client that supports sampling today will keep supporting it; the wire-level mechanics of how the request arrives are what's changing.

    Worth noting: elicitation itself is not on the deprecated list — SEP-2577 names roots, sampling, and logging specifically. Elicitation's push-style elicitation/create call is affected by the same MRTR restructuring, but the capability isn't being deprecated the way roots and sampling are.

    The legacy HTTP+SSE transport got a similar treatment in the same spec cycle — officially deprecated with a year-long offramp, not removed outright. If you're building a new server or client today, that's the pattern to notice: the 2026-07-28 revision is broadly moving MCP away from long-lived bidirectional connections and toward a request/response model that's easier to run behind standard HTTP infrastructure (load balancers, serverless functions, standard proxies) without needing sticky connections.

    What This Means If You're Building Something Today

    If you're implementing a server that needs sampling or elicitation right now, use them — they still work, and the deprecation clock gives you a defined runway, not an immediate breaking change. What you shouldn't do is treat the current standalone RPC shape as the long-term target to optimize around. When you pick an SDK, prefer one that's tracking the current spec revision (check the SDK's changelog against 2026-07-28 rather than an older dated spec), since the SDK maintainers are the ones absorbing the MRTR migration so your server code mostly doesn't have to.

    If you're implementing roots specifically, remember the honor-system caveat above regardless of which wire format carries the request — declaring a root communicates intent to a cooperating server, it does not enforce a boundary against a malicious or buggy one. Pair it with real filesystem permissions or container isolation if the server is running code you don't fully trust.

    Frequently Asked Questions

    Q: Are roots, sampling, and elicitation the same as tools, resources, and prompts?
    A: No — they're the other half of the protocol. Tools, resources, and prompts are declared by the server and consumed by the client. Roots, sampling, and elicitation flow from the client to the server (or are requested by the server from the client): roots define what a server may access, sampling lets a server borrow the client's LLM, and elicitation lets a server ask the user a question mid-task.

    Q: Does a root actually stop a server from reading files outside it?
    A: Not by itself. Roots are a client-declared boundary that a cooperating server is expected to respect, but nothing in the protocol enforces it against a server that ignores the declaration. Treat roots as a scope signal between trusted parties, and add OS-level sandboxing if the server isn't fully trusted.

    Q: Are roots, sampling, and elicitation being removed from MCP?
    A: Roots, sampling, and logging were deprecated (not removed) in the 2026-07-28 spec under SEP-2577. They're guaranteed to keep working for at least twelve months from that date. New implementations are steered toward the newer Multi Round-Trip Requests pattern instead of the original standalone RPC calls. Elicitation itself isn't on the deprecated list, though its request format is affected by the same MRTR restructuring.

    Q: Do most MCP clients actually support sampling and elicitation?
    A: Support is uneven. Tool and resource support is close to universal across clients at this point; sampling and elicitation support varies by host application and has historically lagged behind. If your server depends on either, check the specific client's documentation rather than assuming support, and design a fallback path for clients that don't implement them.

    Q: What replaces the standalone sampling/createMessage and roots/list calls?
    A: The 2026-07-28 spec embeds their payload types inside an InputRequiredResult.input_requests structure as part of the move to a stateless, Multi Round-Trip Requests model, rather than requiring a persistently open bidirectional stream. The data your server sends and receives is functionally the same; the transport-level mechanics of the request are what changed.

    Related Guides


  • MCP Tools vs Resources vs Prompts

  • MCP Architecture Deep Dive

  • How to Build Your First MCP Server

  • Fix MCP Error -32000: Connection Closed

  • Related guides