MCP server + WebSocket bridge for the poke-browser Chrome extension
32 tools with mostly complete schemas and descriptions, but significant gaps in parameter documentation and error guidance. Tool names follow verb_noun convention well (navigate_to, click_element, get_dom_snapshot). Descriptions average ~80-120 chars, below the 194-char baseline for A+ tools. Many parameters lack detailed constraints (e.g., 'timeout' in navigate_to has no range; 'format' in capture_screenshot has no enum). Error handling is minimal, most tools return raw bridge errors without recovery guidance. No tool annotations (readOnlyHint/destructiveHint) despite clear risk classifications. Output schemas are undocumented; LLMs cannot predict response structure. Composition is strong, tools chain well (find_element → click_element → type_text). Security concern: evaluate_js and execute_script expose arbitrary code execution without warnings.
This playbook (static Markdown; no parameters).
Same capture, then multipart POST to uploadUrl or POKE_UPLOAD_URL; on failure returns base64 + temp path.
Visible viewport screenshot (PNG/JPEG).
Clear the content-script console ring buffer.
Clear captured network logs.
Click via CSS/XPath or viewport x/y (CDP); 1s CDP hover (mouseMoved) at the target before the click.
Read/write/delete cookies via chrome.cookies.
Missing output schemas: No tool documents its return type structure. LLMs cannot predict response fields, forcing them to guess at downstream tool parameters. E.g., navigate_to returns success/error but structure is undocumented.
Parameter constraints missing: 'timeout' in navigate_to has no range (seconds? ms?). 'format' in capture_screenshot should be enum ['png','jpeg']. 'quality' in capture_screenshot lacks min/max (0-100). LLMs will pass invalid values.
No error recovery guidance: Tools return raw bridge errors ('extension bridge disconnected') without actionable next steps. Pattern requires: 'User not found. Try search_users() first.' Current errors give LLM nothing to act on.
Inferred effective spec: <=2025-11-25.
| Scored | Grade | Overall | Spec posture | Rubric |
|---|---|---|---|---|
| 2026-09-23 | D | 59 | <=2025-11-25 | v2 |
CDP device metrics and optional user-agent preset.
Recent uncaught errors and unhandled rejections.
Run JavaScript in the page main world via the content-script relay (subject to page CSP).
Async script via chrome.scripting (extension main world; bypasses page CSP).
Fill multiple fields in one call; optional submit.
Locate up to 5 nodes by CSS, visible text, ARIA, or XPath; returns bounding rects.
Stitched full-page screenshot (slower; fixed headers may repeat).
Flat semantic nodes (roles, names, selectors) in reading order.
Read the content-script console ring buffer.
Compact DOM tree with tags, roles, aria, text, bounding rects, interactivity.
Retrieve captured network logs.
Navigation timing, paint, JS heap (CDP).
Read localStorage / sessionStorage (and read cookies).
Hover by selector (synthetic events) or CDP coordinates.
List / get active / new / close / switch tabs.
Open a URL in a tab; waits for load (short or long timeout).
Print page to PDF via CDP (Page.printToPDF).
Extract content as structured data, plain text, or lightweight Markdown.
Inject a classic <script> into the DOM (optional persistent per-origin).
Scroll the page (selector into view, absolute position, deltas, or direction).
Write localStorage / sessionStorage.
CDP network buffering and retrieval.
Stop CDP network capture.
Type into the currently active input/textarea/contenteditable. Recommended flow: click target field first, verify focus/active element, then type. Optional clear (default true) replaces existing value first.
Poll until a CSS selector or XPath matches (optional visibility checks).
No tool annotations despite clear risk levels: evaluate_js and execute_script are destructive (arbitrary code execution) but lack destructiveHint. Many read-only tools (get_dom_snapshot, capture_screenshot) lack readOnlyHint. Agents cannot reason about safety.
Underdocumented parameter relationships: 'click_element' accepts selector OR (x,y) but description doesn't state they're mutually exclusive. 'scroll_window' accepts selector OR position OR deltaX/deltaY OR direction, no guidance on which to use when.