cdp-mcp 0.1.2 → 0.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +100 -37
- package/dist/contract.d.ts +11 -0
- package/dist/contract.js +11 -0
- package/dist/contract.js.map +1 -0
- package/dist/index.d.ts +18 -0
- package/dist/locator.d.ts +108 -0
- package/dist/locator.js +176 -0
- package/dist/locator.js.map +1 -0
- package/dist/server.d.ts +2 -0
- package/dist/server.js +4 -0
- package/dist/server.js.map +1 -1
- package/dist/session/browser.d.ts +29 -0
- package/dist/session/browser.js +17 -2
- package/dist/session/browser.js.map +1 -1
- package/dist/session/buffers.d.ts +48 -0
- package/dist/session/pause.d.ts +21 -0
- package/dist/session/state.d.ts +53 -0
- package/dist/sourcemap/loader.d.ts +4 -0
- package/dist/sourcemap/normalize.d.ts +2 -0
- package/dist/sourcemap/store.d.ts +57 -0
- package/dist/tools/_locator_runtime.d.ts +31 -0
- package/dist/tools/_locator_runtime.js +243 -0
- package/dist/tools/_locator_runtime.js.map +1 -0
- package/dist/tools/_register.d.ts +2 -0
- package/dist/tools/breakpoints.d.ts +4 -0
- package/dist/tools/console.d.ts +2 -0
- package/dist/tools/dom.d.ts +2 -0
- package/dist/tools/dom.js +3 -221
- package/dist/tools/dom.js.map +1 -1
- package/dist/tools/execution.d.ts +29 -0
- package/dist/tools/forms.d.ts +8 -0
- package/dist/tools/forms.js +256 -0
- package/dist/tools/forms.js.map +1 -0
- package/dist/tools/inspect.d.ts +2 -0
- package/dist/tools/nav.d.ts +2 -0
- package/dist/tools/network.d.ts +2 -0
- package/dist/tools/session.d.ts +2 -0
- package/dist/tools/session.js +1 -1
- package/dist/tools/session.js.map +1 -1
- package/dist/tools/source.d.ts +2 -0
- package/dist/tools/storage.d.ts +2 -0
- package/dist/tools/storage.js +296 -0
- package/dist/tools/storage.js.map +1 -0
- package/dist/util/browser-resolve.d.ts +19 -0
- package/dist/util/errors.d.ts +7 -0
- package/dist/util/format.d.ts +20 -0
- package/dist/util/log.d.ts +6 -0
- package/docs/chromium-sandboxing.md +197 -0
- package/docs/known-chromium-gaps.md +138 -0
- package/docs/launchd-service.md +217 -0
- package/docs/local-l3-e2e-setup.md +199 -0
- package/docs/systemd-service.md +233 -0
- package/package.json +18 -2
package/README.md
CHANGED
|
@@ -4,11 +4,13 @@ A Model Context Protocol (MCP) server that exposes the Chrome DevTools Protocol
|
|
|
4
4
|
|
|
5
5
|
Designed for agents running in CLIs (Claude Code, GitHub Copilot CLI) that have local source + source-map access. Coordinates flow in TS terms; the server translates to JS for CDP under the hood.
|
|
6
6
|
|
|
7
|
-
**Status:** alpha
|
|
7
|
+
**Status:** alpha. **License:** [MIT](./LICENSE).
|
|
8
|
+
|
|
9
|
+
**Last updated: 2026-06-09**
|
|
8
10
|
|
|
9
11
|
## What it gives an agent
|
|
10
12
|
|
|
11
|
-
Across
|
|
13
|
+
Across 48 tools:
|
|
12
14
|
|
|
13
15
|
- **Breakpoints in TS source** — `set_breakpoint(file="src/foo.ts", line=42, condition?, log_message?)`. The server matches source maps and binds in every script that maps back to that file.
|
|
14
16
|
- **Stepping** — `step_over`, `step_into`, `step_out`, `resume`, `pause`, plus the authoritative sync point `wait_for_pause`.
|
|
@@ -16,12 +18,42 @@ Across 39 tools:
|
|
|
16
18
|
- **Buffered console + network** — pull-based, paginated by monotonic `seq`. Bodies are lazy-loaded via `get_request_body` / `get_response_body`.
|
|
17
19
|
- **Light DOM interaction** — `query_selector`, `click`, `type_text`, `press_key`, `screenshot` so the agent can drive a flow to a breakpoint.
|
|
18
20
|
- **Structured DOM querying** — Playwright-inspired `locate` (LocatorSpec: CSS, text, role, test-id, label, placeholder, name), `wait_for` (poll until DOM state), `get_form_state` (read named form fields).
|
|
21
|
+
- **Form driving** — `fill`, `check` / `uncheck`, `select_option`, plus `suggest_locator` to get a robust semantic locator for an element.
|
|
22
|
+
- **Session portability** — `export_storage_state` / `load_storage_state` carry a logged-in session (cookies + localStorage) across runs; `get_cookies` / `set_cookies` read and set cookies directly (`get_cookies` redacts likely-auth / HttpOnly values for safe logging).
|
|
19
23
|
- **Source-map diagnostics** — `list_scripts`, `resolve_source_position`, `get_script_source`.
|
|
20
24
|
|
|
21
25
|
Auto-attaches to iframes and workers via `Target.setAutoAttach({ flatten: true })`.
|
|
22
26
|
|
|
23
27
|
## Install / build
|
|
24
28
|
|
|
29
|
+
### Runtime install from npm
|
|
30
|
+
|
|
31
|
+
Requires Node.js 20+ and a local Chrome/Chromium browser.
|
|
32
|
+
|
|
33
|
+
```sh
|
|
34
|
+
npm install -g cdp-mcp
|
|
35
|
+
cdp-mcp # stdio MCP transport
|
|
36
|
+
cdp-mcp --port 9719 # SSE MCP transport on 127.0.0.1:9719
|
|
37
|
+
cdp-mcp --host 0.0.0.0 --port 9719 --allow-remote
|
|
38
|
+
```
|
|
39
|
+
|
|
40
|
+
The npm package ships prebuilt `dist/`, so there is no build step for runtime
|
|
41
|
+
use. If `launch_chrome` cannot find Chrome/Chromium automatically, set
|
|
42
|
+
`CHROME_PATH` to the browser binary.
|
|
43
|
+
|
|
44
|
+
For MCP clients that support SSE, you can run `cdp-mcp` as a persistent local
|
|
45
|
+
service:
|
|
46
|
+
|
|
47
|
+
- [macOS launchd user service](docs/launchd-service.md)
|
|
48
|
+
- [Linux systemd user service](docs/systemd-service.md)
|
|
49
|
+
|
|
50
|
+
Persistent service mode keeps the `cdp-mcp` process and current browser/CDP
|
|
51
|
+
session alive across MCP client restarts or reconnects. It does **not** persist
|
|
52
|
+
state across service-process restarts. SSE mode is single-client today; if a
|
|
53
|
+
new client should start fresh, call `close_session` first.
|
|
54
|
+
|
|
55
|
+
### Build from source
|
|
56
|
+
|
|
25
57
|
```sh
|
|
26
58
|
npm install
|
|
27
59
|
npm run build
|
|
@@ -39,9 +71,11 @@ SSE mode caveats:
|
|
|
39
71
|
tears down client A's session).
|
|
40
72
|
- **Non-loopback bind requires opt-in.** `--allow-remote` (or
|
|
41
73
|
`CDP_MCP_ALLOW_REMOTE=1`) is required to bind to anything other than
|
|
42
|
-
loopback. MCP tools include `evaluate` (in-page code exec)
|
|
43
|
-
`screenshot path=` filesystem write
|
|
44
|
-
|
|
74
|
+
loopback. MCP tools include `evaluate` (in-page code exec), a
|
|
75
|
+
`screenshot path=` filesystem write, `export_storage_state` (writes full
|
|
76
|
+
cookie values — including HttpOnly auth secrets — to a server-side file) and
|
|
77
|
+
`load_storage_state` (reads an arbitrary server-side file); the gate makes
|
|
78
|
+
remote exposure a deliberate operator decision rather than a default.
|
|
45
79
|
- **Host / Origin headers are validated on loopback binds** to block
|
|
46
80
|
DNS-rebinding against `127.0.0.1` / `localhost` / `[::1]`. On
|
|
47
81
|
non-loopback binds the operator has already accepted exposure via
|
|
@@ -62,11 +96,10 @@ Unit + L2 contract tests (~640ms, no browser, no LLM):
|
|
|
62
96
|
npm test
|
|
63
97
|
```
|
|
64
98
|
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
See `docs/test-eval-plan.md` for the full pyramid.
|
|
99
|
+
The `test/` tree is the L2 contract layer (every tool exercised against a fake
|
|
100
|
+
CDP — see `test/fake-cdp.ts`); the inline `src/**/*.test.ts` files are L1
|
|
101
|
+
pure-data tests; `evals/**/*.test.ts` cover the L4 harness's
|
|
102
|
+
grader/trace/oracle units. See `docs/test-eval-plan.md` for the full pyramid.
|
|
70
103
|
|
|
71
104
|
### L3 — real-browser end-to-end
|
|
72
105
|
|
|
@@ -74,10 +107,10 @@ See `docs/test-eval-plan.md` for the full pyramid.
|
|
|
74
107
|
npm run test:e2e
|
|
75
108
|
```
|
|
76
109
|
|
|
77
|
-
Drives the
|
|
78
|
-
built copy of `examples/sample-app/`.
|
|
79
|
-
stepping, exceptions, console, network, workers, screenshot,
|
|
80
|
-
interaction. Sequential (one Chrome shared across specs, isolated by a
|
|
110
|
+
Drives the 48 MCP tools against a real headless Chromium attached to a
|
|
111
|
+
built copy of `examples/sample-app/`. Eleven specs cover lifecycle, breakpoints,
|
|
112
|
+
stepping, exceptions, console, network, workers, screenshot, DOM
|
|
113
|
+
interaction, form driving, and storage portability. Sequential (one Chrome shared across specs, isolated by a
|
|
81
114
|
shared `afterEach(close_session)`). Run time is a few seconds on a warm
|
|
82
115
|
machine.
|
|
83
116
|
|
|
@@ -113,14 +146,17 @@ pretest hook) enforces this.
|
|
|
113
146
|
`launch_chrome` defaults to `--no-sandbox` for Ubuntu/Playwright-Chromium
|
|
114
147
|
compatibility. See [`docs/chromium-sandboxing.md`](docs/chromium-sandboxing.md)
|
|
115
148
|
before changing that default or relying on `sandbox: true`, AppArmor, snap
|
|
116
|
-
confinement, or Bubblewrap.
|
|
149
|
+
confinement, or Bubblewrap. For the step-by-step setup that gets local
|
|
150
|
+
`npm run test:e2e` passing with the sandbox **on** (install Playwright Chromium
|
|
151
|
+
+ attach the AppArmor profile), see
|
|
152
|
+
[`docs/local-l3-e2e-setup.md`](docs/local-l3-e2e-setup.md).
|
|
117
153
|
|
|
118
154
|
### L4 — LLM agent evals
|
|
119
155
|
|
|
120
156
|
```sh
|
|
121
157
|
export ANTHROPIC_API_KEY=...
|
|
122
|
-
npm run eval:quick # 1 scenario × 1 trial (~$0.50–2 at default Opus-4.
|
|
123
|
-
npm run eval # all scenarios × 3 trials (first observed
|
|
158
|
+
npm run eval:quick # 1 scenario × 1 trial (~$0.50–2 at default Opus-4.8-medium; ~$0.05 with EVAL_MODEL_OVERRIDE=claude-sonnet-4-6)
|
|
159
|
+
npm run eval # all scenarios × 3 trials (~$4 full pass — first observed on Opus-4.7-medium, the prior default; 4.8 shares its rate card)
|
|
124
160
|
npm run eval -- --scenarios=compute-step --trials=1
|
|
125
161
|
```
|
|
126
162
|
|
|
@@ -128,8 +164,10 @@ Use `npm run eval` (or `npm run eval:quick`) — NOT `npx tsx evals/cli.ts` dire
|
|
|
128
164
|
|
|
129
165
|
Drives the cdp-mcp tool surface through an LLM agent via the
|
|
130
166
|
`VendorAdapter` seam (`evals/harness/vendor.ts`); the Anthropic adapter
|
|
131
|
-
backed by `@anthropic-ai/sdk` is the default
|
|
132
|
-
|
|
167
|
+
backed by `@anthropic-ai/sdk` is the default; OpenAI, Vertex, DeepSeek,
|
|
168
|
+
and Moonshot/Kimi are also shipped production adapters (plus an LM Studio
|
|
169
|
+
reference adapter for local models), each selected via `EVAL_PROVIDER`.
|
|
170
|
+
Each trial spawns a fresh `dist/index.js` MCP subprocess + a
|
|
133
171
|
static server for the scenario's sample-app variant; the tool-use loop
|
|
134
172
|
drives the page, sets source-level breakpoints, inspects pauses, and
|
|
135
173
|
produces a natural-language final answer. NDJSON traces land under
|
|
@@ -138,7 +176,7 @@ produces a natural-language final answer. NDJSON traces land under
|
|
|
138
176
|
exercise the debugger workflow under test) + **correctness** (did the
|
|
139
177
|
final answer name the bug) — plus efficiency ratio and recovery count.
|
|
140
178
|
|
|
141
|
-
**Default model**: `claude-opus-4-
|
|
179
|
+
**Default model**: `claude-opus-4-8` with adaptive thinking at
|
|
142
180
|
`effort=medium` (set in `evals/harness/model.ts`). Adaptive-style models
|
|
143
181
|
(Opus 4.7+) default to medium-effort thinking when no env override is
|
|
144
182
|
set; budget-style models (Sonnet 4.6, selectable via
|
|
@@ -172,23 +210,27 @@ each `t:"usage"` trace entry (the Anthropic adapter populates
|
|
|
172
210
|
`cacheTokens.cacheReadInputTokens` and `cacheTokens.cacheCreationInputTokens`
|
|
173
211
|
verbatim from the SDK's `cache_read_input_tokens` / `cache_creation_input_tokens`).
|
|
174
212
|
|
|
175
|
-
Non-Anthropic backends
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
[evals/README.md](evals/README.md) for full `EVAL_PROVIDER` /
|
|
183
|
-
`
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
Currently registered scenarios (
|
|
187
|
-
`adversarial-out-of-order`
|
|
188
|
-
`
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
`npm run
|
|
213
|
+
Non-Anthropic backends ship behind the same seam, each selected via
|
|
214
|
+
`EVAL_PROVIDER`: OpenAI / GPT-5.5 (#50/#58) — reasoning-off trials route to
|
|
215
|
+
`/v1/chat/completions` (#50), reasoning-on trials to `/v1/responses` (#58),
|
|
216
|
+
the only OpenAI surface that supports tools × reasoning_effort on GPT-5.5;
|
|
217
|
+
Vertex / Gemini (#51); and DeepSeek + Moonshot/Kimi (GH #8), remote
|
|
218
|
+
OpenAI-compatible `/v1` vendors. An LM Studio investigation artifact is
|
|
219
|
+
wired behind the seam for local models (issue #45). See
|
|
220
|
+
[evals/README.md](evals/README.md) for full `EVAL_PROVIDER` / `EVAL_OPENAI_*`
|
|
221
|
+
/ `EVAL_VERTEX_*` / `EVAL_DEEPSEEK_*` / `EVAL_MOONSHOT_*` / `EVAL_LM_STUDIO_*`
|
|
222
|
+
details.
|
|
223
|
+
|
|
224
|
+
Currently registered scenarios (14) — 8 **debugger** scenarios
|
|
225
|
+
(`compute-step`, `adversarial-out-of-order`, `network-bug`, `console-error`,
|
|
226
|
+
`event-binding`, `deep-source-map`, `worker-bug`, `conditional-bp`) plus 6
|
|
227
|
+
**driving + session-portability** scenarios from issue #12 (`form-drive`,
|
|
228
|
+
`clearing-fill`, `idempotent-toggle`, `robust-locator`, `session-resume`,
|
|
229
|
+
`cookie-redaction`). `compute-step` is the canonical `npm run eval:quick`
|
|
230
|
+
target; some scenarios run against the stock `examples/sample-app/`, others
|
|
231
|
+
against per-scenario forks under `evals/sample-app-variants/<name>/` built via
|
|
232
|
+
`npm run sample:build` (`scripts/build-variants.mjs`). See
|
|
233
|
+
[evals/README.md](evals/README.md) for the full scenario table.
|
|
192
234
|
|
|
193
235
|
## Wire into Claude Code
|
|
194
236
|
|
|
@@ -226,6 +268,27 @@ Or via `~/.claude.json`:
|
|
|
226
268
|
- **Errors** come back as `isError: true` with a structured `{ error, message }` JSON payload.
|
|
227
269
|
- **Compact returns**: previews trimmed to ~200 chars, lists capped at sensible defaults — bodies lazy-loaded via dedicated tools.
|
|
228
270
|
|
|
271
|
+
## Programmatic contract (`cdp-mcp/contract`)
|
|
272
|
+
|
|
273
|
+
The structured `LocatorSpec` that `locate`, `wait_for`, and the form-driving tools
|
|
274
|
+
accept is published as a side-effect-free subpath export, so external tooling can
|
|
275
|
+
*produce and validate* specs without duplicating the shape or pulling in the CLI:
|
|
276
|
+
|
|
277
|
+
```ts
|
|
278
|
+
import { locatorSchema, parseLocator, serializeLocator } from "cdp-mcp/contract";
|
|
279
|
+
import type { LocatorSpec } from "cdp-mcp/contract";
|
|
280
|
+
|
|
281
|
+
const spec = parseLocator({ by: "role", role: "button", name: "Submit" });
|
|
282
|
+
locatorSchema.parse(spec); // throws on an invalid shape
|
|
283
|
+
serializeLocator(spec); // stable, normalized JSON
|
|
284
|
+
```
|
|
285
|
+
|
|
286
|
+
Exports: `LocatorSpec` (type), `LocatorBy`, `locatorSchema` / `locatorShape` /
|
|
287
|
+
`locatorBySchema` (Zod), and `normalizeLocator` / `parseLocator` / `serializeLocator`
|
|
288
|
+
/ `LocatorError`. This module imports only `zod`. The subpath is **ESM-only** (the
|
|
289
|
+
`exports` map defines `import`, not `require`) — consume it from an ESM module or a
|
|
290
|
+
bundler.
|
|
291
|
+
|
|
229
292
|
## Prior art
|
|
230
293
|
|
|
231
294
|
If `cdp-mcp` doesn't fit your workflow, look at:
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Public package contract, published under the `cdp-mcp/contract` subpath export.
|
|
3
|
+
*
|
|
4
|
+
* Keep this a thin, side-effect-free barrel: it must only re-export from modules
|
|
5
|
+
* (like `./locator.js`) whose import graph never reaches the CLI/server entry
|
|
6
|
+
* (`./index.js`, `./server.js`, `./session/*`). That guarantee is what lets a
|
|
7
|
+
* downstream consumer `import { locatorSchema } from "cdp-mcp/contract"` without
|
|
8
|
+
* dragging in the executable's transport/shebang side effects.
|
|
9
|
+
*/
|
|
10
|
+
export { LocatorError, locatorBySchema, locatorShape, locatorSchema, normalizeLocator, parseLocator, serializeLocator, } from "./locator.js";
|
|
11
|
+
export type { LocatorBy, LocatorSpec } from "./locator.js";
|
package/dist/contract.js
ADDED
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Public package contract, published under the `cdp-mcp/contract` subpath export.
|
|
3
|
+
*
|
|
4
|
+
* Keep this a thin, side-effect-free barrel: it must only re-export from modules
|
|
5
|
+
* (like `./locator.js`) whose import graph never reaches the CLI/server entry
|
|
6
|
+
* (`./index.js`, `./server.js`, `./session/*`). That guarantee is what lets a
|
|
7
|
+
* downstream consumer `import { locatorSchema } from "cdp-mcp/contract"` without
|
|
8
|
+
* dragging in the executable's transport/shebang side effects.
|
|
9
|
+
*/
|
|
10
|
+
export { LocatorError, locatorBySchema, locatorShape, locatorSchema, normalizeLocator, parseLocator, serializeLocator, } from "./locator.js";
|
|
11
|
+
//# sourceMappingURL=contract.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"contract.js","sourceRoot":"","sources":["../src/contract.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AACH,OAAO,EACL,YAAY,EACZ,eAAe,EACf,YAAY,EACZ,aAAa,EACb,gBAAgB,EAChB,YAAY,EACZ,gBAAgB,GACjB,MAAM,cAAc,CAAC"}
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
import { type IncomingMessage, type ServerResponse } from "node:http";
|
|
3
|
+
import { SSEServerTransport } from "@modelcontextprotocol/sdk/server/sse.js";
|
|
4
|
+
import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
|
|
5
|
+
export interface SseClient {
|
|
6
|
+
server: McpServer;
|
|
7
|
+
transport: SSEServerTransport;
|
|
8
|
+
}
|
|
9
|
+
export declare function handleSseRequest({ req, res, clients, host, port, validateHostOrigin, allowedHosts, allowedOrigins, }: {
|
|
10
|
+
req: IncomingMessage;
|
|
11
|
+
res: ServerResponse;
|
|
12
|
+
clients: Map<string, SseClient>;
|
|
13
|
+
host: string;
|
|
14
|
+
port: number;
|
|
15
|
+
validateHostOrigin: boolean;
|
|
16
|
+
allowedHosts: Set<string>;
|
|
17
|
+
allowedOrigins: Set<string>;
|
|
18
|
+
}): Promise<void>;
|
|
@@ -0,0 +1,108 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Canonical `LocatorSpec` contract for cdp-mcp.
|
|
3
|
+
*
|
|
4
|
+
* This module is the single source of truth for the structured element-locator
|
|
5
|
+
* shape that `locate`, `wait_for`, and the form-driving tools accept. It is
|
|
6
|
+
* deliberately **side-effect free** and depends only on `zod`, so external
|
|
7
|
+
* consumers can import it (via `cdp-mcp/contract`) to produce and validate specs
|
|
8
|
+
* without pulling in the CLI/server. Tool code re-imports these symbols rather
|
|
9
|
+
* than redefining them, so the published contract can never silently drift from
|
|
10
|
+
* what the tools actually accept.
|
|
11
|
+
*/
|
|
12
|
+
import { z } from "zod";
|
|
13
|
+
/**
|
|
14
|
+
* Error thrown by {@link normalizeLocator} / {@link parseLocator} for an invalid
|
|
15
|
+
* spec. `code` mirrors the cdp-mcp tool error codes so tool handlers can re-wrap it
|
|
16
|
+
* structurally: `"missing_arg"` when a spec is under-specified for its strategy,
|
|
17
|
+
* `"invalid_locator"` for an unsupported strategy.
|
|
18
|
+
*/
|
|
19
|
+
export declare class LocatorError extends Error {
|
|
20
|
+
readonly code: string;
|
|
21
|
+
constructor(message: string, code?: string);
|
|
22
|
+
}
|
|
23
|
+
/** The locator strategies cdp-mcp understands. `css` is the default when a selector is given. */
|
|
24
|
+
export declare const locatorBySchema: z.ZodEnum<["css", "text", "role", "test_id", "testId", "label", "placeholder", "name"]>;
|
|
25
|
+
/**
|
|
26
|
+
* The raw Zod shape for a LocatorSpec. Spread into tool input schemas
|
|
27
|
+
* (`{ ...locatorShape, ... }`) so the field docs stay identical everywhere.
|
|
28
|
+
*/
|
|
29
|
+
export declare const locatorShape: {
|
|
30
|
+
by: z.ZodOptional<z.ZodEnum<["css", "text", "role", "test_id", "testId", "label", "placeholder", "name"]>>;
|
|
31
|
+
selector: z.ZodOptional<z.ZodString>;
|
|
32
|
+
css: z.ZodOptional<z.ZodString>;
|
|
33
|
+
text: z.ZodOptional<z.ZodString>;
|
|
34
|
+
role: z.ZodOptional<z.ZodString>;
|
|
35
|
+
name: z.ZodOptional<z.ZodString>;
|
|
36
|
+
test_id: z.ZodOptional<z.ZodString>;
|
|
37
|
+
testId: z.ZodOptional<z.ZodString>;
|
|
38
|
+
label: z.ZodOptional<z.ZodString>;
|
|
39
|
+
placeholder: z.ZodOptional<z.ZodString>;
|
|
40
|
+
exact: z.ZodOptional<z.ZodBoolean>;
|
|
41
|
+
};
|
|
42
|
+
/** A standalone `ZodObject` for a LocatorSpec — external consumers can `.parse()`/`.safeParse()`. */
|
|
43
|
+
export declare const locatorSchema: z.ZodObject<{
|
|
44
|
+
by: z.ZodOptional<z.ZodEnum<["css", "text", "role", "test_id", "testId", "label", "placeholder", "name"]>>;
|
|
45
|
+
selector: z.ZodOptional<z.ZodString>;
|
|
46
|
+
css: z.ZodOptional<z.ZodString>;
|
|
47
|
+
text: z.ZodOptional<z.ZodString>;
|
|
48
|
+
role: z.ZodOptional<z.ZodString>;
|
|
49
|
+
name: z.ZodOptional<z.ZodString>;
|
|
50
|
+
test_id: z.ZodOptional<z.ZodString>;
|
|
51
|
+
testId: z.ZodOptional<z.ZodString>;
|
|
52
|
+
label: z.ZodOptional<z.ZodString>;
|
|
53
|
+
placeholder: z.ZodOptional<z.ZodString>;
|
|
54
|
+
exact: z.ZodOptional<z.ZodBoolean>;
|
|
55
|
+
}, "strip", z.ZodTypeAny, {
|
|
56
|
+
css?: string | undefined;
|
|
57
|
+
text?: string | undefined;
|
|
58
|
+
role?: string | undefined;
|
|
59
|
+
test_id?: string | undefined;
|
|
60
|
+
testId?: string | undefined;
|
|
61
|
+
label?: string | undefined;
|
|
62
|
+
placeholder?: string | undefined;
|
|
63
|
+
name?: string | undefined;
|
|
64
|
+
exact?: boolean | undefined;
|
|
65
|
+
by?: "css" | "text" | "role" | "test_id" | "testId" | "label" | "placeholder" | "name" | undefined;
|
|
66
|
+
selector?: string | undefined;
|
|
67
|
+
}, {
|
|
68
|
+
css?: string | undefined;
|
|
69
|
+
text?: string | undefined;
|
|
70
|
+
role?: string | undefined;
|
|
71
|
+
test_id?: string | undefined;
|
|
72
|
+
testId?: string | undefined;
|
|
73
|
+
label?: string | undefined;
|
|
74
|
+
placeholder?: string | undefined;
|
|
75
|
+
name?: string | undefined;
|
|
76
|
+
exact?: boolean | undefined;
|
|
77
|
+
by?: "css" | "text" | "role" | "test_id" | "testId" | "label" | "placeholder" | "name" | undefined;
|
|
78
|
+
selector?: string | undefined;
|
|
79
|
+
}>;
|
|
80
|
+
export type LocatorBy = z.infer<typeof locatorBySchema>;
|
|
81
|
+
export interface LocatorSpec {
|
|
82
|
+
by?: LocatorBy;
|
|
83
|
+
selector?: string;
|
|
84
|
+
css?: string;
|
|
85
|
+
text?: string;
|
|
86
|
+
role?: string;
|
|
87
|
+
name?: string;
|
|
88
|
+
test_id?: string;
|
|
89
|
+
testId?: string;
|
|
90
|
+
label?: string;
|
|
91
|
+
placeholder?: string;
|
|
92
|
+
exact?: boolean;
|
|
93
|
+
}
|
|
94
|
+
/**
|
|
95
|
+
* Validate and canonicalize a spec: infer `by` from selector/css, enforce the
|
|
96
|
+
* required field for the chosen strategy, and fold the `name` fallback into the
|
|
97
|
+
* strategy-specific field. Throws {@link LocatorError} on an under-specified spec.
|
|
98
|
+
*/
|
|
99
|
+
export declare function normalizeLocator(input: LocatorSpec): LocatorSpec;
|
|
100
|
+
/** Validate an unknown value as a LocatorSpec (shape + strategy requirements). */
|
|
101
|
+
export declare function parseLocator(input: unknown): LocatorSpec;
|
|
102
|
+
/**
|
|
103
|
+
* Serialize a LocatorSpec to a stable, normalized JSON string. Equivalent specs
|
|
104
|
+
* serialize identically regardless of which alias the caller used — e.g.
|
|
105
|
+
* `{ css: ".x" }` and `{ selector: ".x" }` both yield `{"by":"css","selector":".x"}`
|
|
106
|
+
* — so the output is safe to use as a cache key or for equality checks.
|
|
107
|
+
*/
|
|
108
|
+
export declare function serializeLocator(spec: LocatorSpec): string;
|
package/dist/locator.js
ADDED
|
@@ -0,0 +1,176 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Canonical `LocatorSpec` contract for cdp-mcp.
|
|
3
|
+
*
|
|
4
|
+
* This module is the single source of truth for the structured element-locator
|
|
5
|
+
* shape that `locate`, `wait_for`, and the form-driving tools accept. It is
|
|
6
|
+
* deliberately **side-effect free** and depends only on `zod`, so external
|
|
7
|
+
* consumers can import it (via `cdp-mcp/contract`) to produce and validate specs
|
|
8
|
+
* without pulling in the CLI/server. Tool code re-imports these symbols rather
|
|
9
|
+
* than redefining them, so the published contract can never silently drift from
|
|
10
|
+
* what the tools actually accept.
|
|
11
|
+
*/
|
|
12
|
+
import { z } from "zod";
|
|
13
|
+
/**
|
|
14
|
+
* Error thrown by {@link normalizeLocator} / {@link parseLocator} for an invalid
|
|
15
|
+
* spec. `code` mirrors the cdp-mcp tool error codes so tool handlers can re-wrap it
|
|
16
|
+
* structurally: `"missing_arg"` when a spec is under-specified for its strategy,
|
|
17
|
+
* `"invalid_locator"` for an unsupported strategy.
|
|
18
|
+
*/
|
|
19
|
+
export class LocatorError extends Error {
|
|
20
|
+
code;
|
|
21
|
+
constructor(message, code = "missing_arg") {
|
|
22
|
+
super(message);
|
|
23
|
+
this.name = "LocatorError";
|
|
24
|
+
this.code = code;
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
/** The locator strategies cdp-mcp understands. `css` is the default when a selector is given. */
|
|
28
|
+
export const locatorBySchema = z.enum([
|
|
29
|
+
"css",
|
|
30
|
+
"text",
|
|
31
|
+
"role",
|
|
32
|
+
"test_id",
|
|
33
|
+
"testId",
|
|
34
|
+
"label",
|
|
35
|
+
"placeholder",
|
|
36
|
+
"name",
|
|
37
|
+
]);
|
|
38
|
+
/**
|
|
39
|
+
* The raw Zod shape for a LocatorSpec. Spread into tool input schemas
|
|
40
|
+
* (`{ ...locatorShape, ... }`) so the field docs stay identical everywhere.
|
|
41
|
+
*/
|
|
42
|
+
export const locatorShape = {
|
|
43
|
+
by: locatorBySchema.optional().describe("Locator strategy. Omit when passing selector/css for a CSS lookup."),
|
|
44
|
+
selector: z.string().optional().describe("CSS selector. Equivalent to by=css."),
|
|
45
|
+
css: z.string().optional().describe("CSS selector. Equivalent to selector."),
|
|
46
|
+
text: z.string().optional().describe("Text to match for by=text."),
|
|
47
|
+
role: z.string().optional().describe("ARIA/implicit role for by=role, e.g. button, link, textbox."),
|
|
48
|
+
name: z.string().optional().describe("Accessible name, field name, or fallback value depending on the locator strategy."),
|
|
49
|
+
test_id: z.string().optional().describe("Value for data-testid, data-test-id, or data-test."),
|
|
50
|
+
// Both snake_case (`test_id`) and camelCase (`testId`) are accepted so callers
|
|
51
|
+
// can use whichever matches their convention; `normalizeLocator` /
|
|
52
|
+
// `serializeLocator` fold them to the canonical `test_id`. Likewise `name` is a
|
|
53
|
+
// cross-strategy fallback that gets folded into the strategy-specific field.
|
|
54
|
+
testId: z.string().optional().describe("CamelCase alias for test_id."),
|
|
55
|
+
label: z.string().optional().describe("Label text for by=label."),
|
|
56
|
+
placeholder: z.string().optional().describe("Placeholder text for by=placeholder."),
|
|
57
|
+
exact: z.boolean().optional().describe("Default false: substring match for text/name-like fields."),
|
|
58
|
+
};
|
|
59
|
+
/** A standalone `ZodObject` for a LocatorSpec — external consumers can `.parse()`/`.safeParse()`. */
|
|
60
|
+
export const locatorSchema = z.object(locatorShape);
|
|
61
|
+
/**
|
|
62
|
+
* Validate and canonicalize a spec: infer `by` from selector/css, enforce the
|
|
63
|
+
* required field for the chosen strategy, and fold the `name` fallback into the
|
|
64
|
+
* strategy-specific field. Throws {@link LocatorError} on an under-specified spec.
|
|
65
|
+
*/
|
|
66
|
+
export function normalizeLocator(input) {
|
|
67
|
+
const by = input.by ?? (input.selector || input.css ? "css" : undefined);
|
|
68
|
+
if (!by)
|
|
69
|
+
throw new LocatorError("by is required unless selector/css is supplied");
|
|
70
|
+
switch (by) {
|
|
71
|
+
case "css": {
|
|
72
|
+
const selector = input.selector ?? input.css;
|
|
73
|
+
if (!selector)
|
|
74
|
+
throw new LocatorError("selector or css is required for by=css");
|
|
75
|
+
return { ...input, by, selector };
|
|
76
|
+
}
|
|
77
|
+
case "role":
|
|
78
|
+
if (!input.role)
|
|
79
|
+
throw new LocatorError("role is required for by=role");
|
|
80
|
+
return { ...input, by };
|
|
81
|
+
case "text":
|
|
82
|
+
if (!input.text && !input.name)
|
|
83
|
+
throw new LocatorError("text or name is required for by=text");
|
|
84
|
+
return { ...input, by, text: input.text ?? input.name };
|
|
85
|
+
case "test_id":
|
|
86
|
+
case "testId": {
|
|
87
|
+
const testId = input.test_id ?? input.testId ?? input.name;
|
|
88
|
+
if (!testId)
|
|
89
|
+
throw new LocatorError(`test_id, testId, or name is required for by=${by}`);
|
|
90
|
+
return { ...input, by, test_id: testId };
|
|
91
|
+
}
|
|
92
|
+
case "label": {
|
|
93
|
+
const label = input.label ?? input.name;
|
|
94
|
+
if (!label)
|
|
95
|
+
throw new LocatorError("label or name is required for by=label");
|
|
96
|
+
return { ...input, by, label };
|
|
97
|
+
}
|
|
98
|
+
case "placeholder": {
|
|
99
|
+
const placeholder = input.placeholder ?? input.name;
|
|
100
|
+
if (!placeholder)
|
|
101
|
+
throw new LocatorError("placeholder or name is required for by=placeholder");
|
|
102
|
+
return { ...input, by, placeholder };
|
|
103
|
+
}
|
|
104
|
+
case "name":
|
|
105
|
+
if (!input.name)
|
|
106
|
+
throw new LocatorError("name is required for by=name");
|
|
107
|
+
return { ...input, by };
|
|
108
|
+
default: {
|
|
109
|
+
// Compile-time exhaustiveness: if `locatorBySchema` gains a strategy and a
|
|
110
|
+
// case here is missed, `by` is no longer `never` and this fails to build
|
|
111
|
+
// (pairs with `noFallthroughCasesInSwitch`).
|
|
112
|
+
const _exhaustive = by;
|
|
113
|
+
throw new LocatorError(`unsupported locator strategy: ${String(_exhaustive)}`, "invalid_locator");
|
|
114
|
+
}
|
|
115
|
+
}
|
|
116
|
+
}
|
|
117
|
+
/** Validate an unknown value as a LocatorSpec (shape + strategy requirements). */
|
|
118
|
+
export function parseLocator(input) {
|
|
119
|
+
return normalizeLocator(locatorSchema.parse(input));
|
|
120
|
+
}
|
|
121
|
+
/**
|
|
122
|
+
* Serialize a LocatorSpec to a stable, normalized JSON string. Equivalent specs
|
|
123
|
+
* serialize identically regardless of which alias the caller used — e.g.
|
|
124
|
+
* `{ css: ".x" }` and `{ selector: ".x" }` both yield `{"by":"css","selector":".x"}`
|
|
125
|
+
* — so the output is safe to use as a cache key or for equality checks.
|
|
126
|
+
*/
|
|
127
|
+
export function serializeLocator(spec) {
|
|
128
|
+
return JSON.stringify(canonicalLocator(spec));
|
|
129
|
+
}
|
|
130
|
+
/**
|
|
131
|
+
* Reduce a spec to only its canonical fields, in a fixed key order, dropping
|
|
132
|
+
* alias inputs (`css`, `testId`, and the cross-strategy `name` fallback). This is
|
|
133
|
+
* what makes {@link serializeLocator} stable across equivalent inputs — the raw
|
|
134
|
+
* `normalizeLocator` result still carries whichever aliases the caller passed.
|
|
135
|
+
*/
|
|
136
|
+
function canonicalLocator(spec) {
|
|
137
|
+
const n = normalizeLocator(spec);
|
|
138
|
+
const out = {};
|
|
139
|
+
switch (n.by) {
|
|
140
|
+
case "css":
|
|
141
|
+
out.by = "css";
|
|
142
|
+
out.selector = n.selector;
|
|
143
|
+
break;
|
|
144
|
+
case "role":
|
|
145
|
+
out.by = "role";
|
|
146
|
+
out.role = n.role;
|
|
147
|
+
if (n.name !== undefined)
|
|
148
|
+
out.name = n.name;
|
|
149
|
+
break;
|
|
150
|
+
case "text":
|
|
151
|
+
out.by = "text";
|
|
152
|
+
out.text = n.text;
|
|
153
|
+
break;
|
|
154
|
+
case "test_id":
|
|
155
|
+
case "testId":
|
|
156
|
+
out.by = "test_id";
|
|
157
|
+
out.test_id = n.test_id;
|
|
158
|
+
break;
|
|
159
|
+
case "label":
|
|
160
|
+
out.by = "label";
|
|
161
|
+
out.label = n.label;
|
|
162
|
+
break;
|
|
163
|
+
case "placeholder":
|
|
164
|
+
out.by = "placeholder";
|
|
165
|
+
out.placeholder = n.placeholder;
|
|
166
|
+
break;
|
|
167
|
+
case "name":
|
|
168
|
+
out.by = "name";
|
|
169
|
+
out.name = n.name;
|
|
170
|
+
break;
|
|
171
|
+
}
|
|
172
|
+
if (n.exact !== undefined)
|
|
173
|
+
out.exact = n.exact;
|
|
174
|
+
return out;
|
|
175
|
+
}
|
|
176
|
+
//# sourceMappingURL=locator.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"locator.js","sourceRoot":"","sources":["../src/locator.ts"],"names":[],"mappings":"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"}
|
package/dist/server.d.ts
ADDED
package/dist/server.js
CHANGED
|
@@ -8,6 +8,8 @@ import { registerInspectTools } from "./tools/inspect.js";
|
|
|
8
8
|
import { registerConsoleTools } from "./tools/console.js";
|
|
9
9
|
import { registerNetworkTools } from "./tools/network.js";
|
|
10
10
|
import { registerDomTools } from "./tools/dom.js";
|
|
11
|
+
import { registerFormTools } from "./tools/forms.js";
|
|
12
|
+
import { registerStorageTools } from "./tools/storage.js";
|
|
11
13
|
export function buildServer() {
|
|
12
14
|
const server = new McpServer({
|
|
13
15
|
name: "cdp-mcp",
|
|
@@ -22,6 +24,8 @@ export function buildServer() {
|
|
|
22
24
|
registerConsoleTools(server);
|
|
23
25
|
registerNetworkTools(server);
|
|
24
26
|
registerDomTools(server);
|
|
27
|
+
registerFormTools(server);
|
|
28
|
+
registerStorageTools(server);
|
|
25
29
|
// The SDK advertises `tools: { listChanged: true }` as soon as any tool is
|
|
26
30
|
// registered, but never emits the matching notification on its own. Some
|
|
27
31
|
// clients (e.g. GitHub Copilot CLI over SSE) gate their first `tools/list`
|
package/dist/server.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"server.js","sourceRoot":"","sources":["../src/server.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,yCAAyC,CAAC;AACpE,OAAO,EAAE,oBAAoB,EAAE,MAAM,oBAAoB,CAAC;AAC1D,OAAO,EAAE,gBAAgB,EAAE,MAAM,gBAAgB,CAAC;AAClD,OAAO,EAAE,mBAAmB,EAAE,MAAM,mBAAmB,CAAC;AACxD,OAAO,EAAE,uBAAuB,EAAE,MAAM,wBAAwB,CAAC;AACjE,OAAO,EAAE,sBAAsB,EAAE,MAAM,sBAAsB,CAAC;AAC9D,OAAO,EAAE,oBAAoB,EAAE,MAAM,oBAAoB,CAAC;AAC1D,OAAO,EAAE,oBAAoB,EAAE,MAAM,oBAAoB,CAAC;AAC1D,OAAO,EAAE,oBAAoB,EAAE,MAAM,oBAAoB,CAAC;AAC1D,OAAO,EAAE,gBAAgB,EAAE,MAAM,gBAAgB,CAAC;
|
|
1
|
+
{"version":3,"file":"server.js","sourceRoot":"","sources":["../src/server.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,yCAAyC,CAAC;AACpE,OAAO,EAAE,oBAAoB,EAAE,MAAM,oBAAoB,CAAC;AAC1D,OAAO,EAAE,gBAAgB,EAAE,MAAM,gBAAgB,CAAC;AAClD,OAAO,EAAE,mBAAmB,EAAE,MAAM,mBAAmB,CAAC;AACxD,OAAO,EAAE,uBAAuB,EAAE,MAAM,wBAAwB,CAAC;AACjE,OAAO,EAAE,sBAAsB,EAAE,MAAM,sBAAsB,CAAC;AAC9D,OAAO,EAAE,oBAAoB,EAAE,MAAM,oBAAoB,CAAC;AAC1D,OAAO,EAAE,oBAAoB,EAAE,MAAM,oBAAoB,CAAC;AAC1D,OAAO,EAAE,oBAAoB,EAAE,MAAM,oBAAoB,CAAC;AAC1D,OAAO,EAAE,gBAAgB,EAAE,MAAM,gBAAgB,CAAC;AAClD,OAAO,EAAE,iBAAiB,EAAE,MAAM,kBAAkB,CAAC;AACrD,OAAO,EAAE,oBAAoB,EAAE,MAAM,oBAAoB,CAAC;AAE1D,MAAM,UAAU,WAAW;IACzB,MAAM,MAAM,GAAG,IAAI,SAAS,CAAC;QAC3B,IAAI,EAAE,SAAS;QACf,OAAO,EAAE,OAAO;KACjB,CAAC,CAAC;IAEH,oBAAoB,CAAC,MAAM,CAAC,CAAC;IAC7B,gBAAgB,CAAC,MAAM,CAAC,CAAC;IACzB,mBAAmB,CAAC,MAAM,CAAC,CAAC;IAC5B,uBAAuB,CAAC,MAAM,CAAC,CAAC;IAChC,sBAAsB,CAAC,MAAM,CAAC,CAAC;IAC/B,oBAAoB,CAAC,MAAM,CAAC,CAAC;IAC7B,oBAAoB,CAAC,MAAM,CAAC,CAAC;IAC7B,oBAAoB,CAAC,MAAM,CAAC,CAAC;IAC7B,gBAAgB,CAAC,MAAM,CAAC,CAAC;IACzB,iBAAiB,CAAC,MAAM,CAAC,CAAC;IAC1B,oBAAoB,CAAC,MAAM,CAAC,CAAC;IAE7B,2EAA2E;IAC3E,yEAAyE;IACzE,2EAA2E;IAC3E,4EAA4E;IAC5E,2EAA2E;IAC3E,yEAAyE;IACzE,iEAAiE;IACjE,MAAM,CAAC,MAAM,CAAC,aAAa,GAAG,GAAG,EAAE;QACjC,MAAM,CAAC,mBAAmB,EAAE,CAAC;IAC/B,CAAC,CAAC;IAEF,OAAO,MAAM,CAAC;AAChB,CAAC"}
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
export interface LaunchArgs {
|
|
2
|
+
url?: string;
|
|
3
|
+
headless?: boolean;
|
|
4
|
+
userDataDir?: string;
|
|
5
|
+
args?: string[];
|
|
6
|
+
chromePath?: string;
|
|
7
|
+
sandbox?: boolean;
|
|
8
|
+
}
|
|
9
|
+
export interface AttachArgs {
|
|
10
|
+
port?: number;
|
|
11
|
+
host?: string;
|
|
12
|
+
targetFilter?: {
|
|
13
|
+
type?: string;
|
|
14
|
+
urlIncludes?: string;
|
|
15
|
+
};
|
|
16
|
+
}
|
|
17
|
+
export declare function launchChrome(opts?: LaunchArgs): Promise<{
|
|
18
|
+
targetId: string;
|
|
19
|
+
url: string;
|
|
20
|
+
}>;
|
|
21
|
+
export declare function attachChrome(opts?: AttachArgs): Promise<{
|
|
22
|
+
targetId: string;
|
|
23
|
+
url: string;
|
|
24
|
+
}>;
|
|
25
|
+
export declare function closeSession(): Promise<void>;
|
|
26
|
+
export declare function switchTarget(targetId: string): Promise<{
|
|
27
|
+
targetId: string;
|
|
28
|
+
url: string;
|
|
29
|
+
}>;
|