Skip to content

feat(proxy): add mcp-auth-proxy OAuth rewriting proxy#407

Open
TarasSpashchenko wants to merge 36 commits into
mainfrom
feat/mcp-auth-proxy
Open

feat(proxy): add mcp-auth-proxy OAuth rewriting proxy#407
TarasSpashchenko wants to merge 36 commits into
mainfrom
feat/mcp-auth-proxy

Conversation

@TarasSpashchenko

Copy link
Copy Markdown
Collaborator

Summary

Adds codemie mcp-auth-proxy — a local, loopback-only, transparent HTTP proxy that sits between Claude Code and remote MCP servers implementing MCP Authorization (OAuth 2.1, spec rev 2025-11-25). It lets Claude Code authenticate against MCP servers whose IdP rejects Claude Code's default client identity, by surgically rewriting client_name (DCR) and scope/resource at every point the spec requires — without modifying the MCP servers, without pre-registered clients, and without breaking Claude Code's native lazy browser-based auth flow.

Full design rationale is in docs/SPEC-mcp-auth-proxy.md (authoritative spec) and docs/superpowers/specs/2026-07-03-mcp-auth-proxy-design.md (repo-binding design, decisions D1–D8).

Changes

  • New module src/mcp/auth-proxy/: types.ts, config.ts, rewrites.ts (pure R1–R6 rewrite rules), state.ts, upstream-client.ts, metadata-cache.ts (OAuth discovery + TTL cache), server.ts (route dispatch + streaming pass-through), runtime.ts (shared daemon runtime)
  • New daemon entry src/bin/mcp-auth-proxy-daemon.ts + git-tracked wrapper bin/mcp-auth-proxy-daemon.js, mirroring the existing proxy-daemon pattern (deliberately without the self-healing watcher — spec non-goal)
  • New CLI command codemie mcp-auth-proxy start|stop|status, registered in src/cli/index.ts
  • Streaming pass-through uses raw node:http/node:https + stream/promises pipeline (gate-approved deviation from the spec's undici hint — no new dependency, matches the repo's proven SSO-proxy streaming template)
  • Docs: docs/COMMANDS.md updated with the new command surface
  • Tests: 5 new suites under src/mcp/auth-proxy/__tests__/ (config, rewrites, state, metadata-cache, server), 67 tests total, including a real local fake-upstream integration suite covering SSE streaming, multi-route isolation, and OAuth rewrite correctness

Delivered via an autonomous SDLC run (docs/superpowers/runs/20260703-1845-mcp-auth-proxy/): spec → plan → TDD implementation → two-round multi-lens code review → QA gates → complexity assessment. Code review found and fixed 3 issues before merge: a crash on malformed request-targets, prototype-inherited route keys resolving as valid routes, and unrestricted fetching of an upstream-supplied metadata hint (SSRF hardening).

Testing

  • Tests added/updated — 67 new tests across 5 suites (unit + local-integration)
  • Manual testing done — real daemon lifecycle smoke test (start/status//healthz/stop) against an isolated CODEMIE_HOME

Checklist

  • Code follows project standards
  • CI is green (npm run ci gates: license-check, lint, build, test:unit, test:integration all pass; npm run test:integration also verified separately)
  • No merge conflicts with main

TarasSpashchenko and others added 30 commits July 3, 2026 19:08
Design for codemie mcp-auth-proxy (run 20260703-1845-mcp-auth-proxy),
binding docs/SPEC-mcp-auth-proxy.md to repo patterns; resolves streaming
mechanism to node:http + pipeline per spec.clarification gate.

Generated with AI

Co-Authored-By: codemie-ai <codemie.ai@gmail.com>
Nine TDD tasks binding the approved design to concrete code; design doc
errata: license-check gates dependencies only, no package.json change,
upstream-client.ts file split.

Generated with AI

Co-Authored-By: codemie-ai <codemie.ai@gmail.com>
Generated with AI

Co-Authored-By: codemie-ai <codemie.ai@gmail.com>
Generated with AI

Co-Authored-By: codemie-ai <codemie.ai@gmail.com>
Generated with AI

Co-Authored-By: codemie-ai <codemie.ai@gmail.com>
Generated with AI

Co-Authored-By: codemie-ai <codemie.ai@gmail.com>
Generated with AI

Co-Authored-By: codemie-ai <codemie.ai@gmail.com>
…OAuth rewrites

Generated with AI

Co-Authored-By: codemie-ai <codemie.ai@gmail.com>
Generated with AI

Co-Authored-By: codemie-ai <codemie.ai@gmail.com>
Generated with AI

Co-Authored-By: codemie-ai <codemie.ai@gmail.com>
Generated with AI

Co-Authored-By: codemie-ai <codemie.ai@gmail.com>
…very

Address code review CR-001 (crash on malformed request-target),
CR-002 (prototype-inherited route keys return 404), CR-003 (restrict
captured resource_metadata hint to the configured upstream host).

Generated with AI

Co-Authored-By: codemie-ai <codemie.ai@gmail.com>
Normative spec (docs/SPEC-mcp-auth-proxy.md) that the feature implements,
plus the run 20260703-1845 work item record (status: Ready for review).

Generated with AI

Co-Authored-By: codemie-ai <codemie.ai@gmail.com>
mcp-auth-proxy-windows Task 1

Generated with AI

Co-Authored-By: codemie-ai <codemie.ai@gmail.com>
mcp-auth-proxy-windows Task 2

Generated with AI

Co-Authored-By: codemie-ai <codemie.ai@gmail.com>
mcp-auth-proxy-windows Task 3

Generated with AI

Co-Authored-By: codemie-ai <codemie.ai@gmail.com>
mcp-auth-proxy-windows Task 4

Generated with AI

Co-Authored-By: codemie-ai <codemie.ai@gmail.com>
mcp-auth-proxy-windows Task 5

Generated with AI

Co-Authored-By: codemie-ai <codemie.ai@gmail.com>
mcp-auth-proxy-windows Task 6

Generated with AI

Co-Authored-By: codemie-ai <codemie.ai@gmail.com>
Addresses code-review CR-W-001: use requestShutdown's ack result so a wedged
daemon escalates to SIGTERM immediately instead of polling ~5s first.
Happy path unchanged.

mcp-auth-proxy-windows

Generated with AI

Co-Authored-By: codemie-ai <codemie.ai@gmail.com>
mcp-auth-proxy-windows

Generated with AI

Co-Authored-By: codemie-ai <codemie.ai@gmail.com>
Generated with AI

Co-Authored-By: codemie-ai <codemie.ai@gmail.com>
Generated with AI

Co-Authored-By: codemie-ai <codemie.ai@gmail.com>
Generated with AI

Co-Authored-By: codemie-ai <codemie.ai@gmail.com>
…-proxy tls

Generated with AI

Co-Authored-By: codemie-ai <codemie.ai@gmail.com>
…vided

Generated with AI

Co-Authored-By: codemie-ai <codemie.ai@gmail.com>
…d state

Generated with AI

Co-Authored-By: codemie-ai <codemie.ai@gmail.com>
…-proxy

Generated with AI

Co-Authored-By: codemie-ai <codemie.ai@gmail.com>
…ocal ca

Generated with AI

Co-Authored-By: codemie-ai <codemie.ai@gmail.com>
TarasSpashchenko and others added 4 commits July 5, 2026 23:25
…atus/stop

Generated with AI

Co-Authored-By: codemie-ai <codemie.ai@gmail.com>
Generated with AI

Co-Authored-By: codemie-ai <codemie.ai@gmail.com>
CR-001 protocol-aware already-running banner + tls mismatch warning
CR-002 uninstall reads existing CA only, never regenerates material
CR-003 trust exec timeout + stderr surfaced on failure
CR-004 tests: EKU serverAuth assertion + expiry-window reissue
CR-005 leaf validity clamped to CA expiry
CR-006 corrupt/mismatched key material detected and self-healed
CR-007 linux NSS DB bootstrap + system-store manual fallback
CR-008 idempotent uninstall-when-absent + action-aware manual text

Generated with AI

Co-Authored-By: codemie-ai <codemie.ai@gmail.com>
Generated with AI

Co-Authored-By: codemie-ai <codemie.ai@gmail.com>
TarasSpashchenko and others added 2 commits July 6, 2026 00:03
- trust.ts: build the Linux NSS DB path with path.posix.join so the
  certutil command never carries host backslashes (production fix).
- certs.test.ts: skip the 0600 key-mode assertion on win32 (Windows
  secures files via ACLs, not POSIX mode bits).
- runtime.test.ts: tolerate the shared logger's held append stream on
  <home>/logs when removing the temp home (Windows cannot unlink open files).

Generated with AI

Co-Authored-By: codemie-ai <codemie.ai@gmail.com>
The daemon's shared logger opens a lifetime append stream on
<home>/logs/debug-*.log. Windows cannot unlink an open file, so the
previous retry-based rm compounded across the tree and blew the 10s
afterEach hook timeout. Release the handle with logger.close() before
removing the temp home, and make rm fail-fast so the insurance path
can never hang. No-op on Linux, which deletes open files fine.

Generated with AI

Co-Authored-By: codemie-ai <codemie.ai@gmail.com>
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