Sampling
specification/2026-07-28/client/sampling
History
specification/2026-07-28/client/sampling First recorded · 677 lines, first recorded
# Sampling ## User Interaction Model ## Tools in Sampling ## Capabilities ## Protocol Messages ### Creating Messages ### Sampling with Tools ### Multi-turn Tool Loop ## Message Content Constraints ### Tool Result Messages ### Tool Use and Result Balance ## Cross-API Compatibility ### Message Roles ### Tool Choice Modes ### Parallel Tool Use ## Message Flow ## Data Types ### Messages #### Text Content #### Image Content #### Audio Content ### Model Preferences #### Capability Priorities #### Model Hints ### System Prompt ### Context Inclusion ### Sampling Parameters ### Result Fields ## Error Handling ## Security Considerations
The first capture of this source. The page was already there, and this is what it said.
# Sampling
<div id="enable-section-numbers" />
<Warning>
**Deprecated**: The Sampling feature is deprecated as of protocol version
`2026-07-28`
([SEP-2577](https://github.com/modelcontextprotocol/modelcontextprotocol/pull/2577)).
Under the [feature lifecycle policy](/community/feature-lifecycle), it remains
in the specification for at least twelve months after this revision's release
before it becomes eligible for removal. New implementations **SHOULD NOT**
adopt it; existing implementations **SHOULD** migrate to integrating directly
with LLM provider APIs. See the [deprecated features
registry](/specification/2026-07-28/deprecated).
</Warning>
The Model Context Protocol (MCP) provides a standardized way for servers to request LLM
sampling ("completions" or "generations") from language models via clients. This flow
allows clients to maintain control over model access, selection, and permissions while
enabling servers to leverage AI capabilities—with no server API keys necessary.
Servers can request text, audio, or image-based interactions and optionally include
context from MCP servers in their prompts.
## User Interaction Model
Sampling in MCP allows servers to implement agentic behaviors, by enabling LLM calls to
occur *nested* inside other MCP server features.
Implementations are free to expose sampling through any interface pattern that suits
their needs—the protocol itself does not mandate any specific user interaction
model.
<Warning>
For trust & safety and security, there **SHOULD** always
be a human in the loop with the ability to deny sampling requests.
Applications **SHOULD**:
* Provide UI that makes it easy and intuitive to review sampling requests
* Allow users to view and edit prompts before sending
* Present generated responses for review before delivery
</Warning>
## Tools in Sampling
Servers can request that the client's LLM use tools during sampling by providing a `tools` array and optional `toolChoice` configuration in their sampling requests. The tool definitions in the `tools` array are scoped to the sampling request — they don't need to correspond to registered tools. This enables servers to implement agentic behaviors where the LLM can call specially designated tools, receive results, and continue the conversation - all within a single sampling request flow.
Clients **MUST** declare support for tool use via the `sampling.tools` capability to receive tool-enabled sampling requests. Servers **MUST NOT** send tool-enabled sampling requests to Clients that have not declared support for tool use via the `sampling.tools` capability.
## Capabilities
Clients that support sampling **MUST** declare the `sampling` capability in
`_meta.io.modelcontextprotocol/clientCapabilities` on each request:
**Basic sampling:**
```json theme={null}
{
"_meta": {
"io.modelcontextprotocol/clientCapabilities": {
"sampling": {}
}
}
}
```
**With tool use support:**
```json theme={null}
{
"_meta": {
"io.modelcontextprotocol/clientCapabilities": {
"sampling": {
"tools": {}
}
}
}
}
```
**With context inclusion support (deprecated):**
```json theme={null}
{
"_meta": {
"io.modelcontextprotocol/clientCapabilities": {
"sampling": {
"context": {}
}
}
}
}
```
<Note>
The `includeContext` parameter values `"thisServer"` and `"allServers"` are
deprecated under the [feature lifecycle
policy](/community/feature-lifecycle#deprecating-a-feature)
([SEP-2596](https://github.com/modelcontextprotocol/modelcontextprotocol/pull/2596));
they will be removed no later than the Sampling feature itself. Servers
**SHOULD** avoid using these values (e.g. can just omit `includeContext` since
it defaults to `"none"`), and **SHOULD NOT** use them unless the client
declares `sampling.context` capability. See the [deprecated features
registry](/specification/2026-07-28/deprecated).
</Note>
## Protocol Messages
### Creating Messages
To request a language model generation during the processing of a client request, servers send an `InputRequiredResult` containing a `sampling/createMessage` request:
**Input request (delivered inside [`InputRequiredResult.inputRequests`](/specification/2026-07-28/basic/patterns/mrtr#inputrequests)):**
```json theme={null}
{
"method": "sampling/createMessage",
"params": {
"messages": [
{
"role": "user",
"content": {
"type": "text",
"text": "What is the capital of France?"
}
}
],
"modelPreferences": {
"hints": [
{
"name": "claude-3-sonnet"
}
],
"costPriority": 0.3,
"intelligencePriority": 0.8,
"speedPriority": 0.5
},
"temperature": 0.1,
"systemPrompt": "You are a helpful assistant.",
"includeContext": "thisServer",
"maxTokens": 100
}
}
```
**Client result (returned inside `inputResponses` on the retried request):**
```json theme={null}
{
"role": "assistant",
"content": {
"type": "text",
"text": "The capital of France is Paris."
},
"model": "claude-3-sonnet-20240307",
"stopReason": "endTurn"
}
```
### Sampling with Tools
The following diagram illustrates the complete flow of sampling with tools, including the multi-turn tool loop:
```mermaid theme={null}
sequenceDiagram
participant Server
participant Client
participant User
participant LLM
Client->>Server: tools/call(id:1)
note right of Server: Server needs more info
Server->>Client: InputRequiredResult(<br/>sampling/createMessage<br/>(messages + tools))
Note over Client,User: Human-in-the-loop review
Client->>User: Present request for approval
User-->>Client: Approve/modify
Client->>LLM: Forward request with tools
LLM-->>Client: Response with tool_use<br/>(stopReason: "toolUse")
Client->>User: Present tool calls for review
User-->>Client: Approve tool calls
Client-->>Server: tools/call(id:2, Return tool_use response)
Note over Server: Execute tool(s)
Server->>Server: Run get_weather("Paris")<br/>Run get_weather("London")
Note over Server,Client: Continue with tool results
Server->>Client: InputRequiredResult(<br/>sampling/createMessage<br/>(history + tool_results + tools))
Client->>User: Present continuation
User-->>Client: Approve
Client->>LLM: Forward with tool results
LLM-->>Client: Final text response<br/>(stopReason: "endTurn")
Client->>User: Present response
User-->>Client: Approve
Client-->>Server: tools/call(id:3, Return final response)
Note over Server: Server processes result<br/>(may continue conversation...)
```
To request LLM generation with tool use capabilities, servers include `tools` and optionally `toolChoice` in the request:
**Input request (Server -> Client, delivered inside `InputRequiredResult.inputRequests`):**
```json theme={null}
{
"method": "sampling/createMessage",
"params": {
"messages": [
{
"role": "user",
"content": {
"type": "text",
"text": "What's the weather like in Paris and London?"
}
}
],
"tools": [
{
"name": "get_weather",
"description": "Get current weather for a city",
"inputSchema": {
"type": "object",
"properties": {
"city": {
"type": "string",
"description": "City name"
}
},
"required": ["city"]
}
}
],
"toolChoice": {
"mode": "auto"
},
"maxTokens": 1000
}
}
```
**Client result (Client -> Server, returned inside `inputResponses` on the retried request):**
```json theme={null}
{
"role": "assistant",
"content": [
{
"type": "tool_use",
"id": "call_abc123",
"name": "get_weather",
"input": {
"city": "Paris"
}
},
{
"type": "tool_use",
"id": "call_def456",
"name": "get_weather",
"input": {
"city": "London"
}
}
],
"model": "claude-3-sonnet-20240307",
"stopReason": "toolUse"
}
```
### Multi-turn Tool Loop
After receiving tool use requests from the LLM, the server typically:
1. Executes the requested tool uses.
2. Sends a new sampling request with the tool results appended
3. Receives the LLM's response (which might contain new tool uses)
4. Repeats as many times as needed (server might cap the maximum number of iterations, and e.g. pass `toolChoice: {mode: "none"}` on the last iteration to force a final result)
**Follow-up input request (Server -> Client, delivered inside `InputRequiredResult.inputRequests`) with tool results:**
```json theme={null}
{
"method": "sampling/createMessage",
"params": {
"messages": [
{
"role": "user",
"content": {
"type": "text",
"text": "What's the weather like in Paris and London?"
}
},
{
"role": "assistant",
"content": [
{
Cut at 300 lines.