Skip to main content
Glama

claude-preview-mcp

Dev-server lifecycle + Chrome browser automation, as an MCP server. The preview_* tool family that any MCP-compatible agent can use.

This is the Anthropic Claude_Preview plugin re-implemented as a standalone MCP server so it works in Claude Code, OpenCode, Kilo Code, and any other MCP-compatible agent — with one canonical launch.json per project.

The repo ships the patched-upstream source (TypeScript) + pre-built JS, so installs don't need a build step. A single install.sh handles all three target agents.


What you get

mcp__Claude_Preview__preview_* tools (14 total):

Tool

What it does

Browser?

preview_start

Spawn a dev server from .claude/launch.json (PID, ready detection, port inference)

preview_stop

SIGTERM / SIGKILL a running server

preview_list

List configured + currently-running servers

preview_logs

Last N lines of combined stdout+stderr (default 80, max 500)

preview_navigate

Open a URL in a headless Chrome

yes

preview_screenshot

PNG/JPEG screenshot, base64 inline or saved to disk

yes

preview_snapshot

A11y tree (tag, role, name, value, focusable)

yes

preview_inspect

DOM element by CSS selector (rect, attrs, text, display)

yes

preview_click

Click an element by CSS selector

yes

preview_fill

Fill an input/textarea/select by CSS selector

yes

preview_eval

Run JavaScript in the page, return JSON-serializable result

yes

preview_console_logs

Captured console messages (filter by substring or type)

yes

preview_network

List captured requests, or fetch one response body by URL

yes

preview_resize

Resize the preview viewport

yes

Browser-required tools use the system's Chrome (/Applications/Google Chrome.app on macOS, google-chrome / chromium on Linux).


Related MCP server: @nimbus21.ai/chrome-devtools-mcp

# 1. Clone
git clone https://github.com/MichaelTendoSsemwanga/claude-preview-mcp
cd claude-preview-mcp

# 2. Pick your agent
./scripts/install.sh claude-code   # one-line: plugin cache, plugin.json, done
./scripts/install.sh opencode      # ~/tools + ~/.config/opencode/opencode.jsonc
./scripts/install.sh kilo          # ~/tools + ~/.kilocode/mcp_settings.json
./scripts/install.sh all           # all three

install.sh:

  • Copies the committed build/ into the right agent location

  • Provisions node_modules/ (just @modelcontextprotocol/sdk + puppeteer-core, ~25MB) into the same location via a temp scratch dir — so the repo itself stays light

  • Writes / merges the MCP config (uses jq for an atomic JSON merge that preserves any existing config)

  • Restores .claude-plugin/plugin.json for Claude Code

Per-agent activate

Agent

Activate

Claude Code

restart; tools appear as mcp__Claude_Preview__preview_*

OpenCode

opencode mcp list → should show ✓ Claude_Preview connected

Kilo Code

VS Code: Cmd-Shift-P → "Developer: Reload Window"

  • One-line setup (drop the plugin into the cache, no MCP config to touch)

  • Plugin lifecycle is managed by Claude Code — auto-spawned on launch, auto-killed on exit

  • The plugin.json uses ${CLAUDE_PLUGIN_ROOT} so the install path is stable across moves/upgrades

  • Same launch.json file works in Claude Code's built-in preview (which uses the configurations format) AND this MCP

Why other agents

OpenCode and Kilo don't have a plugin system. They register MCP servers by hand-rolling a config file, and they don't ship a configurations preview concept. This MCP bridges that gap: they get the same dev-server workflow, using the same launch.json, just with the extra hop of an MCP server entry in their config.


.claude/launch.json (the only project-side file)

The MCP server reads dev-server definitions from <project>/.claude/launch.json, walking upward from the agent's process.cwd() until it finds one. Two formats supported, picked in priority order:

Claude Code format (preferred)

{
  "version": "0.0.0",
  "configurations": [
    {
      "name": "back-office",
      "runtimeExecutable": "npm",
      "runtimeArgs": ["run", "dev"],
      "port": 5173
    },
    {
      "name": "tkt-backend",
      "runtimeExecutable": "bash",
      "runtimeArgs": ["-c", "cd /Users/loft/tkt-backend && bun run --hot src/index.ts"],
      "port": 3001
    }
  ]
}

Fields: name, runtimeExecutable, runtimeArgs (array), port, autoPort (advisory), env (object), url (optional — overrides the synthesized http://localhost:{port}).

The MCP translates internally: runtimeExecutablecommand, runtimeArgsargs, porturl.

Legacy servers format (still supported)

{
  "servers": [
    {
      "name": "web",
      "command": "npm",
      "args": ["run", "dev"],
      "url": "http://localhost:3000",
      "readyPattern": "Local:"
    }
  ]
}

Use this if you have a project that already used it. Don't mix the two formats in the same file (only configurations is read when both are present).


Repo layout

claude-preview-mcp/
├── .claude-plugin/
│   └── plugin.json          # Claude Code plugin manifest
├── src/                     # TypeScript source (patches live here)
│   ├── index.ts             #   MCP server entry, tool definitions, handlers
│   ├── process-manager.ts   #   launch.json parser + dev-server spawn
│   ├── browser-manager.ts   #   headless Chrome session
│   └── schemas.ts           #   zod input schemas
├── build/                   # Pre-compiled JS (committed; don't need to build)
│   └── *.js, *.js.map
├── scripts/
│   └── install.sh           # Universal installer (claude-code | opencode | kilo | all)
├── docs/
│   └── ARCHITECTURE.md      # Claude Code plugin internals + MCP protocol details
├── package.json             # Name, deps, build script
├── package-lock.json        # Locked dep versions
├── tsconfig.json            # TS compiler config (Node16 ESM, strict)
├── .gitignore
├── LICENSE                  # MIT
└── README.md                # this file

Develop / rebuild

# Edit src/*.ts
npm install            # one time, fetches dev deps
npm run build          # tsc → build/
git add build/ src/    # commit both

The install script will use the freshly-built build/ on the next run.


Smoke test (any agent)

In the agent's session:

  1. mcp__Claude_Preview__preview_list → returns {configured: [...], running: []}

  2. mcp__Claude_Preview__preview_start {"name": "<one-of-your-configurations>"} → starts it

  3. mcp__Claude_Preview__preview_list → now shows it in running[]

  4. (browser) preview_navigate {"url": "http://localhost:5173"} then preview_snapshot

  5. preview_logs {"name": "<name>", "tail": 50} → see the dev-server output

  6. preview_stop {"name": "<name>"} → SIGTERM

Or from the shell, no agent needed:

node ./build/index.js &
sleep 1
# Talk JSON-RPC to stdin/stdout (use the test script in /tmp, or any MCP client)
kill %1

What's patched vs upstream

The Anthropic Claude_Preview plugin (this repo's source) ships with four bugs that surface under modern MCP clients (Claude Code, OpenCode 1.17+ — both use protocol 2025-11-25). All four are fixed in src/:

#

Symptom

Fix location

4a

preview_network schema malformed (anyOf at top level) → whole tool list rejected

src/index.ts

4b

Only reads legacy servers format, ignores Claude Code's configurations

src/process-manager.ts

4c

preview_eval "() => ({foo:1})" returns undefined → result validation fails

src/index.ts

4d

preview_screenshot returns invalid Base64 (Uint8Array.toString pitfall)

src/index.ts

4e

preview_fill "Illegal invocation" on non-input elements

src/index.ts

Each patch has an inline comment explaining the original cause. See docs/ARCHITECTURE.md for the long version with the diagnostic traces.


Caveats

  • One Chrome per MCP server. If you have this AND chrome-devtools-mcp registered, each spawns its own Chrome instance. Don't run both pointing at the same page.

  • One dev server per port. Two preview systems (Claude Code's built-in + this MCP) can't both bind the same port. Use one per project.

  • Process state isn't shared. Servers started via this MCP die when the MCP process exits. Claude Code's built-in preview is more durable.

  • launch.json walks up. If you run an agent from ~/ expecting project launch files, it won't — cd into the project root first.

  • Per-agent permissions. Most agents prompt on first tool use. Allowlist Claude_Preview (or each individual tool) to stop the prompts. The Kilo Code install includes an alwaysAllow block by default.

  • macOS Chrome path is hard-coded in browser-manager.ts (looks for /Applications/Google Chrome.app/Contents/MacOS/Google Chrome first, then google-chrome on PATH). Override with CHROME_PATH env var.


License

MIT — see LICENSE. Bundled dependencies (@modelcontextprotocol/sdk, puppeteer-core) retain their own licenses.

Related MCP Connectors

Related MCP Servers