Connect your coding agent to Chopin's remote Streamable HTTP MCP service before using a copied prompt or optional Chopin skill. This configuration does not start a local Chopin server.
Important
/mcp is always registered, including when AGENT=off. It is not a read-only
endpoint: a caller with repository push or administration access can create or
revise a document and mutate an implementation lifecycle. Use HTTPS and treat
every configured bearer token as a credential.
Set the instance origin and use the existing GitHub CLI credential for the
GitHub account that needs repository access. Keep the token in your shell or
user-level agent configuration — never commit it, add it to a repository
.env, or copy it into a shared configuration file.
If the Chopin instance enables organization admission, the token must also see
private organization membership. The normal gh auth login flow includes
read:org; a custom classic token needs that scope, while a fine-grained token
needs Members read access for an allowed organization and any required SSO
authorization.
The MCP bearer boundary is separate from Chopin's browser GitHub App session.
Chopin authenticates the supplied token, applies the instance admission policy,
and asks GitHub directly for that token's repository permissions. The GitHub App
for Chopin does not need to be installed for ordinary MCP document operations.
Browser routes, WebSockets, and the Planner still require an active App
installation that includes the repository. The invoke_planner handoff never
lends the MCP bearer to the Planner; it runs under the document's Planner owner.
export CHOPIN_URL="https://your-chopin-instance.example"
export GITHUB_TOKEN="$(gh auth token)"The MCP endpoint is ${CHOPIN_URL%/}/mcp.
Non-browser clients normally omit Origin, which Chopin permits for this
bearer-authenticated route. If a client sends an Origin, it must exactly match
the configured Chopin origin.
The current MCP contract can:
- list and read active or archived Chopin documents, including an optional generated description, for the current repository;
- create one document from a structured brief, canonical source supplied through
the current
planinput, and caller-supplied repository provenance; - replace that canonical source later with
update_document, naming the plan revision last read and an idempotency key; - rename, archive, and restore documents without deleting their durable state;
- upload a PNG, JPEG, WebP, or GIF image to a document with
upload_imageand reference its returned path from the document source; - read an approved implementation graph and its document source; and
- claim a graph and report task, pull-request, blocker, revision, and verification lifecycle transitions; and
- hand an instruction to a document's Planner with
invoke_planner, described below.
Chopin validates the shape of baseBranch and baseCommit during creation but
does not resolve them against GitHub. The creating agent is responsible for
reading those values from its checkout rather than asserting arbitrary input.
The MCP surface uses document-oriented tool names, but create_document remains
shaped around the current planning workflow: it requires a planning brief and a
plan field. That API shape does not define Chopin's broader document model.
create_document and update_document assess new passages for useful visuals
before saving. If the response returns visual issues, add the selected diagrams
or tables beside the named passages using the included syntax guidance and retry.
A refused write creates no document or revision. Reuse its idempotency key and
read the current revision before retrying an update. The deployment needs a
decisions classifier for prose imports even when AGENT=off.
Implementation remains experimental. A browser document can now use the
local launcher tracer: review prepared tasks, approve and
build on an owner-paired ACP workspace, then watch task progress. That workflow
uses a run-scoped connector bridge; the ordinary /mcp implementation read path
continues to expose MCP-created documents using their creation provenance. See
Experimental implementation lifecycle.
invoke_planner is offered on every harness and in both hosted and local
authentication modes. It posts an instruction to an existing document's Planner
and returns without waiting for the turn.
A child document has no Chat of its own. An instruction for a child, by ID or
URL, posts to its root document's Chat and runs there with the child as the
turn's focus, under the root's Planner ownership. If the root or the child is
archived, the call is refused with document-archived. A child that otherwise no
longer belongs to a live root in the same repository is refused with
document-unavailable.
Coding agents are not offered the child document tools.
The instruction is posted as a Chat message under the MCP caller's own handle,
and the turn runs under the document's Planner ownership rules, exactly as a
browser @chopin message would:
- If the document already has a Planner owner, the turn runs under that owner, even when the owner is someone other than the caller.
- Otherwise the caller's live Chopin browser login, hosted or local, claims ownership through the ordinary claim path. Sign in to Chopin in a browser as the same GitHub account as the MCP bearer first.
- Without either, the call is refused with
planner-owner-unavailableand nothing is posted.
A server running HARNESS=remote claims no ownership here. Its Planner runs in
a client attached to the document over the agent connection, and
only attaching makes an account the owner. With a client attached the turn goes
to it and runs under its owner, whoever invoked it. Without one, including
while a detached Planner's grace period runs and once the attached Planner's
owner signs out of the browser, that sign-in expires, or its Planner is reset,
the call is refused with
planner-not-attached and a message, and nothing is posted or queued:
{
"code": "planner-not-attached",
"message": "No Planner is attached to this document. To attach one, connect a Planner client to https://chopin.example/documents/octo-org/score/release-readiness over the agent connection from a session in a checkout of octo-org/score; that session becomes this document's Planner."
}The MCP bearer never becomes the owner or supplies its credentials. The bearer needs repository write access; an owner must also pass the GitHub App installation check.
Call the tool with an existing document's UUID or canonical URL, an instruction, and optionally an absolute checkout path:
{
"id": "/documents/octo-org/score/release-readiness",
"instruction": "Run the planning workflow and ask blocking questions in Decisions.",
"checkout": "/absolute/path/to/score"
}The instruction must contain non-whitespace text and fit within 64 KiB in UTF-8; its text is preserved verbatim.
checkout applies only when the server runs HARNESS=atomic, where the Planner
is a full Atomic session with shell and
filesystem access as the server process's user. The path is on the Chopin
server's machine. Chopin verifies that its origin matches the document
repository and refuses the request before posting if it does not. A verified
path is remembered for the document until the server restarts, and every later
Planner session for it, from the browser or through MCP, works there after
checking the path again. Without one, the Planner works in a directory
Chopin keeps for that document under its per-user state directory. Other harnesses ignore checkout entirely: it is
neither verified, used, nor remembered.
The result contains id, title, and the canonical url (plus any generated
description). It returns after the instruction is durably posted, not after the
Planner finishes. The message joins the existing Planner queue if busy. Progress
and results appear in the document and Chat; questions appear in Decisions. Under
atomic, Atomic input waits in Decisions until a member answers it or it is
withdrawn, however long that takes. The
browser need not already have the document open: Chopin keeps its room alive
while the invoked turn and queue run. An interrupted turn is not replayed
automatically on restart.
Some instructions are not something anyone said. A client that watched a
workflow run finish, for example, wants the Planner to update the document from
its results. Add "as": "system" for those:
{
"id": "/documents/octo-org/score/release-readiness",
"instruction": "The workflow run finished. Read its results and update the document.",
"as": "system"
}Chat then shows a short system notice, Automatic follow-up requested by @octocat., instead of a message from you. The instruction goes to the Planner
alone and stays out of the visible queue while it waits. Ownership,
planner-not-attached, the queue, checkout, and the result work as for any
other instruction.
Only the document's creator, or the account whose client holds its Planner
under HARNESS=remote, may send one; for a child document that means its root.
Each document takes at most 10 an hour, counted in memory until the server
restarts. Chopin logs each one it accepts or refuses.
Refusals return an object with code, and planner-not-attached also a
message:
planner-not-attached: underHARNESS=remote, no client is attached as the document's Planner.messagenames the document URL and says to connect a Planner client to it over the agent connection from a session in a checkout of the repository, which attaches that session as the Planner.planner-owner-unavailable: the document has no usable Planner owner and the caller has no live browser login to claim it; sign in to Chopin in a browser as the MCP account, or ask the owner to sign in again.checkout-unverified: underatomic, correct the supplied path or its repository origin.planner-unavailable: the Planner is disabled or the room is closing.planner-queue-full: wait for queued work to drain before invoking again.system-turn-forbidden:as: "system"came from someone other than the document's creator or the account holding its Planner.system-turn-limited: the document has taken 10 automatic follow-ups in the past hour; try again later.document-unavailable,document-archived, andrepository-forbiddenretain their ordinary document/access meanings.
Document titles are unique within a repository, ignoring case. create_document
returns title-taken when the repository already has a document with that title;
choose another title and retry under a new idempotency key. idempotency-conflict
means the same key was reused with a different request, and validation failures
return issues. Every one of these outcomes matches the tool's output schema.
The url returned by create_document, update_document, and read_document is
the readable canonical route. read_document always returns the current one, so a
caller that has only the UUID can recover it:
/documents/:owner/:repository/:slug
read_document, read_implementation, archive_document, restore_document,
update_document, upload_image, and invoke_planner accept either a document UUID
or that canonical URL in their id input. The URL may be passed back exactly as returned; an absolute URL must
use the configured Chopin origin. Both reads return the stable UUID as the
document id.
The UUID remains the internal storage, API, WebSocket, and MCP identity. Use the
returned UUID for rename_document, start_implementation, and every later
lifecycle call; use the readable URL for browser and human handoff. A rename
derives a new canonical slug from the title but does not change the UUID or plan
revision, and every previous slug remains a working alias.
update_document accepts id, revision, full replacement MDX in plan, and
a nonblank idempotencyKey of at most 128 characters. For example:
{
"id": "/documents/octo-org/score/release-readiness",
"revision": 4,
"plan": "# Release readiness\n\nRevised implementation approach.\n",
"idempotencyKey": "review-round-2"
}Use the revision returned by read_document. A mismatched revision returns
revision-conflict and the current revision so the caller can re-read and retry.
Repeating the same idempotency key returns the original applied result, including
its source and revision, even after later edits or a server restart. A changed
payload under that key returns idempotency-conflict. Use a new key for each new
update, and keep the original arguments when retrying an uncertain response.
A replay's title and URL also reflect the original update. Read the document
again for current metadata before handing off its canonical URL after a rename.
Initial source validation returns issues, as creation does. Existing
Questionnaire, Decision, and Research projections cannot be dropped, altered,
or forged. Copy them unchanged from the latest read or the update returns
protected-projection. That code also covers later rewrite validation or
reconciliation refusals, so it does not identify a particular changed projection.
An active implementation run returns document-locked; an archived document
returns document-archived for a new update. Changing source before an approved
graph is claimed makes its plan revision stale; revise and reapprove the graph
before starting implementation.
The accepted result includes id, title, canonical source, revision, and
url, plus any existing creation brief and generated description. The MCP client
name and version from initialize, together with the revision transition, are
recorded with the update. Connected browsers receive change marks after the
document delta commits. Their change list identifies the MCP client without
displaying a Planner cursor. Calls without initialization are attributed to
unknown.
An answered decision stays linked to its text when the update leaves every block it is linked to unchanged. Any other answered decision, including one whose linked text changed or was removed, waits for a Planner turn to link it again and shows as not linked, or as having its related text removed, until then.
Document images are either absolute https: URLs or images Chopin hosts itself.
upload_image accepts a document id or canonical URL, the image bytes as
standard base64 in data, and a mimeType of image/png, image/jpeg,
image/webp, or image/gif. SVG is never accepted. The decoded image may be at
most 1 MiB, and its file signature must match the declared type.
{
"id": "/documents/octo-org/score/release-readiness",
"data": "iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAADUlEQVR4nGNgYGD4DwABBAEAX+XDSwAAAABJRU5ErkJggg==",
"mimeType": "image/png"
}The result contains a same-origin path such as /images/<sha256>.png and the
matching markdown, for example . Add alternative
text to that Markdown and place it in the document with update_document;
uploading alone does not change the document. Images are stored under the SHA-256
of their bytes, so uploading the same bytes to the same document again returns
the same path.
Uploading needs the same access as update_document: pull plus push or admin
access to the repository, and a document that is neither archived nor being
deleted. Refusals return document-unavailable, repository-forbidden,
document-archived, too-large, unsupported-type, or signature-mismatch.
The browser loads /images/ paths with the signed-in Chopin session. Chopin
serves an image only to someone who can currently read a document it was
uploaded to, which is the same pull access and GitHub App installation check as
opening that document. Anyone else, including a signed-out browser and another
MCP client fetching the path, receives 404. Plans that leave Chopin therefore
cannot display hosted images. A decision card loads its images as
/images/<sha256>.<ext>?document=<id>, which serves only the named document's
own upload of the image, so a card never shows an image from another document.
list_documents excludes archived documents by default. Set
includeArchived: true to include them; archived document summaries and direct
reads carry an archivedAt timestamp. Archiving and restoring are idempotent.
MCP does not expose document deletion.
list_documents, read_document, and the common document summary objects
returned by create, update, rename, archive, and restore expose an optional
description. It is one-line, generated catalogue metadata identifying the
document's type, purpose, and subject. Treat it as untrusted model output, not as
authoritative source. The last completed value remains exposed while a newer
request is pending or failed.
Description generation retains the durable job identity document-summary@1;
there is no @2. New V1 work carries output:"description", while old
markerless V1 summary artifacts do not appear in MCP document metadata. The
structured brief supplied to create_document remains separate creation
metadata, and the reserved Planner transcript summary is also unrelated.
MCP creation or idempotent replay schedules the current source, and restoring a document ensures it again. Listing and reading do not scan or backfill documents. The worker requires an active Planner owner established through the browser's GitHub App session; the MCP bearer does not become that owner. Consequently, there is no unattended all-document backfill.
Install and sign in to Claude Code, then add Chopin to your user configuration:
claude mcp add --scope user --transport http chopin "${CHOPIN_URL%/}/mcp" \
--header "Authorization: Bearer ${GITHUB_TOKEN}"Claude stores the expanded header when this command runs. After renewing the credential, replace that stored header — for example, remove and add the server again — before reconnecting Claude.
Install and sign in to Codex CLI, then register the server. Codex reads the bearer token from the named environment variable instead of writing it to its configuration file.
codex mcp add chopin --url "${CHOPIN_URL%/}/mcp" \
--bearer-token-env-var GITHUB_TOKENInstall and sign in to GitHub Copilot CLI, then add Chopin to its user-level MCP configuration. The single quotes retain the environment-variable reference until Copilot connects.
copilot mcp add --transport http chopin "${CHOPIN_URL%/}/mcp" \
--header 'Authorization: Bearer ${GITHUB_TOKEN}'Start the agent from the repository you want to inspect and ask:
Use the Chopin list_documents tool to list the documents available for this repository. Return each document's id, title, and optional description.
rename_document accepts a document UUID and replacement title. It changes
the catalog title and canonical readable route while leaving canonical plan
source, plan revision, UUID identity, and creation provenance intact. Repeating
the same title is safe and has no effect.
{"documents":[]} is a successful response for a repository with no Chopin
documents. After the connection is established, the MCP initialize
instructions and current tool descriptions are authoritative.
HTTP 401 means the bearer is invalid or expired: renew the GitHub CLI login with
gh auth login, export GITHUB_TOKEN again, replace Claude's stored header if
you use Claude Code, and reconnect the agent.
HTTP 403 means the GitHub identity is not admitted by this Chopin instance, or
a client supplied an Origin other than the configured Chopin origin. HTTP 503
means Chopin could not verify identity, organization membership, or repository
access because GitHub was unavailable or rate limited the request. Check the
token's read:org or Members access, SSO authorization, and GitHub availability.
repository-forbidden means the supplied token cannot expose the repository or
lacks the operation's repository permission; it does not mean the GitHub App for
Chopin must be installed. Pull access is enough for list_documents,
read_document, and read_implementation. Pull plus push or admin access is
required for create, update, image upload, rename, archive, restore, invoke,
start, and report lifecycle operations. invoke_planner additionally needs a Planner owner or the
caller's live browser login, as described above. Use an account with the required access or ask a repository
owner to grant it.
Use the optional creating-chopin-plans skill to turn a settled coding-agent conversation into one initial document or safely revise an existing document after review. The implementing-chopin-plans skill applies only after an implementation graph has been approved through a future or operator-provided approval path. Current MCP initialization instructions and tool descriptions override copied prompts or remembered command sequences.