tori mcp is a stdio MCP server that exposes Tori itself as a set of tools:
listing sessions, reading a transcript, starting a worktree, creating a
checkpoint diff, asking you a question and waiting for the answer, opening a
pull request. Every tool call becomes one call on the same protocol the
tori CLI and the phone app use, so there is one source of truth for what
Tori can do, not three.
How a session gets it
A Claude session gets it automatically: Tori writes a small MCP config file
naming tori mcp as a server and passes it on launch. An ACP agent (Codex,
OpenCode today) gets it the same way, sent as part of its own session setup,
only for adapters measured actually calling a server they were handed. A
worker session autopilot spawned gets the same tools, with outward actions
(opening a pull request, submitting a review, merging) gated behind an
approval you gave beforehand rather than a permission prompt mid-task, since
nobody is watching a background worker’s chat directly.
The server also tells the agent, as it connects, to use Tori’s tool where
there is one instead of the shell: worktree_new rather than git worktree add, session_spawn to start another agent, the pull request tools rather
than gh pr, and ask_create to ask you. That keeps the sidebar, the
project’s setup command, approvals and checkpoints in step. It also says a
refused tool is to be taken at its word, not worked around from the shell,
and asks the main agent, never a subagent, to publish a plan of several steps
with plan_set and keep it up to date.
Claude reads this; whether another agent does depends on the agent. It is
guidance, not a lock: nothing stops an agent from running git itself.
What it will not do without you
Anything that leaves the machine, a pushed branch, a posted review, a merge, needs an approval reserved for that exact action and exact draft content ahead of time. A worker cannot invent its own approval, spend one meant for something else, or reuse one twice.
Reading a session’s tools
Every tool an agent can see is scoped to what kind of caller it is; a worker session, for instance, never sees the tools that would let it spawn another session or start or stop autopilot itself. From inside Tori, a session’s overflow menu > Session shows the live MCP servers it has connected, including this one, and how many tools each exposes.
Every tool
Tool names are the method names with the dot as an underscore, so
session.spawn is the tool session_spawn, which Claude shows as
mcp__tori__session_spawn. The last column is who may call it: a shell
is a terminal tab or a script, a chat is a session you drive, a
worker is a session another session spawned, the phone is a
paired device, and the browser is the
browser extension. Everyone means shell,
chat and worker; the phone and the browser are named wherever they are
included.
| Tool | What it does | Who may call |
|---|---|---|
sessions.list |
Sessions, newest first, with whether each is live and its state | Everyone, phone and browser too |
session.tail |
The last events of a conversation, tool output capped. A chat may only read a related chat or one you referenced | Everyone, phone and browser too |
session.history |
A conversation a page at a time, by whole turns, with the same rule as session.tail for chats |
Everyone, phone too |
session.wait |
Wait for a session to stop working; its state, why it came back (ended, idle, asking, needs_you, limited with when the limit resets, or timeout), its pending question, its last message, and handed_to once it was handed over. A chat waits only on a session it owns |
Shell, chat |
session.check |
What a session’s work came to: the verification verdict and checks of its latest turn that changed code, and a diff stat over all its turns in files it wrote | Everyone |
session.handoff |
Hand a live chat over to another agent: a new session in the same folder with a brief of the old one’s work, and the old one closed once it is idle. Refused for a session the autopilot drives | Shell, chat |
session.pending |
What a session is waiting on, each with its id. A chat reads only a session it owns | Shell, chat, phone, browser |
session.answer |
Answer a question or permission prompt of a session you spawned | Chat, phone |
session.spawn |
Start a session, optionally in a new worktree, with a first message and files. From a terminal tab or a shell outside Tori, a mode that runs tools without asking needs an approval. A chat cannot start one in a mode freer than its own: a chat that asks cannot start a worker in bypassPermissions or Claude’s auto |
Shell, chat, phone (a plain chat only) |
session.steer |
Send a message to a live chat, as a steer or as its next turn, with files. From a chat, a message to a chat it is not allowed to reach answers queued and waits for you. From a terminal tab or a shell outside Tori it arrives as a Tori note naming the tab or “a shell outside Tori”. The browser’s files must be ones attachment.write stored, and it may not wake a chat that is not live |
Shell, chat, phone, browser |
session.interrupt |
Stop a live chat’s current turn. A chat stops only a session it owns | Shell, chat, phone |
session.info, session.model |
Read or switch a live chat’s model | Outside shell, phone |
session.mode |
Switch a live chat’s permission mode | Phone |
caller |
Who is calling: the session or tab, its agent, account and folder, and made_by, the chat that made its worktree |
Everyone, phone and browser too |
projects.list |
The tree the sidebar draws, then Topics with their members | Everyone, phone and browser too |
project.icon |
The image a project’s row shows | Everyone, phone too |
ports.list |
Each worktree’s dev servers: branch, folder, port block and listening ports | Everyone, browser too |
worktree.at |
The worktree serving a localhost port, with its project and space, or nothing | Everyone, browser too |
worktree.new |
Create a worktree on a new branch, from an issue or a pull request if given | Everyone |
window.open |
Open a file in Tori’s editor | Everyone |
window.reveal |
Bring Tori’s window forward on a chat’s tab | Browser |
chat.draft |
Open a new chat draft in Tori in the tab’s worktree, with text and files as chips, for you to send | Browser |
web.setup |
The tab’s app in its worktree: framework, bundler, and the code-inspector-plugin line and install command, or nothing | Browser |
attachment.write |
Write a file into Tori’s attachments in base64 chunks, at most 8 MB, for session.steer and chat.draft to carry |
Browser |
budget |
Spend against your ceilings, the agent’s quota windows, and with item or pr what an autopilot item or a pull request cost |
Everyone |
checkpoints.list, checkpoint.diff, checkpoint.revert |
A session’s per-turn checkpoints: list, diff, revert. checkpoint.diff with why also says who wrote each hunk |
Everyone |
provenance.hunks |
Who wrote each hunk of a file in a worktree: the turn, the tool call and the agent’s words before it, or why nothing recorded can say | Everyone |
ask.create |
Ask you a question in the calling chat and wait. A terminal tab or a shell outside Tori may only ask for an approval, which shows in the tab or in a dialog | Chat, worker; terminal and outside shell for an approval only |
plan.set |
Show the calling chat’s plan in its plan card: every step each call, pending, in progress or completed, replacing the last list. An empty list hides it. Refused outside a turn | Chat |
ask.wait |
Wait for the answer to a question asked earlier | Everyone |
ask.answer |
Answer another session’s question on your behalf. A chat answers only for a session it owns, and a terminal tab answers none; a chat or terminal that may not answer sees the question without its id | Terminal tab, chat, phone, browser. Never an outside shell |
issues.assigned |
Open issues assigned to you in the project’s issue repos, its own repo when none are listed, then pull requests waiting on your review | Everyone |
issues.get |
One issue: title, body, url and a suggested branch name. Given a URL, it finds the project by the repo’s origin, or the one project whose issue sources read that repo | Everyone |
issues.link_branch |
Make a branch on the host under an issue and fetch it | Shell, chat |
pr.get |
One pull request to review, with the lines a comment may anchor to | Shell, chat |
pr.create |
Push an exact commit, never forced, and open a pull request | Everyone; a background session, a terminal tab or a shell outside Tori needs an approval |
review.submit |
Submit a review: a verdict, a body and line comments | Everyone; a background session, a terminal tab or a shell outside Tori needs an approval |
pr.push |
Push an exact commit, never forced, onto an open pull request’s branch on origin | Everyone; a background session, a terminal tab or a shell outside Tori needs an approval, except the autopilot fixing its own pull request under a project’s fix loop |
pr.merge |
Merge a pull request at the head commit given | Everyone; a background session, a terminal tab or a shell outside Tori needs an approval |
pr.check_log |
What a failed check left to read: the last 300 lines of a GitHub Actions job’s log, or another check’s summary and link | Everyone |
pr.watch, pr.unwatch |
Watch a pull request and be woken with its news | Chat, and only with the setting on |
topic.member.promote |
Give a Topic member a worktree so the chat can change it | Chat, worker |
autopilot.state |
The autopilot’s queue | Everyone, phone too |
autopilot.item.update, autopilot.project.set, autopilot.hold.resolve |
Update a queue item, set a project’s contract, withdraw a hold | Shell, chat |
autopilot.loop |
Queue one ship item per entry of a list, the prompt as each one’s task; an entry already open is skipped. See Loops | Shell, chat |
autopilot.start, autopilot.stop |
Turn the autopilot on or off | Outside shell, phone. Never an agent session or a terminal tab |
autopilot.schedule.list |
The schedules, each with when it fires next | Everyone |
autopilot.schedule.add, autopilot.schedule.remove |
Add or remove a schedule | Shell, chat |
autopilot.schedule.resume |
Resume a schedule three failed runs paused | Shell only. Never an agent session |
A few methods exist only for the phone’s screens and are on no agent’s tool list: the git standing of each worktree, the pull request line of each branch, and the autopilot’s log. Pairing a device can only be done from the Mac itself.
A tool a caller may not use is left off its list rather than listed and
refused. A worker that still reaches for one is told why: a worker never
spawns or steers, it finishes its turn and its spawner reads the result. A
worker can still check a session’s work with session.check.
The CLI
tori mcp is also a subcommand of the plain tori CLI, alongside commands
for listing sessions, tailing a transcript, creating a worktree, and the
rest of the same tool surface from a shell instead of an agent. Run tori mcp yourself to start the server directly, useful for wiring a session up
by hand outside of Tori’s own launch flow.