pickfix-mcp
v1.2.1
Published
Local MCP server that receives UI feedback from the Pickfix browser extension and hands it to your coding agent.
Downloads
605
Maintainers
Readme
pickfix-mcp
The local half of Pickfix. The Pickfix browser extension lets developers, QA and PMs pick an element on a running web app, say what is wrong (or rewrite the text in place, comment on the page, record the steps to a bug) and press Send to Claude. pickfix-mcp receives that feedback on your machine and hands it to the coding agent working on the repository, which fixes it and reports back to the extension.
Chrome: Pickfix extension ──WebSocket, 127.0.0.1──▶ pickfix-mcp ──MCP──▶ Claude Code
pick · comment · send (extension origin only) queue fixes the code
◀──────────────── Queued → Claude is fixing → Done, with a summary ─────────────────Quick start
Install the extension: Pickfix on the Chrome Web Store (in review; the link works once it is published).
Install the plugin in Claude Code, in your project:
/plugin marketplace add ledutu-studio/pickfix-mcp /plugin install pickfix@pickfixRestart Claude Code. The plugin starts one
pickfix-mcpserver per session.Open the Pickfix panel on a local page in Chrome. It finds every running session by itself; there is nothing to pair. If it does not, use Connect manually.
Then pick an element, write what should change and press Send to Claude. Requires Node.js 20 or newer.
Let Claude start fixing as soon as feedback arrives (optional)
Channels are a Claude Code research preview. To have a batch pushed straight into the session, start Claude with:
claude --dangerously-load-development-channels plugin:pickfix@pickfixClaude Code shows a warning first; choose I am using this for local development. A shell alias helps: alias claudefix='claude --dangerously-load-development-channels plugin:pickfix@pickfix'.
Without the flag everything still works: run /pickfix:fix when the extension shows Queued. A hook also reminds Claude of waiting feedback when you send a prompt.
Connect manually with a port
The extension looks for sessions on ports 47400–47409. When a session is not found there (all ten are taken, another program owns the range, or you started the server on a port of your own), connect to it by port:
- Ask the agent for the port: run the
pickfix_statustool (in Claude Code, ask "what is the Pickfix status?"). It printsExtension link: listening on ws://127.0.0.1:<port>/pickfix. - In the Pickfix panel choose Connect manually (on the No Claude Code session card, under the session list, or after Change), enter the port and press Connect. Pasting the whole
ws://127.0.0.1:<port>/pickfixaddress works too.
The session becomes the one this site sends to, and the extension remembers the port (the last five) and looks there again on every scan, so it reconnects after the session restarts on the same port. If the connection fails, the panel says why: nothing answered on that port, the server refused the handshake, or its version does not match the extension.
Choose the port: PICKFIX_PORT
Set PICKFIX_PORT to make the server listen on that port only, from 1024 to 65535, instead of the first free one of 47400–47409. A fixed port is handy when the default range is blocked or when you want the extension to reach a session at a port you know in advance.
PICKFIX_PORT=51234 claudeFor clients with an mcpServers JSON file, put it in env:
{
"mcpServers": {
"pickfix": { "command": "npx", "args": ["-y", "pickfix-mcp"], "env": { "PICKFIX_PORT": "51234" } }
}
}With PICKFIX_PORT the server does not fall back to another port: if the port is in use, or the value is not a valid port, pickfix_status says so and the extension link stays off until you restart the session with a free port. Give each session its own port; two sessions cannot share one. A port outside 47400–47409 is only found through Connect manually (once entered, the extension keeps scanning it).
Other agents (Cursor, Codex, Claude Desktop, …)
Run the server with npx -y pickfix-mcp as a stdio MCP server. For clients that use an mcpServers JSON file (Cursor's .cursor/mcp.json, Claude Desktop):
{
"mcpServers": {
"pickfix": { "command": "npx", "args": ["-y", "pickfix-mcp"] }
}
}Codex (~/.codex/config.toml):
[mcp_servers.pickfix]
command = "npx"
args = ["-y", "pickfix-mcp"]Start the client from your project folder: the server queues feedback per repository. These clients have no channel push: ask the agent to use the fix prompt, or to call pickfix_list_batches and follow the tool descriptions.
What the agent gets
| Tool | Purpose |
|---|---|
| pickfix_status | Session, repository, port (for Connect manually), batch counts |
| pickfix_list_batches | Queued and working batches (or by status) |
| pickfix_claim_batch | Claims a batch and returns its items as markdown plus screenshots and reference images |
| pickfix_report | Reports done / partial / failed with a summary and per-item results |
| pickfix_import | Queues a JSON file exported from the extension |
A batch can be claimed by one session only, so two Claude windows on the same repository never fix the same feedback twice.
Security model
- The server listens on
127.0.0.1only, on the first free port of 47400–47409 (or onPICKFIX_PORTwhen set), path/pickfix. Connecting manually to a port changes nothing below: the same checks apply on every port. - Plain HTTP requests get an empty
404with no CORS headers. The extension sendsHEAD /to each port it scans and opens a WebSocket only where something answers: Chrome slows every new WebSocket down for seconds once a few dozen have failed, so the scan must not fail with sockets. Keep this answer if you change the server. - A connection must come from the Pickfix extension (
Origin: chrome-extension://<Pickfix id>) to a loopbackHost; web pages, other extensions and DNS-rebinding hosts are refused at the handshake. Browsers do not let a page setOrigin, so this is the gate; there is no pairing step. Programs already running under your account can still connect, as they can to any local port. - Everything captured from a web page is passed to the agent as fenced, untrusted data with an instruction never to follow it.
- The server has no tool that runs commands or writes files in your repository; code changes go through your agent's normal permissions.
Full privacy policy (English and Vietnamese): PRIVACY.md.
Files
~/.pickfix/ 0700
queue/<repo-key>/<batch>/ batch.json, state.json, screenshots, reference imagesFinished batches are deleted after 7 days. Set PICKFIX_HOME to use another directory.
Protocol
The extension and server speak protocol 3 over WebSocket; the batch format is pickfix.batch/2. The original contract is section 5 of docs/specs/2026-10-02-pickfix-mcp-design.md; protocol 3's additions (regions, reference images, per-item viewport) are in the extension repo's docs/specs/2026-10-06-capture-upgrades-design.md. Types and schemas ship as @pickfix/protocol (packages/protocol).
| Direction | Messages |
|---|---|
| Server → extension | server.info, welcome, batch.accepted, batch.status, pong, error |
| Extension → server | hello, batch.submit, batch.watch, batch.cancel, ping |
Development
pnpm install
pnpm test # unit tests
pnpm test:e2e # builds, then drives plugin/dist/server.mjs end to end
pnpm build # rebuild plugin/dist (commit the result; a test checks it is fresh)
pnpm compile # type-check
pnpm --filter @pickfix/protocol build # build the protocol package the extension links toPICKFIX_EXTENSION_IDS=<id>[,<id>] allows extra extension ids, for unpacked builds made without the Pickfix key.
| Environment variable | Effect |
|---|---|
| PICKFIX_PORT | Listen on this port only (1024–65535) instead of the first free one of 47400–47409; see Connect manually |
| PICKFIX_HOME | Where the queue lives (default ~/.pickfix) |
| PICKFIX_EXTENSION_IDS | Extra extension ids allowed to connect, comma-separated |
The extension's id is its Chrome Web Store item id, eehanlcaccamfaalnfcikkdneffjkife. EXTENSION_PUBLIC_KEY in @pickfix/protocol is that item's public key (Developer Dashboard → Package → View public key); Google holds the private key, so nothing secret lives on a developer machine.
Release
From your machine, once main is pushed and CI passed:
pnpm release --dry-run # checks, starts nothing
pnpm release minor # patch (default) | minor | major; asks, then starts publish.yml and follows itpnpm release refuses a main whose CI did not pass (it skips [skip ci] release commits when looking), local commits that are not pushed, a release already running, a main with nothing new since the last tag, and a version npm already has. It never changes the version itself; the workflow below does. To ship this and the extension together, in the right order (this server first), run pnpm release in the pickfix repository (ledutu-studio/pickfix, the folder that holds both checkouts); its docs/release.md has the whole flow.
.github/workflows/ci.ymlruns on every push tomainand every pull request: type-check, unit tests (which also check thatplugin/distis fresh) and the end-to-end tests..github/workflows/publish.ymlruns only when started by hand (pnpm release, or Actions → publish → Run workflow) frommain. It bumps the version (patchby default, orminor/major) inpackage.json,plugin/.claude-plugin/plugin.jsonandsrc/version.ts, runs the checks, rebuildsplugin/dist, publishes to npm, then commitschore(release): <version>and tagsv<version>. Do not change the version by hand.- npm accepts the upload through trusted publishing, so no npm token is stored. One-time setup on npmjs.com:
pickfix-mcp→ Settings → Trusted publisher → GitHub Actions, repositoryledutu-studio/pickfix-mcp, workflowpublish.yml. - Optional secret
DISCORD_WEBHOOK_URLposts the result to Discord. - Claude Code plugin users do not wait for npm: the marketplace reads
plugin/frommain.
Tiếng Việt
Pickfix giúp dev frontend, QA và PM chỉ vào chỗ sai trên giao diện đang chạy, ghi cần sửa gì, rồi gửi thẳng cho Claude Code sửa trong source. pickfix-mcp là phần chạy trên máy bạn: nhận feedback từ extension qua 127.0.0.1 và chuyển cho Claude.
Cài extension: Pickfix trên Chrome Web Store (đang chờ duyệt).
Cài plugin trong Claude Code, ngay trong project của bạn:
/plugin marketplace add ledutu-studio/pickfix-mcp /plugin install pickfix@pickfixKhởi động lại Claude Code.
Mở panel Pickfix trên trang localhost. Panel tự tìm các session đang chạy, không cần ghép nối.
Kết nối thủ công bằng port: nếu panel không tự tìm thấy phiên (extension chỉ dò các port 47400–47409), chạy tool pickfix_status trong Claude Code để xem port (dòng ws://127.0.0.1:<port>/pickfix), rồi trong panel chọn Kết nối thủ công, nhập port và bấm Kết nối. Extension nhớ port này (tối đa 5 port gần nhất) và tự kết nối lại khi phiên khởi động lại. Muốn server chạy trên một port cố định, đặt biến môi trường PICKFIX_PORT (1024–65535), ví dụ PICKFIX_PORT=51234 claude; với file cấu hình mcpServers thì thêm "env": { "PICKFIX_PORT": "51234" }. Nếu port đó đang bị dùng, server không tự chọn port khác: pickfix_status sẽ báo lỗi để bạn đổi port.
Muốn Claude tự sửa ngay khi nhận feedback, mở Claude bằng claude --dangerously-load-development-channels plugin:pickfix@pickfix. Không dùng cờ này thì gõ /pickfix:fix khi panel hiện Đang chờ. Giao diện extension có tiếng Việt và tiếng Anh, đổi trong phần cài đặt của extension.
Phát hành phiên bản mới: sau khi push lên main và CI xanh, chạy pnpm release minor (hoặc patch, major; thêm --dry-run để chỉ kiểm tra). Script kiểm tra CI, commit chưa push, rồi chạy workflow publish.yml (bump version, đẩy lên npm, tag) và theo dõi tới khi xong. Không sửa version bằng tay. Muốn phát hành cả extension, chạy pnpm release trong repo pickfix (thư mục chứa cả hai repo; MCP trước, extension sau).
Cursor, Codex và các agent khác: thêm MCP server chạy npx -y pickfix-mcp (xem cấu hình ở trên). Chính sách quyền riêng tư: PRIVACY.md.
License
MIT. See LICENSE.
