Skip to content

feat: JIT scope upgrade via ElicitationAgent#63

Draft
mattzcarey wants to merge 1 commit intomainfrom
feat/auth-improvements
Draft

feat: JIT scope upgrade via ElicitationAgent#63
mattzcarey wants to merge 1 commit intomainfrom
feat/auth-improvements

Conversation

@mattzcarey
Copy link
Contributor

Summary

  • When the execute tool hits a 403 from the Cloudflare API, creates an ElicitationAgent (Durable Object via Agents SDK) that serves a scope picker UI
  • The scope picker matches the Cloudflare design system and shows current scopes pre-checked so the user can add what they need
  • After selecting scopes, the user is redirected through Cloudflare OAuth to get a new token — no full MCP reconnection required
  • The upgraded token is stored in KV and automatically picked up by subsequent execute calls

How it works

  1. execute tool catches 403 → elicitUpdatedScopes() creates ElicitationAgent with error context + current scopes
  2. User opens the elicitation URL → sees scope picker with templates (Read Only, Workers Full, DNS Full) + individual checkboxes
  3. User adds scopes, clicks Continue → redirected to Cloudflare OAuth
  4. /oauth/callback detects scope_upgrade state → exchanges code → stores upgraded token in OAUTH_KV as token-upgrade:{tokenHash}
  5. Next execute call → getUpgradedToken() finds the upgrade in KV → uses the new token transparently

Changes

File Change
src/elicitation-agent.ts New — ElicitationAgent with scope picker UI, OAuth redirect, token storage
src/server.ts elicitUpdatedScopes() passes scopes/tokenHash/userId to agent; execute handler checks KV for upgrades
src/auth/oauth-handler.ts Stores scopes in props; /oauth/callback handles scope_upgrade flow
src/auth/types.ts Added scopes?: string[] to UserAuthProps
src/executor.ts HTTP status propagation from sandbox worker errors (httpStatus field)
src/index.ts Exports ElicitationAgent; routes /elicitation/:id[/action] to DO
wrangler.jsonc DO binding + migration for ElicitationAgent (all envs)
worker-configuration.d.ts ELICITATION_AGENT binding type
src/tests/jit-auth.test.ts New — tests for httpStatus propagation and elicitUpdatedScopes

Test plan

  • npm run typecheck passes
  • npm test — 92 tests pass
  • Deployed to staging (staging.mcp.cloudflare.com)
  • Triggered 403 via execute → elicitation URL returned
  • Opened elicitation URL → scope picker renders correctly
  • Selected "Workers Full Access" template → 21 scopes checked
  • Clicked Continue → redirected to Cloudflare OAuth login

When the execute tool hits a 403 from the Cloudflare API, instead of
returning a generic error, we now create an ElicitationAgent (Durable
Object) that serves a scope picker UI matching the Cloudflare design
system. The user can upgrade their permissions without a full re-auth:

- HTTP status propagation from sandbox worker errors (httpStatus field)
- ElicitationAgent renders scope picker with current scopes pre-checked
- Scope templates (read-only, workers-full, dns-full) + individual checkboxes
- POST /upgrade redirects through Cloudflare OAuth with new scopes
- /oauth/callback detects scope_upgrade state, stores upgraded token in KV
- Execute handler checks KV for upgraded tokens before each API call
- Supports MCP URL elicitation for capable clients, falls back to tool error URL
@mattzcarey mattzcarey force-pushed the feat/auth-improvements branch from 8ae3f6c to 4475054 Compare March 5, 2026 20:03
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