agentscope-ai / agentscope-ai/QwenPaw
[Bug]: `server/discover` HTTP 500 with non-standard `jsonRpcError` envelope is not treated as legacy-protocol evidence — Driver build fails against Java MCP SDK servers
- Lenguaje dominante
- TypeScript
- Estrellas
- 35k
- Forks
- 3.1k
- Merge medio
- 1 d 13 h
- PR fusionados (30 d)
- 228
Descripción
## QwenPaw Version
2.2.0 (desktop, macOS arm64)
## Description
An MCP card of type `streamable_http` pointing at a Java/Kotlin MCP SDK server fails Driver construction with `Failed to build Driver '': MCP server/discover rejected with HTTP 500`.
Root cause: the server answers the unknown method `server/discover` with HTTP **500** plus a non-standard error envelope `{"jsonRpcError": {"code": -32603, "message": "Missing handler for request type: server/discover", ...}}` (not the standard `{"jsonrpc": "2.0", "error": {...}}`). Two break points in the chain (`mcp_streamable_http.py` → `_negotiate` → `_rpc`):
1. `_unwrap_jsonrpc_result` (~L395): on `status >= 400` it checks `_is_jsonrpc_envelope(data)` first; the non-standard envelope fails the check → raises `httpx.HTTPStatusError` directly.
2. `_negotiate` (~L710): its `except httpx.HTTPStatusError` branch only classifies bare 400/404/405 as legacy-protocol evidence → 500 is not in the set → exception propagates → entire Driver build fails.
Control group: endpoints returning 400 or a standard `-32601` for `server/discover` fall back to legacy and connect fine. The affected server's standard `initialize` handshake works (HTTP 200, protocol 2025-11-25) — it would work via the legacy `HttpStatefulClient` path if the fallback triggered.
## Component(s) Affected
- [x] Core / Backend (app, agents, config, providers, utils, local_models)
## Environment
- **QwenPaw version:** 2.2.0
- **OS:** macOS (arm64)
- **Install method:** desktop app
## Steps to Reproduce
1. Configure an MCP card with `streamable_http` transport pointing at a Java/Kotlin MCP SDK server.
2. Let QwenPaw build the Driver (startup or card hot-reload).
3. Driver construction fails; no tools are injected.
## Actual vs Expected
- **Actual:** `Failed to build Driver '': MCP server/discover rejected with HTTP 500`; legacy fallback never triggers because HTTP 500 with a `jsonRpcError` envelope is not classified as legacy-protocol evidence.
- **Expected:** the non-standard 500 response is recognized as "server does not support server/discover" and negotiation falls back to the legacy `HttpStatefulClient` path, which then connects successfully via standard `initialize`.
## Logs / Screenshots
```
Failed to build Driver 'mx-ds-mcp': MCP server/discover rejected with HTTP 500
# server response body:
{"jsonRpcError": {"code": -32603, "message": "Missing handler for request type: server/discover", ...}}
```
## Additional Notes
Suggested fix (any one suffices):
1. In `_negotiate`'s `HTTPStatusError` branch, also classify 5xx responses whose error body contains "Missing handler" / "server/discover" evidence as legacy-protocol evidence; or
2. In `_unwrap_jsonrpc_result`, recognize the `jsonRpcError` (Java MCP SDK variant) envelope and convert it to a standard RPC error (code=-32603); or
3. Add an explicit card-level config option such as `negotiation: legacy` / `skip_discover: true` to force the `HttpStatefulClient` path.
Local workaround (deployed and verified): switch the card to stdio transport with a local bridge process (official MCP SDK `streamable_http_client` → stdio server forwarding `list_tools`/`call_tool`), bypassing `server/discover` entirely. Verified: `initialize` OK, full tool list, real queries return.
Guía de contribución
Línea de trabajo
Inspect `mcp_streamable_http.py`, especially `_unwrap_jsonrpc_result` (~L395) and `_negotiate` (~L710), since these are the identified breakpoints. Reproduce through the Driver build path using a `streamable_http` card pointed at the Java/Kotlin MCP server response shown in the report (HTTP 500 with `jsonRpcError`). Then confirm legacy fallback should be triggered and verify Driver creation succeeds with tools injected via the legacy `HttpStatefulClient` path.
Escrito por el modelo de indexación a partir del texto del issue.
Evaluación
- Stack tecnológico
- java, kotlin, python
- Área
- backend
- Tipo de issue
- Error
- Dificultad
- 2/5
- Tiempo estimado
- 1-3 horas
- Estado de actividad
- Activo
- Claridad
- Bien especificado
- Aptitud para principiantes
- 48/100