# har-forensics-mcp Audit a `.har` capture from inside your editor. Other HAR tools show you a list of requests. This one answers the question you opened the file for: what leaked, who's on the page, and what to strip before you send it anywhere. Reads a file from local disk, computes, writes to stdout. **It makes no network calls**, which is the point: a real capture holds live session cookies, `Authorization` headers, and sometimes card numbers. Works with anything that speaks MCP over stdio — Cursor, Claude Code, Windsurf, Zed, VS Code Copilot. ## Setup **Claude Code:** ```bash claude mcp add --scope user har-forensics -- npx -y har-forensics-mcp ``` `--scope user` registers it for every directory. Without it the server is scoped to whichever directory you ran the command in — which still reports success, and then the tools are silently absent everywhere else. **Cursor** — `.cursor/mcp.json` in the project, or `~/.cursor/mcp.json` globally: ```json { "mcpServers": { "har-forensics": { "command": "npx", "args": ["-y", "har-forensics-mcp"] } } } ``` **Windsurf / Zed / VS Code Copilot** take the same `command` + `args` shape in their own MCP config files. Restart the editor, then point a tool at a capture: > Run `analyze_har` on `~/Downloads/checkout.har` Requires Node 20+. Nothing else — no clone, no build, no API key, no account. ## Tools | Tool | Answers | | --- | --- | | `find_captures` | "Where are my .har files?" — scans Downloads, Desktop, Documents, cwd, temp. | | `analyze_har` | "What's in this capture?" — triage overview, one verdict per check. **Start here.** | | `har_brief` | The full audit as redacted markdown. The artifact to quote or paste. | | `har_findings` | Findings, worst-first, filterable by severity. Paged. | | `har_vendors` | Every third party, scored 0–100 by blast radius, with an HTTP Archive scrutiny tier. | | `har_provenance` | Who loaded whom — the fourth parties your vendors brought with them. | | `har_perf` | "Why was this slow?" — slowest requests by dominant phase, per-origin handshake cost, uncompressed assets, time lost to redirects. | | `har_csp` | A starter Content-Security-Policy synthesized from observed traffic. | | `har_hunt` | Query requests — `is:thirdparty`, `status:>=400`, `type:script`, `host:…`. Returns entry indices. | | `har_entry` | Everything about one request: headers, cookies, body, timing phases. | | `har_curl` | That request as a runnable cURL or `fetch()`, credentials masked. | | `har_diff` | Before vs. after: what was added, what regressed, which third parties are new. | | `sanitize_har` | Write a `.redacted.har` safe to attach to a ticket. | `har_hunt` → `har_entry` → `har_curl` is the loop: find the request, read it, replay it. Every tool that returns a list takes a `limit` and tells you the total, so nothing silently returns a first page as if it were the whole answer. Every tool except `sanitize_har` is annotated `readOnlyHint`, and all of them are `openWorldHint: false` — the no-network guarantee below, in a form your client can read and act on rather than prose you have to take on trust. ## Three properties it inherits from the web app **No network.** The analyzers contain no `fetch`, and this transport does not add one. That invariant is the product — Cloudflare shipped a DLP profile in March 2026 that detects HAR files in HTTP traffic and lets admins block the upload outright, because unsanitized HARs are a known credential-exfiltration path. **Summaries, never dumps.** Every tool returns a rendered conclusion, not raw entries, and every list is bounded with its total stated. The captures this exists for run to tens of thousands of entries and hundreds of megabytes; handing an agent the entry list would blow its context and make it slower at a job the analyzers already did. (This was a promise the code broke until 0.2.0 — `har_findings` had no cap and returned ~93,000 tokens on a 10,000-entry capture. The 27-entry demo returned ~175, which is exactly why it went unnoticed.) **Redacted by default.** `har_brief` and `har_findings` route through the same redactor the browser export uses, built from a single shared secret-pattern table. An agent reading a capture in an editor is *more* likely to paste a finding into a chat window than a human with a download folder. ## What it will not do - **Overwrite anything.** `sanitize_har` refuses to write over an existing target or the original capture. - **Read a file above ~512 MB.** Guarded rather than left to OOM — pinned just under V8's maximum string length, since the file is read as one string. - **Answer a query it did not understand.** A misspelled filter (`is:third-party`, `staus:404`) is an error, not an empty result. Those were the same response until 0.2.0, which meant a typo could report a capture clean. - **Judge time against your clock.** A HAR is a historical artifact, so token expiry is measured against each entry's `startedDateTime`. Comparing to `now` marks every token in a week-old capture as expired and buries the one that was genuinely dead when the browser sent it. ## Reading the code This package ships one file, `dist/server.js`. It is deliberately not minified — the build treats it as something a human debugging an editor integration will read far more often than something a machine will parse for size — so it is the same code a build would produce, already built. There is no separate source repository to clone; the shipped file is the artifact to audit. ## License MIT. Bundled vendor data is generated from [`third-party-web`](https://github.com/patrickhulce/third-party-web) — MIT, Copyright (c) 2017 Patrick Hulce, derived from HTTP Archive.