Skip to content

Forward proxy initialize as bridge behavior#4228

Open
jlowin wants to merge 4 commits into
mainfrom
codex/remove-proxy-initialize-validation
Open

Forward proxy initialize as bridge behavior#4228
jlowin wants to merge 4 commits into
mainfrom
codex/remove-proxy-initialize-validation

Conversation

@jlowin
Copy link
Copy Markdown
Member

@jlowin jlowin commented May 23, 2026

FastMCP proxies are lazy bridges: they do not touch the upstream server during Python construction or process startup, but they do forward real downstream MCP requests. initialize is part of that protocol surface, so a proxy only reports successful initialization after the upstream server initializes successfully too.

This removes the validate_on_initialize concept and makes initialize forwarding inherent to FastMCPProxy. A bogus URL, denied upstream auth, or non-MCP upstream now fails the downstream initialize handshake instead of producing a local “connected” proxy with empty or failed capability fetches.

proxy = create_proxy("http://127.0.0.1:8000/mcp")

The proxy still does no upstream work until a client connects and sends initialize. Existing HTTP/SSE authorization header forwarding remains in the transport path, and fastmcp-remote continues to use strict provider errors so later proxied fetches surface upstream failures instead of empty results.

@jlowin jlowin marked this pull request as ready for review May 23, 2026 19:01
@marvin-context-protocol marvin-context-protocol Bot added bug Something isn't working. Reports of errors, unexpected behavior, or broken functionality. server Related to FastMCP server implementation or server-side functionality. breaking change Breaks backward compatibility. Requires minor version bump. Critical for maintainer attention. labels May 23, 2026
@jlowin jlowin changed the title Remove proxy initialize validation Forward proxy initialize in bridge mode May 23, 2026
Copy link
Copy Markdown

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

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: 5830c1d117

ℹ️ 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 thread fastmcp_slim/fastmcp/server/server.py Outdated
_create_client_factory,
)

settings.setdefault("forward_initialize", True)
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P1 Badge Stop forwarding initialize by default in create_proxy

create_proxy() now unconditionally enables forward_initialize, so a proxy handshake always opens and initializes the upstream client before responding locally. This reintroduces the eager remote availability/auth check that this change is trying to remove, and it means default proxies still fail at Client(proxy) time whenever the upstream is down instead of deferring failures to the first proxied operation. That breaks lazy/degraded startup scenarios and keeps the same side effects (extra upstream sessions/auth) on every initialize.

Useful? React with 👍 / 👎.

@jlowin jlowin changed the title Forward proxy initialize in bridge mode Forward proxy initialize as bridge behavior May 23, 2026
Copy link
Copy Markdown

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

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: 23b797286d

ℹ️ 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".

self.add_provider(provider)
if validate_on_initialize:
self.middleware.append(ProxyInitializeMiddleware(self))
self.middleware.append(ProxyInitializeMiddleware(self))
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P1 Badge Restore opt-out for initialize forwarding in FastMCPProxy

This change makes FastMCPProxy always install ProxyInitializeMiddleware, so every downstream initialize now forces an upstream connect/initialize handshake with no way to disable it. That regresses the prior lazy behavior for direct FastMCPProxy(...) usage (and any caller that previously used validate_on_initialize=False), causing startup to fail immediately when upstream is temporarily unavailable instead of deferring failure to the first proxied operation; this is especially disruptive for stateful/custom client_factory mounting flows that rely on lazy or degraded startup.

Useful? React with 👍 / 👎.

Copy link
Copy Markdown

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

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: 9b4598fe91

ℹ️ 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 +1169 to +1172
if "roots" in self._proxy_restoring_handler_keys:
self._session_kwargs["list_roots_callback"] = create_roots_callback(
_make_restoring_handler(default_proxy_roots_handler, self._proxy_rc_ref)
)
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P1 Badge Preserve overridden callbacks when cloning stateful proxy clients

StatefulProxyClient.new() now calls _bind_restoring_handlers(), which unconditionally rewrites callbacks for any handler key that was defaulted at construction time. That means a caller who later customizes behavior (for example via set_roots, set_sampling_callback, or set_elicitation_callback) will have those overrides silently discarded on new_stateful() clones, and the proxy falls back to the built-in forwarding handlers instead. This is a regression from prior behavior where Client.new() preserved post-init callback updates, and it can break custom routing/auth/context logic in stateful proxy deployments.

Useful? React with 👍 / 👎.

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.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant