litellm - 💡(How to fix) Fix [Bug]: JSON-RPC protocol-level rejections on /mcp/ produce no standard_logging_object record

Official PRs (…)
ON THIS PAGE

GitHub issue graph ai analysis

Paste a GitHub issue URL. We fetch that issue, discover linked issues from bodies/comments/timeline, collect linked pull requests, and produce a structured English report.

The report is written in English Markdown for sharing and archival.

Helpful · Quick feedback

Loading…

When the LiteLLM /mcp/ endpoint receives a JSON-RPC request that's rejected at the protocol layer (e.g. an unknown method like tools/totally_made_up, or malformed params), the proxy returns a JSON-RPC error response to the caller — but no standard_logging_object is produced. No callback fires, no spend log entry is written, no audit trail exists.

This creates a blind spot for:

  • Audit/compliance pipelines that expect every inbound request to produce a record.
  • Abuse/malformed-traffic detection.
  • Operators investigating a client that's hammering the proxy with bad requests.

Error Message

When the LiteLLM /mcp/ endpoint receives a JSON-RPC request that's rejected at the protocol layer (e.g. an unknown method like tools/totally_made_up, or malformed params), the proxy returns a JSON-RPC error response to the caller — but no standard_logging_object is produced. No callback fires, no spend log entry is written, no audit trail exists. "error":{"code":-32602,"message":"Invalid request parameters","data":""}}

  • call_type: something like "call_mcp_protocol_error" or a more general "call_mcp_tool" with a populated error
  • error_information with the JSON-RPC error code/message
  • Debugging. When a caller reports "my MCP integration sends tools/list and gets back an error", operators currently have no record on the LiteLLM side and have to ask the caller to share their request body.

Root Cause

When the LiteLLM /mcp/ endpoint receives a JSON-RPC request that's rejected at the protocol layer (e.g. an unknown method like tools/totally_made_up, or malformed params), the proxy returns a JSON-RPC error response to the caller — but no standard_logging_object is produced. No callback fires, no spend log entry is written, no audit trail exists.

This creates a blind spot for:

  • Audit/compliance pipelines that expect every inbound request to produce a record.
  • Abuse/malformed-traffic detection.
  • Operators investigating a client that's hammering the proxy with bad requests.

Code Example

curl -s -X POST 'http://localhost:4000/mcp/' \
     -H 'Authorization: Bearer sk-1234' \
     -H 'Content-Type: application/json' \
     -H 'Accept: application/json, text/event-stream' \
     -d '{"jsonrpc":"2.0","id":1,"method":"tools/totally_made_up","params":{}}'

---

{"jsonrpc":"2.0","id":1,
    "error":{"code":-32602,"message":"Invalid request parameters","data":""}}
RAW_BUFFERClick to expand / collapse

Description

When the LiteLLM /mcp/ endpoint receives a JSON-RPC request that's rejected at the protocol layer (e.g. an unknown method like tools/totally_made_up, or malformed params), the proxy returns a JSON-RPC error response to the caller — but no standard_logging_object is produced. No callback fires, no spend log entry is written, no audit trail exists.

This creates a blind spot for:

  • Audit/compliance pipelines that expect every inbound request to produce a record.
  • Abuse/malformed-traffic detection.
  • Operators investigating a client that's hammering the proxy with bad requests.

Repro

Tested on ghcr.io/berriai/litellm:main-v1.81.14-stable.

  1. POST a JSON-RPC request with an unknown method:
    curl -s -X POST 'http://localhost:4000/mcp/' \
      -H 'Authorization: Bearer sk-1234' \
      -H 'Content-Type: application/json' \
      -H 'Accept: application/json, text/event-stream' \
      -d '{"jsonrpc":"2.0","id":1,"method":"tools/totally_made_up","params":{}}'
  2. Caller receives:
    {"jsonrpc":"2.0","id":1,
     "error":{"code":-32602,"message":"Invalid request parameters","data":""}}
  3. Search verbose proxy logs / Langfuse / spend logs for a standard_logging_object corresponding to this request.

Observed

No record produced. No call_type, no request_id tied to this request, no entry in LiteLLM_SpendLogs, no callback invocation (verified via a registered CustomLogger in tests).

For comparison, well-formed JSON-RPC requests that fail downstream (e.g. unknown tool name → internal HTTPException) do produce records — see related #N. The asymmetry is specifically at the protocol-layer rejection point.

Expected

Even when LiteLLM rejects a request at the JSON-RPC protocol layer, it should still produce a standard_logging_object with at minimum:

  • request_id, startTime, endTime
  • call_type: something like "call_mcp_protocol_error" or a more general "call_mcp_tool" with a populated error
  • status: "failure"
  • error_information with the JSON-RPC error code/message
  • metadata.mcp_tool_call_metadata with whatever request fields were parsable (e.g. the method name that was rejected)

This is consistent with how other LiteLLM endpoints log every inbound request, successful or not.

Why it matters

  • Audit completeness. Many enterprise deployments require that every inbound request appears in spend logs / a callback. Silent drops break this assumption.
  • Abuse detection. A client sending a flood of malformed requests is invisible to the existing observability stack.
  • Debugging. When a caller reports "my MCP integration sends tools/list and gets back an error", operators currently have no record on the LiteLLM side and have to ask the caller to share their request body.

Related

  • #28900 — call_mcp_tool success records have no response field
  • #28927 — Upstream isError: true recorded as status: "success"
  • (Companion issue: MCP tools/call HTTPException path leaves call_type empty + mcp_tool_call_metadata null — filed alongside this one.)

Vote matrix · Quick signals

Works
Did the solution work? Tap to confirm.
Easy Fix
Was it a quick fix?
Time Saver
Did it save you time?
Blocking
Was it severely blocking?
Common Issue
Are others likely hitting this too?
Flaky / Intermittent
Is it intermittent?
Verified / Reproducible
Can you reproduce it reliably?
Loading…

Still need to ship something?

×6

Another batch ranked right after the header list — different links, same matching logic.

Back to top recommendations

TRENDING