Commit a6811d3
feat(modes): per-mode MCP server restrictions (allowlist) (#453)
* feat(modes): add per-mode allowed MCP servers (allowlist)
Adds optional `allowedMcpServers: string[]` to ModeConfig. When defined,
only listed MCP servers' schemas are injected into the system prompt and
exposed as native tools, preventing context bloat in specialized modes.
- Schema: packages/types ModeConfig + schemas/roomodes.json
- Prompt: filter mcpHub.getServers() by allowlist in system.ts and
native-tools/mcp_server.ts; wired via core/task/build-tools.ts
- UI: new McpServerRestriction.tsx editor (cachedState + 150ms debounce,
per AGENTS.md SettingsView pattern), integrated into ModesView for both
edit and create flows
- Tests: schema, system-prompt filtering, native-tool filtering,
component behavior; vitest config + toolkit mock updates
Ports upstream RooCodeInc/Roo-Code#12004 (fix from simurg79/Roo-Code#1).
* test(modes): relax over-strict Profiler assertion in McpServerRestriction Test 3
`<Profiler onRender>` fires whenever the Profiler boundary commits, which
happens whenever its parent re-renders — even when every child inside
bails out via React.memo. The `=== 0` assertion in Test 3 part (b)
therefore measured the Profiler's own commit cadence rather than the
child's render work. Relax to `<= 1` and document the caveat in the
test's JSDoc.
The real anti-flicker guarantee is verified by Test 2 (DOM-node identity
preserved across an equivalent `mcpServers` heartbeat). No production
code changed.
* fix(mcp): enforce mode allowlist in access_mcp_resource availability check
Restricted modes could still read MCP resources from disallowed servers because hasAnyMcpResources() inspected the full hub. Forward allowedMcpServers from build-tools into filterNativeToolsForMode so the resource-availability check only considers allowed servers. Addresses review comment from PR #75 (RooCodeInc/Roo-Code -> Zoo-Code-Org/Zoo-Code).
* fix(modes): avoid clobbering concurrent mode edits in debounced MCP allowlist flush
The 150ms debounced flush in McpServerRestriction captured the customMode from the scheduling render and spread it on commit, so an edit to another field within the debounce window was overwritten by the stale snapshot. Track the latest customMode/onCommit in refs and merge allowedMcpServers into the freshest snapshot at flush time. Adds Test 4 covering concurrent-edit safety. Addresses review comment from PR #75.
* ci: trigger checks
* fix(webview-tests): correct toolkit mock data-testid + missing exports
* test(modes): align McpServerRestriction queries with updated checkbox mock shape
The shared toolkit mock now forwards data-testid to the inner <input type='checkbox'>, so getByTestId resolves to the checkbox input directly. The old queries re-derived the input via .querySelector("input[type='checkbox']") on the testid element, which now returns null (the testid element IS the input). Update the 5 affected tests to target the checkbox input directly for both the restrict toggle and per-server checkboxes. Meaningful assertions (allowlist enforcement, debounced-flush-merge) are unchanged.
* fix(modes): address CodeRabbit review on per-mode MCP allowlist
- filter-tools-for-mode: default access_mcp_resource gating to modeConfig.allowedMcpServers when the parameter is omitted (defense in depth), so a restricted mode can never retain the tool via a caller that forgets to thread the allowlist. Adds tests covering param-omitted fallback and explicit-param precedence.
- ModesView: add newModeAllowedMcpServers (and switchMode/resetFormState) to handleCreateMode useCallback deps and drop the now-unnecessary react-hooks/exhaustive-deps disable, fixing a potential stale-closure on mode creation.
- system.ts: document that the capabilities MCP line is already gated by the filtered allowlist via shouldIncludeMcp.
Addresses review feedback on PR #453.
* fix(modes): address frontend PR review on per-mode MCP allowlist (F4-F7)
F4: extract shared McpServerChecklist (server checkboxes + not-connected warning) and use it in both the edit panel and the create-mode dialog. F5: add slug-change reseed tests. F6: move toolkit mock registration into vitest.setup.ts via vi.mock and drop the alias from vitest.config.ts. F7: dependency array already complete (no eslint-disable).
* fix(modes): address PR review on per-mode MCP allowlist (backend)
- Filter MCP servers passed to the capabilities section so disallowed servers are not described in the system prompt (review: getCapabilitiesSection)
- Hoist allow-list Set construction out of the server .filter() in system.ts
- Add invocation-time MCP server guard (use_mcp_tool / access_mcp_resource) rejecting calls to servers not in the mode's allowedMcpServers, as a second defense layer beyond tool listing/filtering
- Add unit tests for the invocation-time guard (mcpServerRestriction.spec.ts)
* fix(tests): repair sections.spec MCP mock for getServers-based capability check
getCapabilitiesSection now calls mcpHub.getServers() to honor the per-mode allowedMcpServers allowlist, so the prior empty {} as McpHub mock threw 'TypeError: mcpHub.getServers is not a function' in CI. Provide a proper getServers stub (matching the existing repo mock pattern) and add coverage for the new allowlist filtering paths.
* fix(schema): add allowedMcpServers description to Zod schema and regenerate roomodes.json
---------
Co-authored-by: Bertan Ari <bertanari@microsoft.com>1 parent 12ea787 commit a6811d3
23 files changed
Lines changed: 1656 additions & 51 deletions
File tree
- packages/types/src
- __tests__
- schemas
- src/core
- prompts
- __tests__
- sections
- tools
- __tests__
- native-tools
- __tests__
- task
- tools
- __tests__
- webview-ui
- src
- __mocks__/@vscode/webview-ui-toolkit
- components/modes
- __tests__
Lines changed: 56 additions & 0 deletions
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
| 1 | + | |
| 2 | + | |
| 3 | + | |
| 4 | + | |
| 5 | + | |
| 6 | + | |
| 7 | + | |
| 8 | + | |
| 9 | + | |
| 10 | + | |
| 11 | + | |
| 12 | + | |
| 13 | + | |
| 14 | + | |
| 15 | + | |
| 16 | + | |
| 17 | + | |
| 18 | + | |
| 19 | + | |
| 20 | + | |
| 21 | + | |
| 22 | + | |
| 23 | + | |
| 24 | + | |
| 25 | + | |
| 26 | + | |
| 27 | + | |
| 28 | + | |
| 29 | + | |
| 30 | + | |
| 31 | + | |
| 32 | + | |
| 33 | + | |
| 34 | + | |
| 35 | + | |
| 36 | + | |
| 37 | + | |
| 38 | + | |
| 39 | + | |
| 40 | + | |
| 41 | + | |
| 42 | + | |
| 43 | + | |
| 44 | + | |
| 45 | + | |
| 46 | + | |
| 47 | + | |
| 48 | + | |
| 49 | + | |
| 50 | + | |
| 51 | + | |
| 52 | + | |
| 53 | + | |
| 54 | + | |
| 55 | + | |
| 56 | + | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
102 | 102 | | |
103 | 103 | | |
104 | 104 | | |
| 105 | + | |
| 106 | + | |
| 107 | + | |
| 108 | + | |
| 109 | + | |
| 110 | + | |
105 | 111 | | |
106 | 112 | | |
107 | 113 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
31 | 31 | | |
32 | 32 | | |
33 | 33 | | |
| 34 | + | |
| 35 | + | |
| 36 | + | |
| 37 | + | |
| 38 | + | |
| 39 | + | |
| 40 | + | |
34 | 41 | | |
35 | 42 | | |
36 | 43 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
43 | 43 | | |
44 | 44 | | |
45 | 45 | | |
46 | | - | |
47 | | - | |
| 46 | + | |
| 47 | + | |
| 48 | + | |
| 49 | + | |
| 50 | + | |
| 51 | + | |
| 52 | + | |
48 | 53 | | |
49 | 54 | | |
50 | 55 | | |
| |||
55 | 60 | | |
56 | 61 | | |
57 | 62 | | |
| 63 | + | |
| 64 | + | |
| 65 | + | |
| 66 | + | |
| 67 | + | |
| 68 | + | |
| 69 | + | |
| 70 | + | |
| 71 | + | |
| 72 | + | |
| 73 | + | |
| 74 | + | |
| 75 | + | |
| 76 | + | |
| 77 | + | |
| 78 | + | |
| 79 | + | |
| 80 | + | |
| 81 | + | |
| 82 | + | |
| 83 | + | |
| 84 | + | |
| 85 | + | |
| 86 | + | |
| 87 | + | |
| 88 | + | |
| 89 | + | |
| 90 | + | |
58 | 91 | | |
59 | 92 | | |
60 | 93 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
571 | 571 | | |
572 | 572 | | |
573 | 573 | | |
| 574 | + | |
| 575 | + | |
| 576 | + | |
| 577 | + | |
| 578 | + | |
| 579 | + | |
| 580 | + | |
| 581 | + | |
| 582 | + | |
| 583 | + | |
| 584 | + | |
| 585 | + | |
| 586 | + | |
| 587 | + | |
| 588 | + | |
| 589 | + | |
| 590 | + | |
| 591 | + | |
| 592 | + | |
| 593 | + | |
| 594 | + | |
| 595 | + | |
| 596 | + | |
| 597 | + | |
| 598 | + | |
| 599 | + | |
| 600 | + | |
| 601 | + | |
| 602 | + | |
| 603 | + | |
| 604 | + | |
| 605 | + | |
| 606 | + | |
| 607 | + | |
| 608 | + | |
| 609 | + | |
| 610 | + | |
| 611 | + | |
| 612 | + | |
| 613 | + | |
| 614 | + | |
| 615 | + | |
| 616 | + | |
| 617 | + | |
| 618 | + | |
| 619 | + | |
| 620 | + | |
| 621 | + | |
| 622 | + | |
| 623 | + | |
| 624 | + | |
| 625 | + | |
| 626 | + | |
| 627 | + | |
| 628 | + | |
| 629 | + | |
| 630 | + | |
| 631 | + | |
| 632 | + | |
| 633 | + | |
| 634 | + | |
| 635 | + | |
| 636 | + | |
| 637 | + | |
574 | 638 | | |
575 | 639 | | |
576 | 640 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
1 | 1 | | |
2 | 2 | | |
3 | | - | |
| 3 | + | |
| 4 | + | |
| 5 | + | |
| 6 | + | |
| 7 | + | |
| 8 | + | |
| 9 | + | |
| 10 | + | |
| 11 | + | |
| 12 | + | |
| 13 | + | |
| 14 | + | |
| 15 | + | |
| 16 | + | |
| 17 | + | |
| 18 | + | |
| 19 | + | |
| 20 | + | |
| 21 | + | |
| 22 | + | |
| 23 | + | |
| 24 | + | |
| 25 | + | |
| 26 | + | |
| 27 | + | |
| 28 | + | |
| 29 | + | |
| 30 | + | |
| 31 | + | |
| 32 | + | |
4 | 33 | | |
5 | 34 | | |
6 | 35 | | |
7 | 36 | | |
8 | 37 | | |
9 | 38 | | |
10 | 39 | | |
11 | | - | |
| 40 | + | |
12 | 41 | | |
13 | 42 | | |
14 | 43 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
66 | 66 | | |
67 | 67 | | |
68 | 68 | | |
69 | | - | |
| 69 | + | |
| 70 | + | |
| 71 | + | |
| 72 | + | |
| 73 | + | |
| 74 | + | |
| 75 | + | |
| 76 | + | |
| 77 | + | |
| 78 | + | |
| 79 | + | |
70 | 80 | | |
71 | 81 | | |
72 | 82 | | |
| |||
90 | 100 | | |
91 | 101 | | |
92 | 102 | | |
93 | | - | |
| 103 | + | |
| 104 | + | |
| 105 | + | |
| 106 | + | |
| 107 | + | |
| 108 | + | |
| 109 | + | |
| 110 | + | |
| 111 | + | |
94 | 112 | | |
95 | 113 | | |
96 | 114 | | |
| |||
0 commit comments