modelcontextprotocol / modelcontextprotocol/python-sdk
[Bug] Client sends empty _meta:{} on every request; strict servers (Meta Ads MCP) reject with HTTP 400
Dieses Issue hat noch niemand übernommen.
- Vorherrschende Sprache
- Python
- Sterne
- 24.3k
- Forks
- 4k
- Ø Merge
- 1 T. 1 Std.
- Gemergte PRs (30 T.)
- 31
Beschreibung
Description
JSONRPCDispatcher.send_raw_request attaches _meta to params unconditionally:
out_params = dict(params) if params is not None else {}
out_meta = dict(out_params.get("_meta") or {})
on_progress = opts.get("on_progress")
if on_progress is not None:
out_meta["progressToken"] = request_id
out_params["_meta"] = out_meta # <- empty dict goes on the wire
When no progress callback is set and the otel tracer is a no-op (default), out_meta stays {} and every request ships _meta: {}.
Strict JSON-RPC servers reject this: Meta's hosted Ads MCP server (https://mcp.facebook.com/ads) returns HTTP 400 with -32602 "_meta for Request must be a dict or null" on initialize, making it unreachable from any client built on this SDK. _meta: null is rejected identically — the field must be absent.
Other MCP clients Meta documents (Claude Code, ChatGPT) don't emit an empty _meta and connect fine.
Reproduction
Reported downstream from Hermes Agent (NousResearch/hermes-agent#105637), with a minimal curl repro against the real server (400 with _meta:{}}, 200 without). Happy to attach a self-contained repro against a local strict server if preferred.
Proposed fix
if out_meta:
out_params["_meta"] = out_meta
elif "_meta" in out_params:
del out_params["_meta"]
after inject_trace_context(out_meta) so a real trace context is still sent.
Environment
- mcp SDK: current main (
src/mcp/shared/jsonrpc_dispatcher.py) - Python 3.12
Beitragsleitfaden
Erste Schritte
- Lies das ganze Issue und danach den Beitragsleitfaden des Projekts.
- Schreib ins Issue, dass du es übernimmst — das erspart doppelte Arbeit.
- Forke das Repository und arbeite in einem Branch.
- Öffne einen Pull Request, der die Issue-Nummer nennt.
Rechercherichtung
Beginne in src/mcp/shared/jsonrpc_dispatcher.py bei JSONRPCDispatcher.send_raw_request und verfolge, wie out_meta befüllt wird, einschließlich inject_trace_context. Führe die initialize-Anfrage gegen einen strikten Server oder die beschriebene minimale Reproduktion aus; abgeschlossen ist es, wenn Anfragen ohne Progress- oder Trace-Metadaten _meta vollständig weglassen, während tatsächlich vorhandene Metadaten erhalten bleiben.
Vom Indexierungsmodell aus dem Issue-Text verfasst.
Bewertung
- Tech-Stack
- python
- Bereich
- api
- Issue-Typ
- Bug
- Schwierigkeit
- 2/5
- Geschätzter Aufwand
- 1-3 Stunden
- Aktivitätsstatus
- Aktiv
- Klarheit
- Klar beschrieben
- Anfängerfreundlichkeit
- 78/100