MCP tools (Phase 14.3)
Four new tools added to `@mandujs/mcp` in Phase 14.3 — `mandu.run.tests`, `mandu.deploy.preview`, `mandu.ai.brief`, and `mandu.loop.close`. Each closes the loop between an agent's actions and its orchestrator.
On this page
MCP tools (Phase 14.3)
Four new tools added to @mandujs/mcp as part of Phase 14.3. They
close the loop between an agent's actions and the orchestrator that
drives it: run the project's tests, preview a deploy without touching
production, build a structured briefing for a fresh agent, and convert
raw output into an actionable next-step prompt.
All four follow the existing packages/mcp/src/tools/* convention:
an exported *ToolDefinitions: Tool[] array plus an exported
*Tools(projectRoot) handler factory, registered via TOOL_MODULES
in packages/mcp/src/tools/index.ts.
1. mandu.run.tests
Runs mandu test as a child process, parses the bun-test output,
returns a structured summary.
Input schema
| Field | Type | Default | Description |
|---|---|---|---|
target |
"unit" | "integration" | "e2e" | "all" |
"all" |
Subcommand passed through to mandu test. |
filter |
string? |
— | Forwarded as --filter <pattern> to bun test. |
coverage |
boolean? |
false |
Adds --coverage. |
Output shape
{
target: "unit" | "integration" | "e2e" | "all",
passed: number,
failed: number,
skipped: number,
duration_ms?: number,
failing_tests: Array<{ name: string; file?: string; error?: string }>,
exit_code: number,
note?: "no test files" | "timed out",
stdout_tail?: string, // last 2000 chars, for diagnostics
stderr_tail?: string,
}
On validation failure the tool returns { error, field, hint } with
isError: true propagated by the MCP error handler. A child-process
timeout is enforced at 10 minutes.
Empty test dirs produce { passed: 0, failed: 0, skipped: 0, note: "no test files" } —
callers get a benign zeroed summary instead of a crash.
2. mandu.deploy.preview
Invokes mandu deploy --target=<target> --dry-run. Always dry-run;
the tool cannot trigger a real deployment.
Input schema
| Field | Type | Required | Description |
|---|---|---|---|
target |
one of docker | fly | vercel | railway | netlify | cf-pages | docker-compose |
yes | Deployment adapter target. |
Output shape
{
target: DeployTarget,
mode: "dry-run",
artifact_list: Array<{
path: string;
preserved: boolean;
description?: string;
}>,
warnings: string[],
diff?: string, // parsed from fenced diff blocks if present
exit_code: number,
stdout_tail?: string,
stderr_tail?: string,
}
The artifact marker + (new) vs • (preserved) maps to
preserved: false | true. Warning lines starting with ⚠️ or
Warning: are collected separately into warnings.
3. mandu.ai.brief
Assembles a structured briefing for an AI agent newly attaching to the project. Use it as the first tool an onboarded agent calls.
Input schema
| Field | Type | Default | Description |
|---|---|---|---|
depth |
"short" | "full" |
"short" |
short trims lists for fast ingestion; full returns the complete view. |
Output shape
{
title: string, // "<pkg.name> @ <version>"
summary: string, // pkg.description or default
depth: "short" | "full",
files: string[], // package.json, mandu.config.*, AGENTS.md, CLAUDE.md, manifest
skills: Array<{ id; source: "static" | "generated"; path? }>,
recent_changes: Array<{ hash; subject; author?; date? }>, // last 20 commits
docs: Array<{ path; title }>, // top-level docs/*.md files
config: {
guard_preset?: string,
fs_routes?: boolean,
has_playwright?: boolean,
},
suggested_next: string[], // derived heuristics
}
The tool is read-only. It invokes git log as a 10-second-capped
child process; failures produce empty recent_changes rather than
erroring.
4. mandu.loop.close
Adapts the pure closeLoop() function from
@mandujs/skills/loop-closure into an MCP tool surface. Given
stdout, stderr, and exitCode from the most recent child-process
run, it identifies the dominant stall pattern and composes an advisory
nextPrompt.
Input schema
| Field | Type | Default | Description |
|---|---|---|---|
stdout |
string? |
"" |
Captured stdout. |
stderr |
string? |
"" |
Captured stderr. |
exitCode |
number? |
0 |
Child-process exit code. |
detectors |
string[]? |
all | Optional allow-list of detector IDs. |
Output shape
{
stallReason: string,
nextPrompt: string,
evidence: Array<{ kind; file?; line?; snippet; label? }>,
detectors_run: string[],
}
Safety
mandu.loop.close is pure: the underlying function never writes
files, never spawns processes, and never performs I/O. It is declared
readOnlyHint: true. The returned nextPrompt is advisory text —
an orchestrator decides whether to feed it back into the agent.
See Loop Closure for the full list of detectors and sample prompts.
Tool registration
All four are registered through the standard TOOL_MODULES array in
packages/mcp/src/tools/index.ts. They appear in the mandu-mcp
server's list_tools response without any profile enabled (i.e. in
the default full profile).
To expose them in the minimal or standard profiles, add the
category IDs (run-tests, deploy-preview, ai-brief, loop-close)
to packages/mcp/src/profiles.ts.
Testing
Test files mirror the tools under packages/mcp/tests/tools/:
run-tests.test.ts— 14 tests (definition shape, input validation, parser correctness)deploy-preview.test.ts— 14 tests (definition shape, input validation, artifact/warning/diff parsing)ai-brief.test.ts— 14 tests (definition shape, fake-project handler,buildSuggestedNextheuristics)loop-close.test.ts— 13 tests (definition shape, validation, determinism, detector allow-list)
Run with:
cd packages/mcp && bun test
Example end-to-end flow
The intended composition of these four tools:
Agent runs a task
↓
mandu.run.tests → exit_code = 1, failing_tests populated
↓
mandu.loop.close(stdout, stderr, exit_code=1)
↓
stallReason: "3 test failures detected"
nextPrompt: "# Stall detected..."
↓
Orchestrator feeds nextPrompt back to agent
↓
Agent proposes changes, runs mandu.deploy.preview(target=fly)
↓
mode: "dry-run"
artifact_list: [ { path: "fly.toml", preserved: true }, ... ]
↓
Agent ready for human-approved deploy
Each tool is independently useful; together they cover the stall → recover → ship path.
🤖 Agent Prompt
Apply the guidance from the Mandu docs page at https://mandujs.com/docs/ai/mcp-tools to my project.
Summary of the page:
Phase 14.3 Agent G adds 4 MCP tools: run.tests (runs mandu test, returns structured summary), deploy.preview (mandu deploy --dry-run adapter), ai.brief (project briefing for new agents), loop.close (pure stall-pattern detector → nextPrompt). All four in TOOL_MODULES in packages/mcp/src/tools/index.ts.
Required invariants — must hold after your changes:
- All four tools ship in the default `full` MCP profile — appear in `list_tools`
- `mandu.loop.close` is pure (readOnlyHint: true) — no I/O, no spawn
- `mandu.deploy.preview` always passes `--dry-run` — cannot trigger real deployments
- `mandu.run.tests` child process timeout: 10 minutes
- `mandu.ai.brief` is read-only — git log is cap'd at 10s, failure → empty recent_changes
Then:
1. Make the change in my codebase consistent with the page.
2. Run `bun run guard` and `bun run check` to verify nothing
in src/ or app/ breaks Mandu's invariants.
3. Show me the diff and any guard violations.
Related
- AI — Loop closure — the pure framework
under
mandu.loop.close. - Testing index — the command under
mandu.run.tests. - Deploy index — the commands under
mandu.deploy.preview. - CLI —
mcp register— wire the MCP server into your IDE.
For Agents
{
"schema": "mandu.mcp.tools/v0.25",
"phase": "14.3",
"new_tools": [
{ "id": "mandu.run.tests", "category": "run-tests", "writes": false, "spawns": true, "timeout_ms": 600000 },
{ "id": "mandu.deploy.preview", "category": "deploy-preview", "writes": false, "spawns": true, "mode": "always --dry-run" },
{ "id": "mandu.ai.brief", "category": "ai-brief", "writes": false, "spawns": true, "readOnlyHint": true },
{ "id": "mandu.loop.close", "category": "loop-close", "writes": false, "spawns": false, "readOnlyHint": true, "pure": true }
],
"profile_default": "full (all four visible)",
"rules": [
"loop.close is pure — no side effects, safe to call speculatively",
"deploy.preview cannot trigger real deploys — always --dry-run",
"run.tests child process capped at 10 minutes",
"ai.brief is read-only — treat as a safe warm-up call"
]
}For Agents
Phase 14.3 Agent G adds 4 MCP tools: run.tests (runs mandu test, returns structured summary), deploy.preview (mandu deploy --dry-run adapter), ai.brief (project briefing for new agents), loop.close (pure stall-pattern detector → nextPrompt). All four in TOOL_MODULES in packages/mcp/src/tools/index.ts.
- All four tools ship in the default `full` MCP profile — appear in `list_tools`
- `mandu.loop.close` is pure (readOnlyHint: true) — no I/O, no spawn
- `mandu.deploy.preview` always passes `--dry-run` — cannot trigger real deployments
- `mandu.run.tests` child process timeout: 10 minutes
- `mandu.ai.brief` is read-only — git log is cap'd at 10s, failure → empty recent_changes