Who this is for and what you will be able to do
This guide explains how MCP sampling works, how a server asks the client's language model for help during a tool call, and how the example is built. It also explains why you should not start new work on sampling. By the end you will understand the request and response flow, know how a client turns sampling on, and know where to go for new implementations [1].
Read this first: sampling is deprecated
Sampling is deprecated in MCP 2026-07-28. It is kept for legacy implementations, and new servers should integrate directly with an LLM provider API [1][2]. The specification keeps sampling for compatibility and says it may be removed in the first revision released on or after July 28, 2027 [1]. The examples may use SDK APIs that implement 2025-11-25 [1].
How sampling works
In legacy implementations, sampling lets an MCP server ask for help from an LLM that the client manages [1]. Take a blog post as an example. The user asks the client to write a post. The client calls a tool on the server. The server sends a sampling request asking for a summary. The client calls the LLM and returns the summary. The server then returns the complete post, with the draft and the summary [1].
What the request and response look like
A sampling request uses the JSON-RPC method sampling/createMessage. Its params include messages, modelPreferences, systemPrompt and maxTokens [1]. modelPreferences is a recommendation, and the user can choose to follow it or change it. systemPrompt gives the LLM its personality and guidance, and maxTokens says how many tokens the task should use [1].
The client sends back a response with the LLM's output. In the example, the client chose the active gpt-5.1 deployment from the server's preference. Because preferences are only recommendations, the client may pick another active deployment when it needs to [1]:
{
"jsonrpc": "2.0",
"id": 1,
"result": {
"role": "assistant",
"content": {
"type": "text",
"text": "Here's your abstract <ABSTRACT>"
},
"model": "gpt-5.1",
"stopReason": "endTurn"
}
}Sampling messages can carry images and audio as well as text. Image content has the type image, base64 data and a mimeType such as image/jpeg. Audio content works the same way with type audio and a mimeType such as audio/wav [1].
Turn sampling on in the client
If you are only building a server, you do not need to do much here. A client enables sampling by declaring it in its capabilities [1]:
{
"capabilities": {
"sampling": {}
}
}Example: a tool that asks the client's LLM for a summary
The example tool is create_blog. It takes a title, some content and a Context argument. It sends a sampling request, waits for the answer, and then returns the result [1]:
@mcp.tool()
async def create_blog(title: str, content: str, ctx: Context[ServerSession, None]) -> str:
"""Create a blog post and generate a summary"""Inside the tool, the example builds the post object, writes a prompt and sends it with ctx.session.create_message and max_tokens=100 [1]:
post = BlogPost(
id=len(posts) + 1,
title=title,
content=content,
abstract=""
)
prompt = f"Create an abstract of the following blog post: title: {title} and draft: {content} "
result = await ctx.session.create_message(
messages=[
SamplingMessage(
role="user",
content=TextContent(type="text", text=prompt),
)
],
max_tokens=100,
)It then stores the abstract and returns it as JSON [1]:
post.abstract = result.content.text
posts.append(post)
# return the complete product
return json.dumps({
"id": post.title,
"abstract": post.abstract
})The __main__ block starts the server with mcp.run(transport="streamable-http"). Run it with python server.py [1].
Test it in Visual Studio Code
Start the server, then add it to *mcp.json* as a server of type http at http://localhost:8000/mcp [1]:
"servers": {
"blog-server": {
"type": "http",
"url": "http://localhost:8000/mcp"
}
}Then type a prompt such as the one in the example [1]:
create a blog post named "Where Python comes from", the content is "Python is actually named after Monty Python Flying Circus"The first time you test sampling, you must accept an extra dialog before the usual dialog for running a tool appears [1]. VS Code lets you choose which models GitHub Copilot may use for sampling under "Configure Model Access", and "Show Sampling requests" shows recent requests [1].
Limits and common questions
- Sampling is deprecated, so the examples above are for reading and maintaining legacy code [1][2].
- The examples may use SDK APIs that implement
2025-11-25, which may differ from the2026-07-28specification [1]. - The model preference is only a recommendation, so the model that runs can differ from the one named in the request [1].
Next step
For new implementations, call the LLM provider's API directly instead of using sampling [1]. The current status of sampling is in the specification [2].
Adapted from the sampling lesson of Microsoft's open-source course *mcp-for-beginners*[1], released under the MIT License.
Sources
- 1Sampling - delegate features to the ClientMicrosoft mcp-for-beginners (MIT)
- 2Sampling (MCP specification 2026-07-28)Model Context Protocol
Cite this page: MCP sampling. TellWorld, https://www.tellworld.net/practice/practice-mcp-sampling. Updated 2026-11-14