github / github/copilot-cli

Background Agent MCP Connections Destroyed After Text-Only Turn

未关闭
#2,949 0 条评论 0 个 reaction 已指派 0 人 在 GitHub 查看
area:agents area:mcp
主要语言
Shell
星标
11.2k
派生
1.9k
平均合并
14 小时 16 分钟
30 天内合并 PR
6

描述

### Describe the bug

MCP tools in background agents (launched via the `task` tool) are unreliable. The CLI framework destroys MCP transport connections after any turn where the LLM produces a text-only response (no tool calls). This means background agents that depend on MCP tools intermittently fail with `"Not connected"` or `"Connection closed"` errors - even when the MCP server is healthy and reachable.

This is a blocking issue for using custom agents with MCP servers in background mode. Any non-trivial agent workflow that involves MCP tools will eventually hit this bug because the LLM occasionally produces a text-only response before making a tool call (~10% of the time with default prompts, 100% when the system prompt encourages reasoning before acting).

The bug does not affect standalone agent invocations (`copilot --agent -p `) or the parent session's own MCP connections - only background agents.

### Affected version

GitHub Copilot CLI 1.0.35

### Steps to reproduce the behavior

### Prerequisites

- Python 3.10+ with `aiohttp` (`pip install aiohttp`)

### 1. Add the attached server

```py
from mcp.server.fastmcp import FastMCP

mcp = FastMCP("repro-mcp-server", port=8099)

@mcp.tool()
def fast_tool(query: str) -> str:
"""Returns immediately. Echoes the query back. For testing MCP transport reliability."""
return f'{{"status": "ok", "query": "{query}"}}'

if __name__ == "__main__":
mcp.run(transport="sse")
```

Save to `~/.copilot/repro_mcp_server.py`

This is a minimal MCP SSE server that exposes a single `fast_tool` which immediately echoes back its input.

### 2. Create the agent definition

Save as `~/.copilot/agents/repro-test-agent.agent.md`:

```markdown
---
name: repro-test-agent
description: "Minimal agent for reproducing background-agent MCP bug."
mcp-servers:
repro:
type: sse
url: "http://localhost:8099/sse"
tools: ["*"]
tools: ['repro/*']
---

You are a test agent with a STRICT protocol. You MUST follow this exact sequence
for EVERY request:

Turn 1: Reply with ONLY this exact text: "Processing request." — absolutely NO
tool calls on this turn.
Turn 2: Now call the requested tool.

CRITICAL RULE: You are FORBIDDEN from calling any tool on your first turn. Your
first message MUST be pure text with zero tool calls.
```

The system prompt forces a text-only first turn. This simulates the natural LLM behaviour of reasoning before acting, which triggers the bug deterministically.

When run, the background agent produces "Processing request." on turn 1, calls `repro-fast_tool` on turn 2, and returns `{"status": "ok", "query": "test-bug"}`.

### Expected behavior

I expect that MCP tool calling is reliable for any background agent session.

### What actually happens

The agent produces text on turn 1. The framework fires internal `response` and `messages_snapshot` events which tear down the MCP transport. The agent either never gets a turn 2, or turn 2's tool call fails on a dead connection.

Debug log signature (`~/.copilot/logs/process-*.log`):

```
[DEBUG] response (Request-ID null):
[DEBUG] Ignoring event of kind: response
[DEBUG] Ignoring event of kind: messages_snapshot
[ERROR] MCP transport for repro closed
[ERROR] MCP client for repro closed
```

**Repro rate: 3/3 (100%)** with the included agent definition.

### Intermittent variant without special system prompt

The "text first" system prompt makes the bug deterministic, but it also occurs naturally. With a neutral system prompt ("call the tool and report the result"), the LLM occasionally produces text before a tool call. In testing:

- 2 failures out of ~20 background agent invocations with neutral prompts (~10%)

### Non-background agents are not affected

- `copilot --agent -p ` (standalone mode): MCP survives across turns. 0/15 failures.
- Parent session MCP tools: text-only turns do not destroy connections.
- The bug is specific to background agents spawned via the `task` tool.

### Additional context

### CLI log: standalone agent (works — MCP survives)

```
copilot --agent repro-test-agent -p 'Call repro-fast_tool with query "standalone-test".' --allow-all-tools
```

```
09:24:25.374 [ERROR] Starting remote MCP client for repro with url: http://localhost:8099/sse
09:24:25.402 [ERROR] MCP client for repro connected, took 27ms
09:24:25.533 [DEBUG] Adding tool: repro-fast_tool
09:24:27.996 [DEBUG] Making Anthropic Messages streaming request with messages: [
09:24:32.836 [DEBUG] response (Request-ID null): ← LLM response arrives
09:24:40.914 [DEBUG] Tool calls count: 2 ← includes tool_use
09:24:40.915 [DEBUG] Permission request (kind=mcp) ← tool executes
09:24:40.971 [DEBUG] Tool invocation result: {"result":"{\"status\": \"ok\", \"query\": \"standalone-test\"}"}
09:24:40.997 [DEBUG] Making Anthropic Messages streaming request ← turn 2 (report result)
09:24:43.433 [DEBUG] response (Request-ID null):
09:24:43.434 [DEBUG] Ignoring event of kind: response ← event fires...
09:24:43.434 [DEBUG] Ignoring event of kind: messages_snapshot
← but NO MCP teardown
```

### CLI log: background agent (fails — MCP destroyed)

```
copilot -p '...launch background agent...' --allow-all-tools
```

```
09:19:17.426 [INFO] Started background agent with id: bug-repro
09:19:17.486 [INFO] Custom agent "repro-test-agent" invoked
09:19:17.545 [ERROR] Starting remote MCP client for repro with url: http://localhost:8099/sse
09:19:17.573 [ERROR] MCP client for repro connected, took 27ms
09:19:17.664 [DEBUG] Adding tool: repro-fast_tool
09:19:17.666 [INFO] Found 1 MCP tools from server 'repro'
09:19:17.671 [INFO] Custom agent "repro-test-agent" using tools: repro-fast_tool, view
09:19:18.074 [DEBUG] Making Anthropic Messages streaming request ← child agent turn 1
09:19:20.632 [DEBUG] response (Request-ID null): ← text-only "Processing request."
(no "Tool calls count" line)
09:19:20.715 [INFO] System notification: Agent "bug-repro" has finished processing
← agent treated as DONE after text-only turn
...
09:19:54.619 [DEBUG] response (Request-ID null):
09:19:54.621 [DEBUG] Ignoring event of kind: response ← same event as standalone...
09:19:54.623 [DEBUG] Ignoring event of kind: messages_snapshot
09:19:54.629 [ERROR] MCP transport for repro closed ← ...but HERE it kills MCP
09:19:54.629 [ERROR] MCP client for repro closed
```

Note: both modes fire `Ignoring event of kind: response`, but only the background agent path destroys the MCP transport afterward.

贡献指南

打开贡献指南

调研方向

首先,使用提供的 Python SSE 服务器和 repro-test-agent.agent.md 复现问题,并通过 task tool 启动它们。将 background-agent 路径与 standalone 模式进行比较,并检查 response 和 messages_snapshot 事件附近的 ~/.copilot/logs/process-*.log。完成的标准是:仅文本回合不会使 MCP 连接失效,并且后续工具调用成功。

由索引模型根据 Issue 内容生成。

评估

技术栈
python
领域
cli, networking
Issue 类型
缺陷
难度
4/5
预计耗时
3-5 天
活跃度
冷清
描述清晰度
基本清楚
新手友好度
48/100

把新 issue 发到你的邮箱

精选适合新手参与的 GitHub issue 摘要。