Driving Ptah via MCP
The Ptah CLI ships a ptah mcp-serve command that turns Ptah into a Model Context Protocol server. An external MCP-aware host — Claude Code, Cursor, the Gemini CLI, or any other MCP client — launches ptah mcp-serve as a child process and drives Ptah’s agent surface through the host’s existing MCP integration, with no bespoke wiring.
When to use it
Section titled “When to use it”- An external coding agent (Claude Code, Cursor, Gemini CLI) should be able to delegate a whole task to Ptah’s Team Leader.
- You want to expose Ptah’s CLI-agent spawn/steer/stop surface to another orchestrator over a standard protocol.
- You’re building an MCP host and want Ptah as one of its connected servers.
For headless scripting against Ptah’s own JSON-RPC surface (rather than the MCP standard), use ptah interact instead.
The command
Section titled “The command”ptah mcp-servemcp-serve speaks JSON-RPC 2.0 over newline-delimited JSON on stdin/stdout, using the MCP method namespace (initialize, tools/list, tools/call, notifications/cancelled) rather than Ptah’s own task.* / session.* methods.
stdout is reserved for the MCP wire. All boot and teardown logging goes to stderr with a [ptah-mcp] prefix. --verbose does not relax this — stdout stays pristine so the host’s parser never chokes.
| Flag | Description |
|---|---|
--allow-tools <csv> | Comma-separated tool allowlist override. Defaults to the full 7-tool MVP catalog. |
mcp-serve also honors the global CLI flags — most relevantly --cwd <dir> (working directory for the agent), --auto-approve, --verbose, and --quiet. See CLI Flags for the full list.
Host configuration
Section titled “Host configuration”Point your MCP host at ptah mcp-serve. A typical .mcp.json entry:
{ "mcpServers": { "ptah": { "command": "npx", "args": ["-y", "@hive-academy/ptah-cli", "mcp-serve", "--auto-approve"], "cwd": "/path/to/your/project" } }}Because the host namespaces tools by server name (e.g. ptah:agent_spawn), the tool names on the wire drop the ptah_ prefix used by the built-in HTTP server.
MVP tool catalog
Section titled “MVP tool catalog”tools/list advertises seven tools. Six are agent-process controls; session_submit delegates a full task to Ptah’s Team Leader.
| Tool | What it does | Pro-gated |
|---|---|---|
agent_list | List detected CLIs and configured Ptah CLI agents. | Free |
agent_spawn | Spawn a CLI agent and return its handle. | Conditional* |
agent_status | Report a spawned agent’s status. | Conditional* |
agent_read | Read a spawned agent’s buffered stdout/stderr and exit code. | Conditional* |
agent_steer | Push a steering message to a running agent. | Conditional* |
agent_stop | Terminate a running agent. | Conditional* |
session_submit | Delegate an entire task to Ptah’s Team Leader, which fans out to sub-agents via the SDK Task tool. | Pro |
* See Premium gating below — these are Pro-gated only when targeting a Ptah-CLI agent.
session_submit accepts a free-form task (required), plus optional cwd, allowSubagents (default true), and a profile (claude_code or enhanced). With allowSubagents enabled, the Team Leader decomposes the task and fans work out to sub-agents, aggregating their results into a single MCP response.
Premium gating
Section titled “Premium gating”Pro-only tool calls are not rejected with JSON-RPC error codes. Per the MCP spec, the gate returns a normal tools/call result with isError: true and a structured upgrade hint:
{ "content": [{ "type": "text", "text": "This tool requires a Ptah Pro subscription." }], "isError": true, "structuredContent": { "ptah_code": "license_required" }}Gating policy:
session_submitalways requires Pro — it drives the Team Leader harness.agent_spawnrequires Pro only when spawning a Ptah-CLI agent (theptahCliIdargument is set). Spawning a user-installed binary (Gemini, Codex, Copilot, …) is free.agent_status/agent_read/agent_steer/agent_stoprequire Pro when they target a Ptah-CLI agent; targeting your own rival-CLI binaries is free.agent_listis always free.
The gate fails closed: if a referenced agent can’t be resolved, the call is treated as Pro-gated to prevent bypass via an unknown agent id.
Cost attribution
Section titled “Cost attribution”On startup mcp-serve mints a per-process host session id (a ULID) and exports it as PTAH_MCP_HOST_SESSION_ID so downstream usage can be attributed back to this host. It’s also reported in the notifications/initialized payload.
During a session_submit run, cost and token deltas stream as notifications/message frames (including session.cost), and a final mcp.session.summary lands when the turn settles. Hosts that surface MCP notifications will see these inline; hosts that ignore notifications still get the aggregated result.
Introspection
Section titled “Introspection”Two introspection methods are available in both interact and mcp-serve modes:
| Method | Returns |
|---|---|
session.describe | serverName, version, schemaVersion, mode (mcp-serve), the registered method list, the MCP tool catalog, error codes, and capabilities. |
session.methods | Just { methods: string[] } — the live registered method list. |
In mcp-serve mode, session.describe reports mode: "mcp-serve", capabilities: ["mcp"], and the seven-tool catalog (filtered by --allow-tools when set).
Cancellation and shutdown
Section titled “Cancellation and shutdown”- An MCP host cancels an in-flight call by sending
notifications/cancelled. - The process shuts down cleanly on stdin EOF (exit
0), SIGINT (exit130), or SIGTERM (exit143). - On any of these, the server drains pending stdout, races the drain against a 5-second cap, and tears down the session.
Troubleshooting
Section titled “Troubleshooting”| Symptom | Cause / fix |
|---|---|
A tools/call hangs, then the process exits 3 | An approval-gated tool ran without --auto-approve. Add --auto-approve (or PTAH_AUTO_APPROVE=true) to the host config. |
tools/call returns isError: true with license_required | The tool is Pro-gated and no valid Pro license is present. See Premium gating. |
tools/call returns isError: true with sdk_init_failed | The call arrived before the agent SDK finished bootstrapping. Retry after notifications/initialized. |
| The host’s MCP parser reports garbage / extra lines | Something wrote to stdout that isn’t the MCP wire. Ptah keeps stdout pristine and logs to stderr — check a wrapper script isn’t echoing to stdout. |
| The host’s handshake times out | initialize is answered eagerly before DI finishes, so this is rare. Confirm the host launches the binary directly and isn’t buffering stdio. |
Related
Section titled “Related”- Built-in MCP Server — the in-app HTTP/SSE server that exposes
ptah_*tools to models (the opposite direction). - Ptah CLI — registering CLI agents and the broader headless surface.
- CLI Flags — global flag reference.