dev-tools
by briancox730
README.md
# dev-tools-mcp
[](https://github.com/briancox730/dev-tools-mcp/actions/workflows/ci.yml)
[](./LICENSE)
An MCP ([Model Context Protocol](https://modelcontextprotocol.io)) stdio server that gives Claude Code - or any MCP client - five structured development tools:
| # | Tool | What it does |
|---|------|-------------|
| 1 | `run_e2e_tests` | Runs Playwright tests, starts the dev server, returns pass/fail per test |
| 2 | `execute_sql_as_role` | Executes SQL as a Postgres role with JWT claims - verifies Supabase RLS |
| 3 | `typecheck` | Runs `tsc --noEmit`, returns structured errors (file, line, code, message) |
| 4 | `npm_run` | Runs any npm script, parses Vitest/Jest output into structured results |
| 5 | `nextjs_build` | Runs `next build`, returns structured errors + page list with sizes |
## Prerequisites
- **Node.js** ≥ 18
- **Claude Code** installed
- For the RLS tool: **psql** on your PATH and a running Supabase/Postgres instance
## Quick start
```bash
# 1. Clone the repo
git clone https://github.com/briancox730/dev-tools-mcp.git
cd dev-tools-mcp
# 2. Install dependencies
npm install
# 3. Build
npm run build
# 4. Register with Claude Code (local scope - this project only)
claude mcp add --transport stdio dev-tools -- node /absolute/path/to/dev-tools-mcp/build/index.js
# OR register globally (available in all projects)
claude mcp add --transport stdio --scope user dev-tools -- node /absolute/path/to/dev-tools-mcp/build/index.js
```
## Alternative: edit `.claude.json` directly
Add this to the `mcpServers` key in `~/.claude.json` (global) or `.claude.json` in your project root:
```json
{
"mcpServers": {
"dev-tools": {
"type": "stdio",
"command": "node",
"args": ["/absolute/path/to/dev-tools-mcp/build/index.js"]
}
}
}
```
Then restart Claude Code.
## Verify it's working
Inside Claude Code, run `/mcp` - you should see `dev-tools: connected` with 5 tools listed.
## Tool details
### 1. `run_e2e_tests` - Playwright E2E runner
Runs Playwright with the JSON reporter and parses results into structured output.
**Inputs:**
- `project_dir` (required) - absolute path to your project
- `test_pattern` - glob or file path to filter, e.g. `"tests/auth.spec.ts"`
- `headed` - run in headed mode (default: false)
- `start_server` - use Playwright's webServer config (default: true)
- `timeout_seconds` - kill after this many seconds (default: 120)
**What you get back:**
```json
{
"success": true,
"summary": { "passed": 8, "failed": 1, "skipped": 0, "total": 9 },
"tests": [
{ "name": "Auth > should redirect unauthenticated users", "status": "passed", "duration_ms": 1200 },
{ "name": "Auth > should show dashboard after login", "status": "failed", "duration_ms": 3400, "error": "Expected element to be visible..." }
]
}
```
**Tip:** Make sure your `playwright.config.ts` has a `webServer` section so Playwright auto-starts your dev server:
```ts
export default defineConfig({
webServer: {
command: 'npm run dev',
port: 3000,
reuseExistingServer: !process.env.CI,
},
});
```
### 2. `execute_sql_as_role` - Supabase RLS tester
Executes SQL as a specific Postgres role with JWT claims, then rolls back. Never mutates data.
**Inputs:**
- `connection_string` (required) - e.g. `"postgresql://postgres:postgres@localhost:54322/postgres"`
- `sql` (required) - the query to run
- `role` - Postgres role (default: `"authenticated"`)
- `user_id` - UUID set as `auth.uid()`
- `claims` - additional JWT claims, e.g. `{ "app_role": "parent" }`
**Example prompt for Claude Code:**
> "Run `SELECT * FROM children` as an authenticated parent user with id `abc-123` and confirm they can only see their own children."
**What you get back:**
```json
{
"success": true,
"role": "authenticated",
"user_id": "abc-123",
"query": "SELECT * FROM children",
"rows": [["id-1", "abc-123", "Alice"], ["id-2", "abc-123", "Bob"]],
"row_count": 2
}
```
### 3. `typecheck` - TypeScript checker
Runs `tsc --noEmit` and parses the output into structured errors.
**Inputs:**
- `project_dir` (required)
- `tsconfig` - relative path to tsconfig (default: `"tsconfig.json"`)
- `files` - check only specific files
**What you get back:**
```json
{
"success": false,
"error_count": 2,
"errors": [
{ "file": "src/utils.ts", "line": 42, "column": 5, "code": "TS2345", "message": "Argument of type 'string' is not assignable..." },
{ "file": "src/api.ts", "line": 18, "column": 12, "code": "TS2339", "message": "Property 'foo' does not exist on type..." }
]
}
```
### 4. `npm_run` - Structured npm script runner
Runs any npm script with `CI=true` and `FORCE_COLOR=0`, then parses Vitest/Jest output.
**Inputs:**
- `project_dir` (required)
- `script` (required) - e.g. `"test"`, `"test:unit"`, `"lint"`
- `args` - extra args passed after `--`
- `env` - extra environment variables
**What you get back:**
```json
{
"success": false,
"exit_code": 1,
"script": "test",
"summary": { "total_tests": 14, "passed_tests": 12, "failed_tests": 2 },
"file_results": [
{ "file": "src/auth.test.ts", "status": "failed", "tests_failed": 2 },
{ "file": "src/utils.test.ts", "status": "passed", "tests_passed": 5 }
],
"raw_stdout": "..."
}
```
### 5. `nextjs_build` - Next.js build validator
Runs `next build` in production mode and parses errors and page output.
**Inputs:**
- `project_dir` (required)
- `env` - extra env vars for the build
- `timeout_seconds` - (default: 180)
**What you get back:**
```json
{
"success": true,
"error_count": 0,
"errors": [],
"pages": [
{ "path": "/", "size_kb": 5.42, "type": "static" },
{ "path": "/dashboard", "size_kb": 12.1, "type": "dynamic" },
{ "path": "/api/auth", "size_kb": 0, "type": "ssr" }
],
"build_duration_ms": 24500
}
```
## Development
```bash
# Watch mode
npm run watch
# Run the unit tests (Vitest)
npm test
# Test interactively with the MCP Inspector
npm run inspect
```
### Tests
The output parsers are the trickiest, most regression-prone part of the codebase.
They turn free-form Vitest/Jest/`tsc`/`next build` console output into structured
JSON. Those pure functions are unit-tested with [Vitest](https://vitest.dev) under
[`test/`](./test); run them with `npm test`. CI (see
[`.github/workflows/ci.yml`](.github/workflows/ci.yml)) runs `npm ci`, the
TypeScript build, and the test suite on Node 20 and 22 for every push and pull
request.
## Customization ideas
- **Add a `lint` tool** that parses ESLint JSON output
- **Add a `prisma_migrate` tool** for structured migration status
- **Add a `docker_compose` tool** to manage test containers
- **Wire the RLS tool to Supabase CLI** (`supabase db test`) instead of raw psql
## License
[MIT](./LICENSE) © 2026 Brian Cox
TDQS
A3.7/5.0
Scored across 5 tools
Disambiguation4/5
每个工具针对开发流程的不同方面: 端到端测试, SQL角色执行, 类型检查, 运行脚本, 构建。npm_run可以运行任意脚本, 包括测试, 但run_e2e_tests专门用于Playwright, 因此边界相对清晰。少数可能重叠, 但描述有帮助。
Naming Consistency3/5
命名模式部分一致: 有些工具使用动词开头(run_e2e_tests, execute_sql_as_role), 而其他使用名词开头(npm_run, nextjs_build)或单词(typecheck)。虽然每个名称都具描述性, 但顺序和风格并不统一。
Tool Count5/5
5个工具的数量非常适合开发工具服务器。每个工具都服务于核心开发任务, 没有冗余或过度精简, 范围恰当。
Completeness4/5
工具集覆盖了主要开发步骤: 测试, 类型检查, 构建, 运行脚本以及SQL安全验证。npm_run可以运行lint或单元测试等其他任务, 因此没有明显缺口, 但可能缺少如专门的格式或代码质量检查工具, 不过可通配。
Maintenance
ActivityMaintained
ResponsivenessNo issues