agentscope-ai / agentscope-ai/QwenPaw

[Bug]: MCP driver ignoring transport config \u2014 hardcoded SSE client breaks streamable_http servers

Đang mở
#6,470 5 bình luận 0 reaction 1 người được giao Được @xiaoming-qxm nhận Xem trên GitHub
Ngôn ngữ chính
Python
Star
34.9k
Fork
3.1k
Merge trung bình
1 ngày 15 giờ
Pull request đã merge (30 ngày)
225

Mô tả

## QwenPaw Version

v2.0.1 (Windows, exe installer)

## Description

MCP driver 在建立 transport 连接时硬编码使用了 `sse_client`,完全忽略了 YAML 配置文件中指定的 `transport: streamable_http`。这导致所有配置为 Streamable HTTP 传输协议的 MCP 服务器连接失败,工具无法加载。

**根因**:`mcp_stateful_client.py` 约第 800 行的 `_setup_transport` 方法直接调用 `mcp.client.sse.sse_client()`,没有读取配置中的 transport 字段来决定使用 `sse_client` 还是 `streamablehttp_client`。

**影响**:所有使用 `transport: streamable_http` 的 MCP 驱动(如 Jin10 金融数据 MCP)均无法工作。

**相关 PR(s):** 无

**安全考量:** 无

## Component(s) Affected

- [x] Core / Backend (app, agents, config, providers, utils, local_models)
- [ ] Console (frontend web UI)
- [ ] Channels (DingTalk, Feishu, QQ, Discord, iMessage, etc.)
- [x] Skills
- [ ] CLI
- [ ] Documentation (website)
- [ ] Tests
- [ ] CI/CD
- [ ] Scripts / Deploy

## Environment

- **QwenPaw 版本:** v2.0.1
- **操作系统:** Windows 10 (AMD64)
- **安装方式:** exe 安装包
- **Python 版本:** 3.11 (bundled in exe)

## Steps to Reproduce

1. 配置一个使用 `transport: streamable_http` 的 MCP 驱动,例如 Jin10 金融数据 MCP:

```yaml
# drivers/mcp/jin10.yaml
name: jin10
transport: streamable_http
url: https://mcp.jin10.com/mcp
headers:
Authorization: "Bearer "
```

2. 确保 `credentials.yaml` 中有对应的凭证条目。
3. 重启 QwenPaw daemon。
4. 在 Agent 中尝试调用 Jin10 MCP 工具(如 `list_calendar`)。
5. 观察 daemon 日志和工具调用结果。

## Actual vs Expected

- **Actual:**
- Daemon 启动时日志报错:`Error in MCP client lifecycle for jin10`
- 完整错误堆栈:
```
File "qwenpaw\drivers\handlers\mcp_stateful_client.py", line 157, in _run_lifecycle
File "qwenpaw\drivers\handlers\mcp_stateful_client.py", line 800, in _setup_transport
File "contextlib.py", line 650, in enter_async_context
File "mcp\client\sse.py", line 62, in sse_client
...
httpx.HTTPStatusError: Client error '400 Bad Request' for url 'https://mcp.jin10.com/mcp'
```
- MCP 工具列表为空,Agent 无法调用任何 Jin10 工具。
- 框架重试 10+ 次后超时,MCP 驱动完全不可用。

- **Expected:**
- 框架应读取 YAML 中的 `transport: streamable_http` 配置。
- 使用 `mcp.client.streamablehttp.streamablehttp_client()` 建立连接。
- Jin10 MCP 工具正常加载并可调用。

## Root Cause Analysis

### 证据 1:daemon 日志

```
2026-07-25 08:45:02 | ERROR | mcp_stateful_client.py:203 | Error in MCP client lifecycle for jin10:
+ Exception Group Traceback:
| File "qwenpaw\drivers\handlers\mcp_stateful_client.py", line 157, in _run_lifecycle
| File "qwenpaw\drivers\handlers\mcp_stateful_client.py", line 800, in _setup_transport
| File "contextlib.py", line 650, in enter_async_context
| File "mcp\client\sse.py", line 62, in sse_client \u2190 hardcoded SSE
| ...
| httpx.HTTPStatusError: Client error '400 Bad Request' for url 'https://mcp.jin10.com/mcp'
```

### 证据 2:raw HTTP 对比测试

使用原生 HTTP POST 直接调用金十 MCP 服务端(Streamable HTTP 协议):

```bash
# initialize \u2192 success,获得 session ID
curl -X POST https://mcp.jin10.com/mcp \
-H "Content-Type: application/json" \
-H "Accept: application/json, text/event-stream" \
-H "Authorization: Bearer " \
-d '{"jsonrpc":"2.0","id":"1","method":"initialize","params":{"protocolVersion":"2025-11-25","capabilities":{},"clientInfo":{"name":"test","version":"1.0"}}}'

# tools/list \u2192 success,returns 8 tools
# tools/call list_calendar \u2192 success,returns full calendar data
```

**Conclusion**: The Jin10 MCP server is online and Streamable HTTP protocol works correctly. The issue is entirely on the framework side.

### 证据 3:YAML 配置正确

```yaml
# Both workspaces have identical jin10.yaml:
transport: streamable_http \u2190 config is correct
url: https://mcp.jin10.com/mcp
```

## Suggested Fix

Modify `qwenpaw/drivers/handlers/mcp_stateful_client.py` around line 800, the `_setup_transport` method:

**Current code (pseudocode)**:
```python
async def _setup_transport(self):
# Line 800 - hardcoded SSE
async with sse_client(url, headers=headers) as (read_stream, write_stream, _):
...
```

**Suggested fix**:
```python
async def _setup_transport(self):
transport = self.endpoint_config.get("transport", "sse")

if transport == "streamable_http":
from mcp.client.streamablehttp import streamablehttp_client
async with streamablehttp_client(url, headers=headers) as (read_stream, write_stream, _):
...
else:
async with sse_client(url, headers=headers) as (read_stream, write_stream, _):
...
```

**Key points**:
1. Read `transport` field from `self.endpoint_config` (or equivalent config object)
2. Select `streamablehttp_client` or `sse_client` based on the value
3. Maintain backward compatibility: drivers without transport config or with `sse` still use SSE

## Workaround

Before the framework fix, use an independent Python script to bypass the MCP driver:

```bash
python jin10_client.py list_calendar # Economic calendar
python jin10_client.py list_flash # Flash news
python jin10_client.py search_flash --keyword "央行"
python jin10_client.py stock_quotes --market_codes SH,SZ
```

The script uses raw HTTP + Streamable HTTP protocol with 3-layer defense (session rebuild / ping detection / error retry), tested stable.

## Impact

- Affects all MCP drivers configured with `transport: streamable_http`
- Currently known affected MCP: Jin10 financial data
- MCP drivers using default SSE transport (e.g. tavily_search) are NOT affected
- Fix should ensure backward compatibility

## Additional Context

- MCP SDK version: mcp Python SDK (QwenPaw v2.0.1 bundled)
- Streamable HTTP transport: `mcp/client/streamablehttp.py`
- SSE transport: `mcp/client/sse.py`
- Reproducible in both `default` and `cloud-orchestrator` workspaces
- Framework code is compiled in exe, users cannot modify source code, requires official update

Hướng dẫn đóng góp

Mở hướng dẫn đóng góp

Đánh giá

Issue này chưa được đánh giá.

Nhận issue mới trong hộp thư của bạn

Bản tóm tắt ngắn những issue GitHub phù hợp với người mới.