Skip to content

fix MCP client OAuth origin/redirect guidance for user-added servers - #1324

Merged
kody-bot merged 3 commits into
mainfrom
cursor/mcp-oauth-origin-guidance-44d4
Aug 8, 2026
Merged

kody-bot merged 3 commits into
mainfrom
cursor/mcp-oauth-origin-guidance-44d4

Conversation

@kentcdodds

@kentcdodds kentcdodds commented Aug 8, 2026

Copy link
Copy Markdown
Owner

Summary

Feedback from cameronpak: connecting an OAuth-protected remote MCP server failed with Invalid origin uri https://heykody.app. That is not a Kody outage — it matches FusionAuth-style authorized origin rejection when Kody acts as the MCP client. Kent’s own MCP still works because many providers do not enforce that allowlist.

Gap on our side: we did not document or surface the allowlisted redirect URI / client origin, errors were opaque, callbacks followed the request host (unstable during dual-host migration), and the authorize link sent Kody’s origin as Referer.

Changes

  • Document the flow and allowlist requirement (docs/use/mcp-client-servers.md + troubleshooting)
  • Show copyable OAuth redirect URI on /account/mcp-servers
  • Return oauthClientOrigin / oauthCallbackUrl from mcp_server_add / list / reconnect
  • Enrich origin/redirect rejection messages with those values
  • Register OAuth callbacks from canonical APP_BASE_URL
  • Open authorize with rel="noopener noreferrer" to avoid Referer-based origin rejection
  • Triaged feedback f518f067-… with investigation notes

Workaround until deploy

On the remote IdP, allow https://heykody.app and register https://heykody.app/account/mcp-servers/oauth/callback, then remove/re-add the server in Kody.

System recap — extends existing primitives (medium risk)

Overall

Field Value
Classification extends
Risk Medium
Primitives touched mcp-client-servers, app-ui

Touched primitives

Primitive Classification Why
mcp-client-servers extends Canonical callback registration, enriched OAuth errors, capability output shape
app-ui extends Account MCP servers page surfaces redirect URI + noreferrer authorize

What changed

flowchart LR
  user[User / agent] --> kodyUi["/account/mcp-servers"]
  kodyUi -->|register client| remoteAs[Remote AS / MCP OAuth]
  remoteAs -->|reject missing origin/redirect| enrich[Enrich error + docs]
  kodyUi -->|callback| callback["canonical /account/mcp-servers/oauth/callback"]
Loading

Kody-as-client OAuth now advertises a stable canonical origin/callback, explains allowlist failures, and reduces Referer-triggered origin checks.

Invariants

  • Per-user hub isolation unchanged
  • Tokens still stay in the MCP client hub DO

Docs

  • docs/use/mcp-client-servers.md
  • docs/use/troubleshooting.md
  • docs/contributing/architecture/mcp-client-servers.md
Open in Web Open in Cursor 

Summary by CodeRabbit

  • New Features

    • Added support for connecting remote MCP servers, including OAuth authorization and reconnection guidance.
    • Display the OAuth client origin and callback URL, with a copy option for easier provider configuration.
    • Added actionable explanations for invalid origin and redirect URI authorization errors.
  • Documentation

    • Added a guide covering remote MCP server setup, OAuth allowlists, troubleshooting, and reconnection.
    • Updated architecture and troubleshooting documentation with canonical URL and provider configuration details.

Surface Kody's canonical OAuth client origin and redirect URI, enrich
FusionAuth-style origin/redirect rejection errors, register callbacks from
APP_BASE_URL, and document the allowlist requirement so remote IdP
misconfiguration is actionable instead of opaque.

Co-authored-by: Kent C. Dodds <me+github@kentcdodds.com>
@coderabbitai

coderabbitai Bot commented Aug 8, 2026

Copy link
Copy Markdown

Review Change Stack

Warning

Review limit reached

@cursor[bot], you've reached your PR review limit, so we couldn't start this review.

Next review available in: 31 minutes

You've used all free OSS reviews for now. Wait for the free limit to reset to keep reviewing this public repository.

How can I continue?

After more reviews become available, a review can be triggered using the @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

To avoid repeated limits, reduce automatic review volume by pausing incremental auto-reviews earlier, using label-based review opt-in, excluding WIP or generated PR titles, or requesting reviews manually when the PR is ready. If your team needs uninterrupted high-volume reviews, an organization admin can enable usage-based reviews.

How do review limits work?

CodeRabbit enforces per-developer PR review limits for each organization. Most developers receive the normal plan review availability.

For paid Pro and Pro+ PR reviews, CodeRabbit uses adaptive limits for sustained high-volume activity. When a developer's recent PR review activity reaches the 95th percentile or higher among CodeRabbit users, additional reviews become available more gradually as earlier reviews age out of the rolling window.

Please refer docs for additional details.

Review details
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro Plus

Run ID: e6b38ef5-e6d7-4858-80d6-24cd7883c2f2

📥 Commits

Reviewing files that changed from the base of the PR and between 3ab4a9a and 58a856d.

📒 Files selected for processing (5)
  • docs/use/mcp-client-servers.md
  • packages/worker/src/app/handlers/account-mcp-servers.node.test.ts
  • packages/worker/src/app/handlers/account-mcp-servers.ts
  • packages/worker/src/mcp-client/oauth-provider-error.node.test.ts
  • packages/worker/src/mcp-client/settings-service.node.test.ts
📝 Walkthrough

Walkthrough

Changes

MCP OAuth configuration

Layer / File(s) Summary
Resolve canonical OAuth URLs
packages/worker/src/mcp-client/settings-service.ts, packages/worker/src/mcp-client/settings-service.node.test.ts, packages/worker/universal/loader-data.ts
The worker derives the OAuth client origin from APP_BASE_URL or the request URL and builds the callback URL. Account loader data exposes both values.
Enrich OAuth provider errors
packages/worker/src/mcp-client/oauth-provider-error.ts, packages/worker/src/mcp-client/oauth-provider-error.node.test.ts
Origin and redirect URI errors include the client origin, callback URL, and reconnect guidance. Unrelated errors remain unchanged.
Propagate OAuth context through MCP flows
packages/worker/src/mcp/capabilities/mcp-servers/*, packages/worker/src/app/handlers/account-mcp-servers.ts, packages/worker/src/app/account-mcp-servers-data.ts, packages/worker/src/app/handlers/account-mcp-servers.node.test.ts
MCP capabilities and account handlers resolve OAuth URLs, use the client origin during server creation, expose both URLs, and enrich OAuth errors.
Expose callback configuration in the account UI
packages/worker/client/routes/account-mcp-servers.tsx
The account page displays and copies the callback URL, explains provider allowlisting, and secures authorization links.
Document remote MCP OAuth setup
docs/use/mcp-client-servers.md, docs/use/index.md, docs/use/troubleshooting.md, docs/contributing/architecture/mcp-client-servers.md
The documentation covers remote MCP setup, provider allowlists, OAuth troubleshooting, reconnect behavior, and architecture details.

Estimated code review effort: 3 (Moderate) | ~25 minutes

Sequence Diagram(s)

sequenceDiagram
  participant MCPClient
  participant MCPServerCapability
  participant SettingsService
  participant OAuthProvider
  MCPClient->>MCPServerCapability: Add or reconnect server
  MCPServerCapability->>SettingsService: Resolve client origin and callback URL
  SettingsService-->>MCPServerCapability: Return OAuth URLs
  MCPServerCapability->>OAuthProvider: Start authorization
  OAuthProvider-->>MCPServerCapability: Return success or provider error
  MCPServerCapability-->>MCPClient: Return OAuth configuration and result
Loading

Possibly related PRs

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 30.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Title check ✅ Passed The title clearly and concisely describes the PR’s main change to MCP client OAuth origin and redirect guidance.
Description check ✅ Passed The description clearly explains the intent, changes, system impact, and workaround, but it does not include a dedicated Testing section.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
✨ Finishing Touches 💡 2
📝 Generate docstrings 💡
  • Create stacked PR
  • Commit on current branch
🛠️ Fix failing CI checks 💡
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch cursor/mcp-oauth-origin-guidance-44d4

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.

@kentcdodds
kentcdodds marked this pull request as ready for review August 8, 2026 17:58

@cursor cursor Bot left a comment

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.

Cursor Bugbot has reviewed your changes using default effort and found 1 potential issue.

Fix All in Cursor

❌ Bugbot Autofix is OFF. To automatically fix reported issues with cloud agents, enable autofix in the Cursor dashboard.

Reviewed by Cursor Bugbot for commit 3ab4a9a. Configure here.

Comment thread packages/worker/src/app/handlers/account-mcp-servers.ts
Bugbot: reconnect/refresh/enable/delete reloads omitted requestUrl, so
preview/local responses could fall back to the production default origin
for oauthClientOrigin/oauthCallbackUrl.

Co-authored-by: Kent C. Dodds <me+github@kentcdodds.com>

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Actionable comments posted: 2

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@docs/use/mcp-client-servers.md`:
- Line 13: Update the server URL guidance in the MCP client documentation to
require HTTPS generally while explicitly permitting plain HTTP for loopback
hosts, matching the runtime contract described in the architecture
documentation.
- Around line 39-40: Update the reconnect guidance in the server registration
instructions to state that reconnecting does not refresh stored OAuth provider
metadata such as allowlisted origins or redirect values; require removing and
re-adding the server for those changes, while describing reconnect only as
reconnecting or recovering the existing registration.
🪄 Autofix

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro Plus

Run ID: ea9b97c9-cf83-466b-927c-4317082aeca4

📥 Commits

Reviewing files that changed from the base of the PR and between fbbc885 and 3ab4a9a.

📒 Files selected for processing (17)
  • docs/contributing/architecture/mcp-client-servers.md
  • docs/use/index.md
  • docs/use/mcp-client-servers.md
  • docs/use/troubleshooting.md
  • packages/worker/client/routes/account-mcp-servers.tsx
  • packages/worker/src/app/account-mcp-servers-data.ts
  • packages/worker/src/app/handlers/account-mcp-servers.node.test.ts
  • packages/worker/src/app/handlers/account-mcp-servers.ts
  • packages/worker/src/mcp-client/oauth-provider-error.node.test.ts
  • packages/worker/src/mcp-client/oauth-provider-error.ts
  • packages/worker/src/mcp-client/settings-service.node.test.ts
  • packages/worker/src/mcp-client/settings-service.ts
  • packages/worker/src/mcp/capabilities/mcp-servers/mcp-server-add.ts
  • packages/worker/src/mcp/capabilities/mcp-servers/mcp-server-list.ts
  • packages/worker/src/mcp/capabilities/mcp-servers/mcp-server-reconnect.ts
  • packages/worker/src/mcp/capabilities/mcp-servers/shared.ts
  • packages/worker/universal/loader-data.ts


1. Open [`/account/mcp-servers`](https://heykody.app/account/mcp-servers), or ask
your agent to use `mcp_server_add` with a short kebab-case `name` and the
server `url` (https required).

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🎯 Functional Correctness | 🟡 Minor | ⚡ Quick win

Document the loopback HTTP exception.

Line 13 says that the server URL requires HTTPS. The runtime contract in docs/contributing/architecture/mcp-client-servers.md Lines 28-31 also permits plain HTTP for loopback hosts. This wording tells users not to use a supported local MCP server. State the exception explicitly.

Suggested wording
-   the server `url` (https required).
+   the server `url` (HTTPS required; HTTP is allowed for loopback hosts).
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@docs/use/mcp-client-servers.md` at line 13, Update the server URL guidance in
the MCP client documentation to require HTTPS generally while explicitly
permitting plain HTTP for loopback hosts, matching the runtime contract
described in the architecture documentation.

Comment on lines +39 to +40
2. Remove and re-add the server in Kody (or reconnect) so client registration
picks up the allowlisted values.

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🎯 Functional Correctness | 🟡 Minor | ⚡ Quick win

🧩 Analysis chain

🏁 Script executed:

#!/usr/bin/env bash
set -euo pipefail

if command -v ast-grep >/dev/null 2>&1; then
  ast-grep outline packages/worker/src/mcp-client \
    --items all \
    --type function \
    --match 'reconnectServer|addServer|register'
fi

rg -n -C 12 \
  'reconnectServer|addServer|register.*client|clientMetadata|redirectUri|redirectUris|oauthCallbackUrl|oauthClientOrigin' \
  packages/worker/src/mcp-client \
  packages/worker/src/mcp

Repository: kentcdodds/kody

Length of output: 32970


🏁 Script executed:

#!/bin/bash
set -euo pipefail

echo 'hub.ts relevant sections:'
sed -n '136,210p' packages/worker/src/mcp-client/hub.ts

echo
echo 'manager files:'
fd -a '.*\.(ts|tsx)$' packages/worker/src/mcp-client packages/worker/src/mcp | sed 's#^\./##' | head -200

echo
echo 'search mcp manager symbols:'
rg -n -C 8 \
  'removeServer|connectToServer|registerServer|addMcpServer|disconnects|unregister|store|metadata|client_metadata|redirect_uri|redirect_uris|origin' \
  packages/worker/src/mcp-client packages/worker/src/mcp | head -300

echo
echo 'files containing reconnect/add/remove managers:'
rg -n -C 15 \
  'reconnectServer|connectToServer|removeServer|addServer' \
  packages/worker/src/mcp-client packages/worker/src/mcp

Repository: kentcdodds/kody

Length of output: 20038


🏁 Script executed:

#!/bin/bash
set -euo pipefail

echo 'hub.ts full file outline and relevant sections:'
wc -l packages/worker/src/mcp-client/hub.ts
sed -n '136,226p' packages/worker/src/mcp-client/hub.ts

echo
echo 'find relevant test/source files:'
rg -n -C 12 \
  'DurableObjectOAuthClientProvider|McpClientHub|registerServer|removeServer|connectToServer|restoreConnectionsFromStorage|client_metadata|redirect_uri|redirect_uris|redirectUri|callbackUrl|mcpClientName' \
  packages/worker/src/mcp-client packages/worker/src/mcp packages/worker/test packages/worker/workers | head -500

echo
echo 'list mcp-client files:'
fd -e ts . packages/worker/src/mcp-client | sort

echo
echo 'files with agent/sdk imports:'
rg -n \
  '`@modelcontextprotocol/sdk`|Agent|OAuth|client_metadata|redirect_uri|callbackUrl|registerServer|removeServer|connectToServer' \
  packages/worker/src/mcp-client packages/worker/src/mcp | head -500

Repository: kentcdodds/kody

Length of output: 42210


🌐 Web query:

Cloudflare Agents MCPClientManager restoreConnectionsFromStorage DurableObjectOAuthClientProvider client_metadata redirect_uri

💡 Result:

In Cloudflare Agents, the MCPClientManager and DurableObjectOAuthClientProvider are components of the framework's Model Context Protocol (MCP) support, designed to manage persistent connections and OAuth authentication within Durable Objects (DOs) [1][2]. MCPClientManager is responsible for managing MCP server connections. Its restoreConnectionsFromStorage(clientName: string) method is called during Agent initialization to recover connections that were previously stored [1][3]. This method retrieves registered servers from storage and initiates connection attempts, typically in the background to avoid blocking the DO's execution [1][4]. DurableObjectOAuthClientProvider is the default implementation of the OAuth provider interface (AgentMcpOAuthProvider) used by the MCP client [5][2]. It manages the OAuth flow specifically within a Durable Object, utilizing the DO's storage to securely maintain sensitive data, including OAuth tokens, nonces, and PKCE-related code verifiers [5][6][2]. Key technical aspects include: - Client Metadata and Redirect URIs: The DurableObjectOAuthClientProvider exposes properties such as clientMetadata, clientUri, and redirectUrl [5]. The redirect_uri is a critical component of the OAuth flow, enabling the provider to receive authorization codes back from the OAuth server. When configuring or customizing this, developers ensure the callback path is correctly registered to maintain security and proper flow completion [7][8]. - Customization: Users can override the default provider by implementing the AgentMcpOAuthProvider interface and specifying it through the agent's createMcpOAuthProvider method [9][10][11]. Recent framework updates have improved support for these custom providers by ensuring that restoreConnectionsFromStorage respects these overrides rather than hardcoding the default provider [10]. - Storage: Because the default provider is tied to ctx.storage, tokens are scoped to a single DO instance. Advanced implementations often utilize custom providers to route token storage to external databases (e.g., KV) to enable cross-DO access [9].

Citations:


🌐 Web query:

github.com Cloudflare agents client.ts restoreConnectionsFromStorage clientMetadata callback_url storeServer row.remove

💡 Result:

The query relates to the MCPClientManager class found in the Cloudflare Agents SDK (cloudflare/agents), specifically within packages/agents/src/mcp/client.ts. The components mentioned are part of the internal logic for managing, persisting, and restoring Model Context Protocol (MCP) server connections, particularly across Durable Object (DO) restarts. Key technical aspects include: 1. restoreConnectionsFromStorage: This method is called during agent initialization to restore previously saved MCP server connections [1]. Recent updates have improved this process to run in the background (fire-and-forget) to avoid blocking the Durable Object onStart method and to properly handle failed connection attempts [2][3]. 2. Client Metadata & Callback URL: The system uses metadata and callback URLs to manage OAuth flows for MCP servers. Recent changes addressed race conditions and security vulnerabilities where callback URLs were improperly handled during restoration [2]. Specifically, OAuth providers are now correctly injected via a factory pattern to respect custom createMcpOAuthProvider overrides defined by the user, rather than hardcoding a default provider [4][5]. 3. storeServer and row.remove: These operations are associated with the storage abstraction layer used by the MCP client. The SDK uses a storage adapter pattern to decouple connection management from the underlying storage (e.g., Durable Object SQL storage) [6]. The cleanupClosedConnection logic (which replaces or relates to the removal of server rows) has been improved to ensure session IDs and connection states are properly cleared in a finally block, guaranteeing cleanup even if connection termination throws an error [7][8]. 4. Connection Lifecycle: The SDK has undergone significant refactoring to improve session persistence, including the ability to store and restore session IDs across restarts [7][8]. When a connection is closed, the system now ensures associated resources (subscriptions, session IDs) are cleared to prevent state corruption [7][8]. In summary, these components work together to ensure that an agent's MCP server connections are resilient, properly authenticated via OAuth, and correctly persisted and cleaned up within the Cloudflare Durable Object environment [7][8][5].

Citations:


🌐 Web query:

github.com cloudflare agents packages agents src mcp client.ts restoreConnectionsFromStorage source

💡 Result:

The restoreConnectionsFromStorage method is a member of the MCPClientManager class located in packages/agents/src/mcp/client.ts within the Cloudflare Agents repository [1][2]. Its primary purpose is to automatically re-establish connections to Model Context Protocol (MCP) servers upon Agent initialization (specifically when a Durable Object restarts or hibernates) [1][3]. Key aspects of its implementation and behavior include: 1. Restoration Logic: It retrieves server connection details from storage using getServersFromStorage() and iterates through them to recreate connections [1]. 2. Background Execution: Connections are established in the background (using an internal _restoreServer method) to ensure the restoration process does not block the Durable Object's startup or trigger blockConcurrencyWhile timeouts [4]. 3. Handling OAuth: The method was historically problematic because it bypassed custom OAuth provider overrides defined in the Agent class [5][6]. Recent updates (specifically PR #944) resolved this by introducing a factory pattern: the MCPClientManager now uses an injected factory (linked to the Agent's createMcpOAuthProvider override) rather than a hardcoded DurableObjectOAuthClientProvider [7][6]. This ensures that restored connections correctly utilize custom OAuth storage backends (e.g., KV instead of SQLite) [5][6]. 4. State Management: If a connection requires OAuth and the auth_url is present in storage, the connection state is set to AUTHENTICATING [1][4]. Servers using RPC bindings (rpc:// URLs) are skipped by this method, as they are managed separately by the Agent class using env bindings [1].

Citations:


🌐 Web query:

GitHub cloudflare agents "callback_url" "client_metadata" "cf_agents_mcp_servers"

💡 Result:

In Cloudflare Agents, cf_agents_mcp_servers is a SQLite table used to store metadata about connected Model Context Protocol (MCP) servers [1][2][3]. It is managed by the Agent class to persist connection details across sessions, enabling agents to interact with external services like GitHub, Slack, or databases [1][2][4]. Key technical aspects regarding the fields and management of this system include: 1. cf_agents_mcp_servers Table: This internal table stores critical connection information, including the server's unique ID, name, URL, client_id, auth_url, callback_url, and additional server_options [1][3]. This table is automatically maintained by the Agent; its lifecycle (creation and deletion) is managed by the Agent class [2]. 2. OAuth Callback URL (callback_url): When an MCP server requires OAuth authentication, the agent constructs a callback URL to handle the OAuth flow [5][6][7]. * Construction: By default, the URL is constructed as https://{host}/{agentsPrefix}/{agent-name}/{instance-name}/callback [6]. * Configuration: Developers can influence this using options like callbackHost (to set the origin) and callbackPath (to define a custom path) in addMcpServer [6][8][9]. * Optionality: Recent updates have made callbackHost optional, deferring OAuth setup only to cases where it is strictly required, which simplifies connections to non-OAuth MCP servers [10][8]. 3. client_metadata: When implementing a custom OAuth provider for an MCP server, the client_metadata (typically part of an interface like AgentMcpOAuthProvider) is used to supply necessary OAuth credentials, such as client_id, client_secret, and the redirect_uris [5]. This metadata allows the agent to securely manage the authentication handshake with the MCP provider [7]. 4. Stable IDs: Users can provide a stable ID when calling addMcpServer [11][4]. When provided, this ID replaces auto-generated identifiers in the cf_agents_mcp_servers table and other related storage keys, ensuring that tool names and OAuth state remain predictable across restarts [3][4]. The system includes migration logic (migrateServerId) to transition servers from auto-generated IDs to these stable IDs without losing existing connection data [1][11][3].

Citations:


🌐 Web query:

github.com cloudflare agents do-oauth-client-provider.ts clientMetadata constructor callbackUrl storage

💡 Result:

The file do-oauth-client-provider.ts in the cloudflare/agents repository defines the DurableObjectOAuthClientProvider class, which implements the AgentsOAuthProvider interface [1][2][3]. In the constructor, the provider requires an instance of DurableObjectStorage, along with a clientName and baseRedirectUrl [2]. The DurableObjectStorage instance is used to persist OAuth-related data, such as token storage, PKCE code verifiers, and state verification data, enabling secure handling of OAuth flows within Durable Objects [1][2][3]. Key aspects of the implementation include: Constructor: The constructor accepts a DurableObjectStorage object, enforcing its presence with a check that throws an error if it is invalid [2]. It also initializes the client name and base redirect URL [2]. Storage Usage: The class leverages the storage object to perform asynchronous operations [2]. For instance, it uses storage.put and storage.get to manage: - OAuth tokens [2]. - PKCE code verifiers, often bound to specific client IDs or states to prevent overwriting during concurrent flows [1][4][2]. - State parameter validation data, which includes nonces and server IDs, to ensure the security of the OAuth handshake [3]. The callbackUrl is typically managed in the context of the authentication flow, with the provider handling the necessary redirects and state validation to ensure the integrity of the process [1][4][3]. Recent updates have focused on security hardening, such as binding PKCE verifiers to specific callback states and removing sensitive data from logs [4][5][6][3].

Citations:


🌐 Web query:

"DurableObjectOAuthClientProvider" "baseRedirectUrl" "clientMetadata" "agents/mcp/do-oauth-client-provider"

💡 Result:

DurableObjectOAuthClientProvider is a built-in class in the Cloudflare Agents SDK used to manage secure OAuth flows for MCP (Model Context Protocol) servers [1][2]. It handles security-sensitive logic such as CSRF state generation, PKCE (Proof Key for Code Exchange), nonce management, and token storage [1][3]. Key technical details regarding the requested components: - baseRedirectUrl: This is a string parameter passed to the constructor of DurableObjectOAuthClientProvider [4]. It defines the base URL for the OAuth redirect callback used in the authentication flow [4][1]. - clientMetadata: This is a getter method on the DurableObjectOAuthClientProvider class that returns an OAuthClientMetadata object [4][5]. It provides the necessary metadata (such as client IDs and redirect URIs) required for the OAuth handshake [6][7]. - agents/mcp/do-oauth-client-provider: This is the internal module path where the DurableObjectOAuthClientProvider class is defined [3]. Recent updates to the Cloudflare Agents SDK (specifically in version 0.20.1 and later) have exported this class at the top level of the agents package, allowing users to import it directly as { DurableObjectOAuthClientProvider } from "agents" rather than using deep imports [8][9][3]. Developers often use this class when they wish to customize the storage backend for OAuth tokens (e.g., using a database or KV store instead of the default Durable Object storage) while retaining the built-in security logic of the SDK [6][10][7]. This is typically done by overriding the createMcpOAuthProvider method in an Agent subclass [6][10]. Recent patches have ensured that this custom provider override is correctly respected even during Durable Object restarts and connection restorations [8][9][11].

Citations:


🌐 Web query:

github.com cloudflare agents "baseRedirectUrl" "clientMetadata" "get" "put" "client_id"

💡 Result:

In the Cloudflare Agents SDK, particularly within the context of Model Context Protocol (MCP) OAuth authentication, the baseRedirectUrl, clientMetadata, and clientId properties are associated with the DurableObjectOAuthClientProvider (or custom implementations of AgentMcpOAuthProvider) [1][2][3]. Key details regarding these properties: - clientId: This property stores the unique identifier for the OAuth client [1][4]. The SDK previously exposed this in the OAuth state parameter, but it was updated to store it separately as a secure property to prevent CSRF and state prediction vulnerabilities [4]. You can access or set it using the class getter/setter [1][2]. - clientMetadata: This is a getter that returns an object containing OAuth client information, typically used for dynamic client registration [1][2][3]. When overriding the default OAuth provider, you implement this to return fields such as client_id, client_secret, and redirect_uris [3]. - baseRedirectUrl: This is a property used by the DurableObjectOAuthClientProvider to construct the callback URL that the OAuth provider uses to return the user to your Agent after authentication [1][2]. These components work together to facilitate secure OAuth flows for MCP servers. When addMcpServer() is called, if OAuth is required, the system uses these providers to manage the authentication URL, state storage (including nonces), and the callback mechanism [5][6]. If you need to customize authentication strategies (e.g., using pre-registered credentials), you can override the createMcpOAuthProvider() method in your Agent class to return an object providing these metadata and configuration values [3].

Citations:


🌐 Web query:

cloudflare agents DurableObjectOAuthClientProvider get clientId baseRedirectUrl clientMetadata stored callback_url

💡 Result:

The DurableObjectOAuthClientProvider is a component provided by the Cloudflare Agents SDK designed to manage OAuth authentication state securely within a Durable Object [1][2]. It handles tasks such as storing nonces, generating and validating state for CSRF protection, PKCE (Proof Key for Code Exchange) support, and token persistence [3][2][4]. Key properties and methods of DurableObjectOAuthClientProvider include: - Constructor: It is initialized with a DurableObjectStorage instance (or compatible adapter), the client name, and the baseRedirectUrl [5][4]. - clientId: You can get and set the clientId via the clientId property [5][3]. - baseRedirectUrl: This is passed during instantiation and defines the base URL for OAuth callbacks [5][4]. - clientMetadata: This getter returns an OAuthClientMetadata object, which typically encapsulates information about the OAuth client [5]. - callback_url: While not an explicit property named exactly callback_url, the class utilizes the baseRedirectUrl provided at construction to manage redirection and callback logic [5][4]. The SDK allows developers to customize the OAuth provider by overriding the createMcpOAuthProvider method in their Agent class [4][6]. This is commonly used to implement custom storage backends (e.g., routing tokens to a different database) while maintaining the built-in OAuth logic [4]. The SDK ensures that these custom providers are respected, including during connection restoration from storage [7].

Citations:


🌐 Web query:

github.com cloudflare agents "clientMetadata" "'client_id'" "'redirect_uris'"

💡 Result:

In the context of Cloudflare Agents and the Model Context Protocol (MCP), clientMetadata is a data structure used to provide OAuth client information, including client_id and redirect_uris, when establishing connections to MCP servers [1][2]. If you are implementing a custom OAuth provider for your Cloudflare Agent, you can override the default behavior by defining createMcpOAuthProvider within your Agent class [1][2]. This method allows you to specify the client metadata, which is critical for authentication flows [1][3]: - client_id: The unique identifier for your OAuth client (typically retrieved from environment variables) [1][2]. - redirect_uris: An array containing the authorized callback URL(s) to which the user should be redirected after successful authorization [1][4]. By default, if you do not override this method, Cloudflare Agents use an OAuth 2.0 Dynamic Client Registration process [1][3]. Providing custom metadata is necessary when utilizing pre-registered client credentials or specialized authentication strategies [1][2]. Additionally, the workers-oauth-provider repository managed by Cloudflare uses similar structures for managing OAuth clients, where clientMetadata is parsed and validated to ensure the presence of required fields like redirect_uris [4][5]. Example implementation of the clientMetadata getter: get clientMetadata { return { client_id: env.MCP_CLIENT_ID, client_secret: env.MCP_CLIENT_SECRET, redirect_uris: [callbackUrl], }; } [1][2][3]

Citations:


🌐 Web query:

github.com cloudflare agents DurableObjectOAuthClientProvider clientMetadata source client_id redirect_uris callbackUrl baseRedirectUrl

💡 Result:

The DurableObjectOAuthClientProvider is a component within the Cloudflare Agents framework used to manage OAuth 2.0 flows for MCP (Model Context Protocol) clients [1][2]. It securely handles operations such as CSRF state, PKCE, nonce generation, token management, and storage [1][3][2]. Key components related to your query include: - clientMetadata: This is a property of the provider that returns an object containing OAuth client details, such as the client_id, client_secret, and redirect_uris [1][3][4]. - redirect_uris: An array of URIs where the authorization server sends the user after authentication [1][3][4]. - callbackUrl: Often passed as a parameter to the provider, this represents the endpoint to which the OAuth flow redirects [1][3]. - DurableObjectOAuthClientProvider: Users can override the default OAuth provider by implementing createMcpOAuthProvider in their Agent class, which allows for custom strategies (e.g., pre-registered credentials) or routing token storage to different backends (such as KV or an external database) by passing a custom storage adapter to this provider [1][3][4]. For more details on implementation, developers can refer to the official Cloudflare Agents documentation on the MCP Client API [1][3]. The provider is exported directly from the agents package, enabling easier access for custom implementations [5][6].

Citations:


🌐 Web query:

"DurableObjectOAuthClientProvider" "clientMetadata" "{" "client_id" "redirect_uris" "baseRedirectUrl"

💡 Result:

The DurableObjectOAuthClientProvider is a class within the Cloudflare Agents framework, designed to securely manage OAuth state for Model Context Protocol (MCP) clients [1][2]. It is commonly used to handle nonces, server IDs, authorization states, and token management within a Cloudflare Durable Object [1][3]. Regarding the specific properties and structure you mentioned: 1. clientMetadata: This is a getter property on the DurableObjectOAuthClientProvider class that returns an OAuthClientMetadata object [4][5]. This metadata typically includes information required by the OAuth provider, such as client_id and redirect_uris [6][7]. 2. client_id (or clientId): In the DurableObjectOAuthClientProvider class, this is managed as an accessible property [4][5]. The class provides a getter and setter for clientId, allowing the agent to retrieve or update the identifier used for the OAuth client [4][8][5]. 3. redirect_uris: While redirect_uris is standard in OAuthClientMetadata [6][7], the provider class itself uses a baseRedirectUrl property [4][5]. This baseRedirectUrl is passed into the DurableObjectOAuthClientProvider constructor during initialization [4][9][5]. It serves as the base for the callback URL used during the OAuth flow [9][3]. For custom authentication requirements (e.g., if you need to provide specific client metadata beyond what is automatically handled), you can override the createMcpOAuthProvider() method in your Agent class to return a custom provider or a configured instance of DurableObjectOAuthClientProvider [9][3][10]. Sources: [4], [8], [5] (Provider class definition and properties), [9], [3], [11] (Usage and customization via createMcpOAuthProvider), [6], [7] (OAuth metadata standards).

Citations:


Clarify what reconnect refreshes for OAuth registrations.

reconnectServer does not recreate the stored OAuth provider; it only reconnects or invokes recoverStuckAuthenticating. If the documented issue is allowlisted origin or redirect value changes, either remove and re-add the server or document that reconnect does not update that registration metadata.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@docs/use/mcp-client-servers.md` around lines 39 - 40, Update the reconnect
guidance in the server registration instructions to state that reconnecting does
not refresh stored OAuth provider metadata such as allowlisted origins or
redirect values; require removing and re-adding the server for those changes,
while describing reconnect only as reconnecting or recovering the existing
registration.

Co-authored-by: Kent C. Dodds <me+github@kentcdodds.com>
@kody-bot
kody-bot merged commit 969e103 into main Aug 8, 2026
10 of 12 checks passed
@kody-bot
kody-bot deleted the cursor/mcp-oauth-origin-guidance-44d4 branch August 8, 2026 18:18
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants