Fagan
Server Configuration
Describes the environment variables required to run the server.
| Name | Required | Description | Default |
|---|---|---|---|
No arguments | |||
Instructions
Guidance the server publishes about itself, which clients place ahead of the tool catalog so the model reads it before choosing anything.
This server publishes no instructions, or was last inspected before Glama recorded them.
Capabilities
Features and capabilities supported by this server
Protocol revision2025-11-25
| Capability | Details |
|---|---|
| tools | {
"listChanged": false
} |
| prompts | {
"listChanged": false
} |
| resources | {
"subscribe": false,
"listChanged": false
} |
| experimental | {} |
Tools
Functions exposed to the LLM to take actions
| Name | Description |
|---|---|
| check_usageA | Probe current subscription usage (current session + current week) via a headless |
| get_effective_configA | Read-only diagnostic snapshot of the pipeline's effective configuration: every role in config_provenance.PIPELINE_ROLES with its resolved (provider, model) and provenance, every cataloged env var's resolved value and provenance, any unrecognized/ignored env vars present, and which config-source files were actually consulted (and whether each exists). Pure read - makes no changes and writes nothing. "restart_required" on a role/env entry means that entry's winning value came from an env var or the launchd plist/mcp_server_env layer, so a change there only takes effect after the scheduler/MCP server is restarted. By contrast, a plan's role_config and model_registry.json are both read fresh on every call, so edits to either are live immediately with no restart needed. A role entry carrying a non-None "error" key is misconfigured (e.g. no model configured for it anywhere, or its provider/model pairing isn't declared in model_registry.json) - never raises for this; the bad role just reports its error inline while the rest of the roles resolve normally. Pass plan_name to additionally layer in that plan's role_config overrides (same effect as get_effective_config's plan_name); a plan_name whose manifest doesn't exist degrades to "no plan overrides" rather than raising. |
| decompose_planA | Turn a raw goal/feature request into epics/stories JSON via the product-analyst persona, run on whichever provider the "decompose" role is configured for (PIPELINE_BACKEND_DECOMPOSE env var, or a "decompose" entry in model_registry.json - defaults to Claude when neither is set). This is a separate, additional path from the interactive product-analyst subagent (invoked via the Agent tool, which is always Claude) - that path remains available and is still the default choice for Claude-quality decomposition; this tool exists so decomposition can also run on a local provider when desired. Does NOT call save_plan itself - review the returned plan the same way you would review the interactive subagent's output, then save_plan it yourself. Returns {"ok": True, "plan": {...}} on success. On failure, returns {"ok": False, "error": ...}, with "raw": included whenever the backend actually returned text that failed to parse (never raises). |
| save_planA | Save a generated project plan to disk. Plan should be JSON matching the schema: { "epics": [ { "summary", "stories": [...] } ] }. Call this after generating a plan so the user can review before ingestion. workspace is optional. When supplied, it is validated and (WS-11) the model-authored repo_root in plan_json is OVERWRITTEN with the server-validated resolved path (the server overwrites the model-authored value; this tool never resolves or rewrites plan_json itself). When omitted, the plan's own repo_root is trusted, exactly as before. The tool deliberately does NOT fall back to the dashboard's persisted active workspace: the MCP server and the dashboard are separate processes, and silently coupling them through shared durable state is out of scope (that fallback lives only in the dashboard HTTP route). |
| list_plansA | List plan names found in the plan directory (~/.claude/plans, or $PLAN_DIR). No parameters. Returns the '.json' stem of every file in that directory, not just fresh, ingestable plan sources — an already-ingested plan's '.manifest.json' surfaces as '.manifest', and a story journal or notification log contributes its own noisy stem too. Treat a returned name as a candidate to inspect, not a guarantee it is a valid target for save_plan/ingest_plan. Call this to check whether a plan name is already taken before save_plan, or to confirm a plan file actually landed on disk after saving it. |
| ingest_planA | Push a saved plan into Plane. Creates epics first, then issues linked to their parent epic. Optionally restrict to specific epic summaries via only_epics. Returns a manifest mapping local IDs to Plane UUIDs. Re-ingesting an already-ingested plan merges into the existing manifest rather than replacing it: epics/stories not touched this call (including everything only_epics excludes) are preserved verbatim, a story whose key already exists gets its authored fields (summary, agent_instructions, dependencies, persona, model, acceptance, risk (only while todo), backend, tdd_split, files) refreshed while its runtime state (status, pr_url, escalated, ...) is kept, and top-level manifest keys outside epics/stories/repo_root (paused, local_model_fallback, final_rework_escalation, ...) carry over untouched. Pass overwrite=True to restore the old wholesale-replace behavior (drops anything not produced by this call). |
| list_ready_storiesA | Return the stories in this plan that are unblocked and available to dispatch: status == "todo" and every entry in the story's own dependencies list refers to an already-completed story. plan_name: the plan's name, as returned by list_plans or passed to save_plan/ingest_plan. Returns [] if the plan has no manifest yet (not yet ingested) rather than raising. Returns a list of {"key": ..., "summary": ...} — just enough to choose a story key for dispatch_story or check_story_status, not the full story record (agent_instructions, acceptance, etc. are omitted; use check_story_status for those). A story already in_progress, parked, or done is never included, and neither is a "todo" story whose dependencies aren't all done yet — call this again after a dependency completes rather than assuming today's list stays valid. |
| dispatch_storyA | Spawn a headless Claude Code agent to work on a single story. For a fresh story, creates a git worktree on a new branch. For a story left "interrupted" (or whose worktree already exists from a prior run), reuses the existing worktree/branch instead and seeds the agent's prompt with the checkpoint journal so it continues rather than starting over. Transitions the Plane issue to In Progress. Returns the subprocess PID; completion is async. Acquires |
| check_story_statusA | Check whether a dispatched agent has finished. If complete, runs tests in the worktree and reports pass/fail without auto-merging. |
| interrupt_storyA | Stop a dispatched agent and leave its story resumable. Sends SIGTERM to the agent's process (a no-op if it has already exited), commits any uncommitted work in its worktree as a checkpoint, and marks the story "interrupted" rather than "failed" so a later dispatch_story call resumes it instead of starting over. The worktree and branch are left in place. Acquires |
| mark_story_in_progressA | Transition the ticket to In Progress and update the local manifest's story status. plan_name: the plan's name, as returned by list_plans or passed to save_plan/ingest_plan. story_key: the story's key within that plan's manifest, as returned by list_ready_stories or dispatch_story. Use this before writing any code for a story. Call it once, right after dispatch_story (or after claiming a story for manual work) — it only records status, it does not create a worktree/branch or start an agent itself (dispatch_story does that). Calling it on a story that doesn't exist in the local manifest returns {"ok": False, "error": ...} rather than raising. If another dispatch/ingest/interrupt holds the plan's lock, this is a no-op that returns {"ok": True, "skipped": "locked", ...} — retry rather than assuming the status change happened. |
| checkpoint_storyA | Record a durable checkpoint for a dispatched agent's own progress on a story. Commits any uncommitted work in the story's worktree as a WIP commit and appends an entry to the story's journal (..journal.json). plan_name: the plan's name this story belongs to. story_key: the story's key within that plan's manifest — the same key this agent was dispatched with. step: a short label identifying this step (e.g. "wrote-failing-test", "implemented-fix") — becomes part of the WIP commit message, so keep it terse and distinct from other steps in this story. summary: a sentence describing what was actually done in this step, for whoever (human or resumed agent) reads the journal later. next_hint: optional — what to do next if this run is interrupted right after this checkpoint. Leave empty if there's nothing beyond "continue the story normally." Call this after completing each idempotent step of a story (not mid- step) so a killed or interrupted agent resumes from the last checkpoint via dispatch_story instead of starting the story over from scratch. |
| checkpointA | Deprecated alias for checkpoint_story — identical behavior and parameters (see checkpoint_story's docstring for the full description of plan_name/story_key/step/summary/next_hint). Kept only for backward compatibility with agents/prompts still calling the old name; prefer checkpoint_story in new code. |
| mark_story_doneA | Mark a story finished: sets its ticket (Plane, when enabled) to Done, sets manifest["stories"][story_key]["status"] to "done", and clears any stale parked_reason. If this was the plan's last remaining story, fires the plan-completion notification. plan_name: the plan's name, as returned by list_plans or passed to save_plan/ingest_plan. story_key: the story's key within that plan's manifest, as returned by list_ready_stories, check_story_status, or dispatch_story. Call this only after the story's PR has actually been reviewed and
merged — approve_merge already calls this internally as its last step,
so you normally only need to call mark_story_done directly for a
merge that happened outside the pipeline (e.g. a manual |
| patch_storyA | Edit a story's plan-authored fields (agent_instructions, model, persona,
risk, dependencies, acceptance, pr_url, summary, tdd_split, backend)
without hand-editing the manifest JSON. Hand-editing the manifest races the scheduler's 60s advance_all_plans tick - a read-modify-write on either side can clobber the other's write. This tool takes the same _plan_lock the scheduler and dispatch_story use, so the edit is atomic with respect to it. Only the fields above may be set; status transitions go through set_story_status, not this tool. |
| patch_planA | Edit a plan manifest's top-level fields (currently only role_config) without hand-editing the manifest JSON. Hand-editing the manifest directly races the scheduler's 60s advance_all_plans tick - a read-modify-write on either side can silently clobber the other's write. This tool acquires the same _plan_lock the scheduler and dispatch_story use, so the edit is atomic with respect to it. Only role_config may be set; every other top-level field (repo_root, epics, stories, ...) is rejected fail-closed before the lock is taken, so an unknown field can never reach disk. |
| set_story_statusA | Transition a story to an explicit status without hand-editing the manifest JSON (e.g. resetting a "parked" story to "interrupted" so the scheduler retries it). Acquires _plan_lock for the same reason patch_story does. Only accepts the fixed set of statuses the pipeline itself assigns (todo/in_progress/running/interrupted/failed/tests_passed/pr_open/ changes_requested/parked/done) - this is a sanctioned status change, not a way to invent pipeline state the rest of the code doesn't expect. |
| request_decisionA | Escalate a blocking decision to the overlord, which rules on the user's behalf per the decision policy. The ruling is appended to the plan's decisions log (audit trail, readable via list_decisions) and returned. plan_name: the plan's name this story belongs to.
story_key: the story's key within that plan's manifest — the story
that's actually blocked.
question: the specific question you need answered, stated so a ruling
of "pick one of these options" fully resolves it.
options: the mutually exclusive choices the overlord may rule between,
as plain strings (e.g. ["hand-roll a parser", "add a dependency"]).
Not free text — the ruling should select one of these verbatim.
context: optional — anything the overlord needs to rule correctly that
isn't in On success returns a dict with at least "ruling" (the chosen option's text), "rationale", "risk", "tier", "action", and "notify_user" — act on "ruling", not on your own preference. Call this from a story agent when you are blocked on a choice the user would normally make; do not guess. Fails open: if the overlord backend errors, the story is parked for a human and a single-line escalation message (a plain string, not the dict above) is returned instead of raising — check whether the return value is a str before reading dict keys off it. |
| list_decisionsA | Return the overlord's decision log for a plan: every ruling ever made by request_decision on this plan, oldest first, as an audit trail. Read-only — makes no changes to the plan or any story. plan_name: the plan's name, as returned by list_plans or passed to save_plan/ingest_plan. Each entry corresponds one-to-one with a prior request_decision call and carries at least the story_key, question, the ruling made, and a timestamp. Returns an empty list if the plan has no decisions logged yet — this is normal for a plan with no blocked stories, not an error. Call this to check for precedent before escalating a similar decision with request_decision, or when a human wants to review what the overlord has ruled on so far for a plan. |
| review_storyA | Run the code-reviewer persona over a dispatched story's branch. On APPROVE, open a PR via gh and set status to pr_open; otherwise set status to changes_requested. Does not merge — merge is the overlord's decision. Only reviewable when story["status"] == "tests_passed" - any other status (a stale/duplicate call, e.g. a second tick racing an already-merged story) is a no-op skip; see README.md's "Review & merge" section. |
| advance_pipelineA | Run one orchestration tick: dispatch every ready story (deps satisfied), advance finished stories through test -> review -> PR, and adjudicate merges against the risk threshold. Idempotent; designed to be called repeatedly by a scheduler (/loop or cron). In PIPELINE_AUTONOMY=dry-run it plans and logs only, taking no actions. Honors a per-backend resource gate: dispatch and review are gated independently by their own backend's resource_status() (see _role_resource_ok). If the dispatch backend is gated, in-progress stories are interrupted (checkpointed, resumable) and no new dispatch starts; if the review backend is gated, review is deferred. Each is independent, so a Claude usage pause no longer freezes local-backed dispatch. Merge adjudication always runs (no model usage). "interrupted" stories are dispatch-eligible like "todo" ones, so they resume automatically once the dispatch backend frees up. Also honors MAX_CONCURRENT_AGENTS: dispatch is capped to the number of free slots remaining (limit minus agents already in_progress across all plans), so a tick never starts more agents than the configured ceiling. Stories left undispatched this tick stay "todo"/"interrupted" and are picked up on a later tick as slots free up. Skips entirely (returns {"ok": True, "skipped": "locked"}) if another tick for this same plan is already running - see _plan_lock. |
| approve_mergeA | Merge a reviewed story's PR into the default branch, right now, on the caller's explicit approval — this is the human/overlord merge decision itself, not a status check. plan_name: the plan's name, as returned by list_plans or passed to save_plan/ingest_plan. story_key: the story's key within that plan's manifest. Must currently be "parked" or "pr_open" with review_verdict == "APPROVE" — any other state (not yet reviewed, still in progress, already merged) returns {"ok": False, "error": ...} without changing anything. On success this: rebases the story's branch onto the current default branch, force-pushes it (--force-with-lease) to origin, polls real CI (gh pr checks) — auto-retrying once on a cancelled run, and failing closed on a fail/cancelled/still-pending result — re-runs the story's acceptance fixtures and a build check against the rebased code, then merges the PR, deletes the branch/worktree, marks the story "done" in the manifest and its ticket, and notifies the user to restart the MCP server if the story touched the pipeline's own source. Any failure at any of those steps aborts the merge and returns the specific reason instead of partially completing it. This does more than a plain |
| pause_planA | Stop advance_pipeline/advance_all_plans from touching this one plan - no new dispatch, review, or merge - while leaving every other ingested plan's scheduler ticks unaffected. Any story currently in_progress is interrupted (checkpointed and left resumable) so a paused plan isn't quietly burning usage in the background. Resume with resume_plan. |
| resume_planA | Clear a pause set by pause_plan so this plan's stories are eligible for dispatch/review/merge on the next advance_pipeline tick again. |
| advance_all_plansA | Run advance_pipeline on every plan that has been ingested (has a manifest), keyed by plan name. Plans saved but not yet ingested (no manifest) are skipped. Intended for a recurring scheduler (cron/launchd or /loop) so newly ingested plans are picked up automatically with no hardcoded plan name to maintain. NOTE on zombie reaping: the per-plan advance_pipeline polling phase already handles dead-pid in_progress stories via check_story_status (which falls through to test-running on dead pids). Running an external reap pass BEFORE the polling would clobber that and silently leave stories re-dispatching forever without ever running the test (manifest observation 2026-06-28: 3 e2e stories hit dispatch_attempts= MISSING because the reap ate the polling opportunity). The reap helper _reap_zombie_in_progress_stories is kept for callers that need a one-shot cleanup (e.g. tests, ops CLI) but is NOT wired in here. |
| record_security_auditA | Record that a repository was security-audited at a given commit. Parameters: repo_root: Absolute path to an existing directory containing the git repo. sha: Optional 4-64 hex-character commit id. Defaults to HEAD. Returns:
On success, |
Prompts
Interactive templates invoked by user choice
| Name | Description |
|---|---|
No prompts | |
Resources
Contextual data attached and managed by the client
| Name | Description |
|---|---|
No resources | |
TDQS
Scored across 26 tools
Several tools overlap in purpose: checkpoint is a deprecated alias of checkpoint_story, and mark_story_in_progress/mark_story_done/set_story_status all mutate story status while dispatch_story also transitions to In Progress. Detailed descriptions mitigate confusion, but an agent could still misselect among the status-transition tools.
Nearly all tools follow a consistent snake_case verb_noun pattern (e.g. list_plans, dispatch_story, approve_merge). The main deviation is the deprecated 'checkpoint' alias, which drops the object noun and breaks the pattern slightly.
26 tools is on the heavy side, but the server covers a broad multi-agent pipeline domain (planning, dispatch, review, merge, decisions, config, usage, audit). The count is justified though a few redundant tools (deprecated alias, overlapping status setters) inflate it.
The surface covers the full plan-to-merge lifecycle including planning, ingestion, dispatch, checkpointing, review, merge, decisions, and operational diagnostics. Some gaps remain, such as listing all stories in a plan or managing plan/story deletion, but core workflows are complete.