Skip to main content

MCP Server

Prowl can run as an MCP server, exposing QA as a small set of named tools that any MCP-capable agent can call over stdio. The agent triggers runs and reads structured results through these tools — it never needs shell access to your repo.

This is the deepest form of the agent integration: instead of shelling out to prowl run, an agent connects once and drives QA through list_hunts, run_hunt, run_suite, and list_projects.

Prerequisites

  • prowl must be on your PATH. Install it globally with npm install -g prowl-tools, or launch it through npx (see the npx config below). If the binary can't be found, the MCP client fails to start the server with no hunt-specific error.
  • The target project must be initialized — a .prowl/ directory with a valid config and hunts. Run prowl init and author hunts first. Pointed at an uninitialized repo, MCP tool calls fail with a missing .prowl/config.yml error.

Starting the server

prowl mcp

This starts a stdio server for the current project — it discovers .prowl/ from the working directory, exactly like the other commands. To drive several repos from one server, pass a project registry:

prowl mcp --projects ~/.prowl/projects.yml

Configuring an MCP client

Point your MCP client at a command that starts the server from the initialized project. Most stdio MCP clients support command, args, and env; a cwd field is not portable, so these examples use a shell wrapper to enter the project directory before launching prowl mcp. If your client has a documented working-directory setting, you can use that instead.

{
"mcpServers": {
"prowl": {
"command": "/bin/sh",
"args": ["-lc", "cd \"/path/to/your/project\" && exec prowl mcp"]
}
}
}

Tools

ToolArgumentsReturns
list_huntsproject?Hunt names in run order
run_hunthunt, project?The full RunResult for a single hunt
run_suiteincludeTags?, excludeTags?, parallel?, logBugs?, project?Pass/fail/skip counts, the ci-result.json path, and the bug tickets created
list_projectsRegistered projects (empty unless a registry is configured)

Existing guardrails (allowedDomains, forbiddenSelectors, maxSteps, maxTotalTimeMs) apply to every run the server triggers.

Controlling what the agent can do

Prowl exposes only these four tools and never runs arbitrary shell. To restrict the agent further, allow-list tool names in your MCP client (e.g. OpenClaw) config — for example, allow list_hunts and run_suite but withhold run_hunt. That allow-listing is configured on the agent/client side, not in Prowl.

Logging bugs automatically

run_suite runs every hunt and, by default, logs each failure as a deduplicated bug ticket in the project's docs/backlog.md, under a ## QA Findings (automated) section that stays separate from your hand-written items. A bug is identified by hunt + failing step + normalized error, so:

  • a brand-new failure creates a QA-NNN ticket with the hunt, failing step, error, and a link to the run artifacts;
  • a failure that already has an open ticket is left alone (no duplicates);
  • a failure matching something already in docs/resolved.md is logged as a regression that references the old ticket id.

Pass logBugs: false to run without touching the backlog. A run_suite response looks like this:

{
"status": "fail",
"totalHunts": 8,
"passed": 6,
"failed": 2,
"skipped": 0,
"resultPath": "/path/to/project/.prowl/runs/ci-2026-05-26_09-12-03-456/ci-result.json",
"bugs": {
"created": ["QA-014"],
"regressions": ["QA-015"],
"alreadyOpen": ["QA-009"],
"backlogPath": "/path/to/project/docs/backlog.md"
}
}

status is one of pass, fail, no-hunts, or all-skipped. When logBugs is false, the bugs arrays are empty and backlogPath is null.

tip

The same bug-logging flow is available to non-MCP consumers via the updateBacklogFromSuite() library function.

Driving multiple projects

By default the server acts on the current directory. To drive several repos from a single server, give it a project registry — one YAML file that maps project names to repo roots. This file lives outside any repo (it spans many), not inside a target project:

# ~/.prowl/projects.yml
projects:
coupe:
root: /Users/you/projects/coupe
storefront:
root: /Users/you/projects/storefront
configPath: /custom/.prowl/config.yml # optional; defaults to <root>/.prowl/config.yml

The registry is resolved in priority order:

  1. prowl mcp --projects <path>
  2. the PROWL_PROJECTS environment variable
  3. ~/.prowl/projects.yml

With a registry loaded, every tool accepts an optional project argument that selects which repo to act on, and list_projects enumerates what's available. For example, these run_suite arguments run the smoke suite for coupe and log any failures to coupe/docs/backlog.md:

{ "project": "coupe", "includeTags": ["smoke"] }

Omit project and the tool falls back to the current directory. Naming a project that isn't registered — or naming one when no registry is configured — returns a clear error.

What's Next