Connect an AI agent (MCP)
Drive Marshal from the AI agent you already use. Connect Claude Code or Codex on your laptop, or a headless agent in CI, and it can do what you do in the web app: start runs, follow them, steer them, answer the questions they ask, manage your spaces, deputies, manifests and connections, and for admins, run the org. It acts as the person who signed in, with that person’s permissions.
The endpoint is on the same host as the web app:
https://<your-marshal-host>/mcpEach install has its own endpoint. Give your people this address.
An agent connected over MCP sees only what the signed-in person sees in the web app. A connection never raises anyone’s role and never reaches another org.
What you can do with it
- Hand off a task and keep coding. In Claude Code: “Start the release-notes mission on our
docs deputy, and tell me when it asks something.” The agent starts the run (
runs_launch), follows it (runs_wait), and shows you the question when the run asks one. You answer in the same chat, and the agent passes your answer on (inbox_answer). The run continues. - Find out why a run failed. “Why did my last run fail?” The agent lists your runs
(
runs_list), reads the failed one (runs_get) and its output (runs_logs), and checks the space it ran in for restarts or out-of-memory stops (spaces_get). You get the cause, not a page of logs. - Clear your inbox from one place. “What is waiting for me?” The agent lists the open asks
from your runs (
inbox_list), and answers the ones you decide on (inbox_answer). - Get answers from the docs. “What does Marshal recommend for space compute sizes?” The agent
searches the official docs (
docs_search), reads the page (docs_read), and answers with the link.
See it end to end: Delegate from your AI client.
Step 1: an admin turns MCP on
MCP access is off in every org until an owner or admin turns it on, in Organization settings > General, card MCP access. Until then, an agent that tries to connect is told to ask an org admin.
| Switch | Default | What it does |
|---|---|---|
| Allow MCP access | Off | When off, no agent can connect, and every agent already connected in this org is refused on its next call. |
| Agents may answer approval gates | Off | When off, agents answer ordinary questions only. Approval and takeover asks wait for an answer in the web app or Slack. |
| Agents may approve blocked domains and tools | Off | When off, an agent that hits a blocked domain or tool can only report it. Approving it for a space stays in the web app. |
| Require approval for every launch | On | When on, an agent asks you before it starts a run or a space, and API keys and apps that cannot show a confirmation prompt cannot launch. When off, agents and API keys launch without asking. |
The approval switches are separate on purpose. An agent reads text that runs produce, so text inside a run can try to steer it. Keep approval gates and policy approvals for people unless you decide otherwise.
Every run and space uses compute and AI tokens, so a person approves each launch by default. Turn Require approval for every launch off when you want unattended launches, such as an API key in CI. Marshal asks you to confirm the change first. With approval off, an agent can start several runs in a row on its own. Runs it starts still count toward the run cap, and every launch is in the audit log.
The switches are stored as mcp.access_enabled, mcp.answer_approval_gates,
mcp.policy_approvals and mcp.launch_without_approval (the inverse of Require approval for
every launch) in the org’s settings.
Step 2: connect your agent
Marshal shows the exact commands for your install, with your address filled in:
- Connect agent, in the top bar on every page. It opens the same commands, with a tab for Claude Code and a tab for Codex, and a link to your connected apps. Once you have connected an agent, it shrinks to an icon.
- Personal settings > Connected apps, card Connect an agent, with a tab for Claude Code and a tab for Codex. Select the copy button next to a command.
- Home, when you have no connected app yet. The card there shows the Claude Code command and links to the full card.
Claude Code
Add the server once:
claude mcp add --transport http marshal https://<your-marshal-host>/mcpThe first tool call opens your browser (/mcp inside Claude Code starts the same flow). You sign
in to Marshal as usual, then approve the consent page.
What you approve
After you sign in, a consent page asks:
- which org this connection is for. One org per connection.
- which permissions to grant. See the five permissions.
The page names the client and the host its identity comes from. A client whose host is not on the install’s verified list is marked Unverified, and only Read starts ticked. Tick the others yourself if you want them.
Manage your work and Org admin are never ticked for you, for any client. You opt in on purpose, because they change things. Org admin is shown only to owners and admins.
Select Approve, and the client is connected. Nothing has to be registered in Marshal first.
An app connected earlier holds Read, Launch and Answer only. To use the manage and admin tools, reconnect the app and approve Manage your work (and Org admin, for admins).
What the agent can do
Every tool needs exactly one of five permissions, so a Read-only connection cannot start, stop, change or delete anything.
The five permissions
| Permission | On the consent page | What it covers |
|---|---|---|
| Read | Read | See runs, logs, spaces, deputies, manifests, audit events and the inbox, and read the Marshal docs. |
| Launch | Launch and stop runs | Start runs from deputies and manifests, steer them and stop them. |
| Answer | Answer your inbox | Answer the questions runs and agents ask, in your name. |
| Manage | Manage your work | Create, change and delete your own spaces, deputies, missions, schedules, memory, manifests and connections. |
| Admin | Org admin | Org admin actions: packages, members, teams, policies, compute and the admin dashboards. |
Manage and Admin are never pre-ticked on the consent page, and Admin is offered only to owners and admins. Your role still decides each call: an agent never does more than the person it acts for.
Every tool
The Lowest role column is the lowest org role the tool is listed for. Member means any member. Admin means owners and admins. A tool that asks you to confirm shows you what will happen first, and declining changes nothing. Deputy tools appear when deputies are enabled for your org.
Runs
Start, follow, steer and continue runs.
Name every run you start. A title such as Fix flaky checkout test shows in the runs list, in the web app and in marshal runs list, so runs from the same mission are easy to tell apart. A launch that waits in a mission’s queue shows its title there too, and the run keeps it when it starts. A title can be up to 120 characters. A launch without a title still starts, and the answer asks you to name the next one.
| Tool | What it does | Permission | Lowest role | Asks you to confirm |
|---|---|---|---|---|
runs_launch | Start a run from a deputy mission (with optional notes for that run only), or from a manifest with a task. Pass a title to name the run. | Launch | Member | Yes, unless launch approval is off |
runs_wait | Wait for news on a run and return the events after a cursor. summary returns only the state and the agent’s last message. | Read | Member | No |
runs_get | Read one run: its result once it ended, state, what started it, deputy, mission, manifest, task and timing. brief leaves out the task, manifest and who started it. | Read | Member | No |
runs_list | List runs with the web app’s filters. scope=org needs owner or admin. Each task shows its first 80 characters; task_chars changes that. | Read | Member | No |
runs_stop | Cancel a run that has not ended. | Launch | Member | No |
runs_logs | Read what a run printed. | Read | Member | No |
runs_usage | What a run’s agent has cost so far: estimated USD and tokens by provider and model, and per conversation. | Read | Member | No |
runs_attention | Everything that needs you now, in one call: your open asks, one line each, and runs that failed or timed out in the last minutes (default 60), or are parked. scope=org needs owner or admin. | Read | Member | No |
changes_since | What changed since your last call: runs created, started or ended and asks raised or resolved, oldest first, with a cursor for the next call. scope=org needs owner or admin. | Read | Member | No |
runs_message | Send a message to a running run’s agent, queued for the end of its turn or, with interrupt, read now. While the run waits on an ask the message is attached to that ask and the agent reads it with your answer (attached_to_ask). | Launch | Member | No |
runs_interrupt | Stop the step a running run’s agent is on and let it read what is queued. | Launch | Member | No |
runs_take_wheel | Take over a run you own or share a team with, to drive it by hand. | Launch | Member | Yes |
runs_timeout | Add time to a live run’s timeout, pause the timeout clock, or resume it. | Launch | Member | No |
runs_rename | Give a run’s whole chain a new name. | Launch | Member | No |
runs_continuation | Whether a finished run can be continued, and what continuing would do (working tree carried over, depth). | Read | Member | No |
runs_chain | Every run of one chain, oldest first: the original and each continuation, with status and a short task. Give any run of the chain. | Read | Member | No |
runs_lineage | The run this one continues, and every run that continues it. | Read | Member | No |
runs_changes | The files a run changed, per checkout; give path (and repo, group) for one file’s patch. | Read | Member | No |
runs_continue | Start a new segment of a finished run’s conversation with a follow-up task. | Launch | Member | Yes, unless launch approval is off |
deputies_run_adhoc | Start a one-off task on a deputy, keeping its context and memory. Pass a title to name the run. | Launch | Member | Yes, unless launch approval is off |
runs_cancel_queued | Cancel a launch that is still waiting in a mission’s queue. | Launch | Member | Yes |
Inbox and agent requests
Answer what runs and agents are waiting on you for.
| Tool | What it does | Permission | Lowest role | Asks you to confirm |
|---|---|---|---|---|
inbox_list | List the open asks put to you. brief gives one line per ask. | Read | Member | No |
inbox_answer | Answer one ask, in your name. | Answer | Member | No |
inbox_all | Everything waiting on you: asks, space agent requests, preview reviews. | Read | Member | No |
inbox_count | How many items are waiting on you: the number on the web inbox badge. | Read | Member | No |
inbox_get | One ask in full: its question, choices, state and whether you may answer it here. | Read | Member | No |
inbox_reply | Answer an ask as you; the run continues. | Answer | Member | No |
inbox_claim | Take the first-responder lock on an ask so nobody else works it. | Answer | Member | No |
inbox_dismiss | Close an ask nobody will answer; the run carries on told nothing. | Answer | Member | No |
inbox_wake | Bring a parked run back so you can look before you answer its ask. | Answer | Member | No |
spaces_requests_list | The questions and documents an agent in your space is waiting on you for. | Read | Member | No |
spaces_requests_get | One agent request in full, with the draft comments people have added. | Read | Member | No |
spaces_requests_respond | Settle an agent request in your space as you: answer an ask, or submit annotations on a document. | Answer | Member | No |
spaces_requests_dismiss | Close an agent request nobody will answer; the agent is told it went unanswered and carries on. | Answer | Member | No |
spaces_requests_comment | Add a draft comment on lines of an annotate request, as you. | Answer | Member | No |
spaces_reviews_list | The preview reviews open on your space, newest first. | Read | Member | No |
spaces_reviews_submit | Finish a preview review with the comments gathered; any waiting agent continues with them. | Answer | Member | No |
spaces_reviews_cancel | End a preview review with no verdict so a waiting agent stops waiting. | Answer | Member | No |
Spaces
Create, resize and manage your spaces.
| Tool | What it does | Permission | Lowest role | Asks you to confirm |
|---|---|---|---|---|
spaces_get | Read the space a run executed in: restarts, out-of-memory stops, why it stopped. | Read | Member | No |
spaces_list | List your spaces: id, name, state, when each started and stopped. | Read | Member | No |
spaces_archived | List your archived spaces. | Read | Member | No |
spaces_create | Start a new space from a manifest. | Manage | Member | Yes, unless launch approval is off |
spaces_fork | Start a new space from a copy of an existing space’s workspace disk. | Manage | Member | Yes, unless launch approval is off |
spaces_rename | Give one of your spaces a new name. | Manage | Member | No |
spaces_stop | Stop a running space. | Manage | Member | No |
spaces_resume | Start a stopped space again from its kept workspace. | Manage | Member | No |
spaces_archive | Stop and archive a space. | Manage | Member | Yes |
spaces_restore | Bring an archived space back to stopped, so spaces_resume can start it. | Manage | Member | No |
spaces_delete | Delete a space and its workspace. | Manage | Member | Yes |
spaces_ports | List the ports a running space is listening on, and whether each speaks HTTP. | Read | Member | No |
spaces_preview_url | Get a preview URL for an HTTP port of a running space. | Manage | Member | No |
spaces_compute_get | Read a space’s compute size, any resize in progress or staged, and how far it can be resized in place. | Read | Member | No |
spaces_compute_set | Resize a running space: move to a compute class, or set cpu_limit and memory_limit in place. | Manage | Member | Yes |
spaces_upload | Put a file (up to 10 MB) into a running space’s inbox. | Manage | Member | No |
spaces_audit | Read the audit events of one space, newest first: who did what and when. | Read | Member | No |
Space policy approvals
Allow a blocked domain or tool for a space. These need the Agents may approve blocked domains and tools switch.
| Tool | What it does | Permission | Lowest role | Asks you to confirm |
|---|---|---|---|---|
spaces_policy_approve | Allow a domain the space blocked, for this space and for every future space from its manifest. | Manage | Member | Yes, with the switch on |
spaces_live_overlay_set | Allow a domain the space blocked, for this space’s session only. | Manage | Member | Yes, with the switch on |
spaces_tool_policy_set | Allow a tool the space blocked by removing the tool-policy rules that block it, for this session only. | Manage | Member | Yes, with the switch on |
spaces_live_overlay_get | The policy changes applied to a running space so far: its network rules, tool policy and MCP and database policies. | Read | Member | No |
Deputies, missions, schedules and triggers
Build and run deputies.
| Tool | What it does | Permission | Lowest role | Asks you to confirm |
|---|---|---|---|---|
deputies_list | List deputies with their active missions. | Read | Member | No |
deputies_get | One deputy: name, description, owner, manifest, state, defaults (timeout, compute, output mode, concurrency). | Read | Member | No |
deputies_create | Create a deputy (personal by default; team or org if your role allows). | Manage | Member | No |
deputies_update | Change a deputy’s name, description, manifest or defaults. | Manage | Member | No |
deputies_suspend | Suspend a deputy: its schedules and triggers stop starting runs until it is resumed. | Manage | Member | No |
deputies_resume | Resume a suspended deputy. | Manage | Member | No |
deputies_restore | Bring an archived deputy back. | Manage | Member | No |
deputies_archive | Archive a deputy: it stops running and is hidden; deputies_restore brings it back. | Manage | Member | Yes |
deputies_insights | A deputy’s insights for a window: runs, success rate, people, waiting, reliability, human-in-the-loop, per mission and version. | Read | Member | No |
deputies_queue | Launches of a deputy waiting for their mission’s concurrency limit, in order. | Read | Member | No |
missions_list | A deputy’s missions: name, stage (draft or active), active version, mode, run count. | Read | Member | No |
missions_create | Create a mission with its version 1, as a draft: nothing runs until missions_version_activate. | Manage | Member | No |
missions_rename | Give a mission a new name. | Manage | Member | No |
missions_delete | Delete a mission; one with runs is archived instead, so its history stays readable. | Manage | Member | Yes |
missions_versions | A mission’s versions, newest first: prompt, mode, grants, inputs, timeout. | Read | Member | No |
missions_version_add | Add a version; it becomes the mission’s active version at once. | Manage | Member | Yes, when the mission is active |
missions_version_dry_run | Render the mission’s active version with these inputs, at any stage, without starting a run. | Manage | Member | No |
missions_version_activate | Make a draft mission active: its latest version starts running unattended. | Manage | Member | Yes |
schedules_list | A deputy’s schedules: mission, cron and zone, notes, paused or not, last and next firing. | Read | Member | No |
schedules_create | Run a mission on a cron schedule in a time zone. | Manage | Member | Yes |
schedules_update | Pause or resume a schedule, or change when it fires or its notes. | Manage | Member | Yes, when the notes change |
schedules_delete | Remove a schedule; its mission stops firing on it. | Manage | Member | Yes |
triggers_list | A deputy’s triggers: which integration event starts which mission, its filter and input mapping. | Read | Member | No |
triggers_preview | Try a trigger filter on recent deliveries of an event: how many match, with samples. | Read | Member | No |
triggers_create | Start a mission whenever an integration event matches. | Manage | Member | Yes |
triggers_update | Pause or resume a trigger, or change its event, filter, inputs or endpoint. | Manage | Member | No |
triggers_delete | Remove a trigger; its events stop starting the mission. | Manage | Member | Yes |
Memory
Read and write deputy and personal memory documents.
| Tool | What it does | Permission | Lowest role | Asks you to confirm |
|---|---|---|---|---|
memory_get | Read a deputy’s context or memory document, or your own (omit deputy). | Read | Member | No |
memory_revisions | A memory document’s revisions, newest first: content, who wrote it (person or agent, which run), reverts. | Read | Member | No |
memory_put | Replace a memory document, based on the version you read; an out-of-date version is refused. | Manage | Member | Yes, when writing context |
memory_revert | Restore an earlier version of a memory document as a new version; history keeps both. | Manage | Member | Yes, when reverting context |
Manifests and stacks
Environments for runs and the curated stacks they build on.
| Tool | What it does | Permission | Lowest role | Asks you to confirm |
|---|---|---|---|---|
manifests_list | List manifests (run environments). | Read | Member | No |
manifests_get | Read one manifest: stack version, owner, auto-stop, overrides and whether it is held. | Read | Member | No |
manifests_preview | Resolve a manifest, optionally with trial overrides, and report policy violations and warnings. | Read | Member | No |
manifests_create | Create a manifest (a run environment) on a published stack version. | Manage | Member | No |
manifests_update | Change a manifest’s name, overrides, auto-stop or compute class. | Manage | Member | No |
manifests_delete | Delete a manifest. | Manage | Member | Yes |
manifests_upgrade | Move a manifest to a newer published version of its stack. | Manage | Member | Yes |
manifests_clone | Copy a manifest you can see into a new one you own, with its own name. | Manage | Member | No |
manifests_send | Send an independent copy of a manifest you manage to another member. | Manage | Member | Yes |
stacks_list | The stacks (curated environments) you can see, with their latest published version. | Read | Member | No |
stacks_get | One stack: its draft, published versions, held upgrades and whether it follows major versions. | Read | Member | No |
stacks_create | Create a stack, a curated environment members build manifests on. | Admin | Admin | No |
stacks_update_draft | Change a stack’s name, description, modules, policy or compute classes. | Admin | Admin | No |
stacks_publish | Publish the stack’s draft as a new version. | Admin | Admin | Yes |
stacks_unpublish | Retire a stack: hide it from the picker and stop launches from manifests on it. | Admin | Admin | Yes |
stacks_push_to_members | Give every member without one a manifest on the stack’s latest version. | Admin | Admin | Yes |
stacks_check_upgrades | Look for newer versions of the stack’s modules and apply the allowed ones. | Admin | Admin | No |
Connections, credentials and secrets
Manage who can reach what. Values are never returned, and adding or replacing a secret value happens in the web app.
| Tool | What it does | Permission | Lowest role | Asks you to confirm |
|---|---|---|---|---|
connections_list | The connections you can sign in to or add a credential for, and whether you are connected. | Read | Member | No |
credentials_list | The credentials you can see: name, type, owner, status, who reaches them. | Read | Member | No |
credentials_impact | How many live sessions use a credential now, so you know what rotating it would affect. | Read | Member | No |
http_secrets_list | Your HTTP secrets: name, env var, the hosts each is sent to, its credential and owner. | Read | Member | No |
vault_connections_list | Your vault connections (AWS, GCP, HashiCorp, 1Password): name, provider, owner. | Read | Member | No |
shares_list | Who an item is shared with (resource_type + resource_id), or what is shared with someone (principal_type + principal_id). | Read | Member | No |
shares_recipients | Teams and people (and the org, if you may share org-wide) you can share with, by name or email. | Read | Member | No |
integrations_list | The integration catalog you can see, custom MCP servers included; installed=true for this org’s own. | Read | Member | No |
connections_oauth_start | Start an OAuth sign-in to a connection; you finish it in the browser. | Manage | Member | No |
connections_device_start | Get the link that starts a device-code sign-in (for example AWS SSO) in the web app. | Manage | Member | No |
credentials_add | Get the link where you add a credential value in the web app. | Manage | Member | No |
credentials_rotate | Get the link where you replace a credential value in the web app. | Manage | Member | No |
http_secrets_add | Get the link where you add an HTTP secret in the web app. | Manage | Member | No |
credentials_remove | Delete a credential. | Manage | Member | Yes |
credentials_owner_set | Move a credential to you, a team or the org. | Manage | Member | Yes |
http_secrets_update | Rename an HTTP secret, or change the hosts it is sent to or its credential. | Manage | Member | Yes, when hosts or credential change |
http_secrets_remove | Delete an HTTP secret; running sessions stop getting it. | Manage | Member | Yes |
http_secrets_owner_set | Move an HTTP secret to you, a team or the org. | Manage | Member | Yes |
vault_connections_remove | Delete a vault connection and the HTTP secrets it produced. | Manage | Member | Yes |
vault_connections_owner_set | Move a vault connection, with its secrets, to you, a team or the org. | Manage | Member | Yes |
shares_create | Share a credential, HTTP secret, vault connection, manifest or stack with people, teams or the org. | Manage | Member | Yes |
shares_update | Change one share between read and use. | Manage | Member | Yes |
shares_withdraw | Stop sharing an item with one person, team or the org. | Manage | Member | Yes |
integrations_remove | Delete an integration catalog entry, such as a custom MCP server, and its connections. | Manage | Member | Yes |
Marketplace, network and compute
Org-wide packages, network policies and compute classes.
| Tool | What it does | Permission | Lowest role | Asks you to confirm |
|---|---|---|---|---|
marketplace_browse | Search the marketplace’s packages, or read one package or one version: compatibility, publisher, declared credential injections. | Read | Member | No |
marketplace_installed | The packages installed in the org, each with its Auto-update setting, latest compatible version and whether an upgrade is available; or, with a catalog id, the manifests and stack versions that still reference one. | Read | Member | No |
marketplace_install | Install a marketplace package version for the whole org. | Admin | Admin | Yes |
marketplace_upgrade | Install a newer version of an installed package, as the web’s Upgrade does. | Admin | Admin | Yes |
marketplace_uninstall | Remove an installed package from the org. | Admin | Admin | Yes |
network_policies_list | The org’s network policies with their rules, or one policy by id. | Read | Member | No |
network_policies_create | Create a network policy, or copy one with duplicate_of. | Admin | Admin | Yes |
network_policies_update | Change a network policy’s name, default action, rules or user additions; omitted fields keep their value. | Admin | Admin | Yes |
network_policies_delete | Delete a network policy. | Admin | Admin | Yes |
compute_classes_list | The org’s compute classes, one class by id, or with policy=true the compute policy (allowed classes, default, default storage class, resize overrides). | Read | Member | No |
compute_classes_create | Create a compute class (CPU, memory, disk, QoS, GPU). | Admin | Admin | Yes |
compute_classes_update | Change a compute class; omitted fields keep their value. | Admin | Admin | Yes |
compute_classes_delete | Delete an org compute class. | Admin | Admin | Yes |
compute_classes_bulk_storage | Set the storage mode and storage class on all of the org’s compute classes, or on a chosen few, in one change. Preview it first with a per-class before and after and the effect on existing spaces; apply it with apply=true. Moving persistent classes to ephemeral also needs confirm_ephemeral=true. | Admin | Admin | Apply only |
compute_policy_set | Set which compute classes people may pick and the default class. The org’s default storage class and resize overrides are kept. | Admin | Admin | Yes |
People
Members, invitations and teams.
| Tool | What it does | Permission | Lowest role | Asks you to confirm |
|---|---|---|---|---|
members_list | List everyone in the org with their role. | Read | Member | No |
members_offboarding | The shared items that need a new owner, and what is deleted or stopped, if a member is removed. | Read | Admin | No |
members_role_set | Change a member’s role to owner, admin or member. | Admin | Admin | Yes |
members_remove | Remove a member from the org. | Admin | Admin | Yes |
invitations_list | The org’s invitations with role, expiry and whether they were used or cancelled. | Read | Admin | No |
invitations_create | Invite someone as admin or member. | Admin | Admin | Yes |
invitations_cancel | Cancel an invitation that was not used yet. | Admin | Admin | Yes |
teams_list | The org’s teams with member counts and your role on each. | Read | Member | No |
teams_create | Create a team. | Admin | Admin | Yes |
teams_update | Rename, re-describe, archive or restore a team. | Admin | Admin | Yes |
teams_member_add | Add a member to a team as member or lead. | Admin | Admin | Yes |
teams_member_remove | Remove a member from a team; they lose what the team’s shares gave them. | Admin | Admin | Yes |
Admin dashboards
The admin dashboards, for owners and admins.
| Tool | What it does | Permission | Lowest role | Asks you to confirm |
|---|---|---|---|---|
admin_overview | The admin dashboard’s headline numbers: active people, sessions, spend, blocked egress, credentials, deputy runs. | Admin | Admin | No |
admin_usage | Usage over time or by breakdown: series, utilization, top egress hosts, egress decisions, MCP and tool usage. | Admin | Admin | No |
admin_cost | Spend: compute cost by person, LLM token cost, deputy cost by deputy, by day or both (view: deputy), or what pausing saved. | Admin | Admin | No |
admin_security | Security: egress posture, credential exfiltration attempts, anomaly days, active alerts. | Admin | Admin | No |
admin_sessions | Every session in the org with state, owner, activity and LLM cost; or one by id. | Admin | Admin | No |
admin_nodes | The cluster’s nodes: capacity, requests, usage, headroom, pending sessions and recommendations. | Admin | Admin | No |
admin_nodes_refresh | Take a fresh reading of the cluster’s nodes now; the platform limits how often one is taken. | Admin | Admin | No |
admin_credentials | Credential statistics, or the inventory of every credential with owner, last use and age (no values). | Admin | Admin | No |
admin_credentials_revoke | Force-revoke any member’s or the org’s credential. | Admin | Admin | Yes |
Security Center
Block a vulnerable package version, see what it affects, move it out of your stacks and manifests, and restart spaces that run an old setup. These are the same actions as the Security Center in the web app, for owners and admins. Anything that changes something asks you to confirm first, showing facts read from the server.
| Tool | What it does | Permission | Lowest role | Asks you to confirm |
|---|---|---|---|---|
security_blocks_list | The org’s blocked version ranges, or one block with what it affects and its last stop job. | Admin | Admin | No |
security_blocks_create | Block a version range of a package (it does not have to be installed yet), or of the runtimes a toolchain offers; choose whether running spaces keep running or stop now. | Admin | Admin | Yes |
security_blocks_remove | Unblock a version range. The block stays as history. | Admin | Admin | Yes |
security_blocks_affected | The stacks, manifests, spaces (running, stopped, or with no package record) and runs that hold a version in a block’s range, with their owners. | Admin | Admin | No |
security_blocks_fix | Preview, then apply, moving the block’s stacks and manifests to the newest installed version outside every block. A preview changes nothing; applying asks you to confirm. | Admin | Admin | Yes, to apply |
security_blocks_stop_affected | Stop the running spaces that hold a block’s versions and cancel their runs. Spaces with their own disk keep it. | Admin | Admin | Yes |
security_overview | Counts: active blocks, affected spaces, spaces with no package record, outdated spaces. | Admin | Admin | No |
security_outdated_spaces | Spaces whose snapshot is behind their manifest, and the last restart-all job. | Admin | Admin | No |
security_outdated_notify | Email each owner a list of their outdated spaces, at most once per 24 hours each. | Admin | Admin | Yes |
security_outdated_restart | Stop each running outdated space and start it on its manifest, resolved again as its owner. | Admin | Admin | Yes |
Audit
Search the audit log.
| Tool | What it does | Permission | Lowest role | Asks you to confirm |
|---|---|---|---|---|
audit_search | Search the audit log: your own events, or the whole org for owners and admins. | Read | Member | No |
Credential, secret and vault values are never returned. Adding or replacing a value happens in the web app, and the tool hands you the link.
Docs
Let the agent read the official docs instead of guessing. The pages are the ones on docs.marshal.codes, bundled with your install, so the agent reads the docs as of your install’s API release. It works on installs with no outbound internet, and every member and admin sees the same pages.
| Tool | What it does | Permission | Lowest role | Asks you to confirm |
|---|---|---|---|---|
docs_search | Find the pages and sections that answer a question, such as “upgrade to a new release” or “space compute sizes”. Returns up to 10 pages, each with a snippet and its docs.marshal.codes link. | Read | Member | No |
docs_read | Read one page as markdown, by the path docs_search returned. A long page comes in parts of up to 32 KiB; pass next_offset as offset until done is true. | Read | Member | No |
Ask for them by name when you want a sourced answer: “Search the Marshal docs for how to add a package to a stack, read the best page, and tell me the steps with the link.”
How the tools behave
- Confirmations come from your client. Claude Code and Codex ask you before the action runs.
- Short ids work. The run and ask tools take the first 8 or more characters of an id, the way the web app and the CLI show it, as long as only one run or ask that you can see starts with them: your own runs (any run in the org for owners and admins) and the asks you may answer. Give the whole id for anything else.
- Messages reach a run that is waiting on an ask. A run waiting on an ask cannot read its
queue until the ask is settled, so
runs_messageattaches your message to the ask instead and returnsdelivered: truewithattached_to_ask. The agent gets the message together with the answer, before it acts. The person answering sees it on the ask card in the web app and ininbox_get. An ask holds up to 5 messages of 2 KB each; when it is full, wait for the ask to be settled and send again. A message is attached only to the agent’s own question, and only when the run can show it. In every other case (a tool-permission prompt, a longer message, a run whose agent cannot show the message, aninterrupt) the message is queued as before, anddeliveredisfalsewhile the run waits. If the ask is skipped, a running agent reads the message at the end of its turn; a parked run whose ask is skipped does not resume, and the message ends with it. If the ask times out, the run ends and the message ends with it: continue the run withruns_continueand repeat the instruction. runs_continuesays what to do instead. When a run kept no conversation to continue from, start a new run withruns_launchand give it what it needs to know innotes.- Runs started over MCP read as MCP. A run started with
runs_launchordeputies_run_adhocshows MCP as its trigger on the run page and in the Runs list, so you can tell it apart from a run started in the web app, the CLI or the API. runs_waitholds at most 30 seconds per call and returns at most 200 events. It returns early when the run ends, asks a question, or produces events. The agent calls it again with the cursor it got back.runs_waitkeeps each answer small. One call returns about 24,000 characters of events (max_chars, up to 57,344) and the rest on the next call, so nothing is lost. The text of each tool call and tool result is cut to its first 400 characters (text_chars;-1returns it whole, andruns_logsalways does).summaryreturns no events at all: the run’s state, the agent’s last message, how many tools it called and a count of each kind of event, over everything after the cursor.- A run that handed off names its successor. When a run ends because a later segment picked
it up (stop reason
continued, after an answer or a wake),runs_getandruns_waitreturn that run’s id ascontinued_by_run_id. Follow that run to see the work finish. - Watch for changes with
changes_since. Call it once with no cursor to get a cursor, then pass the cursor from each answer into the next call. Each call returns only what happened since: runs created, started or ended, and asks raised, answered, expired or canceled, oldest first. Addminutes(up to 1,440) on the first call to start with the last few minutes; it is ignored once you pass a cursor. You see your own runs and the asks put to you;scope=orgshows the whole org to owners and admins. An event appears about 5 seconds after it happens, so a change that commits a moment late is still returned, in order, and each event comes back once. A change that takes more than 5 seconds to commit can still be missed. Whenhas_moreis true, call again straight away. A cursor older than 24 hours starts again from 24 hours ago and saysreset. A run that parks gets an ended event, because its turn is over; thestateon an event is the run’s state when you call, so a run that has since been ended shows its final state. What happens to a parked run afterwards, and runs waiting on an ask, show inruns_attention. - Lists stay short.
runs_listshows the first 80 characters of each task, andinbox_listwithbriefshows one line per ask. Read the whole thing withruns_getorinbox_get. runs_logsreads the stored transcript first. If your install keeps no transcripts, it reads the run events that are still kept (about an hour after the run ends). When there is neither, it returnslogs_unavailable, never an empty success.- Deputy cost is one call.
admin_costwithview: deputyrolls up what your deputies’ runs cost over a date range (sinceanduntil, up to 90 days, the last 7 by default). Setgroup_bytodeputy(run hours, compute, LLM cost, total and tokens per deputy, most tokens first),day(LLM cost and tokens per UTC day) ordeputy_day(each deputy with a row for each day it used tokens, up to 31 days). It lists the top 20 deputies (10 fordeputy_day) and sums the rest inother, so the total covers every deputy. Only the usage of deputy runs counts, not people’s own spaces. Per-day rows, and the total of thedayanddeputy_daygroupings, carry LLM cost and tokens only. Deputies are ordered by tokens, then known spend (compute plus priced LLM cost), so a large spender on an unpriced model is listed first. Run hours are the part of each run inside the range, and a run that is waiting on a person or parked adds its hours when it completes, so a closed day can grow. A model with no price is flaggedunpricedon the row, named once in the total, and its cost is left out, never counted as $0. Owners and admins only; it answers once per 10 seconds. - Run output is wrapped in an
<untrusted-content>block, with known secret shapes redacted, so the agent treats it as data and not as instructions. The note that explains the block comes once per answer, on the first block.
The run cap
One person may have 5 runs started through the MCP active at once, per org. The sixth is refused, with the runs that are in the way:
refused: you already have 5 active runs started through the MCP in this org,
and the cap is 5. Active runs: <ids>. Wait for one to end (runs_wait) or stop
one (runs_stop), then launch again.Runs started in the web app, the CLI or by a schedule do not count. The cap guards clients that
cannot ask you to confirm a launch, so think about that before you raise it. To change it for the
whole install, set MARSHAL_MCP_RUN_CAP on the API (chart value api.extraEnv).
Auditing and revoking
Every launch, stop and answer, and every sign-in, token and revoke, is written to the audit log
with the person, the client, the permissions and the outcome, under channel mcp. Search it on
the Audit page, or from an agent with audit_search.
To end a connection:
- A person revokes their own in Personal settings > Connected apps, with Revoke. The client is refused on its next call and must sign in again.
- An owner or admin sees every connection in the org on the same page and can revoke any of them.
- Turning off Allow MCP access ends every connection in the org at once.
Access also ends by itself when the person leaves the org or their role changes, by the same rules that end their web sign-in.
Other MCP clients
Any client that speaks MCP over streamable HTTP and OAuth 2.1 with PKCE can connect. Nothing
about the endpoint is Claude-specific. One rule decides whether a client works: its redirect URI
must be https://, or http:// on a loopback host (127.0.0.1, [::1] or localhost, on any
port, which is what desktop clients use). A client that registers a private-use scheme such as
myapp://callback is refused.
Installs with no inbound internet
Most self-hosted installs take no traffic from the internet. MCP works there with two settings. Claude Code, Codex, other clients inside your network, and headless agents with an API key all work.
How a laptop reaches the install
The chart supports two ways:
- A tailnet name. Set
tailscaleIngress.enabled=trueandtailscaleIngress.hostname, and the install also answers on<hostname>.<your tailnet>.ts.netfor anyone on the tailnet. Also settailscaleIngress.tailnetto your tailnet’s domain. The chart then allows both the short name and the full MagicDNS name on/mcp. - An internal DNS name. Any name that resolves to the install’s ingress inside your network.
List it in
ingress.extraHostsso it gets its own routing rule. If the name reaches the API another way, list it inmcp.extraHosts.
A name that is not in one of those lists gets 403 on /mcp, while the rest of the app works
on it. This check is deliberate: it stops a name someone else controls from pointing at your
install and driving the MCP with a person’s token.
Each name is its own sign-in
A person signs in per name. Connect on marshal.ts.net and you sign in there. The same
laptop connecting on marshal.internal signs in again. The address you use decides the whole
exchange (the sign-in page, the consent page and the token), so a token from one name is refused
on the other, and the client asks you to sign in again.
So pick one name per audience and put it in your install’s instructions.
No outbound internet: turn off client metadata documents
By default, Marshal identifies a client by fetching the https:// URL the client uses as its ID,
a Client ID Metadata Document on the public internet. An install with no outbound internet
cannot fetch it: the fetch waits for its timeout and fails, and the person sees an error about the
client’s host.
On such an install, set mcp.cimdEnabled=false in the chart (MARSHAL_MCP_CIMD_ENABLED=false on
the API). Then:
- the authorization server stops advertising those documents, so clients register themselves dynamically instead. Claude Code and other standard clients do this.
- a client that still sends a URL as its ID is refused at once, with a message telling it to register dynamically.
- every client is Unverified on the consent page (only a document can carry a verified host), so only Read starts ticked and the person ticks the ones they want.
Keep it on (the default) if the install can reach the internet outbound, even when nothing can reach it inbound. Fetching those documents is what lets the consent page tell a real client from one that only uses the name.