@anyforge/mcp-server
v3.11.0
Published
AnyForge MCP Server — drive AnyForge (HIL approvals, initiatives, work items, crews) from Claude CLI, Cursor, and other MCP clients
Maintainers
Readme
AnyForge MCP Server
Drive AnyForge from Claude CLI (Claude Code), Cursor, and other MCP clients: view and approve HIL notifications, read programs / initiatives / work items, add and modify work items, see crew outputs, and interact with crews.
The server is a thin client over AnyForge's key-authenticated control
API (/api/v1/control/*). It holds no business logic and never needs a
Firebase login.
User-facing setup guide: Connect AnyForge to Claude, Cursor and VS Code (
apps/www/content/docs/mcp-server.md). This README is the in-repo developer reference; the docs page is the canonical install walkthrough.
No key needed for OAuth-capable clients. This package needs an
sk_anyforge_…key. Claude (via the AnyForge listing in its connectors directory), Claude Code, VS Code, Cursor and any other client that supports MCP authorization can instead connect to the hosted endpointhttps://crew.anyforge.ai/api/mcpand sign in with OAuth.
Platform guide for connected agents
The server advertises a static anyforge-platform guide without tenant data or
extra authority. MCP clients can load it on demand with the platform_guide
prompt or the anyforge://guide/platform resource. The resource also exposes
the guide's three reference files.
For an Agent Skills-compatible local host, install the same guide with:
npx @anyforge/control skill install anyforge-platformThe default is the project-local .agents/skills/anyforge-platform/ directory.
Use --scope user --client claude or --scope user --client codex for the
corresponding user-level directory. Existing files are preserved unless
--force is explicit.
1. Authorise this machine (once)
npx @anyforge/control initThis runs the device-auth flow and writes a long-lived sk_anyforge_…
key to ~/.anyforge/credentials. The MCP server reads that file — so
you don't put any secret in your MCP config.
The key carries scopes (
read/write/approve). A read-only key can list and inspect but can't create work items or approve HILs.
2. Register with Claude CLI
claude mcp add anyforge -- npx tsx /ABS/PATH/TO/packages/control/mcp-server/index.ts- Add
--scope userto make it available in every project, or--scope projectto commit it to this repo's.mcp.json. - No env vars are required — credentials come from
~/.anyforge/credentials.
To point at a non-prod deployment or inline a key instead of using the credentials file, pass env vars:
claude mcp add anyforge \
-e ANYFORGE_API_URL=https://staging.anyforge.ai \
-e ANYFORGE_API_TOKEN=sk_anyforge_xxx \
-- npx tsx /ABS/PATH/TO/packages/control/mcp-server/index.tsCursor / other clients
Use the equivalent stdio MCP config (command: npx, args: ["tsx",
"…/index.ts"]). The same credential resolution applies.
Tools
Code Studio tools require @anyforge/mcp-server 3.8.0 or later and a
deployed Studio API. For stdio clients use npx -y @anyforge/mcp-server@^3.8.0
after its npm release, then restart the client to refresh its tool catalogue.
Hosted HTTP follows the application deployment and does not depend on the
installed stdio package version.
Code Studio tools require explicit studio:read, studio:write,
studio:execute, or studio:publish scopes; ordinary and legacy keys do not
inherit them. Owners and operators can request these scopes, and editors can
request them only when their company owner enables developer Studio access.
External coding runs use audited coding, reads and reviews. Hosted commands and
orchestration require browser Studio; crew launches and PR ready/merge require
confirmation there. See the portable references/code-studio.md guide for the
complete capability and local/remote workspace boundary.
| Tool | Scope | Description |
|------|-------|-------------|
| anyforge_branch_studio_session | studio:write | Fork a session with explicit conversation/files/both scope. File scope also requires studio:execute and checkpoints; rewind requires exact workspace revisions. Does not undo external GitHub actions. For branch, reuse the same idempotencyKey when retrying; inspect incomplete preparation before retrying. |
| anyforge_rewind_studio_session | studio:write | Rewind a session with explicit conversation/files/both scope. File scope also requires studio:execute and checkpoints; rewind requires exact workspace revisions. Does not undo external GitHub actions. For branch, reuse the same idempotencyKey when retrying; inspect incomplete preparation before retrying. |
| anyforge_update_studio_review_finding | studio:write | Record a finding disposition with rationale and the revision containing a claimed fix. A fixed status does not imply independent verification; request a linked re-review to verify. |
| anyforge_get_studio_pr_comments | studio:read | Read paged inline PR review comments and reviewed file/line/commit provenance. |
| anyforge_get_studio_pr_jobs | studio:read | Read CI job identifiers for the exact PR head and a workflow run from its checks. Follow nextPage before claiming complete evidence. |
| anyforge_get_studio_pr_logs | studio:read | Read a bounded CI log page only for a job belonging to this exact PR head. Preserve nextOffset to continue. |
| anyforge_request_studio_review | studio:execute | Enqueue a durable, budgeted specialist review of an exact checkpoint, branch or PR. Returns a run ID; inspect its events and structured review artifacts. Reviewers cannot publish changes. |
| anyforge_list_studio_crew_batches | studio:read | Read the session crew batches and unexpired proposals, including aggregate progress and limits. |
| anyforge_get_studio_crew_batch | studio:read | Read one owned Studio crew batch. Active crews remain governed by their own gates. |
| anyforge_preview_studio_crew_batch | studio:write | Persist a proposal for existing/new work items, planned or expedited crews, dependencies and aggregate limits. Starts nothing. Also requires studio:publish because orchestration can reach external systems. Open Code Studio to confirm the returned proposal; API/MCP arguments cannot attest human confirmation. |
| anyforge_cancel_studio_crew_batch | studio:execute | Cancel queued starts; already active crews require separate stop actions. Also requires studio:publish. |
| anyforge_retry_studio_crew_batch | studio:execute | Create a new proposal for failed/cancelled work; open Code Studio to confirm execution. This action never starts crews. Also requires studio:publish. |
| anyforge_list_studio_sessions | studio:read | List your owned remote Code Studio sessions and their active/latest run IDs. |
| anyforge_create_studio_session | studio:write | Prepare a direct coding session or attach it to an existing initiative. Does not start execution. Context is a reference; local edits are not uploaded to the remote checkout. additionalRepos needs an explicit repoFullName. |
| anyforge_get_studio_usage | studio:read | Read the owned session recorded billing subtotal from the newest 200 rows, grouped by model/product/run/leg. Preserve truncated, coverage and pending; historical coverage may be incomplete or unavailable, so this is not a complete session bill. Provider cost and platform fee remain separate fields. |
| anyforge_get_studio_session | studio:read | Read one owned Studio session and its reconnect IDs. |
| anyforge_update_studio_session | studio:write | Update a session title, repository, branch, additional repositories or initiative. Does not execute code. additionalRepos replaces the whole list; null or [] clears it. |
| anyforge_get_studio_context | studio:read | Inspect effective context provenance, instructions, skills, graph/document snapshots and MCP availability. Does not expose credentials. |
| anyforge_add_studio_context | studio:write | Attach a bounded context snapshot to a prepared prompt. No code execution; explicitly identify local versus remote provenance. |
| anyforge_list_studio_runs | studio:read | List durable runs for your session. |
| anyforge_start_studio_run | studio:execute | Start a durable coding run in the remote workspace. Can spend tokens and edit files. External runs are limited to audited coding, reads and reviews; hosted shell, browser, outbound connectors, Oracle and crew/workflow/approval actions require the browser Studio surface. Use planned=true for analysis only. Dedicated Git push and draft PR tools need studio:publish; ready/merge require confirmation in Code Studio. |
| anyforge_get_studio_run | studio:read | Read run status, usage and any pending user question. |
| anyforge_get_studio_run_events | studio:read | Read ordered durable run events after a sequence cursor. Persist nextCursor to reconnect without replaying earlier events. |
| anyforge_control_studio_run | studio:execute | Pause, cancel, resume, steer or answer a pending question. Answer requires its current questionId. Resuming may execute code and spend tokens. |
| anyforge_get_studio_changes | studio:read | Read remote workspace revision, Git state and changes. Does not create a workspace or install dependencies. |
| anyforge_list_studio_artifacts | studio:read | Read checkpoint and structured reviewer artifacts for this session. |
| anyforge_get_studio_review | studio:read | Read structured reviewer findings, dispositions and review target provenance. |
| anyforge_create_studio_checkpoint | studio:execute | Capture remote workspace files, including staged and untracked changes, as a persistent checkpoint. |
| anyforge_get_studio_checkpoint | studio:read | Read checkpoint metadata and exact revision. |
| anyforge_diff_studio_checkpoint | studio:read | Read the remote workspace diff for a saved checkpoint. |
| anyforge_read_studio_checkpoint_file | studio:read | Read a bounded file window from a persistent checkpoint. |
| anyforge_restore_studio_checkpoint | studio:execute | Restore a checkpoint into the remote workspace after comparing its current revision. Saves a safety checkpoint first; does not rewind external GitHub actions. |
| anyforge_stage_studio_files | studio:execute | Stage explicitly selected remote files after checking the current revision. |
| anyforge_commit_studio_files | studio:execute | Commit reviewed remote changes. Read changes and confirm file scope before committing; does not push. |
| anyforge_push_studio_branch | studio:publish | Publish the exact remote Git HEAD to its branch. Rejects changed HEAD and default-branch pushes. |
| anyforge_get_studio_pull_request | studio:read | Read a session repository pull request, checks, review decision and merge blockers. |
| anyforge_create_studio_pull_request | studio:publish | Create or reuse a draft PR for the persisted session branch after checking its exact pushed HEAD. Uses your connected GitHub identity. Does not mark ready or merge. |
| anyforge_update_studio_pull_request | studio:publish | Update metadata or mark a session branch PR as draft using its exact expectedHeadSha. Open Code Studio to review and confirm ready/merge; tool arguments cannot authorize those actions. |
| anyforge_search_studio_sessions | studio:read | Search your own Studio sessions by title, repository, branch or folder, newest first. Set conversations=true (q of 2+ characters) to also search message text, five sessions per page. Follow nextCursor; conversationsLimited means a session had more messages than were searched. |
| anyforge_archive_studio_sessions | studio:write | Archive all of your own unarchived Studio sessions (CI auto-fix monitors excluded). Transcripts are kept and each session can be unarchived with update_studio_session. Call again while remaining is true. |
| anyforge_list_studio_decisions | studio:read | List your Studio runs waiting on you: each owned session whose current run asked a question, with the question and its options. Answer with control_studio_run. |
| anyforge_list_studio_models | studio:read | List the models your company and personal credentials can run, grouped by provider, for the model argument of start_studio_run. A provider with ok=false is not configured or not reachable. Cached for 30 minutes unless refresh=true. |
| anyforge_get_studio_quota | studio:read | Read the remaining quota of the Anthropic subscription Studio runs on for you. oauth=false means runs use an API key, which has no subscription window. |
| anyforge_get_studio_conversation | studio:read | Read an owned session's conversation, oldest first: your messages, the agent's replies and, with includeTools=true, each round's tool calls and results. Long text is clipped and flagged truncated. A page can hold fewer than limit messages; follow nextCursor until it is null. |
| anyforge_list_studio_tasks | studio:read | Read the session's task list (the agent's to-do items), newest change first. |
| anyforge_compact_studio_session | studio:execute | Compact the session's stored history: older messages are replaced by one summary so the next run starts lean. Deletes the summarized messages and cannot be undone. Spends a small model call on your credential. Refused while a run is active. |
| anyforge_list_studio_verifications | studio:read | Read the session's verification reports (newest 20): diagnostics, tests, lint, typecheck, build and acceptance checks with their evidence and the exact source they ran against. Running a new verification requires the browser Studio surface. |
| anyforge_get_studio_environment | studio:read | Inspect the existing remote checkout's environment readiness: detected toolchain, dependencies and setup scripts. Never clones, installs or loads secrets; preparing the environment requires the browser Studio surface. |
| anyforge_list_studio_outcomes | studio:read | Read the accepted, needs-rework and abandoned outcomes recorded for the session's runs, with the verification each was bound to. Pass runId for one run's outcome history. Outcomes are recorded by a person in Code Studio. |
| anyforge_list_studio_workspace_files | studio:read | List a directory of the live remote workspace (omit path for the root). Never creates a checkout: a session without one returns workspace_missing. |
| anyforge_read_studio_workspace_file | studio:read | Read a line window of a file in the live remote workspace, including unsaved agent edits. offset is the first line (default 1), limit the line count (default 500, maximum 2000). Never creates a checkout. |
| anyforge_inspect_studio_code | studio:read | Run a language-service query on a live workspace file: diagnostics (default), definition, references, hover, completions, or rename (a preview of the edits; apply with rename_studio_symbol). line and column are 1-based. Pass revision to refuse a changed workspace. |
| anyforge_write_studio_workspace_file | studio:execute | Create an empty file or save a file's complete content in the live remote workspace, without a model run. Name the repository, branch and revision you read, so a changed workspace is refused. Each write saves a checkpoint first. Does not commit or push. |
| anyforge_rename_studio_symbol | studio:execute | Apply a language-service rename of the symbol at a 1-based line and column across the live remote workspace. Preview it first with inspect_studio_code operation=rename. Name the repository, branch and revision you read; a changed workspace is refused. Does not commit. |
| anyforge_list_pending_approvals | read | List HIL approvals awaiting a decision |
| anyforge_get_approval_detail | read | Read one approval's plan / ADR / security context |
| anyforge_submit_approval | approve | Approve or reject a HIL (resumes the crew) |
| anyforge_list_programs | read | List programs |
| anyforge_get_program | read | Get a program |
| anyforge_get_program_brief_context | read | Read a program's structured Brief, version history, legacy mirror, and ICE readiness |
| anyforge_save_program_brief_version | write | Save a complete structured Brief version; archives the prior active version and replaces the retired free-form writer |
| anyforge_get_program_intake_definition | read | Read a program's intake definition (the typed form its intake agent interviews against), the checklist that applies, and its version history; version reads one version in full |
| anyforge_set_program_intake_definition | write | Edit a program's intake definition; every change is a new version, and a change that strands answers open requests hold needs acknowledgeImpact (use dryRun to preview) |
| anyforge_restore_program_intake_version | write | Republish an earlier intake definition version as a new version |
| anyforge_get_intake_request_details | read | Read one program intake request's answers against its program's intake definition: each field's state, answer, who gave it, and whether it can be edited |
| anyforge_edit_intake_request_details | write | Set, confirm or clear a program intake request's answers by hand (validated against the definition; audited; no re-approval, no follower notice) |
| anyforge_update_program | write | Update a program's name / status / owner / lead / long-lived flag / target date / coverage goal / tags / change freezes |
| anyforge_set_program_status_line | write | Write or clear a program's status line, shown on a report's program status board |
| anyforge_set_program_request_intake | write | Turn a program's incoming requests on (creates its Incoming Requests initiative) or off |
| anyforge_delete_program | write | Delete a program; deleteChildren: true also deletes child initiatives + work items (else they're detached) |
| anyforge_set_program_milestones | write | Set a program's milestones/waves and the initiatives assigned to each (whole-array replace; an initiative sits in at most one wave) |
| anyforge_get_program_rollup | read | Read a program's rolled-up progress, initiative/work-item counts, token budget/spend, and risks — the console program header numbers |
| anyforge_architect_program | write | Run program-level architecture planning: decompose every still-DRAFT initiative in the program at once |
| anyforge_approve_program_architecture | approve | Approve the program's rolled-up solution architecture — one review approves every proposed initiative backlog (HIL #1 each) |
| anyforge_list_program_comments | read | List a program brief's Discussion comments — the same threaded comments the console shows; shared-report comments are marked external with the author's name only |
| anyforge_post_program_comment | write | Post a Discussion comment on a program brief (default overview section, or pass section; reply with parentId), into the thread the console renders; always stored private to the team |
| anyforge_update_program_initiative | write | Enrich one existing program initiative and return changed fields or a structured no-op |
| anyforge_close_program_initiative | write | Preview then close one program initiative with a supported close reason |
| anyforge_close_program_work_items_as_fixed | write | Preview then batch-close non-terminal program work items fixed outside AnyForge |
| anyforge_list_initiatives | read | List initiatives with progress + budget. Returns ONE PAGE (50 default, 100 max) — continue with meta.nextCursor, or narrow with programId, status, priority, owner, tag, search. Unknown arguments are rejected; the page echoes appliedFilters |
| anyforge_get_initiative | read | Initiative + crew and work-item rows + burn-down; long text is excerpted unless shape: "full" |
| anyforge_get_initiative_spec | read | Read the active ICE spec, its readiness, what backlog approval will decide (approvalGate), and any submission awaiting human review |
| anyforge_propose_initiative_spec | write | Submit an ICE spec for human review; it becomes active only when a person reviews and publishes it in the Console |
| anyforge_update_initiative | write | Update a (non-system) initiative — only the fields you pass change, including its owning team (teamId); an argument the tool does not declare is refused and nothing is changed |
| anyforge_delete_initiative | write | Delete a DRAFT initiative (archive via update once it's past DRAFT) |
| anyforge_list_initiative_comments | read | List an initiative's Discussion comments — the same threaded comments the console shows |
| anyforge_post_initiative_comment | write | Post a Discussion comment on an initiative (reply with parentId), into the thread the console renders |
| anyforge_list_opportunities | read | List opportunities in the Discovery (product-planning) layer |
| anyforge_create_opportunity | write | Create an opportunity (bridges raw signals to themed roadmap work) |
| anyforge_update_opportunity | write | Edit an opportunity's RICE inputs, stage, theme assignment, or program link (programId; null unlinks) |
| anyforge_delete_opportunity | write | Hard-delete an opportunity (prefer archiving via anyforge_update_opportunity) |
| anyforge_promote_opportunity | write | Promote a prioritized opportunity into a Program + Initiative |
| anyforge_list_signals | read | List signals in the Discovery (product-planning) layer |
| anyforge_create_signal | write | Capture a signal — a raw data point that may inform product direction |
| anyforge_update_signal | write | Edit a signal's status, linked opportunity, or other fields |
| anyforge_delete_signal | write | Hard-delete a signal (prefer archiving via anyforge_update_signal) |
| anyforge_list_themes | read | List themes in the Discovery (product-planning) layer |
| anyforge_create_theme | write | Create a theme — a strategic grouping above individual initiatives |
| anyforge_update_theme | write | Edit a theme's name, status, charter lines or other fields (no strategy link — see anyforge_set_initiative_key_results) |
| anyforge_delete_theme | write | Hard-delete a theme (prefer archiving via anyforge_update_theme) |
| anyforge_get_strategy | read | Read the complete strategy tree, attainment, delivery rollups, horizons, orphan work, and delivery conditions |
| anyforge_list_pillars | read | List strategy pillars |
| anyforge_create_pillar | write | Create a strategy pillar |
| anyforge_update_pillar | write | Update a pillar's name, description, lead, or order |
| anyforge_delete_pillar | write | Delete a pillar when it has no objectives |
| anyforge_list_objectives | read | List strategy objectives |
| anyforge_create_objective | write | Create an objective under a pillar |
| anyforge_update_objective | write | Update or move an objective |
| anyforge_delete_objective | write | Delete an objective when it has no key results |
| anyforge_list_key_results | read | List strategy key results |
| anyforge_create_key_result | write | Create a measurable key result |
| anyforge_update_key_result | write | Update a key result or record a reading |
| anyforge_delete_key_result | write | Delete a key result |
| anyforge_get_initiative_key_results | read | Read which key results an initiative moves |
| anyforge_set_initiative_key_results | write | Set which key results an initiative moves — the one link from work to the strategy |
| anyforge_get_horizons | read | Read NOW / NEXT / LATER narratives and completion criteria |
| anyforge_set_horizon_narrative | write | Update a horizon narrative |
| anyforge_get_cluster_charter | read | Read one theme's charter and outstanding lines |
| anyforge_approve_backlog | approve | Approve a proposed backlog (HIL #1), optionally deferring chosen items (deferItemIds, deferReason) |
| anyforge_approve_task_proposal | approve | Approve a mid-flight task proposal |
| anyforge_list_work_items | read | List backlog items + crew state. Use itemId for a full work-item id or queue code, search for partial code/title matches, and includeArchived: true to include archived items. Also supports status, owner, assignee, program, initiative, team (a team slug, including the teams beneath it), priority, type and label (one exact label, such as a stage of a label group) filters. Returns ONE PAGE (50 default, 200 max) — continue with nextCursor. Unknown arguments are rejected; the page echoes appliedFilters |
| anyforge_list_label_groups | read | List the company label groups (id, name, ordered labels, appliesTo). A group's name is not a label: pass one of its labels to anyforge_list_work_items as label |
| anyforge_list_work_boards | read | List the saved Work boards; a board that follows a label group carries labelColumns and columnLabels (the stage labels in column order) |
| anyforge_get_work_item | read | Get one work item by its returned id, with assigneeName, blockerOwnerName and createdByName beside the uids (null when nobody visible is named; list items carry them too) |
| anyforge_create_work_item | write | Create a work item with routing, migration, incident, intake, estimate, and evidence fields |
| anyforge_update_work_item | write | Edit, assign, begin, expedite, dispatch, confirm, drop (with optional droppedReason), archive, close, or reopen a work item. Each action takes only its own fields: one it does not read is refused (unsupported_fields) and nothing is changed. There is no status argument |
| anyforge_retry_work_item | write | Terminate a work item's crew and dispatch a fresh one on the same branch; recovers missing/phantom crew records from work-item + initiative defaults |
| anyforge_list_work_item_comments | read | List the work item's discussion thread, separate from crew transcripts; every comment carries a boolean clientVisible |
| anyforge_post_work_item_comment | write | Add a discussion comment to a work item; internal unless clientVisible: true shares it with the client as it is written |
| anyforge_share_work_item_comment | write | Share an existing work-item comment with the client (clientVisible: true) or take it back to internal (false) |
| anyforge_split_work_item | write | Replace one unstarted work item with multiple children |
| anyforge_merge_work_items | write | Replace multiple unstarted work items with one merged item |
| anyforge_list_crews | read | Discover crews by status, active state, and limit |
| anyforge_get_crew | read | Crew state + recent outputs + comments. Leads with status, halt reason, work item, PR and timestamps; shape: "summary" (default) excerpts long text and leaves out large snapshots, naming each; messages: 0 is the status read; shape: "full" for every field |
| anyforge_post_crew_comment | write | Comment on / @-mention people on a crew (the crew does not read comments; use anyforge_message_crew to steer a running crew, anyforge_amend_crew for one at a gate) |
| anyforge_message_crew | approve | Message a running crew's Engineer ("skip X", "check Z first"). It reads the message before its next step and confirms in the crew chat; a crew not yet started or stopped inside the Engineer reads it on its first step or on resume. Refused with crew_not_reading_messages at a gate, in review or when finished. Optional idempotencyKey makes a retry safe |
| anyforge_resume_crew | approve | Resume a PAUSED/HALTED crew |
| anyforge_halt_crew | approve | Halt a crew |
| anyforge_amend_crew | approve | Continue & finish — send a crew at its HIL gate back to the engineer with guidance. Optional postToPullRequest also posts the notes on the pull request; left out, the organization setting decides (off by default) |
| anyforge_fix_crew_ci | approve | Fix CI: send a crew whose pull request has failing checks back to the Engineer to fix them on the same PR. Works from PR review (HIL_SHIP) or a HALTED/PAUSED crew that has a PR; refused when GitHub does not report CI as failing. Requires approve scope and spends crew tokens. Only call when the operator asks. |
| anyforge_resume_crew_with_pr | approve | Review & approve: take a HALTED or PAUSED crew's already-open pull request through the specialist reviews to the approve & merge gate, without re-running the Engineer. Omit prUrl to use the PR stored on the crew. A merged PR is refused. Requires approve scope. |
| anyforge_decide_crew_permission | approve | Approve or deny the permission a crew in PERMISSION_PENDING is waiting on (see pendingPermissionRequest on anyforge_get_crew). A tool permission applies for the rest of the run; an MCP write approval decides that one call. Pass approvalId to refuse a decision on a newer request. Requires approve scope. Only call when the operator decides. |
| anyforge_create_program | write | Create a program (cross-initiative grouping), optionally with a lead and as long-lived |
| anyforge_create_initiative | write | Create a (DRAFT) initiative, optionally under a program |
| anyforge_dispatch_architect | write | Decompose an initiative into a backlog (→ HIL #1) |
| anyforge_list_repo_index | read | List the org repo index (activity, coverage, analyzed) — discover codebases to scope |
| anyforge_get_repo_analysis | read | One repo's coverage / architecture / gap summary |
| anyforge_check_dispatch_readiness | read | Check the repository's Phase 1 + Phase 2 analysis gate before dispatch; does not launch a crew |
| anyforge_analyze_repos | write | Start Phase-1 analysis for one or more repos; Phase 2 follows automatically when Phase 1 completes |
| anyforge_start_coverage_sweep | write | Paced Phase 1→2 analysis sweep over a program/repo set |
| anyforge_refresh_repo_index | write | Refresh the repo index + committed-coverage detection now |
| anyforge_upload_coverage | write | Upload test-coverage measurements for one or many repos (e.g. synced from SonarQube) |
| anyforge_list_escrow_deposits | read | List a codebase's (or the company's) escrow deposit ledger |
| anyforge_generate_escrow_deposit | write | Generate a source-escrow deposit bundle for one codebase |
| anyforge_list_escrow_scope | read | List the codebases currently in escrow scope (escrow.enabled) |
| anyforge_set_escrow_scope | write | Bulk-set the "In escrow scope" checkbox across many codebases (repos and/or codebaseIds, up to 1000 per call) |
| anyforge_start_escrow_sweep | write | Seed/inspect a paced fleet-wide escrow deposit sweep |
| anyforge_escrow_scoping_report | read (write if store=true) | Generate the Escode scoping-answers report (markdown); store=true persists it to Storage |
| anyforge_deliver_escrow_deposit | write | SFTP a stored deposit bundle to the escrow agent; stamps the ledger with a delivery receipt |
| anyforge_ask_oracle | read | Ask the AnyForge Oracle a workspace question (codebases, releases, decisions, live data from connected integrations); runs the full research loop server-side and returns one cited answer. Waits up to ~40s; a longer turn returns status: "running" and an askId |
| anyforge_get_oracle_answer | read | Wait (up to ~40s per call) for the answer to a running anyforge_ask_oracle question by its askId; never re-runs the question |
| anyforge_investigate_repository | read | Delegate a bounded repository investigation across one to five selected repos; returns an evidence-backed report from indexed code intelligence and analysis docs without exposing raw graph records or live source. Waits up to ~40s; a longer investigation returns status: "running" and a jobId |
| anyforge_get_repository_investigation | read | Wait (up to ~40s per call) for the report of a running anyforge_investigate_repository investigation by its jobId; never re-runs the investigation |
| anyforge_list_workflows | read | List the company's Operator Workflows — reusable multi-step orchestrations (agent / tool / parallel / map / gate steps) with each one's inputs and enabled flag |
| anyforge_get_workflow | read | Get one workflow including its full current spec (steps, inputs, budget) — inspect required inputs before a run |
| anyforge_run_workflow | write | Dispatch a run of a workflow (returns the QUEUED run); runs pause at gate steps for an operator decision |
| anyforge_get_workflow_run | read | Get a workflow run's status and per-step progress; gate decisions are made on the Console run page |
| anyforge_resolve_workflow_gate | approve | Resolve a run paused at a gate (approve / amend / reject; amend carries guidance in comment) |
| anyforge_retry_workflow_run | write | Retry a FAILED run from the step that failed: finished steps and a map's answered items are kept, spend keeps accumulating; refused for a failed crew step. Runs on the company key |
| anyforge_list_observability_signals | read | List production-error triage signals (filter by status) |
| anyforge_accept_observability_signal | write | Accept a signal into a governed incident under the KTLO program |
| anyforge_dismiss_observability_signal | write | Dismiss a production-error signal as noise |
| anyforge_list_audit_events | audit:read | Read one page of the hash-chained audit trail, oldest first, with each entry's sequence, hash and prevHash (filter by eventType, actor, from, to; page with cursor). Needs a key minted with the explicit audit:read scope by an owner |
| anyforge_list_members | read | List the workspace's approved members with uid, name, email, role and whether they can be assigned work. Assignment takes the uid, not an email; q finds a person by name or email |
| anyforge_invite_person | people:invite | Invite one person, or refresh their pending invitation: role is operator, editor, viewer or filer (never owner), email on a verified company domain, optional teamIds and notify. Needs an owner's key with the people:invite scope |
| anyforge_list_people_invitations | people:invite | List the invitations a people:invite key could have written, pending and accepted |
| anyforge_withdraw_person_invitation | people:invite | Withdraw a pending invitation by email address (an accepted or owner invitation cannot be withdrawn this way) |
| anyforge_list_page_spaces | read | List the Pages spaces you can read, with each space's key and what you may do there |
| anyforge_list_pages | read | Browse a space by id, with its settings/revision and paginated page metadata; follow nextCursor while hasMore is true |
| anyforge_create_page_space | write | Create a space as a workspace Owner |
| anyforge_update_page_space | write | Change settings, access, main page or archive state as a space admin; requires ifRevision |
| anyforge_list_page_versions | read | Paginated history metadata; readers see only published history |
| anyforge_restore_page_version | write | Restore an older version as a new save; requires current ifVersion and keeps history |
| anyforge_set_page_publishing | write | Set live or publish-to-update mode and replace reviewers as the page owner or space admin |
| anyforge_publish_page | write | Publish, request publication, or approve a pending request as a named reviewer |
| anyforge_search_pages | read | Search the pages you can read (by meaning, or by title); each match has its page id, space, section and snippet |
| anyforge_get_page | read | Read one page: title, space, version, owner and markdown body (version for an older one) |
| anyforge_create_page | write | Create a page in a space you can edit (space key, title, optional content and parentId), owned by you |
| anyforge_update_page | write | Save a new version (title and/or body, optional change note); ifVersion is the version you read, and a page saved since is refused with 409 |
| anyforge_move_page | write | Move a page under another page, to the top level, or to a position among its siblings |
| anyforge_archive_page | write | Archive a page (kept with its history, hidden from the tree and search), or restore it |
| anyforge_propose_page_edit | write | Propose find/replace edits as suggestions an editor accepts or rejects in the page; nothing changes until they do (live pages only) |
| anyforge_list_reports | read | List the Insights reports, most recently edited first: id, title, description, widget count, updatedAt and Console url; one page at a time (follow meta.nextCursor) |
| anyforge_get_report | read | Read one report: settings (datesShown, trendDays, textSize), whether a share link is live, and every widget definition with its query |
| anyforge_create_report | write | Create an empty report (title, optional description and datesShown), owned by you; needs a role that edits reports |
| anyforge_update_report | write | Change the title, description or settings, and edit widgets by id (addWidgets, replaceWidgets, removeWidgetIds) or replace the whole list (widgets). Every widget is validated as a Console save is; a refusal saves nothing |
| anyforge_preview_report_query | read | Run one report query against live data without saving anything: total, rows and a text summary (program, strategy and cycles snapshots included); needs a role that edits reports |
| anyforge_describe_report_catalog | read | The report data catalog: sources, measures, group-bys, filter fields and widget types; needs a role that edits reports |
| anyforge_create_risk | write | Record an accepted risk on a program, initiative or work item: owner (defaults to you), reviewBy date or acceptedUntilMilestoneId, trigger, mitigation. A risk never blocks dispatch, Depends on or the critical path |
| anyforge_list_risks | read | List accepted risks for a program (programId) or one subject (subjectKind + subjectId); closed risks only with includeClosed |
| anyforge_update_risk | write | Change a risk's status (for example MATERIALISED or CLOSED), owner, review date, mitigation or follow-up work items; only the fields passed change |
| anyforge_list_report_filter_values | read | The values a query filter field may take: an enum's closed set, or real ids with names (query looks one up by name); needs a role that edits reports |
| anyforge_triage_ticket | read | Run or continue a Support Triage interview — classification, readiness scoring, owning-team routing — and get a paste-ready rendering plus the structured draft; pass the same sessionId to continue an interview. Never files anything itself |
| anyforge_list_triage_eval_cases | read | List permitted triage eval cases; historical cases require Owner/Operator |
| anyforge_upsert_triage_eval_cases | write | Create or update triage eval cases in bulk; pass an existing case's id to update it in place |
| anyforge_delete_triage_eval_case | write | Delete one triage eval case by id |
| anyforge_update_triage_eval_case | write | Edit one triage eval case in place (bulk-edit via anyforge_upsert_triage_eval_cases) |
| anyforge_run_triage_eval | write | Evaluate current knowledge by default, or explicitly select historical saved-snapshot mode (at most 20 cases); eligible cases consume model tokens; no tickets are filed |
| anyforge_save_triage_evidence_snapshot | write | Save supplied historical evidence immutably; no source fetch or model call; Owner/Operator only |
| anyforge_get_triage_evidence_snapshot | read | Read a saved company snapshot; Owner/Operator only |
| anyforge_get_triage_eval_run | read | Poll a queued triage eval run by id and read its completed result |
Work item labels (the Console's Labels field) are tags.
anyforge_create_work_item takes tags. On anyforge_update_work_item with
action: "update", addTags and removeTags change some labels against the
labels stored at write time and need no revision, so a script can relabel many
items without reading each first. tags replaces the whole list and needs
ifClassificationRevision, the classificationRevision that
anyforge_get_work_item returns. A labels-only update works at any status,
DONE, DROPPED and archived items included, and its result carries the
item's labels and classificationRevision after the write.
anyforge_update_work_item advertises the complete action enum: advance,
approve_refinement, approve-and-route, move-initiative, dispatch,
complete, update, reorder, archive, unarchive, close-as-fixed,
reopen, mark-incident, drop, confirm-repo, assign, begin,
dismiss-automation-suggestion, expedite, block, unblock,
link-external, verification, add-evidence, remove-evidence,
share-evidence, undefer, set-cycle, link-pull-request,
unlink-pull-request, link-work-item, and unlink-work-item.
link-work-item with linkedWorkItemId and linkType (relates_to or
duplicates) connects two work items at any status, done and dropped
included; unlink-work-item with the same fields removes the link. undefer returns an item
deferred at plan
approval to the ordinary backlog flow. Use drop for an obsolete
unfinished item and pass droppedReason when the reconciliation needs an audit
explanation. archive requires DONE or DROPPED; if it returns
archive_requires_terminal, drop the item first. close-as-fixed instead
records an external fix and requires closedReason; closedEvidenceUrls
optionally adds up to 10 http(s) evidence links. link-external records the
item's key in another tracker (externalKey, optional externalUrl; null
unlinks). verification with verificationState: "verified" records the
client's acceptance of a DONE item and needs a key bound to a user; a key
with no user gets user_bound_credential_required. add-evidence records a
test run done outside AnyForge from an evidence object (summary and
status required; environment, links, casesRun, casesPassed,
casesFailed and clientVisible optional), attributed to the key's user or,
for a key with no user, to an API key. share-evidence with evidenceId and
clientVisible shows or hides a reviewed entry on client reports and requires
a user-bound key. remove-evidence with evidenceId
removes one entry, for its author or an owner. anyforge_get_work_item returns
the entries as testEvidence. A program can require one entry before its items
are marked done: set testEvidenceRequired with anyforge_update_program.
While it is on, complete on an item with no entry answers 409
test_evidence_required; close-as-fixed is not held by it.
Comment audience uses the same clientVisible vocabulary as test evidence.
anyforge_list_work_item_comments returns a boolean clientVisible on every
comment (absent in storage reads as false). anyforge_post_work_item_comment
is internal unless clientVisible: true; anyforge_share_work_item_comment
(itemId, commentId, clientVisible) changes an existing comment. The gate is
the Console's: write scope and a key owner who is currently an Editor or
above, so a key with no user gets key_not_attributable. A reply can be shared
only while its parent is shared (parent_not_shared). Replies and attachments
stay Console-only.
The structured Program Genesis writes are program-scoped. Brief saves are full
versioned replacements through anyforge_save_program_brief_version. Initiative
closures and batch close-as-fixed operations use preview followed by
execute with the short-lived proposalToken returned by the preview. A
successful initiative enrichment returns changedFields; a valid request that
does not change stored data returns changed: false and
reason: "no_changes_requested".
With the default analysis gate enabled, Crew dispatches require a connected
Codebase with both Phase 1 and Phase 2 analysis complete. Use
anyforge_analyze_repos to start Phase 1, then wait for the automatically
chained Phase 2 before dispatching a work item. The dispatch response identifies
the missing stage when a repository is not ready.
Tool metadata: annotations + structured output
Every tool advertises 2025-06-18 MCP metadata so clients can present it well:
- Title + behaviour annotations — a human-readable
titleplus hints (readOnlyHint,destructiveHint,idempotentHint,openWorldHint) derived from the tool's verb, matching the explicit policies and Scope column above. Clients use these to, e.g., auto-run read-only tools and confirm before adelete_*. They are advisory only: the control API still re-checks the key's scopes on every call, so annotations never widen access. - Structured output — every tool declares an
outputSchema(a JSON object) and returns the result asstructuredContentalongside the human-readable text block, so structured-output-aware clients get machine-parseable data. Arrays come back as{ items: [...] }and prose as{ text: "…" }.
Both are filled in centrally (lib/toolMeta, lib/toolResult) so the stdio and
hosted-HTTP transports advertise and return exactly the same thing.
Find a work item by code
For a known full code, call anyforge_list_work_items with itemId:
{ "itemId": "WBA-004", "limit": 5 }Use the returned item's id with anyforge_get_work_item for its full details.
For a partial code or title, use search instead, for example
{ "search": "WBA-", "limit": 20 }. Search is case-insensitive and matches
substrings, so check the returned code and title before selecting a record.
Archived items are excluded by default, including code lookups; add
"includeArchived": true when looking for archived work. Check hasMore and
follow nextCursor with unchanged filters when there are more results.
Prompts (guided flows)
MCP clients that support server prompts (e.g. Claude Code surfaces them as
/mcp__anyforge__<name> slash commands) get:
| Prompt | Args | What it does |
|--------|------|--------------|
| genesis | programId?, goal? | Turns the client into the Program Genesis agent: it interviews you to scope a program across your codebases (using anyforge_list_repo_index / anyforge_get_repo_analysis), writes the program brief, then creates one initiative per in-scope codebase and offers to dispatch the architect on each. |
| platform_guide | topic? | Loads the static AnyForge platform model, surface map, tool-selection rules, and safety boundaries. Use live tools for current tenant state. |
The Genesis flow runs entirely in your agent — there's no server-side chat-in-a-tool. The prompt gives your client the persona + interview script; it drives the conversation and calls the tools above as it goes.
Resources
Clients that support MCP resources can list and read:
| URI | Content |
|-----|---------|
| anyforge://guide/platform | The portable anyforge-platform Agent Skill |
| anyforge://guide/platform/references/entity-model.md | Entity relationships and delivery lifecycle |
| anyforge://guide/platform/references/tool-map.md | Representative tool categories and selection rules |
| anyforge://guide/platform/references/operating-boundaries.md | Identity, evidence, trust, and secret-handling boundaries |
The server's bootstrap instructions point clients at the prompt and resource when platform context is needed. They are orientation only; permissions and current state still come from the authenticated server and live tool results.
Example prompts
- "What's waiting for my approval in AnyForge?" →
anyforge_list_pending_approvals - "Show me the plan for approval
abc123then approve it." →anyforge_get_approval_detail→anyforge_submit_approval - "Add a P1 bug: rate-limit the export endpoint." →
anyforge_create_work_item - "Crew
xyzis running: tell it not to touch the migration files." →anyforge_message_crew - "What did crew
xyzproduce? Tag Sam on it to review the tests." →anyforge_get_crew→anyforge_post_crew_comment - "Scope a coverage program across our Go services." → run the
genesisprompt → it lists repos, scopes, and creates an initiative per service.
How it works
Claude CLI ──stdio──▶ MCP server ──HTTPS (Bearer sk_anyforge_…)──▶ /api/v1/control/* ──▶ shared control servicesThe /api/v1/control/* routes share the exact same service layer as the
AnyForge web app, so the CLI and the dashboard behave identically.
Console links in findings
The server advertises MCP instructions (see lib/consoleLinks.ts, mirrored by
the hosted /api/mcp transport) telling every client to present entity ids as
clickable links to their Console views by default — crew → /studio?crew={crewId},
work item → /work?item={workItemId}, initiative → /initiatives/{initiativeId},
and so on — never as bare ids. Crew payloads additionally carry an absolute url
field built server-side from the deployment's public origin. The path table is a
hand copy of the app's single source of truth
(app/lib/navigation/entityRoutes.ts), kept in lock-step by a drift test
(__tests__/lib/navigation/entityRoutes.test.ts) — change them together. The
Console enforces the viewer's permissions when a link is opened, so linking never
widens access.
Build & publish (maintainers)
The package ships a single bundled, minified JS file (dist/index.js),
so end users can run npx -y @anyforge/mcp-server without a TypeScript
toolchain. Source lives in index.ts / lib/ / tools/; esbuild
bundles it into one ESM file with the shebang preserved and node_modules
deps left external (--packages=external). The bundle is minified — not as
a security control (a downloaded npm package is always readable), but to keep
the tarball small; the real trust boundary is the key-authenticated control
API, and this process holds no secrets. Type-checking is a separate tsc
--noEmit step. dist/ is git-ignored and rebuilt at publish by
prepublishOnly.
npm install # esbuild + typescript devDependencies
npm run type-check # tsc --noEmit (types only, no output)
npm run build # esbuild → dist/index.js (bundled + minified)
npm pack --dry-run # verify the tarball: dist/ + README + package.json onlyPublishing is automated. Push a mcp-server-v<version> tag and the
.github/workflows/publish-mcp-server.yml workflow builds and runs
npm publish (scoped public), after a locked install, type check, build and
tarball inspection. Re-running a tag whose version is already on npm skips
publication. Keep the tag version in sync with
package.json:
cd packages/control/mcp-server
npm version minor --no-git-tag-version # update package.json and package-lock.json
# Commit and merge the reviewed version change before tagging that merge:
git tag mcp-server-vX.Y.Z <reviewed-merge-sha>
git push origin refs/tags/mcp-server-vX.Y.ZThe workflow needs an
NPM_TOKENrepo secret (an npm automation token for an account with publish rights on the@anyforgescope). One- time setup:npm token create --read-only=false, then add it under GitHub → Settings → Secrets → Actions asNPM_TOKEN.To publish manually instead:
npm login && npm publishfrom this directory (prepublishOnlyrebuildsdist/first).
Historical triage compatibility
Historical contextMode and saved-snapshot tools require MCP server 3.2.1 or
later after its separate release. A deployed hosted MCP endpoint follows the
application version; installing or pinning the stdio package is a separate step.
Older stdio handlers can drop an unknown contextMode, so do not infer isolation
from the request: verify the returned run says contextMode: "historical".
Historical case IDs are excluded from default-current runs. Saved evidence and
historical run reads require Owner/Operator management permissions. No package
tag or publication is performed merely by building these sources.
