Skip to content

Latest commit

 

History

History
128 lines (105 loc) · 6.42 KB

code-mode.md

File metadata and controls

128 lines (105 loc) · 6.42 KB

Code mode

Code mode lets an AI client run a short JavaScript program that orchestrates several of a workspace's MCP tools in one step, instead of making the tool calls one at a time. A program that filters, joins or loops over tool results turns dozens of round trips and megabytes of intermediate data into a single call that returns only what matters.

Off by default, everywhere. Code mode does nothing until an operator runs the code-runner service (CODE_RUNNER_URL) and a workspace turns it on per MCP server (codeMode). With either missing, code runs are refused — never executed in the main process.

How code runs safely

Code is untrusted by construction: a prompt-injected tool result can steer what the model writes. So it never runs in the AnythingMCP backend. It runs in a separate code-runner container, one locked-down subprocess per run, with no filesystem, no network, no environment and no subprocess access. The only thing a program can do is call the MCP tools the caller is already allowed to use, through an amcp bridge the backend answers under that caller's role. The full containment model and its verification are in deploy/code-runner/README.md.

Inside a program you have one capability:

// Discover tools, read their schema, and call them.
const tools = await amcp.search('invoice');
const schema = await amcp.describe('list_invoices');
const invoices = await amcp.run('list_invoices', { customerId: args.customerId });
return invoices.filter((i) => i.status === 'open').map((i) => i.id);

amcp.run is governed exactly like a direct tool call: the caller's role decides what it may reach, and read/write rules still apply.

Two forms

Saved code tools. A reusable tool whose body is a stored program. It is an ordinary MCP tool (it shows up in tools/list, obeys role access, is audited and can be exported), created in the dashboard under a connector's tools with the Code tool type. A saved code tool declares:

  • Uses — the connectors (optionally specific tools) the program may call. Only connectors from the same workspace.
  • Run as — invoker re-checks the calling user's own permissions on every inner call; definer runs with the author's curation instead (like a stored procedure), still limited to Uses and the write setting. Definer is admin-only.
  • Allow write tools — off means the program may call only read-only tools. Turning it on needs AnythingMCP Enterprise.

Inline code (code_execute). A generic tool the model can call with a program it writes on the spot. Always read-only and with the caller's own permissions, over the connectors they can reach on that server. It appears only when the server's codeMode is inline and the caller's role carries the inlineCode capability.

Proposing a tool (code_propose_tool)

When an agent finds a multi-step pattern worth keeping, it can propose a saved code tool instead of an admin writing one by hand. code_propose_tool appears under the same gate as inline code (codeMode inline + the inlineCode capability + a configured runner). It does not run code and does not create a tool — it records an inert proposal that shows up for admins under Knowledge → Skills. A proposal is always invoker and read-only and can only reference the proposer's own connectors, so an agent can never raise its own authority. An admin reviews the program and clicks Create tool, which runs the normal tool-creation checks (same-workspace connectors, plan cap); writes or definer rights are added only afterwards by editing the tool, where Enterprise and admin gating apply again.

Governance

  • Per server: codeMode is off (default), tools (saved code tools only) or inline (also code_execute). Set it on the MCP server's settings page, or with PUT /api/mcp-servers/:id (codeMode).
  • Per role: the inlineCode capability gates inline code; saved code tools follow the normal tool allow-list.
  • Per plan: saved code tools are capped per plan — Community 3, Starter 5, Team 20, Enterprise unlimited (same on Cloud and self-hosted; an Enterprise contract can override the cap with the licence feature maxCodeTools). Inline code (code_execute / code_propose_tool) is Team and above. A Cloud trial with a card on file is treated as Team for code mode for the length of the trial (inline code and the Team cap of 20), so a high-intent user can try everything; a free, card-less trial stays tools-only with the cap of 3. A self-hosted trial carries no billing and so is never promoted.
  • Writes happen only in an admin-approved code tool with Allow write tools on; inline code and read-only tools can never write.
  • Audit: every run is recorded (a code_runs row), and each tool call the program makes is recorded like any other tool call.
  • Shared endpoint: code tools are never served on the shared /mcp endpoint used by directory AI clients; they run only on a workspace's own MCP servers.

Deployment

Code mode is the same feature on Cloud and self-hosted; both run the runner as a separate service and refuse code runs when it is unreachable.

Self-hosted, with Docker Compose:

COMPOSE_PROFILES=code-runner
CODE_RUNNER_URL=ws://code-runner:8777

Then set a server's codeMode to tools or inline (on the server's settings page or via the API). The runner holds no secrets and needs no inbound internet; it accepts only the backend's connection on the internal network. A saved code tool's Test button in the tool editor runs the program through the runner, so you can check it before a client does.

Limits

A run is bounded by a wall-clock deadline, a memory ceiling, a cap on how many tool calls it may make, and limits on output size. A program that exceeds a limit fails with a clear error; it never affects other runs or the backend.

On Cloud, where the runner is shared between tenants, two per-workspace quotas apply on top of the per-run limits: a monthly run cap (trial 100, Starter 500, Team 5,000, Enterprise unlimited; an Enterprise contract can override it with the licence feature maxCodeRunsPerMonth) and a concurrency cap on simultaneous runs (trial/Starter 1, Team 3, Enterprise 10). Over a quota, a run is refused with a clear message and nothing is executed. A card-backed trial gets the Team quotas. Self-hosted is single-tenant and not metered by runs, so neither quota applies there.