Skip to content

fix(mcp): match Seal's Agents-SDK callback path shape for cf-portal compatibility - #87

Merged
jonnyparris merged 1 commit into
mainfrom
oauth/seal-default-callback
May 26, 2026
Merged

fix(mcp): match Seal's Agents-SDK callback path shape for cf-portal compatibility#87
jonnyparris merged 1 commit into
mainfrom
oauth/seal-default-callback

Conversation

@jonnyparris

Copy link
Copy Markdown
Owner

Discovery

After hitting Redirect URI not allowed by application configuration from cf-portal, I checked how Seal (cloudflare/cto/seals) does it — Seal successfully connects to cf-portal in production.

Seal's callback path (in apps/seal/worker/objects/user/user-do.ts):

callbackPath: `${AGENTS_PREFIX}/user-do/${this.name}/callback`,

Which resolves to /agents/user-do/{userId}/callback. The shape matters — cf-portal validates redirect_uri against an expected OAuth-callback pattern and rejects anything non-canonical.

We were using /agents/oauth/callback (no per-instance segment). cf-portal said no.

Fix

Switch to the Seal-pattern shape for Dodo:

callbackPath: `/agents/coding-agent/${userEmail}/callback`

This is the Agents SDK's default callbackUrl template from MCPClientManager (see /agents/{kebab-class}/{name}/callback in the SDK source). /agents/* Hono wildcard still catches it; the SDK's built-in MCP callback handler resolves state -> server -> token exchange unchanged.

Why this is safe

  • userEmail is already lowercased + trimmed by the auth middleware. @ and . are valid URL path chars per RFC 3986; no encoding needed.
  • Existing tests still pass (817/817) — the route handler signature is unchanged.

Verification

  • npm run typecheck clean
  • npx vitest run 817/817 pass
  • Will verify end-to-end via chrome-devtools after deploy

beep-boop-🤖

…al compatibility)

Reading the Seal implementation (cloudflare/cto/seals) reveals the
canonical Agents-SDK callbackPath shape:

  /agents/<kebab-class-name>/<instance-name>/callback

Seal uses `/agents/user-do/{userId}/callback` and successfully connects
to cf-portal. We were using `/agents/oauth/callback` (no instance name
in the path), which cf-portal rejected with:

  Redirect URI not allowed by application configuration

cf-portal appears to validate redirect URI shape, requiring the
SDK-canonical pattern. Switch Dodo to
`/agents/coding-agent/{userEmail}/callback` to match. The path still
gets caught by `app.all("/agents/*")` so the existing dispatch logic
works unchanged — the Agents SDK's MCP callback handler picks up the
state param and routes to the correct DO storage.

userEmail is already canonicalized by the auth middleware (lowercased,
trimmed). Email chars (@ + .) are safe in URL paths per RFC 3986.

Tests: 817/817 pass. Typecheck clean.

beep-boop-🤖
@jonnyparris
jonnyparris merged commit 14decbe into main May 26, 2026
1 of 2 checks passed
@jonnyparris
jonnyparris deleted the oauth/seal-default-callback branch May 26, 2026 12:22
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.

1 participant