import type { FafData } from '../core/types.js'; /** * Build an MCP Server Card (SEP-2127) from a .faf. * * The card is a published discovery manifest. By design it carries the FAF * context-block in `_meta["one.faf/context"]` — so every Server Card produced * through FAF ships FAF context by default. This emitter is the SINGLE SOURCE of * the block — faf-server-card-ref and `.fafa` provenance compose it (never * hand-roll), so every surface is byte-identical by construction: one context, * one source, every door. * * Honest-first: no score is baked (it would go stale on disk); the block points * to the .faf and asserts the score is deterministic. The card omits `remotes` * unless a deployment URL is supplied — it must not claim an endpoint it lacks. */ export interface ServerCardOptions { /** Pointer to the .faf context (default: ./project.faf). Pass an absolute URL * for a remote/served card (e.g. faf-server-card-ref at context.faf.one). */ fafPointer?: string; /** Optional live endpoint; adds a streamable-http remote when set. */ remoteUrl?: string; /** Optional "verify the score here" URL — makes verify-don't-trust actionable * (faf-server-card-ref uses https://faf.one). Omitted from the block if unset. */ scoreEndpoint?: string; /** Override timestamp (tests); otherwise .faf `generated`, else now. */ now?: string; } /** * The canonical FAF context-block — the value of `_meta["one.faf/context"]`, * identical across every surface (Server Card, registry `server.json`, `.fafa`): * one context, every door. Honest-first: no score baked (it would go stale on * disk); it points to the .faf and asserts the score is deterministic. */ export declare function fafContextBlock(data: FafData, opts?: ServerCardOptions): Record; /** Build the Server Card object from .faf data. */ export declare function buildServerCard(data: FafData, opts?: ServerCardOptions): Record; export declare const REGISTRY_PUBLISHER_KEY = "io.modelcontextprotocol.registry/publisher-provided"; /** * Build the `_meta` for an MCP Registry `server.json`. * * The SAME canonical context-block as the Server Card, but nested under * `io.modelcontextprotocol.registry/publisher-provided` — the ONLY `_meta` key * the official registry preserves on publish. Top-level keys (the way the card * carries `one.faf/context`) are silently dropped by the registry. Throws if the * block exceeds the registry's 4KB cap. Merge the result into an existing * `server.json` `_meta`; don't regenerate the manifest (packages/mcpb are tuned). */ export declare function registryMeta(data: FafData, opts?: ServerCardOptions): Record; /** The canonical reverse-DNS registry name, e.g. `one.faf/claude-faf-mcp`. * * HOMEPAGE REQUIRED: the namespace is derived from `project.homepage`'s host * (faf.one -> one.faf). With no homepage/website/url the namespace falls back * to `local/`. This can't silently ship — the migration is guarded * (`rewrite-server-json.ts` refuses any name that isn't `one.faf/*`) — but set * `homepage: https://faf.one` in the .faf to get the correct `one.faf/`. */ export declare function registryName(data: FafData): string; /** The display title for a registry `server.json` — the human-readable card name * (e.g. "Claude FAF"), sourced from `project.title` in the .faf. This is the * SINGLE SOURCE of the title across the fleet: JS emitters import it, and the * `faf server-card` CLI uses it so Python/Rust repos compose the identical * value (compose-not-fork). Distinct from `registryName` (the reverse-DNS id). * Returns undefined when unset or >100 chars (the registry cap) so the field is * omitted rather than shipped invalid — GitHub's registry then derives a name * from the namespace, so set `project.title` to control the display. */ export declare function registryTitle(data: FafData): string | undefined; /** True when `bytes` are a Server Card faf wrote: JSON carrying the FAF * context-block at `_meta["one.faf/context"]`, as every card faf has * written does. */ export declare function hasServerCardMark(bytes: Uint8Array): boolean; /** True when `bytes` are a registry `server.json` carrying faf's identity: * `_meta[REGISTRY_PUBLISHER_KEY]["one.faf/context"]`. */ export declare function hasRegistryMark(bytes: Uint8Array): boolean; /** Options for the card writers ({@link writeServerCard}, `faf cards`). */ export interface CardWriteOptions { /** Replace a card faf cannot prove it wrote — no faf mark, edited since * faf wrote it, or from before 7.13 — the explicit overwrite (`--force`). * Default: such a file is refused and left as it is. */ force?: boolean; } /** Write the Server Card to a `server-card` file. Returns the path. * Per experimental-ext-server-card#22 the reserved location is * `/server-card` (no longer `.well-known`); serve the * emitted file there as `application/mcp-server-card+json`. * * The card carries faf's render hash at `_meta["one.faf/render"]` (the hash * of the card without that key; the Server Card schema leaves `_meta` open * for namespaced keys). A `server-card` already there is replaced only when * it is byte for byte what faf last wrote (its hash still fits); a card edited * since, a hand-written card, or a card from before 7.13 that is not exactly * faf's render of `data` is refused (SafePathError `not-owned`) and left byte * for byte, unless `force`. The write is atomic and never goes through a link * that leaves `dir` or dangles. */ export declare function writeServerCard(dir: string, data: FafData, opts?: ServerCardOptions, write?: CardWriteOptions): string; /** The identity faf owns in a registry `server.json`. */ export interface ServerJsonIdentity { /** The reverse-DNS registry name ({@link registryName}). */ name: string; /** The display title ({@link registryTitle}); when undefined the file's own title is kept. */ title?: string; /** A version to set (`--set-version`); when undefined the file's own is kept. */ version?: string; /** The `_meta` faf writes ({@link registryMeta}). */ meta: Record; } /** * Put faf's identity into the text of a registry `server.json`, changing * nothing else: the `name` value, the `title` (only when faf has one — the * file's own title is kept otherwise), a `version` asked for, and the keys of * faf's context-block under `_meta[REGISTRY_PUBLISHER_KEY]["one.faf/context"]`. * Each is a text edit of that one value, or the key added when missing; no * field is deleted, and every other byte — key order, a 20-digit number, an * array on one line, spacing, CRLF — stays as it was. Throws a JsonEditError, * changing nothing, when the text cannot be edited that way (not valid JSON, * not an object, a key repeated on the way, a `_meta` that is not an object). */ export declare function patchServerJson(text: string, identity: ServerJsonIdentity): { text: string; changed: boolean; }; /** @deprecated Use {@link buildServerCard}. Removed in the next major. */ export declare const generateServerCard: typeof buildServerCard;