@@ -13,10 +13,43 @@ import {
1313 afterEach ,
1414 type Mock ,
1515} from 'vitest' ;
16+
17+ const {
18+ mockSendMessageStream,
19+ mockScheduleAgentTools,
20+ mockSetSystemInstruction,
21+ mockCompress,
22+ mockMaybeDiscoverMcpServer,
23+ mockStopMcp,
24+ } = vi . hoisted ( ( ) => ( {
25+ mockSendMessageStream : vi . fn ( ) . mockResolvedValue ( {
26+ async * [ Symbol . asyncIterator ] ( ) {
27+ yield {
28+ type : 'chunk' ,
29+ value : { candidates : [ ] } ,
30+ } ;
31+ } ,
32+ } ) ,
33+ mockScheduleAgentTools : vi . fn ( ) ,
34+ mockSetSystemInstruction : vi . fn ( ) ,
35+ mockCompress : vi . fn ( ) ,
36+ mockMaybeDiscoverMcpServer : vi . fn ( ) . mockResolvedValue ( undefined ) ,
37+ mockStopMcp : vi . fn ( ) . mockResolvedValue ( undefined ) ,
38+ } ) ) ;
39+
40+ vi . mock ( '../tools/mcp-client-manager.js' , ( ) => ( {
41+ McpClientManager : class {
42+ maybeDiscoverMcpServer = mockMaybeDiscoverMcpServer ;
43+ stop = mockStopMcp ;
44+ } ,
45+ } ) ) ;
46+
1647import { debugLogger } from '../utils/debugLogger.js' ;
1748import { LocalAgentExecutor , type ActivityCallback } from './local-executor.js' ;
1849import { makeFakeConfig } from '../test-utils/config.js' ;
1950import { ToolRegistry } from '../tools/tool-registry.js' ;
51+ import { PromptRegistry } from '../prompts/prompt-registry.js' ;
52+ import { ResourceRegistry } from '../resources/resource-registry.js' ;
2053import { DiscoveredMCPTool } from '../tools/mcp-tool.js' ;
2154import { LSTool } from '../tools/ls.js' ;
2255import { LS_TOOL_NAME , READ_FILE_TOOL_NAME } from '../tools/tool-names.js' ;
@@ -70,18 +103,6 @@ import type {
70103import { getModelConfigAlias , type AgentRegistry } from './registry.js' ;
71104import type { ModelRouterService } from '../routing/modelRouterService.js' ;
72105
73- const {
74- mockSendMessageStream,
75- mockScheduleAgentTools,
76- mockSetSystemInstruction,
77- mockCompress,
78- } = vi . hoisted ( ( ) => ( {
79- mockSendMessageStream : vi . fn ( ) ,
80- mockScheduleAgentTools : vi . fn ( ) ,
81- mockSetSystemInstruction : vi . fn ( ) ,
82- mockCompress : vi . fn ( ) ,
83- } ) ) ;
84-
85106let mockChatHistory : Content [ ] = [ ] ;
86107const mockSetHistory = vi . fn ( ( newHistory : Content [ ] ) => {
87108 mockChatHistory = newHistory ;
@@ -2722,6 +2743,67 @@ describe('LocalAgentExecutor', () => {
27222743 } ) ;
27232744 } ) ;
27242745
2746+ describe ( 'MCP Isolation' , ( ) => {
2747+ it ( 'should initialize McpClientManager when mcpServers are defined' , async ( ) => {
2748+ const { MCPServerConfig } = await import ( '../config/config.js' ) ;
2749+ const mcpServers = {
2750+ 'test-server' : new MCPServerConfig ( 'node' , [ 'server.js' ] ) ,
2751+ } ;
2752+
2753+ const definition = {
2754+ ...createTestDefinition ( ) ,
2755+ mcpServers,
2756+ } ;
2757+
2758+ vi . spyOn ( mockConfig , 'getMcpClientManager' ) . mockReturnValue ( {
2759+ maybeDiscoverMcpServer : mockMaybeDiscoverMcpServer ,
2760+ } as unknown as ReturnType < typeof mockConfig . getMcpClientManager > ) ;
2761+
2762+ await LocalAgentExecutor . create ( definition , mockConfig ) ;
2763+
2764+ const mcpManager = mockConfig . getMcpClientManager ( ) ;
2765+ expect ( mcpManager ?. maybeDiscoverMcpServer ) . toHaveBeenCalledWith (
2766+ 'test-server' ,
2767+ mcpServers [ 'test-server' ] ,
2768+ expect . objectContaining ( {
2769+ toolRegistry : expect . any ( ToolRegistry ) ,
2770+ promptRegistry : expect . any ( PromptRegistry ) ,
2771+ resourceRegistry : expect . any ( ResourceRegistry ) ,
2772+ } ) ,
2773+ ) ;
2774+ } ) ;
2775+
2776+ it ( 'should inherit main registry tools' , async ( ) => {
2777+ const parentMcpTool = new DiscoveredMCPTool (
2778+ { } as unknown as CallableTool ,
2779+ 'main-server' ,
2780+ 'tool1' ,
2781+ 'desc1' ,
2782+ { } ,
2783+ mockConfig . getMessageBus ( ) ,
2784+ ) ;
2785+
2786+ parentToolRegistry . registerTool ( parentMcpTool ) ;
2787+
2788+ const definition = createTestDefinition ( ) ;
2789+ definition . toolConfig = undefined ; // trigger inheritance
2790+
2791+ vi . spyOn ( mockConfig , 'getMcpClientManager' ) . mockReturnValue ( {
2792+ maybeDiscoverMcpServer : vi . fn ( ) ,
2793+ } as unknown as ReturnType < typeof mockConfig . getMcpClientManager > ) ;
2794+ const executor = await LocalAgentExecutor . create (
2795+ definition ,
2796+ mockConfig ,
2797+ onActivity ,
2798+ ) ;
2799+ const agentTools = (
2800+ executor as unknown as { toolRegistry : ToolRegistry }
2801+ ) . toolRegistry . getAllToolNames ( ) ;
2802+
2803+ expect ( agentTools ) . toContain ( parentMcpTool . name ) ;
2804+ } ) ;
2805+ } ) ;
2806+
27252807 describe ( 'DeclarativeTool instance tools (browser agent pattern)' , ( ) => {
27262808 /**
27272809 * The browser agent passes DeclarativeTool instances (not string names) in
@@ -2827,13 +2909,11 @@ describe('LocalAgentExecutor', () => {
28272909 const navTool = new MockTool ( { name : 'navigate_page' } ) ;
28282910
28292911 const definition = createInstanceToolDefinition ( [ clickTool , navTool ] ) ;
2830-
28312912 const executor = await LocalAgentExecutor . create (
28322913 definition ,
28332914 mockConfig ,
28342915 onActivity ,
28352916 ) ;
2836-
28372917 const registry = executor [ 'toolRegistry' ] ;
28382918 expect ( registry . getTool ( 'click' ) ) . toBeDefined ( ) ;
28392919 expect ( registry . getTool ( 'navigate_page' ) ) . toBeDefined ( ) ;
0 commit comments