feat: add MCP server install for coding agents (workos mcp)#184
Merged
Conversation
Greptile SummaryThis PR adds MCP server onboarding and management for coding agents. The main changes are:
Confidence Score: 5/5The MCP onboarding and management changes appear merge-ready with no blocking issues identified. The implementation scope is well covered by command, onboarding, doctor, preference, and telemetry tests, and no code defects were identified in the reviewed changes.
What T-Rex did
|
nicknisi
added a commit
that referenced
this pull request
Jul 6, 2026
…stall The 30s Promise.race in maybeOfferMcpInstall returned at the deadline while offerMcpInstall kept running: a never-answered clack.confirm still held stdin (ref'd, raw mode), so the process could not exit and `workos install` stayed wedged despite the wrapper. Thread an AbortController from the deadline into clack.confirm — on abort, clack resolves the prompt as a cancel and releases stdin — and skip install work when an answer lands after the deadline. A pty run with stdin held open now exits at ~30s instead of hanging. Addresses Greptile P1 on #184.
… agents Adds `workos mcp install|remove|status` plus a client-writer library (src/lib/mcp-clients.ts) that configures the secret-free WorkOS MCP server (https://mcp.workos.com/mcp, HTTP transport) in Claude Code, Codex, and Cursor. - Claude Code / Codex via their own CLIs; Cursor via a jsonc-parser merge of ~/.cursor/mcp.json that preserves comments, trailing commas, and other servers - Every per-agent operation degrades to a reported outcome, never throws - Both human and JSON output modes; no auth guard (config is secret-free) - Codex eagerly starts OAuth on add and exits non-zero despite persisting the server, so add() verifies actual config state before reporting failure Review: 1 cycle, PASS (0 critical/high).
Wire the Phase 1 MCP client library into three onboarding surfaces plus
adoption telemetry:
- Install-flow consent prompt after the skills step (maybeOfferMcpInstall):
human/TTY-only, not-JSON, decline-respecting, and best-effort so it can
never fail or wedge `workos install`.
- One-time startup banner (maybeShowMcpNotice) nudging `workos mcp install`,
behind a shared one-notice-per-run gate (startup-notice-gate.ts) so the
telemetry notice and unclaimed warning take precedence.
- `workos doctor` MCP section (checkMcp) reporting per-agent status; a
warning is derived only for a Cursor entry with an unexpected URL, never
for absent MCP.
Shared gate state (declined/banner-shown markers, eligibility predicate)
lives in src/lib/mcp-notice.ts and persists in the plain prefs store.
Review (1 pass): fixed a JSON-mode prompt-suppression gap so `install
--json` on a TTY stays machine-clean. Known limitation: install-flow
capture('mcp install') tags don't reach the backend because the installer
session ends (runWithCore finally) before the post-install offer runs;
tracked for a follow-up session-independent wire event.
The install-flow prompt and banner previously used analytics.capture(), which only folds props into installer session tags — dead by the time the offer runs, because run-with-core's finally has already shut down analytics and flushed session.end. Queue real 'mcp offer' command events instead, carrying entry_point, accepted, and per-agent outcomes as mcp.* attributes; queued events ride bin.ts's unconditional final flush, with store-forward covering anything the flush misses. The telemetry gateway's command schema is passthrough and flattens custom attributes onto command spans, so no backend change is needed. Also emits a banner impression event, making banner→install conversion directly measurable instead of approximate.
…stall The 30s Promise.race in maybeOfferMcpInstall returned at the deadline while offerMcpInstall kept running: a never-answered clack.confirm still held stdin (ref'd, raw mode), so the process could not exit and `workos install` stayed wedged despite the wrapper. Thread an AbortController from the deadline into clack.confirm — on abort, clack resolves the prompt as a cancel and releases stdin — and skip install work when an answer lands after the deadline. A pty run with stdin held open now exits at ~30s instead of hanging. Addresses Greptile P1 on #184.
Commit 9464704 was regenerated without a lockfile by pnpm 8 (a stale mise shim shadowing the repo's pnpm@10.28.2): it downgraded the lockfile to v6 format and bumped in-range transitive deps, including @anthropic-ai/claude-agent-sdk 0.2.62 -> 0.2.141, whose SDKResultError type change broke the build. This restores the v9 lockfile as of 4136f62; `pnpm i --frozen-lockfile`, build, and the full test suite pass again.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Gives the GA management MCP server (
https://mcp.workos.com/mcp) a CLI + onboarding surface. Developers previously had to discover the URL on their own and hand-edit a different config format per agent; this adds aworkos mcpcommand group plus three onboarding surfaces, all writing secret-free HTTP config (OAuth happens in the client on first use).Three commits, each independently reviewed and validated:
src/lib/mcp-clients.tsclient writers (Claude Code + Codex shell out to their ownmcp addCLIs; Cursor via JSONC merge on~/.cursor/mcp.json),workos mcp install | remove | statuswith--agentfiltering, JSON output modes, per-agent outcome matrix (a missing binary or version gap is afailedrow, never a crash).workos install, one-time stderr banner (yields to the telemetry notice / unclaimed warning via a one-notice-per-run gate), and aworkos doctorMCP section (report-only; warns only on a misconfigured Cursor URL, never on absent MCP). Declining once silences every automatic surface forever via a prefs marker;workos mcp installstays available manually.mcp offercommand events (mcp.entry_point,mcp.accepted,mcp.agents_installed,mcp.agents_failed). Queued events ride the CLI's unconditional final flush + store-forward, so they ship even though the installer session has already ended. The telemetry gateway's command schema is passthrough and flattens custom attributes onto spans — no backend change required.Safety properties
CLAUDECODE,CURSOR_AGENT,WORKOS_MODE=agent, …) never see a prompt or banner and never get config written by an automatic surfaceValidation
pnpm build/pnpm typecheck/pnpm test(2175 tests) all greencommand(mcp offer, 0ms, success=true), telemetry notice wins the first-run slotRollback
Revert the PR;
workos mcp removecleans user machines. Prefs markers are inert without the code.