DS DevShelfHub Projects · AI tools
Tutorials / MCP / Reference / Interfaces / SamplingMessage
Interface client-features modelcontextprotocol/types

SamplingMessage

By DevShelfHub

One message in a sampling conversation.

What is SamplingMessage?

SamplingMessage is the atomic unit of conversation history passed to a host LLM during an MCP sampling request. It mirrors the role/content envelope found in OpenAI-compatible and Anthropic chat APIs, giving MCP servers a familiar structure when they need the client to perform an inference call on their behalf. Each message carries exactly one role — either "user" or "assistant" — and one content block, making the schema intentionally minimal and easy to validate. Within the MCP message flow, SamplingMessage instances appear inside a CreateMessageRequest as the messages array. The server constructs this array to represent the conversation so far, the client (typically Claude Desktop or a similar host) prepends its own system prompt and appends any model-preference hints, then forwards the assembled context to the underlying LLM. This separation means the server never has direct access to the client's system prompt, which is a deliberate privacy boundary in the protocol design. The content block type (SamplingMessageContentBlock) is a discriminated union covering TextContent, ImageContent, AudioContent, ToolUseContent, and ToolResultContent. The tool-bearing variants enable agentic loops where a server drives multi-turn tool-call cycles entirely through the sampling primitive. AudioContent was added in a later revision of the spec, so older SDK versions may not deserialize it gracefully — always check SDK release notes before relying on audio payloads in production.

When to use

Inside CreateMessageRequest.params.messages.

When NOT to use

Outside sampling — use PromptMessage in prompt results.

Notes

Single content block per message

Unlike the Anthropic Messages API, where a message's content field accepts an array of blocks, SamplingMessage allows exactly one SamplingMessageContentBlock per message. If you need to interleave text and an image in a single turn, you must split them into consecutive messages with the same role, or pack them into a single TextContent string. Violating this constraint causes validation failures in strict SDK implementations.

ToolUseContent enables agentic loops

Servers that need multi-turn tool-call cycles can alternate ToolUseContent (role: assistant) and ToolResultContent (role: user) messages inside the same sampling request. This lets a single CreateMessageRequest encode an arbitrarily deep reasoning trace without the server needing its own inference stack. Keep these arrays short in practice — most hosts impose a token budget on the full messages array.

Image and audio payload size limits

ImageContent and AudioContent embed data as base64 strings, which means large media blobs balloon the JSON payload sent over the transport. SSE and stdio transports both have practical frame-size limits; audio above roughly 30 seconds often exceeds what default configurations can handle. Prefer passing a URI reference when the host supports it, and document your server's media constraints clearly.

Role ordering is not enforced by the schema

The SamplingMessage schema does not mandate strict user/assistant alternation, but many LLM backends will reject or misinterpret sequences with consecutive same-role messages. Always validate your messages array before passing it in a CreateMessageRequest, especially when constructing history from tool-loop replays where two assistant turns can appear back-to-back.

SDK deserialization of newer content types

AudioContent was introduced after the initial sampling specification stabilized, so TypeScript SDK versions below 1.1 and Python SDK versions below 1.2 will throw on unknown discriminant values rather than falling back gracefully. Pin your MCP SDK version and set an explicit protocol version in your server's initialization handshake to avoid silent deserialization errors when clients and servers are on mismatched releases.

Fields

Field Type Required Purpose
role 'user' | 'assistant' yes Who is speaking.
content SamplingMessageContentBlock yes Text/image/audio/tool block.

Examples

User message

json
{ "role": "user", "content": { "type": "text", "text": "Hello" } }

Common mistakes

❌ Using role:'system'

✅ Use systemPrompt at the request level — messages are user/assistant only.

Related

SamplingMessage FAQ

What is SamplingMessage in the MCP protocol?

SamplingMessage is an MCP interface type that defines the structure of protocol data exchanged between MCP clients and servers. It is part of the Model Context Protocol's JSON-RPC 2.0 message schema.

Which package provides the SamplingMessage type?

SamplingMessage is defined in the modelcontextprotocol/types package of the MCP TypeScript SDK. Equivalent types are available in the Python, Kotlin, Go, Ruby, and C# SDK implementations.

When should I use SamplingMessage in my MCP implementation?

Use SamplingMessage when your MCP host, client, or server implementation needs to work with this protocol structure. Refer to the When to use section above and the MCP specification for authoritative guidance.

What fields does SamplingMessage contain?

See the Fields table on this page for a complete list of fields in SamplingMessage, their types, whether they are required or optional, and their purpose.

Where can I find more MCP interface documentation?

The complete MCP API reference on DevShelfHub documents all MCP interfaces, methods, and notifications. Visit the MCP API Reference index to browse all types.