How the Target Filter Excludes Internal Chrome Pages in chrome-devtools-mcp

The makeTargetFilter function in src/browser.ts blocks all targets whose URLs start with chrome://, chrome-extension://, or chrome-untrusted://, while explicitly allowing chrome://newtab/ and chrome://inspect to ensure essential browser functionality remains accessible.

The chrome-devtools-mcp project provides a Model Context Protocol (MCP) server that enables AI assistants to interact with Chrome DevTools programmatically. To prevent internal browser pages from cluttering the target list and causing errors during automation, the codebase implements a sophisticated target filter that excludes internal Chrome URLs while preserving necessary system pages.

How the Target Filter Works

The filtering logic resides in the makeTargetFilter factory function within src/browser.ts. This function returns a closure that Puppeteer invokes for every browser target to determine whether it should be exposed to the MCP tooling.

The makeTargetFilter Implementation

The function maintains a Set of ignored URL prefixes and implements specific exceptions for required internal pages:

// src/browser.ts
function makeTargetFilter() {
  const ignoredPrefixes = new Set([
    'chrome://',
    'chrome-extension://',
    'chrome-untrusted://',
  ]);

  return function targetFilter(target: Target): boolean {
    // Always keep the New Tab page – it may be the only page opened.
    if (target.url() === 'chrome://newtab/') {
      return true;
    }

    // Keep the DevTools "Inspect" UI – required for remote-debugging.
    if (target.url().startsWith('chrome://inspect')) {
      return true;
    }

    // Block any other internal Chrome URLs.
    for (const prefix of ignoredPrefixes) {
      if (target.url().startsWith(prefix)) {
        return false;   // <-- filtered out
      }
    }

    // All other (user) pages are retained.
    return true;
  };
}

Ignored Prefixes and Exceptions

The filter applies a deny-list approach with three specific exclusions:

  • Blocked schemes: chrome://, chrome-extension://, and chrome-untrusted:// are automatically rejected to prevent MCP clients from attempting to interact with browser internals, settings, or extension backgrounds.
  • Allowed exceptions: chrome://newtab/ is preserved because it may be the only available target when Chrome launches. URLs beginning with chrome://inspect are retained to support remote debugging workflows.

Integration with Puppeteer

The target filter integrates with Puppeteer's browser lifecycle through the targetFilter configuration option. This ensures consistent filtering whether launching a new Chrome instance or connecting to an existing one.

Launching Chrome with Filtering

When the MCP server launches Chrome via the launch function in src/browser.ts, it automatically injects the filter:

const browser = await puppeteer.launch({
  // ... other options
  targetFilter: makeTargetFilter(),
});

This prevents internal pages from appearing in the browser's target list immediately upon startup.

Connecting to Existing Instances

For scenarios where the MCP attaches to a running Chrome instance via ensureBrowserConnected, the same filter applies:

const browser = await puppeteer.connect({
  browserURL: 'http://127.0.0.1:9222',
  targetFilter: makeTargetFilter(),
});

This ensures that even when connecting to long-running browser sessions with multiple internal tabs open, only user-facing web pages are exposed to the MCP tooling.

Practical Implementation Examples

The following patterns demonstrate how the target filter operates in practice.

Verifying Filtered Targets

After connecting or launching, you can verify that internal pages are excluded:

const pages = await browser.pages(); // only pages passing the filter
for (const page of pages) {
  console.log('Accessible page:', page.url());
}
// Output will never include chrome://settings, chrome-extension://*, etc.

Customizing the Filter

While the default implementation covers standard internal schemes, you can extend the logic by modifying the ignoredPrefixes Set or adding additional conditional checks within the targetFilter closure before deploying your own MCP server instance.

Summary

  • The makeTargetFilter function in src/browser.ts defines the exclusion logic for internal Chrome pages.
  • Three URL schemes are blocked by default: chrome://, chrome-extension://, and chrome-untrusted://.
  • Two critical exceptions are preserved: chrome://newtab/ and chrome://inspect URLs.
  • The filter integrates with Puppeteer via the targetFilter option in both launch and connect configurations.
  • This mechanism ensures MCP clients interact only with user-facing web content, avoiding errors from internal browser interfaces.

Frequently Asked Questions

What specific Chrome URL schemes does the target filter block?

The filter blocks three specific schemes: chrome://, chrome-extension://, and chrome-untrusted://. These prefixes cover all standard internal browser pages, extension background pages, and untrusted Chrome resources that could cause errors if accessed through the MCP tooling.

Why does the filter allow chrome://newtab and chrome://inspect?

The chrome://newtab/ page is explicitly allowed because it may be the only available target when Chrome first launches, ensuring the MCP server has at least one valid page to interact with. URLs starting with chrome://inspect are preserved because they host the DevTools remote debugging interface, which is essential for the MCP's core functionality.

How is the target filter applied when connecting to an existing Chrome instance?

When connecting to a running Chrome instance via ensureBrowserConnected in src/browser.ts, the filter is passed to puppeteer.connect through the targetFilter option. This ensures that even when attaching to long-running browser sessions with multiple internal tabs, only user-facing pages are exposed to the MCP client.

Can I modify the target filter to allow specific internal Chrome pages?

Yes, you can customize the filter by modifying the ignoredPrefixes Set or adding conditional logic within the targetFilter closure in src/browser.ts. However, exposing internal pages like chrome://settings or extension backgrounds may cause Puppeteer errors, as these pages often have restricted APIs that differ from standard web content.

Have a question about this repo?

These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:

Share the following with your agent to get started:
curl -s "https://instagit.com/install.md"

Works with
Claude Codex Cursor VS Code OpenClaw Any MCP Client

Maintain an open-source project? Get it listed too →