Skip to content

feat(mcp): 'Clear sign-in data' recovery for stuck MCP auth#2189

Open
benjaminshafii wants to merge 1 commit into
devfrom
fix/mcp-auth-clear-recovery
Open

feat(mcp): 'Clear sign-in data' recovery for stuck MCP auth#2189
benjaminshafii wants to merge 1 commit into
devfrom
fix/mcp-auth-clear-recovery

Conversation

@benjaminshafii

Copy link
Copy Markdown
Member

Problem

Stale MCP OAuth state (tokens + clientInfo + oauthState from a broken flow) can permanently block re-auth. Real case: PostHog's OAuth proxy returns Unable to determine region forever once the stored client registration's region mapping expires — retrying Sign in reuses the poisoned client and fails every time. Today the only fix is hand-editing ~/.local/share/opencode/mcp-auth.json, which is not something we can walk a customer through.

Fix (two gaps)

1. UI gap — the recovery action was hidden exactly when needed. The sign-out button only rendered when status === "connected". The broken states (failed, needs_auth, needs_client_registration) now show a Clear sign-in data button next to Sign in, reusing the existing logout confirm flow, with a hint: "Stuck signing in? Clear sign-in data to reset the saved OAuth tokens and app registration, then sign in again."

2. Server gap — logout depended on the engine being reachable. DELETE /workspace/:id/mcp/:name/auth now falls back to removing the entry from mcp-auth.json directly when the engine call fails for any reason other than 404 (engine down, old engine, broken state). New mcp-auth-store.ts mirrors opencode's xdg data-dir resolution; the write is idempotent and only touches the named entry. Also fixes the approval/audit path string, which pointed at ~/.config/opencode/ instead of the engine's actual data dir (~/.local/share/opencode/).

Support flow this enables: "Open the extension → Clear sign-in data → Sign in again" — works even if the engine itself is wedged.

Tests

  • bun test src/mcp-auth-store.e2e.test.ts — 2 pass: clears the stale entry through the full HTTP route with an unreachable engine, leaves other entries untouched; second delete is idempotent
  • bun test (apps/server) — 413 pass / 7 fail (same 7 pre-existing on dev; the real-engine OAuth e2e flaked once under load at 92s but passes in isolation in 1.6s)
  • pnpm typecheck — app clean; server only the pre-existing SessionMessagesResponse2 error

No video: UI change is a button + hint in an existing row; to reproduce, break an MCP's auth (e.g. PostHog with a stale client) and check the failed/needs-auth state now offers Clear sign-in data.

Stale OAuth state (tokens + clientInfo from a broken flow, e.g. PostHog's
'Unable to determine region') can permanently block re-auth, and the only
fix was hand-editing ~/.local/share/opencode/mcp-auth.json. Two gaps:

- UI: the sign-out action was only rendered when status === connected —
  hidden in exactly the broken states (failed / needs_auth /
  needs_client_registration) where users get stuck. Those states now show
  a 'Clear sign-in data' button next to Sign in, reusing the existing
  logout confirm flow, with a hint explaining the reset.
- Server: DELETE /workspace/:id/mcp/:name/auth depended on the engine
  being reachable. When the engine call fails (not a 404), the route now
  falls back to removing the entry from mcp-auth.json directly
  (mcp-auth-store.ts, mirroring opencode's xdg data-dir resolution).
  Also fixes the approval/audit path, which pointed at the config dir
  instead of the engine's data dir.
@vercel

vercel Bot commented Jun 12, 2026

Copy link
Copy Markdown
Contributor

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated (UTC)
openwork-app Ready Ready Preview, Comment Jun 12, 2026 4:07am
openwork-den Ready Ready Preview, Comment Jun 12, 2026 4:07am
openwork-den-worker-proxy Ready Ready Preview, Comment Jun 12, 2026 4:07am
openwork-landing Ready Ready Preview, Comment, Open in v0 Jun 12, 2026 4:07am

@cubic-dev-ai cubic-dev-ai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

2 issues found across 4 files

Prompt for AI agents (unresolved issues)

Check if these issues are valid — if so, understand the root cause of each and fix them. If appropriate, use sub-agents to investigate and fix each issue separately.


<file name="apps/app/src/react-app/domains/settings/pages/mcp-view.tsx">

<violation number="1" location="apps/app/src/react-app/domains/settings/pages/mcp-view.tsx:1133">
P3: New user-facing strings are hardcoded and bypass i18n, causing untranslated text in non-English locales.</violation>
</file>

<file name="apps/server/src/mcp-auth-store.ts">

<violation number="1" location="apps/server/src/mcp-auth-store.ts:24">
P2: MCP auth-store path resolution omits `OPENWORK_DATA_DIR`, so clear-auth can silently report success without deleting the real entry in orchestrator-managed data dirs.</violation>
</file>

Reply with feedback, questions, or to request a fix.

Re-trigger cubic

// opencodeDataDirs() in opencode-db.ts.
function opencodeDataDirs(): string[] {
const dirs: string[] = [];
const xdg = process.env.XDG_DATA_HOME?.trim();

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2: MCP auth-store path resolution omits OPENWORK_DATA_DIR, so clear-auth can silently report success without deleting the real entry in orchestrator-managed data dirs.

Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. At apps/server/src/mcp-auth-store.ts, line 24:

<comment>MCP auth-store path resolution omits `OPENWORK_DATA_DIR`, so clear-auth can silently report success without deleting the real entry in orchestrator-managed data dirs.</comment>

<file context>
@@ -0,0 +1,61 @@
+// opencodeDataDirs() in opencode-db.ts.
+function opencodeDataDirs(): string[] {
+  const dirs: string[] = [];
+  const xdg = process.env.XDG_DATA_HOME?.trim();
+  if (xdg) dirs.push(join(xdg, "opencode"));
+  dirs.push(join(homedir(), ".local", "share", "opencode"));
</file context>

disabled={props.busy || props.logoutBusy}
onClick={() => props.onRequestLogout(props.entry.name)}
>
{clearingThis ? t("mcp.logout_working") : "Clear sign-in data"}

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P3: New user-facing strings are hardcoded and bypass i18n, causing untranslated text in non-English locales.

Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. At apps/app/src/react-app/domains/settings/pages/mcp-view.tsx, line 1133:

<comment>New user-facing strings are hardcoded and bypass i18n, causing untranslated text in non-English locales.</comment>

<file context>
@@ -1110,15 +1110,39 @@ function McpConfiguredServerDetails(props: Parameters<typeof McpConfiguredServer
+                disabled={props.busy || props.logoutBusy}
+                onClick={() => props.onRequestLogout(props.entry.name)}
+              >
+                {clearingThis ? t("mcp.logout_working") : "Clear sign-in data"}
+              </Button>
+            ) : null}
</file context>

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