jev-mcp

September 21, 2026 · View on GitHub

An MCP server that turns Cursor's "I think I'm done" into a checked decision. It collects git and test signals, asks TypeSafe Jev a set of narrow questions, and returns a typed verdict: fix, ask, or done.

The routing decision is made by policy code in this repository. Jev answers atomic questions about the state; it does not choose the action.

Name
PyPImcp-jev-mcp
CLIjev-mcp

Quick start

pipx install mcp-jev-mcp
jev-mcp key add <YOUR_TYPESAFE_API_KEY>
jev-mcp key status

Then add the MCP server to Cursor (~/.cursor/mcp.json or the project's .cursor/mcp.json):

{
  "mcpServers": {
    "jev-mcp": {
      "type": "stdio",
      "command": "jev-mcp",
      "args": ["serve"]
    }
  }
}

Reload MCP in Cursor, then ask the agent to call health.

Requirements

  • Python 3.11 or newer
  • git on PATH
  • A TypeSafe API key

API key

Resolution order:

  1. TYPESAFE_API_KEY in the environment — use this in CI.
  2. <JEV_MCP_HOME>/credentials.yaml, written by jev-mcp key add.

JEV_MCP_HOME defaults to ~/.jev-mcp.

jev-mcp key add <API_KEY>   # verifies against TypeSafe, then stores
jev-mcp key status            # source plus a masked hint, never the key
jev-mcp key remove

On Linux and macOS the file is written with mode 0600. On Windows it is protected only by your user profile ACL, so prefer the environment variable on a shared machine.

MCP tools

ToolWhat it does
collect_git(project_root, base_ref?, staged_only?, max_diff_bytes?)Branch, changed files, and a diff budgeted per file so no hunk is cut in half
run_tests(project_root, command?, timeout_s?)Runs the detected or supplied test command; a non-zero exit code comes back as data
decide(goal, git?, tests?, profile?, extra?)Asks Jev, applies policy, returns fix / ask / done with reasons
health(project_root?, probe?)Key source, git availability, detected test command
describe()The live question set, policy rules, and profiles

The tools are stateless: pass the collect_git and run_tests payloads straight into decide.

  1. The agent implements the change.
  2. collect_git and run_tests.
  3. decide with the user's goal and both payloads.
  4. Obey the verdict — fix keeps working, ask goes to the user, done may finish.

Add a project rule requiring step 4 before any completion claim.

Profiles

ProfileBehavior
defaultThe nine policy rules as written
strictAlso asks when code changed with no test signal, or when Jev's cross-check confidently disagrees with a done
cidone requires a test run that exited zero

Headless gate

jev-mcp gate --goal "add retry to the uploader" --project-root . --profile ci --json
Exit codeMeaning
0done
1fix
2ask
3tool error

Usable from a pre-push hook or a CI job.

Configuration

<JEV_MCP_HOME>/config.yaml, with environment variables taking precedence. See docs/superpowers/specs/2026-09-21-jev-mcp-design.md section 4 for every field.

git:
  max_diff_bytes: 524288
  max_file_diff_bytes: 65536
tests:
  default_timeout_s: 600
  projects:
    - match: "pyproject.toml"
      command: ["poetry", "run", "pytest", "-q"]
jev:
  model: jev-1.13
  max_retries: 2
decision:
  default_profile: default

Security

  • The key never travels through an MCP tool; key management is CLI-only.
  • Diffs and test output pass through a redactor before they reach Jev or the logs.
  • Subprocesses run through an argument vector; there is no shell interpolation.
  • Your diff and test output are sent to the TypeSafe API. Treat that as you would any third-party code analysis service, and read their terms.
  • serve --transport http binds to localhost and has no authentication. It is for local debugging only.

Development

poetry install
poetry run pytest -v
poetry run ruff check src tests
poetry run jev-mcp serve --transport http

License

MIT