What is the sampling capability, and why does it let a server request completions from the client's LLM?
Quick Answer
Sampling lets an MCP server send a sampling/createMessage request to the client, asking the client's already-configured LLM to generate a completion on the server's behalf, rather than the server needing its own model API key/access. This inverts the usual direction of MCP traffic — normally the client calls the server, but sampling is a server-initiated request. It exists because many servers need some LLM reasoning as part of their own logic (summarizing a large tool result before returning it, deciding how to phrase something) but shouldn't need to manage their own model credentials, incur separate API costs, or assume any specific model provider — they simply borrow whatever LLM the host/user has already set up, with the client staying in control of approving the request and picking the actual model to use.
Detailed Answer
Sampling is the one MCP primitive that flips the normal request direction. Instead of the client always initiating, the server asks the client for something.
Why a server would want this
Imagine an MCP server that processes a large log file and needs a concise natural-language summary before returning it as a tool result. Dumping raw logs back to the model to summarize itself burns context on the client side. Giving the server its own separate LLM API key means extra cost, extra credential management, and ties it to one specific model provider. Instead, the server can just ask: "hey, client, can your LLM summarize this for me?"
// Server -> Client
{"method": "sampling/createMessage", "params": {
"messages": [{"role": "user", "content": {"type": "text", "text": "Summarize these logs: ..."}}],
"modelPreferences": {"intelligencePriority": 0.3, "speedPriority": 0.8},
"maxTokens": 200
}}
// Client -> Server (after the user approves, and the client's LLM generates a completion)
{"result": {
"role": "assistant",
"content": {"type": "text", "text": "3 errors occurred, all related to a database timeout."},
"model": "claude-sonnet-5",
"stopReason": "endTurn"
}}
Why this design instead of "servers just call an LLM API directly"
- No separate credentials or billing for the server to manage. It uses whatever model access the client/user already has.
- Model-agnostic. The server doesn't hardcode a dependency on any specific provider. The client decides which model actually services the request.
- Keeps a human in the loop. Sampling requests go through the client, so the client — and by extension the user — can review, modify, or reject the request before it's ever sent to a model. That matters, since the server is asking to spend the user's model budget and potentially see sensitive conversation context.
The tradeoff
A server using sampling depends on the client actually supporting and approving sampling requests. It's an optional capability, and a client is free to decline. A well-designed server should have a sensible fallback for clients that don't support sampling — returning the raw content, say, or a simpler non-LLM-based summary.