# Giving Claude Code, Cursor and Other Agents a Verifier: The quelltest MCP Server and a Stop Hook

> Run npx quelltest mcp to give any MCP client find, verify and gate tools, and add a Claude Code Stop hook that blocks done when tests were weakened.

Published: 2026-10-20 | Author: Shashank Bindal | Tags: npm, mcp, claude code, cursor, ai agents, hooks

Canonical page: https://quelltest.com/blog/quelltest-mcp-server-and-stop-hook-for-coding-agents

**TL;DR.** `npx -y quelltest mcp` starts an MCP server over stdio with three tools: `find`, `verify` and `gate`. Register it in Claude Code with one `claude mcp add` line, and add a `Stop` hook that runs `quell gate` and exits 2 when tests were weakened, which tells Claude Code to keep working. We checked the server with a scripted stdio client; we have not run the hook inside a live Claude Code session.

This post is about the npm package (JavaScript and TypeScript projects). The Python package has a different MCP server with different tools (and its newest version is ahead of the PyPI release), described in [/docs/mcp](https://quelltest.com/docs/mcp.md) and [the earlier agent-native post](https://quelltest.com/blog/quelltest-is-now-agent-native.md).

## Why give an agent a verifier instead of a prompt?

An agent that writes the code also writes the tests that judge it, so the most common failure is a suite that goes green because it was edited, not because the code is right. Asking the agent to "be rigorous" is a request. A tool that returns a failing exit code is a check.

`verify` and `gate` are those checks, and MCP lets the agent call them as tools inside its own loop. `verify` returns surviving mutants as a handoff the agent can act on by strengthening the test.

## How do I add the quelltest MCP server to Claude Code?

```bash
claude mcp add quelltest -- npx -y quelltest mcp
```

The `--` separates Claude Code's own options from the command that starts the server. That is the documented shape of `claude mcp add [options] <name> -- <command> [args...]`.

Any other MCP client can launch the same command. Most clients take a JSON entry with a command and arguments, along these lines. Check your client's MCP documentation for the exact file and keys:

```json
{
  "mcpServers": {
    "quelltest": { "command": "npx", "args": ["-y", "quelltest", "mcp"] }
  }
}
```

For Cursor, start from [Cursor's documentation](https://cursor.com/docs). We did not test Cursor, Windsurf or any client other than our own scripted one.

## Does `npx quell mcp` really answer `tools/list`?

We did not want to claim it without checking. This script spawns the server, performs the MCP handshake over newline-delimited JSON-RPC, and asks for the tool list:

```js
import { spawn } from "node:child_process";

const child = spawn("npx", ["-y", "quelltest", "mcp"], { stdio: ["pipe", "pipe", "inherit"], shell: true });
const send = (message) => child.stdin.write(JSON.stringify(message) + "\n");

child.stdout.on("data", (chunk) => {
  for (const line of chunk.toString().split("\n").filter(Boolean)) {
    const message = JSON.parse(line);
    if (message.id === 1) {
      console.log("initialize ->", JSON.stringify(message.result));
      send({ jsonrpc: "2.0", method: "notifications/initialized" });
      send({ jsonrpc: "2.0", id: 2, method: "tools/list" });
    }
    if (message.id === 2) {
      console.log("tools/list ->", message.result.tools.map((tool) => tool.name).join(", "));
      child.kill();
    }
  }
});

send({ jsonrpc: "2.0", id: 1, method: "initialize", params: { protocolVersion: "2024-11-05", capabilities: {}, clientInfo: { name: "check", version: "0" } } });
```

Output, from the published `quelltest@0.3.1`:

```text
initialize -> {"protocolVersion":"2024-11-05","capabilities":{"tools":{}},"serverInfo":{"name":"quelltest","version":"0.3.1"}}
tools/list -> find, verify, gate
```

The input schemas we read from the same response:

| Tool | Required arguments | Other arguments |
| --- | --- | --- |
| `find` | none | `path`, `diff`, `coverage`, `top` |
| `verify` | `test`, `source` | `functions`, `runner`, `min_score` |
| `gate` | `diff` | `strict` |

`find` lists risk-ranked edge-case candidates and executes nothing. `verify` runs the test on the original source and then on mutants. `gate` reports deleted, skipped, `.only`, removed and loosened tests. The behavior of each is the same as the command line, which is described in [the verify post](https://quelltest.com/blog/does-your-test-fail-when-the-code-is-wrong.md) and [the gate post](https://quelltest.com/blog/did-the-ai-weaken-your-tests-quell-gate.md).

One detail matters for agents on Jest, Vitest or Mocha: the `verify` tool takes a `runner` argument, and the default is `node` (the `node:test` runner). See [the runner post](https://quelltest.com/blog/one-verification-layer-for-jest-vitest-mocha-and-node-test.md).

## How do I block "done" with a Claude Code Stop hook?

Claude Code runs a `Stop` hook when the agent finishes responding. Exit code 2 blocks the stop, and the hook's stderr goes back to the agent as the reason. Add this to `.claude/settings.json`:

```json
{
  "hooks": {
    "Stop": [
      {
        "hooks": [
          { "type": "command", "command": "npx quell gate --diff origin/main || exit 2" }
        ]
      }
    ]
  }
}
```

`quell gate` exits with code 5 when it finds weakened tests. The `|| exit 2` turns that into the blocking code. The same line works in Windows `cmd`, which supports both `||` and `exit 2`. Exit code 1, which a plain failure often gives, is not a blocking code for hooks, so do not drop the `|| exit 2`.

To also require that the tests you touched can fail, add a verify step for the test file that changed:

```bash
npx quell verify tests/pay.test.js --source src/pay.js --min-score 60 --handoff quell-handoff.md || exit 2
```

The `--handoff` file lists each surviving mutant with the diff, the surrounding code and a specific instruction. An agent can open it and fix the test.

## What should I watch out for?

- **A hook that always blocks can trap a session.** If the agent cannot satisfy the gate, it will keep being told no. When a weakening is deliberate, the agent can add `// quell-allow-weaken <reason>` in the test, which is visible in the diff. Try the hook on a scratch branch first.
- **The gate compares against a ref.** `origin/main` must exist locally, so fetch before running.
- **The verify hook runs your tests once per mutant.** Keep it to the files that changed.

## What are the limits?

- The hook and MCP recipes follow the documented Claude Code conventions but have only been exercised through quelltest's unit tests and a scripted stdio client, not inside a live Claude Code session. Treat them as a starting point. That is also the caveat in the project's own `docs/agents.md`.
- The server reports on the paths and refs it is given. It is a mechanical check, not a substitute for human review of what the agent changed.
- The gate does not catch a test rewritten under a new name, weakening done by editing the source, or logic inside test helpers. See [limits](https://quelltest.com/docs/npm/limits.md).
- An agent can still ignore a tool it is not forced to call. The `Stop` hook is what makes the check mandatory.

More recipes, including pull-request workflows, are in [/docs/npm/agents](https://quelltest.com/docs/npm/agents.md) and [/docs/npm/ci](https://quelltest.com/docs/npm/ci.md). Version history is in the [changelog](https://quelltest.com/changelog).

## FAQ

### Does the MCP server send my code to a service?

No. It runs on your machine and quelltest sends no code to any service. Your MCP client and your model provider have their own data handling, which quelltest does not control.

### Which Node.js version does it need?

The published 0.3.1 declares Node.js 20 or newer. The next release will require Node.js 22.18+ or 24.11+.

### Can the agent write tests through it?

Not in 0.3.1. The MCP server exposes `find`, `verify` and `gate`. Test generation is the CLI command `quell generate`.

### How is this different from the Python MCP server?

The Python repository has a `quelltest-mcp` server with tools for finding gaps and writing verified pytest tests. As of 2026-10-20 that command is in the repository (version 2.0.1) and not in the published PyPI 2.0.0 wheel, which ships an earlier server started with `python -m quell.mcp_server`. The npm server in this post is a separate implementation with the three tools above.

## Sources

- quelltest agents and CI guide: [docs/agents.md](https://github.com/quelltest/quelltest-npm/blob/main/docs/agents.md)
- Claude Code hooks reference (Stop event, exit code 2): [code.claude.com/docs/en/hooks](https://code.claude.com/docs/en/hooks)
- Claude Code MCP documentation (`claude mcp add`): [code.claude.com/docs/en/mcp](https://code.claude.com/docs/en/mcp)
- Model Context Protocol: [modelcontextprotocol.io](https://modelcontextprotocol.io)
- Cursor documentation: [cursor.com/docs](https://cursor.com/docs)
