github / github/copilot-cli

MCP Sampling is Always Declined in Non-Interactive Mode

Abierto
#2,882 1 comentario 1 reacción 0 asignados Ver en GitHub
area:mcp area:non-interactive
Lenguaje dominante
Shell
Estrellas
11.2k
Forks
1.9k
Merge medio
14 h 16 min
PR fusionados (30 d)
6

Descripción

### 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 |

Guía de contribución

Abrir la guía de contribución

Evaluación

Este issue todavía no se ha evaluado.

Recibe los nuevos issues en tu correo

Un resumen breve de issues de GitHub para principiantes.