diff --git a/packages/core/src/agents/browser/browserManager.test.ts b/packages/core/src/agents/browser/browserManager.test.ts index ed6c336420..28092bc06e 100644 --- a/packages/core/src/agents/browser/browserManager.test.ts +++ b/packages/core/src/agents/browser/browserManager.test.ts @@ -152,7 +152,7 @@ describe('BrowserManager', () => { }); expect(result.isError).toBe(true); - expect(result.content[0]?.text).toContain('not permitted'); + expect((result.content || [])[0]?.text).toContain('not permitted'); expect(Client).not.toHaveBeenCalled(); }); @@ -170,7 +170,7 @@ describe('BrowserManager', () => { }); expect(result.isError).toBe(false); - expect(result.content[0]?.text).toBe('Tool result'); + expect((result.content || [])[0]?.text).toBe('Tool result'); }); it('should allow navigate_page to subdomain when wildcard is used', async () => { @@ -187,7 +187,7 @@ describe('BrowserManager', () => { }); expect(result.isError).toBe(false); - expect(result.content[0]?.text).toBe('Tool result'); + expect((result.content || [])[0]?.text).toBe('Tool result'); }); it('should block new_page to disallowed domain', async () => { @@ -204,7 +204,7 @@ describe('BrowserManager', () => { }); expect(result.isError).toBe(true); - expect(result.content[0]?.text).toContain('not permitted'); + expect((result.content || [])[0]?.text).toContain('not permitted'); }); }); @@ -235,6 +235,25 @@ describe('BrowserManager', () => { expect(args[userDataDirIndex + 1]).toMatch(/cli-browser-profile$/); }); + it('should pass --host-rules when allowedDomains is configured', async () => { + const restrictedConfig = makeFakeConfig({ + agents: { + browser: { + allowedDomains: ['google.com', '*.openai.com'], + }, + }, + }); + + const manager = new BrowserManager(restrictedConfig); + await manager.ensureConnection(); + + const args = vi.mocked(StdioClientTransport).mock.calls[0]?.[0] + ?.args as string[]; + expect(args).toContain( + '--chromeArg="--host-rules=MAP * 127.0.0.1, EXCLUDE google.com, EXCLUDE *.openai.com, EXCLUDE 127.0.0.1"', + ); + }); + it('should pass headless flag when configured', async () => { const headlessConfig = makeFakeConfig({ agents: { diff --git a/packages/core/src/agents/browser/browserManager.ts b/packages/core/src/agents/browser/browserManager.ts index b9d0e6c5db..0cb3a829d7 100644 --- a/packages/core/src/agents/browser/browserManager.ts +++ b/packages/core/src/agents/browser/browserManager.ts @@ -118,7 +118,7 @@ export class BrowserManager { content: [ { type: 'text', - text: `Tool '${toolName}' is not permitted for the requested URL/domain based on your current browser settings. DO NOT attempt to call with same URL/domain`, + text: `Tool '${toolName}' is not permitted for the requested URL/domain based on your current browser settings.`, }, ], isError: true, @@ -287,6 +287,18 @@ export class BrowserManager { mcpArgs.push('--userDataDir', defaultProfilePath); } + if ( + browserConfig.customConfig.allowedDomains && + browserConfig.customConfig.allowedDomains.length > 0 + ) { + const exclusionRules = browserConfig.customConfig.allowedDomains + .map((domain) => `EXCLUDE ${domain}`) + .join(', '); + mcpArgs.push( + `--chromeArg="--host-rules=MAP * 127.0.0.1, ${exclusionRules}, EXCLUDE 127.0.0.1"`, + ); + } + debugLogger.log( `Launching chrome-devtools-mcp (${sessionMode} mode) with args: ${mcpArgs.join(' ')}`, );