1# tools/mcp 2 3`strudel-mcp.mjs` is the MCP server Claude Code starts from `.mcp.json` 4(`nix run .#mcp`). It speaks MCP over stdio and forwards each message to 5one of two jevstrudel environments: 6 7- **dev** (the default): the jevstrudel Worker's MCP endpoint 8 (`worker/src/mcp.ts`) that `buck2 run //:dev` runs, playing into this 9 machine's tabs with no sign-in. It keeps no connection, so the Worker can 10 restart or reload under a running Claude Code session; while it is down, 11 tool calls say how to start it, and the tool list is the Worker's own 12 files (`worker/src/tools.json`, then `shared-tools.json`, as the Worker 13 lists them). It polls the Worker's tool list and sends 14 `tools/list_changed` when it changes, so an edited tool reaches Claude 15 Code without a restart. 16- **prod**: the public site's hosted MCP (`/jev/mcp`, 17 `worker/README.md`, The hosted MCP), as the user's own account. 18 19The proxy adds one tool of its own to either list, `use_environment`: 20`{ "environment": "prod" }` or `"dev"` switches, and with no argument it 21says which is in use. A switch sends `tools/list_changed`, since the lists 22differ (prod has `list_songs`, `publish_song`, `comment`, …; both have the 23shared tools, `list_sounds`, `ask_jev_sound`, `api_reference`, the settings, 24`play_song`, `ask_jev_song`, `react` and `vote`). 25 26The first switch to prod signs in. The proxy is an OAuth client of the 27site: the MCP SDK's `auth()` does discovery, dynamic registration, PKCE and 28the token exchange; the proxy listens for the redirect on `127.0.0.1` and 29a random port and opens the authorize page in the Windows browser 30(`rundll32.exe url.dll,FileProtocolHandler` through WSL interop). The user 31signs in with a passkey and allows the app; the call waits up to two 32minutes for that, and if it takes longer, answers with the URL and switches 33by itself when the sign-in completes. A token prod refuses later (expired, 34or the app disconnected in the account panel) is refreshed silently, or 35else the call answers with a new sign-in's URL. Rate limits and missing 36scopes come back as tool errors saying so. 37 38The tokens and the registration are in the proxy's memory only: a new 39Claude Code session signs in once, and the proxy revokes its grant when it 40exits. 41 42| File | What it is | 43|---|---| 44| `strudel-mcp.mjs` | The stdio server: reads the ports, wires the rest together. | 45| `proxy.mjs` | Forwarding and the environment switch, apart from stdio. | 46| `oauth.mjs` | The OAuth client: the SDK's `auth()` plus the loopback redirect, `state` and `iss` checks, and revocation. | 47| `browser.mjs` | Opening the authorize page in the user's browser. | 48| `proxy.test.mjs` | `node --test`: the switch and forwarding, against fakes (in `nix flake check`). | 49| `package.json` | The MCP SDK, pinned; `package-lock.json` is what nix fetches. | 50 51`tools/mcp-e2e/proxy.mjs` runs the prod path end to end against a local 52production Worker.