Skip to content

MCP agent operations

This page lives in Guides because the Agents group documents coding agents Shipper launches, while this guide is for agents that consume Shipper over MCP and the people who configure them.

MCP listings group next work as Design, Plan, Implement, Review, Rework, and Ready. Designed simple issues next need Implement; complex or undecided issues next need Plan. Packaged work next needs Review with or without a pull request. Ready means ready for final integration, not shipped. Existing records receive this presentation without migration or reprocessing.

Blocked issues remain in their next-step group with blocker details. New is separate; held and failed leave the six groups, and closure hold takes precedence. Attention counts overlap pipeline membership. nextStep and nextStepPipeline add presentation information while completed-stage fields, filters, reset arguments, and historical records retain their meanings.

Reset previews lead with next work and the literal completed-stage target. Plan drops target designed for complex or undecided routes; --to planned next needs Implement. A simple Plan drop refuses without changing route, and a non-failed same-column drop does nothing. Existing eligibility, confirmations, warnings, and work-preservation guarantees apply.

See Next-step presentation for full count and reset rules and label-description rollout. Descriptions refresh during normal label setup or maintenance; read-only status, list, and view make no label writes.

Shipper owns issue identity and content, workflow state, lifecycle history, and issue actions. A GitHub issue mirror is an optional projection of that state, not a peer authority or a fallback when an operation is unavailable.

Start from the intent you need to accomplish and use a Shipper capability. Do not treat a projected GitHub issue as an alternate interface to Shipper-managed state.

S#42 is a complete, valid Shipper issue reference. A local issue does not need a GitHub issue number to exist or move through the workflow.

Shipper reports one of three exact postures: GitHub-backed, Remote git without pull requests, or Fully local. Read the operating model in Repository postures instead of reconstructing it from the presence of a remote or issue mirror.

Server startup and local tools support a committed Shipper repository with no remote. They require neither an authenticated gh nor GitHub reachability. GitHub access is checked only when the invoked operation needs effective transport, pull-request, or issue-projection capability. A failure in such an operation does not make local tools unavailable.

Protected workflow operations invoked through MCP spawn protected Shipper CLI stages and therefore inherit the Shipper license boundary. See Licensing and authentication for sign-in, revalidation, and cached-grace behavior.

An initialization failure still starts the MCP server with one stable tool catalog. shipper_switch_repo remains callable as in-band recovery. Repository reads without repository_path and all mutations keep returning the original startup error until recovery succeeds. A valid explicit repository_path on a repository-scoped read remains usable against that checkout without repairing or changing the degraded active state.

Recover from a degraded repository startup

Section titled “Recover from a degraded repository startup”

Invoke shipper_switch_repo while treating untargeted repository operations’ original startup error as authoritative until a switch succeeds. Recovery targets may be absolute paths or paths relative to the server’s current working directory. A target must already be an existing readable local Git checkout with at least one commit that passes the same settings, policy, and preflight readiness as a normal startup. A committed local repository without a remote is a valid switch target; a remote is not required. Never clone, initialize, or otherwise prepare a checkout as part of recovery.

A failed attempt returns that target’s error, preserves degraded state and the original startup error, and can be retried immediately. Successful recovery takes effect on the same connection without restarting the server. Capable clients may receive a tools/list_changed notification, but clients do not need to relist tools before calling the previously advertised names. The recovered selection is runtime-only: it does not persist across a server restart.

Every currently delivered repository-scoped read accepts the same optional local-checkout repository_path: status, monitor, watch listing/inspection, issue listing/detail/review/session logs, and pull-request inspection. Omit it to use the active repository. An explicit repository_path uses that checkout’s local identity and settings for one call, changes no cwd or active/committed server state, does not count as active-repository work, and preserves the existing successful response shape. Preparation does not contact GitHub, run preflight, or start a daemon; after preparation, live issue/PR/check reads retain their ordinary external behavior. Documentation search/get remain target-free.

Switches never wait for active work. A different-repository request immediately refuses with the exact current active-operation count, leaves the active repository unchanged, and queues nothing. The already-active checkout remains an immediate success even while busy. Unrelated calls continue during switch preparation; if one is still active at the final pre-commit recheck, the switch refuses instead of draining it. A concurrent different switch is also refused without queuing.

shipper_advance, fresh shipper_groom, and grooming reconstructed by shipper_answer_question have no MCP-specific whole-run deadline. agentTimeoutMinutes is enforced independently for each agent attempt; ordinary retries, correction agents, answer waits, projection, cleanup, recorded-run finalization, and lock release remain part of the child-owned lifecycle. Time paused awaiting a product-owner answer consumes no agent-running timeout.

A terminal timeout response means the authoritative local agent_timeout record and failed workflow state already exist, the MCP-attributed run is terminal, and the timed-out run no longer owns the issue lock. Mirror-on projection failure is repairable debt, not a rollback: the response preserves the shipper issue reconcile --repair warning while local failure and unlock remain complete. The report names discarded staged, unstaged, and untracked work and the exact reset action. When it also names a workflow branch and full revision, only an unchanged ref at that revision survives the matching same-stage reset; the ephemeral worktree is removed, and the next groom or scaffold run continues from the commit. Never infer preservation from a branch name alone.

Mirror-on adds a GitHub issue view without changing which system is authoritative. A Shipper-managed issue is one that carries a Shipper local ID such as S#42. mirrorMode is independent of the repository posture wherever policy validation permits it. In both mirror modes, never use direct GitHub issue reads or writes as substitutes for Shipper capabilities for a managed issue.

The write and read hazards are different:

  • Writes: store-only has no GitHub issue mirror to write. Under mirror-on, a direct GitHub issue write can succeed, exit zero, and render correctly, then be silently reconciled away because the local store governs the issue.
  • Reads: store-only has no GitHub issue mirror to read. Under mirror-on, the mirror is a projection that can lag the local store that governs workflow behavior.

This restriction does not apply to ordinary GitHub issues in the same repository that Shipper has never adopted. Those issues do not carry a Shipper local ID and remain ordinary GitHub objects.

For configuration and transition mechanics, use Settings and the State Machine rather than deriving policy from a mirror’s current shape.

Call shipper_status and read configuration.effective.posture, configuration.effective.transport, configuration.effective.pullRequests, configuration.effective.reviewDelivery (always local), and configuration.effective.mirrorMode. The posture gives the operating picture; the individual capabilities tell an agent whether the requested side effect is enabled. Do not infer them from how an issue reference renders, and do not inspect committed settings out of band.

The map below names unsupported intents explicitly. Omitting them would make the map look incomplete and encourage an agent to improvise with gh; an explicit absence closes that unsafe fallback and states the available alternative.

IntentShipper capability and effective boundary
Discover posture, capabilities, and mirror modeshipper_status
Switch repositories or recover from startup failureshipper_switch_repo remains callable after a repository initialization failure and restores the same connection without a restart.
Observe auto-ship desired state and suppressionRead shipper_status.autoShip during orientation. This is a read-only view of enabled, worker-count, halt-request, and durable safety-stop suppression for the active repository.
Observe or recover dispatch ownershipRead shipper_status.dispatchOwnership. If held ownership must be discarded, call shipper_clear_dispatch_ownership without input, review the holder and warning, then echo its confirmation_token.
Change auto-ship desired stateshipper_set_auto_ship is an explicit machine-local state mutation. Do not call it speculatively during orientation.
Resume auto-ship after a safety stopshipper_resume_auto_ship clears only the active repository’s durable stop. The active repository is selected at startup or by shipper_switch_repo.
Create, read, list, or triage local issuesshipper_create_issue, shipper_get_issue, and shipper_list_issues work in all three postures.
Browse a locally held review roundRead compact Reviews with shipper_get_issue, then pass a stable round identity to shipper_get_review_round for full detail.
Find issue session transcriptsshipper_get_session_logs returns per-run paths and context for open or closed issues; transcript contents and consolidated workflow logs are outside this capability.
Record or retract a durable noteshipper_comment and shipper_retract_comment remain local; mirror-on projects them only when issue projection is enabled.
Set priority, close, block, or unblockUse shipper_set_priority, shipper_close_not_planned, shipper_block, and shipper_unblock.
Advance workflow, package, review, or reworkUse shipper_groom at intake and shipper_advance afterward. PR-disabled postures package a local change and retain review and implementation rework locally.
Reset or unlockshipper_reset and shipper_unlock work on local workflow state.
Merge the ready changeshipper_merge merges a GitHub PR when PRs are enabled or the recorded local change when they are disabled.
Recover a failed packaged changeshipper_recover works in all three postures and dispatches from the raw stored artifact. It commits locally first and reports projection warnings without rolling recovery back.
Inspect a pull request and its checksshipper_get_pr requires effective pullRequests: "github"; omission of mode returns the comprehensive view, while mode: "checks" fetches only checks and applies up to three ten-second retries after an initial no-checks observation; there is no gh fallback when pull requests are disabled.
Adopt an existing GitHub issue or pull requestshipper_adopt requires the corresponding GitHub issue or PR capability. It is absent in a fully local repository.
Arbitrarily edit a managed issue title or bodyNo general MCP capability. GitHub is not a fallback. Use grooming at intake, add a durable note for additive context, or report that MCP cannot perform the canonical edit.
Have a human author a durable Shipper noteNo capability. GitHub is not a durable-note fallback. A linked issue or pull-request comment is transient steering only; purely local work has no external advisory target.

This table is intentionally organized by intent. The generated MCP reference is the sole authority for the complete, current operation inventory, schemas, results, and errors.

Review browsing is read-only, local-only, unbounded, and available for active, completed, and not-planned issues. Compact Reviews includes optional handling state; full locally held review round reads include complete feedback, stable finding identities and locations, comments, replies, optional handling enrichment, and partial coverage. An issue with no rounds returns explicit empty Reviews, while an unreadable review record reports that section as unavailable without hiding ordinary issue detail. GitHub-sourced inline PR review threads are not shown here; locally retained Shipper review rounds are shown under Reviews.

Read shipper_status.supervision alongside autoShip, automaticWork, and supervisorAvailability from an enable response. Registration, enabled intent, pickup, and running work are separate facts. The diagnosis distinguishes unregistered, unresolvable, pickup-unconfirmed, supervised, and unknown.

For missing registration: Switch to owner/repo’s checkout and explicitly enable Auto-ship. For an unavailable registration, correct the reported path/access/identity problem or register its replacement. Pickup unconfirmed is neutral: check status after roughly five seconds. Available evidence may not establish the cause. A host connection or a live dispatch owner alone does not confirm pickup, and a supervised repository may have zero running work. When an enabled repository leaves supervision, the daemon emits a named warning and auto-ship-supervision-lost diagnostic.

Unreadable registrations are preserved unchanged. Use a build able to read newer records, restore damaged files from a valid copy, or correct the reported storage/lock problem. Do not delete/reset registration information. Readable peers remain visible. Discovery of legacy schema-1 saved intent requires a verified identity mapping; otherwise Desktop reports an unidentified enabled saved record by path. Without surviving identifying evidence, the original name cannot be recovered.

shipper_status.autoShip observes the active repository without mutation. Its available form has four required fields: enabled, workerCount, haltRequested, and suppression. The suppression union is either { suppressed: false } or an engaged value with suppressed: true, engagedAt, lifetime engagementCount, exactly three distinct qualifying failures, and resumeTool: "shipper_resume_auto_ship". Each failure is a strict scope variant. Issue conditions name the Shipper issue with localId, nullable githubIssueNumber, and title; repository conditions name only the affected objectKey; migrated legacy conditions explicitly say their identity is unavailable. Every variant exposes a human summary, cause, qualifying kind, and initial/changed/recurred relation, but no opaque revision, progress generation, or raw observation count. engagementCount > 1 identifies a recurring engage/clear/re-trip loop. If the machine-global record cannot be read, the entire section is an explicit unavailable marker rather than false, one worker, no halt, and no suppression. That degradation is independent of issue-state degradation and does not carry the issue-reconcile recovery command. A repository with no record and one explicitly recorded as not enabled have the same effective observation.

Agents must check suppression before concluding that an enabled repository is dispatching. Disabled, halted, suppressed, daemon availability, and automatic-work counts are independent facts; do not collapse them into one dispatch state. The durable stop remains visible even after a daemon idle-exits.

Halt, disable, and the safety stop are three distinct states:

  • Halt is a persistent operator-requested repository hold recorded in haltRequested. It preserves enablement and worker settings, withdraws queued automatic starts, drains running automatic Ships to their safe checkpoints, blocks every later automatic stage and merge, and survives an idle repository, wind-down completion, and daemon, Desktop, CLI, or machine restart. It ends only through an explicit clear with shipper_clear_auto_ship_halt or a halt_requested: false MCP patch.
  • Disable is enabled: false. It drains current automatic work and prevents dispatch until Auto-ship is enabled again. Neither disabling nor enabling clears a halt.
  • The safety stop is the automatic failure safeguard, with its own status and its own recovery gesture, shipper_resume_auto_ship. Safety recovery never clears a halt.

Explicit manual work stays available under a repository halt, including hand-driven workflow advances and per-run Pause and Stop actions.

Use shipper_set_auto_ship deliberately to record one or more values in a single write:

  • Every field is literal: fields the patch does not supply are preserved exactly.
  • Supply only worker_count to preserve both enablement and the halt.
  • Supply halt_requested: true to record the persistent hold; enabled and halted is a valid state.
  • Supply halt_requested: false alone as an explicit halt clear without changing enablement.
  • Supply enabled: true and halt_requested: false together for an atomic enable-and-clear.
  • Supplying enabled: true alone never clears a halt.
  • Repeating enabled over an already-enabled record does not clear an engaged safety stop. Use shipper_resume_auto_ship for direct recovery. A genuine not-enabled-to-enabled transition remains the other gesture that clears the stop.

Interpret the result as durable intent plus explicit runtime evidence:

  • Enable attempts and reports. Explicit enable registers the resolved checkout before the entire desired-state patch, then makes a bounded attempt to provide a supervisor. Registration refusal is a tool error: enablement did not complete, no supplied worker or halt field is written, the prior enabled setting is unchanged, and no startup is attempted. If a later intent write fails, registration remains recorded and is disclosed, including in compatibility-refusal text. The result contains exactly one supervisorAvailability outcome: available, not-started, incompatible, or indeterminate. An incompatible outcome includes the client, daemon, and minimum daemon versions plus which side is stale; a human operator should re-run Shipper installation and surface the result to the agent. Other mutations do not start or attach to a supervisor. A running supervisor normally observes those changes within roughly five seconds.
  • Halt and disable request safe-checkpoint Stops. A supervisor withdraws queued automatic work and arms running automatic Ships with repository-control. Once enabled and unhalted is observed, it retracts only unconsumed repository-control requests; explicit per-run Pause and Stop survive. Runs that already stopped and queue entries already withdrawn are not revived.
  • Halt responses report intent plus observed evidence. Any patch that sets halt_requested: true states whether durable halt intent changed or was already set, states that the hold persists until it is explicitly cleared, and includes the normalized automaticWork status the tool actually observed: draining, idle and held, in flight without confirmed draining, or unavailable. No response describes a halt as consumed or automatically cleared.
  • Clear output is intent, not observation. A halt clear can be recorded with no live supervisor. It reports cleared or already-clear, reports no retraction count, and does not prove which runs were released; use later status observations for runtime evidence. Clearing never restarts already-stopped runs, restores withdrawn queue entries, or replays prior work.
  • Non-enable changes to untracked repositories persist. A supervisor acts only on repositories it tracks, and the operator has no board surface on which to observe or stop work for an untracked repository. Explicit enable registers the active resolved checkout before its availability attempt.
  • Enabled means requested, not dispatching. A persistent halt or a durable safety stop prevents automatic dispatch across daemon exit and restart without changing the recorded enabled value. Check autoShip.haltRequested and autoShip.suppression; only an available outcome proves a usable supervisor was reached during an enable call.
  • Auto-merge is separate. Enabling auto-ship advances stages, but nothing merges unless the operator separately enabled Auto-merge.
  • The state is machine-global. This machine-global operator state follows the machine and its operator, is not committed repository configuration, and is not shared with collaborators.

shipper_status adds two read-only runtime views. daemon reports advisory instanceId, version, generation, superseded, and updatedAt facts when running; plain not-running is an ordinary value. automaticWork reports only the active repository’s inFlight count and drainInProgress boolean. Combine it with autoShip.haltRequested to distinguish a repository still draining from one fully held: available evidence with drainInProgress: true is draining, available evidence with no in-flight work and no drain is fully held, and an unavailable marker means report durable halt intent only without claiming drain completion. Its unavailable marker is independent from daemon, issue-state, and desired-state markers, and it never substitutes another repository’s row or identities. Status reads local ownership and status files only: it never starts or attaches to a daemon, creates a client, or affects daemon lifetime.

shipper_resume_auto_ship performs one atomic safety-stop clear for the active repository. It succeeds with outcome: "cleared" when a stop was engaged and with outcome: "not-engaged" as an idempotent no-op otherwise. It never enables a disabled repository, changes workerCount or haltRequested, registers a checkout, or starts or coordinates a daemon.

shipper_clear_auto_ship_halt is the separate halt-specific gesture. It takes no input, performs one { haltRequested: false } patch for the active repository, and succeeds with outcome: "cleared" when a halt was recorded and outcome: "already-clear" as an idempotent no-op otherwise. It never enables Auto-ship, changes workerCount, resumes an engaged safety stop, registers a checkout, or starts or coordinates a daemon.

shipper_status.dispatchOwnership is independent of desired state, suppression, daemon advisory state, and automatic-work counts. It is not-held, held, or unavailable. A held value contains exactly five public facts: surface, pid, acquiredAt, liveness, and lastRefreshAt. Surfaces are desktop, daemon, terminal, or unrecognized; liveness is running or could-not-determine. Last refresh is diagnostic context only. While dispatch ownership is held, any other scheduler on this machine stands down rather than dispatching for this repository.

An unrecognized surface is still clearable held ownership. An unavailable value is unknown, names no holder, and must never be treated as not-held; resolve its local read failure before recovery. Status reads the active repository’s record locally and neither attaches to or creates a daemon nor calls GitHub.

shipper_clear_dispatch_ownership is a guarded two-call operation:

  1. Call {}. confirmation_required returns the same five facts, an opaque confirmation_token, and this warning: Discarding dispatch ownership held by a genuinely running holder means two schedulers will dispatch for this repository concurrently. The first call never mutates. nothing_to_clear is the successful no-op when that preview finds no holder.
  2. After reviewing the facts, call { "confirmation_token": "<opaque>" }. cleared returns the removed holder. unavailable states that nothing was cleared and requires the read failure to be resolved.
  3. If the stable holder identity changed or the reviewed record vanished, changed returns the current observed status and states that nothing was cleared. Discard the prior token and make a fresh tokenless preview; never retry blindly.

The token covers stable repository and holder identity, not renewedAt, liveness, schema version, or future members. A same-owner refresh therefore remains confirmable, while a successor owner does not. The tool scopes both calls to the active repository, does not change desired state, and calls local core storage directly without daemon or GitHub side effects. After a clear, the affected supervisor reacquires on its normal four-second observation cadence and resumes dispatch; other repositories remain unchanged.

In GitHub-backed, packaging produces a GitHub PR and the stored stage displays as Review. shipper_get_pr without mode loads the comprehensive summary, merge-state, checks, review, and thread view. Its mode: "checks" branch is materially lighter: it loads only checks, retaining the no-check startup grace without requesting summary, review submissions, or inline threads. A direct GitHub pull-request read consults the PR source of truth and is acceptable only for observations that shipper_get_pr does not expose.

Anything that changes pull-request or workflow state must go through Shipper. Merge with shipper_merge, advance stages with shipper_advance, and establish or restore the pull-request-to-issue association through the normal Shipper workflow or shipper_adopt. Merging directly on GitHub leaves the local store believing the work is still in flight.

Acquisition uses the real PR, and Shipper keeps the review as a locally held review round; read it with shipper_get_review_round.

In Remote git without pull requests and Fully local, packaging records a pinned local change and displays Review. Review reads its local three-dot diff, retains a locally held review round, and displays Review. Implementation review-rework consumes that held round locally.

shipper_merge operates on the recorded local change and advances the target branch. With effective transport: "origin", Shipper publishes the advanced target branch; with transport: "none", the merge remains local. PR inspection, checks, and PR adoption are unavailable in both postures, and agents must not replace them with direct GitHub operations. Packaged-change recovery remains available through shipper_recover: it inspects the pinned local artifact and uses posture-neutral Change Packaged output containing no pull-request terminology. Remote git without pull requests can still adopt GitHub issues because its origin transport provides that source; Fully local has no GitHub issue or PR adoption source.

Shipper has three distinct annotation and steering channels, as described by Protocol:

  1. Agent-authored shipper_comment notes are the durable, retractable, Shipper-owned agent-to-agent record. Use a note to preserve a decision or context that later stages must retain.
  2. Ordinary GitHub issue and pull-request conversation comments are refreshed once at agent-stage entry as transient advisory input. They can steer an agent, but they cannot change Shipper issue or workflow state and are not a durable Shipper decision record.
  3. Inline pull-request review threads are the separate input channel for implementation review-rework.

Under mirror-on, a human can read an agent-authored note through its GitHub comment projection, but cannot author a durable note that agents treat as Shipper-owned history. The lack of a first-class human writer for durable Shipper notes is a known, deliberate gap. A human can instead leave a comment on a linked GitHub issue or pull request for transient advisory steering. Purely local work with no GitHub issue and no linked pull request has no external advisory target.

Shipper’s deliberate ingestion of those comments at stage entry does not permit an agent to replace a Shipper capability with direct GitHub issue reads. Ordinary comments are bounded advisory input, not an alternate issue-state interface.