diff --git a/docs/servers/auth/oauth-proxy.mdx b/docs/servers/auth/oauth-proxy.mdx
index dd4751350..03727ec87 100644
--- a/docs/servers/auth/oauth-proxy.mdx
+++ b/docs/servers/auth/oauth-proxy.mdx
@@ -315,8 +315,10 @@ auth = OAuthProxy(..., client_storage=MemoryStore())
**`"remember"` — silent consent on return:**
Users see the consent screen on first authorization; subsequent flows from the same browser for the same `(client_id, redirect_uri)` are silently approved via a signed cookie. Cross-site navigations (detected via `Sec-Fetch-Site`) fall back to the prompt. `Sec-Fetch-Site` is a browser-level heuristic rather than a protocol guarantee: an attacker who finds a way to initiate a non-cross-site navigation (XSS on a sibling origin, a same-site redirect chain, etc.) can reach the silent-consent path. `True` does not depend on this signal. See [Confused Deputy Attacks](#confused-deputy-attacks) for the underlying attack class.
- **`"external"` — delegate to upstream:**
- Skip the built-in consent page; consent is collected by the upstream IdP or a custom login page referenced via `upstream_authorization_endpoint`. No security warning is logged.
+ **`"external"` — externally managed:**
+ Follows the same authorization path as `False`: FastMCP skips its consent page and associated browser-binding protections, then redirects directly to the upstream provider. The difference is logging. `False` emits a security warning, while `"external"` suppresses that warning as an explicit acknowledgment that the operator is enforcing equivalent consent and transaction-binding protections elsewhere. FastMCP does not provide or verify those external protections.
+
+ Ordinary upstream OAuth consent is generally not equivalent. It typically authorizes FastMCP's shared upstream application without identifying the downstream MCP client or binding approval to that client's transaction. Use `"external"` only when your surrounding authorization system supplies those protections.
**`False` — disable entirely:**
Authorization proceeds directly to the upstream provider without any consent UI. Logs a security warning. Only for local development or testing.
@@ -336,7 +338,7 @@ auth = OAuthProxy(..., client_storage=MemoryStore())
```
- Disabling consent removes an important security layer. Only disable for local development or testing environments where you fully control all connecting clients.
+ Both `False` and `"external"` disable FastMCP's consent and browser-binding protections. `False` warns about this configuration; `"external"` suppresses the warning because it is an operator acknowledgment that equivalent protections exist elsewhere. Prefer the default `True` unless you own that external authorization flow.
diff --git a/docs/servers/auth/oidc-proxy.mdx b/docs/servers/auth/oidc-proxy.mdx
index 006efc8d6..be4bcb22d 100644
--- a/docs/servers/auth/oidc-proxy.mdx
+++ b/docs/servers/auth/oidc-proxy.mdx
@@ -206,7 +206,7 @@ auth = OIDCProxy(
- Consent screen behavior for authorization requests. Accepts `True` (default; always prompt — strongest protection), `"remember"` (silent consent on return visits via signed cookie, gated by `Sec-Fetch-Site` to block AS-in-the-middle attacks), `"external"` (consent handled by upstream IdP or custom page), or `False` (disable entirely; local/testing only). See the [OAuthProxy documentation](/servers/auth/oauth-proxy) for full details on each mode and the security trade-offs.
+ Consent screen behavior for authorization requests. Accepts `True` (default; always prompt — strongest protection), `"remember"` (silent consent on return visits via signed cookie, gated by `Sec-Fetch-Site` to block AS-in-the-middle attacks), `"external"` (same authorization path as `False`, but the warning is suppressed because the operator asserts that equivalent protections are enforced externally), or `False` (disable entirely; local/testing only). See the [OAuthProxy documentation](/servers/auth/oauth-proxy) for full details on each mode and the security trade-offs.
diff --git a/docs/v2/servers/auth/oauth-proxy.mdx b/docs/v2/servers/auth/oauth-proxy.mdx
index eef3bce1c..678c396b5 100644
--- a/docs/v2/servers/auth/oauth-proxy.mdx
+++ b/docs/v2/servers/auth/oauth-proxy.mdx
@@ -296,8 +296,10 @@ auth = OAuthProxy(..., client_storage=MemoryStore())
**`"remember"` — silent consent on return:**
Users see the consent screen on first authorization; subsequent flows from the same browser for the same `(client_id, redirect_uri)` are silently approved via a signed cookie. Cross-site navigations (detected via `Sec-Fetch-Site`) fall back to the prompt. `Sec-Fetch-Site` is a browser-level heuristic rather than a protocol guarantee: an attacker who finds a way to initiate a non-cross-site navigation (XSS on a sibling origin, a same-site redirect chain, etc.) can reach the silent-consent path. `True` does not depend on this signal. See [Confused Deputy Attacks](#confused-deputy-attacks) for the underlying attack class.
- **`"external"` — delegate to upstream:**
- Skip the built-in consent page; consent is collected by the upstream IdP or a custom login page referenced via `upstream_authorization_endpoint`. No security warning is logged.
+ **`"external"` — externally managed:**
+ Follows the same authorization path as `False`: FastMCP skips its consent page and associated browser-binding protections, then redirects directly to the upstream provider. The difference is logging. `False` emits a security warning, while `"external"` suppresses that warning as an explicit acknowledgment that the operator is enforcing equivalent consent and transaction-binding protections elsewhere. FastMCP does not provide or verify those external protections.
+
+ Ordinary upstream OAuth consent is generally not equivalent. It typically authorizes FastMCP's shared upstream application without identifying the downstream MCP client or binding approval to that client's transaction. Use `"external"` only when your surrounding authorization system supplies those protections.
**`False` — disable entirely:**
Authorization proceeds directly to the upstream provider without any consent UI. Logs a security warning. Only for local development or testing.
@@ -317,7 +319,7 @@ auth = OAuthProxy(..., client_storage=MemoryStore())
```
- Disabling consent removes an important security layer. Only disable for local development or testing environments where you fully control all connecting clients.
+ Both `False` and `"external"` disable FastMCP's consent and browser-binding protections. `False` warns about this configuration; `"external"` suppresses the warning because it is an operator acknowledgment that equivalent protections exist elsewhere. Prefer the default `True` unless you own that external authorization flow.
diff --git a/docs/v2/servers/auth/oidc-proxy.mdx b/docs/v2/servers/auth/oidc-proxy.mdx
index 750298298..a7988995e 100644
--- a/docs/v2/servers/auth/oidc-proxy.mdx
+++ b/docs/v2/servers/auth/oidc-proxy.mdx
@@ -199,7 +199,7 @@ auth = OIDCProxy(
- Consent screen behavior for authorization requests. Accepts `True` (default; always prompt — strongest protection), `"remember"` (silent consent on return visits via signed cookie, gated by `Sec-Fetch-Site` to block AS-in-the-middle attacks), `"external"` (consent handled by upstream IdP or custom page), or `False` (disable entirely; local/testing only). See the [OAuthProxy documentation](/v2/servers/auth/oauth-proxy) for full details on each mode and the security trade-offs.
+ Consent screen behavior for authorization requests. Accepts `True` (default; always prompt — strongest protection), `"remember"` (silent consent on return visits via signed cookie, gated by `Sec-Fetch-Site` to block AS-in-the-middle attacks), `"external"` (same authorization path as `False`, but the warning is suppressed because the operator asserts that equivalent protections are enforced externally), or `False` (disable entirely; local/testing only). See the [OAuthProxy documentation](/v2/servers/auth/oauth-proxy) for full details on each mode and the security trade-offs.
diff --git a/docs/v3/servers/auth/oauth-proxy.mdx b/docs/v3/servers/auth/oauth-proxy.mdx
index e35f244eb..79ba7bf09 100644
--- a/docs/v3/servers/auth/oauth-proxy.mdx
+++ b/docs/v3/servers/auth/oauth-proxy.mdx
@@ -310,8 +310,10 @@ auth = OAuthProxy(..., client_storage=MemoryStore())
**`"remember"` — silent consent on return:**
Users see the consent screen on first authorization; subsequent flows from the same browser for the same `(client_id, redirect_uri)` are silently approved via a signed cookie. Cross-site navigations (detected via `Sec-Fetch-Site`) fall back to the prompt. `Sec-Fetch-Site` is a browser-level heuristic rather than a protocol guarantee: an attacker who finds a way to initiate a non-cross-site navigation (XSS on a sibling origin, a same-site redirect chain, etc.) can reach the silent-consent path. `True` does not depend on this signal. See [Confused Deputy Attacks](#confused-deputy-attacks) for the underlying attack class.
- **`"external"` — delegate to upstream:**
- Skip the built-in consent page; consent is collected by the upstream IdP or a custom login page referenced via `upstream_authorization_endpoint`. No security warning is logged.
+ **`"external"` — externally managed:**
+ Follows the same authorization path as `False`: FastMCP skips its consent page and associated browser-binding protections, then redirects directly to the upstream provider. The difference is logging. `False` emits a security warning, while `"external"` suppresses that warning as an explicit acknowledgment that the operator is enforcing equivalent consent and transaction-binding protections elsewhere. FastMCP does not provide or verify those external protections.
+
+ Ordinary upstream OAuth consent is generally not equivalent. It typically authorizes FastMCP's shared upstream application without identifying the downstream MCP client or binding approval to that client's transaction. Use `"external"` only when your surrounding authorization system supplies those protections.
**`False` — disable entirely:**
Authorization proceeds directly to the upstream provider without any consent UI. Logs a security warning. Only for local development or testing.
@@ -331,7 +333,7 @@ auth = OAuthProxy(..., client_storage=MemoryStore())
```
- Disabling consent removes an important security layer. Only disable for local development or testing environments where you fully control all connecting clients.
+ Both `False` and `"external"` disable FastMCP's consent and browser-binding protections. `False` warns about this configuration; `"external"` suppresses the warning because it is an operator acknowledgment that equivalent protections exist elsewhere. Prefer the default `True` unless you own that external authorization flow.
diff --git a/docs/v3/servers/auth/oidc-proxy.mdx b/docs/v3/servers/auth/oidc-proxy.mdx
index fde747e2b..81ca677a2 100644
--- a/docs/v3/servers/auth/oidc-proxy.mdx
+++ b/docs/v3/servers/auth/oidc-proxy.mdx
@@ -199,7 +199,7 @@ auth = OIDCProxy(
- Consent screen behavior for authorization requests. Accepts `True` (default; always prompt — strongest protection), `"remember"` (silent consent on return visits via signed cookie, gated by `Sec-Fetch-Site` to block AS-in-the-middle attacks), `"external"` (consent handled by upstream IdP or custom page), or `False` (disable entirely; local/testing only). See the [OAuthProxy documentation](/servers/auth/oauth-proxy) for full details on each mode and the security trade-offs.
+ Consent screen behavior for authorization requests. Accepts `True` (default; always prompt — strongest protection), `"remember"` (silent consent on return visits via signed cookie, gated by `Sec-Fetch-Site` to block AS-in-the-middle attacks), `"external"` (same authorization path as `False`, but the warning is suppressed because the operator asserts that equivalent protections are enforced externally), or `False` (disable entirely; local/testing only). See the [OAuthProxy documentation](/servers/auth/oauth-proxy) for full details on each mode and the security trade-offs.
diff --git a/fastmcp_slim/fastmcp/server/auth/oauth_proxy/proxy.py b/fastmcp_slim/fastmcp/server/auth/oauth_proxy/proxy.py
index 2ca7fa311..760552bcc 100644
--- a/fastmcp_slim/fastmcp/server/auth/oauth_proxy/proxy.py
+++ b/fastmcp_slim/fastmcp/server/auth/oauth_proxy/proxy.py
@@ -397,8 +397,10 @@ class OAuthProxy(OAuthProvider, ConsentMixin):
redirect_uri) in the same browser. Cross-site navigations are
still prompted to block AS-in-the-middle attacks. Lower UX
friction, but weaker protection than True.
- - "external": skip the built-in consent screen; consent is handled
- externally (e.g. by the upstream IdP or a custom login page).
+ - "external": follow the same authorization path as False, but
+ suppress the warning as an operator acknowledgment that equivalent
+ consent and transaction-binding protections are enforced externally.
+ FastMCP does not provide or verify those external protections.
- False: skip consent entirely. SECURITY WARNING: only set to
False for local development or testing environments.
consent_csp_policy: Content Security Policy for the consent page.
diff --git a/fastmcp_slim/fastmcp/server/auth/oidc_proxy.py b/fastmcp_slim/fastmcp/server/auth/oidc_proxy.py
index e2bda58ab..5e4086c7a 100644
--- a/fastmcp_slim/fastmcp/server/auth/oidc_proxy.py
+++ b/fastmcp_slim/fastmcp/server/auth/oidc_proxy.py
@@ -306,8 +306,9 @@ class OIDCProxy(OAuthProxy):
require_authorization_consent: Whether to require user consent before authorizing clients (default True).
When True, users see a consent screen before being redirected to the upstream IdP.
When False, authorization proceeds directly without user confirmation.
- When "external", the built-in consent screen is skipped but no warning is
- logged, indicating that consent is handled externally (e.g. by the upstream IdP).
+ When "external", authorization follows the same direct path as False,
+ but the warning is suppressed as an operator acknowledgment that
+ equivalent protections are enforced externally.
SECURITY WARNING: Only set to False for local development or testing environments.
consent_csp_policy: Content Security Policy for the consent page.
If None (default), uses the built-in CSP policy with appropriate directives.
diff --git a/fastmcp_slim/fastmcp/server/auth/providers/auth0.py b/fastmcp_slim/fastmcp/server/auth/providers/auth0.py
index 0a3120a2b..29cc02a88 100644
--- a/fastmcp_slim/fastmcp/server/auth/providers/auth0.py
+++ b/fastmcp_slim/fastmcp/server/auth/providers/auth0.py
@@ -135,8 +135,9 @@ class Auth0Provider(OIDCProxy):
require_authorization_consent: Whether to require user consent before authorizing clients (default True).
When True, users see a consent screen before being redirected to Auth0.
When False, authorization proceeds directly without user confirmation.
- When "external", the built-in consent screen is skipped but no warning is
- logged, indicating that consent is handled externally (e.g. by the upstream IdP).
+ When "external", authorization follows the same direct path as False,
+ but the warning is suppressed as an operator acknowledgment that
+ equivalent protections are enforced externally.
SECURITY WARNING: Only set to False for local development or testing environments.
fallback_refresh_token_expiry_seconds: Lifetime for the FastMCP-issued
refresh token when the upstream provider omits `refresh_expires_in`
diff --git a/fastmcp_slim/fastmcp/server/auth/providers/aws.py b/fastmcp_slim/fastmcp/server/auth/providers/aws.py
index 01b1bcbd5..553c9b705 100644
--- a/fastmcp_slim/fastmcp/server/auth/providers/aws.py
+++ b/fastmcp_slim/fastmcp/server/auth/providers/aws.py
@@ -175,8 +175,9 @@ class AWSCognitoProvider(OIDCProxy):
require_authorization_consent: Whether to require user consent before authorizing clients (default True).
When True, users see a consent screen before being redirected to AWS Cognito.
When False, authorization proceeds directly without user confirmation.
- When "external", the built-in consent screen is skipped but no warning is
- logged, indicating that consent is handled externally (e.g. by the upstream IdP).
+ When "external", authorization follows the same direct path as False,
+ but the warning is suppressed as an operator acknowledgment that
+ equivalent protections are enforced externally.
SECURITY WARNING: Only set to False for local development or testing environments.
fallback_refresh_token_expiry_seconds: Lifetime for the FastMCP-issued
refresh token when the upstream provider omits `refresh_expires_in`
diff --git a/fastmcp_slim/fastmcp/server/auth/providers/azure.py b/fastmcp_slim/fastmcp/server/auth/providers/azure.py
index b8d4332e2..b0cf9d360 100644
--- a/fastmcp_slim/fastmcp/server/auth/providers/azure.py
+++ b/fastmcp_slim/fastmcp/server/auth/providers/azure.py
@@ -173,8 +173,9 @@ class AzureProvider(OAuthProxy):
require_authorization_consent: Whether to require user consent before authorizing clients (default True).
When True, users see a consent screen before being redirected to Azure.
When False, authorization proceeds directly without user confirmation.
- When "external", the built-in consent screen is skipped but no warning is
- logged, indicating that consent is handled externally (e.g. by the upstream IdP).
+ When "external", authorization follows the same direct path as False,
+ but the warning is suppressed as an operator acknowledgment that
+ equivalent protections are enforced externally.
SECURITY WARNING: Only set to False for local development or testing environments.
http_client: Optional httpx2.AsyncClient for connection pooling in JWKS fetches.
When provided, the client is reused for JWT key fetches and the caller
diff --git a/fastmcp_slim/fastmcp/server/auth/providers/clerk.py b/fastmcp_slim/fastmcp/server/auth/providers/clerk.py
index 6378e5de8..cb7a20660 100644
--- a/fastmcp_slim/fastmcp/server/auth/providers/clerk.py
+++ b/fastmcp_slim/fastmcp/server/auth/providers/clerk.py
@@ -327,8 +327,9 @@ class ClerkProvider(OAuthProxy):
into a 32-byte key. If not provided, the upstream client secret will be used to
derive a 32-byte key using PBKDF2.
require_authorization_consent: Whether to require user consent before authorizing
- clients (default True). When "external", the built-in consent screen is skipped
- but no warning is logged, indicating that consent is handled externally by Clerk.
+ clients (default True). When "external", authorization follows the same direct
+ path as False, but the warning is suppressed as an operator acknowledgment that
+ equivalent protections are enforced externally.
consent_csp_policy: Custom CSP policy for the consent page.
extra_authorize_params: Additional parameters to forward to Clerk's authorization
endpoint. Example: {"prompt": "login"} to force re-authentication.
diff --git a/fastmcp_slim/fastmcp/server/auth/providers/discord.py b/fastmcp_slim/fastmcp/server/auth/providers/discord.py
index bdb922fa2..8a6b657b6 100644
--- a/fastmcp_slim/fastmcp/server/auth/providers/discord.py
+++ b/fastmcp_slim/fastmcp/server/auth/providers/discord.py
@@ -241,8 +241,9 @@ class DiscordProvider(OAuthProxy):
require_authorization_consent: Whether to require user consent before authorizing clients (default True).
When True, users see a consent screen before being redirected to Discord.
When False, authorization proceeds directly without user confirmation.
- When "external", the built-in consent screen is skipped but no warning is
- logged, indicating that consent is handled externally (e.g. by the upstream IdP).
+ When "external", authorization follows the same direct path as False,
+ but the warning is suppressed as an operator acknowledgment that
+ equivalent protections are enforced externally.
SECURITY WARNING: Only set to False for local development or testing environments.
http_client: Optional httpx2.AsyncClient for connection pooling in token verification.
When provided, the client is reused across verify_token calls and the caller
diff --git a/fastmcp_slim/fastmcp/server/auth/providers/github.py b/fastmcp_slim/fastmcp/server/auth/providers/github.py
index db6718922..214d24c3b 100644
--- a/fastmcp_slim/fastmcp/server/auth/providers/github.py
+++ b/fastmcp_slim/fastmcp/server/auth/providers/github.py
@@ -257,8 +257,9 @@ class GitHubProvider(OAuthProxy):
require_authorization_consent: Whether to require user consent before authorizing clients (default True).
When True, users see a consent screen before being redirected to GitHub.
When False, authorization proceeds directly without user confirmation.
- When "external", the built-in consent screen is skipped but no warning is
- logged, indicating that consent is handled externally (e.g. by the upstream IdP).
+ When "external", authorization follows the same direct path as False,
+ but the warning is suppressed as an operator acknowledgment that
+ equivalent protections are enforced externally.
SECURITY WARNING: Only set to False for local development or testing environments.
http_client: Optional httpx2.AsyncClient for connection pooling in token verification.
When provided, the client is reused across verify_token calls and the caller
diff --git a/fastmcp_slim/fastmcp/server/auth/providers/google.py b/fastmcp_slim/fastmcp/server/auth/providers/google.py
index 7a9e4ba18..a8536b223 100644
--- a/fastmcp_slim/fastmcp/server/auth/providers/google.py
+++ b/fastmcp_slim/fastmcp/server/auth/providers/google.py
@@ -290,8 +290,9 @@ class GoogleProvider(OAuthProxy):
require_authorization_consent: Whether to require user consent before authorizing clients (default True).
When True, users see a consent screen before being redirected to Google.
When False, authorization proceeds directly without user confirmation.
- When "external", the built-in consent screen is skipped but no warning is
- logged, indicating that consent is handled externally (e.g. by Google's own consent).
+ When "external", authorization follows the same direct path as False,
+ but the warning is suppressed as an operator acknowledgment that
+ equivalent protections are enforced externally.
SECURITY WARNING: Only set to False for local development or testing environments.
extra_authorize_params: Additional parameters to forward to Google's authorization endpoint.
By default, GoogleProvider sets {"access_type": "offline", "prompt": "consent"} to ensure
diff --git a/fastmcp_slim/fastmcp/server/auth/providers/workos.py b/fastmcp_slim/fastmcp/server/auth/providers/workos.py
index bf955e821..18c0a763a 100644
--- a/fastmcp_slim/fastmcp/server/auth/providers/workos.py
+++ b/fastmcp_slim/fastmcp/server/auth/providers/workos.py
@@ -213,8 +213,9 @@ class WorkOSProvider(OAuthProxy):
require_authorization_consent: Whether to require user consent before authorizing clients (default True).
When True, users see a consent screen before being redirected to WorkOS.
When False, authorization proceeds directly without user confirmation.
- When "external", the built-in consent screen is skipped but no warning is
- logged, indicating that consent is handled externally (e.g. by the upstream IdP).
+ When "external", authorization follows the same direct path as False,
+ but the warning is suppressed as an operator acknowledgment that
+ equivalent protections are enforced externally.
SECURITY WARNING: Only set to False for local development or testing environments.
extra_authorize_params: Additional parameters to forward to WorkOS's authorization endpoint.
Useful for forcing scopes like `offline_access` so WorkOS issues a refresh token,