MCP Sampling is Always Declined in Non-Interactive Mode
- Dominant language
- Shell
- Stars
- 11.2k
- Forks
- 1.9k
- Avg merge
- 14h 16m
- Merged PRs (30d)
- 6
Description
### Describe the bug
MCP sampling (#1748) works in interactive mode, but the same MCP server reaches a denied permissions prompt in `-p` non-interactive mode, even when `--allow-all` is enabled.
With `--allow-all`, the CLI does invoke the MCP tool in `-p` mode. The tool starts, the server receives `CallToolRequest`, and then the sampling call back into the CLI fails with `Method not found`.
The same server, config, CLI version, and prompts work in interactive mode. In that control case, the CLI logs `Received sampling request from sampling-repro` and the tool returns successfully.
### Affected version
GitHub Copilot CLI 1.0.31
### Steps to reproduce the behavior
### 1. Create a minimal FastMCP server that uses sampling
**`sampling_server.py`**
```python
#!/usr/bin/env python3
"""Minimal FastMCP server that exercises sampling/createMessage."""
from mcp.server.fastmcp import Context, FastMCP
from mcp.types import SamplingMessage, TextContent
mcp = FastMCP("sampling-repro")
async def sample_text(ctx: Context, prompt: str, system_prompt: str) -> str:
result = await ctx.session.create_message(
messages=[
SamplingMessage(
role="user",
content=TextContent(type="text", text=prompt),
)
],
max_tokens=256,
system_prompt=system_prompt,
)
parts = getattr(result, "content", None)
if isinstance(parts, list):
text = "".join(
part.text for part in parts if getattr(part, "type", None) == "text"
).strip()
if text:
return text
text = getattr(getattr(result, "content", None), "text", None)
if isinstance(text, str) and text.strip():
return text.strip()
raise RuntimeError(f"Unexpected sampling response: {result!r}")
@mcp.tool()
async def summarize(text: str, ctx: Context) -> str:
"""Summarize the given text in one sentence."""
summary = await sample_text(
ctx,
prompt=f"Summarize in exactly one sentence:\n\n{text}",
system_prompt="You are a concise summarizer. Reply with exactly one sentence.",
)
return f"Summary: {summary}"
@mcp.tool()
async def duplicate(text: str, ctx: Context) -> str:
"""Repeat the given text exactly twice with a separator."""
repeated = await sample_text(
ctx,
prompt=(
"Repeat the following text exactly twice, separated by ' | ', and add no "
f"other words:\n\n{text}"
),
system_prompt="Return only the duplicated text.",
)
return repeated
if __name__ == "__main__":
mcp.run()
```
### 2. Create a minimal MCP config file
**`mcp-config.json`**
```json
{
"mcpServers": {
"sampling-repro": {
"command": "/path/to/python3",
"args": [
"/path/to/sampling_server.py"
],
"env": {}
}
}
}
```
### 3. Run the same prompts in `-p` mode
**Summarize example**
```bash
copilot \
--log-level=all \
--log-dir /path/to/logs \
--additional-mcp-config @/path/to/mcp-config.json \
--disable-builtin-mcps \
--no-custom-instructions \
--allow-all \
-p "Use the summarize tool from the sampling-repro MCP server exactly once to summarize this text: 'The quick brown fox jumps over the lazy dog. This sentence contains every letter of the alphabet and is often used for typing practice.'"
```
**Duplication example**
```bash
copilot \
--log-level=all \
--log-dir /path/to/logs \
--additional-mcp-config @/path/to/mcp-config.json \
--disable-builtin-mcps \
--no-custom-instructions \
--allow-all \
-p "Use the duplicate tool from the sampling-repro MCP server exactly once with this text: 'alpha beta'"
```
### 4. Check the outputs
Both non-interactive runs fail the same way:
```text
✗ summarize (MCP: sampling-repro) · text: "The quick brown fox jumps over the lazy dog. This senten…
└ MCP server 'sampling-repro': Error executing tool summarize: Method not found
```
```text
✗ duplicate (MCP: sampling-repro) · text: "alpha beta"
└ MCP server 'sampling-repro': Error executing tool duplicate: Method not found
```
Redacted log excerpt from the `-p` summarize run:
```text
[DEBUG] Tool calls count: 2
[ERROR] [mcp server sampling-repro stderr] ... Processing request of type CallToolRequest
[DEBUG] Tool invocation result: Error executing tool summarize: Method not found
```
### Expected behavior
If `--allow-all` is set, `sampling/createMessage` should work in `-p` mode the same way it works in interactive mode.
The non-interactive session cannot show approval prompts, but `--allow-all` already bypasses tool, path, and URL confirmations. Once the tool call is allowed to run, the CLI should expose the sampling handler to the MCP server instead of returning `Method not found`.
### Control: interactive mode works
Run the same prompts in interactive mode:
```bash
copilot \
--log-level=all \
--log-dir /path/to/logs \
--additional-mcp-config @/path/to/mcp-config.json \
--disable-builtin-mcps \
--no-custom-instructions \
--allow-all \
-i "Use the duplicate tool from the sampling-repro MCP server exactly once with this text: 'alpha beta'"
```
```bash
copilot \
--log-level=all \
--log-dir /path/to/logs \
--additional-mcp-config @/path/to/mcp-config.json \
--disable-builtin-mcps \
--no-custom-instructions \
--allow-all \
-i "Use the summarize tool from the sampling-repro MCP server exactly once to summarize this text: 'The quick brown fox jumps over the lazy dog. This sentence contains every letter of the alphabet and is often used for typing practice.'"
```
These succeed with the same server and config:
```text
duplicate (MCP: sampling-repro) · text: "alpha beta"
└ {"result":"alpha beta | alpha beta"}
```
```text
summarize (MCP: sampling-repro) · text: "The quick brown fox jumps over the lazy dog. This sentence c…"
└ {"result":"Summary: \"The quick brown fox jumps over the lazy dog\" is a pangram containing every letter of the alphabet and is commonly used for typing practice."}
```
### Expected behavior
MCP sampling should be allowed through non-interactive sessions when using `-p` and `--allow-all`.
### Additional context
| Field | Value |
|-------|-------|
| Process log (redacted) | [process-1776747687370-23478-redacted.log](https://github.com/user-attachments/files/26940309/process-1776747687370-23478-redacted.log) |
| CLI version | GitHub Copilot CLI 1.0.31 |
| OS | Linux |
| Shell | bash |
Contributor guide
Assessment
This issue has not been assessed yet.