Skip to content

feat: add Static Client Registration (#3085)#3086

Merged
jlowin merged 7 commits intoPrefectHQ:mainfrom
martimfasantos:task/static-client-registration
Feb 10, 2026
Merged

feat: add Static Client Registration (#3085)#3086
jlowin merged 7 commits intoPrefectHQ:mainfrom
martimfasantos:task/static-client-registration

Conversation

@martimfasantos
Copy link
Copy Markdown
Contributor

@martimfasantos martimfasantos commented Feb 5, 2026

Context

Some MCP servers do not support OAuth 2.0 Dynamic Client Registration (DCR).

The MCP specification explicitly does not require DCR support:

MCP clients and authorization servers SHOULD support the OAuth 2.0 Dynamic Client Registration Protocol (RFC 7591) to allow MCP clients to obtain OAuth client IDs without user interaction.

reference: https://modelcontextprotocol.io/specification/2025-11-25/basic/authorization#preregistration

So we should be able to manually register the OAuth client and obtain a client_id and client_secret.

Summary

This PR adds support for providing a pre-registered client_id and client_secret to the OAuth client provider in FastMCP. When provided, these credentials are used to pre-seed the token storage, effectively bypassing the OAuth 2.0 Dynamic Client Registration (DCR) step.

Motivation

The MCP specification suggests that clients and servers SHOULD support RFC 7591 (Dynamic Client Registration). However, some MCP servers (e.g., GitHub Copilot's MCP server) do not support DCR and require clients to be manually registered or use static credentials.

Currently, users wishing to connect to such servers must manually instantiate OAuthClientInformationFull and inject it into the TokenStorage before creating the client, which relies on internal implementation details.

This change exposes client_id and client_secret as first-class arguments in the OAuth class, streamlining the connection process for these servers.

Proposed Changes

src/fastmcp/client/auth/oauth.py

Update OAuth.__init__ to accept client_id and client_secret:

class OAuth(OAuthClientProvider):
    def __init__(
        self,
        # ... existing args ...
        client_id: str | None = None,
        client_secret: str | None = None,
    ):
        # ... existing setup ...

        # 1. Create client_metadata as before
        client_metadata = OAuthClientMetadata(
            client_name=client_name,
            redirect_uris=[AnyHttpUrl(redirect_uri)],
            grant_types=["authorization_code", "refresh_token"],
            response_types=["code"],
            scope=scopes_str,
            **(additional_client_metadata or {}),
        )

        # 2. If client_id is provided, create client full information
        if self._client_id:
            # Create the full static client info directly which will avoid DCR
            self._static_client_info = OAuthClientInformationFull(
                client_id=self._client_id,
                client_secret=self._client_secret,
                **(self._additional_client_metadata or {}),
            )

...

Example Usage

from fastmcp.client.auth import OAuth

# For a server that doesn't support Dynamic Client Registration
auth = OAuth(
    mcp_url="https://api.githubcopilot.com/mcp",
    client_id="Iv1...",
    client_secret="e9a...",
    client_name="My App"
)

# Using the FastMCP client
async with Client(
    "https://mcp-server.example.com/mcp",
    auth=OAuth(
        client_id="my-registered-client-id",
        client_secret="my-client-secret",
    ),
) as client:
   ....

Contributors Checklist

Review Checklist

  • I have self-reviewed my changes
  • My Pull Request is ready for review

@marvin-context-protocol marvin-context-protocol Bot added enhancement Improvement to existing functionality. For issues and smaller PR improvements. client Related to the FastMCP client SDK or client-side functionality. auth Related to authentication (Bearer, JWT, OAuth, WorkOS) for client or server. labels Feb 5, 2026
Copy link
Copy Markdown

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

Choose a reason for hiding this comment

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

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: d7c6526fb8

ℹ️ About Codex in GitHub

Codex has been enabled to automatically review pull requests in this repo. Reviews are triggered when you

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

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

When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "@codex address that feedback".

Comment thread src/fastmcp/client/auth/oauth.py
Comment thread src/fastmcp/client/auth/oauth.py Outdated
Comment thread src/fastmcp/client/auth/oauth.py Outdated
@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai Bot commented Feb 5, 2026

Walkthrough

The OAuth provider in src/fastmcp/client/auth/oauth.py now accepts optional client_id and client_secret. When a client_id is provided, the provider constructs a static OAuthClientInformationFull, stores it per-MCP-endpoint in the token storage, and bypasses Dynamic Client Registration by injecting the static client info during _bind/_initialize. Redirect and auth flows now pre-flight-check static credentials and surface ClientNotFoundError for invalid static credentials instead of retrying DCR. Token storage and context handling were updated to align static client info with the MCP server URL.

Possibly related PRs

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Title check ✅ Passed The title 'feat: add Static Client Registration (#3085)' clearly and specifically describes the main change—adding support for static OAuth client credentials to bypass DCR.
Description check ✅ Passed The PR description addresses context, motivation, summary, and proposed changes. However, the Contributors Checklist shows tests and documentation updates are only partially complete (one unchecked).
Linked Issues check ✅ Passed The code changes implement all core objectives: expose client_id and client_secret as constructor parameters, create OAuthClientInformationFull with full metadata, pre-seed token storage, and support optional client_secret.
Out of Scope Changes check ✅ Passed All changes are directly related to issue #3085: OAuth constructor updates, documentation of pre-registered client flow, and proper error handling. No unrelated modifications detected.
Docstring Coverage ✅ Passed Docstring coverage is 100.00% which is sufficient. The required threshold is 80.00%.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing touches
  • 📝 Generate docstrings
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment

No actionable comments were generated in the recent review. 🎉

🧹 Recent nitpick comments
src/fastmcp/client/auth/oauth.py (2)

376-383: Consider defining a dedicated error message constant or keeping the message shorter.

The static analysis tool flags TRY003 for the long inline message. While the descriptive error is helpful for users, you could extract the message to a class-level constant or define a custom subclass with a default message to satisfy the lint rule.

That said, the behavior is correct — surfacing an immediate error for static credentials instead of futile DCR retries is the right approach.

♻️ Optional: extract error message
+_STATIC_CRED_ERROR = (
+    "OAuth server rejected the static client credentials. "
+    "Verify that the client_id (and client_secret, if provided) "
+    "are correct and that the client is registered with the server."
+)
+
 ...
 
             if self._static_client_info is not None:
-                raise ClientNotFoundError(
-                    "OAuth server rejected the static client credentials. "
-                    "Verify that the client_id (and client_secret, if provided) "
-                    "are correct and that the client is registered with the server."
-                ) from None
+                raise ClientNotFoundError(_STATIC_CRED_ERROR) from None

290-306: Pre-flight 400 check is a broad heuristic — consider logging the response body.

A 400 status from the authorization endpoint doesn't always mean "client not found" — it could be a malformed request, unsupported response_type, invalid redirect_uri, etc. Consider logging the response body at debug level to aid troubleshooting, especially when static credentials are in use.

🔍 Optional: log response body for diagnostics
         if response.status_code == 400:
+            logger.debug(f"Authorization pre-flight 400 response: {response.text[:500]}")
             raise ClientNotFoundError(
                 "OAuth client not found - cached credentials may be stale"
             )

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 Feb 5, 2026

Test Failure Analysis

Summary: Multiple test failures in OAuth client tests due to an AttributeError when _static_client_info attribute is not initialized.

Root Cause: The _initialize() method in OAuth (line 255) checks if self._static_client_info is not None:, but this attribute is only created when client_id and client_secret are provided during initialization. For standard OAuth flows (without static credentials), the attribute doesn't exist, causing an AttributeError.

The HeadlessOAuth test class inherits from OAuth and doesn't pass client_id/client_secret, triggering this error during test execution.

Suggested Solution:

Initialize self._static_client_info = None in OAuth.__init__() before the conditional block that sets it. This ensures the attribute always exists.

In src/fastmcp/client/auth/oauth.py, after line 210 (after creating token_storage_adapter), add:

# Use full URL for token storage to properly separate tokens per MCP endpoint
self.token_storage_adapter: TokenStorageAdapter = TokenStorageAdapter(
    async_key_value=token_storage, server_url=mcp_url
)

# Initialize static client info (will be set if credentials are provided)
self._static_client_info: OAuthClientInformationFull | None = None

# Handle static client credentials (bypasses dynamic client registration)
# If client_id is provided, we construct OAuthClientInformationFull and inject
# it during initialization to prevent the SDK from performing dynamic registration
if client_id and client_secret:
    logger.info(
        "Using static OAuth client credentials (client_id provided)"
    )
    # Create the full client information for static credentials
    self._static_client_info = OAuthClientInformationFull(
        client_id=client_id,
        client_secret=client_secret,
    )
    # Inject static client info into token storage
    anyio.run(
        self.token_storage_adapter.set_client_info, 
        self._static_client_info
    )
Detailed Analysis

The error occurs in these test cases:

  • test_list_tools
  • test_call_tool
  • test_list_resources
  • test_read_resource

All fail with:

E       AttributeError: 'HeadlessOAuth' object has no attribute '_static_client_info'

Stack trace shows the error originates from:

# src/fastmcp/client/auth/oauth.py:255
async def _initialize(self) -> None:
    await super()._initialize()
    
    if self._static_client_info is not None:  # <-- AttributeError here
        self.context.client_info = self._static_client_info

The HeadlessOAuth class (defined in src/fastmcp/utilities/tests.py:225) inherits from OAuth and calls super().__init__(mcp_url, **kwargs) without providing client_id or client_secret. Since the attribute is only created conditionally, it doesn't exist for subclasses or standard OAuth flows.

Additional Issues to Consider

While fixing the immediate AttributeError, there are two other issues mentioned in previous reviews that should be addressed:

  1. Event Loop Issue (src/fastmcp/client/auth/oauth.py:230): Using anyio.run() in __init__() will fail if called within an already-running event loop (common in async contexts). Consider moving the storage injection to _initialize() where it can run asynchronously.

  2. Public Client Support: The code requires both client_id and client_secret (if client_id and client_secret:), but OAuth public clients don't require a secret. Consider whether to support public clients by changing the logic to if client_id: and making client_secret truly optional.

Related Files
  • src/fastmcp/client/auth/oauth.py:210-255 - OAuth class initialization and _initialize method
  • src/fastmcp/utilities/tests.py:225 - HeadlessOAuth test helper class that inherits from OAuth
  • tests/client/auth/test_oauth_client.py - Tests using HeadlessOAuth that are currently failing

Updated: 2026-02-05 - Analysis of test failures from workflow run #21711611027

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

🧹 Nitpick comments (1)
src/fastmcp/client/auth/oauth.py (1)

220-220: Consider documenting behavior when only client_id is provided.

The condition if client_id and client_secret silently skips static registration if only client_id is provided (without client_secret). This may be intentional for OAuth public clients, but consider either:

  1. Documenting this behavior in the docstring, or
  2. Supporting public clients explicitly by allowing client_secret=None, or
  3. Raising a ValueError if client_id is provided without client_secret

Comment thread src/fastmcp/client/auth/oauth.py Outdated
Comment thread src/fastmcp/client/auth/oauth.py Outdated
Comment thread src/fastmcp/client/auth/oauth.py Outdated
Copy link
Copy Markdown
Member

@jlowin jlowin left a comment

Choose a reason for hiding this comment

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

The feature makes sense — the implementation has a few issues though:

anyio.run() in init crashes in async contexts, which is the common case. The MCP SDK's own ClientCredentialsOAuthProvider shows the right pattern: store credentials in init, then override _initialize() to set context.client_info directly. There can be no async work in the constructor at all.

_static_client_info AttributeError — the _initialize override references it unconditionally but it's only set when credentials are provided, breaking all existing usage.

Static client info needs the full metadata — just passing client_id/client_secret without redirect_uris, grant_types, etc. will likely fail server-side validation. Since client_metadata is already constructed at that point, just spread it in.

client_secret should be optional — the spec says "client ID (and, if applicable, client credentials)," explicitly accommodating public client pre-registration (no secret, relying on PKCE + redirect URI validation). The current if client_id and client_secret guard silently falls through to DCR when only client_id is provided.

The fix for all four (roughly):

# in __init__
self._static_client_info: OAuthClientInformationFull | None = None
if client_id is not None:
    self._static_client_info = OAuthClientInformationFull(
        client_id=client_id,
        client_secret=client_secret,
        **client_metadata.model_dump(exclude_none=True),
    )

# override _initialize
async def _initialize(self) -> None:
    await super()._initialize()
    if self._static_client_info is not None:
        self.context.client_info = self._static_client_info
    if self.context.current_tokens and self.context.current_tokens.expires_in:
        self.context.update_token_expiry(self.context.current_tokens)

@marvin-context-protocol
Copy link
Copy Markdown
Contributor

Test Failure Analysis

Summary: The static analysis check failed because the code contains trailing whitespace that violates the ruff formatting rules.

Root Cause: The PR introduces trailing whitespace on two lines in src/fastmcp/client/auth/oauth.py:

  • Line 230 (after the closing parenthesis following the stacklevel=2, line)
  • Line 250 (blank line with trailing spaces before the comment about token storage)

The ruff format hook automatically removed these trailing spaces, which causes the CI to fail since files were modified during the check.

Suggested Solution: Run the formatting tools locally to fix the trailing whitespace:

uv run prek run --all-files

This will automatically remove the trailing whitespace and ensure the code passes all static analysis checks. After running this command, commit the changes and push to update the PR.

Detailed Analysis

The ruff format hook found and fixed these issues:

@@ -227,7 +227,7 @@ class OAuth(OAuthClientProvider):
             scope=scopes_str,
             **(self._additional_client_metadata or {}),
         )
-        
+
         if self._client_id:
             # Create the full static client info directly which will avoid DCR
             self._static_client_info = OAuthClientInformationFull(
@@ -247,7 +247,7 @@ class OAuth(OAuthClientProvider):
                 + "See https://gofastmcp.com/clients/auth/oauth#token-storage for details.",
                 stacklevel=2,
             )
-                    
+
         # Use full URL for token storage to properly separate tokens per MCP endpoint
         self.token_storage_adapter: TokenStorageAdapter = TokenStorageAdapter(
             async_key_value=token_storage, server_url=mcp_url

The lines marked with - had trailing whitespace, and ruff automatically removed it (shown in the + lines).

Related Files
  • src/fastmcp/client/auth/oauth.py (lines 230, 250) - Contains the trailing whitespace that needs to be removed

@marvin-context-protocol
Copy link
Copy Markdown
Contributor

Test Failure Analysis

Summary: The static analysis check failed due to trailing whitespace in src/fastmcp/client/auth/oauth.py.

Root Cause: The PR introduces trailing whitespace on lines 231 and 250 of src/fastmcp/client/auth/oauth.py. The ruff-format hook detected and removed this trailing whitespace, causing the pre-commit checks to fail.

Suggested Solution: Remove the trailing whitespace from these lines:

  • Line 231: After ) in the static client info creation block
  • Line 250: After ) in the warning message block

Run uv run prek run --all-files locally to fix the formatting, then commit the changes.

Detailed Analysis

The CI log shows:

ruff format.............................................................Failed
- hook id: ruff-format
- files were modified by this hook

  1 file reformatted, 613 files left unchanged

The specific changes made by ruff-format:

@@ -228,7 +228,7 @@ class OAuth(OAuthClientProvider):
              scope=scopes_str,
              **(self._additional_client_metadata or {}),
          )
-        
+
          if self._client_id:
              # Create the full static client info directly which will avoid DCR
              self._static_client_info = OAuthClientInformationFull(
@@ -248,7 +248,7 @@ class OAuth(OAuthClientProvider):
                  + "See https://gofastmcp.com/clients/auth/oauth#token-storage for details.",
                  stacklevel=2,
              )
-                    
+
          # Use full URL for token storage to properly separate tokens per MCP endpoint
          self.token_storage_adapter: TokenStorageAdapter = TokenStorageAdapter(
              async_key_value=token_storage, server_url=mcp_url

The formatter removed trailing spaces from two blank lines.

Related Files
  • src/fastmcp/client/auth/oauth.py: The file containing the trailing whitespace that needs to be removed.

🤖 Analysis by Marvin - triage bot for FastMCP

@martimfasantos
Copy link
Copy Markdown
Contributor Author

The feature makes sense — the implementation has a few issues though:

anyio.run() in init crashes in async contexts, which is the common case. The MCP SDK's own ClientCredentialsOAuthProvider shows the right pattern: store credentials in init, then override _initialize() to set context.client_info directly. There can be no async work in the constructor at all.

_static_client_info AttributeError — the _initialize override references it unconditionally but it's only set when credentials are provided, breaking all existing usage.

Static client info needs the full metadata — just passing client_id/client_secret without redirect_uris, grant_types, etc. will likely fail server-side validation. Since client_metadata is already constructed at that point, just spread it in.

client_secret should be optional — the spec says "client ID (and, if applicable, client credentials)," explicitly accommodating public client pre-registration (no secret, relying on PKCE + redirect URI validation). The current if client_id and client_secret guard silently falls through to DCR when only client_id is provided.

The fix for all four (roughly):

# in __init__
self._static_client_info: OAuthClientInformationFull | None = None
if client_id is not None:
    self._static_client_info = OAuthClientInformationFull(
        client_id=client_id,
        client_secret=client_secret,
        **client_metadata.model_dump(exclude_none=True),
    )

# override _initialize
async def _initialize(self) -> None:
    await super()._initialize()
    if self._static_client_info is not None:
        self.context.client_info = self._static_client_info
    if self.context.current_tokens and self.context.current_tokens.expires_in:
        self.context.update_token_expiry(self.context.current_tokens)

I’ve addressed all these points @jlowin, thanks for calling them out.
Should we also add documentation, as was done in #2871?

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.

Caution

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

⚠️ Outside diff range comments (1)
src/fastmcp/client/auth/oauth.py (1)

365-381: ⚠️ Potential issue | 🟠 Major

Retry-on-stale-credentials logic is counterproductive with static credentials.

When static credentials are in use and the server rejects them (triggering ClientNotFoundError), the handler clears the cache and retries. But static credentials are fixed — they won't change on retry. Worse, after clearing the cache, the retry may silently fall back to Dynamic Client Registration, contradicting the user's intent.

Consider short-circuiting the retry when _static_client_info is set:

🔧 Proposed fix sketch
         except ClientNotFoundError:
+            if self._static_client_info is not None:
+                raise ClientNotFoundError(
+                    "Static OAuth client credentials were rejected by the server. "
+                    "Verify your client_id and client_secret are correct."
+                )
             logger.debug(
                 "OAuth client not found on server, clearing cache and retrying..."
             )
🧹 Nitpick comments (1)
src/fastmcp/client/auth/oauth.py (1)

270-278: Consider persisting static client info to storage.

_initialize sets self.context.client_info in-memory but never calls await self.token_storage_adapter.set_client_info(...). If any code path (e.g., the parent SDK) reads client info from storage rather than from self.context, it will find nothing. Persisting also ensures consistency if _initialize is called multiple times after a cache clear.

🔧 Proposed fix
         if self._static_client_info is not None:
+            await self.token_storage_adapter.set_client_info(self._static_client_info)
             self.context.client_info = self._static_client_info

@martimfasantos martimfasantos requested a review from jlowin February 9, 2026 18:19
Include full client_metadata in static client info, short-circuit
retry for static credentials, persist static client info to storage,
add tests and documentation.
Copy link
Copy Markdown
Member

@jlowin jlowin left a comment

Choose a reason for hiding this comment

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

@martimfasantos thank you! I've pushed a few doc changes to the branch, this LGTM

@marvin-context-protocol
Copy link
Copy Markdown
Contributor

Test Failure Analysis

Summary: Two OAuth static client E2E tests are failing with "Authorization failed: 400" errors due to redirect URI mismatch between pre-registered clients and dynamically allocated callback ports.

Root Cause: The tests pre-register OAuth clients with redirect_uris=[AnyHttpUrl("http://localhost:0/callback")] (port 0), but the OAuth client initialization dynamically picks an available port via find_available_port(), resulting in redirect URIs like http://localhost:56923/callback. The MCP SDK's authorization handler validates redirect_uris strictly, and http://localhost:56923/callback doesn't match the registered http://localhost:0/callback, causing a 400 error.

Suggested Solution:

  1. Modify the test to pre-register clients with the actual dynamic port - Update tests/client/auth/test_oauth_static_client.py to:
    • Find an available port before creating the OAuth client
    • Pre-register the client with that specific port in redirect_uris
    • Pass that port to HeadlessOAuth via the _callback_port parameter

Example fix for test_static_client_with_dcr_disabled:

# Find port before pre-registering
callback_port = find_available_port()
pre_registered = OAuthClientInformationFull(
    client_id="pre-registered-client",
    client_secret="pre-registered-secret",
    redirect_uris=[AnyHttpUrl(f"http://localhost:{callback_port}/callback")],  # Use actual port
    grant_types=["authorization_code", "refresh_token"],
    response_types=["code"],
    scope="read write",
)
await provider.register_client(pre_registered)

# Pass the same port to OAuth client
oauth = HeadlessOAuth(
    mcp_url=url,
    client_id="pre-registered-client",
    client_secret="pre-registered-secret",
    scopes=["read", "write"],
    _callback_port=callback_port,  # Use same port
)

Apply the same fix to test_static_client_with_dcr_enabled.

Detailed Analysis

Error from logs:

INFO:     127.0.0.1:43924 - "GET /authorize?...&redirect_uri=http%3A%2F%2Flocalhost%3A56923%2Fcallback..." 400 Bad Request
ERROR   [0m mcp.client.auth.oauth2:oauth2.py:589 OAuth flow error
...
RuntimeError: Authorization failed: 400

Code paths:

  1. Test pre-registers client (test_oauth_static_client.py:214):

    pre_registered = OAuthClientInformationFull(
        redirect_uris=[AnyHttpUrl("http://localhost:0/callback")],  # Port 0
        ...
    )
  2. OAuth client picks dynamic port (src/fastmcp/client/auth/oauth.py:201-202):

    self.redirect_port = self._callback_port or find_available_port()  # Gets 56923
    redirect_uri = f"http://localhost:{self.redirect_port}/callback"
  3. Authorization request includes dynamic redirect_uri - Client sends redirect_uri=http://localhost:56923/callback

  4. MCP SDK validates redirect_uri - The AuthorizationHandler calls client.validate_redirect_uri() which checks if the provided URI matches one of the registered URIs. Since 56923 != 0, validation fails and returns a 400 error.

Related Files
  • tests/client/auth/test_oauth_static_client.py:214,273 - Pre-registration with port 0
  • src/fastmcp/client/auth/oauth.py:201 - Dynamic port allocation
  • src/fastmcp/server/auth/providers/in_memory.py:92 - InMemoryOAuthProvider.authorize()
  • MCP SDK's AuthorizationHandler.handle() - Redirect URI validation logic

🤖 Analysis by Marvin test triage bot

Static client info now defaults token_endpoint_auth_method to
"client_secret_post" (with secret) or "none" (without), which is
required for the token exchange to work. E2E tests fixed for
AnyUrl/AnyHttpUrl type mismatch in MCP SDK's redirect_uri validation.
@jlowin jlowin merged commit 939cf5f into PrefectHQ:main Feb 10, 2026
8 checks passed
@martimfasantos martimfasantos deleted the task/static-client-registration branch February 10, 2026 10:22
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. client Related to the FastMCP client SDK or client-side functionality. enhancement Improvement to existing functionality. For issues and smaller PR improvements.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Support Static OAuth Client Credentials (Bypass Dynamic Client Registration)

2 participants