cdp-toolkit 1.9.5 → 1.10.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/src/mcp.ts CHANGED
@@ -26,7 +26,7 @@ import { toolAvailability } from "./capabilities.ts";
26
26
  import { FIREFOX_TOOLS } from "./firefox-tools.ts";
27
27
  import { leaseFromArgs, markLongLivedProcess, withLeaseScope } from "./leases.ts";
28
28
 
29
- const VERSION = "1.9.5";
29
+ const VERSION = "1.10.0";
30
30
 
31
31
  // Backend + (Firefox only) attach endpoint are read once at startup (MCP has no per-call notion
32
32
  // of backend): --browser flag / CDP_BROWSER env, else "chrome" (zero behavior change for existing
@@ -50,7 +50,21 @@ function auditCoverage(): void {
50
50
  if (orphanSchema.length) console.error(`[cdp-toolkit] WARN: manifest schemas with no registered tool: ${orphanSchema.join(", ")}`);
51
51
  }
52
52
 
53
- const server = new Server({ name: "cdp-toolkit", version: VERSION }, { capabilities: { tools: {} } });
53
+ // Server `instructions` (MCP initialize result): the cross-cutting conventions that
54
+ // used to be re-stated inside every tool's schema — the target-selector grammar, the
55
+ // lease-token model, the MV3 worker/wake arm, the origin vocabulary. Stating them ONCE
56
+ // here (loaded a single time at init) is what let the per-tool descriptions and the
57
+ // 42-way-duplicated `lease` param collapse to short pointers, cutting the tools/list
58
+ // payload without losing a single behavior. Kept under Claude Code's 2KB instructions
59
+ // cap and front-loaded (grammar + leases before origin) so nothing critical is clipped.
60
+ const INSTRUCTIONS = [
61
+ "cdp-toolkit drives a real browser over Chrome DevTools Protocol (or Firefox WebDriver-BiDi): open and drive pages, click/fill/type, screenshot and accessibility-snapshot, read console + network, set cookies, emulate devices, run Lighthouse and performance traces, record screencasts. Conventions shared across its tools:",
62
+ "TARGET SELECTOR (the `target` param, unless a tool says otherwise): 'active' (default = first page) | 'index:N' (0-based) | 'url:<substr>' | 'title:<substr>' | 'label:<name>' (exact, from the origin ledger or a live lease) | a 32-hex '<targetId>'. Four Chrome-only tools (evaluate_script, list_network_requests, get_network_request, list_console_messages) also accept 'worker:<substr>' to reach a service/shared worker — e.g. an MV3 extension's background worker (worker:<extension-id> or worker:background.js); an idle-evicted worker is started first (see each tool's `wake`).",
63
+ "LEASES (the `lease` param): claim_page, and new_page{claim:true}, mint an opaque token. Omit it for a tab THIS process already holds. It is required for a tab held by ANOTHER process, or one claimed explicitly. Under CDP_REQUIRE_LEASE the gate auto-acquires a lease for any tab this process drives — no token is surfaced, so pass `target`, not `lease` — while an explicit claim:true still demands its token on every later call. Without CDP_REQUIRE_LEASE an unleased tab needs no token at all.",
64
+ "ORIGIN: list_pages and list_leases tag each tab's `origin` as 'agent' (this toolkit created it) or 'unknown' — never 'human', because the toolkit cannot prove a person opened a tab. An 'agent' tab stays findable after its creator releases the lease or dies.",
65
+ ].join("\n\n");
66
+
67
+ const server = new Server({ name: "cdp-toolkit", version: VERSION }, { capabilities: { tools: {} }, instructions: INSTRUCTIONS });
54
68
 
55
69
  server.setRequestHandler(ListToolsRequestSchema, async () => ({
56
70
  // Filtered to whatever the selected backend can actually run, per REQUIRED_CAPABILITIES:
@@ -80,17 +80,20 @@ import {
80
80
  WORKER_EMPTY_NEEDLE_MESSAGE,
81
81
  } from "../workers.ts";
82
82
 
83
- /** Artifact / buffer directory (shared with the rest of the toolkit). */
84
- export const ARTIFACT_DIR = process.env.CDP_ARTIFACT_DIR ?? "/tmp/cdp-toolkit";
83
+ /** Artifact / buffer directory (shared with the rest of the toolkit). Read per
84
+ * call, not at module load, so a test can redirect the directory (as leases.ts). */
85
+ function artifactDir(): string {
86
+ return process.env.CDP_ARTIFACT_DIR ?? "/tmp/cdp-toolkit";
87
+ }
85
88
 
86
89
  /** Compute the shared "latest" JSONL buffer path for a given targetId. */
87
90
  export function recFile(targetId: string): string {
88
- return `${ARTIFACT_DIR}/rec-${targetId}.jsonl`;
91
+ return `${artifactDir()}/rec-${targetId}.jsonl`;
89
92
  }
90
93
 
91
94
  /** Compute a unique per-capture JSONL buffer path (isolates concurrent captures). */
92
95
  export function captureFile(targetId: string, captureId: string): string {
93
- return `${ARTIFACT_DIR}/rec-${targetId}-${captureId}.jsonl`;
96
+ return `${artifactDir()}/rec-${targetId}-${captureId}.jsonl`;
94
97
  }
95
98
 
96
99
  /** Sleep helper (module runtime only; not the workflow-script sandbox). */
@@ -200,7 +203,7 @@ export async function startRecorder(target: TargetSelector, opts: RecorderOption
200
203
  const network = opts.network ?? true;
201
204
  const consoleCap = opts.console ?? true;
202
205
 
203
- await mkdir(ARTIFACT_DIR, { recursive: true });
206
+ await mkdir(artifactDir(), { recursive: true });
204
207
  const { conn, target: resolved } = await openPage(target, { timeoutMs: opts.timeoutMs });
205
208
  const file = opts.file ?? recFile(resolved.id);
206
209