Browser debugging MCP server via Chrome DevTools Protocol — part of the khimaira workspace. Console, screenshots, React component tree, network, interaction.
Project description
Specter
The invisible observer.
Specter now ships inside khimaira as a workspace member at
packages/specter/. Its tools are re-registered on khimaira's MCP server under source-prefixed names (mcp__khimaira__specter_take_screenshot, etc.). The standalonespecter servepath below still works for backward compatibility.
Specter is a browser debugging MCP server that connects to Firefox via the Chrome DevTools Protocol (CDP) and gives AI assistants direct eyes into the browser: console logs, JavaScript exceptions, network activity, screenshots, DOM inspection, and runtime JS evaluation — all as MCP tools that Claude can call autonomously during debugging.
Built for Claude Code, but works with any MCP-compatible client.
Part of the khimaira workspace alongside Séance (semantic code search) and Scarlet (codebase cartography); Serena (LSP navigation, jeevy-only) is an independent MCP server.
Why "Specter"
From the Latin spectrum — "appearance, vision" — by way of specere, "to look at, observe." The word predates the ghost sense; at its root, a specter is an observer, something that sees from a vantage the living can't occupy.
That's the tool's function. A browser's internal state — console buffer, unhandled exceptions, network timing, React's fiber tree, Redux's store — is invisible during normal use. You can't look at it without special instruments. Specter is the instrument: it attaches to the browser over CDP and watches from a position the user can't reach, then reports back what it saw.
Literary resonances that reinforce it:
- Hamlet's ghost — returns to testify about what the living couldn't see. Specter does the same with exceptions and failed requests: bears witness to what went wrong when nobody was watching.
- "The ghost in the machine" (Gilbert Ryle, 1949) — an observer inside the mechanism. A near-literal description of a CDP client: a watcher embedded in the browser process.
- The gothic-novel specter — silently present, seeing everything, speaking only when summoned.
It completes the suite:
Séance summons what's hidden in the code.
Scarlet inscribes what Séance finds.
Specter watches what the code does when it's running.
Séance works on the source. Scarlet works on the structure. Specter works on the execution — the live evidence of what the code actually does, not what it was written to do.
The debugging loop
sequenceDiagram
participant U as You
participant C as Claude Code
participant S as Specter MCP
participant F as Firefox (dev)
U->>C: "the page looks broken"
C->>S: take_screenshot()
S->>F: Page.captureScreenshot
F-->>S: PNG data
S-->>C: /tmp/specter/screenshots/screenshot_20260411.png
C->>C: Read screenshot (multimodal) — sees broken layout
C->>S: get_console_logs(level="error")
S-->>C: [{level: "error", text: "Cannot read property 'map' of undefined", source: "QuoteDetails.js:247"}]
C->>S: get_network_errors()
S-->>C: [{method: "GET", url: "/api/v1/quotes/123", status: 500}]
C->>C: Reads QuoteDetails.js:247 — identifies the bug
C->>C: Fixes the code
C->>S: take_screenshot()
C->>C: Read screenshot — verifies the fix visually
C-->>U: "Fixed. The quotes API was returning null for line items..."
How it works
flowchart LR
F[Firefox<br/>--remote-debugging-port 9222] -->|CDP WebSocket| S[Specter MCP Server]
S --> A[Console Buffer<br/>log/warn/error/info]
S --> B[Exception Buffer<br/>unhandled errors + stacks]
S --> C[Network Buffer<br/>requests + responses]
S --> D[Runtime<br/>JS eval + screenshots + DOM]
CL[Claude Code] -->|MCP tools| S
CL -->|Read tool| E[Screenshots<br/>/tmp/specter/screenshots/]
Specter connects to Firefox's CDP endpoint over WebSocket, enables the Runtime, Network, and Page domains, and streams events into ring buffers. Claude queries the buffers on demand via MCP tools.
Prerequisites
Firefox must be launched with remote debugging enabled:
firefox --remote-debugging-port 9222
Or create an alias for development:
alias firefox-dev="firefox --remote-debugging-port 9222"
Installation
git clone git@github.com:fsocietydisobey/specter.git
cd specter
uv sync
No API keys required. Fully local.
CLI usage
# Check if Firefox is reachable
uv run specter status
# Print recent console logs
uv run specter logs
uv run specter logs --level error
# Take a screenshot
uv run specter screenshot
uv run specter screenshot --full # full scrollable page
uv run specter screenshot -s ".main-content" # specific element
# Start the MCP server
uv run specter serve
MCP integration
Claude Code
Register globally:
claude mcp add -s user specter -- uv --directory /path/to/specter run specter serve
Once registered, Claude gets these tools:
| Tool | What it does |
|---|---|
take_screenshot |
Capture page as PNG — Claude reads it with the Read tool (multimodal vision) |
get_console_logs |
Retrieve buffered console.log/warn/error/info output with source locations |
get_errors |
Retrieve unhandled JS exceptions with full stack traces |
get_network_errors |
Retrieve failed HTTP requests (4xx/5xx + network failures) |
get_network_log |
Retrieve all HTTP requests (for tracing API flow) |
evaluate_js |
Run JavaScript in the page and return the result |
get_page_info |
Current URL, title, document ready state |
get_dom_html |
Get rendered HTML of any CSS selector |
list_tabs |
List all open browser tabs with IDs, titles, URLs |
clear_logs |
Reset all event buffers (clean slate before reproducing a bug) |
Other MCP clients
{
"mcpServers": {
"specter": {
"command": "uv",
"args": ["--directory", "/path/to/specter", "run", "specter", "serve"]
}
}
}
What Claude can do with these tools
Visual debugging
Claude: take_screenshot() → reads the PNG → "I can see the sidebar is collapsed
and the main content area shows a loading spinner that never resolves"
Error diagnosis
Claude: get_errors() → "QuoteDetails.js:247 — Cannot read properties of null
(reading 'map'). The quoteData.bids array is null when the API returns an
empty quote. Fix: add a fallback: `(quoteData.bids ?? []).map(...)`"
API flow tracing
Claude: get_network_log(url_filter="/api/v1") → sees the exact sequence of
API calls, their status codes, and timing → "The /api/v1/quotes/123 call
returns 200 but the response is missing the `bids` field entirely"
Runtime state inspection
Claude: evaluate_js("JSON.stringify(window.__NEXT_DATA__.props)") → reads
the server-side props → "The SSR is passing projectId but not quoteId"
DOM verification
Claude: get_dom_html(".error-boundary") → sees the rendered error message →
"The error boundary caught the crash but is showing a generic message. The
actual error is in the console"
Architecture
graph TB
subgraph "src/specter/"
CLI[cli.py<br/>CLI entry point]
SRV[server.py<br/>MCP server — 10 tools]
CFG[config.py<br/>Config loader]
subgraph "browser/"
CONN[connection.py<br/>CDP WebSocket manager]
CON[console.py<br/>Console event buffer]
NET[network.py<br/>Network event buffer]
RT[runtime.py<br/>JS eval + screenshots + DOM]
end
end
CLI --> CONN & CON & RT
SRV --> CONN & CON & NET & RT
CON --> CONN
NET --> CONN
RT --> CONN
CFG -.->|port, screenshot dir| CONN & RT
Configuration
All via environment variables (no config file needed):
| Variable | Default | Description |
|---|---|---|
SPECTER_DEBUG_HOST |
localhost |
CDP host |
SPECTER_DEBUG_PORT |
9222 |
CDP port (must match Firefox's --remote-debugging-port) |
SPECTER_SCREENSHOT_DIR |
/tmp/specter/screenshots |
Where screenshots are saved |
SPECTER_MAX_BUFFER |
1000 |
Max buffered events per category |
The full MCP suite
| Tool | What it does | Mode |
|---|---|---|
| Serena | LSP-powered symbol navigation | Read (compiler-precise) |
| Séance | Semantic code search via embeddings | Read (semantic-fuzzy) |
| Scarlet | Structural doc generation | Write (cartography) |
| Specter | Browser debugging via CDP | Read (runtime) |
Together: Serena finds symbols, Séance finds concepts, Scarlet writes the docs, Specter watches the browser. Claude orchestrates all four.
Tech stack
- Chrome DevTools Protocol — browser communication (Firefox supports CDP experimentally)
- websockets — CDP WebSocket connection
- httpx — target discovery via
/jsonendpoint - MCP Python SDK — Model Context Protocol server
- Click — CLI framework
- uv — Package management
License
MIT
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
File details
Details for the file khimaira_specter-0.2.0.tar.gz.
File metadata
- Download URL: khimaira_specter-0.2.0.tar.gz
- Upload date:
- Size: 45.6 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: uv/0.11.12 {"installer":{"name":"uv","version":"0.11.12","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Arch Linux","version":null,"id":null,"libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":null}
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
5eb9ceaf7bc839687f49020859fdc2e9b50ced4be1743bddcf8d69a65fbc3c85
|
|
| MD5 |
8a74f17f47ca1762f3488347e6e0d58f
|
|
| BLAKE2b-256 |
77c374b34c50c2650205763b3299183a8040d18272bcd0924bd7459797a3da34
|