Skip to content

Commit a6256cd

Browse files
fix(patch): cherry-pick 931e668 to release/v0.33.0-preview.4-pr-21425 [CONFLICTS] (#21478)
Co-authored-by: Abhi <43648792+abhipatel12@users.noreply.github.com> Co-authored-by: Abhi <abhipatel@google.com>
1 parent c316fc6 commit a6256cd

20 files changed

Lines changed: 691 additions & 501 deletions

.github/workflows/ci.yml

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -124,7 +124,9 @@ jobs:
124124
- name: 'Link Checker'
125125
uses: 'lycheeverse/lychee-action@885c65f3dc543b57c898c8099f4e08c8afd178a2' # ratchet: lycheeverse/lychee-action@v2.6.1
126126
with:
127-
args: '--verbose --accept 200,503 ./**/*.md'
127+
# Exclude GEMINI.md because the absolute GitHub URL in CONTRIBUTING.md (which is symlinked)
128+
# causes intermittent 429 Too Many Requests errors from GitHub API rate limits.
129+
args: '--verbose --accept 200,503 --exclude "GEMINI\\.md" ./**/*.md'
128130
fail: true
129131
test_linux:
130132
name: 'Test (Linux) - ${{ matrix.node-version }}, ${{ matrix.shard }}'

.github/workflows/links.yml

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,4 +22,6 @@ jobs:
2222
id: 'lychee'
2323
uses: 'lycheeverse/lychee-action@885c65f3dc543b57c898c8099f4e08c8afd178a2' # ratchet: lycheeverse/lychee-action@v2.6.1
2424
with:
25-
args: '--verbose --no-progress --accept 200,503 ./**/*.md'
25+
# Exclude GEMINI.md because the absolute GitHub URL in CONTRIBUTING.md (which is symlinked)
26+
# causes intermittent 429 Too Many Requests errors from GitHub API rate limits.
27+
args: '--verbose --no-progress --accept 200,503 --exclude "GEMINI\\.md" ./**/*.md'

integration-tests/extensions-reload.test.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -104,7 +104,7 @@ describe('extension reloading', () => {
104104
return (
105105
output.includes(
106106
'test-server (from test-extension) - Ready (1 tool)',
107-
) && output.includes('- hello')
107+
) && output.includes('- mcp_test-server_hello')
108108
);
109109
},
110110
30000, // 30s timeout
@@ -148,7 +148,7 @@ describe('extension reloading', () => {
148148
return (
149149
output.includes(
150150
'test-server (from test-extension) - Ready (1 tool)',
151-
) && output.includes('- goodbye')
151+
) && output.includes('- mcp_test-server_goodbye')
152152
);
153153
},
154154
30000,

packages/cli/src/config/policy-engine.integration.test.ts

Lines changed: 42 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -89,45 +89,45 @@ describe('Policy Engine Integration Tests', () => {
8989
// Tools from allowed server should be allowed
9090
// Tools from allowed server should be allowed
9191
expect(
92-
(await engine.check({ name: 'allowed-server__tool1' }, undefined))
92+
(await engine.check({ name: 'mcp_allowed-server_tool1' }, undefined))
9393
.decision,
9494
).toBe(PolicyDecision.ALLOW);
9595
expect(
9696
(
9797
await engine.check(
98-
{ name: 'allowed-server__another_tool' },
98+
{ name: 'mcp_allowed-server_another_tool' },
9999
undefined,
100100
)
101101
).decision,
102102
).toBe(PolicyDecision.ALLOW);
103103

104104
// Tools from trusted server should be allowed
105105
expect(
106-
(await engine.check({ name: 'trusted-server__tool1' }, undefined))
106+
(await engine.check({ name: 'mcp_trusted-server_tool1' }, undefined))
107107
.decision,
108108
).toBe(PolicyDecision.ALLOW);
109109
expect(
110110
(
111111
await engine.check(
112-
{ name: 'trusted-server__special_tool' },
112+
{ name: 'mcp_trusted-server_special_tool' },
113113
undefined,
114114
)
115115
).decision,
116116
).toBe(PolicyDecision.ALLOW);
117117

118118
// Tools from blocked server should be denied
119119
expect(
120-
(await engine.check({ name: 'blocked-server__tool1' }, undefined))
120+
(await engine.check({ name: 'mcp_blocked-server_tool1' }, undefined))
121121
.decision,
122122
).toBe(PolicyDecision.DENY);
123123
expect(
124-
(await engine.check({ name: 'blocked-server__any_tool' }, undefined))
124+
(await engine.check({ name: 'mcp_blocked-server_any_tool' }, undefined))
125125
.decision,
126126
).toBe(PolicyDecision.DENY);
127127

128128
// Tools from unknown servers should use default
129129
expect(
130-
(await engine.check({ name: 'unknown-server__tool' }, undefined))
130+
(await engine.check({ name: 'mcp_unknown-server_tool' }, undefined))
131131
.decision,
132132
).toBe(PolicyDecision.ASK_USER);
133133
});
@@ -147,12 +147,16 @@ describe('Policy Engine Integration Tests', () => {
147147

148148
// ANY tool with a server name should be allowed
149149
expect(
150-
(await engine.check({ name: 'mcp-server__tool' }, 'mcp-server'))
150+
(await engine.check({ name: 'mcp_mcp-server_tool' }, 'mcp-server'))
151151
.decision,
152152
).toBe(PolicyDecision.ALLOW);
153153
expect(
154-
(await engine.check({ name: 'another-server__tool' }, 'another-server'))
155-
.decision,
154+
(
155+
await engine.check(
156+
{ name: 'mcp_another-server_tool' },
157+
'another-server',
158+
)
159+
).decision,
156160
).toBe(PolicyDecision.ALLOW);
157161

158162
// Built-in tools should NOT be allowed by the MCP wildcard
@@ -167,7 +171,7 @@ describe('Policy Engine Integration Tests', () => {
167171
allowed: ['my-server'],
168172
},
169173
tools: {
170-
exclude: ['my-server__dangerous-tool'],
174+
exclude: ['mcp_my-server_dangerous-tool'],
171175
},
172176
};
173177

@@ -180,20 +184,24 @@ describe('Policy Engine Integration Tests', () => {
180184
// MCP server allowed (priority 4.1) provides general allow for server
181185
// MCP server allowed (priority 4.1) provides general allow for server
182186
expect(
183-
(await engine.check({ name: 'my-server__safe-tool' }, undefined))
187+
(await engine.check({ name: 'mcp_my-server_safe-tool' }, undefined))
184188
.decision,
185189
).toBe(PolicyDecision.ALLOW);
186190
// But specific tool exclude (priority 4.4) wins over server allow
187191
expect(
188-
(await engine.check({ name: 'my-server__dangerous-tool' }, undefined))
189-
.decision,
192+
(
193+
await engine.check(
194+
{ name: 'mcp_my-server_dangerous-tool' },
195+
undefined,
196+
)
197+
).decision,
190198
).toBe(PolicyDecision.DENY);
191199
});
192200

193201
it('should handle complex mixed configurations', async () => {
194202
const settings: Settings = {
195203
tools: {
196-
allowed: ['custom-tool', 'my-server__special-tool'],
204+
allowed: ['custom-tool', 'mcp_my-server_special-tool'],
197205
exclude: ['glob', 'dangerous-tool'],
198206
},
199207
mcp: {
@@ -238,21 +246,21 @@ describe('Policy Engine Integration Tests', () => {
238246
(await engine.check({ name: 'custom-tool' }, undefined)).decision,
239247
).toBe(PolicyDecision.ALLOW);
240248
expect(
241-
(await engine.check({ name: 'my-server__special-tool' }, undefined))
249+
(await engine.check({ name: 'mcp_my-server_special-tool' }, undefined))
242250
.decision,
243251
).toBe(PolicyDecision.ALLOW);
244252

245253
// MCP server tools
246254
expect(
247-
(await engine.check({ name: 'allowed-server__tool' }, undefined))
255+
(await engine.check({ name: 'mcp_allowed-server_tool' }, undefined))
248256
.decision,
249257
).toBe(PolicyDecision.ALLOW);
250258
expect(
251-
(await engine.check({ name: 'trusted-server__tool' }, undefined))
259+
(await engine.check({ name: 'mcp_trusted-server_tool' }, undefined))
252260
.decision,
253261
).toBe(PolicyDecision.ALLOW);
254262
expect(
255-
(await engine.check({ name: 'blocked-server__tool' }, undefined))
263+
(await engine.check({ name: 'mcp_blocked-server_tool' }, undefined))
256264
.decision,
257265
).toBe(PolicyDecision.DENY);
258266

@@ -479,7 +487,7 @@ describe('Policy Engine Integration Tests', () => {
479487
expect(blockedToolRule?.priority).toBe(4.4); // Command line exclude
480488

481489
const blockedServerRule = rules.find(
482-
(r) => r.toolName === 'blocked-server__*',
490+
(r) => r.toolName === 'mcp_blocked-server_*',
483491
);
484492
expect(blockedServerRule?.priority).toBe(4.9); // MCP server exclude
485493

@@ -489,11 +497,13 @@ describe('Policy Engine Integration Tests', () => {
489497
expect(specificToolRule?.priority).toBe(4.3); // Command line allow
490498

491499
const trustedServerRule = rules.find(
492-
(r) => r.toolName === 'trusted-server__*',
500+
(r) => r.toolName === 'mcp_trusted-server_*',
493501
);
494502
expect(trustedServerRule?.priority).toBe(4.2); // MCP trusted server
495503

496-
const mcpServerRule = rules.find((r) => r.toolName === 'mcp-server__*');
504+
const mcpServerRule = rules.find(
505+
(r) => r.toolName === 'mcp_mcp-server_*',
506+
);
497507
expect(mcpServerRule?.priority).toBe(4.1); // MCP allowed server
498508

499509
const readOnlyToolRule = rules.find((r) => r.toolName === 'glob');
@@ -505,18 +515,19 @@ describe('Policy Engine Integration Tests', () => {
505515
(await engine.check({ name: 'blocked-tool' }, undefined)).decision,
506516
).toBe(PolicyDecision.DENY);
507517
expect(
508-
(await engine.check({ name: 'blocked-server__any' }, undefined))
518+
(await engine.check({ name: 'mcp_blocked-server_any' }, undefined))
509519
.decision,
510520
).toBe(PolicyDecision.DENY);
511521
expect(
512522
(await engine.check({ name: 'specific-tool' }, undefined)).decision,
513523
).toBe(PolicyDecision.ALLOW);
514524
expect(
515-
(await engine.check({ name: 'trusted-server__any' }, undefined))
525+
(await engine.check({ name: 'mcp_trusted-server_any' }, undefined))
516526
.decision,
517527
).toBe(PolicyDecision.ALLOW);
518528
expect(
519-
(await engine.check({ name: 'mcp-server__any' }, undefined)).decision,
529+
(await engine.check({ name: 'mcp_mcp-server_any' }, undefined))
530+
.decision,
520531
).toBe(PolicyDecision.ALLOW);
521532
expect((await engine.check({ name: 'glob' }, undefined)).decision).toBe(
522533
PolicyDecision.ALLOW,
@@ -545,7 +556,7 @@ describe('Policy Engine Integration Tests', () => {
545556

546557
// Exclusion (195) should win over trust (90)
547558
expect(
548-
(await engine.check({ name: 'conflicted-server__tool' }, undefined))
559+
(await engine.check({ name: 'mcp_conflicted-server_tool' }, undefined))
549560
.decision,
550561
).toBe(PolicyDecision.DENY);
551562
});
@@ -556,7 +567,7 @@ describe('Policy Engine Integration Tests', () => {
556567
excluded: ['my-server'], // Priority 195 - DENY
557568
},
558569
tools: {
559-
allowed: ['my-server__special-tool'], // Priority 100 - ALLOW
570+
allowed: ['mcp_my-server_special-tool'], // Priority 100 - ALLOW
560571
},
561572
};
562573

@@ -569,11 +580,11 @@ describe('Policy Engine Integration Tests', () => {
569580
// Server exclusion (195) wins over specific tool allow (100)
570581
// This might be counterintuitive but follows the priority system
571582
expect(
572-
(await engine.check({ name: 'my-server__special-tool' }, undefined))
583+
(await engine.check({ name: 'mcp_my-server_special-tool' }, undefined))
573584
.decision,
574585
).toBe(PolicyDecision.DENY);
575586
expect(
576-
(await engine.check({ name: 'my-server__other-tool' }, undefined))
587+
(await engine.check({ name: 'mcp_my-server_other-tool' }, undefined))
577588
.decision,
578589
).toBe(PolicyDecision.DENY);
579590
});
@@ -643,13 +654,13 @@ describe('Policy Engine Integration Tests', () => {
643654
const tool3Rule = rules.find((r) => r.toolName === 'tool3');
644655
expect(tool3Rule?.priority).toBe(4.4); // Excluded tools (user tier)
645656

646-
const server2Rule = rules.find((r) => r.toolName === 'server2__*');
657+
const server2Rule = rules.find((r) => r.toolName === 'mcp_server2_*');
647658
expect(server2Rule?.priority).toBe(4.9); // Excluded servers (user tier)
648659

649660
const tool1Rule = rules.find((r) => r.toolName === 'tool1');
650661
expect(tool1Rule?.priority).toBe(4.3); // Allowed tools (user tier)
651662

652-
const server1Rule = rules.find((r) => r.toolName === 'server1__*');
663+
const server1Rule = rules.find((r) => r.toolName === 'mcp_server1_*');
653664
expect(server1Rule?.priority).toBe(4.1); // Allowed servers (user tier)
654665

655666
const globRule = rules.find((r) => r.toolName === 'glob');

packages/core/src/agents/local-executor.test.ts

Lines changed: 2 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -17,10 +17,7 @@ import { debugLogger } from '../utils/debugLogger.js';
1717
import { LocalAgentExecutor, type ActivityCallback } from './local-executor.js';
1818
import { makeFakeConfig } from '../test-utils/config.js';
1919
import { ToolRegistry } from '../tools/tool-registry.js';
20-
import {
21-
DiscoveredMCPTool,
22-
MCP_QUALIFIED_NAME_SEPARATOR,
23-
} from '../tools/mcp-tool.js';
20+
import { DiscoveredMCPTool } from '../tools/mcp-tool.js';
2421
import { LSTool } from '../tools/ls.js';
2522
import { LS_TOOL_NAME, READ_FILE_TOOL_NAME } from '../tools/tool-names.js';
2623
import {
@@ -504,7 +501,7 @@ describe('LocalAgentExecutor', () => {
504501
it('should automatically qualify MCP tools in agent definitions', async () => {
505502
const serverName = 'mcp-server';
506503
const toolName = 'mcp-tool';
507-
const qualifiedName = `${serverName}${MCP_QUALIFIED_NAME_SEPARATOR}${toolName}`;
504+
const qualifiedName = `mcp_${serverName}_${toolName}`;
508505

509506
const mockMcpTool = {
510507
tool: vi.fn(),

packages/core/src/core/__snapshots__/prompts.test.ts.snap

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -103,7 +103,7 @@ The following tools are available in Plan Mode:
103103
<tool>\`exit_plan_mode\`</tool>
104104
<tool>\`write_file\`</tool>
105105
<tool>\`replace\`</tool>
106-
<tool>\`read_data\` (readonly-server)</tool>
106+
<tool>\`mcp_readonly-server_read_data\` (readonly-server)</tool>
107107
</available_tools>
108108
109109
## Rules
@@ -271,7 +271,7 @@ The following tools are available in Plan Mode:
271271
<tool>\`exit_plan_mode\`</tool>
272272
<tool>\`write_file\`</tool>
273273
<tool>\`replace\`</tool>
274-
<tool>\`read_data\` (readonly-server)</tool>
274+
<tool>\`mcp_readonly-server_read_data\` (readonly-server)</tool>
275275
</available_tools>
276276
277277
## Rules
@@ -558,7 +558,7 @@ The following tools are available in Plan Mode:
558558
<tool>\`exit_plan_mode\`</tool>
559559
<tool>\`write_file\`</tool>
560560
<tool>\`replace\`</tool>
561-
<tool>\`read_data\` (readonly-server)</tool>
561+
<tool>\`mcp_readonly-server_read_data\` (readonly-server)</tool>
562562
</available_tools>
563563
564564
## Rules

packages/core/src/core/loggingContentGenerator.test.ts

Lines changed: 9 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -709,7 +709,7 @@ describe('estimateContextBreakdown', () => {
709709
{
710710
functionDeclarations: [
711711
{
712-
name: 'myserver__search',
712+
name: 'mcp_myserver_search',
713713
description: 'Search via MCP',
714714
parameters: {},
715715
},
@@ -747,8 +747,7 @@ describe('estimateContextBreakdown', () => {
747747
expect(builtinOnly.mcp_servers).toBe(0);
748748
});
749749

750-
it('should not classify tools with __ in the middle of a segment as MCP', () => {
751-
// "__" at start or end (not a valid server__tool pattern) should not be MCP
750+
it('should not classify tools without mcp_ prefix as MCP', () => {
752751
const config = {
753752
tools: [
754753
{
@@ -842,7 +841,7 @@ describe('estimateContextBreakdown', () => {
842841
functionDeclarations: [
843842
{ name: 'read_file', description: 'Read', parameters: {} },
844843
{
845-
name: 'myserver__search',
844+
name: 'mcp_myserver_search',
846845
description: 'MCP search',
847846
parameters: {},
848847
},
@@ -858,7 +857,7 @@ describe('estimateContextBreakdown', () => {
858857
expect(result.history).toBeGreaterThan(0);
859858
// tool_calls should only contain non-MCP tools
860859
expect(result.tool_calls['read_file']).toBeGreaterThan(0);
861-
expect(result.tool_calls['myserver__search']).toBeUndefined();
860+
expect(result.tool_calls['mcp_myserver_search']).toBeUndefined();
862861
// MCP tokens are only in mcp_servers
863862
expect(result.mcp_servers).toBeGreaterThan(0);
864863
});
@@ -870,7 +869,7 @@ describe('estimateContextBreakdown', () => {
870869
parts: [
871870
{
872871
functionCall: {
873-
name: 'myserver__search',
872+
name: 'mcp_myserver_search',
874873
args: { query: 'test' },
875874
},
876875
},
@@ -881,7 +880,7 @@ describe('estimateContextBreakdown', () => {
881880
parts: [
882881
{
883882
functionResponse: {
884-
name: 'myserver__search',
883+
name: 'mcp_myserver_search',
885884
response: { results: [] },
886885
},
887886
},
@@ -890,7 +889,7 @@ describe('estimateContextBreakdown', () => {
890889
];
891890
const result = estimateContextBreakdown(contents);
892891
// MCP tool calls should NOT appear in tool_calls
893-
expect(result.tool_calls['myserver__search']).toBeUndefined();
892+
expect(result.tool_calls['mcp_myserver_search']).toBeUndefined();
894893
// MCP call tokens should only be counted in mcp_servers
895894
expect(result.mcp_servers).toBeGreaterThan(0);
896895
});
@@ -908,7 +907,7 @@ describe('estimateContextBreakdown', () => {
908907
},
909908
{
910909
functionCall: {
911-
name: 'myserver__search',
910+
name: 'mcp_myserver_search',
912911
args: { q: 'hello' },
913912
},
914913
},
@@ -919,7 +918,7 @@ describe('estimateContextBreakdown', () => {
919918
// Non-MCP tools should be in tool_calls
920919
expect(result.tool_calls['read_file']).toBeGreaterThan(0);
921920
// MCP tools should NOT be in tool_calls
922-
expect(result.tool_calls['myserver__search']).toBeUndefined();
921+
expect(result.tool_calls['mcp_myserver_search']).toBeUndefined();
923922
// MCP tool calls should only be in mcp_servers
924923
expect(result.mcp_servers).toBeGreaterThan(0);
925924
});

0 commit comments

Comments
 (0)