MCP tools
With Arugula’s MCP tools, Claude Code (or Codex, or any MCP client) can run builds and dev servers in panes you can watch from your phone and take over, wait on them, start and answer other agents, show you diffs, pull requests and issues, write you a Doc, and search what happened yesterday.
Adding it
Section titled “Adding it”Add Arugula’s MCP server to your agent with one command.
claude mcp add arugula -- arugula mcparugula setup claude (or Use Claude Code with Arugula in Getting
started) does this for you.
Or install Arugula’s Claude Code plugin, which adds this server along with the hooks and a short skill:
/plugin marketplace add arugula-salad/arugula/plugin install arugula@arugulaThe plugin’s tools are named mcp__plugin_arugula_arugula__*, not
mcp__arugula__*, so use those names in permission rules. If Claude Code
already runs arugula mcp from claude mcp add, it keeps that copy and drops
the plugin’s. A server you added by path (for example with Use Claude Code
with Arugula) runs alongside the plugin’s, and arugula hooks status tells
you to remove it.
codex mcp add arugula -- arugula mcparugula mcp relays to the daemon’s own MCP server over its socket (or
another daemon’s, with --host), so the client can start and stop it at any
time, and a daemon restart doesn’t break it. Started in a pane, it knows
which pane it’s in, so run can split beside it.
Permissions
Section titled “Permissions”The read-only tools are safe to allow outright; leave the rest to ask. In
Claude Code, put this in ~/.claude/settings.json (or a project’s
.claude/settings.json):
{ "permissions": { "allow": [ "mcp__arugula__read_output", "mcp__arugula__wait", "mcp__arugula__list", "mcp__arugula__capabilities", "mcp__arugula__history", "mcp__arugula__read_forge", "mcp__arugula__forge_read", "mcp__arugula__read_invite", "mcp__arugula__read_file", "mcp__arugula__read_cloud", "mcp__arugula__read_thread", "mcp__arugula__search_threads", "mcp__arugula__read_run", "mcp__arugula__read_deploy" ], "ask": [ "mcp__arugula__run", "mcp__arugula__send_input", "mcp__arugula__attach", "mcp__arugula__close", "mcp__arugula__show", "mcp__arugula__doc", "mcp__arugula__start_agent", "mcp__arugula__prompt_agent", "mcp__arugula__agent_respond", "mcp__arugula__draft", "mcp__arugula__forge_draft", "mcp__arugula__invite_person", "mcp__arugula__device_call", "mcp__arugula__cloud", "mcp__arugula__link_repo", "mcp__arugula__post_thread", "mcp__arugula__issue_write", "mcp__arugula__start_run", "mcp__arugula__plan_deploy" ] }}Each tool also says whether it’s read-only or destructive, so a client’s own permission settings can tell them apart.
The tools
Section titled “The tools”list, show and draft take a kind argument that picks what they do;
each tool’s description lists its kinds and arguments.
| Tool | What it does | Key arguments | Read-only |
|---|---|---|---|
run |
Runs a command in a new tab or split, typed into a shell so it’s in history and you can take over. With wait, returns its exit code and last lines. |
command, cwd, split, session, policy, wait |
no |
send_input |
Types text (and Enter, unless enter: false) or named keys (C-c, Up) into a pane; to an agent block, sends its next prompt. |
pane, text, keys |
no |
attach |
Puts a file into a pane: into a terminal, its path is pasted where a shell or an agent reads it; to an agent block, it goes with text as the next prompt, an image as an image. |
path or base64 data, force |
no |
read_output |
Returns a pane’s output as text: the latest, from an offset, or its last command’s. Paged, 16,000 characters at a time. |
offset, last_command, screen |
yes |
wait |
Waits for command_end, exit, match, idle or needs_input, or for a Cloud workspace’s tab to be idle or needs_input. After timeout seconds (100 by default) it answers “still running” with the offset: call it again. |
pattern, timeout, cloud_workspace, tab |
yes |
list |
Lists panes (the default), Claude Code conversations, the user’s devices that lend tools, their Cloud workspaces (cloud_workspaces), a workspace’s tabs (cloud_tabs), the GitHub repos linked to their projects (linked_repos), and the conversations in control this machine’s agents may read (threads). |
kind |
yes |
capabilities |
Says what this machine offers an agent: the blocks it can open, its tools and Labs features, the forges the user is signed in to, whether Claude Code’s hooks are live in the calling pane, and whether the machine is joined to control or a team. Worth calling first. | yes | |
close |
Closes a pane or block. | pane |
no |
history |
Commands across panes, and answers and approvals with who gave them; or, with kind: "output", lines of output matching a pattern. |
kind, failed, since, before, cwd, match |
yes |
show |
Opens a block beside a pane: a browser on a port, changes (a diff), a file, a pr or issue, a Claude Code conversation, or the team’s chat (one room of it, pinned, with room). |
kind, beside |
no |
doc |
Builds a Doc in a block beside the pane: new (its outline), fill (a section), asset (a picture), list and open (an earlier one), share (asks the user for a link). See Docs. |
kind, block, section |
no |
start_agent |
Starts an agent block (Claude Code, Codex, any ACP agent) with a prompt. | allow, permission_mode |
no |
prompt_agent |
Prompts an agent (a block, or Claude Code or Codex in a terminal) and waits through its turn: done, needs_input with its question, or stalled. |
answering |
no |
agent_respond |
Allows or denies an agent’s pending request, or answers or skips its question. | no | |
read_forge |
Returns a pull request or issue block as text: what it waits on the user for, and the drafts. | yes | |
draft |
Drafts a comment, a review or merge of a pull request, or a new issue: a card the user sends, edits or drops. |
kind |
no |
forge_read |
Reads PRs, issues, a PR’s checks, drafts and the user’s inbox on GitHub repos linked to their projects in control, with no block open. Only what GitHub lets the user read. | kind, item |
yes |
forge_draft |
Drafts a comment, a review or a new issue on a linked repo, or discards a draft. Agents draft; only people send, from the web page, their phone or the CLI. |
kind, item |
no |
invite_person |
Asks to bring someone into the pane’s session: a card only the session’s owner sends or declines. | who, role, note |
no |
read_invite |
Says what became of an invite draft: waiting, sent, declined, dropped or failed. |
yes | |
read_file |
Reads a text file on this machine or a pane’s machine, paged. | yes | |
read_cloud |
Reads one of the user’s Cloud workspaces: a tab’s transcript (events) or what it asks (requests), or its machine’s files, a file, the diff or git_status; diff and git_status read its first repository unless given a path. Reading wakes a paused machine. |
cloud_workspace, tab, kind |
yes |
cloud |
Drives the user’s Cloud workspaces: create one, open_tab, prompt a tab and wait through its turn, interrupt it, answer what it asks, close_tab or rebuild. Changing a workspace’s settings or deleting it stays on control’s page. |
cloud_workspace, tab, kind |
no |
link_repo |
Links a GitHub repo to one of the user’s projects in control, or unlinks it. Linking takes admin or maintain on the repo; unlinking purges its rows within a day. | kind |
no |
device_call |
Uses a tool on one of the user’s devices, for example taking a photo or getting the phone’s location, which the user allows or denies there (Phone). | no | |
read_thread |
Reads a conversation in control that the user let this machine’s agents into: a team channel, a direct message, or an issue’s or pull request’s thread (list with kind: "threads" lists them). Paged by seq; mentions_only reads the messages that mention this machine’s agents. |
room, after_seq, mentions_only |
yes |
search_threads |
Searches the conversations this machine’s agents may read: words (mea* for a prefix), in:#channel, from:@login, has:quote. Newest first, at most 50. |
q, team |
yes |
post_thread |
Posts in a conversation where the user let this machine’s agents post, or comments on an issue or pull request in its thread. Everyone there sees it as the user’s agent on this machine. | room, text |
no |
issue_write |
Writes to a project’s own issues in control, at once, as the user’s agent on this machine: create, comment, edit, label, assign, close or reopen. GitHub’s stay drafts (draft, forge_draft). |
kind, project |
no |
start_run |
Starts a run on one of a project’s Cloud workspaces: a run spec by name, a command, or an instruction to Claude Code. It runs there, in a pane the project’s people watch, as started by the user, and the call returns its run_… id at once; wait with run follows it to its end. |
project, spec, command, instruction, box |
no |
read_run |
Reads a run: its state, exit code, timeline and a page of its log by byte offset. Without run, a project’s latest runs. |
run, project, state, offset |
yes |
plan_deploy |
Plans a deploy of a commit to one of a project’s environments and asks the project’s owners to approve it. Returns the plan’s text and the deploy’s dep_… id. It never approves: an owner does, on their phone or in a browser, with a passkey. |
project, environment, commit, repo, roll_back |
no |
read_deploy |
Reads a deploy: where it goes, what it deploys, its plan, its state (waiting for approval, running, succeeded, failed, denied, stale and so on) and its log. Reading never approves. | id |
yes |
doc builds a Doc, a report, plan or write-up longer than a
screen, in a block the user watches fill in. Agents write Docs only
through the tool, never its files by hand.
| Kind | What it does |
|---|---|
new |
Makes the Doc beside the caller’s pane (or beside), with a title and every section’s heading and intent at once (at most 40). Returns the block and the section ids, s1, s2 and so on. |
fill |
Writes one section’s Markdown (at most 64 KB; a Doc at most 1 MiB). Filling it again replaces it. No HTML. |
asset |
Puts a PNG, JPEG, GIF or WebP into the Doc (at most 2 MB, 20 a Doc), from a path or as base64 data. A section shows it as ; an SVG file is refused. |
list |
The machine’s Docs, to go on with one. |
open |
Opens one from list beside the pane, or answers with the block it’s already in. |
share |
Asks the user to share the Doc with a link: a card on the Doc, and nothing is published until they choose Share. Answers waiting at once; call it again for shared (with the link), declined, lapsed (nobody answered in a day) or failed. |
Besides Markdown (headings, lists, tables, links), a section can hold a
callout (a quote starting [!NOTE], [!TIP], [!IMPORTANT], [!WARNING]
or [!CAUTION], as on GitHub) and three fences that draw: ```stats
(one to six stat tiles), ```chart (a bar or line chart from a JSON
spec) and ```svg (one drawing, shown as a picture). Their colors are
named (leaf, pepper, sky, plum, sun, stone, ink, paper), so
a Doc reads in light and dark. Each fence is checked before anything is
written: a bad one is refused with what to fix, and the section stays as
it was.
Resources: arugula://history, and the templates
arugula://pane/{id}/output, arugula://pane/{id}/screen and
arugula://block/{id}.
- Long waits. A
waitsends a progress notification every 15 seconds (over HTTP, Claude Code drops a call that’s silent for 60 seconds), and answers “still running” well before any client’s limit. - Clear errors. Errors say what happened (“pane %7 is gone; its last
command
makeexited 2 3m ago”). - Who did it. Every call is logged with the client’s name. A pane or
block an MCP client started says “started by mcp:{client}”
(
mcp:claude-code, say), and what it typed is in history as theirs.
Cloud workspaces
Section titled “Cloud workspaces”A Cloud workspace is a machine in one of the
user’s projects, with an hw_… id. list with kind: "cloud_workspaces"
lists them; cloud with kind: "create" makes one in a project. Its tabs
are the agent blocks on its machine, by pane number, and the project’s
people see the same blocks.
run, start_agent, prompt_agent, agent_respond, send_input,
read_output, read_file, wait, show, close and list take
cloud_workspace (its id or its name) to work on its machine instead of
this one: run a build there, start an agent, read its output. Its panes
and blocks are that machine’s, so pass cloud_workspace again to reach
them. A paused machine wakes for a call.
Your machine reaches it through control’s relay, only while it holds a
live cloud.drive grant (arugula grants). The workspace lets in the
machines of its project’s owners and editors, as their person; a viewer’s
machine reaches only its agents.
Agent blocks
Section titled “Agent blocks”Agent blocks get the tools without any setup, with a token of their own that reaches only the block’s tab. An agent can start panes and blocks there, drive and close what it started, and read the rest of its tab; other tabs are refused. The token ends with the block.
An agent session’s tools
Section titled “An agent session’s tools”An agent session on a project’s Cloud workspace (one started by
Agent on this or @arugula in a thread) gets
none of the tools above: they start and drive panes as the machine’s
owner. It gets a server of its own instead, on its workspace, with six
tools over its project’s own issues and Docs:
| Tool | What it does |
|---|---|
read_session_issues |
Lists the project’s issues, newest first (by state, labels, words in q), or reads one (#N) with its timeline and newest comments. |
comment_session_issue |
Comments on one of them. It can’t edit, label or close an issue. |
create_session_issue |
Opens a new issue, with labels the project already uses. Nobody is assigned or notified; it returns the link to post. |
create_session_doc |
Makes a Doc in the project, with every section’s heading and Markdown (or an intent to fill later). Returns its id, its sections’ ids and its link. |
fill_session_doc |
Writes a section of a Doc the session made, or adds one at the end. |
read_project_doc |
Lists the project’s Docs, or reads one as Markdown. |
They act in that project only, with the rights of the person who asked for the session, and what they write is labelled as the session’s own. The workspace tells which session is calling by the user its agent runs as, so there’s no token for an agent to leak.
Over HTTP
Section titled “Over HTTP”The daemon also serves the tools at /mcp (Streamable HTTP). On the same
machine, prefer arugula mcp. From your own devices on your tailnet,
nothing more is needed:
claude mcp add --transport http arugula https://{machine}.{tailnet}.ts.net/mcpA client without a tailnet identity of its own (a tagged node, a container) needs a token:
arugula mcp token --name ci # prints ilm_…, onceclaude mcp add --transport http arugula https://{machine}.{tailnet}.ts.net/mcp \ --header "Authorization: Bearer ilm_…"arugula mcp token --list # tokens, and when each was last usedarugula mcp token --revoke ci # its next call is refused--scope read makes a token that sees and calls only the read-only tools.
arugula mcp --token T (or ARUGULA_MCP_TOKEN) sends one through the stdio
bridge.