request-finder
Enables Claude Code to search and inspect live network traffic from Chrome, including HTTP requests, WebSocket frames, and GraphQL calls, with tools to filter history, retrieve full request details, and control capture settings.
README
Netscribe
A Chrome (Manifest V3) extension that captures network traffic across your tabs and lets you search it with a query language — without opening DevTools.
Netscribe was formerly Request Finder — they're the same project. The old name is still the internal identifier throughout, and that's deliberate: it's what the MCP server is registered as and where the daemon keeps its state, so renaming it would break existing setups. Wherever you see
request-finder, read Netscribe:
Where Value MCP server id request-finder(inclaude mcp add)Daemon state ~/.request-finder/(token,history.db, logs)npm package / scripts request-finder,npm run bridge:uninstallExtension name in Chrome Request Finder
What it captures, across every tab, all the time:
- HTTP API calls — XHR/fetch and ordinary page loads: URL, method, status, headers, and timing.
- GraphQL — captured like any other HTTP call (typically
POST /graphql). Under Deep Capture its query and variables are searchable body text, sobody:will match an operation name. - RPC — JSON-shaped RPC (JSON-RPC, tRPC, Connect in JSON mode) is captured
in full, bodies included. Protobuf-shaped RPC (gRPC-Web, Connect in proto
mode) is captured too — URL, status, headers, timing — but its body is binary
protobuf, so
body:won't match it. - WebSockets — the handshake plus the individual frames sent and received (ADR 0006), including binary ones. RPC tunneled over a socket is searchable frame by frame.
Ask Claude about a request. With the bridge daemon running, Netscribe exposes your captured traffic to Claude Code over MCP — so you can ask "why did this call 401?" or "what changed between these two requests?" and Claude can read the real headers and bodies instead of guessing. Each request has a Request Ref you can paste to point Claude at one exact call. See Claude Code integration below.
The search UI lives in a dedicated full-tab page — click the Request Finder toolbar icon to open it.
Privacy note: Netscribe records request/response headers (including
Authorization,Cookie, API keys) and — under Deep Capture — request and response bodies, in plaintext IndexedDB on your machine. It is a personal debugging tool for your own traffic. Use the Discard list (domains never captured — the button right of Purge all), Pause, and Purge all guardrails, and the secret-masking toggle. Purge all clears the extension's history and, if you tick the box, the Claude/MCP daemon's history too (otherwise the daemon keeps its own copy — ADR 0008). Seedocs/adr/0003.
Install & build
A Makefile wraps the npm scripts, so building the extension is one command:
make # fresh build → dist/, ready to load unpacked
make wipes dist/, installs dependencies if a lockfile has moved, then runs
the typecheck and production build. Other targets (make help lists them all):
make dev # Vite + CRXJS watch build
make test # Vitest unit suite (parser, evaluator, index, IDB)
make test-e2e # Playwright smoke (builds first — it needs dist/)
make check # unit suite + a fresh build
make clean # drop build output; `make distclean` also drops node_modules
The underlying npm run build / npm test scripts still work if you prefer them.
Load the unpacked extension: chrome://extensions → Developer mode → Load
unpacked → select dist/.
Capture model
| Path | API | Scope | Captures | Cost |
|---|---|---|---|---|
| Metadata Capture | chrome.webRequest |
all tabs, always on | URL, method, headers, status, timing | silent |
| Deep Capture | chrome.debugger |
opt-in, per tab | the above + request/response bodies | shows a debugging banner; can't coexist with DevTools |
body: and response: only match Deep-Captured requests and degrade
gracefully on the rest (ADR 0001). Storage is a ring buffer (default 50k,
configurable) — the oldest request is evicted past the cap (ADR 0002).
<img width="2880" height="1534" alt="Screenshot_2026-07-20_blurred" src="https://github.com/user-attachments/assets/7a000901-479d-4369-8ae5-5119521c767f" />
Query language
method:POST has:authorization # space = AND
status:500 OR status:401 # explicit OR (binds looser than AND)
domain:slack.com -status:200 # '-' negates
(status:500 OR status:401) method:POST # parentheses group
| Operator | Meaning |
|---|---|
has:<name> |
header present (request or response) |
header:<name> |
header present (alias of has:) |
header:<name>=<value> |
header value contains <value> |
method:<m> |
exact method |
status:<spec> |
500, class 5xx, or comparison >=400 / <500 |
url:<substr> |
substring of the full request URL |
page:<substr> |
substring of the page URL the request fired from (live SPA route) |
domain:<host> |
host or any subdomain (slack.com matches api.slack.com) |
cookie:<name> |
cookie present in the request Cookie header |
tab:<substr> |
substring of the originating tab's title (as captured) |
is:ws / is:sent / is:received / is:http |
WebSocket frames (any / sent / received) or HTTP records |
body:"…" |
substring of the request body (HTTP, Deep Capture only) or a sent WS frame's payload (always captured) |
response:"…" |
substring of the response body (HTTP, Deep Capture only) or a received WS frame's payload (always captured) |
| bare word | substring across URL, headers, bodies, and frame payloads |
WebSocket messages are captured by default — a content script wraps
window.WebSocket (ADR 0006/0007), so frames are recorded with no debugger, no
banner, and even while DevTools is open. Deep Capture is not involved in
WS frames at all (it stays HTTP-only, for response bodies).
The Finder Page has a top-level Requests | WebSockets switch. The
WebSockets view shows frames only — ▲ WS sent / ▼ WS received — and the
search box takes the same operators: response:"chat_message" (received
payload), is:sent, domain:hiver.space, tab:outlook. The handshake itself
appears in the Requests view as a websocket request (recorded at the
101, since a live socket never "completes").
The content script must be in place before the page opens its socket, so reload the page once after installing/reloading the extension. Frames have their own ring-buffer budget (
maxFrames, default 100k) so a chatty socket can't evict HTTP history (maxRequests, default 50k).Heartbeat frames (JSON
{"type":"ping"}/"pong") are dropped at capture by default to cut noise and save the frame budget. The WebSockets toolbar has a Record pings checkbox to keep them.Binary frames are size-only by default. The Log binary checkbox captures their payloads — decoded as text when the bytes are valid UTF-8 (so text-as-Blob stays searchable), else base64 — capped at
maxBodyBytes. When off, the bytes aren't even read/encoded.
Matching is case-insensitive. Use "quotes" for values with spaces.
<img width="2880" height="1534" alt="Screenshot_2026-07-20_1525_blurred" src="https://github.com/user-attachments/assets/705d09f6-97af-4a86-b497-97b31aec654e" /> <img width="1440" height="767" alt="Screenshot 2026-07-20 at 15 21 39" src="https://github.com/user-attachments/assets/05702f6c-85a7-4270-9e71-ae9f7d6240b0" />
Architecture
service worker ── webRequest / debugger ──▶ IndexedDB (source of truth, ring buffer)
│ ▲
└── live feed (port) ──▶ Finder Page ── load ┘
│
├─ Web Worker: in-memory index (URL + headers
│ + structured fields), evaluates queries.
│ Body-dependent matches come back as
│ "needs body scan" …
└─ … which the page resolves (Pass 2) by
reading full records from IndexedDB.
The query evaluator is one three-valued (Kleene) function run twice: in the
Worker against in-RAM data (body text → MAYBE), then against full records from
IndexedDB to resolve the MAYBEs.
Layout
src/
background/ service worker: webRequest + debugger capture, batched IDB writes
shared/ types, IndexedDB layer, query engine (tokenizer→parser→evaluate)
worker/ in-memory RequestIndex + Worker entry
finder/ React full-tab UI (search, virtualized list, detail panel)
docs/adr/ architecture decision records
CONTEXT.md glossary (ubiquitous language)
Claude Code integration (bridge daemon)
A small always-on local daemon (bridge/) lets Claude Code watch traffic
live, query history, and act (toggle Deep Capture, pause, purge) over MCP.
The extension streams captures to it over a localhost WebSocket; the daemon
keeps its own durable SQLite history and exposes an MCP server. See ADR 0004.
extension SW ═══WS═══▶ bridge daemon ◀═══MCP/HTTP═══ Claude Code
◀══WS═══ (actions: deep-capture, pause, purge)
Setup
cd bridge && npm install # native better-sqlite3 build
cd .. && npm run bridge # starts the daemon on 127.0.0.1:8787
The daemon prints a token on first run (and on every start; it's stable,
stored at ~/.request-finder/token). Then:
- In the Finder Page → ⚙ Bridge → paste the token, set the URL
(
ws://127.0.0.1:8787/ws), and check Enable bridge. - Register with Claude Code (the daemon prints this exact line):
Or use the committedclaude mcp add --transport http request-finder http://127.0.0.1:8787/mcp \ --header "Authorization: Bearer <token>".mcp.jsonwithexport RF_BRIDGE_TOKEN=<token>.
MCP tools
| Tool | What it does |
|---|---|
requests_search |
search history with the query language (newest-first) |
request_get |
full record by Request Ref rid (the rf_… the UI's "Copy for Claude" yields) or seq |
requests_tail |
cursor long-poll for live watching (call in a loop) |
tabs_list |
tabs the extension sees + Deep Capture state |
stats |
counts, time range, connection + Deep Capture status |
deep_capture_set |
turn Deep Capture on/off for a tab (to see bodies) |
capture_set_paused |
pause/resume Metadata Capture |
history_purge |
wipe daemon + extension history (confirm: true) |
Security (ADR 0004): loopback bind only, a shared token on both the
WebSocket and every MCP call, and an Origin check that rejects web-page
WebSocket connections. The daemon serves captured secrets — keep the token
private; history_purge clears everything.
Always-on (macOS LaunchAgent)
Instead of npm run bridge each time, run the daemon at login and keep it
alive (deploy/com.requestfinder.bridge.plist, launched via
bridge/run-daemon.sh which resolves your nvm Node):
cp deploy/com.requestfinder.bridge.plist ~/Library/LaunchAgents/
launchctl load ~/Library/LaunchAgents/com.requestfinder.bridge.plist # starts now + every login
# stop/uninstall:
launchctl unload ~/Library/LaunchAgents/com.requestfinder.bridge.plist
Logs: ~/.request-finder/daemon.log (and daemon.err.log). On another machine,
edit the two absolute paths in the plist.
The watch-requests skill
.claude/skills/watch-requests/SKILL.md teaches Claude Code the common
workflows over these MCP tools — "tail any 5xx on the gmail tab", "find the
auth-bearing calls to api.slack.com and show me one", "deep-capture tab 42 and
inspect the failing response". It activates automatically when you ask for that
kind of thing (the request-finder MCP server must be registered).
Running it day-to-day
| Part | When | How |
|---|---|---|
| Extension | always (whenever Chrome runs) | Load unpacked from dist/ once; Chrome remembers it across reboots. After make, click ↻ on the extension card. The Finder Page (toolbar icon) works on its own. |
| Bridge daemon | only for Claude | LaunchAgent (above) runs it at login; or npm run bridge on demand. |
| Claude registration | once | claude mcp add … + paste the token into the extension's ⚙ Bridge panel. Persists. |
Uninstall / cleanup
Two separate stores:
- Extension data — cleared automatically by Chrome when you remove the extension (its IndexedDB + settings). Nothing to do.
- Bridge daemon — a separate local process + SQLite at
~/.request-finder, independent of the extension; uninstalling the extension does not touch it. The extension can't purge it on uninstall (no code runs then). Clean it one of two ways:- Before uninstalling: Purge all → tick Claude/MCP (daemon) history.
- Any time:
npm run bridge:uninstall— removes only Netscribe's own artifacts: its LaunchAgent, its running daemon (only if the process on :8787 is Netscribe's), and~/.request-finder(history.db, token, logs). It touches nothing else.
推荐服务器
Baidu Map
百度地图核心API现已全面兼容MCP协议,是国内首家兼容MCP协议的地图服务商。
Playwright MCP Server
一个模型上下文协议服务器,它使大型语言模型能够通过结构化的可访问性快照与网页进行交互,而无需视觉模型或屏幕截图。
Magic Component Platform (MCP)
一个由人工智能驱动的工具,可以从自然语言描述生成现代化的用户界面组件,并与流行的集成开发环境(IDE)集成,从而简化用户界面开发流程。
Audiense Insights MCP Server
通过模型上下文协议启用与 Audiense Insights 账户的交互,从而促进营销洞察和受众数据的提取和分析,包括人口统计信息、行为和影响者互动。
VeyraX
一个单一的 MCP 工具,连接你所有喜爱的工具:Gmail、日历以及其他 40 多个工具。
graphlit-mcp-server
模型上下文协议 (MCP) 服务器实现了 MCP 客户端与 Graphlit 服务之间的集成。 除了网络爬取之外,还可以将任何内容(从 Slack 到 Gmail 再到播客订阅源)导入到 Graphlit 项目中,然后从 MCP 客户端检索相关内容。
Kagi MCP Server
一个 MCP 服务器,集成了 Kagi 搜索功能和 Claude AI,使 Claude 能够在回答需要最新信息的问题时执行实时网络搜索。
e2b-mcp-server
使用 MCP 通过 e2b 运行代码。
Neon MCP Server
用于与 Neon 管理 API 和数据库交互的 MCP 服务器
Exa MCP Server
模型上下文协议(MCP)服务器允许像 Claude 这样的 AI 助手使用 Exa AI 搜索 API 进行网络搜索。这种设置允许 AI 模型以安全和受控的方式获取实时的网络信息。