Skip to content

feat!: org-scope MCP server configs with RBAC - #27942

Merged
ibetitsmike merged 59 commits into
mainfrom
mike/codagt-711-mcp-org-scope
Aug 19, 2026
Merged

feat!: org-scope MCP server configs with RBAC#27942
ibetitsmike merged 59 commits into
mainfrom
mike/codagt-711-mcp-org-scope

Conversation

@ibetitsmike

@ibetitsmike ibetitsmike commented Aug 8, 2026

Copy link
Copy Markdown
Collaborator

Moves mcp_server_configs from deployment scope to organization scope so each organization fully controls the MCP servers its members can use with Coder Agents.

Summary

  • Migration: adds organization_id (NOT NULL, FK) and keeps existing rows as the default organization's originals with credentials intact. Other organizations start with no MCP servers and configure their own; nothing is copied across organizations. Chats outside the default organization keep any now-cross-organization mcp_server_ids entries; the runtime already ignores IDs that do not resolve in the chat's organization, so no data rewrite is needed. Slug uniqueness becomes (organization_id, slug).

  • RBAC: new org-scoped ResourceMCPServerConfig with regosql converter and GetAuthorizedMCPServerConfigs; org admins get in-org CRUD, org members get read (replaced by ACL evaluation in the follow-up ACL PR in this stack).

  • API: all config routes nest under the organization, matching templates: POST|GET /api/experimental/organizations/{organization}/mcp-servers and GET|PATCH|DELETE .../mcp-servers/{mcpserverconfig} (plus oauth2/connect), resolved by a read-only param middleware that conceals read-denied and cross-organization access as 404. Two routes stay on the frozen /api/experimental/mcp/servers/{mcpServer} block: the OAuth2 callback (the redirect URI baked into existing AS-side client registrations) and oauth2/disconnect, which must remain reachable by users removed from the organization so they can still revoke their token grant.

  • Chat runtime: selection validation and generation resolve configs strictly by IDs, enabled state, and the chat's organization in SQL; requested duplicates are normalized; invalid or cross-org IDs are rejected with the precise ID list. IDs already persisted on a chat are exempt from message-time rejection so disabling a selected server never blocks sends; generation skips servers that are no longer usable.

  • Frontend: API layer and admin settings pages target the new endpoints. The admin page manages the default organization's servers; the org picker is tracked separately (CODAGT-714).

  • Security hardening from review: OAuth user grants are additionally bound to oauth2_revocation_url (changing it invalidates grants, and a racing OAuth callback gets 409 instead of recreating a grant). Stack-wide SSRF protection for MCP config-directed traffic was split into its own PR at the top of this stack (feat: enforce SSRF protection for MCP config-directed traffic #28242) to keep this diff reviewable; this PR keeps main's existing discovery IP-range guard. OAuth2 auto-discovery now completes before the config row is inserted: a failed discovery persists nothing, and there is no provisional row that concurrent updates could race against.

Two follow-up PRs in this stack were split out to keep this diff reviewable: #28064 completes the swagger annotations for the moved routes (main already ships these experimental MCP handlers unannotated), and #28065 carries hardening fixes and regression pins on top of the cutover.

  • Force On enforcement (landed on main mid-review) is org-scoped: the forced set is read per chat organization (GetForcedMCPServerConfigsByOrganization), so another organization's force_on server never attaches to a chat.

Breaking changes (experimental API)

The MCP server config endpoints move from the deployment-scoped /api/experimental/mcp/servers block to organization-nested paths: POST|GET /api/experimental/organizations/{organization}/mcp-servers and GET|PATCH|DELETE /api/experimental/organizations/{organization}/mcp-servers/{mcpserverconfig} (plus oauth2/connect). The old paths are removed, so API consumers must supply an organization. Two routes intentionally stay on the frozen /api/experimental/mcp/servers/{mcpServer} block: the OAuth2 callback (its redirect URI is baked into existing AS-side client registrations) and oauth2/disconnect (must remain reachable by users removed from the organization). These endpoints are under /api/experimental, so no deprecation window is provided.

Rolling upgrades

During a rolling deploy, an old replica creating an MCP config can fail the new NOT NULL organization_id constraint until it is upgraded (reads are unaffected: old binaries' generated queries select their own column lists). This matches the repo's existing precedent for additive NOT NULL migrations (000562) and affects only the admin config-create path in the upgrade window.

Upgrades are expected to run in scheduled maintenance downtime with the database locked during migration, so the migration ships no rolling-upgrade compatibility machinery. The down migration deletes organization-created configs (their chat references are cleaned by the 000510 delete trigger) and restores deployment-wide slug uniqueness.

Part of the MCP org-separation stack (CODAGT-711 -> CODAGT-717 audit -> CODAGT-712 ACLs -> CODAGT-806 token RBAC).

Closes https://linear.app/codercom/issue/CODAGT-711

UAT: validated end to end on a two-org dogfood deployment, including a real pre-migration to post-migration upgrade, cross-org isolation (404s), same-slug-two-orgs, chat selection gating, and a live MCP tool call through the org-scoped generation path. The migration was later revised to keep existing rows in the default organization only (no per-organization copies); that revision is covered by the migration test suite.

Mux (AI agent) authored this PR on Mike's behalf.

@linear-code

linear-code Bot commented Aug 8, 2026

Copy link
Copy Markdown

CODAGT-711

@github-actions

github-actions Bot commented Aug 8, 2026

Copy link
Copy Markdown
Contributor

Docs preview

Check off each page once it's been reviewed. If a page changes in a later push, its checkbox clears automatically so it gets a fresh look. Pages not yet wired into the docs navigation aren't listed here.

@ibetitsmike ibetitsmike changed the title mike/codagt 711 mcp org scope feat: org-scope MCP server configs with RBAC Aug 8, 2026

@chatgpt-codex-connector chatgpt-codex-connector 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.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 151915c50b

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread coderd/exp_chats.go Outdated
Comment thread coderd/httpmw/mcpserverconfigparam.go
Comment thread site/src/pages/AISettingsPage/MCPServersPage/MCPServersPage.tsx
@ibetitsmike

Copy link
Copy Markdown
Collaborator Author

@codex review

@chatgpt-codex-connector chatgpt-codex-connector 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.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: badeb1520f

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread coderd/mcp.go Outdated
Comment thread site/src/pages/AgentsPage/components/AgentCreateForm.tsx
@ibetitsmike

Copy link
Copy Markdown
Collaborator Author

@codex review

@chatgpt-codex-connector chatgpt-codex-connector 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.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: c334dc1a17

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread coderd/database/migrations/000565_mcp_server_configs_organization_id.up.sql Outdated
Comment thread coderd/database/dbauthz/dbauthz.go
@ibetitsmike

Copy link
Copy Markdown
Collaborator Author

@codex review

@chatgpt-codex-connector chatgpt-codex-connector 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.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 0cc80dd1b4

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread coderd/database/migrations/000570_mcp_server_configs_organization_id.down.sql Outdated
@ibetitsmike

Copy link
Copy Markdown
Collaborator Author

@codex review

@chatgpt-codex-connector chatgpt-codex-connector 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.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 0cc80dd1b4

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread coderd/database/migrations/000565_mcp_server_configs_organization_id.up.sql Outdated
@ibetitsmike

Copy link
Copy Markdown
Collaborator Author

@codex review

@chatgpt-codex-connector chatgpt-codex-connector 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.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 4d4cc2f1b5

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread coderd/mcp.go
@ibetitsmike

Copy link
Copy Markdown
Collaborator Author

@codex review

@chatgpt-codex-connector chatgpt-codex-connector 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.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 1319b0876e

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread site/src/pages/AgentsPage/components/AgentCreateForm.tsx Outdated
@ibetitsmike

Copy link
Copy Markdown
Collaborator Author

@codex review

@chatgpt-codex-connector chatgpt-codex-connector 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.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 750a7d4861

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread coderd/mcp.go Outdated
@ibetitsmike

Copy link
Copy Markdown
Collaborator Author

@codex review

@chatgpt-codex-connector

Copy link
Copy Markdown

Codex Review: Didn't find any major issues. Swish!

Reviewed commit: b83f3d80ef

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

@ibetitsmike

Copy link
Copy Markdown
Collaborator Author

@codex review

@ibetitsmike
ibetitsmike force-pushed the mike/codagt-711-mcp-org-scope branch from f6d4a2d to 665eda4 Compare August 10, 2026 08:44
@ibetitsmike

Copy link
Copy Markdown
Collaborator Author

@codex review

@chatgpt-codex-connector

Copy link
Copy Markdown

Codex Review: Didn't find any major issues. Already looking forward to the next diff.

Reviewed commit: 665eda46de

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

@ibetitsmike
ibetitsmike force-pushed the mike/codagt-711-mcp-org-scope branch from 665eda4 to cb91848 Compare August 10, 2026 18:31
@ibetitsmike

Copy link
Copy Markdown
Collaborator Author

@codex review

…zation only

The organization scoping migration no longer copies existing MCP server
configs into every live organization. The deployment-wide originals move
to the default organization and other organizations start with no MCP
servers. Chat references outside the default organization are dropped,
and the rolling-upgrade trigger now drops cross-organization config IDs
instead of remapping them to same-slug copies.
Simplify the compatibility trigger's aggregate FILTER to a WHERE clause,
rename the stale remapTriggerExists test helper, and cover the trigger's
cross-organization drop on the update path.
Upgrades run in scheduled maintenance downtime with the database locked
during migration, so no pre-scoping replica writes chat MCP selections
after the migration commits.
… on read

Replace the eager migrateLegacyMCPSelection/useLegacyMCPSelectionMigration
effect pair with a self-healing read: when getSavedMCPSelection falls back
to the legacy unscoped localStorage key (default organization only), the
parsed selection is rewritten under the organization-scoped key and the
legacy entry is removed. The healing is skipped while the server list is
empty, since saved IDs cannot be validated yet, and never runs for
non-default organizations. Callers no longer need migration wiring.
@ibetitsmike
ibetitsmike force-pushed the mike/codagt-711-mcp-org-scope branch from c93f896 to 14fd3a2 Compare August 19, 2026 17:47
@ibetitsmike ibetitsmike changed the title feat!: org-scope MCP server configs with RBAC feat: org-scope MCP server configs with RBAC Aug 19, 2026
@github-actions github-actions Bot removed the release/breaking This label is applied to PRs to detect breaking changes as part of the release process label Aug 19, 2026
@ibetitsmike ibetitsmike changed the title feat: org-scope MCP server configs with RBAC feat!: org-scope MCP server configs with RBAC Aug 19, 2026
@github-actions github-actions Bot added the release/breaking This label is applied to PRs to detect breaking changes as part of the release process label Aug 19, 2026
@ibetitsmike
ibetitsmike merged commit 443e3b9 into main Aug 19, 2026
35 checks passed
@ibetitsmike
ibetitsmike deleted the mike/codagt-711-mcp-org-scope branch August 19, 2026 18:04
@github-actions github-actions Bot locked and limited conversation to collaborators Aug 19, 2026
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.

Labels

release/breaking This label is applied to PRs to detect breaking changes as part of the release process

Projects

None yet

Development

Successfully merging this pull request may close these issues.

5 participants