Skip to content

Remove automatic environment variable loading from auth providers#2752

Merged
jlowin merged 8 commits intomainfrom
env-var-auth
Dec 26, 2025
Merged

Remove automatic environment variable loading from auth providers#2752
jlowin merged 8 commits intomainfrom
env-var-auth

Conversation

@jlowin
Copy link
Copy Markdown
Member

@jlowin jlowin commented Dec 26, 2025

Auth providers no longer automatically read configuration from environment variables via pydantic-settings. This removes ~50-100 lines of boilerplate per provider and simplifies both the code and documentation.

Users can still use environment variables—they just read them explicitly:

auth = GitHubProvider(
    client_id=os.environ["GITHUB_CLIENT_ID"],
    client_secret=os.environ["GITHUB_CLIENT_SECRET"],
    base_url=os.environ["MY_BASE_URL"],
)

This is cleaner than magic prefix conventions like FASTMCP_SERVER_AUTH_GITHUB_CLIENT_ID, and lets users choose their own env var names or use any configuration library they prefer.

Also removes the server_auth setting from Settings (and FASTMCP_SERVER_AUTH env var) since it relied on the automatic env var loading that's being removed.

Breaking change for v3.0 - documented in upgrade guide.

Closes #2745

@marvin-context-protocol marvin-context-protocol Bot added breaking change Breaks backward compatibility. Requires minor version bump. Critical for maintainer attention. enhancement Improvement to existing functionality. For issues and smaller PR improvements. auth Related to authentication (Bearer, JWT, OAuth, WorkOS) for client or server. v3 Targeted for FastMCP 3 labels Dec 26, 2025
@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai Bot commented Dec 26, 2025

Warning

Rate limit exceeded

@jlowin has exceeded the limit for the number of commits that can be reviewed per hour. Please wait 15 minutes and 56 seconds before requesting another review.

⌛ How to resolve this issue?

After the wait time has elapsed, a review can be triggered using the @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

We recommend that you space out your commits to avoid hitting the rate limit.

🚦 How do rate limits work?

CodeRabbit enforces hourly rate limits for each developer per organization.

Our paid plans have higher rate limits than the trial, open-source and free plans. In all cases, we re-allow further reviews after a brief timeout.

Please see our FAQ for further information.

📥 Commits

Reviewing files that changed from the base of the PR and between a14e2b7 and b96a009.

📒 Files selected for processing (1)
  • docs/servers/auth/token-verification.mdx

Walkthrough

This PR removes automatic environment-variable loading from all auth providers and replaces pydantic BaseSettings-based ProviderSettings with explicit constructor parameters. It updates provider init signatures to require concrete values (removing NotSet sentinels), removes Settings classes and server_auth wiring from global Settings, changes FastMCP.init to default auth to None (no env-based auto-creation), and updates docs to show explicit os.environ reads and passing provider instances into FastMCP.

Possibly related PRs

  • jlowin/fastmcp PR 2676: Overlaps changes to multiple auth-provider constructors and FastMCP auth initialization (direct signature and auth handling modifications).
  • jlowin/fastmcp PR 2389: Directly modifies the OCI provider and its settings, which this PR also refactors to remove OCIProviderSettings and change env-var handling.
  • jlowin/fastmcp PR 2413: Touches the Scalekit provider with the same constructor/signature changes (parameter renames and removal of settings-based config).

Pre-merge checks and finishing touches

✅ Passed checks (5 passed)
Check name Status Explanation
Title check ✅ Passed The pull request title clearly summarizes the main change: removing automatic environment variable loading from auth providers.
Description check ✅ Passed The pull request description provides a clear explanation of changes, includes code examples, and notes the breaking change for v3.0. However, the checklist items are not checked off, which incompletely follows the template.
Linked Issues check ✅ Passed The PR fully meets the objectives from issue #2745: it removes environment variable auto-parsing from auth providers, reduces boilerplate, and requires explicit environment variable reading while preserving the ability to use env vars.
Out of Scope Changes check ✅ Passed All changes are in scope: documentation updates reflect the removal of env var auto-loading, provider constructors now require explicit parameters, and the server_auth setting is removed as planned.
Docstring Coverage ✅ Passed Docstring coverage is 94.12% which is sufficient. The required threshold is 80.00%.

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 6

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (8)
docs/integrations/aws-cognito.mdx (1)

261-277: Remove contradictory dead code from previous version.

This code block demonstrates the old automatic environment variable loading pattern that this PR specifically removes. Line 265's comment "Authentication is automatically configured from environment" describes the previous behavior where FastMCP could auto-load credentials without an explicit auth provider.

This contradicts the new explicit pattern shown in lines 241-260 and will confuse users about the correct approach. This entire code block should have been removed as part of the PR changes.

🔎 Proposed fix

Remove this entire code block:

-```python server.py
-from fastmcp import FastMCP
-from fastmcp.server.dependencies import get_access_token
-
-# Authentication is automatically configured from environment
-mcp = FastMCP(name="AWS Cognito Secured App")
-
-@mcp.tool
-async def get_access_token_claims() -> dict:
-    """Get the authenticated user's access token claims."""
-    token = get_access_token()
-    return {
-        "sub": token.claims.get("sub"),
-        "username": token.claims.get("username"),
-        "cognito:groups": token.claims.get("cognito:groups", []),
-    }
-```
docs/integrations/oci.mdx (1)

251-285: Duplicate "Production Configuration" section with conflicting content.

There's already a "Production Configuration" section starting at line 203. This duplicate section at line 251 contains:

  1. A duplicate header
  2. A code block that isn't properly closed before the next one starts (line 269 vs 270)
  3. Contradictory content—the second code block (lines 270-285) includes mcp = FastMCP(name="OCI Secured App") with the comment "Authentication is automatically configured from environment", which contradicts the PR's objective of removing automatic env var loading

This appears to be leftover content that should be removed.

🔎 Suggested fix: Remove the duplicate section
-## Production Configuration
-
-For production deployments, load sensitive credentials from environment variables:
-
-```python server.py
-import os
-from fastmcp import FastMCP
-from fastmcp.server.auth.providers.oci import OCIProvider
-
-# Load secrets from environment variables
-auth = OCIProvider(
-    config_url=os.environ.get("OCI_CONFIG_URL"),
-    client_id=os.environ.get("OCI_CLIENT_ID"),
-    client_secret=os.environ.get("OCI_CLIENT_SECRET"),
-    base_url=os.environ.get("BASE_URL", "https://your-server.com")
-)
-
-mcp = FastMCP(name="OCI Secured App", auth=auth)
-
-```python server.py
-from fastmcp import FastMCP
-from fastmcp.server.dependencies import get_access_token
-
-# Authentication is automatically configured from environment
-mcp = FastMCP(name="OCI Secured App")
-
-@mcp.tool
-def whoami() -> str:
-    """The whoami function is to test MCP server without requiring token exchange.
-    This tool can be used to test successful authentication against OCI IAM.
-    It will return logged in user's subject (username from IAM domain)."""
-    token = get_access_token()
-    user = token.claims.get("sub")
-    return f"You are User: {user}"
-```
docs/integrations/supabase.mdx (1)

103-112: Duplicate and contradictory FastMCP initialization.

Lines 103-108 correctly demonstrate the new explicit configuration pattern. However, lines 110-111 show a second mcp = FastMCP(...) call with the comment "Authentication is automatically configured from environment" and no auth parameter—this contradicts the PR's objective.

Additionally, the code block appears to be missing its closing fence.

🔎 Suggested fix: Remove the duplicate initialization
 mcp = FastMCP(name="Supabase Secured App", auth=auth)
-
-# Authentication is automatically configured from environment
-mcp = FastMCP(name="Supabase Protected Server")
+```
docs/integrations/descope.mdx (1)

66-69: Syntax error in code example.

Line 67 is missing quotes around the URL:

config_url=https://.../.well-known/openid-configuration,

This should be a string literal or environment variable reference.

🔎 Proposed fix
 auth_provider = DescopeProvider(
-    config_url=https://.../.well-known/openid-configuration,        # Your MCP Server .well-known URL
+    config_url="https://.../.well-known/openid-configuration",        # Your MCP Server .well-known URL
     base_url=SERVER_URL,                  # Your server's public URL
 )
docs/integrations/azure.mdx (1)

283-309: Duplicate "Production Configuration" heading.

This file has two H2 sections with the identical title "Production Configuration" (lines 241 and 283), creating the same issues as noted in google.mdx:

  • Duplicate heading hierarchy
  • Confusing navigation
  • Ambiguous anchor links

Apply the same consolidation approach as recommended for google.mdx to merge both production configuration concerns into a single, comprehensive section.

docs/integrations/auth0.mdx (1)

218-229: Remove contradictory leftover code.

Lines 218-229 contain orphaned code that contradicts the PR's objective:

from fastmcp import FastMCP

# Authentication is automatically configured from environment
mcp = FastMCP(name="Auth0 Secured App")

This example suggests automatic environment-based configuration, which is exactly what this PR removes. The comment "Authentication is automatically configured from environment" is now incorrect.

This appears to be leftover code from before the changes that should have been removed.

Proposed fix
 mcp = FastMCP(name="Auth0 Secured App", auth=auth)
-
-```python server.py
-from fastmcp import FastMCP
-
-# Authentication is automatically configured from environment
-mcp = FastMCP(name="Auth0 Secured App")
-
-@mcp.tool
-async def search_logs() -> list[str]:
-    """Search the service logs."""
-    # Your tool implementation here
-    pass
-```
+
+@mcp.tool
+async def protected_tool(query: str) -> str:
+    """A tool that requires Auth0 authentication to access."""
+    # Your tool implementation here
+    return f"Processing authenticated request: {query}"
+```
docs/integrations/github.mdx (1)

178-201: Duplicate "Production Configuration" heading.

Lines 138 and 178 both contain "Production Configuration" H2 headings. Consolidate these sections following the same pattern recommended for google.mdx and azure.mdx.

docs/integrations/discord.mdx (1)

204-213: Remove contradictory leftover code.

Lines 204-213 contain orphaned code that contradicts the PR's objective:

from fastmcp import FastMCP

mcp = FastMCP(name="Discord Secured App")

This code shows initialization without an explicit auth parameter, contradicting the PR's shift away from automatic environment-based configuration. This is leftover code from before the changes that should be removed (same issue as in auth0.mdx).

Proposed fix
 mcp = FastMCP(name="Discord Secured App", auth=auth)
-
-```python server.py
-from fastmcp import FastMCP
-
-mcp = FastMCP(name="Discord Secured App")
-
-@mcp.tool
-async def protected_tool(query: str) -> str:
-    """A tool that requires Discord authentication to access."""
-    return f"Processing authenticated request: {query}"
-```
+
+@mcp.tool
+async def protected_tool(query: str) -> str:
+    """A tool that requires Discord authentication to access."""
+    return f"Processing authenticated request: {query}"
+```
🧹 Nitpick comments (4)
src/fastmcp/server/auth/providers/oci.py (1)

60-67: Minor inconsistency in docstring example compared to documentation.

The docstring example uses None as the fallback for oci_domain_id:

oci_domain_id=iam_guid.split(".")[0] if iam_guid else None,

However, docs/python-sdk/fastmcp-server-auth-providers-oci.mdx line 73 uses an empty string "":

oci_domain_id=OCI_IAM_GUID.split(".")[0] if OCI_IAM_GUID else "",

Consider aligning these for consistency—None is typically preferred over empty string when representing "no value."

docs/integrations/descope.mdx (1)

108-111: Consider using os.environ[] for required fields.

Using os.environ.get() returns None when the variable is missing, which will likely cause a runtime error later. For required configuration like config_url, consider using os.environ["DESCOPE_CONFIG_URL"] to fail fast with a clear KeyError if the variable is not set.

🔎 Proposed fix
 auth = DescopeProvider(
-    config_url=os.environ.get("DESCOPE_CONFIG_URL"),
+    config_url=os.environ["DESCOPE_CONFIG_URL"],
     base_url=os.environ.get("BASE_URL", "https://your-server.com")
 )
docs/servers/auth/oauth-proxy.mdx (1)

573-577: Use os.environ[] for required fields for consistency.

The upgrade guide at docs/development/upgrade-guide.mdx lines 167-169 uses os.environ["..."] for required fields:

client_id=os.environ["GITHUB_CLIENT_ID"],
client_secret=os.environ["GITHUB_CLIENT_SECRET"],

This example uses os.environ.get() which returns None for missing variables. For consistency and fail-fast behavior, use os.environ[] for required fields.

🔎 Proposed fix
 # Load secrets from environment variables
 auth = GitHubProvider(
-    client_id=os.environ.get("GITHUB_CLIENT_ID"),
-    client_secret=os.environ.get("GITHUB_CLIENT_SECRET"),
+    client_id=os.environ["GITHUB_CLIENT_ID"],
+    client_secret=os.environ["GITHUB_CLIENT_SECRET"],
     base_url=os.environ.get("BASE_URL", "https://your-production-server.com")
 )
docs/servers/auth/token-verification.mdx (1)

306-328: Consider simplifying the scopes parsing logic.

Line 320 contains a complex one-liner for parsing required_scopes:

required_scopes=os.environ.get("JWT_REQUIRED_SCOPES", "").split(",") if os.environ.get("JWT_REQUIRED_SCOPES") else None

While functionally correct, this reads JWT_REQUIRED_SCOPES twice and may be unclear for documentation readers.

Clearer alternative
+# Parse optional comma-separated scopes
+scopes_env = os.environ.get("JWT_REQUIRED_SCOPES")
+required_scopes = scopes_env.split(",") if scopes_env else None
+
 # Load configuration from environment variables
 verifier = JWTVerifier(
     jwks_uri=os.environ.get("JWT_JWKS_URI"),
     issuer=os.environ.get("JWT_ISSUER"),
     audience=os.environ.get("JWT_AUDIENCE"),
-    required_scopes=os.environ.get("JWT_REQUIRED_SCOPES", "").split(",") if os.environ.get("JWT_REQUIRED_SCOPES") else None
+    required_scopes=required_scopes
 )

This approach:

  • Reads the environment variable once
  • Makes the conditional logic clearer
  • Adds a helpful comment
  • Is more suitable for documentation examples
📜 Review details

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between fc19f1f and 7931653.

⛔ Files ignored due to path filters (13)
  • tests/deprecated/test_settings.py is excluded by none and included by none
  • tests/server/auth/providers/test_auth0.py is excluded by none and included by none
  • tests/server/auth/providers/test_aws.py is excluded by none and included by none
  • tests/server/auth/providers/test_azure.py is excluded by none and included by none
  • tests/server/auth/providers/test_descope.py is excluded by none and included by none
  • tests/server/auth/providers/test_discord.py is excluded by none and included by none
  • tests/server/auth/providers/test_github.py is excluded by none and included by none
  • tests/server/auth/providers/test_google.py is excluded by none and included by none
  • tests/server/auth/providers/test_introspection.py is excluded by none and included by none
  • tests/server/auth/providers/test_scalekit.py is excluded by none and included by none
  • tests/server/auth/providers/test_supabase.py is excluded by none and included by none
  • tests/server/auth/providers/test_workos.py is excluded by none and included by none
  • tests/server/test_server.py is excluded by none and included by none
📒 Files selected for processing (47)
  • docs/development/upgrade-guide.mdx
  • docs/development/v3-notes/auth-provider-env-vars.mdx
  • docs/integrations/auth0.mdx
  • docs/integrations/authkit.mdx
  • docs/integrations/aws-cognito.mdx
  • docs/integrations/azure.mdx
  • docs/integrations/descope.mdx
  • docs/integrations/discord.mdx
  • docs/integrations/github.mdx
  • docs/integrations/google.mdx
  • docs/integrations/oci.mdx
  • docs/integrations/scalekit.mdx
  • docs/integrations/supabase.mdx
  • docs/integrations/workos.mdx
  • docs/python-sdk/fastmcp-server-auth-providers-auth0.mdx
  • docs/python-sdk/fastmcp-server-auth-providers-aws.mdx
  • docs/python-sdk/fastmcp-server-auth-providers-azure.mdx
  • docs/python-sdk/fastmcp-server-auth-providers-descope.mdx
  • docs/python-sdk/fastmcp-server-auth-providers-discord.mdx
  • docs/python-sdk/fastmcp-server-auth-providers-github.mdx
  • docs/python-sdk/fastmcp-server-auth-providers-google.mdx
  • docs/python-sdk/fastmcp-server-auth-providers-introspection.mdx
  • docs/python-sdk/fastmcp-server-auth-providers-jwt.mdx
  • docs/python-sdk/fastmcp-server-auth-providers-oci.mdx
  • docs/python-sdk/fastmcp-server-auth-providers-scalekit.mdx
  • docs/python-sdk/fastmcp-server-auth-providers-supabase.mdx
  • docs/python-sdk/fastmcp-server-auth-providers-workos.mdx
  • docs/python-sdk/fastmcp-settings.mdx
  • docs/servers/auth/authentication.mdx
  • docs/servers/auth/oauth-proxy.mdx
  • docs/servers/auth/oidc-proxy.mdx
  • docs/servers/auth/token-verification.mdx
  • src/fastmcp/server/auth/providers/auth0.py
  • src/fastmcp/server/auth/providers/aws.py
  • src/fastmcp/server/auth/providers/azure.py
  • src/fastmcp/server/auth/providers/descope.py
  • src/fastmcp/server/auth/providers/discord.py
  • src/fastmcp/server/auth/providers/github.py
  • src/fastmcp/server/auth/providers/google.py
  • src/fastmcp/server/auth/providers/introspection.py
  • src/fastmcp/server/auth/providers/jwt.py
  • src/fastmcp/server/auth/providers/oci.py
  • src/fastmcp/server/auth/providers/scalekit.py
  • src/fastmcp/server/auth/providers/supabase.py
  • src/fastmcp/server/auth/providers/workos.py
  • src/fastmcp/server/server.py
  • src/fastmcp/settings.py
💤 Files with no reviewable changes (13)
  • docs/python-sdk/fastmcp-settings.mdx
  • docs/python-sdk/fastmcp-server-auth-providers-aws.mdx
  • docs/python-sdk/fastmcp-server-auth-providers-discord.mdx
  • docs/python-sdk/fastmcp-server-auth-providers-github.mdx
  • docs/python-sdk/fastmcp-server-auth-providers-descope.mdx
  • docs/python-sdk/fastmcp-server-auth-providers-azure.mdx
  • docs/python-sdk/fastmcp-server-auth-providers-supabase.mdx
  • docs/python-sdk/fastmcp-server-auth-providers-scalekit.mdx
  • docs/python-sdk/fastmcp-server-auth-providers-google.mdx
  • docs/python-sdk/fastmcp-server-auth-providers-introspection.mdx
  • docs/python-sdk/fastmcp-server-auth-providers-auth0.mdx
  • docs/python-sdk/fastmcp-server-auth-providers-jwt.mdx
  • docs/python-sdk/fastmcp-server-auth-providers-workos.mdx
🧰 Additional context used
📓 Path-based instructions (4)
docs/**/*.mdx

📄 CodeRabbit inference engine (docs/.cursor/rules/mintlify.mdc)

docs/**/*.mdx: Use clear, direct language appropriate for technical audiences
Write in second person ('you') for instructions and procedures in MDX documentation
Use active voice over passive voice in MDX technical documentation
Employ present tense for current states and future tense for outcomes in MDX documentation
Maintain consistent terminology throughout all MDX documentation
Keep sentences concise while providing necessary context in MDX documentation
Use parallel structure in lists, headings, and procedures in MDX documentation
Lead with the most important information using inverted pyramid structure in MDX documentation
Use progressive disclosure in MDX documentation: present basic concepts before advanced ones
Break complex procedures into numbered steps in MDX documentation
Include prerequisites and context before instructions in MDX documentation
Provide expected outcomes for each major step in MDX documentation
End sections with next steps or related information in MDX documentation
Use descriptive, keyword-rich headings for navigation and SEO in MDX documentation
Focus on user goals and outcomes rather than system features in MDX documentation
Anticipate common questions and address them proactively in MDX documentation
Include troubleshooting for likely failure points in MDX documentation
Provide multiple pathways (beginner vs advanced) but offer an opinionated path to avoid overwhelming users in MDX documentation
Always include complete, runnable code examples that users can copy and execute in MDX documentation
Show proper error handling and edge case management in MDX code examples
Use realistic data instead of placeholder values in MDX code examples
Include expected outputs and results for verification in MDX code examples
Test all code examples thoroughly before publishing in MDX documentation
Specify language and include filename when relevant in MDX code examples
Add explanatory comments for complex logic in MDX code examples
Document all API...

Files:

  • docs/integrations/discord.mdx
  • docs/servers/auth/token-verification.mdx
  • docs/integrations/scalekit.mdx
  • docs/servers/auth/oidc-proxy.mdx
  • docs/integrations/aws-cognito.mdx
  • docs/integrations/supabase.mdx
  • docs/development/v3-notes/auth-provider-env-vars.mdx
  • docs/servers/auth/oauth-proxy.mdx
  • docs/integrations/authkit.mdx
  • docs/integrations/workos.mdx
  • docs/integrations/google.mdx
  • docs/integrations/azure.mdx
  • docs/integrations/auth0.mdx
  • docs/integrations/descope.mdx
  • docs/development/upgrade-guide.mdx
  • docs/servers/auth/authentication.mdx
  • docs/integrations/github.mdx
  • docs/python-sdk/fastmcp-server-auth-providers-oci.mdx
  • docs/integrations/oci.mdx
docs/**/*.{md,mdx,json}

📄 CodeRabbit inference engine (AGENTS.md)

Documentation uses Mintlify framework. Files must be in docs.json to be included. Never modify docs/python-sdk/** (auto-generated)

Files:

  • docs/integrations/discord.mdx
  • docs/servers/auth/token-verification.mdx
  • docs/integrations/scalekit.mdx
  • docs/servers/auth/oidc-proxy.mdx
  • docs/integrations/aws-cognito.mdx
  • docs/integrations/supabase.mdx
  • docs/development/v3-notes/auth-provider-env-vars.mdx
  • docs/servers/auth/oauth-proxy.mdx
  • docs/integrations/authkit.mdx
  • docs/integrations/workos.mdx
  • docs/integrations/google.mdx
  • docs/integrations/azure.mdx
  • docs/integrations/auth0.mdx
  • docs/integrations/descope.mdx
  • docs/development/upgrade-guide.mdx
  • docs/servers/auth/authentication.mdx
  • docs/integrations/github.mdx
  • docs/python-sdk/fastmcp-server-auth-providers-oci.mdx
  • docs/integrations/oci.mdx
docs/**/*.{md,mdx}

📄 CodeRabbit inference engine (AGENTS.md)

docs/**/*.{md,mdx}: Code examples in documentation must explain before showing code and make blocks fully runnable (include imports)
Documentation structure: Headers form navigation guide with logical H2/H3 hierarchy. Content should be user-focused with sections motivating features (why) before mechanics (how). Use prose over code comments for important information
Never use 'This isn't...' or 'not just...' constructions in writing - state what something IS directly. Avoid defensive writing patterns

Files:

  • docs/integrations/discord.mdx
  • docs/servers/auth/token-verification.mdx
  • docs/integrations/scalekit.mdx
  • docs/servers/auth/oidc-proxy.mdx
  • docs/integrations/aws-cognito.mdx
  • docs/integrations/supabase.mdx
  • docs/development/v3-notes/auth-provider-env-vars.mdx
  • docs/servers/auth/oauth-proxy.mdx
  • docs/integrations/authkit.mdx
  • docs/integrations/workos.mdx
  • docs/integrations/google.mdx
  • docs/integrations/azure.mdx
  • docs/integrations/auth0.mdx
  • docs/integrations/descope.mdx
  • docs/development/upgrade-guide.mdx
  • docs/servers/auth/authentication.mdx
  • docs/integrations/github.mdx
  • docs/python-sdk/fastmcp-server-auth-providers-oci.mdx
  • docs/integrations/oci.mdx
src/fastmcp/**/*.py

📄 CodeRabbit inference engine (AGENTS.md)

src/fastmcp/**/*.py: Python ≥ 3.10 with full type annotations required
Prioritize readable, understandable code - clarity over cleverness. Avoid obfuscated or confusing patterns even if shorter
Follow existing patterns and maintain consistency in code implementation
Be intentional about re-exports - don't blindly re-export everything to parent namespaces. Core types defining a module's purpose should be exported. Specialized features can live in submodules. Only re-export to fastmcp.* for most fundamental types
Never use bare except - be specific with exception types

Files:

  • src/fastmcp/server/auth/providers/descope.py
  • src/fastmcp/server/auth/providers/jwt.py
  • src/fastmcp/server/auth/providers/discord.py
  • src/fastmcp/server/auth/providers/auth0.py
  • src/fastmcp/server/auth/providers/oci.py
  • src/fastmcp/server/server.py
  • src/fastmcp/server/auth/providers/github.py
  • src/fastmcp/settings.py
  • src/fastmcp/server/auth/providers/supabase.py
  • src/fastmcp/server/auth/providers/azure.py
  • src/fastmcp/server/auth/providers/scalekit.py
  • src/fastmcp/server/auth/providers/google.py
  • src/fastmcp/server/auth/providers/introspection.py
  • src/fastmcp/server/auth/providers/workos.py
  • src/fastmcp/server/auth/providers/aws.py
🧠 Learnings (4)
📚 Learning: 2025-12-25T15:53:07.646Z
Learnt from: CR
Repo: jlowin/fastmcp PR: 0
File: AGENTS.md:0-0
Timestamp: 2025-12-25T15:53:07.646Z
Learning: Applies to tests/**/*.py : Pass FastMCP servers directly to clients for testing without network complexity; only use HTTP transport when explicitly testing network features

Applied to files:

  • docs/servers/auth/oidc-proxy.mdx
  • docs/servers/auth/oauth-proxy.mdx
📚 Learning: 2025-11-26T21:52:08.947Z
Learnt from: CR
Repo: jlowin/fastmcp PR: 0
File: docs/.cursor/rules/mintlify.mdc:0-0
Timestamp: 2025-11-26T21:52:08.947Z
Learning: Applies to docs/**/*.mdx : Provide authentication examples showing proper format in MDX API documentation

Applied to files:

  • docs/integrations/auth0.mdx
  • docs/servers/auth/authentication.mdx
📚 Learning: 2025-12-25T15:53:07.646Z
Learnt from: CR
Repo: jlowin/fastmcp PR: 0
File: AGENTS.md:0-0
Timestamp: 2025-12-25T15:53:07.646Z
Learning: Applies to src/fastmcp/**/*.py : Python ≥ 3.10 with full type annotations required

Applied to files:

  • src/fastmcp/server/server.py
📚 Learning: 2025-12-01T15:48:05.095Z
Learnt from: jlowin
Repo: jlowin/fastmcp PR: 0
File: :0-0
Timestamp: 2025-12-01T15:48:05.095Z
Learning: PR #2505 in fastmcp adds NEW functionality to get_access_token(): it now first checks request.scope["user"] for the token (which never existed before), then falls back to _sdk_get_access_token() (the only thing the original code did). This is not a reversal of order but entirely new functionality to fix stale token issues.

Applied to files:

  • src/fastmcp/server/auth/providers/aws.py
🧬 Code graph analysis (13)
src/fastmcp/server/auth/providers/descope.py (2)
src/fastmcp/server/auth/auth.py (1)
  • TokenVerifier (220-243)
src/fastmcp/utilities/auth.py (1)
  • parse_scopes (9-34)
src/fastmcp/server/auth/providers/jwt.py (1)
src/fastmcp/utilities/auth.py (1)
  • parse_scopes (9-34)
src/fastmcp/server/auth/providers/discord.py (2)
src/fastmcp/server/context.py (2)
  • client_id (358-364)
  • debug (445-459)
src/fastmcp/utilities/auth.py (1)
  • parse_scopes (9-34)
src/fastmcp/server/auth/providers/auth0.py (1)
src/fastmcp/utilities/auth.py (1)
  • parse_scopes (9-34)
src/fastmcp/server/auth/providers/oci.py (1)
src/fastmcp/utilities/auth.py (1)
  • parse_scopes (9-34)
src/fastmcp/server/server.py (1)
src/fastmcp/server/auth/auth.py (1)
  • AuthProvider (91-217)
src/fastmcp/server/auth/providers/github.py (2)
src/fastmcp/server/context.py (2)
  • client_id (358-364)
  • debug (445-459)
src/fastmcp/utilities/auth.py (1)
  • parse_scopes (9-34)
src/fastmcp/server/auth/providers/supabase.py (2)
src/fastmcp/utilities/auth.py (1)
  • parse_scopes (9-34)
src/fastmcp/server/auth/providers/jwt.py (1)
  • JWTVerifier (139-461)
src/fastmcp/server/auth/providers/azure.py (3)
src/fastmcp/server/context.py (2)
  • client_id (358-364)
  • info (461-475)
src/fastmcp/utilities/auth.py (1)
  • parse_scopes (9-34)
src/fastmcp/server/auth/providers/jwt.py (1)
  • JWTVerifier (139-461)
src/fastmcp/server/auth/providers/scalekit.py (3)
src/fastmcp/server/context.py (2)
  • client_id (358-364)
  • warning (477-491)
src/fastmcp/server/auth/auth.py (1)
  • TokenVerifier (220-243)
src/fastmcp/utilities/auth.py (1)
  • parse_scopes (9-34)
src/fastmcp/server/auth/providers/introspection.py (2)
src/fastmcp/server/context.py (1)
  • client_id (358-364)
src/fastmcp/utilities/auth.py (1)
  • parse_scopes (9-34)
src/fastmcp/server/auth/providers/workos.py (2)
src/fastmcp/utilities/auth.py (1)
  • parse_scopes (9-34)
src/fastmcp/server/auth/providers/jwt.py (1)
  • JWTVerifier (139-461)
src/fastmcp/server/auth/providers/aws.py (1)
src/fastmcp/utilities/auth.py (1)
  • parse_scopes (9-34)
🪛 LanguageTool
docs/integrations/oci.mdx

[style] ~101-~101: You have already used this phrasing in nearby sentences. Consider replacing it to add variety to your writing.
Context: ...ity-federation) For token exchange, we need to configure Identity propagation trust. T...

(REP_NEED_TO_VB)

🪛 Ruff (0.14.10)
src/fastmcp/server/auth/providers/jwt.py

185-185: Avoid specifying long messages outside the exception class

(TRY003)


188-188: Avoid specifying long messages outside the exception class

(TRY003)

src/fastmcp/server/auth/providers/discord.py

230-230: Possible hardcoded password assigned to argument: "upstream_token_endpoint"

(S106)

src/fastmcp/server/auth/providers/github.py

223-223: Possible hardcoded password assigned to argument: "upstream_token_endpoint"

(S106)

src/fastmcp/server/auth/providers/scalekit.py

88-88: Avoid specifying long messages outside the exception class

(TRY003)

⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (4)
  • GitHub Check: Run tests with lowest-direct dependencies
  • GitHub Check: Run tests: Python 3.10 on ubuntu-latest
  • GitHub Check: Run tests: Python 3.13 on ubuntu-latest
  • GitHub Check: Run tests: Python 3.10 on windows-latest
🔇 Additional comments (27)
src/fastmcp/server/auth/providers/introspection.py (1)

68-104: LGTM! Clean refactor to explicit constructor parameters.

The initialization logic correctly:

  • Requires explicit introspection_url, client_id, and client_secret parameters
  • Handles SecretStr normalization appropriately
  • Delegates scope parsing to parse_scopes utility
  • Passes parsed values to the parent class
src/fastmcp/server/auth/providers/google.py (1)

186-278: LGTM! Well-structured refactor to explicit parameters.

The GoogleProvider initialization:

  • Correctly requires explicit client_id, client_secret, and base_url
  • Appropriately defaults required_scopes to ["openid"] for Google OIDC
  • Properly handles the issuer_url fallback to base_url
  • Maintains Google-specific defaults for extra_authorize_params
src/fastmcp/server/auth/providers/supabase.py (1)

70-113: LGTM! Clean implementation with appropriate defaults.

The SupabaseProvider correctly:

  • Requires explicit project_url and base_url parameters
  • Defaults algorithm to "ES256" matching Supabase's recommendation
  • Normalizes URLs by stripping trailing slashes
  • Passes parsed scopes to the JWTVerifier
src/fastmcp/server/auth/providers/auth0.py (1)

58-123: LGTM! Consistent implementation with other auth providers.

The Auth0Provider follows the same pattern as other refactored providers:

  • Explicit required parameters (config_url, client_id, client_secret, audience, base_url)
  • Scope parsing with ["openid"] default
  • Direct parameter passing to the parent class
src/fastmcp/server/auth/providers/aws.py (1)

97-170: LGTM! Clean refactor with Cognito-specific handling.

The AWSCognitoProvider correctly:

  • Requires explicit user_pool_id, client_id, client_secret, and base_url
  • Constructs the OIDC discovery URL from aws_region and user_pool_id
  • Uses the specialized AWSCognitoTokenVerifier for claim filtering
src/fastmcp/server/auth/providers/jwt.py (1)

158-229: LGTM! Robust JWT verifier with proper validation.

The JWTVerifier correctly:

  • Validates that exactly one of public_key or jwks_uri is provided
  • Validates the algorithm against a comprehensive whitelist
  • Parses scopes using the shared utility
  • Defaults algorithm to "RS256" when not specified

The static analysis hints about long exception messages (TRY003) can be safely ignored here—the messages provide clear context for debugging configuration errors.

src/fastmcp/server/auth/providers/discord.py (1)

172-246: LGTM! Clean refactor to explicit constructor parameters.

The constructor correctly:

  • Requires client_id, client_secret, and base_url as mandatory parameters
  • Uses parse_scopes to handle flexible scope input with sensible default ["identify"]
  • Defaults issuer_url to base_url when not provided
  • Passes all parameters directly to the parent OAuthProxy

The Ruff S106 hint on line 230 is a false positive—upstream_token_endpoint is a URL constant, not a password.

src/fastmcp/server/auth/providers/oci.py (1)

117-169: LGTM! Constructor properly simplified to explicit parameters.

The implementation correctly:

  • Requires config_url, client_id, client_secret, and base_url
  • Uses parse_scopes with appropriate default ["openid"] for OIDC
  • Passes parameters directly to OIDCProxy parent
src/fastmcp/server/auth/providers/workos.py (2)

134-211: LGTM! WorkOSProvider correctly refactored to explicit parameters.

The implementation:

  • Properly normalizes authkit_domain to ensure HTTPS and trailing slash removal
  • Uses parse_scopes with empty list default (appropriate for WorkOS which may not require scopes)
  • Correctly defaults issuer_url to base_url

250-288: LGTM! AuthKitProvider simplified appropriately.

The constructor correctly:

  • Accepts explicit authkit_domain and base_url parameters
  • Uses parse_scopes with None default (correct for optional scopes)
  • Creates JWTVerifier with parsed scopes when no custom verifier provided
src/fastmcp/server/auth/providers/azure.py (2)

90-107: LGTM! Azure provider correctly requires explicit scopes.

Unlike other providers, required_scopes is a required parameter here (no default). This is appropriate since Azure requires custom API scopes to be explicitly defined under "Expose an API" in the Azure Portal.


151-211: Implementation is correct and well-documented.

The scope handling logic properly:

  • Filters OIDC scopes from validation (Azure doesn't include them in scp claim)
  • Prefixes custom scopes with identifier_uri for Azure
  • Advertises full scopes via valid_scopes while only validating non-OIDC ones
docs/development/upgrade-guide.mdx (1)

153-177: LGTM! Clear migration documentation.

The upgrade guide effectively:

  • Shows before/after code examples for the breaking change
  • Lists all affected providers comprehensively
  • Notes the FastMCPSettings simplification
  • Uses proper code group formatting
src/fastmcp/settings.py (1)

8-11: LGTM! Clean removal of unused imports.

The removal of TYPE_CHECKING and ImportString aligns with eliminating the authentication provider wiring from settings.

docs/servers/auth/oidc-proxy.mdx (1)

236-265: LGTM! Clear production configuration guidance.

This section demonstrates the correct pattern:

  • Explicit environment variable loading
  • Complete, runnable code example
  • Appropriate security reminder about keeping secrets out of codebase
  • Single, well-structured Production Configuration section
src/fastmcp/server/server.py (1)

202-202: LGTM! Clean removal of implicit environment-based auth.

The change from NotSet-based default to explicit None makes the auth parameter behavior transparent. Users must now explicitly pass an AuthProvider instance, eliminating the previous implicit environment-variable loading.

docs/integrations/authkit.mdx (1)

81-96: LGTM! Excellent production configuration example.

This section clearly demonstrates the new explicit environment variable loading pattern. The code is complete, runnable, and uses os.environ.get() consistently for all configuration values with appropriate defaults.

docs/integrations/workos.mdx (1)

176-188: LGTM! Environment variable configuration is correct.

The code example properly demonstrates explicit environment variable loading using os.environ.get() with appropriate defaults. This aligns with the new pattern across all auth providers.

docs/development/v3-notes/auth-provider-env-vars.mdx (1)

1-73: LGTM! Excellent upgrade documentation.

This documentation clearly explains the breaking change, provides strong rationale, and offers straightforward migration guidance. The structure follows best practices with:

  • Clear status and background
  • Well-articulated reasons (maintenance burden, complexity, etc.)
  • Concrete before/after examples
  • Backwards compatibility considerations
  • Complete list of removed features

The content is user-focused and anticipates developer questions effectively.

docs/servers/auth/authentication.mdx (1)

181-202: LGTM! Clear and concise configuration guidance.

The restructured configuration section effectively communicates the new explicit approach. The documentation:

  • Clearly explains programmatic instantiation
  • Provides production-focused environment variable guidance
  • Includes a complete, runnable code example
  • Notes flexibility in environment variable naming

This aligns well with the PR objectives and MDX documentation guidelines.

src/fastmcp/server/auth/providers/descope.py (1)

63-145: LGTM! Clean removal of settings-based configuration.

The updated DescopeProvider constructor successfully removes automatic environment variable loading while maintaining backwards compatibility:

  • Clear required vs optional parameters
  • Explicit parameter types and defaults
  • Proper validation with actionable error messages
  • Supports both new API (config_url) and old API (project_id + descope_base_url)
  • Consistent use of parse_scopes helper

The initialization logic correctly handles both API paths and provides clear errors when configuration is invalid.

src/fastmcp/server/auth/providers/scalekit.py (1)

63-142: LGTM! Well-executed migration with good backwards compatibility.

The updated ScalekitProvider constructor successfully removes automatic environment variable loading while maintaining backwards compatibility through deprecation warnings:

  • Required parameters (environment_url, resource_id) are explicit
  • Graceful handling of deprecated mcp_url parameter with migration guidance
  • Deprecation warning for unnecessary client_id parameter
  • Consistent use of parse_scopes helper
  • Clear error messages for missing configuration

The implementation balances the cleanup goals with user-friendly migration support.

docs/integrations/scalekit.mdx (1)

96-109: Fix variable reference inconsistency in code example.

Lines 103-105 reference SCALEKIT_ENVIRONMENT_URL, SCALEKIT_RESOURCE_ID, and BASE_URL directly as if they were Python variables, but they should be environment variable lookups via os.environ.get(). The code won't execute as-is because these variables are undefined.

🔎 Proposed fix
 # Load configuration from environment variables
 auth = ScalekitProvider(
-    environment_url=os.environ.get("SCALEKIT_ENVIRONMENT_URL"),
-    resource_id=os.environ.get("SCALEKIT_RESOURCE_ID"),
+    environment_url=os.environ["SCALEKIT_ENVIRONMENT_URL"],
+    resource_id=os.environ["SCALEKIT_RESOURCE_ID"],
     base_url=os.environ.get("BASE_URL", "https://your-server.com")
 )

Note: Using os.environ["KEY"] (without .get()) for required variables will raise a clear KeyError if they're missing, while optional variables like BASE_URL can use .get() with a default.

⛔ Skipped due to learnings
Learnt from: CR
Repo: jlowin/fastmcp PR: 0
File: AGENTS.md:0-0
Timestamp: 2025-12-25T15:53:07.646Z
Learning: Applies to tests/**/*.py : Pass FastMCP servers directly to clients for testing without network complexity; only use HTTP transport when explicitly testing network features
src/fastmcp/server/auth/providers/github.py (4)

1-20: Documentation clearly reflects the new explicit configuration approach.

The updated docstring effectively demonstrates the shift from automatic environment variable loading to explicit parameter passing, which aligns perfectly with the PR objectives.


209-212: Scope parsing logic correctly handles defaults and user-provided values.

The implementation properly defaults to ["user"] when None is provided, while allowing users to specify an empty list or custom scopes. The parse_scopes call provides normalization even for list inputs, which is a defensive pattern consistent with the broader provider refactor.


170-240: Constructor successfully migrates to explicit parameter-based configuration.

The refactored __init__ method properly implements the explicit parameter approach:

  • All required credentials are now explicit parameters with proper type annotations
  • Default values are sensible and well-documented
  • The fallback logic for issuer_url (line 229) is clean and correct
  • Parameter pass-through to OAuthProxy and GitHubTokenVerifier is properly wired

The implementation follows Python ≥3.10 guidelines with union types and provides full type annotations as required.


223-223: Static analysis false positive - GitHub OAuth endpoint URL is safe.

The Ruff warning about a hardcoded password is a false positive. Line 223 contains GitHub's public OAuth token endpoint URL (https://github.com/login/oauth/access_token), not a secret. This is a well-known, documented endpoint required for the OAuth flow. The actual sensitive credential (client_secret) is correctly passed as a constructor parameter rather than being hardcoded.

Comment thread docs/integrations/auth0.mdx Outdated
Comment thread docs/integrations/aws-cognito.mdx Outdated
Comment thread docs/integrations/discord.mdx Outdated
Comment thread docs/integrations/google.mdx Outdated
Comment thread docs/integrations/workos.mdx Outdated
Comment thread docs/python-sdk/fastmcp-server-auth-providers-oci.mdx
Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 0

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
docs/integrations/oci.mdx (1)

129-154: Add error handling for missing environment variables.

The code uses os.environ.get() which returns None if variables are not set, but only OCI_IAM_GUID is checked before use (line 152). Lines 153-154 pass OCI_CLIENT_ID and OCI_CLIENT_SECRET directly to TokenExchangeSigner without validation, which could cause confusing runtime errors if these environment variables are missing.

🔎 Proposed fix to validate required environment variables
 # Load configuration from environment
-OCI_IAM_GUID = os.environ.get("OCI_IAM_GUID")
-OCI_CLIENT_ID = os.environ.get("OCI_CLIENT_ID")
-OCI_CLIENT_SECRET = os.environ.get("OCI_CLIENT_SECRET")
+OCI_IAM_GUID = os.environ["OCI_IAM_GUID"]
+OCI_CLIENT_ID = os.environ["OCI_CLIENT_ID"]
+OCI_CLIENT_SECRET = os.environ["OCI_CLIENT_SECRET"]

Then update line 152:

     signer = TokenExchangeSigner(
         jwt_or_func=token,
-        oci_domain_id=OCI_IAM_GUID.split(".")[0] if OCI_IAM_GUID else "",
+        oci_domain_id=OCI_IAM_GUID.split(".")[0],
         client_id=OCI_CLIENT_ID,
         client_secret=OCI_CLIENT_SECRET,
     )

This will raise a clear KeyError with the missing variable name if any required environment variable is not set.

🧹 Nitpick comments (1)
docs/integrations/oci.mdx (1)

222-234: Use consistent pattern for required vs. optional environment variables.

The code mixes os.environ.get() (lines 222-224) and os.environ[] (lines 228, 231-233) inconsistently. Using .get() suggests the values are optional, but config_url, client_id, and client_secret are likely required by OCIProvider. Consider using os.environ[] for required variables to provide clear error messages when they're missing, and reserve .get() with defaults only for truly optional parameters like base_url (line 225).

🔎 Proposed fix for consistency
 # Production setup with encrypted persistent token storage
 auth_provider = OCIProvider(
-    config_url=os.environ.get("OCI_CONFIG_URL"),
-    client_id=os.environ.get("OCI_CLIENT_ID"),
-    client_secret=os.environ.get("OCI_CLIENT_SECRET"),
+    config_url=os.environ["OCI_CONFIG_URL"],
+    client_id=os.environ["OCI_CLIENT_ID"],
+    client_secret=os.environ["OCI_CLIENT_SECRET"],
     base_url=os.environ.get("BASE_URL", "https://your-production-domain.com"),
 
     # Production token management

This makes the pattern consistent: required variables use [] (raising clear errors when missing), while optional variables use .get() with sensible defaults.

📜 Review details

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 7931653 and a14e2b7.

📒 Files selected for processing (11)
  • docs/integrations/auth0.mdx
  • docs/integrations/aws-cognito.mdx
  • docs/integrations/azure.mdx
  • docs/integrations/discord.mdx
  • docs/integrations/github.mdx
  • docs/integrations/google.mdx
  • docs/integrations/oci.mdx
  • docs/integrations/workos.mdx
  • docs/python-sdk/fastmcp-server-auth-providers-oci.mdx
  • src/fastmcp/server/server.py
  • src/fastmcp/settings.py
💤 Files with no reviewable changes (6)
  • docs/integrations/azure.mdx
  • docs/integrations/discord.mdx
  • docs/integrations/workos.mdx
  • docs/integrations/github.mdx
  • docs/integrations/aws-cognito.mdx
  • docs/integrations/auth0.mdx
✅ Files skipped from review due to trivial changes (1)
  • docs/integrations/google.mdx
🚧 Files skipped from review as they are similar to previous changes (2)
  • src/fastmcp/server/server.py
  • docs/python-sdk/fastmcp-server-auth-providers-oci.mdx
🧰 Additional context used
📓 Path-based instructions (4)
docs/**/*.mdx

📄 CodeRabbit inference engine (docs/.cursor/rules/mintlify.mdc)

docs/**/*.mdx: Use clear, direct language appropriate for technical audiences
Write in second person ('you') for instructions and procedures in MDX documentation
Use active voice over passive voice in MDX technical documentation
Employ present tense for current states and future tense for outcomes in MDX documentation
Maintain consistent terminology throughout all MDX documentation
Keep sentences concise while providing necessary context in MDX documentation
Use parallel structure in lists, headings, and procedures in MDX documentation
Lead with the most important information using inverted pyramid structure in MDX documentation
Use progressive disclosure in MDX documentation: present basic concepts before advanced ones
Break complex procedures into numbered steps in MDX documentation
Include prerequisites and context before instructions in MDX documentation
Provide expected outcomes for each major step in MDX documentation
End sections with next steps or related information in MDX documentation
Use descriptive, keyword-rich headings for navigation and SEO in MDX documentation
Focus on user goals and outcomes rather than system features in MDX documentation
Anticipate common questions and address them proactively in MDX documentation
Include troubleshooting for likely failure points in MDX documentation
Provide multiple pathways (beginner vs advanced) but offer an opinionated path to avoid overwhelming users in MDX documentation
Always include complete, runnable code examples that users can copy and execute in MDX documentation
Show proper error handling and edge case management in MDX code examples
Use realistic data instead of placeholder values in MDX code examples
Include expected outputs and results for verification in MDX code examples
Test all code examples thoroughly before publishing in MDX documentation
Specify language and include filename when relevant in MDX code examples
Add explanatory comments for complex logic in MDX code examples
Document all API...

Files:

  • docs/integrations/oci.mdx
docs/**/*.{md,mdx,json}

📄 CodeRabbit inference engine (AGENTS.md)

Documentation uses Mintlify framework. Files must be in docs.json to be included. Never modify docs/python-sdk/** (auto-generated)

Files:

  • docs/integrations/oci.mdx
docs/**/*.{md,mdx}

📄 CodeRabbit inference engine (AGENTS.md)

docs/**/*.{md,mdx}: Code examples in documentation must explain before showing code and make blocks fully runnable (include imports)
Documentation structure: Headers form navigation guide with logical H2/H3 hierarchy. Content should be user-focused with sections motivating features (why) before mechanics (how). Use prose over code comments for important information
Never use 'This isn't...' or 'not just...' constructions in writing - state what something IS directly. Avoid defensive writing patterns

Files:

  • docs/integrations/oci.mdx
src/fastmcp/**/*.py

📄 CodeRabbit inference engine (AGENTS.md)

src/fastmcp/**/*.py: Python ≥ 3.10 with full type annotations required
Prioritize readable, understandable code - clarity over cleverness. Avoid obfuscated or confusing patterns even if shorter
Follow existing patterns and maintain consistency in code implementation
Be intentional about re-exports - don't blindly re-export everything to parent namespaces. Core types defining a module's purpose should be exported. Specialized features can live in submodules. Only re-export to fastmcp.* for most fundamental types
Never use bare except - be specific with exception types

Files:

  • src/fastmcp/settings.py
🪛 LanguageTool
docs/integrations/oci.mdx

[style] ~101-~101: You have already used this phrasing in nearby sentences. Consider replacing it to add variety to your writing.
Context: ...ity-federation) For token exchange, we need to configure Identity propagation trust. T...

(REP_NEED_TO_VB)

⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (4)
  • GitHub Check: Run tests: Python 3.10 on windows-latest
  • GitHub Check: Run tests with lowest-direct dependencies
  • GitHub Check: Run tests: Python 3.10 on ubuntu-latest
  • GitHub Check: Run tests: Python 3.13 on ubuntu-latest
🔇 Additional comments (5)
src/fastmcp/settings.py (2)

8-11: LGTM: Import cleanup aligns with auth provider removal.

The removal of TYPE_CHECKING and ImportString-related imports is appropriate given that server_auth configuration and lazy type resolution have been eliminated. All remaining imports are actively used.


142-334: Removal of server_auth configuration is complete and safe.

The deletion of server_auth and server_auth_class from the Settings class is clean. No code attempts to access these removed settings fields. The codebase correctly uses AuthProvider as an explicit constructor parameter instead (see server.py line 203 and http.py lines 135, 267), aligning with the v3.0 breaking change where auth providers require explicit instantiation.

docs/integrations/oci.mdx (3)

20-20: Clear production URL guidance.

The updated prerequisite clearly distinguishes between development and production URLs with concrete examples.


91-91: Updated guidance aligns with explicit configuration.

The note appropriately directs users to configure the OCIProvider explicitly in code, consistent with the removal of automatic environment variable loading.


101-114: Generic placeholders improve clarity.

The CLI command now uses clear placeholder syntax (<IAM_GUID>, <CLIENT_ID>) and includes explicit instructions to replace them, making the example more universally applicable.

@marvin-context-protocol
Copy link
Copy Markdown
Contributor

Test Failure Analysis

Summary: The integration test test_call_tool_list_commits is failing due to GitHub API rate limiting (429 Too Many Requests), which causes a 30-second timeout.

Root Cause: The test is hitting the GitHub Copilot MCP API (https://api.githubcopilot.com/mcp/) and receiving a 429 error. While tests/integration_tests/conftest.py has logic to automatically skip tests on rate limit errors, it's not catching this case because:

  1. The 429 error occurs during the call_tool request (line 106 in test file)
  2. The test times out after 30 seconds before the error can be properly handled
  3. The 429 HTTPStatusError only surfaces during the __aexit__ teardown phase
  4. The pytest hook (pytest_runtest_makereport) only processes failures during the call phase (conftest.py:61), not the teardown phase

Suggested Solution:

The existing rate limit handling in conftest.py needs to also process the teardown phase to catch 429 errors that surface during cleanup:

# In tests/integration_tests/conftest.py, line 60-66
if (
    report.when in ("call", "teardown")  # Add teardown phase
    and report.failed
    and not hasattr(report, "wasxfail")
    and item.module.__name__ == "tests.integration_tests.test_github_mcp_remote"
    and _is_rate_limit_error(call.excinfo, report)
):

This will allow the hook to catch rate limit errors that only appear during async context manager cleanup, converting them to skipped tests instead of failures.

Detailed Analysis

Error from logs:

Failed: Timeout (>30.0s) from pytest-timeout.

# During teardown:
httpx.HTTPStatusError: Client error '429 Too Many Requests' for url 'https://api.githubcopilot.com/mcp/'
For more information check: https://developer.mozilla.org/en-US/docs/Web/HTTP/Status/429

The timeout occurs at:

  • test_github_mcp_remote.py:106 - await streamable_http_client.call_tool("list_commits", ...)

The 429 error surfaces during teardown at:

  • client.py:503 in __aexit__
  • client.py:630 in _disconnect
  • Eventually bubbling up through the async exit stack

The current hook implementation checks report.when == "call" which misses errors that only become visible during teardown.

Related Files
  • tests/integration_tests/conftest.py:60-66 - pytest hook that needs modification
  • tests/integration_tests/test_github_mcp_remote.py:99-124 - failing test
  • src/fastmcp/client/client.py:503,630 - where the 429 error surfaces during cleanup

🤖 Automated analysis by marvin

@jlowin jlowin merged commit 568300e into main Dec 26, 2025
11 checks passed
@jlowin jlowin deleted the env-var-auth branch December 26, 2025 20:38
@jlowin jlowin mentioned this pull request Dec 26, 2025
6 tasks
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

auth Related to authentication (Bearer, JWT, OAuth, WorkOS) for client or server. breaking change Breaks backward compatibility. Requires minor version bump. Critical for maintainer attention. enhancement Improvement to existing functionality. For issues and smaller PR improvements. v3 Targeted for FastMCP 3

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Remove env var configuration from auth providers

1 participant