Operate with an agent
How an AI agent drives Farther Shore end-to-end via the CLI and MCP, authenticated by a maker token.
How an AI agent drives Farther Shore end-to-end via the CLI and MCP, authenticated by a maker token.
Farther Shore is built to be operated by a coding agent, not just a human at a
keyboard. The farthershore CLI is the canonical control surface: every action
an agent needs — create a product, add a plan, publish, mint a runtime token,
read usage — is a non-interactive command that emits machine-readable JSON. The
MCP server (farthershore-mcp) is a strict subset of that CLI, so an agent can
work over either and never lose a capability.
The one rule that makes this safe: CLI ⊇ MCP. Anything exposed as an MCP tool has a sibling CLI command by construction (a parity test enforces it), and some things are CLI-only on purpose. An agent that learns the CLI has the whole platform; an agent restricted to MCP has the lean, machine-shaped slice.
Everything an agent does is authenticated by a maker token (mk_...) — an
org-scoped credential you mint in the dashboard at /settings/tokens. It is the
only auth an agent needs; there is no browser step in the hot path.
# CI / agents: just export it. No login file, no prompt.
export FARTHERSHORE_TOKEN=mk_xxx
farthershore auth whoami --format json # confirm org, role, scopes
The maker token is exchanged for a short-lived CLI access token on the first
authenticated request. Pass --token mk_xxx per-command to override, or set
FARTHERSHORE_TOKEN once for the session. The CLI is fully non-interactive
whenever a token is present — auth login only prompts on a TTY with no token —
so the same commands run identically in a terminal, in CI, and inside an agent
loop.
Maker tokens are scoped (e.g. products:create, products:publish). Mint a
narrow token per agent; see the MCP page for the tool/scope map
and token management below.
In non-TTY contexts the CLI defaults to --format json and writes exactly one
AgentEnvelope to stdout — diagnostics go to stderr, so stdout is always
parseable:
{
"schema_version": 1,
"ok": true,
"op": "product.create",
"data": { "result": { "id": "prod_…", "name": "croncloud", "status": "DRAFT" } }
}
Failures use the same envelope with ok: false and a stable, bracketed error
code plus a retryable flag and a hint:
{
"schema_version": 1,
"ok": false,
"op": "product.publish",
"error": { "code": "STRIPE_NOT_CONNECTED", "status": 402, "retryable": false, "hint": "Connect Stripe in the dashboard before publishing." }
}
The MCP server returns the byte-identical envelope, so an agent parses one shape regardless of surface.
The CLI process exit code is branchable, so an agent can react without parsing text:
| Exit | Meaning | Agent action |
|---|---|---|
0 | Success | Continue. |
2 | Bad input (4XX validation) | Fix the arguments and retry. |
3 | Auth failure | Re-auth / check the maker token + scopes. |
4 | MANAGED_BY_CODE | Edit the product manifest and push, not the API. See operation classes. |
5 | Server error (5XX) | Retryable — back off and retry. |
Exit 4 is the one that distinguishes Farther Shore: the contractual product
definition is managed as code, so an out-of-band write to it is rejected and
the agent is told to change the repo instead.
The agent operates the platform almost entirely through the CLI plus the matching skills. The canonical lifecycle — modeled throughout these docs on the CronCloud product — is:
export FARTHERSHORE_TOKEN=mk_xxx
# 1. Create (provisions a managed GitHub repo + frontend starter)
farthershore product create \
--name croncloud \
--display-name "CronCloud" \
--origin https://api.example.com \
--repo-owner acme --repo-name croncloud \
--format json
# 2. Connect billing (browser-only; the CLI just reports status to poll)
farthershore connect stripe croncloud --format json
# 3. Add a plan
farthershore plan create croncloud \
--key starter --name "Starter" --recurring-fee-cents 2900 --format json
# 4. Go live
farthershore product publish croncloud --format json
The product itself — its plans, routes, meters, capabilities — is authored as a
decorated @Product class in product/product.config.ts and built locally with
farthershore build. That definition is the contract; the commands above
that touch it (plans) are CLI-only writes, while the imperative steps (publish,
tokens, usage) are also exposed over MCP. The next pages make that boundary
exact.
fs_* tools, how they project from the same
registry as the CLI, and the CLI⊇MCP parity guarantee.Token lifecycle is itself a set of operate-class commands:
farthershore token list --format json
farthershore token create --name "ci-bot" \
--scope products:update products:publish --format json
farthershore token revoke <tokenId> --yes --format json