pigeon

pigeon

Forwards browser console errors, warnings, and unhandled rejections to Claude Code via MCP, enabling natural language debugging.

Category
访问服务器

README

🐦 Pigeon

<p align="center"> <img src="https://img.shields.io/badge/Pigeon-console%20errors%20%E2%86%92%20Claude%20Code-7C3AED?style=for-the-badge&logo=anthropic&logoColor=white" alt="Pigeon" /> </p>

<p align="center"> <a href="https://github.com/pepperonas/pigeon/actions/workflows/ci.yml"><img src="https://github.com/pepperonas/pigeon/actions/workflows/ci.yml/badge.svg" alt="CI" /></a> <a href="LICENSE"><img src="https://img.shields.io/badge/license-MIT-green.svg?style=flat-square" alt="License: MIT" /></a> <img src="https://img.shields.io/badge/version-0.1.0-blue.svg?style=flat-square" alt="Version" /> <img src="https://img.shields.io/badge/status-v1%20minimal-orange.svg?style=flat-square" alt="Status" /> <img src="https://img.shields.io/badge/PRs-welcome-brightgreen.svg?style=flat-square" alt="PRs welcome" /> </p>

<p align="center"> <img src="https://img.shields.io/badge/TypeScript-5.x-3178C6?style=flat-square&logo=typescript&logoColor=white" alt="TypeScript" /> <img src="https://img.shields.io/badge/Node.js-18%2B-339933?style=flat-square&logo=node.js&logoColor=white" alt="Node 18+" /> <img src="https://img.shields.io/badge/MCP-stdio-000000?style=flat-square&logo=anthropic&logoColor=white" alt="Model Context Protocol" /> <img src="https://img.shields.io/badge/WebSocket-ws-010101?style=flat-square&logo=socketdotio&logoColor=white" alt="WebSocket" /> </p>

<p align="center"> <img src="https://img.shields.io/badge/Chrome-Manifest%20V3-4285F4?style=flat-square&logo=googlechrome&logoColor=white" alt="Chrome MV3" /> <img src="https://img.shields.io/badge/bundler-esbuild-FFCF00?style=flat-square&logo=esbuild&logoColor=black" alt="esbuild" /> <img src="https://img.shields.io/badge/Claude%20Code-ready-D97757?style=flat-square&logo=claude&logoColor=white" alt="Claude Code" /> <img src="https://img.shields.io/badge/platform-localhost-lightgrey?style=flat-square" alt="localhost" /> </p>

Forward browser console errors straight to Claude Code — no more copy‑pasting stack traces. Pigeon captures console.error/console.warn, uncaught exceptions, unhandled promise rejections, and failed network requests (fetch/XHR) from your dev pages and exposes them to Claude Code over the Model Context Protocol (MCP). Minified stack traces are resolved back to original source via your dev server's source maps.

Browser page → Extension → WebSocket → Bridge server → MCP (stdio) → Claude Code

A browser extension can't talk to a CLI process directly, hence the chain. The bridge server is a single Node process that wears two hats: a WebSocket receiver for the extension, and an MCP stdio server for Claude Code.

Layout

pigeon/
  extension/   # Chrome Manifest V3 extension (TypeScript, esbuild)
  server/      # Node bridge: WebSocket server + MCP stdio server (TypeScript)
  README.md

What Claude gets

Tools

Tool Purpose
get_recent_errors({ limit?, level?, pageUrl?, since? }) Buffered errors, newest first; filter by level (error/warn/network), pageUrl substring, or since timestamp.
wait_for_next_error({ timeout_ms? }) Block until the next error arrives — “reproduce in the browser, then check.”
get_error_stats() Counts per level + newest/oldest timestamps.
clear_errors() Empty the buffer.
get_error_history({ limit?, level?, since? }) When PIGEON_DB is set. Query the on-disk history — spans restarts, beyond the 200-entry buffer.
reload_tab({ tabId? }) Reload a dev tab (active localhost tab by default) — re-trigger an error after a fix.
eval_in_page({ expression, tabId?, timeout_ms? }) Gated. Run JS in the page's MAIN world and return the result. Off unless explicitly enabled (see below).

Prompts (appear as slash-commands in Claude Code's / menu)

Prompt Purpose
analyze_browser_errors({ limit?, level?, pageUrl? }) Embeds the recent errors and asks for root‑cause analysis + concrete fixes.
fix_latest_error() Focuses on the single newest error (with its resolved stack) and proposes a fix.

Resources

Resource Contents
pigeon://errors Live JSON snapshot of the buffer.
pigeon://errors/{id}/screenshot JPEG of the page when an uncaught error fired.
pigeon://errors/{id}/dom outerHTML of the page at error time.

On uncaught errors / unhandled rejections, Pigeon also captures a screenshot (rate-limited, best-effort — the error's tab must be the visible one) and a DOM snapshot. Entries gain hasScreenshot/hasDom flags plus screenshotUri/domUri. Toggle this off in the popup ("Snapshots on errors"); console/network events never carry snapshots.

Each captured error carries level, message, stack, source, line, col, pageUrl, origin, timestamp, plus tabId/tabTitle (which tab it came from) and, for network events, status. When a source map is available, a resolvedStack field is added with the original file:line:col frames.

The server keeps a ring buffer of the latest 200 errors and deduplicates identical message+stack pairs seen within 2 seconds (collapsed into one entry with a count).


Setup

1. Build & start the bridge server

cd pigeon
npm run install:all      # installs server/ and extension/ deps
npm run build            # builds both

Start the bridge. Normally Claude Code launches it for you (see step 3) — but you can run it standalone for testing:

npm start                # = node server/dist/index.js

The bridge listens on ws://127.0.0.1:8765 for the extension and speaks MCP over stdio. All logs go to stderr (or $PIGEON_LOG_FILE) — never stdout, which is reserved for the MCP JSON‑RPC protocol.

Smoke‑test without the extension:

npm test                 # spawns the server, pushes a fake error, asserts the MCP tools
# or, against an already-running server:
npm --prefix server run test:client

2. Load the extension in Chrome

  1. Open chrome://extensions.
  2. Enable Developer mode (top right).
  3. Click Load unpacked and select pigeon/extension/dist.
  4. The 🐦 icon appears. Click it: the popup shows connection status, the number of buffered errors, and three toggles — forwarding on/off, Snapshots on errors, and Allow remote eval ⚠️ (for eval_in_page, off by default).

The extension only activates on http://localhost/* and http://127.0.0.1/* (your dev servers). It connects to the bridge automatically; if the bridge isn't running yet, it reconnects with exponential backoff and buffers errors in the meantime.

Rebuild after changes with npm run dev:extension (watch) or npm --prefix extension run build, then hit Reload on the extension card.

3. Register the MCP server with Claude Code

Use the absolute path to the built entry point. From the pigeon/ directory:

claude mcp add pigeon -- node "$(pwd)/server/dist/index.js"

Add -s user to register it globally (available in every project, not just this one) — recommended if you do web dev across several repos:

claude mcp add -s user pigeon -- node "$(pwd)/server/dist/index.js"

Or add it to a .mcp.json in your project:

{
  "mcpServers": {
    "pigeon": {
      "command": "node",
      "args": ["/Users/martin/claude/pigeon/server/dist/index.js"]
    }
  }
}

To enable the optional features, pass the env vars at registration. With the CLI:

claude mcp add pigeon \
  --env PIGEON_DB="$HOME/.pigeon/history.jsonl" \
  --env PIGEON_ALLOW_EVAL=1 \
  -- node "$(pwd)/server/dist/index.js"

…or in .mcp.json, add an "env" block alongside command/args:

"env": { "PIGEON_DB": "/abs/path/history.jsonl", "PIGEON_ALLOW_EVAL": "1" }

Then, inside Claude Code, verify with /mcp — you should see pigeon connected with its four tools and the pigeon://errors resource.


Using Pigeon in your Claude Code workflow

Once registered (ideally -s user, so it's there in every project) and the extension shows Connected, run your dev server on localhost and work as usual. Verify with /mcp (pigeon connected) and the popup's green dot.

Recipes

  • Reactive — “what's broken?” → “What errors are in the browser right now?” Claude calls get_recent_errors and reads the message + source-mapped stack (original file, not minified).
  • Repro-driven — the core loop. “I'll reproduce it, wait for the error.” Claude calls wait_for_next_error; you trigger it in the browser; it streams in and Claude fixes it. After the fix: “reload the tab” → reload_tab → wait again. That's edit → reload → verify without leaving the CLI.
  • Slash-commands. The prompts appear in the / menu: /analyze_browser_errors (group all current errors by root cause) and /fix_latest_error (focus the newest one).
  • Visual / state bugs. Uncaught errors carry a screenshot + DOM snapshot — “look at the screenshot from the last error” (pigeon://errors/{id}/screenshot and /dom).
  • Inspect live (opt-in). With eval enabled (see Browser control below): “evaluate window.__store.getState() in the page” → eval_in_page.
  • Recurring errors. With PIGEON_DB set: “has this error happened before?” → get_error_history (spans restarts).

Make it smoother

Let Claude reach for Pigeon on its own — add to a project's CLAUDE.md:

## Debugging
For runtime errors in the browser, use the `pigeon` MCP tools
(`get_recent_errors`, `wait_for_next_error`) instead of asking me to paste console output.

Skip permission prompts for the read-only tools — in settings.json:

{ "permissions": { "allow": [
  "mcp__pigeon__get_recent_errors",
  "mcp__pigeon__get_error_stats",
  "mcp__pigeon__wait_for_next_error",
  "mcp__pigeon__get_error_history"
] } }

Leave reload_tab, eval_in_page, and clear_errors to prompt.

One limitation

The bridge runs inside the Claude Code session and binds port 8765. With multiple Claude Code sessions open at once, the first owns the port; others still have the tools but get no browser feed. Fine for one-session-per-project work; for more, run the bridge as a standalone service.

Browser control & security

Pigeon can also drive the browser, so Claude can reproduce a bug rather than only read it:

  • reload_tab — always available; reloads the target tab.

  • eval_in_page — runs arbitrary JavaScript in the page. This is powerful and dangerous, so it is off by default behind a double opt-in — both must be true:

    1. Start the server with PIGEON_ALLOW_EVAL=1 (otherwise the tool isn't even exposed).
    2. Turn on "Allow remote eval ⚠️" in the extension popup (otherwise the extension refuses every eval command).

    It only targets localhost/127.0.0.1 tabs. Leave both off unless you actively want Claude to execute code in your dev page.

Configuration

Env var Default Where Meaning
PIGEON_WS_PORT 8765 server WebSocket port (must match the extension's WS_URL).
PIGEON_LOG_FILE — server If set, mirror stderr logs to this file.
PIGEON_SOURCEMAPS 1 server Set to 0 to disable source-map resolution of stacks.
PIGEON_ALLOW_EVAL — server Set to 1 to expose the eval_in_page tool (also needs the popup toggle).
PIGEON_DB — server Path to a JSONL file; enables persistent history + the get_error_history tool.

Changing the port? Update WS_URL in extension/src/background.ts and rebuild.

What's captured

  • Console: console.error / console.warn (wrapped, then passed through unchanged). The hooks are installed by a MAIN-world content script at document_start, so they run before any page script and catch even synchronous errors during initial load.
  • Uncaught exceptions (window error) and unhandled promise rejections.
  • Failed network requests: fetch and XMLHttpRequest responses with status ≥ 400 or a transport failure (status 0). Intentional aborts are ignored. Original semantics are preserved — Pigeon never swallows a response or rejection.

Notes & limits

  • Source maps are fetched from the dev server on demand and cached briefly (5 s, so hot-reloads stay accurate). Resolution is best-effort: no map → the raw stack is kept.
  • Only localhost / 127.0.0.1 are matched, by design (your dev servers).
  • The MV3 service worker sleeps after ~30s idle; Pigeon reconnects on wake (incoming messages and a 30s alarms heartbeat) and persists the pending queue in chrome.storage.session, so errors aren't lost across an eviction.
  • One browser, one bridge: the buffer is shared across all matched tabs (filter with get_recent_errors({ pageUrl })).
  • History: with PIGEON_DB=/path/to/history.jsonl, new errors are appended as JSONL and reloaded on startup. The file is append-only and excludes screenshots/DOM (those stay in-memory only) — rotate or delete it yourself.
  • Lighthouse / performance metrics remain out of scope for now.

Development

# server
npm --prefix server run dev             # tsc --watch
npm --prefix server run test:e2e        # full MCP client/server smoke test
npm --prefix server run test:sourcemap  # source-map resolution test

# extension
npm --prefix extension run dev           # esbuild --watch
npm --prefix extension run typecheck     # tsc --noEmit
npm --prefix extension run test:unit     # pure serialization unit tests
npm --prefix extension run test:browser  # real-browser smoke test (loads the extension)

test:browser loads the built extension into Chrome for Testing (system Google Chrome blocks unpacked extensions). Install it once:

cd extension && node node_modules/playwright-core/cli.js install chromium

CI (.github/workflows/ci.yml) runs everything on each push: a build-test job (build, typecheck, unit + source-map + MCP E2E) and a browser-e2e job (real-browser smoke test). See CLAUDE.md for the architecture and the invariants worth not regressing.

推荐服务器

Baidu Map

Baidu Map

百度地图核心API现已全面兼容MCP协议,是国内首家兼容MCP协议的地图服务商。

官方
精选
JavaScript
Playwright MCP Server

Playwright MCP Server

一个模型上下文协议服务器,它使大型语言模型能够通过结构化的可访问性快照与网页进行交互,而无需视觉模型或屏幕截图。

官方
精选
TypeScript
Magic Component Platform (MCP)

Magic Component Platform (MCP)

一个由人工智能驱动的工具,可以从自然语言描述生成现代化的用户界面组件,并与流行的集成开发环境(IDE)集成,从而简化用户界面开发流程。

官方
精选
本地
TypeScript
Audiense Insights MCP Server

Audiense Insights MCP Server

通过模型上下文协议启用与 Audiense Insights 账户的交互,从而促进营销洞察和受众数据的提取和分析,包括人口统计信息、行为和影响者互动。

官方
精选
本地
TypeScript
VeyraX

VeyraX

一个单一的 MCP 工具,连接你所有喜爱的工具:Gmail、日历以及其他 40 多个工具。

官方
精选
本地
graphlit-mcp-server

graphlit-mcp-server

模型上下文协议 (MCP) 服务器实现了 MCP 客户端与 Graphlit 服务之间的集成。 除了网络爬取之外,还可以将任何内容(从 Slack 到 Gmail 再到播客订阅源)导入到 Graphlit 项目中,然后从 MCP 客户端检索相关内容。

官方
精选
TypeScript
Kagi MCP Server

Kagi MCP Server

一个 MCP 服务器,集成了 Kagi 搜索功能和 Claude AI,使 Claude 能够在回答需要最新信息的问题时执行实时网络搜索。

官方
精选
Python
e2b-mcp-server

e2b-mcp-server

使用 MCP 通过 e2b 运行代码。

官方
精选
Neon MCP Server

Neon MCP Server

用于与 Neon 管理 API 和数据库交互的 MCP 服务器

官方
精选
Exa MCP Server

Exa MCP Server

模型上下文协议(MCP)服务器允许像 Claude 这样的 AI 助手使用 Exa AI 搜索 API 进行网络搜索。这种设置允许 AI 模型以安全和受控的方式获取实时的网络信息。

官方
精选