Repository navigation
v3.0.0
The default MCP tool listing went from 49 tools to 7 (37,346 bytes to 5,072, -86.4%; about 9,336 tokens to about 1,268). With CDP_TOOL_PROFILE unset, tools/list now advertises search_tools, call_tool and five core tools (navigate_page, evaluate_script, take_snapshot, click, fill); every other tool is found with search_tools and run with call_tool. CDP_TOOL_PROFILE=full restores the 2.x listing (plus the two meta-tools). The 48 underlying tools and the cdp CLI are unchanged, and the listing is still static: computed once at startup, listChanged:false, same cache hints.
Changed — BREAKING
- The default profile is now
gateway, notfull. Measuredtools/list(raw stdio, compact JSON, tokens = bytes/4): 2.7.0 default 49 entries / 37,346 bytes / about 9,336 tokens; 3.0 default 7 entries / 5,072 bytes / about 1,268 tokens (identical on Chrome and Firefox).CDP_TOOL_PROFILE=fullis now 50 entries / 37,911 bytes on Chrome (the 2.7.0 listing plus the two meta-tools). describe_toolis no longer listed, but is still answered with 2.x output for back-compat;describe_tool {}returns the same catalog assearch_tools {}.- What is traded away. A tool reached through
call_toolappears to the host ascall_tool, so name-keyed host allowlists and per-tool permission prompts (for example "allow click, deny evaluate_script") cannot distinguish the 43 non-gateway tools; setCDP_TOOL_PROFILE=fullif you need per-tool host rules. Drop-in parity with chrome-devtools-mcp's listing is also gone by default: its 29 tool names still exist and are callable with the same names, but only 5 are listed unless you setfull. - Direct calls to unlisted tools by name still work over the wire (SDK and CLI consumers are unaffected).
call_toolexists because a model can only invoke tools its host puts in front of it, and hosts forwardtools/list. - This does not repeat 2.0's
browser_toolsdesign, which mutated the listing mid-connection (a spec MUST-NOT); the 3.0 listing never changes. Seedocs/design/2026-09-29-v3-gateway-default.md.
Added
-
search_tools {query?, limit?}. No query returns the grouped catalog; a query that is an exact tool name returns that one tool; anything else ranks available tools by name (strongest), group, then full docs, returning JSON{query,total,matches:[{name,group,listed,description,inputSchema}],next}.limitdefaults to 8, max 20. (src/mcp.ts) -
call_tool {name, arguments?}. Unwraps and re-enters the same dispatch as a direct call, so availability errors, lease handling (theleaseis read from the innerarguments) and error shapes are identical. Refuses to wrap a meta-tool. Verified live on headless Chrome 154 (bun run gateway:smoke):new_pageviacall_tool {claim:true}mints a lease,navigate_pagewithout it is refused naming the lease holder, with it succeeds, andclose_pagereleases it. (src/mcp.ts) -
The
gatewayprofile andgateway,<groups>lists.gatewayis the default;gateway,network,consoleadds only the named groups on top of the five gateway tools (11 entries, 7,899 bytes, about 1,975 tokens). A group list withoutgatewaystill always includescore, as in 2.x (core: 14 entries, 9,661 bytes;core,network,console: 18 entries, 12,488 bytes). Every profile listssearch_toolsandcall_toolfirst. Unknown groups exit at startup withCDP_TOOL_PROFILE: unknown tool group 'x'. Known: gateway, full, core, input, .... (src/toolGroups.ts) -
The server instructions (1,862 chars, under Claude Code's 2 KB cap) now tell the model that only 5 tools are listed, how to find and run the rest, and "No tab yet? call_tool {name:'new_page'}", since none of the five opens a tab.
-
Wedge benchmark (
bun run bench:wedge). A runnable, CI-able proof of the core claim: an isolated headless Chrome drives a throwaway page into an endpoint that accepts the connection and never responds, 8 times, and measures the whole stuck-page lifecycle — the wedgednavigaterejects at the configured bound (15.03s observed against the default 15s bound), a witness tab keeps answering at healthy latency mid-brick (p95 3ms), and closing the bricked tab plus reopening evaluates at p95 89ms with zero/mcprestarts. Also reports, as an observation rather than a failure, that the stuck page itself stays unresponsive while its load is pending: the blast radius is the tab, not the server. (scripts/wedge-bench.ts)
Migrating from 2.x
- Do nothing if your host and model can use
search_toolspluscall_tool. - Set
CDP_TOOL_PROFILE=fullif you rely on per-tool host allowlists or permission rules, or simply want the old listing. - SDK and CLI callers that call tools by name are unaffected.