MCP server
Model Context Protocol is how an agent reaches your real context instead of guessing at it.
What it is & installing it
Muster runs an MCP server exposing your projects, tasks, worktrees, diffs, database connections, hosts and issue trackers, so the agent acts on what you actually have and you stop pasting schemas back and forth.
The server is a separate process speaking JSON-RPC over stdio; it reads the same database and the same settings as the app.
Which agents Muster can wire it into
Muster writes the MCP config itself — into a repository's agent config or an agent's global config, in one step — for nine of the built-in CLIs: Claude Code, Codex, Cursor Agent, Gemini CLI, OpenCode, Amp, Qwen Code, Kimi CLI and GitHub Copilot CLI. Those are the CLIs with a config dialect Muster knows, so the file it writes is the file the CLI reads.
For the rest it refuses to write anything and names the file you must edit by
hand — Goose's ~/.config/goose/config.yaml, Continue CLI's
~/.continue/config.yaml, Kiro CLI's ~/.kiro/settings/mcp.json, Rovo Dev's
~/.rovodev/mcp.json, Cline's, Droid's, Kilo Code's, Mistral Vibe's, oh-my-pi's, and
the Claude-shaped file Auggie wants handed to it with --mcp-config. For Aider, Grok
CLI, GLM CLI, Pi and the Shell Agent no MCP config location is known, so it says that instead of
guessing. Writing a file the CLI never opens would look like success and behave like nothing.
The same rule gates per-task injection: an agent Muster cannot write a config for is launched without one rather than with a dead file.
Tool reference
Two enforcement shapes appear below, and the difference matters:
- Gated calls are refused outright when the grant is missing.
- Filtered listings always succeed and return only the rows you may see. An agent cannot distinguish "this database does not exist" from "you may not see it", which is deliberate.
| Tool | Does | Enforcement |
|---|---|---|
muster_list_projects | Projects in the workspace | Filtered by projects_read |
muster_list_tasks | Tasks, optionally one project | Filtered by projects_read |
muster_list_hosts | Local + remote hosts | Filtered by hosts_read |
muster_list_db_connections | Saved connections (never secrets) | Filtered by db_read/db_write |
muster_list_issues | Issues from a tracker | Filtered by issues_read |
muster_get_task | One task by id | projects_read |
muster_task_status | Current agent/lifecycle state | projects_read |
muster_wait_task | Block until a task reaches a state | projects_read |
muster_create_task | Record a task | tasks_write — plus worktree_read when borrowing an existing worktree |
muster_spawn_task | Create a task and queue it to run | same as create_task |
muster_update_task_status | Move a task's lifecycle state | tasks_write |
muster_close_task | Close a task, optionally keeping the worktree | tasks_close |
muster_task_worktree | The task's worktree path and branch | worktree_read |
muster_get_diff | The worktree's git diff | diff_read |
muster_open_pr | Open (or return) a pull request | pr_write |
muster_db_schemas | Namespaces in a connection | db_read |
muster_db_objects | Tables, views, collections, key patterns | db_read |
muster_db_describe | Columns, indexes, keys | db_read |
muster_db_preview | A bounded page of rows | db_read |
muster_db_explain | A query plan — plain EXPLAIN, never ANALYZE | db_read; a plan for a WRITE statement also needs db_write |
muster_run_query | Run a query | db_read, plus db_write for a write |
muster_get_issue | One issue by key | issues_read |
muster_create_issue | File a new ticket | issues_write |
muster_import_issue | Turn a ticket into a task | issues_read and tasks_write |
What "read-only" actually rejects
Stricter than most people expect, and deliberately so — it is an allowlist, not a list of banned verbs:
- Only nine leading keywords are read:
select,with,explain,show,pragma,describe,desc,values,table. Anything else — includingCOPY,CALL,DO, or a statement whose first token cannot be parsed — counts as a write. - Multiple statements are refused outright, even two harmless ones:
SELECT 1; SELECT 2does not run. A single trailing semicolon is fine. - A
WITHorEXPLAINstatement is additionally scanned across its entire text — string literals included — for write keywords. That meansEXPLAIN SELECT * FROM audit WHERE op = 'delete'is classified as a write, because the word appears at all. A false positive here costs a refusal; a false negative would cost your data.
Mongo and Redis are classified by their own per-command allowlists rather than by SQL keywords, and for those two the classification is the enforcement.
Other behaviours worth knowing
- A tool you lack the capability for returns a normal response carrying
isError: trueand the missing slug — not a JSON-RPC error. Only an unknown tool name is a protocol error. limitis silently clamped to 1–1000 rather than rejected.timeouthas no ceiling — wait as long as the work takes; a clamped wait would come back asreached: false, which reads exactly like the task having failed.muster_wait_taskdefaults to just 30 seconds when you omit it, so pass a real timeout when orchestrating.
Agents orchestrating agents
muster_spawn_task creates a task and queues it to actually run, which is
what makes a coordinating agent possible: a main agent hands work to several others and blocks
on muster_wait_task until each reaches a state.
1. main agent → muster_spawn_task(project, "migrate the schema") → task A queued
2. main agent → muster_spawn_task(project, "update the client") → task B queued
3. main agent → muster_wait_task(A, needs_review, timeout=3600)
4. main agent → muster_get_diff(A) → reviews → muster_open_pr(A)
Waits may be long — up to a day — because real agent work is. Spawned tasks are real tasks in the app: they appear in the sidebar, get their own worktree and panes, and a human can take over at any point.
New here? Start the 7-day trial — every feature, card up front, $0 today, key on screen. Or buy outright: $39 once per device, no subscription.