Skip to content

Emit one SERVER span per request and adopt spec-correct error codes - #4445

Merged
jlowin merged 5 commits into
mainfrom
modernize/tier0-correctness
Jul 7, 2026
Merged

Emit one SERVER span per request and adopt spec-correct error codes#4445
jlowin merged 5 commits into
mainfrom
modernize/tier0-correctness

Conversation

@jlowin

@jlowin jlowin commented Jul 7, 2026

Copy link
Copy Markdown
Member

Two correctness fixes surfaced by the post-migration modernization audit.

One SERVER span per request. SDK v2 seeds its own OpenTelemetryMiddleware into every low-level server, and FastMCP emits its own richer SERVER span — so anyone with an OTel exporter configured got two SERVER spans per request (plus extras for initialize) with different attribute conventions. LowLevelServer now removes the SDK's seeded middleware (matched by type, other middleware preserved) and keeps FastMCP's spans. Distributed trace propagation is unaffected — FastMCP extracts traceparent from _meta itself, and the new regression tests assert exactly one SERVER span that shares the client's trace id, going through the real dispatcher (the pre-existing telemetry tests called mcp.call_tool in-process, which is why this was never caught). The SDK's client-side MCP send … span was checked too: that one is a legitimate parent/child pair with ours, not a duplicate, and is left alone.

Spec-correct wire error codes. FastMCP returned -32002 for resource-not-found where SEP-2164 (and the SDK's own mapping) specify -32602 INVALID_PARAMS. The hand-rolled per-adapter error literals are replaced by a central to_mcp_error() translator in fastmcp.exceptions built on the SDK's code constants; resource- and prompt-not-found now return -32602 over the wire with messages unchanged. This is a deliberate wire-visible correction for 4.0, recorded in the v4 change register. The opt-in ErrorHandlingMiddleware keeps its separately-documented per-method code mapping.

Labels: bugs, breaking change.

@marvin-context-protocol marvin-context-protocol Bot added breaking change Breaks backward compatibility. Requires minor version bump. Critical for maintainer attention. server Related to FastMCP server implementation or server-side functionality. bugs labels Jul 7, 2026

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: a131ace697

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment on lines +218 to +220
self.middleware = [
mw for mw in self.middleware if not isinstance(mw, OpenTelemetryMiddleware)
]

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Preserve spans for unwrapped request handlers

Dropping every SDK OpenTelemetryMiddleware removes tracing for request methods that FastMCP does not wrap in its own server_span. The FastMCP spans are only created inside the high-level tool/resource/prompt paths in server.py; registered handlers such as initialize, tasks/get|result|list|cancel in server/mixins/lifespan.py, and the proxy ping handler only had the SDK middleware's generic SERVER span. In deployments with an OTel exporter, those requests now emit zero SERVER spans rather than the intended single span, so this filter needs either replacement coverage for all handlers or a narrower way to suppress only duplicate spans.

Useful? React with 👍 / 👎.

@jlowin jlowin added the v4 label Jul 7, 2026

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: f33fd0a69e

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

if (
fastmcp is None
or ctx.request_id is None
or ctx.method in _HIGH_LEVEL_SPANNED_METHODS

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Cover high-level requests before middleware short-circuits

Skipping every method in _HIGH_LEVEL_SPANNED_METHODS here means the only remaining SERVER span is opened later inside call_tool/list_*/read_resource after the FastMCP middleware chain reaches call_next. Built-in middleware can legally return or raise before that point — for example CachingMiddleware.on_call_tool returns cached results at fastmcp_slim/fastmcp/server/middleware/caching.py:438-439, and auth/rate-limit middleware can reject before call_next — so those high-level requests now export no SERVER span after the SDK middleware is removed. The seam needs to cover the outer request and suppress duplicates only when the high-level span actually opens.

Useful? React with 👍 / 👎.

@jlowin
jlowin merged commit ac78e6f into main Jul 7, 2026
15 checks passed
@jlowin
jlowin deleted the modernize/tier0-correctness branch July 7, 2026 11:49
@jlowin jlowin added the bug Something isn't working. Reports of errors, unexpected behavior, or broken functionality. label Jul 20, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

breaking change Breaks backward compatibility. Requires minor version bump. Critical for maintainer attention. bug Something isn't working. Reports of errors, unexpected behavior, or broken functionality. server Related to FastMCP server implementation or server-side functionality. v4

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant