Skip to main content
Glama

dev-tools-mcp

CI License: MIT

Claude Code — 또는 모든 MCP 클라이언트 — 에게 다섯 가지 구조화된 개발 도구를 제공하는 MCP(Model Context Protocol) stdio 서버입니다:

#

도구

기능

1

run_e2e_tests

Playwright 테스트를 실행하고, 개발 서버를 시작하며, 테스트별 통과/실패를 반환합니다

2

execute_sql_as_role

JWT 클레임이 있는 Postgres 역할로 SQL을 실행합니다 — Supabase RLS를 검증합니다

3

typecheck

tsc --noEmit을 실행하고, 구조화된 오류(파일, 줄, 코드, 메시지)를 반환합니다

4

npm_run

모든 npm 스크립트를 실행하고, Vitest/Jest 출력을 구조화된 결과로 파싱합니다

5

nextjs_build

next build를 실행하고, 구조화된 오류와 크기가 포함된 페이지 목록을 반환합니다

사전 요구 사항

  • Node.js ≥ 18

  • Claude Code 설치

  • RLS 도구의 경우: PATH에 psql이 있고 실행 중인 Supabase/Postgres 인스턴스가 있어야 합니다

Related MCP server: groundtruth-mcp

빠른 시작

# 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

대안: .claude.json 직접 편집

~/.claude.json(전역) 또는 프로젝트 루트의 .claude.json에 있는 mcpServers 키에 다음을 추가하세요:

{
  "mcpServers": {
    "dev-tools": {
      "type": "stdio",
      "command": "node",
      "args": ["/absolute/path/to/dev-tools-mcp/build/index.js"]
    }
  }
}

그런 다음 Claude Code를 다시 시작하세요.

작동 확인

Claude Code 내에서 /mcp를 실행하면 — dev-tools: connected와 함께 5개의 도구가 나열된 것을 볼 수 있습니다.

도구 세부 정보

1. run_e2e_tests — Playwright E2E 실행기

JSON 리포터로 Playwright를 실행하고 결과를 구조화된 출력으로 파싱합니다.

입력:

  • project_dir (필수) — 프로젝트의 절대 경로

  • test_pattern — 필터링할 glob 또는 파일 경로, 예: "tests/auth.spec.ts"

  • headed — 헤드 모드로 실행 (기본값: false)

  • start_server — Playwright의 webServer 구성을 사용 (기본값: true)

  • timeout_seconds — 이 시간(초) 후 종료 (기본값: 120)

반환되는 내용:

{
  "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..." }
  ]
}

팁: playwright.config.ts에 webServer 섹션이 있어야 Playwright가 개발 서버를 자동으로 시작합니다:

export default defineConfig({
  webServer: {
    command: 'npm run dev',
    port: 3000,
    reuseExistingServer: !process.env.CI,
  },
});

2. execute_sql_as_role — Supabase RLS 테스터

JWT 클레임이 있는 특정 Postgres 역할로 SQL을 실행한 다음 롤백합니다. 데이터를 변경하지 않습니다.

입력:

  • connection_string (필수) — 예: "postgresql://postgres:postgres@localhost:54322/postgres"

  • sql (필수) — 실행할 쿼리

  • role — Postgres 역할 (기본값: "authenticated")

  • user_id — auth.uid()로 설정되는 UUID

  • claims — 추가 JWT 클레임, 예: { "app_role": "parent" }

Claude Code용 예시 프롬프트:

"SELECT * FROM children을 id가 abc-123인 인증된 부모 사용자로 실행하고 자신의 자식만 볼 수 있는지 확인하세요."

반환되는 내용:

{
  "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 검사기

tsc --noEmit을 실행하고 출력을 구조화된 오류로 파싱합니다.

입력:

  • project_dir (필수)

  • tsconfig — tsconfig의 상대 경로 (기본값: "tsconfig.json")

  • files — 특정 파일만 검사

반환되는 내용:

{
  "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 — 구조화된 npm 스크립트 실행기

CI=true 및 FORCE_COLOR=0으로 모든 npm 스크립트를 실행한 다음 Vitest/Jest 출력을 파싱합니다.

입력:

  • project_dir (필수)

  • script (필수) — 예: "test", "test:unit", "lint"

  • args — -- 뒤에 전달되는 추가 인수

  • env — 추가 환경 변수

반환되는 내용:

{
  "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 빌드 검증기

프로덕션 모드에서 next build를 실행하고 오류와 페이지 출력을 파싱합니다.

입력:

  • project_dir (필수)

  • env — 빌드용 추가 환경 변수

  • timeout_seconds — (기본값: 180)

반환되는 내용:

{
  "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
}

개발

# Watch mode
npm run watch

# Run the unit tests (Vitest)
npm test

# Test interactively with the MCP Inspector
npm run inspect

테스트

출력 파서는 코드베이스에서 가장 까다롭고 회귀가 발생하기 쉬운 부분입니다 — 자유 형식의 Vitest/Jest/tsc/next build 콘솔 출력을 구조화된 JSON으로 변환합니다. 이러한 순수 함수는 test/ 아래에서 Vitest로 단위 테스트됩니다. npm test로 실행하세요. CI(.github/workflows/ci.yml 참조)는 모든 푸시 및 풀 리퀘스트에 대해 Node 20 및 22에서 npm ci, TypeScript 빌드, 테스트 스위트를 실행합니다.

사용자 지정 아이디어

  • lint 도구 추가 — ESLint JSON 출력 파싱

  • prisma_migrate 도구 추가 — 구조화된 마이그레이션 상태 확인

  • docker_compose 도구 추가 — 테스트 컨테이너 관리

  • RLS 도구를 Supabase CLI에 연결 (supabase db test) — 원시 psql 대신

라이선스

MIT © 2026 Brian Cox

Available Tools

5 tools
execute_sql_as_roleTest Supabase RLS policiesA

Executes a SQL query as a specific Postgres role with JWT claims set, so you can verify RLS policies. Runs inside a ROLLBACK transaction — never mutates data.

NameRequiredDescriptionDefault
sqlYesThe SQL query to execute
roleNoPostgres role to SET ROLE to, e.g. 'authenticated', 'anon', 'service_role'authenticated
claimsNoAdditional JWT claims to set, e.g. { "role": "parent" }. Merged into request.jwt.claims.
user_idNoUUID to set as request.jwt.claims sub (auth.uid()). Required for RLS policies that check auth.uid().
timeout_secondsNo
connection_stringYesPostgres connection string, e.g. postgresql://postgres:password@localhost:54322/postgres

TDQS

A4/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

No annotations exist, so the description must disclose behavior. It explicitly states the tool runs inside a ROLLBACK transaction and never mutates data—a critical safety guarantee. It also mentions setting JWT claims. It does not cover error handling or timeout behavior, but the core safety trait is transparently disclosed.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Two sentences with no fluff: the first states what and why, the second highlights the safety behavior. The purpose is front-loaded, making it easy for an agent to quickly grasp the tool's value.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

Given the tool's complexity (role switching, nested claims) and no output schema, the description covers purpose and safety well. It does not mention return values (e.g., query results) or prerequisites like a running database, but these are implied. Slightly more context on expected output would make it fully complete.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema coverage is 83%, so most parameters are already documented. The description adds no extra parameter meaning beyond the schema. The uncovered parameter (timeout_seconds) is not mentioned, but with high schema coverage, the baseline of 3 is appropriate.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description clearly states the verb (Executes), the resource (SQL query), and the purpose (verify RLS policies). It adds specificity with role and JWT claims, and the purpose distinguishes it from unrelated sibling tools like run_e2e_tests or typecheck.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines3/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The usage is implied: 'so you can verify RLS policies' indicates when to use. The ROLLBACK safety note suggests it's safe for testing. However, it does not explicitly state when not to use it or mention alternatives, though siblings are irrelevant. The guidance is clear but not exhaustive.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

nextjs_buildValidate Next.js buildB

Runs next build and returns structured errors (TypeScript, module, page-level) plus a list of generated pages with their render types and sizes.

NameRequiredDescriptionDefault
envNoExtra env vars for the build, e.g. { NEXT_PUBLIC_API_URL: '...' }
project_dirYesAbsolute path to the Next.js project root
timeout_secondsNo

TDQS

B3.3/5.0
Behavior2/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations are completely absent, so the description must disclose behavioral traits. It mentions running a build and returning errors, but omits side effects like the creation/modification of build artifacts (e.g., .next directory), potential long execution time (timeout parameter exists), and that a failed build may still return partial output. The description does not fully cover the tool's impact or failure modes.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

A single, concise sentence that front-loads the core command and lists key outputs with no filler. Efficiently communicates essential information.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness3/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

The description provides some return-value detail (structured error types and page list) but lacks full context: no output schema, no mention of side effects, environment requirements, or how to interpret the results. It gives a reasonable overview but is incomplete for a tool that runs a full build without annotations.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema covers 67% of parameters (env and project_dir have descriptions; timeout_seconds does not). The description adds no extra parameter context beyond what the schema provides, though the missing timeout parameter is self-explanatory. Since coverage is moderate but the description adds no value, a score of 3 is appropriate—adequate but not insightful.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description clearly states the action ('Runs next build') and the specific outcomes (structured errors and generated pages list). It distinguishes itself from siblings like typecheck and npm_run by being Next.js-specific and producing build validation output. No ambiguity.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines2/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

There is no guidance on when to use this tool versus alternatives (e.g., typecheck, npm_run). It does not state prerequisites, like that a Next.js project must exist, or when it should be preferred over other validation tools. The agent is left to infer usage from the name and output description.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

npm_runRun npm script with structured outputA

Runs any npm script (test, lint, etc.) and parses Vitest/Jest output into structured pass/fail results per file. Falls back to raw output for non-test scripts.

NameRequiredDescriptionDefault
envNoExtra environment variables
argsNoExtra args passed after --, e.g. ['--coverage', '--verbose']
scriptYesnpm script name to run, e.g. 'test', 'lint', 'test:unit'
project_dirYesAbsolute path to the project root
timeout_secondsNo

TDQS

A4.2/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

With no annotations provided, the description carries the full burden of behavioral disclosure. It explicitly discloses that Vitest/Jest output is parsed into structured per-file results and falls back to raw output for non-test scripts, which shapes agent expectations. It omits side effects like dependency installation or exit-code behavior, but the core behavior is adequately revealed.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Two sentences, front-loaded with the core purpose and output behavior, with zero redundancy. Every word earns its place.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

Given no output schema, the description's explanation of structured output and raw fallback provides sufficient context for invocation. It could elaborate on error handling or exit codes, but the essential information for calling the tool correctly is present, and sibling tools are clearly separated by their purposes.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is 80% (4/5 parameters have descriptions), so the schema already documents the parameters well. The description adds no additional meaning beyond the schema, meeting the baseline for high coverage without compensating for any gaps.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description states a specific verb (runs) and resource (npm script) and explicitly differentiates from siblings like run_e2e_tests and typecheck by focusing on arbitrary npm scripts. The mention of parsing test output adds specificity, making it unmistakable which tool to use for unit tests.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The description clearly implies the tool is for running any npm script, particularly tests, and distinguishes it from e2e, typecheck, and build tools. However, it does not explicitly name alternatives or state when not to use this tool, leaving exclusions to inference rather than explicit guidance.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

run_e2e_testsRun Playwright E2E testsA

Spins up the dev server (if configured in playwright.config), runs Playwright tests, and returns structured pass/fail results per test with error messages.

NameRequiredDescriptionDefault
headedNoRun in headed mode (useful for debugging)
project_dirYesAbsolute path to the project root
start_serverNoWhether to let Playwright use the webServer config in playwright.config to start the dev server automatically
test_patternNoGlob or file path to filter tests, e.g. 'tests/auth.spec.ts'
timeout_secondsNoMax seconds before the run is killed

TDQS

A4/5.0
Behavior3/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

With no annotations, the description must carry behavioral disclosure. It transparently states that it starts a dev server if configured and returns structured results, which is the core behavior. However, it does not disclose potential side effects such as file modifications, server teardown, or environmental requirements like locally installed Playwright, leaving some transparency gaps.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is a single, well-structured sentence that front-loads the main action and then details the conditional server startup and output format. There is no redundancy or unnecessary detail.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For a test runner with five parameters, the description covers the overall flow and return format sufficiently. The schema handles parameter details, and the description clarifies the conditional server startup. It lacks some environmental prerequisites, but overall it is adequate for an agent to call it correctly.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Because the input schema already provides descriptions for all five parameters, the baseline is 3. The description adds a little context by linking the dev server startup to the Playwright config, but it does not add new parameter-specific semantics beyond what the schema provides.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description explicitly states the tool runs Playwright tests and returns structured pass/fail results, with a clear verb and resource. It also mentions spinning up a dev server, which helps distinguish it from siblings like typecheck or npm_run.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The description implies its usage by identifying Playwright E2E testing as the core function. However, it does not explicitly name alternatives or specify when not to use it, leaving some room for interpretation. The context is clear enough that an agent would know to use it for running E2E tests.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

typecheckRun TypeScript type checkerA

Runs tsc --noEmit and returns structured errors with file, line, column, error code, and message.

NameRequiredDescriptionDefault
filesNoSpecific files to check (overrides tsconfig includes)
tsconfigNoPath to tsconfig file relative to project_dirtsconfig.json
project_dirYesAbsolute path to the project root (must contain tsconfig.json)
timeout_secondsNo

TDQS

A3.5/5.0
Behavior3/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

With no annotations, the description carries the full behavioral burden. It discloses the read-only nature of tsc --noEmit implicitly and describes the return format, which is valuable given no output schema. However, it omits timeout behavior, exit-code/error-handling semantics, and the side-effect-free guarantee explicitly — gaps that annotations would otherwise cover.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

A single, front-loaded sentence that packs the action, the exact command, and the output structure with zero filler. Every word earns its place.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness3/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

The tool has 4 parameters, no annotations, and no output schema, so the description must compensate. It compensates well for the missing output schema by spelling out error fields, but it leaves gaps: timeout_seconds is undocumented in both schema and description, the files/tsconfig interplay is unaddressed, and failure behavior is unstated. Adequate but not complete.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is 75%, so the schema already documents files, tsconfig, and project_dir. The description adds the 'tsc --noEmit' context, which clarifies how tsconfig and project_dir are consumed, but it doesn't explain timeout_seconds (the one undocumented parameter) or the files-overrides-tsconfig behavior. Value added is marginal over the schema.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description names a specific verb ('Runs'), a specific resource ('tsc --noEmit'), and states the output shape (structured errors with file, line, column, error code, and message). This clearly distinguishes it from siblings like run_e2e_tests, npm_run, and nextjs_build, which target different workflows.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines2/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The description provides no when-to-use or when-not-to-use guidance, and never mentions sibling tools. Context is only implied by the tool's name and the 'tsc --noEmit' detail; an agent receives no explicit direction on choosing it over the build/test siblings.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

Tool Schema Changelog

Recent tool additions, removals, and schema changes observed during successful MCP inspections.

  1. 5 tool updatesv0.1.0
    • First observedexecute_sql_as_role
    • First observednextjs_build
    • First observednpm_run
    • First observedrun_e2e_tests
    • First observedtypecheck

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

ActivitySlowing
ResponsivenessNo issues

Related MCP Connectors

Related MCP Servers

  • -
    license
    Not graded
    quality
    Not graded
    maintenance
    Provides comprehensive code quality tools including linting, security scanning, TypeScript checking, and testing through a single MCP server. Integrates multiple quality analysis tools like Biome, ESLint, and Playwright for streamlined development workflows.
    -
  • A
    license
    Not graded
    quality
    C
    maintenance
    Enables coding agents to audit a Next.js codebase read-only, checking routes, Prisma models, environment variables, and locale consistency via MCP tools.
    MIT
  • A
    license
    Not graded
    quality
    B
    maintenance
    Enables coding agents to perform file, search, patch, git, process, test, package, network, and system operations through 60 typed MCP tools with structured inputs/outputs, structured errors, and a full event journal, replacing terminal use with a typed machine API.
    MIT