Skip to main content
Smithers ships a built-in MCP stdio server: --mcp makes the CLI speak the Model Context Protocol over stdin/stdout instead of running interactively, so any MCP-aware client can connect to discover workflows, start runs, watch progress, resolve approvals, and revert attempts through structured tool calls. Use the MCP server when an AI agent should drive Smithers autonomously. Use the HTTP Server for REST endpoints for human-written code or webhooks.

Setup

Start the server

This starts the semantic surface: a stable, structured tool set for AI agent consumption, documented on this page. Two additional surfaces are available via --surface:
Use --surface raw only for direct CLI parity; prefer the semantic surface for new integrations, where every tool returns a { ok, data, error } envelope with Zod-validated input and output schemas. Scope the semantic surface when a client should not receive every Smithers control tool:
--allowed-tools takes a comma-separated list of semantic tool names; an empty allowlist exposes no semantic tools. --read-only removes semantic tools with write or control side effects, such as starting runs, resolving approvals, or reverting attempts. Under --surface both, both flags apply to the semantic toolset only; raw CLI-mirroring tools are always registered by the raw surface.

Register manually

For clients that read JSON config directly:
Project-scoped install (e.g. a monorepo where Smithers is a dev dependency; ensure smthrs is in the local package.json):

If mcp add fails

bunx smthrs mcp add hands the launch command to a registration helper expecting a single argument. If a runner or shell word-splits it, the helper sees a bare --mcp token and aborts:
Register with your agent’s own CLI instead: the -- separator marks everything after it as the launch command, so --mcp never gets parsed as one of the agent’s own flags:
Any MCP-aware CLI follows the same <agent> mcp add <name> -- <command> shape, or write the JSON/TOML config by hand from the snippets above. The Smithers CLI prints these fallback commands automatically whenever mcp add fails.

Tool Registration

On start, every tool registers with:
  • inputSchema: Zod object describing accepted parameters.
  • outputSchema: Zod schema for the structured response envelope.
  • annotations: MCP annotation metadata (readOnlyHint, destructiveHint, idempotentHint, openWorldHint).

Structured tool envelope

Every tool returns the same shape:
The response is also echoed as a text content block, so clients that do not parse structuredContent still receive the JSON payload.

Tool annotations


Tool Reference

list_workflows

List all Smithers workflows discovered in the working directory. Input: none Output:
Use the returned id values as the workflowId parameter for run_workflow.

run_workflow

Start or resume a discovered workflow. Input: Output:
Background vs. waited launch By default (waitForTerminal: false) the tool fires the workflow and returns immediately with launchMode: "background"; observedRun reflects the run state polled during waitForStartMs. Use watch_run to track progress. Set waitForTerminal: true to block until the workflow finishes: result is then populated and launchMode is "waited". Run option forwarding rootDir, logDir, allowNetwork, maxOutputBytes, toolTimeoutMs, and hot forward verbatim to runWorkflow, overriding values baked into the workflow file.

list_runs

List recent runs with summary data. Input: Output:
RunSummary fields: runId, workflowName, workflowPath, parentRunId, status, createdAtMs, startedAtMs, finishedAtMs, heartbeatAtMs, activeNodeId, activeNodeLabel, pendingApprovalCount, waitingTimers, countsByState.

get_run

Get the full detail record for a specific run, including steps, approvals, timers, loop state, lineage, config, and error. Input: Output:

watch_run

Poll a run at a fixed interval until it reaches a terminal state or a timeout expires. Input: Output:
When timedOut is true the run is still active, so call watch_run again or raise timeoutMs. Terminal statuses: any status other than running, waiting-approval, waiting-event, or waiting-timer, including finished, failed, cancelled, and continued.

explain_run

Return a structured diagnosis explaining why a run is blocked, waiting, or stale. Input: Output:
summary is a human-readable sentence. blockers lists every node preventing progress; unblocker describes what action or event would unblock it.

list_pending_approvals

List approvals that are waiting for a human decision, optionally filtered by run, workflow, or node. Input: All parameters optional. Omit all to list every pending approval across all runs. Output:

resolve_approval

Approve or deny a pending approval. This tool is destructive and non-idempotent. Input: Ambiguity guard Zero matches errors with INVALID_INPUT; more than one also errors with INVALID_INPUT, returning matches in details.matches. Add runId, nodeId, or iteration to narrow the selection: the tool never guesses among multiple approvals. Output:

ask_human

Block the current run, ask a human to make a decision, and wait for their answer: creates a durable pending human request and returns only once it’s resolved. Use this whenever the agent is blocked, uncertain, missing information, or about to take an irreversible or destructive action, instead of guessing. When run inside a Smithers task, the run/node context is taken from the SMITHERS_RUN_ID / SMITHERS_NODE_ID / SMITHERS_ITERATION environment variables Smithers injects into the agent; pass runId/nodeId/iteration explicitly to override, or rely on single-active-run autodetection. The orchestrating agent resolves the request on the human’s behalf: relay the question in conversation, collect their decision, then run bunx smthrs human answer <requestId> --value '<json>' (or bunx smthrs human cancel <requestId>) yourself, never instructing the human to run these. bunx smthrs human inbox lists everything waiting. Input: Output:

get_node_detail

Get enriched detail for a single node, including all attempts, tool calls, token usage, scorer results, and validated output. Input: Output:

revert_attempt

Revert the workspace and frame history back to the state captured at a specific attempt. This is destructive and non-idempotent. Input: Output:

fork_run

Create a branched run from a time-travel snapshot checkpoint without starting it. Input: Output: { runId, parentRunId, parentFrameNo, branch, snapshot, run }

replay_run

Fork a run from a checkpoint for replay, optionally restoring VCS state. Resume the returned runId with run_workflow when needed. Input: same as fork_run, plus: Output: { runId, parentRunId, parentFrameNo, branch, snapshot, vcsRestored, vcsPointer, vcsError?, run }

rewind_run

Rewind a run to a previous frame, deleting later frames and invalidating derived state. This is destructive and requires confirm: true. Input: Output: { result, run }

restore_checkpoint

Restore the worktree to a durability checkpoint for a node (latest matching one if seq is omitted). Child subflow nodes with newer discarded checkpoints, plus their dependents, are reset so a resumed parent re-executes that work instead of preserving stale child results. This destructive operation requires confirm: true. Input: Output: { runId, nodeId, iteration, seq, commitId, cwd, success, error? }

list_snapshots

List durability workspace checkpoints for a run and its descendant child runs, with the owning run ID and matching VCS operation IDs when available. Input: { runId: string } Output: { snapshots: Array<{ runId, seq, nodeId, iteration, attempt, tier, source, label, commitId, operationId, cwd, createdAtMs }> }

get_timeline

Return the time-travel timeline for a run, optionally including all child forks recursively. Input: Output: { timeline: unknown }

time_travel

Reset a run back to a prior node attempt and optionally restore VCS state. This destructive operation requires confirm: true (and force: true if the run is still marked running). Input: Output: { result, run }

list_artifacts

List structured output artifacts produced by nodes in a run. Input: Output:
Only nodes with an outputTable and a non-none output source are included.

get_chat_transcript

Return the structured agent chat transcript for a run, grouped by attempts. Input: Output:
Messages sort by timestampMs; use tail to limit context window usage on long transcripts.

get_run_events

Return the raw structured event history for a run with optional filtering. Input: Output:
Paginate via afterSeq: pass the seq of the last received event to fetch the next page.

Usage Examples

List workflows and start a run

Watch until complete

Resolve a pending approval

Debug a blocked run

Revert a failed attempt


Error Codes

Errors follow the structured envelope. Common codes: