MCP setup
This guide covers Shipper MCP setup for Claude Code, Codex, Grok Build, and OpenCode. Claude Desktop, Cursor, GitHub Copilot CLI, and generic MCP host setup are out of scope and are not documented here because each client has its own configuration format and startup behavior.
Prerequisites
Section titled “Prerequisites”Complete these checks before editing any MCP client configuration:
- Install Git and make sure the target repository is checked out locally and readable by the MCP client process.
- Install Node.js 22.23.1 with bundled npm 10.9.8 for the Shipper source checkout.
- Keep a local Shipper source checkout available for the MCP server package.
- Use a valid readable Git repository with at least one commit and
shipper setupalready completed. A committed local repository without a remote is supported. Useshipper setup --repowhen the target needs committed.shipper/artifacts. Seeshipper setupand the .shipper directory. - Make sure any local tooling required by your Shipper settings, such as the configured coding agent CLI for workflow stages, is available in the environment that will run Shipper commands.
Server startup and local tools such as shipper_status do not require GitHub reachability or an
authenticated GitHub CLI. Install and authenticate gh only for tools that access or project to
GitHub. For token-based environments, provide
GH_TOKEN or GITHUB_TOKEN in the MCP server
environment; see Containers and
GitHub Authentication Problems.
Obtain the server
Section titled “Obtain the server”@baremetallabs-ai/shipper-mcp is currently a private monorepo workspace. It is not published to npm,
so do not configure clients with npm install, npm install -g, or npx for this package.
Build the MCP server from a Shipper source checkout:
git clone https://github.com/baremetallabs-ai/shipper.gitcd shippernvm installnvm usenpm installnpm run build --workspace=packages/mcpAfter the build, configure the MCP client to run the generated server entrypoint with Node:
node /absolute/path/to/shipper/packages/mcp/dist/index.jspackages/mcp/dist/index.js is build output. It is gitignored and is absent from a clean checkout
until the build command creates it.
Choose the working repository
Section titled “Choose the working repository”The MCP server chooses one target repository at startup:
- If
SHIPPER_REPO_DIRis set to a non-empty value, the server resolves that value against the MCP process startup working directory and uses the resolved path. - If
SHIPPER_REPO_DIRis not set, the server uses the MCP process startup working directory.
After successful resolution, the server changes into the repository and writes this line to stderr:
shipper mcp: repo dir = /absolute/path/to/target/repoUse explicit SHIPPER_REPO_DIR for Claude Code, Codex, Grok Build, and OpenCode when the client configuration
lives outside the target repository, when one shared or global config can be used from multiple
repositories, or when you are unsure which directory the client uses to start MCP servers. The
canonical variable behavior is documented in
Environment variables.
Implicit startup-cwd selection is valid only when the MCP process starts inside the target repository.
Startup selection remains the default and is what a server restart returns to. After successful
initialization, shipper_switch_repo can retarget the running server at runtime. Switch targets
must already be local Shipper-ready Git checkouts; the tool does not clone, initialize, or persist
configuration.
Claude Code
Section titled “Claude Code”For a project-scoped Claude Code setup, add a .mcp.json file and change only the absolute Shipper
checkout path and target repository path:
{ "mcpServers": { "shipper": { "command": "node", "args": ["/absolute/path/to/shipper/packages/mcp/dist/index.js"], "env": { "SHIPPER_REPO_DIR": "/absolute/path/to/target/repo" } } }}Use claude mcp list or open /mcp in Claude Code to inspect the shipper server connection.
For Codex, add the server to ~/.codex/config.toml or a project .codex/config.toml and change
only the absolute Shipper checkout path and target repository path:
[mcp_servers.shipper]command = "node"args = ["/absolute/path/to/shipper/packages/mcp/dist/index.js"]startup_timeout_sec = 30tool_timeout_sec = 86400
[mcp_servers.shipper.env]SHIPPER_REPO_DIR = "/absolute/path/to/target/repo"The example uses a 24-hour tool timeout so Codex does not interrupt long-running Shipper workflow tools such as implementation, review, or merge stages. Lower it only when you intentionally want a client-side cutoff.
This client-call cutoff is independent of Shipper’s agentTimeoutMinutes. Issue-backed server
orchestration does not apply that agent limit to the whole MCP call: each headless agent attempt gets
its own limit, while retries, corrections, cleanup, finalization, and product-owner answer pauses do
not consume a shared stage timer.
If you deliberately want startup cwd to select the repository, omit SHIPPER_REPO_DIR and set
cwd = "/absolute/path/to/target/repo" under [mcp_servers.shipper]. Keep explicit
SHIPPER_REPO_DIR when the config can be reused outside that repository.
Use codex mcp list or open /mcp in the Codex TUI to inspect the shipper server connection.
Grok Build
Section titled “Grok Build”For Grok Build, add the server to ~/.grok/config.toml (all projects) or a project
.grok/config.toml and change only the absolute Shipper checkout path and target repository path:
[mcp_servers.shipper]command = "node"args = ["/absolute/path/to/shipper/packages/mcp/dist/index.js"]env = { SHIPPER_REPO_DIR = "/absolute/path/to/target/repo" }startup_timeout_sec = 30tool_timeout_sec = 86400The 24-hour tool_timeout_sec keeps Grok from interrupting long-running Shipper workflow tools
such as implementation, review, or merge stages. grok mcp add shipper -e SHIPPER_REPO_DIR=/absolute/path/to/target/repo -- node /absolute/path/to/shipper/packages/mcp/dist/index.js
writes the same entry non-interactively. Grok also imports MCP servers from Claude Code’s
~/.claude.json and a project .mcp.json when its Claude compatibility setting is on, so a
shipper server registered for Claude Code may already appear in Grok without a Grok-side entry.
Keep SHIPPER_REPO_DIR explicit when the Grok config can be reused outside that repository. If you
deliberately want startup cwd to select the repository, start Grok from the target repository and
omit SHIPPER_REPO_DIR.
Use grok mcp list or open /mcps in the Grok TUI to inspect the shipper server connection.
OpenCode
Section titled “OpenCode”For OpenCode, add Shipper as a local MCP server in your OpenCode MCP configuration. Use OpenCode’s current MCP config syntax, but keep the Shipper-side command and environment values the same:
command: nodeargs: ["/absolute/path/to/shipper/packages/mcp/dist/index.js"]env: SHIPPER_REPO_DIR: /absolute/path/to/target/repoKeep SHIPPER_REPO_DIR explicit when the OpenCode config can be reused outside that repository. If
you deliberately want startup cwd to select the repository, start OpenCode from the target
repository and omit SHIPPER_REPO_DIR.
Verify the connection
Section titled “Verify the connection”Confirm the client reports the server as connected or active:
- Claude Code: run
claude mcp listor open/mcpand confirmshipperis connected. - Codex: run
codex mcp listor open/mcpin the Codex TUI and confirmshipperis active. - Grok Build: run
grok mcp listor open/mcpsin the Grok TUI and confirmshipperis active. - OpenCode: inspect OpenCode’s MCP server list or logs and confirm
shipperis active.
Call shipper_status as the connection and repository-orientation smoke check. Use
MCP agent operations to choose the safe capability for a task, and
use the generated MCP reference as the complete, current authority for tool names,
schemas, results, and errors.
Record server.version, server.buildIdentity, and server.startedAt when diagnosing a connection.
After restarting or reconnecting the MCP client and server, call shipper_status again and confirm
that the start time changed and that the build identity identifies the bundle you intended to
launch. Compare issueState.observedSchemaVersion with issueState.supportedSchemaVersion; an
unavailable build identity and an unobserved store version are reported explicitly. If the fresh
server still reports a stale issue-state reader, update the installed Shipper release or rebuild the
source checkout, then reconnect and verify the identity again. Preserve the issue-state store
unchanged throughout this recovery.
Use shipper_get_pr without mode when you need the pull request summary and merge state, checks,
review submissions, and inline review threads in one comprehensive call. Set mode: "checks" for
lightweight CI polling that fetches only checks. If that mode initially finds no configured checks,
it makes up to three additional attempts at ten-second intervals before returning the informational
no-checks result; comprehensive reads report their first checks observation immediately. Both modes
accept either a Shipper issue with a currently linked pull request or a direct GitHub pull request
number. Supply optional repository_path to inspect a local checkout for only that call; omission
uses the active repository and a targeted call does not change it.
shipper_groom and shipper_answer_question are available on every server start. Grooming streams
worker questions through the MCP bridge so the orchestrator can submit each complete answer batch
and resume the worker. Every batch is one ordered set of ordinary authored questions: supply one
answer per carried stable ID in answers, using the IDs rather than question text. There are no
decision or provenance cards, veto controls, mixed or compact-only batches, and no batch-level
action to confirm unvetoed decisions. shipper_answer_question accepts exactly session_id and
answers; a submission carrying the removed confirm_unvetoed field, or any other unrecognized
top-level field, is rejected whole as an unsupported format, and invalid or incomplete calls leave
the identical pending batch retryable. A saved session that still holds the removed
compact-confirmation format is reported as discarded with a plain explanation that grooming must
restart for that issue; an ordinary-question-only saved session resumes normally.
An MCP-owned saved session remains available after the original MCP process
exits: a new client on the MCP surface resumes it normally, and shipper_answer_question
reconstructs its runner from the durable pending batch after a server restart.
Waiting between those calls does not consume agentTimeoutMinutes. When the resumed agent actually
times out terminally, the MCP call returns only after local failed history, terminal run status, and
ownership-safe lock release; any mirror projection warning remains repairable with
shipper issue reconcile --repair.
Desktop-owned, terminal-owned, and legacy unowned sessions refuse ordinary MCP grooming with only
issue identity, owner or unowned state, last-saved time, answered-round count, and pending-batch
presence. No question or answer content is returned. Use takeover: true only after confirming with
the human operator that MCP should permanently receive the saved answers; the same call transfers and
resumes the session. A live issue run makes takeover unavailable. shipper_advance and other
non-deliberate dispatch routes stand down neutrally at New and do not transfer ownership.
After shipper_adopt handles a pull request, read the backing S#<id> identity from its result and
pass that issue to shipper_set_priority. Priority is intentionally a second call; shipper_adopt
does not accept a priority field.
Use shipper_close_not_planned to withdraw an issue with the not-planned outcome only. In
store-only repositories it closes the local Shipper record without GitHub interaction. In
mirror-on repositories it closes the mapped GitHub issue as not planned, removes Shipper workflow
labels, and records local terminal state. Retrying an issue already closed as not planned is a
benign success; an active-run lock or a different closed outcome is an error. The tool does not
reset or clean up development artifacts.
Use shipper_recover when a failed issue still carries a recoverable packaged artifact. The tool
dispatches from the stored pinned local change or open linked pull request regardless of current
posture. It always stores shipper:pr-open, displayed as PR Open or Change Packaged, while
preserving the exact revision, source branch, artifact, workflow history, and completed review
rounds. A local source branch may advance beyond the packaged revision but must still contain it.
Missing, invalid, rewound, or divergent local state and non-open linked artifacts are ineligible and
point to Reset.
shipper_reset remains the destructive rollback path. Start with dry_run: true. A pinned-local
change warning includes the full revision and source branch and recommends shipper_recover. An
open-pull-request warning names what reset would close and explains that the stored association will
be cleared. MCP uses confirm_discard: true as its sole destructive acknowledgement, including for
an open pull request.
An issue note is an append-only annotation that can be withdrawn only by explicit retraction.
shipper_comment returns the new note ID, and every un-retracted note in shipper_get_issue exposes
the same ID in its event attribute. An optional author label supplements the note’s MCP origin
marker. shipper_retract_comment can withdraw a note from any author, but it cannot touch grooming
summaries, stage transitions, blocked comments, or other Shipper workflow comments.
Both note tools support store-only issues without a GitHub number. When mirroring is enabled, a
GitHub projection failure leaves the authoritative local note successful and repairable with
shipper issue reconcile --repair.
Confirm repository resolution by checking the client MCP logs for:
shipper mcp: repo dir = /absolute/path/to/target/repoIf the client does not expose MCP logs, keep SHIPPER_REPO_DIR explicit and call
shipper_status. It is the local-only orientation check and reports repository counts,
configuration, and mirror mode without GitHub. Call shipper_list_issues afterward only when you
need issue identities.
For expected tool visibility problems, see MCP Tool Loading Issues.
Startup failures
Section titled “Startup failures”The server starts with error-reporting tools when startup cannot complete. The tool output includes the exact initialization error; use that message as the source of truth. When repository identity cannot be established, the error identifies the resolved repository path and exactly one observed cause:
- Git is unavailable to the MCP process: install Git and make it available to that process.
- The selected path is not a valid inspectable Git repository: use a valid Git repository or repair
its accessibility or integrity. This includes a missing, unreadable, non-directory, or
non-repository
SHIPPER_REPO_DIRor startup working directory. - The repository has no commits: create an initial commit. This remains the correct classification even if a remote is configured.
After correcting the external condition, restart or reconnect the MCP client.
Settings or local preflight failure is separate: run shipper setup in the target repository and
repair the reported local configuration problem before restarting the MCP client. If committed
.shipper artifacts are required, run shipper setup --repo.
GitHub-dependent tools validate external access when invoked, not at server startup. If one of those
tools reports that gh is missing, unauthenticated, or cannot reach the repository, install or
authenticate GitHub CLI and retry that call. Local tools, including shipper_status, remain
available during the outage.