/** * The account-tied toolset — fourteen tools, identical on every transport. * * `deployments_upload` is not here, and the split is exactly the product's * own shape rather than a convenience: * * - **Upload is the anonymous door.** It is the one operation that works * with no account, and it is the one whose INPUT differs by transport — * a filesystem path over stdio, inline bytes over HTTP, because a Worker * has no filesystem. It also carries the Apps-SDK widget hosted-side. * So it is authored per transport, in each `server.ts`. * - **Everything else needs an identity**, and once a transport has one, * nothing about these fourteen depends on how the bytes arrived. Same * names, same schemas, same prose, same 1:1 SDK calls. * * That is why they live in the shared package: when the hosted transport * gains OAuth it registers this function and has the complete toolset, rather * than someone copying fourteen definitions into a second repo — which is the * moment the two surfaces would begin to drift. The cost of doing it after * the copy is a de-duplication under deadline; the cost of doing it before is * this file. * * **The catalogue is static; identity decides what SUCCEEDS.** These are * registered whether or not a credential is present — an anonymous caller * sees them and gets a typed authentication error naming how to authenticate * on *this* transport (the hint is `createCall`'s one per-transport argument). * A tool list that changes shape under the caller would be a second, dynamic * contract for an agent to track, and MCP clients cache the catalogue. * * **Every tool carries a `title`, and it is a gate rather than a nicety.** The * Claude connectors directory refuses submission for a tool that lacks one, so * a titleless tool is not a shabby tool — it is an unlistable product. The * style is short Title Case verb phrases naming what the USER gets ("List * Deployments", "Connect Custom Domain"); the name obeys `resource_action` for * the agent, the title reads as English for the human, and the description * carries every precision neither can. Both catalogue pins assert a title on * every tool, so the next one cannot be added without one. */ import type { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js'; import type Ship from '@shipstatic/ship'; import type { CallFn } from './call.js'; /** * The fourteen, by name, in registration order. * * Exported so a second transport can state its expected catalogue as * `[UPLOAD_TOOL_NAME, ...ACCOUNT_TOOL_NAMES]` instead of listing fifteen * strings it would then have to keep in agreement with this file — the hosted * parity fence is the consumer, and "fifteen" is otherwise a number two repos * count separately. * * **Deliberately a list beside the registrations rather than a table they are * generated from.** A `Record` would make the pairing * structural, and it would cost the zod→handler inference every one of the * fourteen one-liners below relies on: `({ deployment }) => …` is typed today * from the `inputSchema` literal in the same call, and a loop over a * heterogeneous table cannot correlate the two. The same guarantee costs * nothing as a set comparison, and `tests/server.test.ts` makes it — through a * real `tools/list`, so a registration without a name, a name without a * registration, and a typo in either all turn it red. */ export declare const ACCOUNT_TOOL_NAMES: readonly ["deployments_list", "deployments_get", "deployments_set", "deployments_delete", "domains_set", "domains_list", "domains_get", "domains_records", "domains_dns", "domains_share", "domains_validate", "domains_verify", "domains_delete", "whoami"]; export declare function registerAccountTools(server: McpServer, ship: Ship, call: CallFn): void;