Skip to content

Commit 2c05e4b

Browse files
committed
Emit JSON-RPC error code for error.type on validation failures
Align the ValidationError branch with the MCPError branch and the C# SDK: set error.type and rpc.response.status_code to the numeric JSON-RPC code (INVALID_PARAMS) as a string, not the exception class name.
1 parent cdd6bb2 commit 2c05e4b

2 files changed

Lines changed: 9 additions & 5 deletions

File tree

src/mcp/server/_otel.py

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88
from mcp.server.context import CallNext, HandlerResult, ServerMiddleware, ServerRequestContext
99
from mcp.shared._otel import extract_trace_context, otel_span
1010
from mcp.shared.exceptions import MCPError
11-
from mcp.types import CallToolResult
11+
from mcp.types import INVALID_PARAMS, CallToolResult
1212

1313

1414
class OpenTelemetryMiddleware(ServerMiddleware[Any]):
@@ -20,8 +20,9 @@ class OpenTelemetryMiddleware(ServerMiddleware[Any]):
2020
2121
Tool and prompt operations additionally carry the GenAI semantic-convention attributes `gen_ai.tool.name` /
2222
`gen_ai.prompt.name`, and `gen_ai.operation.name` is set to `execute_tool` for `tools/call`. Failures set
23-
`error.type` and `rpc.response.status_code` to the JSON-RPC error code, or `error.type` to `tool_error` for a
24-
`tools/call` result carrying `is_error`.
23+
`error.type` and `rpc.response.status_code` to the JSON-RPC error code as a string (e.g. `-32602`), or
24+
`error.type` to `tool_error` for a `tools/call` result carrying `is_error`; a non-`MCPError` handler exception
25+
sets `error.type` to its type name.
2526
"""
2627

2728
async def __call__(self, ctx: ServerRequestContext[Any, Any], call_next: CallNext) -> HandlerResult:
@@ -59,7 +60,8 @@ async def __call__(self, ctx: ServerRequestContext[Any, Any], call_next: CallNex
5960
raise
6061
except ValidationError:
6162
# Mirror the sanitized wire response; pydantic messages carry client input.
62-
span.set_attribute("error.type", "ValidationError")
63+
code = str(INVALID_PARAMS)
64+
span.set_attributes({"error.type": code, "rpc.response.status_code": code})
6365
span.set_status(StatusCode.ERROR, "Invalid request parameters")
6466
raise
6567
except Exception as e:

tests/server/test_otel.py

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@
1414
from mcp.shared._otel import inject_trace_context
1515
from mcp.shared.exceptions import MCPError
1616
from mcp.types import (
17+
INVALID_PARAMS,
1718
CallToolRequestParams,
1819
CallToolResult,
1920
GetPromptRequestParams,
@@ -258,7 +259,8 @@ async def test_validation_failure_sets_sanitized_status(server: SrvT, spans: Spa
258259
assert span.status.status_code == StatusCode.ERROR
259260
assert span.status.description == "Invalid request parameters"
260261
assert span.attributes is not None
261-
assert span.attributes["error.type"] == "ValidationError"
262+
assert span.attributes["error.type"] == str(INVALID_PARAMS)
263+
assert span.attributes["rpc.response.status_code"] == str(INVALID_PARAMS)
262264
assert not span.events
263265

264266

0 commit comments

Comments
 (0)