MCP server
The farthershore-mcp tools, how they project from the same operation registry as the CLI, and the CLI ⊇ MCP parity guarantee.
The farthershore-mcp tools, how they project from the same operation registry as the CLI, and the CLI ⊇ MCP parity guarantee.
farthershore-mcp is an MCP stdio server that exposes the agent-writable slice
of the platform as fs_* tools. It ships inside @farthershore/cli, so no
separate install is needed:
FARTHERSHORE_TOKEN=mk_xxx npx -p @farthershore/cli farthershore-mcp
Point your agent's MCP client at that command. Auth is the same
maker token the CLI uses, passed via
FARTHERSHORE_TOKEN. Every tool returns the same AgentEnvelope the CLI
emits, so an agent parses one shape across both surfaces.
{ "schema_version": 1, "ok": true, "op": "product.publish", "data": { … } }
The CLI and MCP are not two codebases. Both project from a single list of
OperationDefs (apps/cli/src/operations/registry.ts). Each operation carries a
shared core (opKey, operationClass, scope, sideEffect) plus a per-surface
projection — a cli block and an optional mcp block:
export interface OperationDef {
opKey: string;
operationClass: OperationClass;
scope: string[];
sideEffect: ToolSideEffect; // "read" | "write"
cli: CliProjection; // every op has one — the CLI is the superset
mcp: McpProjection | null; // null = CLI-only (e.g. contract-class writes)
}
ALL_TOOLS is derived (OPERATIONS.filter(o => o.mcp).map(toMcpTool)), and the
parity map MCP_TOOL_TO_CLI_COMMAND is derived too. An "MCP tool with no CLI
command" is therefore unrepresentable, and the parity is enforced by
apps/cli/src/operations/mcp-cli-parity.test.ts.
The surfaces diverge by design: the CLI is the rich human/agent tool (env-name resolution, more flags, friendly errors); the MCP is the lean machine surface (raw ids, fewer fields). Same capability, different ergonomics.
These are the fs_* tools the registry projects today. Every one is a
read or an operate/dual write — never a contract write, per the
operation-class invariant.
| Tool | Class | Sibling CLI command |
|---|---|---|
fs_product_list | operate | product list |
fs_product_status | operate | product status |
fs_product_publish | dual | product publish |
fs_brand_update | operate | product update |
fs_env_list | dual | env list |
fs_env_create | dual | env create |
fs_plan_list | contract* | plan list |
fs_plan_migrate | operate | plan migrate |
fs_frontend_status | operate | frontend status |
fs_frontend_deploy | operate | frontend deploy |
fs_frontend_rollback | operate | frontend rollback |
fs_backend_list | operate | backend list |
fs_backend_create | operate | backend create |
fs_backend_delete | operate | backend delete |
fs_runtime_token_list | operate | backend tokens list |
fs_runtime_token_mint | operate | backend tokens create |
fs_runtime_token_rotate | operate | backend tokens rotate |
fs_runtime_token_revoke | operate | backend tokens revoke |
fs_persona_bootstrap | operate | persona bootstrap |
fs_persona_list | operate | persona list |
fs_persona_revoke | operate | persona revoke |
fs_usage_read | operate | usage summary |
fs_maker_token_list | operate | token list |
*fs_plan_list is a contract read — reads are always allowed. There is no
fs_plan_create/update/delete tool because those are contract writes,
managed as code. The CLI keeps plan create (CLI-only) for the DRAFT
seed-window; on a published product it returns MANAGED_BY_CODE.
CLI ⊇ MCP means some operations have mcp: null. They fall into three buckets:
contract-class writes — plan create/update/delete, and every other
manifest-owned change. The correct path is to edit product/product.config.ts
and push.product show (the full product
read, including repo-linked fields) has no fs_product_show; over MCP an agent
uses fs_product_list and fs_product_status instead.product create (it provisions a
GitHub repo and the frontend/ starter), init, and build (which executes
the decorated @Product class locally). These run in the agent's shell, not
over a remote tool call.If your agent only has MCP, route those through the CLI sibling listed above — that is exactly what the parity map guarantees exists.
fs_product_publish (a dual write — an agent may publish its own product):
{
"name": "fs_product_publish",
"arguments": { "productId": "prod_abc123" }
}
fs_runtime_token_mint is flagged returnsOneTimeSecret — the server skips its
usual redaction so the agent receives the plaintext fsrt_ token once (deploy it
as FS_RUNTIME_TOKEN):
{ "name": "fs_runtime_token_mint", "arguments": { "productId": "prod_abc123", "backendId": "be_…" } }
The MCP surface is the right fit for a hosted agent with no shell. But the design
intent is that agents primarily drive the CLI plus skills — it is the
superset, it has friendlier errors and env-name resolution, and it is the only
way to run the local build that turns your decorated @Product class into a
manifest. Use MCP for the operate/dual calls; use the CLI for the whole
lifecycle, including the contract edits MCP intentionally withholds. The
end-to-end walkthrough shows the full run.