cmux Cloud as a ChatGPT/Codex plugin: OAuth, lifecycle tools, sidebar app

LA
4d ago
+3340-97

Makes cmux Cloud a ChatGPT and Codex plugin. Builds step 2 to 4 of #16567 on top of the /api/mcp prototype from #16568.

What changed

OAuth 2.1 authorization server for /api/mcp (services/mcp/oauth.ts)

  • Protected resource metadata (RFC 9728) and authorization server metadata (RFC 8414).
  • PKCE S256 only. Public clients only.
  • Client ID Metadata Documents for chatgpt.com and claude.ai, and dynamic client registration for other clients.
  • iss in every authorization response (RFC 9207).
  • Loopback redirects on any port (RFC 8252), as Codex needs.
  • Opaque tokens, stored only as SHA-256 hashes and bound to a grant: 1 h access tokens, 60-day rotating refresh tokens.
  • Reuse of a code or refresh token revokes the grant. RFC 7009 revocation.
  • Each grant is bound to one user, one billing team, and a scope set (machines:read, machines:write, terminals:read, terminals:write, agents:run).
  • MCP tokens work only on /api/mcp. /api/vm still accepts only Stack sessions.

Consent page at /authorize/mcp. It needs a Stack sign-in. The user picks the team and approves each scope. The decision POST checks the origin and validates the whole request again.

New tools

  • open_cloud: sidebar and thread entrypoint with the MCP App.
  • get_account, create_machine, pause_machine, resume_machine, delete_machine.
  • get_profile: the multi-account profile tool.
  • read_settings and update_settings: plugin settings for the default agent, default size, and idle-machine suggestions.

The lifecycle tools run the existing /api/vm route handlers in process as the already-authenticated user (services/vms/preauthenticatedUser.ts, AsyncLocalStorage). Validation, ownership, billing, and plan gates keep one implementation.

MCP App (services/mcp/cloudMcpApp.ts): one dependency-free HTML view for the ChatGPT sidebar, the conversation panel, and inline results. It shows machines, plan usage, create/pause/resume/delete, starting an agent, and a live terminal with input. It also supports deep links (/machines/<id>/terminals/<id>), model context for the selected machine, and "ask about this terminal".

Payments. OpenAI's plugin guidelines forbid selling digital services in a plugin. The plugin therefore uses the connected team's existing cmux plan. When the plan does not include an action, the tool explains it and links cmux.com/pricing, which is informational. It never starts a checkout. toolErrorFromResponse drops the route's "Upgrade to Pro" call to action.

Plugin package in chatgpt-plugin/cmux-cloud/: plugin.json, mcp.json, onboarding and agent skills, icons, and the review test cases for directory submission.

Fix: run_agent started codex exec in $HOME, which is not a git repository, and Codex refused to run ("Not inside a trusted directory"). It now passes --skip-git-repo-check. Failing test first, then the fix. The Swift cmux vm agent has the same argv (CLI/CMUXCLI+VMTransfer.swift:1768); that is not changed here.

Migration 20261007120000_mcp_oauth is additive: three new tables. It is applied to staging. Production still needs it before this merges.

Verification

  • 149 tests pass: tests/mcp-oauth.test.ts (new), cloud-mcp, cloud-mcp-route, vm-route-auth. Typecheck, eslint, and the complexity gate pass.
  • Live on dev stack gptmcp behind a public tunnel, through the Codex runtime in the ChatGPT desktop app:
    • codex mcp login completed CIMD, consent, and token exchange.
    • get_profile, get_account, and list_machines returned real data.
    • On a real Freestyle machine: create_machine, run_agent, read_terminal, pause_machine, and delete_machine succeeded.
  • The plugin shows under Installed in the ChatGPT desktop app (ChatGPT Work mode).
  • Not verified: the MCP App rendering inside ChatGPT, and the chatgpt.com custom-connector path. Both need a signed-in ChatGPT web session.

Changelog

  • Added: cmux Cloud plugin for ChatGPT and Codex (OAuth, machine lifecycle and agent tools, sidebar app).

View with [code]smith Autofix with [code]smith
Need help on this PR? Tag @codesmith-bot with what you need. Autofix is disabled.


[!NOTE]
High Risk
Introduces OAuth grants, team-scoped tokens, and in-process VM mutations with billing/plan enforcement—security- and infrastructure-critical paths that need careful review before production migration.

Overview
Ships cmux Cloud as a ChatGPT/Codex plugin by wiring a full OAuth 2.1 authorization server for /api/mcp (PKCE, CIMD/DCR, scoped grants tied to user + billing team, opaque tokens in new DB tables) plus .well-known metadata, token/register/revoke routes, and a /authorize/mcp consent UI (team + per-scope approval).

/api/mcp now accepts MCP OAuth bearers (with RFC 9728 challenges on 401) or existing Stack/session auth; lifecycle tools call /api/vm handlers in-process via runAsPreauthenticatedVmUser so plan/ownership rules stay unified. The MCP surface grows with scoped tools (open_cloud, machine CRUD, get_account/get_profile, settings), an embedded MCP App HTML resource for sidebar/inline UI, per-grant plugin settings, and plan-limit errors that link pricing without checkout CTAs.

Adds the chatgpt-plugin/cmux-cloud package (manifest, skills, review cases) and fixes run_agent for Codex with --skip-git-repo-check when $HOME is not a git repo.

Reviewed by Cursor Bugbot for commit 12bf0221d9b3bc642b9582abddb5dbc71e3d9890. Bugbot is set up for automated code reviews on this repo. Configure here.


Summary by cubic

Makes cmux Cloud a ChatGPT and Codex plugin, building steps 2 to 4 of #16567. Adds an OAuth 2.1 authorization server for /api/mcp, machine lifecycle and agent tools, and a ChatGPT sidebar app so users can manage Cloud machines from within ChatGPT.

New Features

  • OAuth 2.1 server with PKCE S256 and public clients only; tokens are opaque, stored as SHA-256 hashes, and bound to one user, one billing team, and a fixed scope set.
  • MCP OAuth tokens work only on /api/mcp; /api/vm still accepts only Stack sessions.
  • Consent page at /authorize/mcp lets the user pick a team and approve each scope.
  • New tools: open_cloud, get_account, get_profile, create_machine, pause_machine, resume_machine, delete_machine, read_settings, and update_settings.
  • Lifecycle tools run the existing /api/vm handlers in-process as the already-authenticated user, keeping validation, ownership, billing, and plan gates in one code path.
  • The MCP App is a dependency-free HTML view for the sidebar, conversation panel, and inline results, with deep links and a live terminal.
  • The plugin uses the connected team's plan and links to cmux.com/pricing when an action is not covered; it never starts a checkout.
  • Ships the chatgpt-plugin/cmux-cloud/ package with manifest, MCP config, and onboarding and agent skills.
  • Fixes run_agent, which failed when codex exec ran outside a git repo; it now passes --skip-git-repo-check.
  • Dev stacks can expose /api/mcp through a public tunnel while keeping sign-in on the tailnet host, via the new mcp-dev-tunnel.py proxy.

Migration

  • 20261018130000_mcp_oauth is additive with three new tables and must run on production before this merges.

Summary by CodeRabbit

  • New Features
    • Added a ChatGPT integration for cmux Cloud to view account and machine details, manage machines, run coding agents, and view or interact with terminals.
    • Added account connection and authorization flows, including team selection and review of requested access.
    • Added settings for agent and machine defaults, plus an interactive Cloud interface for supported MCP clients.
    • Added OAuth access with scoped permissions and connection management.