litellm - 💡(How to fix) Fix [Bug]: MCP tool call HTTPException path leaves call_type empty and mcp_tool_call_metadata null

Official PRs (…)
ON THIS PAGE

Recommended Tools

×6

Utilities matched from this issue’s tags and category — try them while you read without losing context.

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 a tools/call invocation triggers an internal HTTPException inside _handle_local_mcp_tool (e.g. the requested tool name isn't found in any registered server's tool mapping → 404: Tool '<name>' not found), the resulting standard_logging_object has two surprising properties on the failure record:

  1. call_type is the empty string "" instead of "call_mcp_tool".
  2. metadata.mcp_tool_call_metadata is null, even though LiteLLM received and parsed both the attempted tool name and the arguments before raising the exception.

This makes failure records hard to find (anyone filtering by call_type == "call_mcp_tool" misses them) and impossible to attribute to a specific tool/args without cross-referencing access logs.

Error Message

{ "request_id": "...", "call_type": "", ← empty string "model": "", "status": "failure", "metadata": { "status": "failure", "error_information": { "error_class": "HTTPException", "error_code": "404", "error_message": "404: Tool 'totally_made_up_tool' not found", "traceback": "Traceback (most recent call last):\n File ".../mcp_server/server.py", line 1606, in call_mcp_tool\n response = await execute_mcp_tool(...)\n File ".../mcp_server/server.py", line 1545, in execute_mcp_tool\n local_content = await _handle_local_mcp_tool(...)\n File ".../mcp_server/server.py", line 1812, in _handle_local_mcp_tool\n raise HTTPException(status_code=404, detail=f"Tool '{name}' not found")\nfastapi.exceptions.HTTPException: 404: Tool 'totally_made_up_tool' not found\n" }, "mcp_tool_call_metadata": null, ← null despite knowing the attempted name + args "spend_logs_metadata": null }, "mcp_namespaced_tool_name": null }

Root Cause

When a tools/call invocation triggers an internal HTTPException inside _handle_local_mcp_tool (e.g. the requested tool name isn't found in any registered server's tool mapping → 404: Tool '<name>' not found), the resulting standard_logging_object has two surprising properties on the failure record:

  1. call_type is the empty string "" instead of "call_mcp_tool".
  2. metadata.mcp_tool_call_metadata is null, even though LiteLLM received and parsed both the attempted tool name and the arguments before raising the exception.

This makes failure records hard to find (anyone filtering by call_type == "call_mcp_tool" misses them) and impossible to attribute to a specific tool/args without cross-referencing access logs.

Code Example

{"jsonrpc":"2.0","id":1,"method":"tools/call",
    "params":{"name":"<alias>-totally_made_up_tool","arguments":{}}}

---

{
  "request_id": "...",
  "call_type": "",                                ← empty string
  "model": "",
  "status": "failure",
  "metadata": {
    "status": "failure",
    "error_information": {
      "error_class": "HTTPException",
      "error_code": "404",
      "error_message": "404: Tool 'totally_made_up_tool' not found",
      "traceback": "Traceback (most recent call last):\n  File \".../mcp_server/server.py\", line 1606, in call_mcp_tool\n    response = await execute_mcp_tool(...)\n  File \".../mcp_server/server.py\", line 1545, in execute_mcp_tool\n    local_content = await _handle_local_mcp_tool(...)\n  File \".../mcp_server/server.py\", line 1812, in _handle_local_mcp_tool\n    raise HTTPException(status_code=404, detail=f\"Tool '{name}' not found\")\nfastapi.exceptions.HTTPException: 404: Tool 'totally_made_up_tool' not found\n"
    },
    "mcp_tool_call_metadata": null,null despite knowing the attempted name + args
    "spend_logs_metadata": null
  },
  "mcp_namespaced_tool_name": null
}
RAW_BUFFERClick to expand / collapse

Description

When a tools/call invocation triggers an internal HTTPException inside _handle_local_mcp_tool (e.g. the requested tool name isn't found in any registered server's tool mapping → 404: Tool '<name>' not found), the resulting standard_logging_object has two surprising properties on the failure record:

  1. call_type is the empty string "" instead of "call_mcp_tool".
  2. metadata.mcp_tool_call_metadata is null, even though LiteLLM received and parsed both the attempted tool name and the arguments before raising the exception.

This makes failure records hard to find (anyone filtering by call_type == "call_mcp_tool" misses them) and impossible to attribute to a specific tool/args without cross-referencing access logs.

Repro

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

  1. Configure any HTTP MCP server (auth_type none works).
  2. Call a tool name that LiteLLM doesn't know:
    {"jsonrpc":"2.0","id":1,"method":"tools/call",
     "params":{"name":"<alias>-totally_made_up_tool","arguments":{}}}
  3. The caller correctly receives result.isError: true with text "Error: Tool 'totally_made_up_tool' not found".
  4. Inspect the standard_logging_object.

Observed

{
  "request_id": "...",
  "call_type": "",                                ← empty string
  "model": "",
  "status": "failure",
  "metadata": {
    "status": "failure",
    "error_information": {
      "error_class": "HTTPException",
      "error_code": "404",
      "error_message": "404: Tool 'totally_made_up_tool' not found",
      "traceback": "Traceback (most recent call last):\n  File \".../mcp_server/server.py\", line 1606, in call_mcp_tool\n    response = await execute_mcp_tool(...)\n  File \".../mcp_server/server.py\", line 1545, in execute_mcp_tool\n    local_content = await _handle_local_mcp_tool(...)\n  File \".../mcp_server/server.py\", line 1812, in _handle_local_mcp_tool\n    raise HTTPException(status_code=404, detail=f\"Tool '{name}' not found\")\nfastapi.exceptions.HTTPException: 404: Tool 'totally_made_up_tool' not found\n"
    },
    "mcp_tool_call_metadata": null,null despite knowing the attempted name + args
    "spend_logs_metadata": null
  },
  "mcp_namespaced_tool_name": null
}

For comparison: a successful tools/call on the same proxy populates call_type: "call_mcp_tool" and a full mcp_tool_call_metadata: {name, arguments, mcp_server_name, namespaced_tool_name}.

Expected

On the HTTPException failure path:

  1. call_type should be "call_mcp_tool" (matching the success path), so downstream filters/dashboards see the failure as a failed MCP tool call.
  2. mcp_tool_call_metadata should be populated with at minimum the attempted name, arguments, and namespaced_tool_name — these are known at the point the exception is raised. If the named tool can't be resolved to a server, mcp_server_name may legitimately be null.

Why it matters

  • Dashboards filtering MCP traffic by call_type (e.g. "show all MCP tool calls last 24h, broken out by status") will miss every internal failure entirely.
  • Operators investigating a 404 spike have no record of which tool name was being attempted from this record alone.
  • Symmetry between success and failure records (same call_type, same metadata shape) is generally expected by observability tooling.

Notes

  • A separate concern with this record: error_information.traceback is a full multi-line Python stack trace including file paths inside the litellm package. Useful for debugging, but somewhat verbose and a potential code-path leak when shipped to third-party loggers. Out of scope for this issue but worth flagging.

Related

  • #28900 (response not captured for call_mcp_tool success records)
  • #28927 (isError: true recorded as status: "success")

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

litellm - 💡(How to fix) Fix [Bug]: MCP tool call HTTPException path leaves call_type empty and mcp_tool_call_metadata null