--mcp to the CLI it speaks the Model Context Protocol over stdin/stdout instead of acting as an interactive CLI. Any MCP-aware client can connect, discover your workflows, start runs, watch progress, resolve approvals, and revert bad attempts — all through structured, machine-readable tool calls.
Use the MCP server when you want an AI agent to drive Smithers autonomously. Use the HTTP Server when you need REST endpoints for human-written code or webhooks.
Setup
Start the server
--surface:
--surface raw only when you need direct CLI parity. The semantic surface is strongly preferred for new integrations: every tool returns a consistent { ok, data, error } envelope and uses validated Zod schemas for both input and output.
Register with Claude Code
smithers mcp add writes the server entry to the appropriate MCP config file for the detected agent. Pass --agent to target a specific client, --no-global to install project-locally, or --command to override the launch command:
Register manually
For clients that read a JSON config directly, add an entry like this:Tool Registration
When the server starts it callsregisterSemanticTools, which loops over the tool definitions produced by createSemanticToolDefinitions and registers each one via server.registerTool. Every tool carries:
inputSchema— a Zod object schema describing accepted parameters.outputSchema— a Zod schema for the structured response envelope.annotations— MCP annotation metadata (readOnlyHint,destructiveHint,idempotentHint,openWorldHint).
Structured tool envelope
Every tool returns the same top-level shape:text content block so clients that do not parse structuredContent still receive the JSON payload.
Tool annotations
| Annotation | Tools | Meaning |
|---|---|---|
readOnlyHint: true | Most query tools | Tool does not modify state |
readOnlyHint: false, openWorldHint: true | run_workflow | Launches external processes |
readOnlyHint: false, destructiveHint: true, idempotentHint: false | resolve_approval, revert_attempt | Mutates persisted state irreversibly |
Tool Reference
list_workflows
List all Smithers workflows discovered in the working directory. Input: none Output:id values as the workflowId parameter for run_workflow.
run_workflow
Start or resume a discovered workflow. Input:| Parameter | Type | Default | Description |
|---|---|---|---|
workflowId | string | required | Workflow ID from list_workflows |
input | Record<string, unknown> | {} | Workflow input object |
prompt | string | — | Shorthand: sets input.prompt when input is not provided |
runId | string | auto | Custom run ID |
resume | boolean | false | Resume an existing run; requires runId |
force | boolean | false | Force-start even if a run with this ID already exists |
waitForTerminal | boolean | false | Block until the run reaches a terminal state |
waitForStartMs | number | 1000 | For background launches, how long to wait for the run row to appear in the database |
maxConcurrency | number | — | Max concurrent nodes |
rootDir | string | — | Root directory for tool sandboxing and path resolution |
logDir | string | — | Directory for log files |
allowNetwork | boolean | false | Allow network access in bash tool |
maxOutputBytes | number | — | Cap on node output size |
toolTimeoutMs | number | — | Per-tool call timeout |
hot | boolean | false | Enable hot-reloading of the workflow file |
waitForTerminal: false) the tool fires the workflow and returns immediately with launchMode: "background". The observedRun field reflects the run state polled during waitForStartMs. Use watch_run to track progress after launch.
Set waitForTerminal: true to block until the workflow finishes. The result field is populated and launchMode is "waited".
Run option forwarding
rootDir, logDir, allowNetwork, maxOutputBytes, toolTimeoutMs, and hot are forwarded verbatim to the engine’s runWorkflow call. They override any values baked into the workflow file.
list_runs
List recent runs with summary data. Input:| Parameter | Type | Default | Description |
|---|---|---|---|
limit | number (1–200) | 20 | Max runs to return |
status | string | — | Filter by status (running, finished, failed, etc.) |
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:| Parameter | Type | Description |
|---|---|---|
runId | string | Run ID |
watch_run
Poll a run at a fixed interval until it reaches a terminal state or a timeout expires. Input:| Parameter | Type | Default | Description |
|---|---|---|---|
runId | string | required | Run to watch |
intervalMs | number | 1000 | Poll interval (minimum enforced by runtime) |
timeoutMs | number | 30000 | Wall-clock budget before giving up |
timedOut is true the run is still active; call watch_run again or increase timeoutMs. Terminal statuses are finished, failed, and cancelled.
explain_run
Return a structured diagnosis explaining why a run is blocked, waiting, or stale. Input:| Parameter | Type | Description |
|---|---|---|
runId | string | Run ID |
summary field is a human-readable sentence. blockers lists every node currently preventing progress, with unblocker describing 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:| Parameter | Type | Description |
|---|---|---|
runId | string | Filter by run ID |
workflowName | string | Filter by workflow name |
nodeId | string | Filter by node ID |
resolve_approval
Approve or deny a pending approval. This tool is destructive and non-idempotent. Input:| Parameter | Type | Description |
|---|---|---|
action | "approve" | "deny" | required — decision to record |
runId | string | Filter to a specific run |
workflowName | string | Filter by workflow name |
nodeId | string | Filter by node ID |
iteration | number | Filter by loop iteration |
note | string | Optional note to record with the decision |
decidedBy | string | Identity of the decision-maker |
decision | unknown | Structured decision payload passed back to the workflow |
INVALID_INPUT. If the filters match more than one approval the tool errors with INVALID_INPUT and returns the list of matches in details.matches — add runId, nodeId, or iteration to narrow the selection. The tool never guesses when multiple approvals match.
Output:
get_node_detail
Get enriched detail for a single node, including all attempts, tool calls, token usage, scorer results, and validated output. Input:| Parameter | Type | Description |
|---|---|---|
runId | string | required |
nodeId | string | required |
iteration | number | Loop iteration (default: latest) |
revert_attempt
Revert the workspace and frame history back to the state captured at a specific attempt. This is destructive and non-idempotent. Input:| Parameter | Type | Default | Description |
|---|---|---|---|
runId | string | required | Run containing the node |
nodeId | string | required | Node to revert |
iteration | number | 0 | Loop iteration |
attempt | number | required | Attempt number to revert to (must be ≥ 1) |
list_artifacts
List structured output artifacts produced by nodes in a run. Input:| Parameter | Type | Default | Description |
|---|---|---|---|
runId | string | required | Run ID |
nodeId | string | — | Limit to a specific node |
includeRaw | boolean | false | Include raw (pre-validation) output values |
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:| Parameter | Type | Default | Description |
|---|---|---|---|
runId | string | required | Run ID |
all | boolean | false | Include all attempts, not just those with known output events |
includeStderr | boolean | true | Include stderr messages |
tail | number | — | Return only the last N messages |
timestampMs. Use tail to limit context window usage when transcripts are long.
get_run_events
Return the raw structured event history for a run with optional filtering. Input:| Parameter | Type | Default | Description |
|---|---|---|---|
runId | string | required | Run ID |
afterSeq | number | — | Only events with seq greater than this value |
limit | number (1–10000) | 200 | Max events to return |
nodeId | string | — | Filter to events for a specific node |
types | string[] | — | Filter to specific event types (e.g. ["NodeFinished", "NodeFailed"]) |
sinceTimestampMs | number | — | Only events at or after this timestamp |
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
All errors follow the structured envelope. Common codes:| Code | Meaning |
|---|---|
RUN_NOT_FOUND | No run exists with the given ID |
INVALID_INPUT | Missing required field, failed validation, or ambiguous approval filter |
WORKFLOW_MISSING_DEFAULT | Workflow file has no default export |
WORKFLOW_NOT_FOUND | No workflow matches the given ID |