Skip to content

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.

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 setup already completed. A committed local repository without a remote is supported. Use shipper setup --repo when the target needs committed .shipper/ artifacts. See shipper setup and 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.

@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:

Terminal window
git clone https://github.com/baremetallabs-ai/shipper.git
cd shipper
nvm install
nvm use
npm install
npm run build --workspace=packages/mcp

After the build, configure the MCP client to run the generated server entrypoint with Node:

Terminal window
node /absolute/path/to/shipper/packages/mcp/dist/index.js

packages/mcp/dist/index.js is build output. It is gitignored and is absent from a clean checkout until the build command creates it.

The MCP server chooses one target repository at startup:

  • If SHIPPER_REPO_DIR is 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_DIR is 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/repo

Use 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.

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 = 30
tool_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.

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 = 30
tool_timeout_sec = 86400

The 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.

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: node
args: ["/absolute/path/to/shipper/packages/mcp/dist/index.js"]
env:
SHIPPER_REPO_DIR: /absolute/path/to/target/repo

Keep 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.

Confirm the client reports the server as connected or active:

  • Claude Code: run claude mcp list or open /mcp and confirm shipper is connected.
  • Codex: run codex mcp list or open /mcp in the Codex TUI and confirm shipper is active.
  • Grok Build: run grok mcp list or open /mcps in the Grok TUI and confirm shipper is active.
  • OpenCode: inspect OpenCode’s MCP server list or logs and confirm shipper is 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/repo

If 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.

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_DIR or 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.