magus v0.3.0 is out. See what's new
¶ View markdown source · ✎ Suggest an edit
8 min read

MCP

When the daemon is running, it also exposes an MCP (Model Context Protocol) server over Streamable HTTP. Agents and IDE plugins that speak MCP (Claude Desktop, Cursor, VS Code Copilot, and others) can call magus tools directly instead of shelling out.

Magus targets humans first. MCP is always compiled in; it is a runtime layer you turn off with mcp.enabled=false (see Enabling and disabling) when you do not want it.

For the full agent surface built on top of MCP - the installable skills, MAGUS.md routing, durable memory, and the drift check - see Agents.

Starting the daemon starts MCP

You don't need a separate process. Start the daemon as usual:

magus server start

The MCP endpoint comes up alongside it:

http://127.0.0.1:7391/mcp

magus doctor reports whether MCP is reachable and prints the endpoint URL.

Is MCP actually reachable?

An agent host connects to the MCP endpoint over HTTP; nothing starts that endpoint on its own, so if the daemon is not running the tools silently disappear from the host. magus status reports the endpoint's live health as its own block, checked independently of the daemon's job socket:

mcp endpoint
  url    http://127.0.0.1:7391/mcp
  state  serving

The state is one of:

state meaning
serving listening and a workspace is loaded - the tools are reachable
not-ready listening, but no workspace is loaded yet
unreachable nothing is listening; start the daemon with magus server start
disabled turned off by mcp.enabled=false

For scripts and container probes, magus status --probe=<kind> exits 0 healthy / 1 unhealthy. The kinds are liveness (the daemon answers), readiness (a workspace is loaded), and mcp (this endpoint is reachable) - and they are comma-combinable, failing if any listed check does:

magus status --probe=mcp             # fail if the tools are unreachable
magus status --probe=liveness,mcp    # fail if the daemon OR the endpoint is down

The daemon also serves /livez, /readyz, and /healthz on the same port. If state is unreachable even though you expect a daemon, see Keeping the daemon running.

Available tools

The daemon exposes 20 tools. This list is authoritative at the time of writing; magus describe mcp-tools (or the magus_describe tool with kind: mcp_tools) prints the live set with full parameters, so trust that over this table if they ever differ.

Discover:

Tool Purpose
magus_describe Describe a concept and list its entities: spells, targets, projects, workspaces, mcp_tools (pass name for one entity's detail)
magus_describe_file Classify paths against declared globs: owning project, and output (generated) vs source
magus_where Resolve a fuzzy project name to its absolute path
magus_config_get Read the resolved workspace config (read-only)

Run:

Tool Purpose
magus_run_target Run a target (build, test, lint, ci, ...) for one or more projects
magus_run_affected Run a target on only the VCS-affected projects
magus_affected_plan Emit a provider-neutral CI shard plan for the affected set
magus_affected_explain Explain why a project is in the affected set

Inspect:

Tool Purpose
magus_doctor Validate workspace health (config, cache, cycles, tool availability)
magus_status Report telemetry/cache settings and the live proc-server pool state
magus_tail_log Return the most recent captured build log for a project
magus_output Fetch one target execution's exact captured output by its out... ref
magus_insight VCS-history lenses: hotspots, files, affinity, ownership, trend

Knowledge graph:

Tool Purpose
magus_query Search the graph and return ranked matches plus their neighborhood
magus_explain Show one node's data, edges with provenance, and how many nodes reach it
magus_path Shortest path between two nodes: how two entities relate
magus_refs Where a code symbol is defined and every file that references it (SCIP)
magus_stats Graph shape: god nodes, orphans, doc coverage

Memory and scratch:

Tool Purpose
magus_memory User-owned per-repo handoff journal: list/get/put/delete/verify named entries shared across worktrees

Config mutation is not exposed over MCP. Use the CLI for magus config set and related commands.

Enabling and disabling

MCP is on by default. To disable it:

# magus.yaml
mcp:
  enabled: false

Or set MAGUS_MCP_ENABLED=0 in the environment before starting the daemon.

To change the listen address:

# magus.yaml
mcp:
  address: "127.0.0.1:9000"

Or MAGUS_MCP_ADDRESS=127.0.0.1:9000.

Security: keep this local

Warning: Reaching the MCP endpoint is equivalent to having shell access to your build workspace. Any authenticated caller can execute arbitrary build targets, which in turn invoke arbitrary toolchain commands defined in your magusfiles.

The endpoint requires a bearer token, and accepts two kinds:

  • The cli token - a single, retrievable secret the daemon generates on first start and stores 0600 at $XDG_STATE_HOME/magus/mcp_token (~/.local/state/magus/mcp_token). magus's own commands reuse it (for example graph open --live). The secret never reaches the daemon log, so retrieve it with magus config mcp token print.
  • Connector tokens - named, hashed-at-rest, expiring secrets you mint per external client (a Claude connector, an IDE). Only their SHA-256 is stored, so a connector token is shown once at creation and can never be re-displayed; rotate by minting a new one.

Every /mcp request must carry Authorization: Bearer <token> with either kind; requests without a valid token get 401 Unauthorized. Manage them with:

magus config mcp token print                     # show the cli token
magus config mcp token generate                  # mint a new cli token (--force to rotate)
magus config mcp token revoke                     # delete it (daemon mints a fresh one on next start)

magus config mcp connector create --name claude   # mint a connector token (prints the secret once)
magus config mcp connector create --expires 30d    # override the default 90-day expiry (or "never")
magus config mcp connector ls                    # names, fingerprints, and expiry
magus config mcp connector revoke <name|fingerprint>

The token must be presented in the Authorization header; the /mcp endpoint does not accept a token in the URL query string (RFC 6750 keeps secrets out of logs and history). How you connect depends on the client:

  • Claude Code connects to the loopback endpoint directly with a header. Mint a connector token, then register the server at user scope so every workspace the daemon serves shares one connection (the daemon binds one loopback port for all of them):

    magus config mcp connector create --name claude-code --expires never
    claude mcp add --transport http --scope user magus http://127.0.0.1:7391/mcp \
      --header "Authorization: Bearer <token>"
    

    claude mcp list should then report magus ... - Connected. Restart the Claude Code session afterward: a session only discovers MCP tools (and skills installed by magus agent install .claude/skills) at launch, so an already-open session will not see them until it is restarted.

  • Codex uses user-level ~/.codex/config.toml to register the local Streamable HTTP endpoint. Do not commit this client configuration. It contains no secret; the token comes from the process environment:

    [mcp_servers.magus]
    url = "http://127.0.0.1:7391/mcp"
    bearer_token_env_var = "MAGUS_MCP_TOKEN"
    enabled = true
    

    For Codex CLI, start the daemon, export the token in the same shell that will launch Codex, then check registration and endpoint health:

    magus server start
    export MAGUS_MCP_TOKEN="$(magus config mcp token print)"
    codex mcp list
    magus status --probe=liveness,mcp
    

    For a dedicated, revocable credential, run magus config mcp connector create --name codex --expires never and store the printed value as MAGUS_MCP_TOKEN in your local secret manager instead. The For the ChatGPT desktop app or Codex IDE extension, set the variable through the OS environment before launching or restarting the client; exporting it in a terminal does not configure an already-running app. Start a new task after the daemon comes up. codex mcp list confirms configuration, while magus status --probe=liveness,mcp confirms the endpoint is live. If you change mcp.address, update the URL in ~/.codex/config.toml too. In the desktop app, /mcp shows connected servers. Install matching guidance with magus agent install .agents/skills --agents-md; see Agents for why Codex needs both locations.

  • Claude Desktop / other IDE plugins that take a Streamable-HTTP URL plus headers use the same shape:

    {
      "type": "streamable-http",
      "url": "http://127.0.0.1:7391/mcp",
      "headers": { "Authorization": "Bearer <token>" }
    }
    

    Clients whose connector UI only speaks OAuth (no static-header option) reach a loopback server through the mcp-remote stdio bridge: npx -y mcp-remote http://127.0.0.1:7391/mcp --header "Authorization: Bearer <token>".

  • The Claude API "MCP connector" cannot reach this server: it requires a public https:// URL and rejects http:// and loopback addresses. Front the daemon with a TLS tunnel first if you need that path.

Treat the token as defense in depth, and still keep the port closed. The server binds to 127.0.0.1 by default and validates the Host and Origin headers on every /mcp request, returning 403 Forbidden for non-loopback values to block browser-based DNS-rebinding attacks. Anyone who reads the token gains the same workspace access, so keep it local.

Do not expose it over:

  • Tailscale, Zerotier, or similar overlay networks where other devices can reach it
  • ngrok, localtunnel, or other public tunnels
  • SSH -L port-forwards shared with others
  • Kubernetes port-forward in shared clusters
  • Any network ACL that admits untrusted hosts

If you need to drive magus remotely, run the CLI over SSH instead.

mcpmodel-context-protocolaiagentsclaudecodexcursordaemonide
Last updated (a103255f)
Earlier changes on this page (2)

Full history ↗ · Blame source ↗

Glossary

Workspace

The magus root directory that owns a set of projects and shared config; the unit magus operates over. See workspace.

Project

A directory magus recognizes as a unit of work (it has a magusfile); the unit of caching, scheduling, and dependency tracking. See workspace.

Magusfile

The magusfile.buzz that declares a project's targets (as export funs) and binds its spells. See targets.

Target

A named operation (build, test, ...) you invoke with magus run <target>; it may compose a spell's tool-native operations and depend on other targets. See targets.

Spell

A language/runtime adapter (e.g. go, md) that maps generic targets onto a toolchain's real commands. See spells.

Ward

A coded diagnostic that inspects a resolved op and nudges or blocks an anti-pattern before it runs. See wards.

Cache

The content-addressed store magus consults before running a target, so unchanged work is skipped. See cache.

Affected

The set of projects touched by a change; magus affected <target> runs a target only over them. See affected.

Daemon

The background magus host that owns shared state such as services and the warm knowledge graph. See daemon.

CI

An ordinary magusfile-defined target you compose yourself with magus\needs - magus does not hardcode its stages. Magus.RunCI treats it specially only in that it strips the rw charm, it is the anchor magus affected ci keys off, and a selected scope with no project declaring it is a load error rather than a silent no-op. See targets.

Pool

The concurrency pool: the shared set of slots that caps how many targets run in parallel on one machine. Its capacity defaults to MAGUS_CONCURRENCY, then 4 on GitHub-hosted runners, then min(NumCPU, 8); magus status and the dashboard report it live. See daemon.

Health

The at-a-glance daemon state derived from the pool: healthy when the pool is reporting, degraded when it reports an error, down when there is no pool. The dashboard color-codes each state. See daemon.

Knowledge graph

The queryable graph of a workspace's spells, targets, docs, and code relationships; query it with magus query/explain/path. See knowledge.

MAGUS.md

The committed routing index at a workspace root, regenerated from the knowledge graph: it lists every node and points at the exact query for a given question, so it is the entry point an agent reads first. See knowledge.

Insight

The reports magus derives over the graph and history (hotspots, affinity, ownership, trend). See insight.

Hotspot

An insight lens: edit frequency times complexity, the prime refactoring targets. The project view heat-colors the dependency graph by churn; --files ranks individual files. See insight.

Affinity

An insight lens: projects that change together (temporal coupling). A pair that co-changes without either declaring a dependency on the other is a candidate architectural smell. See insight.

Ownership

An insight lens: author concentration - the primary author and their share, the distinct-author count (the bus factor), and abandonment. See insight.

Trend

An insight lens: the recent half of the window against the earlier half. A positive delta is a rising hotspot; a negative one is cooling. See insight.

Conventions

Placeholders

Angle brackets mark a value you replace with your own - never type the brackets:

magus run <target>
magus completion <shell>    # e.g. bash, zsh, fish

<target>, <path>, <shell>, <name> and the like are stand-ins, not literal text.