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-mcpThis 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-desktopThis 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-mcpwrites 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.
cwdin 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 thecwdargument.
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:
- Calls
list_workflowsto findapproval-flow. - Calls
start_workflowwith its id. The runner executes script / condition nodes, pauses at the firstai_agentnode, and returns apendingStepwith the prompt. - Reads the prompt, drafts a response, calls
advance_runwith it. - Repeats until the run hits a
humannode, at which point Claude lists the valid transitions and asks you which one to take. - You answer; Claude calls
resume_runwith 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#
- the MCP tools reference — full tool schemas and examples.
- the subscription docs — where AI inference runs, and the consensus handback.
- LLM backends — the backend that server-side runs use.
- Workflow sources — the
sourceparameter on workflow tools.