From 33f952fc4820c042addf6425b74d11c07ed9bab7 Mon Sep 17 00:00:00 2001 From: Chris Guidry Date: Wed, 14 Jan 2026 09:48:07 -0500 Subject: [PATCH] Address CodeRabbit suggestions MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Add return type annotation to main() in run_with_tracing.py - Use spread operator for argv construction - Add type annotations to docs test example - Use async httpx client and asyncio.sleep in diagnostics server - Improve subprocess termination handling with timeout fallback 🤖 Generated with Claude Code Co-Authored-By: Claude Opus 4.5 --- docs/servers/telemetry.mdx | 5 +++-- examples/diagnostics/server.py | 25 ++++++++++++++++--------- examples/run_with_tracing.py | 4 ++-- loq.toml | 2 +- 4 files changed, 22 insertions(+), 14 deletions(-) diff --git a/docs/servers/telemetry.mdx b/docs/servers/telemetry.mdx index 7fc46d593..475bda055 100644 --- a/docs/servers/telemetry.mdx +++ b/docs/servers/telemetry.mdx @@ -231,6 +231,7 @@ For testing, use the in-memory exporter: ```python import pytest +from collections.abc import Generator from opentelemetry import trace from opentelemetry.sdk.trace import TracerProvider from opentelemetry.sdk.trace.export import SimpleSpanProcessor @@ -239,7 +240,7 @@ from opentelemetry.sdk.trace.export.in_memory_span_exporter import InMemorySpanE from fastmcp import FastMCP @pytest.fixture -def trace_exporter(): +def trace_exporter() -> Generator[InMemorySpanExporter, None, None]: exporter = InMemorySpanExporter() provider = TracerProvider() provider.add_span_processor(SimpleSpanProcessor(exporter)) @@ -247,7 +248,7 @@ def trace_exporter(): yield exporter exporter.clear() -async def test_tool_creates_span(trace_exporter): +async def test_tool_creates_span(trace_exporter: InMemorySpanExporter) -> None: mcp = FastMCP("test") @mcp.tool() diff --git a/examples/diagnostics/server.py b/examples/diagnostics/server.py index 8aaaacbda..211c5d893 100644 --- a/examples/diagnostics/server.py +++ b/examples/diagnostics/server.py @@ -1,8 +1,8 @@ """FastMCP Diagnostics Server - for testing tracing, errors, and observability.""" +import asyncio import os import subprocess -import time from collections.abc import AsyncIterator from contextlib import asynccontextmanager from pathlib import Path @@ -43,13 +43,16 @@ async def lifespan(server: FastMCP) -> AsyncIterator[None]: stderr=subprocess.PIPE, ) - # Wait for server to be ready - for _ in range(50): - try: - httpx.get(f"http://localhost:{ECHO_SERVER_PORT}/sse", timeout=0.1) - break - except Exception: - time.sleep(0.1) + # Wait for server to be ready (async to avoid blocking event loop) + async with httpx.AsyncClient() as client: + for _ in range(50): + try: + await client.get( + f"http://localhost:{ECHO_SERVER_PORT}/sse", timeout=0.1 + ) + break + except Exception: + await asyncio.sleep(0.1) # Mount proxy to the running echo server echo_proxy = create_proxy(ECHO_SERVER_URL, name="Echo Proxy") @@ -59,7 +62,11 @@ async def lifespan(server: FastMCP) -> AsyncIterator[None]: yield finally: proc.terminate() - proc.wait(timeout=5) + try: + proc.wait(timeout=5) + except subprocess.TimeoutExpired: + proc.kill() + proc.wait() mcp = FastMCP("Diagnostics Server", lifespan=lifespan) diff --git a/examples/run_with_tracing.py b/examples/run_with_tracing.py index 97d3b2d13..f49255e56 100755 --- a/examples/run_with_tracing.py +++ b/examples/run_with_tracing.py @@ -19,7 +19,7 @@ import os import sys -def main(): +def main() -> None: if len(sys.argv) < 2: print(__doc__) sys.exit(1) @@ -51,7 +51,7 @@ def main(): # Now run fastmcp CLI from fastmcp.cli.cli import app - sys.argv = ["fastmcp", "run"] + sys.argv[1:] + sys.argv = ["fastmcp", "run", *sys.argv[1:]] app() diff --git a/loq.toml b/loq.toml index 8e3634046..2960baeaf 100644 --- a/loq.toml +++ b/loq.toml @@ -288,7 +288,7 @@ max_lines = 1019 [[rules]] path = "src/fastmcp/server/server.py" -max_lines = 3500 +max_lines = 3000 [[rules]] path = "tests/deprecated/test_import_server.py"