# web-dev-mcp

An MCP (Model Context Protocol) server that gives AI coding agents a framework-aware toolkit for
web development: project/dependency workflow (install, dev server, lint, test, build), and
code/project scaffolding, with first-class support for **Laravel**, **CodeIgniter 4**,
**React**, **Vue**, and **Nuxt**, plus detection stubs for **Django**, **Rails**, and **Symfony**
— including combined backend+frontend setups.

See [`PLAN.md`](./PLAN.md) for the full design and roadmap. This README covers what's
implemented today and how to run it.

## Implementation status

Implemented **v1** (PLAN.md milestones 1–14) plus post-v1 **v1.1–v1.5**:

- **Framework detection & adapters** — `detect_framework` auto-detects Laravel (Sail-aware), CodeIgniter 4,
  Symfony, Django, Rails backends and React / Vue / Nuxt frontends, including a PHP/Python/Ruby
  backend + separate frontend living side-by-side (`frontend/`, `client/`, `web/`).
- **Core workflow tools** — `detect_framework`, `detect_workspace` (monorepo package scan),
  `run_install`, `run_script`, `start_dev_server` (Sail `up` when present), `stop_process`,
  `get_process_logs`, `list_processes`, `run_lint`, `run_tests`, `build_project`,
  `deploy_project` (opt-in `confirm: true`; optional `registryPush`). Most workflow tools accept
  an optional `package` argument to scope to a monorepo package.
- **Scaffolding tools** — `scaffold_project` (vite-react, vite-vue, next, express-api,
  static-html, laravel, codeigniter, laravel-react, codeigniter-react), `generate_component`
  (React TSX/JSX or Vue SFC), `generate_api_route`, `add_dependency`.
- **Laravel tools** — `artisan` (allow-listed subcommands; destructive ones need `confirm: true`;
  `queue:work`/`queue:listen`/`reverb:start` run as tracked background processes), `generate_laravel_resource`,
  `generate_eloquent_relation`, `generate_filament_resource`, `generate_nova_resource`, `laravel_queue_status`,
  `composer_require` / `composer_remove` (shared with CodeIgniter backends), `run_phpunit` /
  `run_pest`, `laravel_tinker_eval` (write-looking expressions need `confirm: true`).
- **CodeIgniter tools** — `spark` (allow-listed subcommands; `migrate:refresh` needs
  `confirm: true`), `spark_discover`, `generate_codeigniter_resource` (optional `apiVersion` /
  ResourceController), `generate_codeigniter_shield_auth` (`confirm: true`), `run_codeigniter_tests`.
- **Django / Rails / Symfony** — `generate_django_resource`, `generate_rails_resource`,
  `generate_symfony_resource` (file-based stubs).
- **React tools** — `generate_react_hook`, `add_react_route` (Next.js / react-router /
  TanStack Router), `generate_next_page` / `generate_next_layout` (App Router), `run_react_tests`,
  `analyze_react_component` (incl. missing `"use client"` / server→client prop heuristics).
  `generate_component` supports `clientComponent: true`.
- **Browser tools** — `browser_navigate`, `browser_screenshot`, `browser_screenshot_baseline`,
  `browser_visual_diff`, `browser_get_console_logs`, `browser_inspect_dom`, `browser_click`,
  `browser_fill`, `browser_eval` (Playwright-backed; Chromium binaries via `npx playwright install chromium`).
- **Git helpers** — `git_status`, `git_diff`, `git_diff_summarize`, `git_log`, `git_branch` (create needs
  `confirm: true`), `git_commit` (`confirm: true`; no amend/force/push).
- **Lighthouse audit** — `lighthouse_audit` (category details, opportunities, `failingByCategory`).
- **Prompts** — `new-feature`, `new-laravel-resource`, `new-codeigniter-resource`, `new-react-component`,
  `visual-diff-ci`.
- **Docker tools** — `docker_build_image`, `docker_run_container` (with workspace-confined volume
  mounts, image allow-list, and resource limits), `docker_list_containers`, `docker_get_container_logs`,
  `docker_exec`, `docker_stop_container`, `docker_remove_container`, `docker_compose_up`,
  `docker_compose_down`, `generate_dockerfile`, `generate_compose`, `generate_sail` (`confirm: true`),
  `docker_push_image` (`confirm: true`).
- **Docs & package lookup** — `search_package_docs` (npm README via unpkg, Composer metadata via
  Packagist), `search_mdn`, `search_laravel_docs`, `search_codeigniter_docs`, `get_package_info`.
- **Resources & prompts** — `workspace://project.json`, `workspace://logs/{processId}`,
  `workspace://containers/{containerId}/logs`, and reusable prompts `new-feature`,
  `new-laravel-resource`, `new-codeigniter-resource`, `new-react-component`.
- **Safety** — every filesystem path is confined to `WORKSPACE_ROOT`
  (`src/lib/sandbox.ts`), spawned binaries are restricted to an allow-list, and
  destructive ops (`deploy_project`, `composer_remove`, `migrate:fresh`, `migrate:refresh`,
  `git_commit`, …) require an explicit `confirm: true`. Docker containers are tracked and
  force-removed on server shutdown.
- **Both transports work today**: stdio (for Cursor/Claude Desktop) and Streamable HTTP (for
  remote/shared use), sharing one `createServer()` implementation. The HTTP transport includes
  bearer-token auth and a production-ready `Dockerfile`.
- **Automated test suite** — Vitest tests for sandbox/path confinement, binary allow-list,
  process management, Laravel/CodeIgniter subcommand allow-lists, destructive-command `confirm: true`
  enforcement, Docker guardrails, framework detection, baselines/visual diff, and Lighthouse parsing.
- **Distribution-ready** — install via `npx web-dev-mcp` or add to your MCP client config.

Post-v1 roadmap (see `PLAN.md` §9): **v1.4** Vue/Nuxt adapters, **v1.5** Sail/polish.

## Requirements

- Node.js >= 18.17 (developed/tested on Node 24)
- For Laravel/CodeIgniter tools: PHP + Composer on `PATH`
- For scaffolding Laravel/CodeIgniter projects: Composer on `PATH`
- For browser tools: `npx playwright install chromium` (run once after `npm install`)
- For Docker tools: Docker Engine (Docker Desktop or `dockerd`) running and accessible to the current user
- For `lighthouse_audit`: Chrome/Chromium available (Lighthouse is pulled via `npx` on demand)
- For git tools: `git` on `PATH` and a git workspace under `WORKSPACE_ROOT`

## Setup

```bash
npm install
npm run build
```

## Running tests

```bash
npm run test
```

## Running

**stdio** (what Cursor/Claude Desktop use):

```bash
npm run dev            # ts-node/tsx, no build step needed
# or, after `npm run build`:
npm start
```

**Streamable HTTP** (remote/shared use):

```bash
npm run build
npm run start:http
```

Environment variables:

| Variable | Default | Purpose |
|---|---|---|
| `WORKSPACE_ROOT` | current working directory | The project root every tool is confined to. |
| `MCP_HTTP_HOST` | `127.0.0.1` | Host the HTTP transport binds to. |
| `MCP_HTTP_PORT` | `3939` | Port the HTTP transport binds to. |
| `MCP_HTTP_TOKEN` | _(unset)_ | Bearer token required on `/mcp` when set. **Required** if binding to a non-localhost host. |

**Docker / containerization**:

```bash
docker build -t web-dev-mcp .
docker run -p 3939:3939 -e MCP_HTTP_TOKEN=change-me -v /path/to/project:/workspace web-dev-mcp
```

The image exposes the Streamable HTTP transport on port `3939` and uses `/workspace` as the confined `WORKSPACE_ROOT`. The `Dockerfile` uses a multi-stage build so the final image only contains production dependencies plus the compiled `dist/` directory.

## Using it from Cursor

Add to your MCP config (Cursor Settings → MCP, or `.cursor/mcp.json`):

```json
{
  "mcpServers": {
    "web-dev": {
      "command": "node",
      "args": ["/path/to/web-dev-mcp/dist/transports/stdio.js"],
      "env": { "WORKSPACE_ROOT": "${workspaceFolder}" }
    }
  }
}
```

### Published npm package (recommended)

```json
{
  "mcpServers": {
    "web-dev": {
      "command": "npx",
      "args": ["-y", "web-dev-mcp"],
      "env": { "WORKSPACE_ROOT": "${workspaceFolder}" }
    }
  }
}
```

### Claude Desktop config

Add to `claude_desktop_config.json`:

```json
{
  "mcpServers": {
    "web-dev": {
      "command": "npx",
      "args": ["-y", "web-dev-mcp"],
      "env": { "WORKSPACE_ROOT": "/path/to/your/project" }
    }
  }
}
```

### Local checkout

```json
{
  "mcpServers": {
    "web-dev": {
      "command": "node",
      "args": ["/path/to/web-dev-mcp/dist/transports/stdio.js"],
      "env": { "WORKSPACE_ROOT": "${workspaceFolder}" }
    }
  }
}
```

## Project layout

```
src/
  config.ts               # env vars, allow-lists, timeouts
  server.ts                # createServer(): registers all tools/resources
  transports/
    stdio.ts               # stdio entrypoint (bin)
    http.ts                # Streamable HTTP entrypoint
  lib/
    logger.ts              # stderr-only logging (stdout is reserved for JSON-RPC)
    sandbox.ts              # workspace path confinement + binary allow-list
    runCommand.ts           # foreground command execution with capped output
    processManager.ts       # tracks background processes (dev servers, backgrounded scripts)
    strings.ts               # pascal/camel/kebab-case helpers for codegen
    frameworks/
      types.ts               # FrameworkAdapter interface
      detect.ts               # workspace inspection -> detected adapter(s)
      resolve.ts               # picks backend/frontend/primary adapter for a tool call
      generic.ts, react.ts, vue.ts, djangoRailsSymfony.ts, laravel.ts, codeigniter.ts, phpBase.ts
      packageManager.ts, composer.ts   # npm/pnpm/yarn/bun and Composer helpers
  tools/
    shared.ts                # zod schema + result helpers shared by tools
    workflow/                # detect_framework, run_install, run_script, start_dev_server,
                              # stop_process, get_process_logs, list_processes, run_lint,
                              # run_tests, build_project, deploy_project
    scaffold/                # scaffold_project (+ templates/), generate_component,
                              # generate_api_route, add_dependency
    laravel/                 # artisan, generate_laravel_resource, composer_require/remove,
                              # run_phpunit/run_pest, laravel_tinker_eval
    codeigniter/             # spark, generate_codeigniter_resource, run_codeigniter_tests
    react/                   # generate_react_hook, add_react_route, run_react_tests,
                              # analyze_react_component
    browser/                 # browserManager, navigate, screenshot, consoleLogs,
                              # inspectDom, interact
    docker/                  # dockerManager, buildImage, runContainer, listContainers,
                              # containerLogs, exec, stopRemove, compose
    docs/                    # searchPackageDocs, searchMdn, searchLaravelDocs,
                              # searchCodeIgniterDocs, getPackageInfo
    git/                     # git_status, git_diff, git_log, git_branch, git_commit
    audit/                   # lighthouse_audit
    resources/               # process/container log resources
    prompts/                 # new-feature / laravel / codeigniter / react prompts
```

Screenshot baselines for `browser_visual_diff` are stored under `.web-dev-mcp/baselines/` inside
the workspace (you may commit them for CI, or ignore them locally).

## Publishing

```bash
npm run build
npm run test
npm version <patch|minor|major>
npm publish
```

The package is published as `web-dev-mcp` and exposes `dist/transports/stdio.js` as the `bin` entry,
so `npx web-dev-mcp` launches the stdio transport directly.
