Content
# HARNESS-MCP
Stdio MCP server that orchestrates a Planner → Generator → Evaluator loop to
autonomously implement a feature described in a design document. Inspired by
Anthropic's "Harness design for long-running application development" article.
The harness exposes a single MCP tool, `run_harness`, that blocks until the
run reaches a terminal state (completed / incomplete / failed) and streams
progress updates while running. All artifacts are persisted under
`~/.harness/<run-id>/`.
## How to
### 1. Clone and install
```sh
git clone https://github.com/chindada/harness-mcp.git
cd harness-mcp
uv sync --all-extras
```
### 2. Install the codex binary (separate, not bundled)
```sh
npm install -g @openai/codex
# The Codex Python SDK (openai_codex) is pulled in by `uv sync` from
# github.com/openai/codex@main — no separate install needed.
```
### 3. Verify your environment
```sh
uv run harness-mcp doctor
```
Sample output (clean install):
```sh
[OK] harness-writable: /Users/you/.harness
[OK] claude-cli: /Users/you/.local/bin/claude
[OK] codex-bin: /Users/you/.npm-global/bin/codex
[OK] codex-sdk: 0.131.0a4
[OK] codex-model: model probe succeeded
[OK] required-skills: loaded: superpowers:writing-plans
[OK] claude-auth: via macOS Keychain (Claude Code-credentials)
[OK] playwright: Version 1.60.0
[OK] disk-space: xxxx.x GB free
[OK] resolved-paths: CLAUDE_CONFIG_DIR=/Users/you/.claude codex=/Users/you/.npm-global/bin/codex
```
What each check verifies:
| Check | Verifies |
| ------------------ | -------------------------------------------------------------------------- |
| `harness-writable` | `~/.harness/` and `~/.harness/locks/` exist or can be created (mode 0700). |
| `claude-cli` | `claude` is on PATH or `HARNESS_CLAUDE_CLI_PATH` points to it. |
| `codex-bin` | `codex` is on PATH (or `HARNESS_CODEX_BIN` overrides). |
| `codex-sdk` | `openai_codex` Python module imports cleanly. |
| `codex-model` | Codex SDK live probe — fails fast if no model is configured. |
| `required-skills` | Live SDK probe for `superpowers:writing-plans`. |
| `claude-auth` | Auth resolves via env-var, `.credentials.json`, or (macOS) Keychain. |
| `playwright` | Playwright is installed (WARN-only — UI features need it, others don't). |
| `disk-space` | At least 5 GB free under `~/.harness`. |
| `resolved-paths` | Prints the `CLAUDE_CONFIG_DIR` and `codex` paths the harness will use. |
Exit code is `0` if no `[FAIL]`; `[WARN]` does not affect exit. If anything
fails, fix it before proceeding — the harness fails fast and loudly per
design rule 8.
### 4. Register with Claude Code
The form `claude mcp add` accepts is:
```sh
claude mcp add <name> [options] -- <command> [args...]
```
Place the server name BEFORE any `-e KEY=value` env flags — `-e` is
variadic and will otherwise consume the server name as the next env
value, producing `Invalid environment variable format: harness-mcp`.
The `--` separates the server name from the subprocess command.
Default registration (uses `~/.claude` and `codex` on PATH):
```sh
claude mcp add harness-mcp -- uv run --directory $PWD harness-mcp serve
```
Registration with a non-default Claude profile and a custom codex path
(useful for multi-account macOS users or when `codex` lives outside PATH):
```sh
claude mcp add --scope user harness-mcp \
-e CLAUDE_CONFIG_DIR=$HOME/.claude \
-e HARNESS_CODEX_BIN=$(which codex) \
-- uv run --directory $PWD harness-mcp serve
```
Verify registration:
```sh
claude mcp list
```
### 5. Run the tiny example
```sh
# In Claude Code, ask:
# "Run harness-mcp on the design doc at examples/tiny-feature.md against
# target_dir examples/scratch-app"
#
# Or programmatically (any MCP client):
# tool: run_harness
# args: {
# "target_dir": "$PWD/examples/scratch-app",
# "design_doc_path": "$PWD/examples/tiny-feature.md"
# }
#
# Expected: ~5-10 minutes, status="completed", a working /healthz route
# in examples/scratch-app/.
```
### 6. Inspect a run after the fact
```sh
ls ~/.harness/<run-id>/
# plan/ iteration-1/ iteration-2/ ... status.log state.json run.log
cat ~/.harness/<run-id>/iteration-1/eval.md
```
## Configuration
The harness reads two of its own environment variables and inherits three
from the upstream Anthropic / Claude Code SDKs. All five are optional —
defaults are usable in a standard install.
| Variable | Owner | Default | Purpose |
| ------------------------- | ----------- | ----------- | ----------------------------------------------------------------------------------------------------------------------------------------- |
| `HARNESS_CODEX_BIN` | harness-mcp | `codex` | Override the codex binary name/path resolved via PATH. Useful when `codex` is installed outside PATH or you need to pin a specific build. |
| `HARNESS_CLAUDE_CLI_PATH` | harness-mcp | _(none)_ | Explicit path to the `claude` CLI. Used as a fallback when `claude` is not on PATH. |
| `CLAUDE_CONFIG_DIR` | Claude SDK | `~/.claude` | Selects which Claude profile is active — controls the SDK config directory and (on macOS) which Keychain entry holds OAuth credentials. |
| `ANTHROPIC_API_KEY` | Anthropic | _(none)_ | Direct API key auth. Highest priority; bypasses OAuth entirely. Set this for headless / CI use. |
| `CLAUDE_CODE_OAUTH_TOKEN` | Claude SDK | _(none)_ | Pre-generated OAuth token. Headless alternative to running `claude login`. |
Pass any of these into the harness via `claude mcp add -e KEY=value` (see
step 4 above) or set them in the parent shell where you run
`harness-mcp serve` directly.
## Sensitive-data note
`~/.harness/<run-id>/run.log` may contain prompt and model output snippets;
the harness writes it with mode 0600 and never returns its contents in the
MCP tool result.
## Development
```sh
uv sync --all-extras
uv run ruff check
uv run ruff format --check
uv run pyright
uv run python scripts/check_docstrings.py src tests scripts
uv run pytest -m "not slow"
```
The end-to-end test against real SDKs is `@pytest.mark.slow` (excluded by
default). Run with `uv run pytest -m slow` when you have a working
environment and want to verify the full loop.
## Troubleshooting
- **`harness-mcp doctor` says `claude-cli FAIL`**: install Claude Code
(`npm install -g @anthropic-ai/claude-code`) or set
`HARNESS_CLAUDE_CLI_PATH` to a known-good path.
- **`codex-bin FAIL`**: `npm install -g @openai/codex`.
- **`codex-sdk FAIL: import failed`**: re-run `uv sync --all-extras`; the
git fetch from `openai/codex@main` may have transiently failed.
- **`claude-auth FAIL`**: set `ANTHROPIC_API_KEY` _or_ `CLAUDE_CODE_OAUTH_TOKEN`,
_or_ run `claude login`. On macOS the OAuth token lands in the system
Keychain (`Claude Code-credentials` service, suffixed
`-<sha256(abspath(CLAUDE_CONFIG_DIR))[:8]>` for non-default profiles); on
Linux/Windows it lands in `.credentials.json` under `~/.claude` (or
`CLAUDE_CONFIG_DIR`). The doctor accepts any of these.
- **Skill check fails at run time**: the harness probes `superpowers:writing-plans`
via the live Claude SDK at preflight. It is required. Install the
corresponding plugin/skill in your Claude Code config.
- **`claude mcp add` says `Invalid environment variable format: harness-mcp`**:
the `-e` flag is variadic in the Claude Code CLI and greedily consumes
the next positional argument — so `-e KEY=value harness-mcp` treats the
server name as another env value. Put the server name BEFORE the `-e`
flags: `claude mcp add harness-mcp -e KEY=value -- ...` (this contradicts
the public docs at code.claude.com/docs/en/mcp, but matches the CLI's
actual parsing behavior as of Claude Code 2.1.x).
## Spec
The full design spec is at
`docs/superpowers/specs/2026-05-08-harness-mcp-design.md`.
## License
MIT — see `LICENSE`.
MCP Config
Below is the configuration for this MCP Server. You can copy it directly to Cursor or other MCP clients.
mcp.json
Connection Info
You Might Also Like
everything-claude-code
Complete Claude Code configuration collection - agents, skills, hooks,...
markitdown
MarkItDown-MCP is a lightweight server for converting URIs to Markdown.
cc-switch
All-in-One Assistant for Claude Code, Codex & Gemini CLI across platforms.
servers
Model Context Protocol Servers
servers
Model Context Protocol Servers
Time
A Model Context Protocol server for time and timezone conversions.