Skip to content

fix(oauth): default MCP resource when Gemini omits it - #948

Merged
kody-bot merged 1 commit into
mainfrom
cursor/gemini-oauth-resource-default-1c0d
Jul 25, 2026
Merged

kody-bot merged 1 commit into
mainfrom
cursor/gemini-oauth-resource-default-1c0d

Conversation

@kentcdodds

@kentcdodds kentcdodds commented Jul 25, 2026 •

Copy link
Copy Markdown
Owner

Summary

Gemini Spark custom MCP authorize requests omit RFC 8707 resource. That left grants without a resource, so token exchange minted tokens with no audience and /mcp rejected them (invalid_token / audience mismatch). After approve, Gemini saw “no resource” / failed to stay connected even though OAuth UI returned 200.

This defaults authRequest.resource to {origin}/mcp when the client does not send one. Explicit resource values (Claude, etc.) are unchanged.

Test plan

  • Unit: Gemini-shaped authorize (no resource) defaults to https://heykody.dev/mcp in completeAuthorization
  • Unit: Claude-shaped authorize still keeps explicit resource
  • After deploy: reconnect Gemini custom app with https://heykody.dev/mcp (fresh authorize so the new grant gets /mcp)
System recap — extends existing primitives (medium risk)

Mode: recap · Base: main @ 32bd8b8c · Head: 34885e34

Classification: extends — MCP OAuth authorize now fills a missing RFC 8707 resource so grants/tokens carry an /mcp audience.

Primitives touched

Primitive Group Impact
mcp-oauth auth extends — default {origin}/mcp when authorize omits resource
app-sessions auth composes — shared authorize handlers; session behavior unchanged

System map

Gemini authorize → approve → grant with default MCP resource → token audience accepted by /mcp.

Legend: green = composes (wiring only) · amber = extended by this PR · red = new primitive · gray = context (unchanged, included only when an edge crosses it).

flowchart LR
	mcpOauth["mcp-oauth<br/>MCP OAuth"]:::extended
	appSessions["app-sessions<br/>Browser sessions"]:::touched
	mcpServer["mcp-server<br/>MCP endpoint"]:::untouched
	appSessions -->|"authorize approve"| mcpOauth
	mcpOauth -->|"default resource → grant/token audience"| mcpServer
	classDef touched fill:#1a7f37,color:#fff
	classDef extended fill:#9a6700,color:#fff
	classDef added fill:#cf222e,color:#fff
	classDef untouched fill:#57606a,color:#fff
Loading

Before / after

Before After
Gemini authorize (no resource) Grant has no resource → token has no audience → /mcp 401 Grant resource = {origin}/mcp → token audience matches /mcp
Claude authorize (resource set) Unchanged Unchanged
Open in Web Open in Cursor 

Summary by CodeRabbit

  • Bug Fixes

    • OAuth authorization requests that omit an MCP resource now automatically use the app’s default MCP resource.
    • Improved compatibility with authorization clients that do not provide the optional resource parameter.
  • Tests

    • Added coverage verifying default resource handling without altering the original authorization request.

Gemini Spark custom MCP apps omit RFC 8707 resource on authorize, so grants
mint tokens with no audience and /mcp rejects them. Default resource to
{origin}/mcp when the client did not send one.
@coderabbitai

coderabbitai Bot commented Jul 25, 2026 •

Copy link
Copy Markdown

Review Change Stack

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro Plus

Run ID: c8c8f35d-a8cd-4d3f-806d-eb708f4e673e

📥 Commits

Reviewing files that changed from the base of the PR and between 32bd8b8 and 34885e3.

📒 Files selected for processing (2)
  • packages/worker/src/oauth-handlers.ts
  • packages/worker/src/oauth-handlers.workers.test.ts

📝 Walkthrough

Walkthrough

OAuth authorization handling now supplies the application’s /mcp URL when an authorization request omits resource. Both authorization paths pass the environment into request resolution, and worker tests cover Gemini-shaped requests without mutating the original fixture.

Changes

OAuth resource defaulting

Layer / File(s) Summary
Resource resolution and authorization wiring
packages/worker/src/oauth-handlers.ts
Authorization request resolution derives the application MCP resource from the environment and applies it when resource is absent in both authorization flows.
Gemini-shaped request validation
packages/worker/src/oauth-handlers.workers.test.ts
Fixtures and tests verify that an omitted resource becomes https://heykody.dev/mcp without changing the original request.

Estimated code review effort: 3 (Moderate) | ~15–30 minutes

Sequence Diagram(s)

sequenceDiagram
  participant Client
  participant handleAuthorizeRequest
  participant resolveAuthRequest
  participant getAppBaseUrl
  Client->>handleAuthorizeRequest: Submit OAuth authorization request
  handleAuthorizeRequest->>resolveAuthRequest: Resolve request with env
  resolveAuthRequest->>getAppBaseUrl: Derive application base URL
  getAppBaseUrl-->>resolveAuthRequest: Application base URL
  resolveAuthRequest-->>handleAuthorizeRequest: Request with /mcp resource
  handleAuthorizeRequest-->>Client: Authorization response
Loading

Possibly related PRs

  • kentcdodds/kody#582: Modifies the same OAuth authorization handling path with PKCE validation.
  • kentcdodds/kody#657: Clarifies getAppBaseUrl origin and fallback behavior used by resource defaulting.

Suggested reviewers: kody-bot

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly summarizes the main change: defaulting the MCP resource when Gemini omits the OAuth resource parameter.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
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
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch cursor/gemini-oauth-resource-default-1c0d

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.

@kody-bot
kody-bot marked this pull request as ready for review July 25, 2026 22:14
@github-actions

Copy link
Copy Markdown
Contributor

🔎 Preview deployed: https://kody-pr-948.kody-a99.workers.dev

Worker: kody-pr-948
D1: kody-pr-948-db
KV: kody-pr-948-oauth-kv

Mocks:

@kody-bot
kody-bot merged commit f849df4 into main Jul 25, 2026
15 checks passed
@kody-bot
kody-bot deleted the cursor/gemini-oauth-resource-default-1c0d branch July 25, 2026 22:21
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