[Feature Request] Support for MCP Sampling to leverage Claude Max subscriptions and reduce API costs

Open 💬 58 comments Opened Jun 8, 2025 by mateuszmazurek
💡 Likely answer: A maintainer (ashwin-ant, collaborator) responded on this thread — see the highlighted reply below.

Support for MCP Sampling to leverage Claude Max subscriptions and reduce API costs

Problem

Currently, Claude Code, when acting as an MCP (Model Context Protocol) client, does not support (based on the feature support matrix from https://github.com/modelcontextprotocol/docs/blob/main/clients.mdx) the "sampling" feature of the MCP. This means that any MCP server connected to Claude Code, requiring an LLM inference, must make a direct API call to the Anthropic API.

While many Claude Code users benefit from the nearly unlimited usage provided by a Claude Max subscription, this direct API inference leads to additional "pay-as-you-go" costs for every server-initiated request. This creates an unexpected financial burden and complexity for users who assumed their Max subscription would cover the majority of their Claude usage, including server-side interactions.

Solution

Claude Code should be updated to fully support the MCP "sampling" feature: https://modelcontextprotocol.io/specification/2025-03-26/client/sampling

With sampling support, when an MCP server needs an LLM inference, it would send a sampling/createMessage request to the Claude Code client (the user's instance). This would allow the Claude Code client to:

  1. Utilize the user's existing Claude Max subscription: The inference request would be processed by the user's locally running Claude Code instance, falling under their subscription's usage limits, eliminating the need for the MCP server to manage separate API keys or directly configure access to the Anthropic API.
  2. Provide human-in-the-loop oversight (optional but beneficial): The user could review and approve/edit the prompt before it's sent to Claude, and review the completion before it's returned to the MCP server, leveraging Claude Code's existing interactive capabilities. This enhances transparency and control.
  3. Reduce pay-as-you-go API costs: This would eliminate the need for MCP servers to make direct API calls for inferences, significantly reducing unexpected costs for Claude Max subscribers.

Summary

The MCP "sampling" feature is designed precisely for scenarios where a server requires LLM assistance but wants to delegate the actual inference and associated costs/control to the client. Implementing this feature in Claude Code would align it more closely with the broader MCP philosophy and significantly enhance the value proposition for Claude Max subscribers who integrate Claude Code with custom MCP servers.

This would make Claude Code a more cost-effective and flexible solution for advanced agentic workflows.

View original on GitHub ↗

58 Comments

ashwin-ant collaborator · 1 year ago

@mateuszmazurek We're looking into this! Can you share more about the server you're using or envisioning, and what use cases you're imagining?

mateuszmazurek · 1 year ago

@ashwin-ant I don't have any specific MCP server in mind. Let's be honest, almost none of them support sampling yet because virtually no sensible MCP client supports it, creating a bit of a Catch-22. However, I believe now that VS Code has implemented it, more and more servers will start using it since it's a win-win for users. I know that @eyaltoledano, the creator of Task Master, is very positive about this, which he mentioned in this comment: https://github.com/eyaltoledano/claude-task-master/issues/712#issuecomment-2954261468

jzumwalt · 1 year ago

Would love to see this implemented!

Using Claude-Code with claude-task-master for example, (an MCP server for task management), without sampling there's no choice but to configure the MCP server with external LLM keys.

Despite having a Claude Max subscription, this means I need to configure and pay for API access separately creating unnecessary friction and cost.

With sampling support, the MCP server could delegate these LLM requests back to Claude-Code - eliminated both the extra cost and configuration complexity (not to mention the implementation effort of the MCP server itself and those like it).

There's still the use case for MCPs to manage their own LLM connection, but full support of the MCP protocol seems like a no-brainer in this case!

This opens up a whole range of use cases for Claude-Code:

  • MCP reads your code → asks Claude-Code to analyze complexity → returns actionable insights
  • MCP detects a failing test → requests Claude-Code to suggest fixes → applies the best solution
  • MCP monitors file changes → queries Claude-Code for impact analysis → updates related docs
  • MCP receives user command → gets Claude-Code to plan approach → executes step by step
  • MCP finds TODO comments → asks Claude-Code to expand them → creates implementation tasks

Each interaction leverages your existing Claude instance rather than requiring separate API calls.

andig · 1 year ago

Would love this, too. Shocked when I saw

Error: Error requesting sampling: session does not support sampling

richardkmichael · 12 months ago

@ashwin-ant

I would like to use Sampling in my TailwindPlus MCP server to ask the client's LLM to compare fragments of code between the user's project and the source components from the UI framework.

I'm hoping this can provide a "similarity assessment" not just a technical diff, because source components are often customized and drift from the original code. I could do this by sending the components to the LLM, and it could compare itself, but this would consume far too much context in the user's session; there are many components. Also, if using Sampling, I can control when it is used, from the MCP server-side.

Trevoke · 11 months ago

Chiming in as well. I'd love to be able to use MCP sampling through Claude Code; there are some nontrivial second-order effects I'd like to derive with my MCP servers (e.g. define how to update some state based on an assessment) and it would be great to be able to do this in-band.

eyaltoledano · 11 months ago

Just an FYI that Taskmaster supports consuming the Claude Code CLI (and your claude subscription) without the need for additional API keys.

Just run task-master models —setup and select sonnet / claude-code or tell the LLM to use that as your main model.

FrancisBourre · 11 months ago
Just an FYI that Taskmaster supports consuming the Claude Code CLI (and your claude subscription) without the need for additional API keys. Just run task-master models —setup and select sonnet / claude-code or tell the LLM to use that as your main model.

What's the relation with the current issue???

eyaltoledano · 11 months ago
@ashwin-ant I don't have any specific MCP server in mind. Let's be honest, almost none of them support sampling yet because virtually no sensible MCP client supports it, creating a bit of a Catch-22. However, I believe now that VS Code has implemented it, more and more servers will start using it since it's a win-win for users. I know that @eyaltoledano, the creator of Task Master, is very positive about this, which he mentioned in this comment: eyaltoledano/claude-task-master#712 (comment)

referring to this

sampling is not required if you’re specifically trying to use claude code subscription to power taskmaster

but sampling itself within claude would be awesome either way.

saramaebee · 11 months ago

Echoing the request for sampling in Claude Code. I work on internal MCP servers for my job, and having sampling would be of huge benefit to me!

FrancisBourre · 11 months ago

+1

etherandrius · 11 months ago

+1

dean0x · 11 months ago

+1

codylandry · 10 months ago

+1

praneybehl · 10 months ago

+1

alwin-augustin · 10 months ago

+1

tommey · 10 months ago

+1

bguidolim · 10 months ago

+1 for this

The MCP I'm willing to use that needs MCP Sampling is: https://github.com/cameroncooke/XcodeBuildMCP

josh-enfield · 10 months ago

+1 - I have use cases for this, and I am using github copilot for something of these things because it supports it. I was kind of blown away since you guys are the originators of the MCP protocol. I figured you would be at the forefront. Elicitation would also be nice.

nsteele-loyaltymethods · 8 months ago

Just checking in on this feature. Ideally, I would like to use sampling for some complex tools. I have tested it out on other agents with amazing results and would really love to get it working with Claude Code. Any ETA?

gabrielbryk · 8 months ago

+1

edisonLzy · 8 months ago

+1

tnez · 8 months ago

I have a use case where I am working on an MCP server that maps interactions to template driven documentation to grow docs organically during the course of working sessions. These templates can be user defined and contain use_when: ... examples. I'd love to be able to map extracted insights to appropriate templates and was looking at leveraging MCP sampling to help with that classification. It seems really useful for things like this.

Also agree that Elicitation would be great as well - I don't have a current use case, but seems really useful.

d13 · 8 months ago

+1

antonioaversa · 8 months ago

+1!
MCP Sampling would make some of our use cases in MCP tools development much more straightforward!

jakemac53 · 8 months ago

A concrete use case from the Dart/Flutter MCP server is allowing a "bring your own model" approach to AI assistance features in your running Flutter or Dart application and the associated development tools. One of the biggest advantages of MCP itself is this openness and being model agnostic, it allows us to meet developers where they are.

Specifically this would enable tools such as "ask AI" buttons in the flutter widget inspector, network panel, etc, bringing AI assistance directly to the developer tools/emulators where the user is seeing the information/errors, instead of requiring them trying to describe to the AI agent the context that they want it to fetch (much of this context is available via MCP tools, but it requires a context switch and also the discoverability of these features is poor, agents in our experience don't tend to pro-actively use them a lot and require explicit prompting which requires user knowledge).

cbcoutinho · 8 months ago

I'm very interested in this feature, especially in the context of generative use-cases such as RAG. I want to be able to utilize the LLM within Claude Code to perform the generation step of a RAG pipeline hosted by an MCP server. Essentially the MCP server retrieves relevant searches for a query, and the LLM generates its own response as part of a tool call.

Check out my _pending_ implementation within Gemini CLI for this exact feature, including a short screencast to show the UX - importantly, a user is prompted to consent/reject the sampling request, as per the spec.

https://github.com/google-gemini/gemini-cli/pull/12801#issuecomment-3538432889

ralfbecher · 7 months ago

+1

crazygo · 7 months ago

+1

XavierDK · 7 months ago

+1

johnrogers · 7 months ago

+1

harikb · 6 months ago

+1

Even if API is available, there is a need to use the currently running claude code instance with existing context, local files. Querying an API is not the same. Thank you.

jacob-petterle · 6 months ago

I will get a real chain if you implement this 😤
!1767844065320.jpg

(Yes, I'm ashamed of the Gemini logo on the image. I hope Claude can forgive me 🙏😭)

vospascal · 5 months ago

Can we have this ? Others have this implemented this already

handstandsam · 5 months ago

Sampling would be very useful for UI Automation MCPs that need to process screenshots and avoid adding them to the chat's primary context window.

faxik · 5 months ago

+1

jshph · 5 months ago

+1! interested in leveraging sampling to implement programmatic parallel tool calls that use the LLM

barisione · 5 months ago

I have had some success replacing MCP sampling with a request to Claude Code to spawn a subagent.

For instance, if you want to implement something like this (in pseudo-Python):

def tool_foo():
    # Do some stuff.
    info = ...
    result = ask_the_llm_something(info)
    # Use `result`.

You can instead do:

def tool_start_foo():
    # Do some stuff.
    info = ...
    return f"""\
## ACTION REQUIRED: Spawn Subagent

You MUST now spawn a subagent to perform [...]. Use the Task tool with
the following parameters:

- subagent_type: "general-purpose"
- prompt: The prompt below (everything between BEGIN and END markers)

## After Receiving Results

You **MUST** call the `tool_end_foo` tool passing as a result, [... details
on the result and its format, including examples ...].

== BEGIN {marker_name} PROMPT FOR SUBAGENT ==

[... Prompt with the info you need to pass to the LLM ...]

== END {marker_name} PROMPT FOR SUBAGENT =="""

def tool_end_foo(result):
    # Use `result`.

This is extremely reliable in Claude Code, but its syntax is specific to it. You can make it work more generally by modifying your code to adapt to the specific agent that is calling you, or even by not exposing the two separate tools to agents that support MCP sampling.

jshph · 5 months ago

It just seems wasteful to spawn parallel subagents with the latency of an LLM call when doing so programmatically is so much faster. My binary (which I would like to package as a plugin) leverages this parallelization to make LLM calls but I would just like to make it easier for the user to trust that all calls are going through Anthropic

justinbmeyer · 4 months ago

I just want to add my support for sampling.

I built a MCP server that uses sampling: https://github.com/bitovi/cascade-mcp

It analyzes Figma designs, confluence pages, google docs and will help the user by asking questions and eventually writing stories:

<img width="1920" height="1080" alt="Image" src="https://github.com/user-attachments/assets/1da8a06d-310f-48c5-9012-394130dac6ba" />

<img width="1920" height="1080" alt="Image" src="https://github.com/user-attachments/assets/e3b9fde1-27ee-4c57-bd41-a6c36eecce28" />

It's got a relatively complex multi-prompt workflow. This is why it's much easier to put the behavior in a tool that uses sampling instead of having the user have to call the prompts in the right way themselves.

The tool works great in Copilot, I'd love to start using it in Claude :-).

lesaai · 4 months ago

+1

lesaai · 4 months ago

Use Case: MCP Server Needing LLM for Search Quality (Memory Crystal)

We build Memory Crystal, an MCP server that gives AI agents persistent semantic memory across sessions. It stores 200K+ conversation chunks in a local sqlite-vec database and provides crystal_search, crystal_remember, and crystal_forget tools.

Why we need sampling

Our search pipeline uses LLM calls for two narrow tasks:

  1. Query expansion ... takes a search query, generates 3 variations (lexical, semantic, hypothetical document) to improve recall. ~100 tokens in, ~150 tokens out.
  2. Re-ranking ... takes the top 40 search candidates, scores each for relevance. ~2000 tokens in, ~200 tokens out.

These are cheap, fast operations. A Haiku-class model handles them perfectly. We don't need Opus or Sonnet for this.

Current workaround (and why it's bad)

Without sampling, our MCP server has to bring its own LLM. We built a 5-level provider cascade:

1. MLX (local, Apple Silicon only)
2. Ollama (local)
3. OpenAI API key
4. Anthropic API key (direct, NOT OAuth tokens)
5. None (falls back to basic hybrid search)

The OAuth token problem: Claude Code's internal tokens (sk-ant-oat01-) return 401 from the Messages API. MCP subprocesses can't piggyback on Claude Code's auth. So users on the Max plan still need a separate API key or a local model just for search quality.

The iOS problem: On iOS, there's no MLX or Ollama. Without sampling, mobile users get degraded search (no query expansion, no re-ranking). With sampling, they'd get the same quality as desktop, using their existing subscription.

What we'd use

const result = await server.createMessage({
  messages: [{ role: 'user', content: { type: 'text', text: query } }],
  systemPrompt: EXPAND_PROMPT,
  maxTokens: 300,
  modelPreferences: {
    costPriority: 0.9,
    speedPriority: 0.8,
    intelligencePriority: 0.3,
    hints: [{ name: 'haiku' }],
  },
});

We've already designed and coded the integration (it's in our llm.ts provider cascade as priority 0). The moment Claude Code supports sampling, it lights up automatically.

Impact

This would let every Claude Max subscriber get high-quality semantic search from their MCP memory server without configuring API keys, installing local models, or paying extra. The MCP server just asks the client: "expand this query for me" and the client handles it through the subscription.

We're shipping this as an open-source MCP server. Sampling support would make it zero-config for Claude users.

gabrielbryk · 4 months ago

+1

tlmii · 4 months ago

@ashwin-ant You mentioned last year that you were looking into this. Any sense of the priority here? Lots of +1s, obviously. We've got a set of features we'd like to make usable in claude code in addition to the other tools we already work in and sampling would greatly ease the path to doing so. Knowing if this is truly on the radar or not would help us decide which direction to go.

abpiskunov · 3 months ago

+1

serkan-ozal · 3 months ago

+1

Tris10w · 3 months ago

+1

yurukusa · 3 months ago

While native MCP Sampling requires a protocol-level implementation, a hook-based approach can approximate it by routing expensive operations through your Max subscription:

INPUT=$(cat)
TOOL=$(echo "$INPUT" | jq -r '.tool_name // empty')
if echo "$TOOL" | grep -q '__'; then
    MCP_SERVER=$(echo "$TOOL" | cut -d'_' -f3)
    COST_LOG="/tmp/cc-mcp-costs.json"
    jq -nc --arg s "$MCP_SERVER" --arg t "$TOOL" --arg ts "$(date -u +%Y-%m-%dT%H:%M:%SZ)" '{server: $s, tool: $t, time: $ts}' >> "$COST_LOG"
    COUNT=$(grep -c "$MCP_SERVER" "$COST_LOG" 2>/dev/null || echo 0)
    if [ "$COUNT" -gt 50 ]; then
        echo "⚠️ MCP server '$MCP_SERVER' has $COUNT calls this session — monitor API costs" >&2
    fi
fi
exit 0

For throttling expensive MCP operations:

TOOL=$(cat | jq -r '.tool_name // empty')
echo "$TOOL" | grep -q '__' || exit 0
RATE_FILE="/tmp/cc-mcp-rate-$(echo $TOOL | md5sum | cut -c1-8)"
NOW=$(date +%s)
LAST=$(cat "$RATE_FILE" 2>/dev/null || echo 0)
if [ $((NOW - LAST)) -lt 1 ]; then
    sleep 1
fi
echo "$NOW" > "$RATE_FILE"
exit 0
karimkod · 3 months ago

+1

nnemirovsky · 3 months ago

+1

Voork1144 · 3 months ago

+1

guillaume86 · 3 months ago

Would love this but unfortunately there's probably "financial incentives" that makes this proposition not very attractive to anthropic. It would be the closest thing to an API access (bypassing their harness) usable with a subscription.

I think if we want movement on this issue we and anthropic need to acknowledge/address this fact, maybe that feature would require some additional paid option, and that's fine to discuss it...

justinbmeyer · 2 months ago

I asked claude how it feels about this. Here's it's response:

The user is paying for Max. The inference runs through their client, on their account. Sampling doesn't let some third party freeload — it lets the user route their own subscription's inference capacity through an MCP server they chose to connect. That's no different than the user typing a longer prompt that incorporates the same context the MCP server would have sent via sampling.

The only real difference is who initiated the prompt — the user typing vs. the server requesting. But the user explicitly connected that server and opted in. It's their session, their subscription, their intent.
If Anthropic's position is "Max covers what you do in our UI, but not what your tools ask for on your behalf," that's a product packaging decision they're allowed to make, but it cuts against the whole MCP philosophy they're championing. The spec literally exists to let servers delegate inference to clients. Anthropic designed the protocol, published the spec, promotes it everywhere — and then their flagship developer tool doesn't implement one of its core primitives.

szhygulin · 1 month ago

Adding a fresh data point from 2026-05-20: still reproducible on Claude Code 2.1.145.

Empirical confirmation (binary inspection)

Searched the four client-capability literals compiled into /home/<user>/.local/share/claude/versions/2.1.145. The host's MCP client declares:

capabilities:{}
capabilities:{tools:{}}
capabilities:{roots:{}}
capabilities:{workspace:{configuration:!1,workspaceFolders:!1}}

No sampling: {} literal is present in any of them. The two sampling: substrings that do appear in the binary are (a) the SDK's server-side schema for outgoing-sampling advertisement and (b) the SDK's ClientCapabilitiesSchema validator — neither is a client-side declaration.

Reproduction against a real MCP server

We have a real MCP server (pkb-mcp) that's defensive about this: it probes client capabilities via the SDK's Server.oninitialized hook and lazy-refreshes at tool-call time (handles hosts that skip notifications/initialized), then short-circuits LLM-dependent tools with an explicit "host lacks sampling" error when the cap isn't advertised.

$ printf '{"jsonrpc":"2.0","id":1,"method":"initialize","params":{"protocolVersion":"2025-06-18","capabilities":{},"clientInfo":{"name":"test","version":"1"}}}\n...' | node dist/index.js
→ "tool unavailable: host lacks sampling capability"
   registryState.reason: not-advertised
   rawClientCapabilities: {}

When the same server is given a synthetic client that advertises capabilities: {"sampling": {}}, the gate passes and the tool proceeds. So the detection is correct; the cap simply isn't there on Claude Code's wire.

Why this matters for the "feature request" framing

This thread is labeled feature-request, but at the MCP-protocol level the host signals what it supports via initialize.capabilities. A host that supports sampling but doesn't declare it is indistinguishable from one that doesn't support it — every well-behaved MCP server will refuse LLM-routed tools, exactly as the spec instructs. So the user-visible effect is "Claude Code is incompatible with sampling-using MCP servers", which is closer to a compliance gap than to a pure feature request.

Adding sampling: {} to the client's declared capabilities (and wiring sampling/createMessage handling) would unblock the entire ecosystem of sampling-using servers, not just the cost-routing use case in the original issue. Happy to provide more details if useful.

Puistis · 4 days ago

Could Anthropic have already implemented this? How is this even an issue? They championed a protocol they don't even fully support, I mean, come on!

JonZeolla · 4 days ago

Sampling is deprecated in the July 28th version of MCP so any additional adoption of it is pretty unlikely

https://modelcontextprotocol.io/seps/2577-deprecate-roots-sampling-and-logging

Puistis · 4 days ago
Sampling is deprecated in the July 28th version of MCP so any additional adoption of it is pretty unlikely https://modelcontextprotocol.io/seps/2577-deprecate-roots-sampling-and-logging

Well that sucks, because I have been using it on several things on my servers.