feat(extensions): connect, reconnect, and disconnect org connections from the desktop - #3258
Merged
Merged
Conversation
…from the desktop detail page Per-member org MCP connections (e.g. Granola) previously showed a misleading Connected status with no lifecycle actions in Settings > Extensions. The detail page now reflects real readiness, offers Connect your account (browser OAuth + poll), Reconnect (fresh authorization via disconnect-my-account + connect/start), and Disconnect (member-scoped credential removal) for per-member connections. Shared org-account connections stay admin-managed.
…iaDB MariaDB aliases JSON to LONGTEXT, so mysql2 returns raw strings where MySQL returns parsed objects. The external MCP OAuth path read oauthConfiguration as a string, dropping the bound issuer and failing every per-member connect callback with MCP_OAUTH_CONFIGURATION_REQUIRED on MariaDB-backed Den deployments. Also harden the lifecycle eval flow for split web/api origins and an externally hosted mock provider.
Accept the shared-v1 OAuth callback shape, wait for lifecycle buttons to re-enable between actions, and capture the sandbox desktop for the actions frame so it cannot duplicate the connected frame.
Contributor
|
The latest updates on your projects. Learn more about Vercel for GitHub.
|
Member
Author
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.






What
Per-member org MCP connections (e.g. Granola, shared by your organization) previously showed a hardcoded Connected status in Settings → Extensions and offered no lifecycle actions — members could not connect, disconnect, or re-authorize an external connection from the desktop at all (the working
connect()inuseOrgMcpConnectionswas never wired to any UI, and disconnect was restricted to native Google Workspace / Microsoft 365 providers).The Extensions connection detail page now:
Not connected/Connected) derived from real per-member readiness,connect/startround trip — required becauseconnect/startshort-circuits to "already connected" while the stored token is valid),POST /v1/mcp-connections/:id/disconnect-my-account; native providers keep theiroauth-providersdisconnect route),reconnectActionOwner === "organization_admin").Also includes:
fix(den-db): MariaDB aliases JSON to LONGTEXT so mysql2 returns strings where MySQL returns objects; the external-MCP credential columns (oauth_configuration,credential_health,scopes,extra) now parse string driver values. Without this, every per-member OAuth callback fails withMCP_OAUTH_CONFIGURATION_REQUIREDon MariaDB-backed Den deployments (verified: identical curl dance passes on MySQL 8, failed on MariaDB 11.8 until this fix).org-connection-lifecycle-desktopproving the full lifecycle end-to-end.How it was verified (Daytona, real e2e)
Two Daytona sandboxes: a Den server sandbox (
test-server-on-daytona.sh, MariaDB + den-api/den-web/worker-proxy, seeded demo org) and an Electron sandbox (test-on-daytona.sh --den-base-url ... --den-api-base-url ...), plus the mock OAuth MCP server (scripts/mock-oauth-mcp-server.mjs) hosted on the Electron sandbox behind a public preview URL so den-api performs real RFC 9728 discovery + DCR + token exchange against it, and the sandbox's real Chromium completes the browser round trip viaxdg-open.Result: PASSED — all 6 frames + voice-over coverage (frame-by-frame proof posted below). Server-side witnesses per frame: mock IdP request log (
GET /authorizewith signed state + DCR client), DenconnectedForMe/ freshconnectedAtafter reconnect,connectedForMe: falseafter disconnect.Also ran:
pnpm --filter @openwork/app typecheck— cleanapps/app: bun test tests/— 493 pass, 0 failapps/app: bun test src/react-app/domains/connections/— 23 pass, 0 fail (new lifecycle-helper coverage)pnpm --filter @openwork-ee/den-db build,pnpm --filter @openwork-ee/den-api build— cleanNote: frame 1's screenshot shows an unrelated transient toast (
opencode_unconfigured) from the freshly created eval workspace booting without a runtime — unrelated to this change.