Skip to content

Force On MCP servers reach Owners outside the server's ACL #30652

Open

Description

@fpoussin-finary

Summary

#27944 says "Force On respects the ACL: the forced set is loaded as the chat owner, so a force_on server whose ACL denies the owner never attaches". The forced set is filtered through the owner's RBAC, though, and a site Owner (or an org admin) can read every MCP server config. So a Force On server shared with a single user is forced onto every Owner's chats as well.

The web UI has the same gap for Default On: getDefaultMCPSelection and getSavedMCPSelection select every Force On and Default On server the user can list, and an Owner lists them all.

Steps to reproduce (v2.38.0)

  1. As an Owner, create an MCP server config with availability: force_on.
  2. PATCH /api/v2/organizations/{org}/mcp-servers/{id}/acl with {"user_roles": {"<user A>": "read"}, "group_roles": {"<org ID>": ""}}: shared with user A only, Everyone removed.
  3. As a different Owner, start a chat from the web UI or with POST /api/v2/chats and no mcp_server_ids.

Expected: the chat does not get the server, since its ACL does not name that Owner.

Actual: the chat's mcp_server_ids holds the server and its tools are offered to the model. With default_on instead of force_on, the web UI pre-selects the server for the Owner.

Where

  • coderd/x/chatd/chatd.go, forcedMCPServerConfigsForOwner: GetForcedMCPServerConfigsByOrganization runs as the owner's RBAC subject. Owner roles grant read on every config, so the ACL is never consulted.
  • site/src/pages/AgentsPage/utils/mcpSelection.ts: selection is by availability alone.

Suggested fix

Evaluate Force On (and the UI's Default On pre-selection) against the ACL's own principals: the owner's user ID, their groups, and the organization's Everyone group. RBAC read would no longer count. Owners keep managing and reading every config; they only stop getting servers forced or pre-selected that are not shared with them. For the UI, a per-caller field on MCPServerConfig, such as acl_granted, would let the chat input skip those servers.

We run this in a fork and can open a PR if the approach suits you.

Activity

  1. linear-code commented on Oct 12, 2026

    @linear-code
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions