Skip to content

Fix ty 0.0.5 type errors#2676

Merged
jlowin merged 6 commits intomainfrom
fix/ty-type-errors
Dec 23, 2025
Merged

Fix ty 0.0.5 type errors#2676
jlowin merged 6 commits intomainfrom
fix/ty-type-errors

Conversation

@jlowin
Copy link
Copy Markdown
Member

@jlowin jlowin commented Dec 22, 2025

Upgrades to ty 0.0.5 and fixes all type errors, enabling stricter type checking rules that were previously disabled.

Key changes:

  • Add elicit() method overloads for dict/list response_type patterns (single-select with titles, multi-select)
  • Fix createdAt in tasks/get handler - was passing string where datetime expected
  • Replace bare # type: ignore with explicit casts or specific ignore codes with explanations
  • Use cast(type[AuthProvider], ...) for server_auth_class instead of ignoring call-non-callable
  • Add basedpyright config for future comparison (61 errors vs ty's 0)

All no-matching-overload and call-non-callable ty rules now enabled.

Fixes type errors when upgrading to ty 0.0.5:

- Add base_url validation to auth providers (AWS, Azure, Discord, GitHub, Google, WorkOS)
- Add partial[] to tool/prompt decorator return types
- Add type ignores for PydanticAdapter generic aliases (pending strawgate/py-key-value#250)
- Add type ignores for Depends() in tests (type checker doesn't understand DI unwrapping)
Added type ignores for Pydantic field aliases (_meta) and MCP SDK optional
fields that ty doesn't yet recognize. Also removed useless code_challenge_method
parameters from tests that were being silently ignored by Pydantic.

- Added `# type: ignore[call-arg]` with explanatory comments for _meta (Pydantic alias)
- Added type ignores for MCP SDK optional fields (limit, resource_owner, jwt_signing_key, code_challenge_method)
- Removed code_challenge_method from AuthorizationParams test instantiations (not a real field)
- Upgraded ruff pre-commit hook to v0.14.10
- Enabled unknown-argument rule in ty (was previously ignored)
- Add elicit() overloads for dict/list response_type patterns
- Use cast for server_auth_class instead of type ignore
- Add basedpyright config for future comparison
- Parse createdAt ISO string to datetime in tasks/get handler
- Use explicit type annotations instead of bare type ignores
- Add explanatory comments to remaining type ignores
@marvin-context-protocol marvin-context-protocol Bot added enhancement Improvement to existing functionality. For issues and smaller PR improvements. tests labels Dec 22, 2025
@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai Bot commented Dec 22, 2025

Walkthrough

Adds local typing relaxations and a few runtime validations: many call sites now use # type: ignore[...] for Pydantic _meta/meta alias usage; several auth provider classes (AWS, Azure, Discord, GitHub, Google, WorkOS) require a base_url at initialization and raise ValueError if missing; elicit gained multiple overloads to accept additional response_type shapes; Server.__init__ now instantiates dynamic auth provider classes; task handlers parse created_at into UTC datetimes; minor safe-access and return-type widening changes in server utilities.

Possibly related PRs

Pre-merge checks and finishing touches

❌ Failed checks (1 warning, 1 inconclusive)
Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 78.38% which is insufficient. The required threshold is 80.00%. You can run @coderabbitai generate docstrings to improve docstring coverage.
Description check ❓ Inconclusive The PR description is detailed and comprehensive, covering key changes and objectives, but the Contributors Checklist items are not marked and the description does not explicitly close an issue number. Complete the Contributors Checklist by checking off applicable items and ensure the description references the associated issue number (e.g., 'My change closes #XXXX').
✅ Passed checks (1 passed)
Check name Status Explanation
Title check ✅ Passed The title 'Fix ty 0.0.5 type errors' accurately describes the main objective of the PR, which is upgrading to ty 0.0.5 and fixing type errors to enable stricter type checking rules.
✨ Finishing touches
  • 📝 Generate docstrings
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch fix/ty-type-errors

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.

@marvin-context-protocol
Copy link
Copy Markdown
Contributor

marvin-context-protocol Bot commented Dec 22, 2025

Test Failure Analysis

Summary: 37 tests failing across authentication provider test suites because they're missing the newly-required base_url parameter.

Root Cause: This PR (#2676) adds base_url validation to all OAuth proxy providers (AWS, Azure, Discord, GitHub, Google, WorkOS) as part of fixing ty 0.0.5 type errors. The providers now raise ValueError if base_url is not provided via parameter or environment variable.

Suggested Solution: Update all failing tests to include a base_url parameter when instantiating providers.

Example fix for tests/server/auth/providers/test_azure.py:

def test_init_defaults(self):
    """Test that default values are applied correctly."""
    provider = AzureProvider(
        client_id="test_client",
        client_secret="test_secret",
        tenant_id="test-tenant",
        required_scopes=["read"],
        jwt_signing_key="test-secret",
        base_url="https://example.com",  # Add this line
    )

Apply similar changes to all test files:

  • tests/server/auth/providers/test_azure.py (28 tests)
  • tests/server/auth/providers/test_discord.py (2 tests)
  • tests/server/auth/providers/test_github.py (2 tests)
  • tests/server/auth/providers/test_google.py (4 tests)
  • tests/server/auth/providers/test_workos.py (1 test)
Detailed Analysis

The validation was added in this PR to satisfy ty 0.0.5 type checking:

if not settings.base_url:
    raise ValueError(
        "base_url is required - set via parameter or FASTMCP_SERVER_AUTH_{PROVIDER}_BASE_URL"
    )

Changed files:

  • src/fastmcp/server/auth/providers/aws.py - Lines 200-203
  • src/fastmcp/server/auth/providers/azure.py - Lines 236-239
  • src/fastmcp/server/auth/providers/discord.py - Lines 270-273
  • src/fastmcp/server/auth/providers/github.py - Lines 265-268
  • src/fastmcp/server/auth/providers/google.py - Lines 289-292
  • src/fastmcp/server/auth/providers/workos.py - Lines 237-240

The validation is correct - OAuth proxy providers need base_url to construct redirect URIs and metadata endpoints. The tests just need updating to reflect this requirement.

Related Files

Source files with new validation (from this PR):

  • src/fastmcp/server/auth/providers/aws.py
  • src/fastmcp/server/auth/providers/azure.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/workos.py

Test files needing updates:

  • tests/server/auth/providers/test_azure.py - 28 failing tests
  • tests/server/auth/providers/test_discord.py - 2 failing tests
  • tests/server/auth/providers/test_github.py - 2 failing tests
  • tests/server/auth/providers/test_google.py - 4 failing tests
  • tests/server/auth/providers/test_workos.py - 1 failing test

Comment updated after re-analyzing workflow run 20445082974

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: 1

🧹 Nitpick comments (5)
src/fastmcp/server/auth/oauth_proxy.py (1)

1396-1401: Consider adding explanatory comments for consistency.

The type: ignore[assignment] annotations are appropriate here, as authlib's refresh_token() and fetch_token() methods likely return more specific types than dict[str, Any]. However, for consistency with lines 1024 and 1107, consider adding brief explanatory comments.

Suggested improvement for consistency
-            token_response: dict[str, Any] = await oauth_client.refresh_token(  # type: ignore[assignment]
+            token_response: dict[str, Any] = await oauth_client.refresh_token(  # type: ignore[assignment]  # authlib returns specific token type
                 url=self._upstream_token_endpoint,
                 idp_tokens: dict[str, Any] = await oauth_client.fetch_token(
                     **token_params
-                )  # type: ignore[assignment]
+                )  # type: ignore[assignment]  # authlib returns specific token type

Also applies to: 1803-1805

src/fastmcp/server/tasks/requests.py (1)

10-10: Align createdAt parsing between get and cancel handlers

The new Literal[...]-typed mcp_state and robust created_at_dt parsing in tasks_get_handler look good and defensively handle missing/invalid Redis values.

tasks_cancel_handler still calls datetime.fromisoformat(created_at) directly, which can raise if the stored string has a "Z" suffix or is otherwise malformed, whereas tasks_get_handler now normalizes and falls back to now(). For consistency and resilience, consider sharing the parsing logic (e.g., a small _parse_created_at(created_at: str | None) -> datetime helper) and using it in both places.

Possible helper extraction
+def _parse_created_at(created_at: str | None) -> datetime:
+    """Parse createdAt from Redis, falling back to current UTC time."""
+    if created_at:
+        try:
+            return datetime.fromisoformat(created_at.replace("Z", "+00:00"))
+        except (ValueError, AttributeError):
+            pass
+    return datetime.now(timezone.utc)
+
@@
-        # createdAt is required per spec, but can be None from Redis
-        # Parse ISO string to datetime, or use current time as fallback
-        if created_at:
-            try:
-                created_at_dt = datetime.fromisoformat(
-                    created_at.replace("Z", "+00:00")
-                )
-            except (ValueError, AttributeError):
-                created_at_dt = datetime.now(timezone.utc)
-        else:
-            created_at_dt = datetime.now(timezone.utc)
+        created_at_dt = _parse_created_at(created_at)
@@
-            createdAt=datetime.fromisoformat(created_at)
-            if created_at
-            else datetime.now(timezone.utc),
+            createdAt=_parse_created_at(created_at),

Also applies to: 148-151, 168-178, 416-420

src/fastmcp/server/server.py (1)

2472-2477: HTTP path logging hardening is correct; consider reusing server_path

Using hasattr/getattr(app.state, "path", "") avoids attribute errors and ensures a sane default for logging. There’s a tiny duplication between server_path and the later path = getattr(app.state, "path", "").lstrip("/") that could be collapsed to one variable, but that’s purely cosmetic.

Also applies to: 2504-2507

src/fastmcp/server/context.py (1)

883-904: elicit overloads comprehensively cover new dict/list patterns

The additional overloads for:

  • dict[str, dict[str, str]] (single-select with titles),
  • list[list[str]] (multi-select),
  • list[dict[str, dict[str, str]]] (multi-select with titles),

plus the widened concrete signature, align with the documented return types (str or list[str] as appropriate) and still funnel through parse_elicit_response_type. This gives callers much better type information for the supported response patterns without changing control flow.

You might later expand the main docstring to briefly mention these dict/list selection shapes so the high-level docs match the overload comments.

Also applies to: 905-914, 915-921, 925-948, 950-966

src/fastmcp/client/client.py (1)

1576-1576: Approved with minor suggestion for comment clarity.

The targeted type ignore with specific error code [call-arg] is appropriate for working around upstream MCP SDK type signature issues. However, the comment "Optional field in MCP SDK" is slightly ambiguous since two parameters are being passed.

Consider clarifying which parameter(s) cause the type error, for example:

params = PaginatedRequestParams(cursor=cursor, limit=limit)  # type: ignore[call-arg]  # cursor and limit are optional in MCP SDK but ty requires explicit handling

This helps future maintainers understand exactly what type issue is being suppressed.

📜 Review details

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between bca310c and 407d43d.

⛔ Files ignored due to path filters (9)
  • .pre-commit-config.yaml is excluded by none and included by none
  • pyproject.toml is excluded by none and included by none
  • tests/client/test_elicitation.py is excluded by none and included by none
  • tests/server/auth/test_oauth_consent_flow.py is excluded by none and included by none
  • tests/server/auth/test_oauth_proxy.py is excluded by none and included by none
  • tests/server/tasks/test_task_dependencies.py is excluded by none and included by none
  • tests/server/test_dependencies.py is excluded by none and included by none
  • tests/utilities/test_components.py is excluded by none and included by none
  • uv.lock is excluded by !**/*.lock and included by none
📒 Files selected for processing (20)
  • src/fastmcp/client/client.py
  • src/fastmcp/client/elicitation.py
  • src/fastmcp/client/tasks.py
  • src/fastmcp/prompts/prompt.py
  • src/fastmcp/resources/resource.py
  • src/fastmcp/resources/template.py
  • src/fastmcp/server/auth/oauth_proxy.py
  • src/fastmcp/server/auth/providers/aws.py
  • src/fastmcp/server/auth/providers/azure.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/workos.py
  • src/fastmcp/server/context.py
  • src/fastmcp/server/dependencies.py
  • src/fastmcp/server/middleware/caching.py
  • src/fastmcp/server/server.py
  • src/fastmcp/server/tasks/handlers.py
  • src/fastmcp/server/tasks/requests.py
  • src/fastmcp/tools/tool.py
🧰 Additional context used
📓 Path-based instructions (1)
**/*.py

📄 CodeRabbit inference engine (AGENTS.md)

**/*.py: Use Python ≥ 3.10 with full type annotations
Never use bare except - be specific with exception types

Files:

  • src/fastmcp/resources/template.py
  • src/fastmcp/resources/resource.py
  • src/fastmcp/tools/tool.py
  • src/fastmcp/server/auth/providers/workos.py
  • src/fastmcp/client/elicitation.py
  • src/fastmcp/client/client.py
  • src/fastmcp/server/auth/providers/azure.py
  • src/fastmcp/server/middleware/caching.py
  • src/fastmcp/prompts/prompt.py
  • src/fastmcp/server/auth/providers/github.py
  • src/fastmcp/client/tasks.py
  • src/fastmcp/server/tasks/handlers.py
  • src/fastmcp/server/server.py
  • src/fastmcp/server/auth/providers/aws.py
  • src/fastmcp/server/auth/oauth_proxy.py
  • src/fastmcp/server/auth/providers/discord.py
  • src/fastmcp/server/context.py
  • src/fastmcp/server/tasks/requests.py
  • src/fastmcp/server/auth/providers/google.py
  • src/fastmcp/server/dependencies.py
🧠 Learnings (5)
📚 Learning: 2025-11-26T21:51:44.174Z
Learnt from: CR
Repo: jlowin/fastmcp PR: 0
File: .cursor/rules/core-mcp-objects.mdc:0-0
Timestamp: 2025-11-26T21:51:44.174Z
Learning: Review and update related Manager classes (ToolManager, ResourceManager, PromptManager) when modifying MCP object definitions

Applied to files:

  • src/fastmcp/prompts/prompt.py
📚 Learning: 2025-12-21T21:37:55.015Z
Learnt from: CR
Repo: jlowin/fastmcp PR: 0
File: AGENTS.md:0-0
Timestamp: 2025-12-21T21:37:55.015Z
Learning: When modifying MCP functionality (Tools, Resources, Resource Templates, Prompts), changes typically need to be applied across all object types

Applied to files:

  • src/fastmcp/prompts/prompt.py
📚 Learning: 2025-12-21T21:37:55.015Z
Learnt from: CR
Repo: jlowin/fastmcp PR: 0
File: AGENTS.md:0-0
Timestamp: 2025-12-21T21:37:55.015Z
Learning: Applies to src/fastmcp/**/__init__.py : Core types that define a module's purpose should be exported (e.g., `Middleware` from `fastmcp.server.middleware`), while specialized features can live in submodules

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/dependencies.py
📚 Learning: 2025-12-01T15:53:29.709Z
Learnt from: jlowin
Repo: jlowin/fastmcp PR: 2505
File: src/fastmcp/server/dependencies.py:9-9
Timestamp: 2025-12-01T15:53:29.709Z
Learning: In the MCP SDK (mcp.server.auth.middleware.bearer_auth), the AuthenticatedUser class has an `access_token` attribute (not `token`) that returns an AccessToken object. To get the raw token string, you would use `user.access_token.token`.

Applied to files:

  • src/fastmcp/server/dependencies.py
🧬 Code graph analysis (4)
src/fastmcp/server/server.py (2)
src/fastmcp/settings.py (1)
  • server_auth_class (396-412)
src/fastmcp/server/providers/proxy.py (1)
  • ProxyClient (683-717)
src/fastmcp/server/auth/oauth_proxy.py (1)
src/fastmcp/server/context.py (1)
  • error (473-487)
src/fastmcp/server/context.py (2)
src/fastmcp/server/dependencies.py (1)
  • message (426-427)
src/fastmcp/server/elicitation.py (1)
  • AcceptedElicitation (105-109)
src/fastmcp/server/tasks/requests.py (2)
src/fastmcp/client/tasks.py (1)
  • status (171-199)
src/fastmcp/client/client.py (1)
  • CallToolResult (117-124)
🪛 Ruff (0.14.10)
src/fastmcp/server/auth/providers/workos.py

238-240: Avoid specifying long messages outside the exception class

(TRY003)

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

266-268: Avoid specifying long messages outside the exception class

(TRY003)

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

201-203: Avoid specifying long messages outside the exception class

(TRY003)

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

271-273: Avoid specifying long messages outside the exception class

(TRY003)

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

290-292: 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). (1)
  • GitHub Check: Run tests: Python 3.10 on windows-latest
🔇 Additional comments (24)
src/fastmcp/server/auth/providers/google.py (1)

289-292: Base URL validation is correctly implemented.

The validation ensures base_url is provided before initializing the OAuth proxy, preventing type errors and providing clear feedback to users. The error message appropriately guides users to set the value via parameter or environment variable.

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

237-240: Base URL validation is correctly implemented.

The validation ensures base_url is provided before initializing the OAuth proxy. The error message is clear and consistent with other providers in this PR.

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

236-240: Base URL validation is correctly implemented.

The validation follows the established pattern in this file of using a msg variable for error messages. The check appropriately ensures base_url is provided before proceeding with OAuth proxy initialization.

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

200-203: Base URL validation is correctly implemented.

The validation ensures base_url is provided before initializing the OIDC proxy. The error message correctly includes COGNITO in the environment variable name, matching the provider's configuration prefix.

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

270-273: Base URL validation is correctly implemented.

The validation ensures base_url is provided before initializing the OAuth proxy. The implementation is consistent with other providers in this PR.

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

265-268: Base URL validation is correctly implemented.

The validation ensures base_url is provided before initializing the OAuth proxy. This completes the consistent base_url validation pattern across all OAuth providers in this PR, improving type safety and providing clear error messages when configuration is missing.

src/fastmcp/client/elicitation.py (1)

68-72: LGTM!

The type: ignore[call-arg] annotation is correctly scoped and the explanatory comment clearly documents that _meta is a Pydantic alias for the meta field. This is a valid pattern for handling Pydantic's field aliasing with strict type checkers.

src/fastmcp/tools/tool.py (2)

116-120: LGTM!

The type: ignore[call-arg] is correctly scoped with an explanatory comment. Consistent with the pattern used throughout the PR for handling Pydantic's _meta alias.


193-196: LGTM!

The type ignore is properly applied to the _meta parameter with the correct call-arg code and explanatory comment.

src/fastmcp/resources/resource.py (2)

121-134: LGTM!

Both TextResourceContents and BlobResourceContents constructions correctly apply type: ignore[call-arg] with explanatory comments for the _meta Pydantic alias.


293-296: LGTM!

The type: ignore[call-arg] is properly applied to the SDKResource construction with a clear comment explaining the Pydantic alias behavior.

src/fastmcp/server/tasks/handlers.py (1)

95-104: LGTM!

The type: ignore[call-arg] annotation is correctly applied to the JSONRPCNotification construction with an explanatory comment. The _meta structure for task-related notifications is properly formatted per SEP-1686 spec.

src/fastmcp/prompts/prompt.py (2)

109-115: LGTM!

The type: ignore[call-arg] is correctly scoped with an explanatory comment for the GetPromptResult construction.


157-166: LGTM!

The type ignore is properly applied to the SDKPrompt construction with a clear comment. Based on learnings, this change is correctly applied across all MCP object types (Tools, Resources, and Prompts) in the PR.

src/fastmcp/server/middleware/caching.py (1)

197-202: Scoped PydanticAdapter type ignores look good

The added comment plus # type: ignore[arg-type] on pydantic_model are narrowly scoped and keep runtime semantics unchanged while unblocking stricter type checking. Nothing else to fix here.

Also applies to: 205-208, 211-214, 217-222, 225-228, 231-234

src/fastmcp/resources/template.py (1)

240-251: _meta override handling and typing clarification are correct

Using overrides.get("_meta", self.get_meta(...)) preserves existing defaulting while allowing explicit _meta overrides, and the targeted # type: ignore[call-arg] is appropriate for the Pydantic alias. Looks solid.

src/fastmcp/server/dependencies.py (1)

633-642: Narrow resource_owner type-ignore is appropriate

The explicit # type: ignore[call-arg] on resource_owner matches it being optional in the SDK and keeps the conversion logic unchanged. No further changes needed.

src/fastmcp/server/tasks/requests.py (1)

272-277: _meta propagation for task-related MCP results is consistent

The added _meta=... arguments on CallToolResult and ReadResourceResult, with clear # type: ignore[call-arg] notes about the Pydantic alias, nicely standardize how related-task metadata is attached across error, tuple, and plain-content branches. No issues here.

Also applies to: 300-305, 307-310, 324-336

src/fastmcp/server/server.py (4)

246-257: Auth provider instantiation via server_auth_class cast is sound

Casting fastmcp.settings.server_auth_class to type[AuthProvider] and instantiating it when auth is NotSet keeps behavior (lazy construction from settings) while avoiding call-non-callable issues from the property’s annotation. Guarding on server_auth is not None ensures this only runs when configured.


1850-1869: Expanded tool decorator return type matches actual usage patterns

Including partial[Callable[[AnyFunction], FunctionTool] | FunctionTool] in the return type accurately models the decorator-usage cases where a partially applied function is returned. This should make stricter type checkers happier without changing runtime behavior.


2239-2255: prompt decorator return type union is now aligned with real-world use

Mirroring the tool decorator, the prompt decorator’s return type now covers both direct FunctionPrompt returns and partially applied callables. This improves typing fidelity and doesn’t affect execution.


2911-2918: as_proxy backend handling via ProxyClient(cast(Any, backend)) is reasonable

For non-Client backends, wrapping the transport in ProxyClient and then using .new() for fresh sessions matches the intended API, and the cast(Any, backend) pragmatically sidesteps complex union typing without changing runtime behavior.

src/fastmcp/server/context.py (1)

675-685: tool_results typing with a focused ignore is acceptable

Annotating tool_results as list[SamplingMessageContentBlock] and using # type: ignore[assignment] keeps the local type precise while deferring to the upstream run_sampling_tools signature. Given the downstream usage (content=tool_results), this is a safe and well-scoped typing workaround.

Also applies to: 689-692

src/fastmcp/client/tasks.py (1)

376-383: Legacy ToolResult → CallToolResult conversion _meta handling is consistent

Passing _meta=raw_result.meta with a # type: ignore[call-arg] matches the Pydantic alias behavior and keeps legacy ToolResult conversions aligned with how server-side code attaches metadata.

Comment on lines +1024 to 1026
error="invalid_client", # type: ignore[arg-type] # "invalid_client" is valid OAuth error but not in Literal type
error_description="Client ID is required",
)
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.

⚠️ Potential issue | 🟡 Minor

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
# Find the oauth_proxy.py file and examine lines around 1024, 1107, 1396, 1805
git ls-files | grep oauth_proxy.py

Repository: jlowin/fastmcp

Length of output: 134


🏁 Script executed:

#!/bin/bash
# Search for AuthorizeError class definition
rg -n "class AuthorizeError" --type=py

Repository: jlowin/fastmcp

Length of output: 40


🏁 Script executed:

#!/bin/bash
# Examine lines 1020-1030 to see the context
sed -n '1020,1030p' src/fastmcp/server/auth/oauth_proxy.py | cat -n

Repository: jlowin/fastmcp

Length of output: 636


🏁 Script executed:

#!/bin/bash
# Examine lines 1100-1110 to see the context
sed -n '1100,1110p' src/fastmcp/server/auth/oauth_proxy.py | cat -n

Repository: jlowin/fastmcp

Length of output: 579


🏁 Script executed:

#!/bin/bash
# Examine lines 1390-1400 to see if there are comments
sed -n '1390,1400p' src/fastmcp/server/auth/oauth_proxy.py | cat -n

Repository: jlowin/fastmcp

Length of output: 781


🏁 Script executed:

#!/bin/bash
# Examine lines 1800-1810 to see if there are comments
sed -n '1800,1810p' src/fastmcp/server/auth/oauth_proxy.py | cat -n

Repository: jlowin/fastmcp

Length of output: 553


🏁 Script executed:

#!/bin/bash
# Look for the AuthorizeError class definition
rg -n "^class AuthorizeError" src/fastmcp/server/auth/oauth_proxy.py -A 20

Repository: jlowin/fastmcp

Length of output: 40


🏁 Script executed:

#!/bin/bash
# Search for where error parameter is typed in AuthorizeError
rg -n "class AuthorizeError" -A 30 --type=py

Repository: jlowin/fastmcp

Length of output: 40


🏁 Script executed:

#!/bin/bash
# Search for AuthorizeError class definition across the entire codebase
rg -n "class AuthorizeError" --type=py

Repository: jlowin/fastmcp

Length of output: 40


🏁 Script executed:

#!/bin/bash
# Search for AuthorizeError imports in oauth_proxy.py
rg -n "AuthorizeError" src/fastmcp/server/auth/oauth_proxy.py | head -5

Repository: jlowin/fastmcp

Length of output: 158


🏁 Script executed:

#!/bin/bash
# Look at the imports section of oauth_proxy.py
head -100 src/fastmcp/server/auth/oauth_proxy.py | grep -n "import\|from"

Repository: jlowin/fastmcp

Length of output: 1534


🏁 Script executed:

#!/bin/bash
# Find the AuthorizeError definition in mcp module
find . -name "*.py" -type f -exec grep -l "class AuthorizeError" {} \;

Repository: jlowin/fastmcp

Length of output: 40


🏁 Script executed:

#!/bin/bash
# Check the imports more carefully
sed -n '39,50p' src/fastmcp/server/auth/oauth_proxy.py | cat -n

Repository: jlowin/fastmcp

Length of output: 396


🏁 Script executed:

#!/bin/bash
# Search for AuthorizeError definition in installed packages or local code
python3 << 'EOF'
import inspect
try:
    from mcp.server.auth.provider import AuthorizeError
    print(f"Location: {inspect.getfile(AuthorizeError)}")
    print(f"\nSignature:")
    print(inspect.signature(AuthorizeError.__init__))
    print(f"\nSource:")
    print(inspect.getsource(AuthorizeError))
except Exception as e:
    print(f"Error: {e}")
EOF

Repository: jlowin/fastmcp

Length of output: 144


🏁 Script executed:

#!/bin/bash
# Look for .pyi stub files or search for AuthorizeError in a different way
find . -name "*.pyi" -type f | xargs grep -l "AuthorizeError" 2>/dev/null || echo "No stub files found"

# Also search for the error parameter type definition
rg -n "error.*Literal" --type=py src/fastmcp/ | head -20

Repository: jlowin/fastmcp

Length of output: 427


🏁 Script executed:

#!/bin/bash
# Get more context around lines 1396 and 1805 to understand what needs comments
echo "=== Lines 1390-1400 context ==="
sed -n '1390,1400p' src/fastmcp/server/auth/oauth_proxy.py

echo ""
echo "=== Lines 1800-1810 context ==="
sed -n '1800,1810p' src/fastmcp/server/auth/oauth_proxy.py

Repository: jlowin/fastmcp

Length of output: 1188


🏁 Script executed:

#!/bin/bash
# Check the type annotations for the oauth_client methods to understand the assignment type ignore
rg -n "oauth_client.*refresh_token\|oauth_client.*fetch_token" src/fastmcp/server/auth/oauth_proxy.py -B 2 -A 2

Repository: jlowin/fastmcp

Length of output: 40


🏁 Script executed:

#!/bin/bash
# Get the full function signatures around those lines to understand context better
sed -n '1370,1410p' src/fastmcp/server/auth/oauth_proxy.py | cat -n

Repository: jlowin/fastmcp

Length of output: 2356


🏁 Script executed:

#!/bin/bash
# Check what the PR description or commit message says about these changes
git log --oneline -20

Repository: jlowin/fastmcp

Length of output: 109


🏁 Script executed:

#!/bin/bash
# Check the git diff or changes in this branch
git diff main src/fastmcp/server/auth/oauth_proxy.py | grep -A 3 -B 3 "type: ignore" | head -60

Repository: jlowin/fastmcp

Length of output: 1828


🏁 Script executed:

#!/bin/bash
# Look at the git show for the recent changes
git show HEAD:src/fastmcp/server/auth/oauth_proxy.py | sed -n '1020,1030p'

Repository: jlowin/fastmcp

Length of output: 559


🏁 Script executed:

#!/bin/bash
# Check what was changed - look at line 1396 and 1805 more carefully
echo "Line 1396 area:"
sed -n '1394,1398p' src/fastmcp/server/auth/oauth_proxy.py
echo ""
echo "Line 1805 area:"
sed -n '1803,1807p' src/fastmcp/server/auth/oauth_proxy.py

Repository: jlowin/fastmcp

Length of output: 594


🏁 Script executed:

#!/bin/bash
# Verify the actual lines in the current state to confirm the review comment is accurate
echo "=== Lines 1024-1026 (line numbers) ==="
sed -n '1024,1026p' src/fastmcp/server/auth/oauth_proxy.py

echo ""
echo "=== Lines 1107-1109 ==="
sed -n '1107,1109p' src/fastmcp/server/auth/oauth_proxy.py

echo ""
echo "=== Line 1396 (type: ignore[assignment] area) ==="
sed -n '1396,1396p' src/fastmcp/server/auth/oauth_proxy.py

echo ""
echo "=== Line 1805 (type: ignore[assignment] area) ==="
sed -n '1805,1805p' src/fastmcp/server/auth/oauth_proxy.py

Repository: jlowin/fastmcp

Length of output: 784


Add explanatory comments to lines 1396 and 1805 for consistency.

Lines 1024 and 1107 correctly use type: ignore[arg-type] with clear explanatory comments for the "invalid_client" error, which is documented in RFC 6749 Section 5.2. However, lines 1396 and 1805 have been updated to the more specific type: ignore[assignment] but lack explanatory comments. For consistency with the PR objective and the pattern established in the file, add comments explaining why the assignment type ignores are needed:

  • Line 1396: Explain the return type mismatch for oauth_client.refresh_token()
  • Line 1805: Explain the return type mismatch for oauth_client.fetch_token()
🤖 Prompt for AI Agents
In src/fastmcp/server/auth/oauth_proxy.py around lines 1396 and 1805, add
explanatory inline comments next to the existing type: ignore[assignment]
annotations to match the pattern used elsewhere: for line 1396, note that
oauth_client.refresh_token() returns a broader/untyped dict (or a type that
doesn't match our expected return type) so we intentionally ignore an assignment
type mismatch; for line 1805, note that oauth_client.fetch_token() similarly
returns a dynamic/untyped structure (per the underlying OAuth library) so we
intentionally ignore an assignment type mismatch. Keep the comments concise and
reference that the mismatch is due to the OAuth library return types (analogous
to the RFC comment pattern used in the file).

All OAuth providers (Google, GitHub, Azure, Discord, WorkOS) now properly
validate that base_url is provided either via parameter or environment
variable. Updated tests to always provide base_url and added tests for
the missing base_url validation error.
@marvin-context-protocol
Copy link
Copy Markdown
Contributor

Test Failure Analysis

Summary: The workflow failed due to a transient GitHub infrastructure issue (503 Service Unavailable) when downloading the prek installer, not due to any code problems.

Root Cause: The prek installation step failed with a 503 HTTP error when trying to download from github.com/j178/prek/releases/download/v0.2.23/prek-installer.sh:

curl: (22) The requested URL returned error: 503

This is a temporary service availability issue on GitHub's side, unrelated to the PR changes.

Suggested Solution: No action needed - the workflow has already been automatically retried (run #20445442408 is currently in progress). If the retry also fails with the same infrastructure error, GitHub Actions will likely auto-retry again, or you can manually re-run the workflow.

Detailed Analysis

The failure occurred during the "Run prek" step in the static_analysis job when attempting to install prek v0.2.23. The installer script downloads from GitHub releases, which temporarily returned a 503 error indicating service unavailability.

Timeline:

  • Run #20445442391 (failed): Started at 22:16:50Z, failed with 503 error
  • Run #20445442408 (in progress): Auto-retry started at 22:16:50Z
  • Previous run #20445082983: Succeeded at 22:01:04Z

This confirms the issue is intermittent infrastructure, not code-related.

Related Files

No code files are implicated - this is purely an infrastructure/network issue with the CI environment's ability to download from GitHub releases.

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

🧹 Nitpick comments (1)
src/fastmcp/server/auth/providers/azure.py (1)

236-239: LGTM! Validation logic is correct and consistent.

The base_url validation follows the same pattern as other required field checks in this file and is necessary since base_url is passed to the parent class at line 294.

The static analysis hint (TRY003) about long inline exception messages applies to all validation blocks in this file (lines 211-212, 214-215, 219-224, 228-234, and these new lines). If you want to address it, consider refactoring all validation messages file-wide or codebase-wide for consistency, rather than changing just this one.

📜 Review details

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 407d43d and 3390399.

⛔ Files ignored due to path filters (5)
  • tests/server/auth/providers/test_azure.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_workos.py is excluded by none and included by none
📒 Files selected for processing (1)
  • src/fastmcp/server/auth/providers/azure.py
🧰 Additional context used
📓 Path-based instructions (1)
**/*.py

📄 CodeRabbit inference engine (AGENTS.md)

**/*.py: Use Python ≥ 3.10 with full type annotations
Never use bare except - be specific with exception types

Files:

  • src/fastmcp/server/auth/providers/azure.py
🧬 Code graph analysis (1)
src/fastmcp/server/auth/providers/azure.py (1)
src/fastmcp/server/server.py (1)
  • settings (348-356)
🪛 Ruff (0.14.10)
src/fastmcp/server/auth/providers/azure.py

237-239: 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). (2)
  • GitHub Check: Run tests: Python 3.10 on windows-latest
  • GitHub Check: Run tests with lowest-direct dependencies

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

enhancement Improvement to existing functionality. For issues and smaller PR improvements. tests

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant