Skip to main content

API surface — MCP tools, REST endpoints, and coverage

The current catalog of MCP tools and REST endpoints exposed by the Studio Host, plus which surface (the VS Code extension, autonomous agents, or neither) actually reaches each one. Ground truth (verified directly against source, not the tables below — the tables illustrate shape/category, not an exhaustive per-tool listing): 117 nm_v1_* MCP tools, 72 of them dispatched in-process to autonomous agents, 15 nms_v1_* external-caller tools, and 214 REST routes.
Frozen design principles, request/response schemas, and the error envelope format live in the internal MCP v1 contract — this page is the practical, currently-verified catalog and supersedes tool counts anywhere they’ve drifted.

External caller surface (nms_v1_*)

These 15 tools are the recommended entry point for external MCP clients — Claude Code, Cursor, scripts, CI agents. They cover the full human-in-the-loop lifecycle at a goal-centric level, without requiring knowledge of work units, branches, or the internal DAG.
Naming: nms_v1_* (NodalMerge Studio v1) vs. nm_v1_* (NodalMerge v1). The extra s marks the Studio-level abstraction layer. Both namespaces share the same host and the same error envelope format.

Goal management

Clarifications

Results

Repository registration

Workspace / feedback

Typical external-caller flow

REST equivalents exist for all these operations (/studio/goals, /studio/merges, /studio/repositories, /studio/clarifications), but the nms_v1_* MCP surface is the preferred path for MCP-native clients.

How the transports relate

A capability that has both a REST endpoint and an MCP tool calls the same command service either way — they can’t drift in behavior. Agents never make HTTP calls to their own host’s REST API; they call the tool dispatcher in-process. A REST endpoint with no frontend caller can still be heavily used — just by agents, via the MCP tool it shares a command service with.

MCP tool catalog (117 tools — categories below are not exhaustive)

✅ = dispatched in-process to orchestrator/worker agents · — = MCP-client, REST, or extension only.

Projection

Work unit

Task

Branch

Merge

Dead-letter

Deliberately not dispatched to orchestrator/worker agents — these are human-initiated recovery actions on an already-failed, already-exited work unit, not something a running agent would ever call on itself. The recommended external-caller flow reaches the same capability through nms_v1_goal_status (surfaces an unresolved failure and which actions apply) and nms_v1_goal_recover (resolves the goal’s own latest entry internally — no entry ID needed) instead of these detailed, entry-ID-based tools.

Replay

State / Known Good

Snapshot

Agent

Agents cannot pause/resume themselves or each other — those are human/extension-only actions today.

Workspace — file I/O, execution, semantic navigation, and profile

Routing rule: when semantic tools are allowed in a profile, they are the authoritative path for symbol definition/reference/implementation questions. Use nm_v1_workspace_search for text/content questions, not symbol relationship resolution.

Scheduler

Intent

Artifact

Goal, Decision, Evidence, Trajectory, Hypothesis (Phase 6.7+)

None of these are dispatched to autonomous agents yet.

Phase 7 — REST-only, no MCP tool at all

REST endpoint catalog (214 routes)

Grouped by resource area; StudioRestEndpoints.cs is the single file that registers all of these.

Workspace files & execution

branchId is a query parameter on every one of these, not a route segment — branch IDs like merge/{workUnitId} contain a literal /, which a {branchId} route segment can never match.
  • POST /studio/workspace/build|test|exec|run?branchId=... — trigger build / test / build+test+lint / run on a branch
  • POST /studio/workspace/run/stop?branchId=... — stop one/all branch run processes
  • GET /studio/workspace/exec/latest?branchId=... — latest execution result
  • GET /studio/workspace/exec/output?branchId=...&resultId=... — cached stdout/stderr for a past result
  • GET /studio/workspace/path?branchId=... — branch working directory path
  • GET /studio/workspace/profile?branchId=... — detected workspace roots/stacks/commands
  • POST /studio/workspace/profile/rescan?branchId=... — refresh detected workspace profile
  • POST /studio/workspace/switch — force a repository resync against current disk content (see Guides → Repository virtualization)

Work units, tasks, agents, merges, branches

  • Work units: GET/POST /studio/workunits, GET /studio/workunits/{id} (+/children, /artifacts, /orchestration-events, /intents, /conflict-report, /proposal-dag), POST /studio/workunits/{id}/cancel, POST /studio/workunits/{id}/requeue (un-cancel and resume; optional credential overrides), POST /studio/stop-all
  • Tasks: GET /studio/tasks, GET /studio/tasks/{id}, POST /studio/tasks, PUT /studio/tasks/{id}, POST /studio/tasks/{id}/assign
  • Agents: GET /studio/agents (?all=true for all), POST /studio/agents/spawn, GET /studio/agents/{id}/status, POST /studio/agents/{id}/pause|resume|stop
  • Merges: GET/POST /studio/merges, GET /studio/merges/{id} (+/constituents, /file-changes), POST /studio/merges/{id}/validate|review|apply (review body: { decision: "Approved"|"Rejected" } — there is no separate /accept//reject route), GET /studio/merges/compare?ids=, POST /studio/merges/{id}/branch, POST /studio/merges/{id}/restore-workspace
  • Branches: GET /studio/branches, POST /studio/branches, POST /studio/branches/{id}/checkout, GET /studio/branches/{id}/status, POST /studio/branches/candidate/promote
  • Candidate & task conflicts (reconciliation — see Concepts → Trust & autonomy § Reconciling candidate conflicts): GET /studio/branches/candidate/conflicts, POST /studio/branches/candidate/conflicts/{id}/reconcile, POST /studio/branches/candidate/conflicts/{id}/resolve, GET /studio/workunits/{id}/task-conflicts, POST /studio/workunits/{id}/task-conflicts/{conflictId}/reconcile, POST /studio/workunits/{id}/task-conflicts/{conflictId}/resolve. The work unit’s own /proposal-dag (listed above) now also surfaces reconciliation edges, and GET /studio/merges/{id}/constituents resolves a reconciled proposal back to its source proposals.

Known-good states & cache management

  • POST /studio/state/markKnownGood, GET /studio/state/knownGood/{branchId}, POST /studio/state/checkoutKnownGood, POST /studio/state/{stateId}/fork (fork a new work unit seeded from a checkpoint’s snapshot branch — the extension’s “Fork from Known Good”)
  • Branch directory cache (WorkspaceCacheManager, REST-only — see Guides → Repository virtualization): POST /studio/cache/evict?workUnitId=..., POST /studio/cache/materialize?workUnitId=..., POST /studio/cache/evict/orphaned, POST /studio/cache/gc?dryRun=...

Dead-letter queue

  • GET /studio/dead-letter, GET /studio/dead-letter/{id}, GET /studio/dead-letter/by-work-unit/{workUnitId}, GET /studio/dead-letter/history/{workUnitId} (full failure history, oldest first)
  • POST /studio/dead-letter/{id}/retry, POST /studio/dead-letter/{id}/retry-with-context (folds a human correction into the goal, bypasses the normal attempt cap), POST /studio/dead-letter/{id}/replan (decompose the failed slice into fresh sub-slices, mark original Cancelled — never gated on attempt count since it never resumes the failed work unit), POST /studio/dead-letter/{id}/continue (MaxIterationsExceeded only — resume the SAME work unit with reconstructed prior context and a fresh iteration budget)

Everything else

  • Agent profiles: GET /studio/agent-profiles, GET /studio/agent-profiles/{id}, POST/PUT /studio/agent-profiles/{id}
  • Scheduler: GET /studio/scheduler/pending|awaiting-resume, POST /studio/scheduler/{workUnitId}/resume, POST /studio/scheduler/resume-all, POST /studio/scheduler/enqueue
  • Clarifications: GET /studio/clarifications/awaiting, POST /studio/clarifications/request, POST /studio/clarifications/{workUnitId}/respond
  • Sessions & events: GET/POST /studio/sessions, GET /studio/sessions/{id}, POST /studio/sessions/{id}/pause|resume|abandon, GET /studio/sessions/{id}/workunits|events|state, GET /studio/events/{id}
  • Artifacts: GET/POST /studio/artifacts, GET /studio/artifacts/{id} (+/children), POST /studio/artifacts/{id}/elevate (widen a repo-scoped constraint to all repositories)
  • Insights & findings (see Guides → Knowledge & constraints): GET /studio/findings (?status=), POST /studio/findings/{id}/review ({ decision, notes } — promote/dismiss/investigating), POST /studio/findings/import, POST /studio/insights/detect-findings (deterministic pattern rules), POST /studio/insights/llm-scan (body is a resolved LLM config; routes to an HTTP one-shot or a claude-cli/codex-cli one-shot by provider; returns { findings, rawCliOutput })
  • Constraints: GET /studio/constraints (?repositoryId=; each row labeled with reach + appliesToAllRepos + local enabled), POST /studio/constraints (manual add — { title, body, reach: "Workgroup"|"Private", repoSpecific } → a global constraint at the chosen 2×2 scope), POST /studio/constraints/{id}/toggle ({ disabled } — peer-private local suppression, not replicated), POST /studio/constraints/{id}/scope ({ reach, repoSpecific } — set the full 2×2 scope and re-route; generalizes /elevate), GET /studio/constraints/proposed (work-unit-owned observer/agent constraints eligible for promotion, each flagged promoted), POST /studio/constraints/{id}/promote ({ reach?, repoSpecific? } — mint a global copy of a lineage constraint stamped with promotedFromArtifactId; idempotent, returns the existing promotion if already promoted)
  • Options/policies/projections/snapshots: GET/POST /studio/options, GET /studio/policies, GET /studio/projections, GET /studio/projections/{type}, GET /studio/snapshots/{agentId} (+/compare/{otherAgentId})
  • Replay: GET /studio/replay/timeline (+/{branchId}), GET /studio/replay/range/{branchId}, POST /studio/replay/rollback/{branchId}, GET /studio/replay/inspect/{branchId}
  • Goals/decisions/evidence/trajectory/hypotheses/reasoning/models: GET/POST /studio/goals, GET/POST /studio/decisions, GET /studio/evidence + POST /studio/evidence/attach, GET /studio/trajectory/replay + POST /studio/trajectory, GET /studio/hypotheses + POST /studio/hypotheses/fork, POST /studio/reasoning, GET /studio/models/compare|replay/{workUnitId}
  • Phase 7: GET/POST /studio/experiments, GET /studio/experiments/{id}, POST /studio/steering/redirect|fork-from-node, POST /studio/counterfactuals
See Concepts → Trust & autonomy for the human-in-the-loop rationale behind these boundaries.