Pre-approve Orbit MCP tools in tool_access_policies claim
What does this MR do and why?
Orbit MCP tools (orbit_list_commands, orbit_invoke_command) prompt for approval on every call in web Duo Chat since 2026-07-10, breaking agentic Orbit flows. The Duo Workflow Service treats the tool_access_policies JWT claim as the pre-approval ceiling (hardening for https://gitlab.com/gitlab-org/gitlab/-/issues/604720), and the claim is built from the tool governance registry, which cannot express MCP tool names, so the Orbit pre-approvals Workhorse sends are always dropped.
This MR adds the Orbit tool names to the claim's allow list, prefixed orbit_<tool> exactly as Workhorse registers them with DWS. The two tools are read-only, have no ai_tool_rules registry entries (no admin rule can target them today), and for custom agents the claim is bounded to the agent's selected subset.
The GitLab MCP server tools (search, gitlab_search, ...) lost pre-approval to the same ceiling but are intentionally out of scope: their names shadow governed capabilities (deny/ask twins spelled differently in the registry), so restoring them safely belongs with the governance mapping planned in https://gitlab.com/gitlab-org/gitlab/-/work_items/606073. This MR addresses the Orbit part of https://gitlab.com/gitlab-org/gitlab/-/issues/607151.
Root cause and scope notes
- Chain:
McpConfigServicemarks Orbit tools asPreApprovedTools-> Workhorse prefixes them and sendsstartRequest.preapproved_tools(workhorse/internal/ai_assist/duoworkflow/mcp.go) -> DWS_merge_jwt_governance_claimsreplaces that list with the claim's allow list whenever governance is active, which is effectively always (read_only_gitlabdefaults to allow;gitlab_duo_governance_settingsis default enabled since 19.0). - The affected path is the legacy
chatdefinition.agentic_chat/v1consumes only the claim's deny half today; allow-side enforcement is tracked in https://gitlab.com/gitlab-org/gitlab/-/issues/603024 and this MR keeps the claim correct for when it lands. - The
wsendpoint is the only claim-minting site that injects the Orbit MCP server; IDE/CLI sessions bring their own MCP config and stay capped by design. - For ask-everything namespaces the claim's allow list was previously empty and the DWS ceiling never engaged; the two Orbit names now make it engage, which fails in the strict direction.
References
- Regression (confidential): https://gitlab.com/gitlab-org/gitlab/-/issues/607151
- DWS ceiling hardening: https://gitlab.com/gitlab-org/gitlab/-/issues/604720
- Governance coverage for MCP tools: https://gitlab.com/gitlab-org/gitlab/-/work_items/606073
Screenshots or screen recordings
GDK, web Duo Chat, legacy chat definition, governance flag on, DWS auth enabled (the GDK default disables it, which hides this bug).
| Before (master) | After (this MR) |
|---|---|
![]() |
![]() |
How to set up and validate locally
- In
<gdk>/gitlab-ai-gateway/.envsetDUO_WORKFLOW_AUTH__ENABLED=true(needs a validDUO_WORKFLOW_SELF_SIGNED_JWT__VALIDATION_KEYPEM and the mkcert root CA inREQUESTS_CA_BUNDLE), thengdk restart duo-workflow-service. - Disable
agentic_chat_flow_registry_migrationso web chat uses the legacychatdefinition; keepgitlab_duo_governance_settingsenabled, with Orbit enabled for the user. - In web Duo Chat ask: "Use orbit_query_graph to list projects whose full_path starts with gitlab-org/". Without this MR the first Orbit call shows an approval card; with it, the tool runs immediately.
MR acceptance checklist
Evaluate this MR against the MR acceptance checklist.

