# Vespiquen > A local MCP server that runs Codex and Claude Code as persistent ACP subagents. By Irving Dinh. The calling agent chooses what runs next; Vespiquen manages sessions and returns results. Website: https://vespiquen.irving.dev/ Package: https://www.npmjs.com/package/vespiquen Published version: 0.0.1. License: MIT. Requires Node.js 24+. This file contains the setup guide and tool reference. The website is documentation; the MCP server runs on the user's machine at http://127.0.0.1:46100/mcp by default. ## Setup Goal: install Vespiquen, connect it to Claude Code, and verify a first subagent task. The commands below use the published npm package. 1. Check `node --version`, the user's OS, and whether `vespiquen` is already installed. Reuse an existing installation and running server. 2. Check `claude` on PATH and its login. For Codex tasks, also check `codex` on PATH and its login. Vespiquen uses the installed CLIs and their authentication; it does not provide model accounts. Let the user complete interactive login if needed. 3. Install from npm, then start the server, install the Claude skill and runner files, register the MCP endpoint, and verify health and an actual task. ```sh npm install --global vespiquen ``` Run checks: ```sh vespiquen paths vespiquen doctor ``` `doctor` checks configuration, Node, executables, server health, and starts every registered ACP adapter once. Review the reported authentication status as well as the exit code. Adapter initialization alone does not verify that a model can run a task. `doctor --skip-agents` checks the environment without starting adapters. The default adapters are downloaded through npx on first use, so network access is needed. Start in the foreground in a separate terminal: ```sh vespiquen start ``` Or, when the user wants a login service: ```sh vespiquen service install vespiquen service status ``` The service uses launchd on macOS and systemd --user on Linux. A Linux user service normally stops at logout unless lingering is enabled. `service install --dry-run` shows its changes. Do not start a second server on the same port. Install the supplied Claude skill and runner definitions: ```sh vespiquen claude install ``` This copies `skills/use-vespiquen/SKILL.md`, `agents/codex-runner.md`, and `agents/claude-runner.md` to CLAUDE_CONFIG_DIR, else ~/.claude. Existing files at those paths are replaced. `--target /absolute/path` changes the destination; `--dry-run` previews changes. The command asks for confirmation; use `--yes` for a non-interactive run when the user has authorized installation. It prints an MCP registration command but does not run it. Register the printed command. With default configuration: ```sh claude mcp add -s user --transport http vespiquen http://127.0.0.1:46100/mcp ``` If a bearer token is configured, use the actual command printed by the CLI with its Authorization header. If the port or bind address differs, use the URL printed by `vespiquen paths`. Reconnect or restart the Claude Code session if it does not discover the new tools. For headless Claude runs, `vespiquen claude print-mcp-config` prints the MCP JSON configuration. Other HTTP MCP clients can use the same endpoint; the supplied skill and runners target Claude Code. ## Verify a first task Use actual MCP tools, not REST POST requests. In Claude Code they are named `mcp__vespiquen__health`, `mcp__vespiquen__agents`, `mcp__vespiquen__spawn`, and so on. 1. Call `health {}` and `agents {}`. 2. Choose an installed, authenticated agent. For Codex, call `spawn` with: ```json { "agent": "codex", "cwd": "/absolute/path/to/the/users/project", "mode": "read-only", "permissions": "ask", "prompt": "Reply with exactly PONG. Do not run commands or edit files." } ``` Replace cwd with an existing absolute directory. For Claude, use `agent: "claude"` and omit the Codex-specific mode. Never apply Codex mode ids to Claude. 3. If `session_status` is `input_required`, handle `pending_request` with `respond`, then `wait`. 4. Confirm `turn.status` is `completed` and `final_answer` is PONG. Report an error if it failed; do not claim success based on an empty answer or running turn. 5. Call `close` with the returned session id to finish the verification session. ## Operating rules - A session has an id beginning `s_` and an optional unique name. A turn, beginning `t_`, is one prompt and reply. Use id or name for a session reference, not both. - `spawn`, `send`, `wait`, and `fork` with a prompt block until the turn ends or needs input. Omit `wait_ms` for that behavior. `wait_ms: 0` returns immediately; another nonnegative integer bounds the call in milliseconds. A timeout or client abort ends the wait, not the agent's work. - In the main Claude Code conversation, a long tool call may be backgrounded and delivered as a task notification. Do not issue a duplicate wait while the original background call is pending. - `input_required` means the agent is waiting for a permission or question response. Read the request, call `respond`, then `wait`. Questions always reach the caller, even with `permissions: "allow_all"`. - One turn runs at a time per session. Use `steer` to redirect a running turn, or `send` with `queue: true` to run a follow-up afterward. - Read `turn.error` and `warnings`. Report failed, cancelled, or lost turns accurately. The calling agent must not replace the delegated agent's failed answer with an invented success. - `stop` cancels a turn and keeps its session. `close` ends a session. `fork` copies conversation context; it does not create a git worktree or isolate files. Sessions can share a directory, so the caller manages concurrent edits. - Keep default model, effort, and mode unless the task needs an override. Available settings come from `agents`; lists are empty before that agent has opened a session. Resolved settings are returned with each result. ## Tool reference Arguments use snake_case. All fields are optional unless marked required. Prompt settings shared by spawn/send: `mode`, `model`, `effort` (strings), and `config` (map of string or boolean values). Prompt options: `attachments` (absolute file paths), `output_schema` (JSON Schema object), `wait_ms` (nonnegative integer milliseconds). A session reference is `id` or `name`. - `agents {reset?}`: list registered agents, process states, adapter versions, auth, known settings, and capabilities. `reset: true` clears the failed state caused by the crash guard. Processes start on demand. - `spawn {agent, prompt, cwd, name?, mode?, model?, effort?, config?, permissions?, attachments?, output_schema?, wait_ms?, mcp_servers?}`: agent, prompt, and absolute cwd are required. Start a session and its first turn. An existing name reuses its session if agent and cwd match. permissions is ask (default), allow_all, or deny_all. Returns TurnResult. - `send {id?|name?, prompt, queue?, mode?, model?, effort?, config?, attachments?, output_schema?, wait_ms?}`: a session reference and prompt are required. Continue with existing context. `queue: true` queues behind a running turn. Returns TurnResult. - `steer {id?|name?, message}`: reference and message required. Returns `{outcome, turn_id?}`. outcome is injected, started_new_turn (idle session; call wait), or queued (steering unsupported; runs afterward). - `wait {id?|name?|ids?, turn_id?, wait_ms?, after_seq?}`: a single reference or ids array required. One session returns TurnResult. Several return `{results, ready, still_running}` when any ends or needs input. turn_id selects a stored turn; after_seq adds event summaries. - `tail {id?|name?, after_seq?, limit?, kinds?, include_thoughts?, turn_id?}`: reference required. Returns `{events, next_seq, has_more, warnings?}`. limit defaults to 200, maximum 500; pages also stop near 60,000 characters. Use next_seq as after_seq to continue. Payloads are included when kinds is provided or limit is at most 50. Thoughts are hidden unless include_thoughts is true. Large payload strings are clipped. - `respond {id?|name?, request_id, option_id?, answers?, note?}`: reference and request_id required. Permissions use an option_id from pending_request.options. Questions use an answers map from question_id to choice value or permitted free text; note fills a free-text companion field. Returns `{accepted: true, turn: {id, status: "running"}}`. Call wait next. - `stop {id?|name?, reason?}`: reference required. Cancels the running turn; returns TurnResult with any partial answer. If cancellation is not confirmed within 30 seconds, the turn is marked lost and the session stays busy until the agent ends it. Stop again to wait or close the session. - `fork {id?|name?, new_name?, prompt?, wait_ms?}`: reference required. Copy context into a new session, optionally run a first prompt. Returns its TurnResult. Requires the agent's fork capability. - `list {status?, agent?, cwd?, limit?}`: list sessions with latest activity, settings, transcript path, and pending requests. status is an array of session states. cwd matches exactly. limit defaults to 50, maximum 500. - `close {id?|name?}`: reference required. Stops a running turn, closes the session, and frees its name. Returns `{closed: true}`. Transcript and events remain; the adapter can keep serving other sessions. - `health {}`: server health, version, home, database, session/event counts, agent state/auth, and uptime. `mcp_servers` on spawn adds MCP servers to the child session. Each stdio server is `{name, command, args?, env?}` with an absolute executable path; HTTP is `{name, type: "http", url, headers?}`. env and headers are arrays of `{name, value}`. These supplement the agent's own configuration. `output_schema` asks the agent to end with fenced JSON. Validated output appears in structured_content; a mismatch adds output_schema_mismatch to warnings. This is prompting and validation, not guaranteed constrained decoding. ## Results and states TurnResult fields: ```text id, name?, agent, cwd, session_status turn?: {id, seq, status, stop_reason?, error?, started_at, ended_at?, duration_ms?} final_answer, structured_content?, changed_files, tool_calls pending_request?, usage?, resolved, transcript_path next_seq, truncated, warnings ``` Session states: idle, running, input_required, closed, detached. Turn states: running, input_required, completed, cancelled, failed. detached means the server restarted or the agent process died; a subsequent send attempts to reattach. A session missing from the agent fails explicitly. pending_request includes request_id, kind (permission/question), title, detail, and options or questions, plus expires_at when available. Each permission option has option_id, name, kind. Each question has question_id, title, choices when offered, allow_other, and other form metadata. Use the returned values rather than guessing ids. Requests can expire. final_answer is the agent reply. changed_files tracks reported edits, deletes, and moves. tool_calls includes total, by_kind, and failed counts. usage may include token counts, context size, and cost when reported by the adapter; absence is not zero. resolved gives actual mode/model/effort when available. Long final answers default to a 40,000-character cap with truncated true. Multi-session wait additionally shortens each answer to 8,000 characters. Read transcript_path or the transcript resource for the complete text. Raw event pages and session lists also have size budgets. Tool results contain the same JSON in structuredContent and a text block. Tool failures use isError with `{code, message, details?}`. Codes include agent_unknown, agent_unavailable, auth_required, session_not_found, session_mismatch, turn_busy, request_not_found, request_expired, invalid_option, invalid_argument, cancelled, timeout, agent_error, unsupported, and internal. ## Configuration and diagnostics Defaults: home ~/.vespiquen, bind 127.0.0.1, port 46100, no bearer token. State is SQLite plus per-session Markdown transcripts. The server recreates the database when its schema changes, including the installed release. Back up state before an upgrade that changes the schema. Configuration precedence: CLI flags, environment, config.json in VESPIQUEN_HOME, defaults. Settings include home (`--home`/VESPIQUEN_HOME), port (`--port`/PORT/config.port), bind (`--bind`/HOST/config.bind), token (`--token`/VESPIQUEN_TOKEN/config.token). Paths can be overridden with CODEX_PATH, CLAUDE_CODE_EXECUTABLE, CLAUDE_CONFIG_DIR or config.paths. The server requires a bearer token for a non-loopback bind. Public remote hosting is not the default setup. CLI commands: start, paths, doctor [--skip-agents], service install|uninstall|status|restart, claude install|uninstall, claude print-mcp-config. Service commands read token from config.json and reject --token. Use service restart after changing the service configuration. Service uninstall removes the login service; claude uninstall removes the supplied skill and runner files. Neither is a command to erase the session database. Troubleshooting: - npm reports ETARGET for a dependency version that exists: retry with a fresh cache using `npm install --global vespiquen --prefer-online --cache /absolute/path/to/a/new/npm-cache`. A stale npm metadata cache caused this during installation checks for 0.0.1. - Connection refused: use paths and service status; check the foreground server or logs in ~/.vespiquen/logs. Default health endpoint is GET http://127.0.0.1:46100/api/health. - Unauthorized: supply the configured bearer token to the MCP client. Host/Origin rejection: check bind and allowedHosts. Use loopback for normal local setup. - Missing executable or auth_required: fix the relevant CLI path or login, then rerun doctor. Do not put credentials in prompts or diagnostic output. - turn_busy: wait, steer, or send with queue true; do not spawn a replacement to hide the busy state. - input_required: respond using the current pending request, then wait. - request_expired: read current state with wait or list before responding again. - agent_unavailable: inspect the error, doctor, logs, and agents. Reuse the same session to try reattachment; reset a crash-blocked adapter with agents reset only after diagnosing it. - unsupported: check capability support in agents. Do not assume every configured ACP agent implements fork or steering. - An agent reports that it cannot read workspace files: inspect its tool calls and answer. Text files can be passed through `attachments` as absolute paths; files under 64 KB are embedded. An attached-file review with GPT-6 Luna was verified. Do not claim a workspace review succeeded when no files were read. - Models or efforts absent: open a session first; use defaults until the adapter reports its lists. Codex questions require config `{"collaboration_mode": "plan"}`. ## MCP resources and HTTP Resources: `vespiquen://sessions` (JSON), `vespiquen://sessions/{id}/transcript` (Markdown), `vespiquen://sessions/{id}/pending` (pending request or empty object), `vespiquen://sessions/{id}/events` and `vespiquen://sessions/{id}/events?after=N` (event page). The small REST API is for inspection: GET /api/health, /api/agents, /api/agents/:id, /api/sessions, /api/sessions/:id, /api/sessions/:id/events, /api/sessions/:id/transcript, /api/sessions/:id/stream (SSE), /api/metrics, /api/metrics/daily. Session mutations happen through MCP tools. Bearer authentication applies when configured. ## Links - [Homepage](https://vespiquen.irving.dev/): short human overview. - [npm package](https://www.npmjs.com/package/vespiquen): published releases. - [MIT license](https://opensource.org/license/mit): license terms. - [Irving Dinh](https://irving.dev/): author.