Skip to content

Commit 44504d8

Browse files
committed
fix(otel): do not mark client span ERROR for JSON-RPC caller-error codes (#3811)
1 parent 77001c9 commit 44504d8

1 file changed

Lines changed: 7 additions & 2 deletions

File tree

‎src/mcp/shared/jsonrpc_dispatcher.py‎

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -80,6 +80,9 @@
8080
_CLOSED_OUTCOME = ErrorData(code=CONNECTION_CLOSED, message="Connection closed")
8181
"""What a waiter receives when the connection closes; matched by identity, since a peer can send the same code."""
8282

83+
_CALLER_ERROR_CODES: frozenset[int] = frozenset({-32700, -32600, -32601, -32602, -32002})
84+
"""JSON-RPC error codes that indicate a caller-side request problem and should not mark the client span ERROR."""
85+
8386
TransportT = TypeVar("TransportT", bound=TransportContext, default=TransportContext)
8487

8588
PeerCancelMode = Literal["interrupt", "signal"]
@@ -416,8 +419,10 @@ async def send_raw_request(
416419
outcome = await receive.receive()
417420
if isinstance(outcome, ErrorData) and outcome is not _CLOSED_OUTCOME:
418421
code = str(outcome.code)
419-
span.set_attributes({"error.type": code, "rpc.response.status_code": code})
420-
span.set_status(StatusCode.ERROR, outcome.message)
422+
span.set_attribute("rpc.response.status_code", code)
423+
if outcome.code not in _CALLER_ERROR_CODES:
424+
span.set_attribute("error.type", code)
425+
span.set_status(StatusCode.ERROR, outcome.message)
421426
except TimeoutError:
422427
if not timeout_armed:
423428
# The clock starts only after the write, so this TimeoutError is the

0 commit comments

Comments
 (0)