Skip to content

fix(mcp): translate oauth into the shape Zoo Code validates for .roo/mcp.json - #3633

Merged
dyoshikawa merged 2 commits into
mainfrom
resolve-issue-3629-zoo-mcp-oauth
Oct 25, 2026
Merged

dyoshikawa merged 2 commits into
mainfrom
resolve-issue-3629-zoo-mcp-oauth

Conversation

@dyoshikawa

Copy link
Copy Markdown
Owner

Summary

Zoo Code now validates oauth per transport (Zoo-Code-Org/Zoo-Code#2129, on main after v3.92.0): stdio and sse servers declare oauth: z.undefined(), streamable-http accepts { clientId (required, non-empty), scope?, redirectUri?, resource? }, and McpSettingsSchema.safeParse runs on the whole project file, so one rejected entry makes Zoo Code load none of the servers in .roo/mcp.json. The shared Roo/Zoo adapter (RooMcp) copied the canonical Claude-style oauth block verbatim.

Changes

src/features/mcp/roo-mcp.ts (used by both roo and zoocode):

  • Generate:
    • oauth is kept only on a type: "http" server (written as streamable-http). It is dropped with a warning from stdio, sse and untyped url servers. Zoo Code picks the schema from type alone, so a server with only transport: "http" counts as sse.
    • A block without a non-empty clientId is dropped with a warning.
    • clientId, scope, redirectUri and resource pass through. Claude's callbackPort becomes redirectUri: "http://127.0.0.1:<port>/callback" (the loopback callback Zoo Code listens on; an explicit redirectUri wins). Other keys such as authServerMetadataUrl are dropped with a warning.
  • Import: a loopback http://127.0.0.1|localhost:<port>/callback redirectUri is read back as callbackPort, so generate/import round-trips.
  • The roo target gets the same rules. Roo Code never read oauth, and Zoo Code reads the same .roo/mcp.json.

Docs: the Roo Code / Zoo Code MCP note in docs/reference/file-formats.md (plus the regenerated docs-content.ts).

Not included: the optional tool-scoped zoocode.mcpServers override for Zoo-only resource. A resource already in canonical oauth passes through.

Tests

New unit tests in roo-mcp.test.ts cover the callbackPort mapping, explicit redirectUri/resource, dropped unknown keys, a missing clientId, stdio/sse/untyped servers, the import mapping and the round trip. pnpm cicheck passes.

Closes #3629

🤖 Generated with Claude Code

https://claude.ai/code/session_0179ZomNiDQHCzgoxeRVmfth

dyoshikawa and others added 2 commits October 25, 2026 21:40
…mcp.json

Zoo Code now validates `oauth` per transport (Zoo-Code-Org/Zoo-Code#2129):
stdio and sse servers reject it, streamable-http requires a non-empty
`clientId`, and one rejected entry makes Zoo Code load none of the project
servers. The shared Roo/Zoo adapter copied the canonical Claude-style block
verbatim.

- Keep `oauth` only on `type: "http"` (streamable-http) servers; drop it
  with a warning from stdio, sse and untyped url servers.
- Drop the block with a warning when `clientId` is missing or empty.
- Map Claude's `callbackPort` to `redirectUri: http://127.0.0.1:<port>/callback`,
  pass `clientId`, `scope`, `redirectUri` and `resource` through, and drop
  other keys (e.g. `authServerMetadataUrl`) with a warning.
- On import, read a loopback `/callback` redirectUri back as `callbackPort`.

The rules apply to both the `roo` and `zoocode` targets, which share
`.roo/mcp.json`; Roo Code never read `oauth`.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_0179ZomNiDQHCzgoxeRVmfth
- Drop a `redirectUri` that is not a URL and a `resource` that is not
  "auto", false or a URL, since Zoo Code rejects the whole file for them.
- On import, lift only the exact `http://127.0.0.1:<port>/callback` form
  generate writes back to `callbackPort`; keep a `localhost` redirect URI
  as written so the registered redirect URI survives a round trip.
- Join a canonical `scopes` list into `scope` when no `scope` is given.
- Reuse the shared `isPlainObject` type guard and correct the reason given
  for dropping `oauth` from untyped url servers.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_0179ZomNiDQHCzgoxeRVmfth
@dyoshikawa
dyoshikawa merged commit 486901e into main Oct 25, 2026
9 checks passed
@dyoshikawa
dyoshikawa deleted the resolve-issue-3629-zoo-mcp-oauth branch October 25, 2026 13:14
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.

Follow up Zoo Code upstream updates: MCP oauth now validated per transport (clientId required)

1 participant