| layout | default |
|---|---|
| title | Chapter 3: Client Integrations and Setup Patterns |
| nav_order | 3 |
| parent | Chrome DevTools MCP Tutorial |
Welcome to Chapter 3: Client Integrations and Setup Patterns. In this part of Chrome DevTools MCP Tutorial: Browser Automation and Debugging for Coding Agents, you will build an intuitive mental model first, then move into concrete implementation details and practical production tradeoffs.
This chapter covers integration patterns across coding clients and IDEs.
- configure client-specific MCP formats correctly
- select global vs project-scoped setup patterns
- handle browser URL and startup-time tuning
- reduce client configuration drift
- prefer latest package version for compatibility
- document one canonical config per client class
- use explicit startup timeout overrides when needed
You now have stable setup patterns for multi-client Chrome DevTools MCP usage.
Next: Chapter 4: Automation Tooling: Input and Navigation
The CapturedFunctionCall interface in scripts/eval_gemini.ts handles a key part of this chapter's functionality:
// Define schema for our test scenarios
export interface CapturedFunctionCall {
name: string;
args: Record<string, unknown>;
}
export interface TestScenario {
prompt: string;
maxTurns: number;
expectations: (calls: CapturedFunctionCall[]) => void;
htmlRoute?: {
path: string;
htmlContent: string;
};
/** Extra CLI flags passed to the MCP server (e.g. '--experimental-page-id-routing'). */
serverArgs?: string[];
}
async function loadScenario(scenarioPath: string): Promise<TestScenario> {
const module = await import(pathToFileURL(scenarioPath).href);
if (!module.scenario) {
throw new Error(
`Scenario file ${scenarioPath} does not export a 'scenario' object.`,
);
}
return module.scenario;
}
async function runSingleScenario(
scenarioPath: string,
apiKey: string,This interface is important because it defines how Chrome DevTools MCP Tutorial: Browser Automation and Debugging for Coding Agents implements the patterns covered in this chapter.
The TestScenario interface in scripts/eval_gemini.ts handles a key part of this chapter's functionality:
}
export interface TestScenario {
prompt: string;
maxTurns: number;
expectations: (calls: CapturedFunctionCall[]) => void;
htmlRoute?: {
path: string;
htmlContent: string;
};
/** Extra CLI flags passed to the MCP server (e.g. '--experimental-page-id-routing'). */
serverArgs?: string[];
}
async function loadScenario(scenarioPath: string): Promise<TestScenario> {
const module = await import(pathToFileURL(scenarioPath).href);
if (!module.scenario) {
throw new Error(
`Scenario file ${scenarioPath} does not export a 'scenario' object.`,
);
}
return module.scenario;
}
async function runSingleScenario(
scenarioPath: string,
apiKey: string,
server: TestServer,
modelId: string,
debug: boolean,
includeSkill: boolean,
): Promise<void> {This interface is important because it defines how Chrome DevTools MCP Tutorial: Browser Automation and Debugging for Coding Agents implements the patterns covered in this chapter.
The UncaughtError class in src/PageCollector.ts handles a key part of this chapter's functionality:
} from './third_party/index.js';
export class UncaughtError {
readonly details: Protocol.Runtime.ExceptionDetails;
readonly targetId: string;
constructor(details: Protocol.Runtime.ExceptionDetails, targetId: string) {
this.details = details;
this.targetId = targetId;
}
}
interface PageEvents extends PuppeteerPageEvents {
issue: DevTools.AggregatedIssue;
uncaughtError: UncaughtError;
}
export type ListenerMap<EventMap extends PageEvents = PageEvents> = {
[K in keyof EventMap]?: (event: EventMap[K]) => void;
};
function createIdGenerator() {
let i = 1;
return () => {
if (i === Number.MAX_SAFE_INTEGER) {
i = 0;
}
return i++;
};
}
export const stableIdSymbol = Symbol('stableIdSymbol');This class is important because it defines how Chrome DevTools MCP Tutorial: Browser Automation and Debugging for Coding Agents implements the patterns covered in this chapter.
The PageCollector class in src/PageCollector.ts handles a key part of this chapter's functionality:
};
export class PageCollector<T> {
#browser: Browser;
#listenersInitializer: (
collector: (item: T) => void,
) => ListenerMap<PageEvents>;
#listeners = new WeakMap<Page, ListenerMap>();
protected maxNavigationSaved = 3;
/**
* This maps a Page to a list of navigations with a sub-list
* of all collected resources.
* The newer navigations come first.
*/
protected storage = new WeakMap<Page, Array<Array<WithSymbolId<T>>>>();
constructor(
browser: Browser,
listeners: (collector: (item: T) => void) => ListenerMap<PageEvents>,
) {
this.#browser = browser;
this.#listenersInitializer = listeners;
}
async init(pages: Page[]) {
for (const page of pages) {
this.addPage(page);
}
this.#browser.on('targetcreated', this.#onTargetCreated);
this.#browser.on('targetdestroyed', this.#onTargetDestroyed);This class is important because it defines how Chrome DevTools MCP Tutorial: Browser Automation and Debugging for Coding Agents implements the patterns covered in this chapter.
flowchart TD
A[CapturedFunctionCall]
B[TestScenario]
C[UncaughtError]
D[PageCollector]
E[ConsoleCollector]
A --> B
B --> C
C --> D
D --> E