--- title: telemetry sidebarTitle: telemetry --- # `fastmcp.server.telemetry` Server-side telemetry helpers. ## Functions ### `get_auth_span_attributes` ```python get_auth_span_attributes() -> dict[str, str] ``` Get auth attributes for the current request, if authenticated. ### `get_session_span_attributes` ```python get_session_span_attributes() -> dict[str, str] ``` Get session attributes for the current request. ### `get_protocol_span_attributes` ```python get_protocol_span_attributes() -> dict[str, str] ``` Get the negotiated MCP protocol version for the current request. Mirrors the `mcp.protocol.version` attribute the SDK's own `OpenTelemetryMiddleware` sets — FastMCP drops that middleware to avoid a duplicate SERVER span, so this restores the attribute on FastMCP's span. ### `record_span_exception` ```python record_span_exception(span: Span, e: Exception) -> None ``` Record an exception and error status on a span. ### `seam_span` ```python seam_span(method: str, server_name: str) -> Generator[Span, None, None] ``` Open the per-request SERVER span at the FastMCP middleware seam. The span is named after the method and carries the base MCP attributes (`mcp.method.name`, `fastmcp.server.name`, auth/session context) so seam-only methods (`logging/setLevel`, `tasks/*`, `ping`, `initialize`, ...) are fully attributed even though they never reach the high-level path. It is marked with `SEAM_SPAN_MARKER` so a later `server_span` call in the high-level path enriches this span with component attributes instead of opening a second one. Exceptions raised anywhere below the seam — including rejections *before* the high-level path (auth, not-found, middleware vetoes) that would otherwise produce no SERVER span at all — are recorded here. In `propagation_only` mode no span is opened at all — this is the one place that has to know the difference, because the seam is where the incoming `_meta` parent context is applied for the whole request. ### `server_span` ```python server_span(name: str, method: str, server_name: str, component_type: str, component_key: str, resource_uri: str | None = None, tool_name: str | None = None, prompt_name: str | None = None) -> Generator[Span, None, None] ``` Emit or enrich a SERVER span with standard MCP attributes and auth context. When the current active span is the request's seam span (opened by `FastMCPServerMiddleware` and marked with `SEAM_SPAN_MARKER`), this sets the component attributes on that span and yields it *without* starting a second span — so failures rejected before this point and the successful high-level call share one richly-attributed SERVER span. Otherwise (non-seam contexts, e.g. in-process `mcp.call_tool()` calls that bypass the dispatcher) it opens a new SERVER span as before. Automatically records any exception on the span and sets error status. In `propagation_only` mode no span is opened or enriched. The seam has normally already attached the incoming parent context for this request; doing it again here is a no-op, and covers the in-process callers that bypass the dispatcher and so never reach the seam at all. ### `delegate_span` ```python delegate_span(name: str, provider_type: str, component_key: str, method: str | None = None) -> Generator[Span, None, None] ``` Create an INTERNAL span for provider delegation. Used by FastMCPProvider when delegating to mounted servers. Automatically records any exception on the span and sets error status.