Skip to content

TracingToolCallInterceptor ​

Rasuvaeff\Yii3McpTelemetryBridge\TracingToolCallInterceptor

Class — Rasuvaeff\Yii3McpTelemetryBridge — Source

Wraps every MCP tools/call in a mcp.tool <name> span: the tool name, masked arguments, the client identity (endpoint secret id and the client's name/version), the session id and — when the session budget is configured — how many calls remain, plus the caller's W3C trace context.

Session attributes are recorded on the handshake era only. On the stateless 2026-07-28 era the session is a throwaway the SDK builds for one request: its id names nothing and the per-session budget counter never moves there (yii3-mcp counts that era's budget per client in PSR-16, out of reach here).

The caller's traceparent (stateless era, _meta) cannot parent the span — yii3-telemetry's trace() takes no remote parent — so it is recorded as mcp.caller.trace_id / mcp.caller.span_id, and only when it parses as a valid W3C context: the value is caller-controlled.

Arguments are recorded as one scalar attribute per argument (mcp.tool.argument.<name>), masked, stringified and truncated — the OTel attribute model only accepts primitives and homogeneous lists of primitives, so a single nested-array attribute would be dropped by the OTel backend (same flattening the ecosystem's OtelMiddleware uses for http.request.param.<name>).

The span follows the frozen trace() contract of rasuvaeff/yii3-telemetry: a tool exception is recorded on the span, the span status becomes Error and the ORIGINAL exception is rethrown, so the MCP error envelope the agent sees is unchanged. The mcp.outcome attribute follows the core's shared CallOutcome vocabulary: success, rejected (a client-visible refusal — rate limit, RBAC, budget) or error (an unexpected failure).

Methods ​

intercept() ​

php
intercept(Interceptor\ToolCallContext $context, callable $next): mixed