diff --git a/docs/servers/telemetry.mdx b/docs/servers/telemetry.mdx index 475bda055..73186bfae 100644 --- a/docs/servers/telemetry.mdx +++ b/docs/servers/telemetry.mdx @@ -244,9 +244,11 @@ def trace_exporter() -> Generator[InMemorySpanExporter, None, None]: exporter = InMemorySpanExporter() provider = TracerProvider() provider.add_span_processor(SimpleSpanProcessor(exporter)) + original_provider = trace.get_tracer_provider() trace.set_tracer_provider(provider) yield exporter exporter.clear() + trace.set_tracer_provider(original_provider) async def test_tool_creates_span(trace_exporter: InMemorySpanExporter) -> None: mcp = FastMCP("test") diff --git a/src/fastmcp/server/providers/proxy.py b/src/fastmcp/server/providers/proxy.py index 97456a5f0..d8d817bf2 100644 --- a/src/fastmcp/server/providers/proxy.py +++ b/src/fastmcp/server/providers/proxy.py @@ -120,11 +120,11 @@ class ProxyTool(Tool): span.set_attribute("fastmcp.provider.type", "ProxyProvider") client = await self._get_client() async with client: - context = get_context() + ctx = context or get_context() # Build meta dict from request context meta: dict[str, Any] | None = None - if hasattr(context, "request_context"): - req_ctx = context.request_context + if hasattr(ctx, "request_context"): + req_ctx = ctx.request_context # Start with existing meta if present if hasattr(req_ctx, "meta") and req_ctx.meta: meta = dict(req_ctx.meta) diff --git a/src/fastmcp/server/telemetry.py b/src/fastmcp/server/telemetry.py index 21adf5c23..6bfa8c076 100644 --- a/src/fastmcp/server/telemetry.py +++ b/src/fastmcp/server/telemetry.py @@ -4,6 +4,7 @@ from collections.abc import Generator from contextlib import contextmanager from mcp.server.lowlevel.server import request_ctx +from opentelemetry.context import Context from opentelemetry.trace import Span, SpanKind, Status, StatusCode from fastmcp.telemetry import extract_trace_context, get_tracer @@ -33,14 +34,14 @@ def get_session_span_attributes() -> dict[str, str]: attrs: dict[str, str] = {} try: ctx = get_context() - if ctx.request_context is not None: + if ctx.request_context is not None and ctx.session_id is not None: attrs["fastmcp.session.id"] = ctx.session_id except RuntimeError: pass return attrs -def _get_parent_trace_context(): +def _get_parent_trace_context() -> Context | None: """Get parent trace context from request meta for distributed tracing.""" try: req_ctx = request_ctx.get() diff --git a/tests/server/providers/proxy/test_proxy_server.py b/tests/server/providers/proxy/test_proxy_server.py index 278011ee2..8c0ec2b7d 100644 --- a/tests/server/providers/proxy/test_proxy_server.py +++ b/tests/server/providers/proxy/test_proxy_server.py @@ -214,7 +214,9 @@ async def test_proxy_with_async_client_factory(): proxy = FastMCPProxy(client_factory=async_factory) assert isinstance(proxy, FastMCPProxy) assert inspect.iscoroutinefunction(proxy.client_factory) - client = await proxy.client_factory() + client = proxy.client_factory() + if inspect.isawaitable(client): + client = await client assert isinstance(client, Client) assert isinstance(client.transport, StreamableHttpTransport) assert client.transport.url == "http://example.com/mcp/"