**Implements**: [SEP-2448: server execution telemetry] (https://github.com/modelcontextprotocol/modelcontextprotocol/pull/2448) **Description:** **The Observability Gap (The Problem)** MCP clients propagate trace context to servers, but server-side execution remains a black box. The client sees a single tools/call or resources/read span; everything the server does (auth checks, policy evaluation, API calls, sub-tool invocations) is invisible. In cross-organization deployments, clients and servers use separate observability backends with no shared collector access, making traditional span export useless. <img width="1015" height="450" alt="Screenshot 2026-03-23 at 3 43 21 PM" src="https://github.com/user-attachments/assets/58c817b5-fee6-46a3-9877-d523a25368ad" /> **Server Execution Telemetry (The Solution)** Servers advertise serverExecutionTelemetry and return a curated slice of their execution spans directly in _meta.otel of the response. Clients ingest these verbatim OTLP spans into their own collector, stitching server-side execution into their distributed trace; no shared infrastructure required. The black box becomes transparent. <img width="945" height="574" alt="Screenshot 2026-03-23 at 3 43 44 PM" src="https://github.com/user-attachments/assets/38d97c94-aa73-4e62-9b4e-3264600e5ed0" /> . **Summary:** Implement MCP serverExecutionTelemetry capability that enables cross-organization distributed tracing by returning server-side OpenTelemetry spans to clients inline via _meta.otel.traces. Server-side (middleware): - TelemetryPassbackMiddleware intercepts tools/call and resources/read - ContextVarSpanCollector isolates span collection per-request via ContextVar - Propagates traceparent from client request for distributed trace stitching - Serializes collected spans to verbatim OTLP JSON (resourceSpans format), directly POSTable to /v1/traces - Top-level span filtering by default; full span tree via detailed opt-in - Middleware advertises capabilities via get_capabilities() on the Middleware base class - Provisional API: FutureWarning emitted until SEP-2448 is ratified Client-side (reference agent): - LangChain ReAct agent connects to MCP server via streamable_http_client with OAuth 2.1 - Detects serverExecutionTelemetry capability at initialization - Dynamically wraps discovered MCP tools with traceparent propagation and _meta.otel span request - Ingests returned server spans into Jaeger (OTLP JSON) and Galileo (OTLP protobuf) - Two-act demo: --no-passback (black box) vs default (full server-side visibility) Dependencies: - opentelemetry-api and opentelemetry-sdk added to arcade-mcp-server Bump arcade-mcp-server version to 1.18.0.
42 lines
1.2 KiB
TOML
42 lines
1.2 KiB
TOML
[project]
|
|
name = "telemetry-passback"
|
|
version = "0.1.0"
|
|
description = "SEP-0000 reference implementation: cross-org distributed tracing via MCP serverExecutionTelemetry"
|
|
requires-python = ">=3.11"
|
|
dependencies = [
|
|
"arcade-mcp-server>=1.18.0,<2.0.0",
|
|
"mcp>=1.26.0",
|
|
"langchain>=1.2.13",
|
|
"langchain-community>=0.4.1",
|
|
"langchain-openai>=1.1.12",
|
|
"langgraph>=1.1.3",
|
|
"opentelemetry-api",
|
|
"opentelemetry-sdk",
|
|
"opentelemetry-exporter-otlp-proto-grpc",
|
|
"opentelemetry-exporter-otlp-proto-http",
|
|
"opentelemetry-instrumentation-langchain",
|
|
"opentelemetry-instrumentation-httpx",
|
|
"httpx>=0.28.1",
|
|
"python-dotenv>=1.2.2",
|
|
"protobuf",
|
|
]
|
|
|
|
[project.optional-dependencies]
|
|
dev = [
|
|
"pytest>=7.0.0",
|
|
"pytest-asyncio>=0.21.0",
|
|
"mypy>=1.0.0",
|
|
"ruff>=0.1.0",
|
|
]
|
|
|
|
[build-system]
|
|
requires = ["hatchling"]
|
|
build-backend = "hatchling.build"
|
|
|
|
[tool.hatch.build.targets.wheel]
|
|
packages = ["src/telemetry_passback"]
|
|
|
|
# Use local arcade-mcp-server (TelemetryPassbackMiddleware is not yet published)
|
|
[tool.uv.sources]
|
|
arcade-mcp-server = { path = "../../../libs/arcade-mcp-server/", editable = true }
|
|
arcade-serve = { path = "../../../libs/arcade-serve/", editable = true }
|