Claude integration

Build, run, and manage Roscoe workflows by asking Claude.

Connect Roscoe to Claude and you can build, run, and manage workflows by asking. From an ordinary chat, Claude can turn a plain-language description into a new workflow, edit one you already have, start a run, or check how a past run went, all using Roscoe's tools behind the scenes. Setup takes one step.

Connecting Roscoe to Claude lets it drive your workflows, giving you two things. First, you drive it in plain language: describe what you want and Claude writes or adjusts the workflow for you, with no YAML to write by hand. Second, it runs on the Claude plan you already have. When Claude drives a run, your AI steps run on your existing Claude subscription, with no separate API key to set up and no extra bill to reconcile.

The connection uses MCP, the Model Context Protocol: an open standard Claude uses to talk to outside tools. You don't need to know how it works. Connect once, from the desktop app's Settings or with a single command (see Install), and Claude gains 30 Roscoe tools it can call on your behalf. Each call is scoped to one project or to your global workflows, so one connection serves everything on your machine.

Roscoe works with any MCP client, including Claude Code (the command-line tool) and the Claude desktop app. For the full list of tools, see the MCP tools reference.

Install#

There are two routes:

Compiled binary#

roscoe install-mcp

This registers a user-global roscoe entry in ~/.claude.json. Claude Code reads MCP servers from its top-level mcpServers key, so one install works in every project on your machine. The entry points at the binary's own process.execPath:

{
  "mcpServers": {
    "roscoe": {
      "command": "/Users/you/.roscoe/bin/roscoe",
      "args": ["mcp"]
    }
  }
}

User scope is the right default: the entry is identical for every project, and the machine-specific binary path stays in ~/.claude.json (which is per-machine and never committed) rather than in a shared file.

Pass --project to write a project-local .mcp.json at the current directory instead. A project .mcp.json records the same absolute process.execPath, so it's machine-specific: don't commit it to share with teammates, since their binary lives elsewhere. User scope avoids that problem entirely.

The /roscoe slash command#

The default user-global install also drops a /roscoe slash command at ~/.claude/commands/roscoe.md (the same file roscoe init writes). In Claude Code or Cowork you can then type /roscoe <workflow-name> to start a workflow, or /roscoe alone to list what's available and pick one. It's a thin entry point that tells Claude which mcp__roscoe__* tools to call. The command file is namespaced to Roscoe and refreshed on every install, so it stays current with the binary.

This is skipped for --project, --path, and --client claude-desktop: the Claude desktop app doesn't read ~/.claude/commands (it has no slash commands), so the command benefits Code / Cowork users only. The install is best-effort: a failure never fails the MCP registration.

Claude desktop app#

To register with the Claude desktop app instead, pass --client claude-desktop:

roscoe install-mcp --client claude-desktop

This writes the same roscoe entry (identical mcpServers shape) to the desktop app's own config file (creating the directory if the app hasn't been launched yet):

  • macOS: ~/Library/Application Support/Claude/claude_desktop_config.json
  • Linux: ~/.config/Claude/claude_desktop_config.json (or $XDG_CONFIG_HOME/Claude/…)
  • Windows: %APPDATA%\Claude\claude_desktop_config.json, or, for a Microsoft Store install of Claude Desktop, the per-package path under %LOCALAPPDATA%\Packages\Claude_*\LocalCache\Roaming\Claude\. install-mcp writes to whichever the installed app reads.

Restart the desktop app afterward. --client claude-code is the default, and --project only applies to Claude Code: Claude Desktop has no project-local config.

cwd in the desktop app: unlike Claude Code, the desktop app has no IDE working directory to pass automatically, so project-scoped tools resolve to your global workflows (~/.roscoe) unless you tell Claude which project directory to use. Mention an absolute path (e.g. "use my workflows in ~/dev/projectA") and Claude forwards it as the cwd argument.

From source (dev)#

The repo ships a .mcp.json at the root that runs the CLI directly via Bun:

{
  "mcpServers": {
    "roscoe": {
      "command": "bun",
      "args": ["apps/cli/src/index.ts", "mcp"]
    }
  }
}

Restart Claude Code after either change and the tools become available.

How execution works#

Standalone runs call the LLM themselves; MCP runs hand the work to Claude. At every ai_agent or ai_judge node the runner pauses and returns a pendingStep containing the full prompt and the list of valid transitions. Claude Code reads the prompt, generates a response, and calls advance_run to continue. The runner records the response, advances the state machine, and either runs to completion or returns the next pendingStep.

human nodes pause until resume_run is called with a chosen transition. Claude must wait for the user to pick one. Never advance a human node autonomously.

consensus nodes depend on the client. From Claude Code or Cowork (hosts that can spawn isolated subagents), the runner hands the fan-out back: Claude runs the agentCount reviewers in parallel and returns their verdicts via advance_consensus, and Roscoe tallies the quorum. That runs on your Claude subscription, no API key required.

From plain Claude desktop chat (no subagents) the node runs server-side instead and needs ANTHROPIC_API_KEY or the claude CLI on PATH. See the subscription docs.

Per-call project scoping#

The MCP server is long-lived and project-agnostic. One server can serve calls scoped to any repo on your machine. Every project-scoped tool takes exactly one scope argument: either cwd (absolute path to any directory inside the target project) or global: true.

With cwd, the server resolves it to the git root and isolates workflows + runs to that project. Claude Code passes the user's IDE working directory automatically, so a session in ~/dev/projectA lists projectA's workflows even if roscoe serve was started from elsewhere. Two parallel calls with different cwds see different projects without interference. See the MCP tools reference for the full contract and validation errors.

Passing neither cwd nor global is a loud error (CWD_REQUIRED); the server never silently guesses a project.

Global mode (no project directory)#

The Claude desktop app has no project/working directory, so there's nothing to pass as cwd. In that case pass global: true instead: all operations target the global store (~/.roscoe/workflows). Repo-scoped (source: "repo") operations are unavailable in global mode, so a workflow tool's source/target_source can be omitted: it defaults to the global store. (move_workflow's to still names an explicit destination.)

The server advertises this convention via its MCP instructions, so Claude generally picks the right scope on its own. Runs started in global mode are tracked in a shared global namespace, isolated from project runs (and they don't capture per-commit git metadata).

Build one by asking#

You: Make a workflow that handles a customer refund. Check the request against our 30-day return policy, and if it's a close call, have three AIs vote before it's approved.

Claude turns that into a real workflow, checks it, and saves it with create_workflow. Want a change later? Say so:

You: Pause for a person to sign off on any refund over $500.

Claude edits the file with update_workflow. You never open the YAML yourself.

Run one#

You: Run the approval-flow workflow.

Behind the scenes Claude:

  1. Calls list_workflows to find approval-flow.
  2. Calls start_workflow with its id. The runner executes script / condition nodes, pauses at the first ai_agent node, and returns a pendingStep with the prompt.
  3. Reads the prompt, drafts a response, calls advance_run with it.
  4. Repeats until the run hits a human node, at which point Claude lists the valid transitions and asks you which one to take.
  5. You answer; Claude calls resume_run with your choice; the run completes.

Tools at a glance#

Names plus one-line purposes. Full input/output schemas are in the MCP tools reference.

Workflow CRUD#

Tool Purpose
list_workflows List all workflows with source and shadowed flags
get_workflow Read one workflow's full config
create_workflow Write a new workflow YAML; refuses on collision
update_workflow Replace an existing workflow with a validated new config
delete_workflow Delete a workflow file (requires literal confirm: true)
move_workflow Move a workflow between Global and Project sources
duplicate_workflow Copy a workflow under a new id, optionally to the other source
rename_workflow Rename a workflow's id (file stem) and name field
list_workflow_references List workflows that reference a given one via subworkflow; check before deleting or renaming

Authoring helpers#

Tool Purpose
get_workflow_schema Returns the JSON Schema, executor list, and configured models
validate_workflow Dry-run schema + integrity validation (no FS writes)
lint_workflow Validation plus warnings (dead states, unknown models, unreachables)

Run lifecycle#

Tool Purpose
start_workflow Start a run; returns { runId, status, pendingStep? }
get_run_status Current status plus the pendingStep if paused at an AI node
advance_run Supply Claude's response to an ai_agent / ai_judge pause
advance_consensus Supply host subagents' verdicts to a consensus pause (Claude Code / Cowork)
advance_round_robin Supply host subagents' matchup verdicts to a round_robin pause
advance_map Supply host subagents' branch/reduce results to a map pause
resume_run Resume a human pause with a chosen transition (wait for user)
cancel_run Cancel a running or paused workflow

start_workflow accepts optional spending_cap_usd and spending_cap_tokens. When set, the run is stopped (status cancelled, stop_reason spending_cap_exceeded) once its running total cost or token count exceeds the cap. That bounds consensus / map / round_robin fan-out and nested sub-workflows, and subscription runs too. Caps are off unless supplied (or declared as a default in the workflow YAML). advance_run accepts an optional usage object (inputTokens / outputTokens / cacheCreationTokens / cacheReadTokens / costUsd); supply it when you know the real figures so a subscription handback node records its exact API-equivalent cost instead of an estimate. The run-status / advance payloads carry the cost rollup (totalCostUsd, meteredCostUsd, subscriptionEquivCostUsd, billingMode, token totals).

Run observability#

Tool Purpose
list_runs Recent runs newest-first; filter by workflow, status, since, kind
get_run_history Full per-node trace with timestamps, IO, errors, child sub-runs

Verification#

Tool Purpose
test_workflow Run end-to-end with mocked AI/human responses and auto-cleanup of the run row

Docs#

Tool Purpose
list_docs Enumerate documentation pages
get_doc Fetch the markdown source of one page
search_docs Free-text search across the docs (ranked snippets)
ask_docs Natural-language question → ranked full heading sections within a char budget (knowledge-base lookup)
answer_docs Natural-language question → synthesized prose answer with citations (wraps ask_docs + LLM backend)

Skills#

Tool Purpose
list_skills Find agent skills (SKILL.md convention) on this machine, across harnesses
convert_skill Convert a skill's markdown + scripts into a Roscoe workflow

See also#

View this page as Markdown

Predictable workflows from unpredictable AI