mockpro-mcp
v4.10.0
Published
MCP server for the MockPro Chrome extension — read & write rules/logs over a local WebSocket (127.0.0.1:27319)
Readme
mockpro-mcp
An MCP server that lets Claude Code (and Claude Desktop) mock APIs AND debug any web app in your browser — console logs, network logs, WebSocket frames, DOM inspection, synthetic clicks/typing/navigation.
Browser workflows use a local WebSocket (127.0.0.1:27319). No Native Messaging host to install, no chrome.debugger, no "extension is debugging this browser" banner. Every tool the agent calls is also shown live in the extension's MCP Activity tab, so you can watch exactly what it did. Local image workflows run directly in the MCP process and do not require Chrome.
You need: Node.js 18.17+ · Chrome 136+ · the MockPro extension (free, Chrome Web Store) · an MCP client (Claude Code or Claude Desktop).
Install
Step 1 — Install the MockPro extension (Chrome Web Store)
Open the listing and click Add to Chrome:
https://chromewebstore.google.com/detail/mockpro-api-stream-mocker/liiljkbdpenmgpclbekenhlgpedbcbec
Then grab your extension id (the MCP server needs it):
- Go to
chrome://extensions. - Toggle Developer mode (top-right) on.
- Find the MockPro card and copy the ID — 32 characters,
a–p(e.g.liiljkbdpenmgpclbekenhlgpedbcbec).
Don't want to hunt for the id? Open the MockPro Dashboard → MCP Activity tab — it shows the full
claude mcp addcommand with your id already filled in, plus a Copy button.
Step 2 — Register the MCP server (user scope)
Run this once. --scope user writes to ~/.claude.json so every Claude Code project on your machine inherits it — no per-project re-registration:
claude mcp add --scope user --transport stdio mockpro -- npx -y mockpro-mcp \
--extension-id <YOUR_MOCKPRO_EXTENSION_ID>Drop --scope user if you'd rather scope it to the current project only.
First time / cautious? Append --readonly to disable the write tools until you trust it:
claude mcp add --scope user --transport stdio mockpro -- npx -y mockpro-mcp \
--extension-id <ID> --readonlyTurning readonly off later? Re-run without --readonly (it overwrites the entry), or remove first: claude mcp remove mockpro --scope user.
Step 3 — Verify
Open Claude Code and ask it to call get_state. A healthy connection returns the enabled flag plus rule, group, and log counts. If it errors, open or reload a normal browser tab and retry. Then call list_tabs when you need a browser target. Watch Dashboard → MCP Activity to confirm calls are reaching the extension.
Quickstart
Mock an API while building the frontend
You: "Mock GET /api/users to return 3 fake users, then add a 500 variant I can toggle."
Claude: → add_rule × 2 → toggle_rule to flipOrganize a generated rule set
You: "Create an Authentication group, then add tagged success and error mocks for login."
Claude: → list_rule_groups → create_rule_group → add_rule × 2 → list_rules to verify priorityDebug a failing UI flow on localhost
You: "The checkout button on localhost:3000 isn't responding — figure out why."
Claude: → list_tabs → query_dom('[data-testid=checkout]', ['disabled']) → read_console_logs(level:'error') → read_network_logs(statusFilter:'4xx,5xx')Inspect a remote WebSocket
You: "What WebSocket frames is termix.app receiving right now?"
Claude: → list_tabs → read_websocket_logs(urlContains:'ssh', direction:'in')Capture a lazy-loaded full page
You: "Capture the full page after giving lazy images one second to load."
Claude: → list_tabs → capture_screenshot({fullPage:true, delayMs:1000, savePath:"./full-page.png"})delayMs accepts 0–3000ms and waits after every scroll step. Use a larger value for image-heavy pages with entrance animations.
Drive a form end-to-end (v4.0 ref workflow)
You: "Fill the signup form on localhost:3000/signup with test data and submit."
Claude: → snapshot_page # ~2KB tree: textbox "Email" [ref=e1], … button "Sign up" [ref=e3]
→ type({ref:'e1', value:'[email protected]'}) # reply includes fresh snapshot
→ type({ref:'e2', value:'secret'})
→ click({ref:'e3'}) # reply snapshot shows the success pageInspect, crop, and compress local images with AI
You: "Crop the subject from ./screenshots/hero.png to 16:9, export WebP, then compress every PNG in ./screenshots."
Claude: → inspect_image (sees the source) → edit_image (returns edited preview) → compress_images (batch result)Image processing is local and does not require the Chrome extension to be connected.
Install the Claude Code skill (optional, recommended)
The package bundles a skill that teaches Claude how to use these tools — mocking (missing endpoints, error states, OpenAPI scaffolding), debugging (console + network + WS logs, DOM inspection, clicks/typing/navigation), and UI memory (remember a site's controls and deterministically detect what changed across visits, via a bundled snapshot-diff.cjs helper). Install it once:
npx -y mockpro-mcp install-skill # → ~/.claude/skills/mockpro (current user, recommended)
npx -y mockpro-mcp install-skill --project # → ./.claude/skills/mockpro (this repo only)Restart Claude Code afterward. The skill auto-activates when you ask Claude to mock an API, debug a failing UI flow, drive a form end-to-end, or inspect what a tab is doing.
Flags: --user (default), --project, --dir <path>, --force (overwrite).
Already have an older skill installed? Re-run with
--forceto pick up the latest (v2.4 adds grouped/tagged rule workflows alongside the v2.3 image tools):npx -y mockpro-mcp install-skill --force.
Claude Desktop
Edit Claude Desktop's MCP config (this is global per OS user — equivalent to --scope user for Claude Code):
- macOS:
~/Library/Application Support/Claude/claude_desktop_config.json - Windows:
%APPDATA%\Claude\claude_desktop_config.json
{
"mcpServers": {
"mockpro": {
"command": "npx",
"args": ["-y", "mockpro-mcp", "--extension-id", "<YOUR_MOCKPRO_EXTENSION_ID>"]
}
}
}Restart Claude Desktop after editing.
How it works
Claude Code A (stdio) ── mockpro-mcp A ──┐
Claude Code B (stdio) ── mockpro-mcp B ──┼── private same-user IPC
Claude Desktop (stdio) ─ mockpro-mcp C ──┘ │
▼
shared local broker :27319
│ WebSocket
▼
MockPro extension service worker ── self.handleMessageThe first MCP session auto-starts a detached local broker; later sessions join it through an authenticated Unix socket (macOS/Linux) or named pipe (Windows). The broker owns the single extension WebSocket, fans resource notifications out to every client, and exits shortly after the last MCP session disconnects.
Concurrent sessions must use the same --extension-id and access mode (--readonly, --approve, or normal write). A mismatched client is rejected explicitly rather than inheriting another session's security posture. Rule state and browser tabs are shared, so coordinate destructive writes; import_rules({mode:"merge"}) retains the concurrency caveat below.
Tools
Mocking
- Read (5):
get_state,list_rules,list_rule_groups,get_rule,get_logs(headers redacted by default: Authorization, Cookie, Set-Cookie, Proxy-Authorization). - Write (13):
set_enabled,add_rule,update_rule,delete_rule,toggle_rule,clear_logs,import_rules(merge | replace | append),export_rules,create_rule_group,update_rule_group,delete_rule_group,move_rule,reorder_rule_groups. - Generate (2):
mock_from_openapi,record_then_replay— both return suggested rules; commit viaimport_rules.
Groups, tags, and priority
Requires MockPro extension 3.8.0+ with mockpro-mcp 4.9.0+. Groups are persistent priority blocks; tags are searchable labels. Named groups match from top to bottom, rules match from top to bottom inside each group, and Ungrouped rules match last.
Recommended workflow:
- Call
list_rule_groupsand reuse a suitable group when one exists. - Call
create_rule_groupif a new domain or feature needs its own block. - Pass the returned
group.idand concisetagsto every relatedadd_ruleorimport_rulesitem. - Call
list_ruleswith group/tag/query filters and inspect its zero-basedpriorityvalues.
// 1. Create a priority block.
create_rule_group({
"name": "Authentication",
"color": "#8b5cf6"
})
// 2. Use the returned group.id.
add_rule({
"name": "Login success",
"type": "rest",
"method": "POST",
"urlPattern": "*/api/login",
"groupId": "<GROUP_ID>",
"tags": ["auth", "happy-path"],
"response": { "status": 200, "body": "{\"token\":\"mock-token\"}" }
})
// 3. Find and verify the result.
list_rules({
"groupId": "<GROUP_ID>",
"tag": "auth",
"query": "login"
})| Tool | Behavior |
|---|---|
| list_rule_groups({includeRuleIds?}) | Ordered groups, member counts, and Ungrouped count |
| create_rule_group({name,color?}) | Creates a unique group and returns its generated ID |
| update_rule_group({id,name?,color?}) | Renames or recolors without changing members |
| delete_rule_group({id}) | Deletes only the group; member rules move to Ungrouped |
| move_rule({id,groupId,beforeRuleId?}) | Moves or reorders one rule; groupId:null means Ungrouped |
| reorder_rule_groups({orderedIds}) | Changes both section order and first-match priority blocks |
list_rules combines supplied filters with AND semantics. tag is an exact case-insensitive match. query is a case-insensitive substring search across ID, name, URL pattern, group name, and tags. Use groupId:null to select Ungrouped rules.
export_rules returns {format:"mockpro-rules", version:2, groups, rules} and includes only referenced groups. Pass both arrays to import_rules to preserve organization. Legacy rule arrays remain accepted. See the full Rule Groups and Tags guide for Dashboard drag/drop behavior, limits, migration, and import remapping.
Debug (v4.0.0+)
- Read (8):
list_tabs,read_console_logs,read_network_logs,read_websocket_logs,query_dom,get_dom_snapshot,wait_for_selector,snapshot_page(compact a11y tree with element refs — call this first). - Write (9):
clear_console_logs,clear_network_logs,clear_websocket_logs,click,type,press_key,select_option,scroll,navigate.
Local image workflow
- Read:
inspect_image— returns exact image metadata plus an AI-visible, size-limited preview. Available in--readonlymode and does not require Chrome. - Write:
edit_image— crop, resize, rotate, flip, adjust, convert, and return the edited preview in one pipeline. - Batch write:
compress_images— process 1–100 files with quality or target-KB settings, max dimensions, collision-safe output names, and per-file results.
Image write tools never overwrite an existing file unless overwrite:true is explicit. Relative paths resolve from the MCP process working directory. targetKB is best-effort; targetReached reports whether each result met it.
v4.0.0 BREAKING:
click/type/press_keytakeref(fromsnapshot_page) instead ofselector. Requires MockPro extension ≥ 3.0.0. Action replies include a fresh page snapshot (includeSnapshot: falseto skip); onstale_ref, callsnapshot_pageagain.
Resources (subscribable)
mockpro:rule://{id},mockpro:logs://recentmockpro:console://{tabId}+mockpro:console://activealiasmockpro:network://{tabId}+mockpro:network://activealiasmockpro:websocket://{tabId}+mockpro:websocket://activealias
--readonly de-registers all write tools at the MCP capability level (debug observation tools stay available).
import_rulesmerge caveat:mergeupserts by reading then writing, non-atomically. Under interleaved writes from another tab/the Dashboard/a parallel client it can degrade to append. Serialize MCP writes client-side, or usereplace/appendwhen atomicity matters.
Debug tools require a freshly-loaded tab. Content script is injected at page load; tabs opened BEFORE you installed/reloaded the extension return
tab_no_injector. Reload those tabs once.
WebSocket buffer is chatty. Terminals fire 10-20 frames/sec; per-tab cap 500 fills in ~30s. Read with
sinceTsorclear_websocket_logsbetween snapshots.
Native passthrough compatibility: MockPro records lifecycle and inbound frames without replacing a real socket's
sendmethod. Outboundmessage-outentries are therefore available for mocked sockets only.
CLI flags
--extension-id <id> MockPro extension id (or env MOCKPRO_EXTENSION_ID). Required.
--readonly Refuse all write tools.
--approve Require in-browser approval for page-driving actions.
--allow-pattern <regex> Only allow add/update/import for rules whose urlPattern matches.
--redact-headers <list> Extra header names to redact, comma-separated.
--config <path> JSON config file (CLI > env > file > defaults).
-h, --helpstdout is reserved for MCP JSON-RPC frames; all logs go to stderr. redactionDisabled is config-file-only.
Threat model
The WS transport is designed for a trusted single-user host (your personal dev machine):
- Binds
127.0.0.1only — not reachable from the network. - Accepts exactly one Origin:
chrome-extension://<your extension id>. HTTPS pages can't reach it (Chrome blocks mixed-contentws://); HTTP pages sendOrigin: nulland are rejected. - MCP peer processes do not connect to the public WebSocket. They use a random-token-authenticated private IPC endpoint; its descriptor is stored under the current user's
.mockprodirectory with owner-only permissions where supported. - Not recommended on shared/multi-user hosts (terminal servers, multi-tenant dev VMs): any local user can reach
127.0.0.1:27319. Per-UID isolation is planned for a later release.
The extension re-validates every frame type and re-enforces --readonly at its own boundary (it does not trust the daemon).
Migrating from v2.x
v3.0 removes the Native Messaging (--transport=native) and CDP (--transport=cdp) transports and the install-host command. See CHANGELOG.md for the full list and cleanup commands (removing the stale Native Messaging manifest).
Local development
pnpm install && pnpm build # at repo root → extension dist/
cd mockpro-mcp
pnpm install && pnpm build # compile mockpro-mcp/dist/
pnpm test # unit tests (no Chrome required)
pnpm run test:e2e # real-Chrome E2E — needs Chrome for Testing + ../dist/ builttest:e2e is not run in CI. It requires Chrome for Testing (Chrome stable 148+ blocks --load-extension); resolve it via MOCKPRO_CHROME_BIN or npx @puppeteer/browsers install chrome.
License
MIT — see the root LICENSE file.
