mcp-context-card 1.7.0 → 1.8.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/card-gen.js CHANGED
@@ -1,7 +1,10 @@
1
1
  /**
2
2
  * card-gen - write docs/card.html from the three sources, so the card is
3
3
  * browsable on GitHub and screenshot-able for the README. Same renderer as
4
- * GET /card and the render_context_card tool.
4
+ * GET /card, the CLI, and render_context_card for a client without MCP Apps:
5
+ * the plain card, without the MCP Apps helper. The ui:// resource is
6
+ * rendered at read time and is not one of these files. A plain card over
7
+ * 64 KB fails here, which fails card:check.
5
8
  *
6
9
  * Also writes two theme-pinned siblings (docs/card-light.html,
7
10
  * docs/card-dark.html) — docs/card.html stays "auto" (follows the viewer's
@@ -15,13 +18,19 @@
15
18
  import { writeFileSync } from "node:fs";
16
19
  import { dirname, join } from "node:path";
17
20
  import { fileURLToPath, pathToFileURL } from "node:url";
18
- import { renderCard } from "./render-card.js";
21
+ import { PLAIN_CARD_LIMIT_BYTES, plainCardExceedsLimit, renderCard } from "./render-card.js";
22
+ function writePlain(path, html) {
23
+ if (plainCardExceedsLimit(html)) {
24
+ throw new Error(`card:check: ${path} is ${Buffer.byteLength(html)} bytes; a plain card must not exceed ${PLAIN_CARD_LIMIT_BYTES} bytes (64 KB)`);
25
+ }
26
+ writeFileSync(path, html);
27
+ }
19
28
  if (process.argv[1] && import.meta.url === pathToFileURL(process.argv[1]).href) {
20
29
  const root = join(dirname(fileURLToPath(import.meta.url)), "..");
21
30
  const auto = renderCard(root);
22
- writeFileSync(join(root, "docs/card.html"), auto);
23
- writeFileSync(join(root, "docs/index.html"), auto);
24
- writeFileSync(join(root, "docs/card-light.html"), renderCard(root, { theme: "light" }));
25
- writeFileSync(join(root, "docs/card-dark.html"), renderCard(root, { theme: "dark" }));
31
+ writePlain(join(root, "docs/card.html"), auto);
32
+ writePlain(join(root, "docs/index.html"), auto);
33
+ writePlain(join(root, "docs/card-light.html"), renderCard(root, { theme: "light" }));
34
+ writePlain(join(root, "docs/card-dark.html"), renderCard(root, { theme: "dark" }));
26
35
  console.log("wrote docs/card.html + docs/index.html (auto) + card-light.html + card-dark.html — the context card, rendered from AGENTS.md / project.fafm / .well-known/fafa");
27
36
  }
@@ -1,7 +1,7 @@
1
1
  /** Server identity constants, in their own module so any file can import
2
2
  * them without pulling in the whole server. */
3
3
  export declare const NAME = "mcp-context-card";
4
- export declare const VERSION = "1.7.0";
4
+ export declare const VERSION = "1.8.0";
5
5
  export declare const SERVER_CARD_URI = "mcp-context-card://server-card";
6
6
  /** The server's registry identity: reverse-DNS, the same as server.json `name`.
7
7
  * It is also `serverInfo.name`, so a Server Card never contradicts the live
@@ -32,9 +32,25 @@ export declare const ALLOWED_HOSTS_ENV = "MCP_CONTEXT_CARD_ALLOWED_HOSTS";
32
32
  /** Browser origins allowed to call the HTTP server (comma-separated). */
33
33
  export declare const ALLOWED_ORIGINS_ENV = "MCP_CONTEXT_CARD_ALLOWED_ORIGINS";
34
34
  export declare const publishMemoryFromEnv: (env?: NodeJS.ProcessEnv) => boolean;
35
+ /** What the ui:// card carries for an MCP Apps host. `helper` (the default):
36
+ * the official MCP Apps helper, so the card reports its size (~700 KB).
37
+ * `plain`: the plain card (~30 KB), no MCP Apps messages; the host's default
38
+ * frame. Only the ui:// resource changes: tool text, save_context_card,
39
+ * GET /card and the CLI are always the plain card. */
40
+ export declare const CARD_APP_ENV = "MCP_CONTEXT_CARD_APP";
41
+ export type CardApp = "helper" | "plain";
42
+ /** A setting value as a CardApp: trimmed, any case. Anything else: undefined. */
43
+ export declare function toCardApp(value: unknown): CardApp | undefined;
44
+ /** Unset or empty = `helper`. `plain`/`helper` in any case. Any other value:
45
+ * one stderr line per distinct value (a server builds an instance per HTTP
46
+ * request; warn once), then `helper`. */
47
+ export declare function cardAppFromEnv(env?: NodeJS.ProcessEnv, warn?: (line: string) => void): CardApp;
35
48
  /** MCP Apps (io.modelcontextprotocol/ui): the card as an inline UI resource.
36
49
  * A host that supports MCP Apps fetches this resource and renders it in a
37
50
  * sandboxed iframe next to the conversation. */
38
51
  export declare const CARD_UI_URI = "ui://mcp-context-card/card.html";
39
52
  export declare const MCP_APP_MIME = "text/html;profile=mcp-app";
40
53
  export declare const UI_EXTENSION = "io.modelcontextprotocol/ui";
54
+ /** Protocol revisions served beside the SDK's 2025-era list (SUPPORTED_PROTOCOL_VERSIONS):
55
+ * createMcpHandler / serveStdio answer 2026-07-28 too. The SDK exports no constant for it. */
56
+ export declare const MODERN_PROTOCOL_VERSIONS: readonly ["2026-07-28"];
package/dist/constants.js CHANGED
@@ -1,7 +1,7 @@
1
1
  /** Server identity constants, in their own module so any file can import
2
2
  * them without pulling in the whole server. */
3
3
  export const NAME = "mcp-context-card";
4
- export const VERSION = "1.7.0";
4
+ export const VERSION = "1.8.0";
5
5
  export const SERVER_CARD_URI = "mcp-context-card://server-card";
6
6
  /** The server's registry identity: reverse-DNS, the same as server.json `name`.
7
7
  * It is also `serverInfo.name`, so a Server Card never contradicts the live
@@ -32,9 +32,43 @@ export const ALLOWED_HOSTS_ENV = "MCP_CONTEXT_CARD_ALLOWED_HOSTS";
32
32
  /** Browser origins allowed to call the HTTP server (comma-separated). */
33
33
  export const ALLOWED_ORIGINS_ENV = "MCP_CONTEXT_CARD_ALLOWED_ORIGINS";
34
34
  export const publishMemoryFromEnv = (env = process.env) => env[PUBLISH_MEMORY_ENV] === "1";
35
+ /** What the ui:// card carries for an MCP Apps host. `helper` (the default):
36
+ * the official MCP Apps helper, so the card reports its size (~700 KB).
37
+ * `plain`: the plain card (~30 KB), no MCP Apps messages; the host's default
38
+ * frame. Only the ui:// resource changes: tool text, save_context_card,
39
+ * GET /card and the CLI are always the plain card. */
40
+ export const CARD_APP_ENV = "MCP_CONTEXT_CARD_APP";
41
+ const CARD_APP_VALUES = ["helper", "plain"];
42
+ const warnedCardApp = new Set();
43
+ /** A setting value as a CardApp: trimmed, any case. Anything else: undefined. */
44
+ export function toCardApp(value) {
45
+ if (typeof value !== "string")
46
+ return undefined;
47
+ const v = value.trim().toLowerCase();
48
+ return CARD_APP_VALUES.includes(v) ? v : undefined;
49
+ }
50
+ /** Unset or empty = `helper`. `plain`/`helper` in any case. Any other value:
51
+ * one stderr line per distinct value (a server builds an instance per HTTP
52
+ * request; warn once), then `helper`. */
53
+ export function cardAppFromEnv(env = process.env, warn = (line) => console.error(line)) {
54
+ const raw = env[CARD_APP_ENV]?.trim();
55
+ if (!raw)
56
+ return "helper";
57
+ const known = toCardApp(raw);
58
+ if (known)
59
+ return known;
60
+ if (!warnedCardApp.has(raw)) {
61
+ warnedCardApp.add(raw);
62
+ warn(`${NAME} · ${CARD_APP_ENV}="${raw}" is not one of ${CARD_APP_VALUES.join(", ")}; using helper`);
63
+ }
64
+ return "helper";
65
+ }
35
66
  /** MCP Apps (io.modelcontextprotocol/ui): the card as an inline UI resource.
36
67
  * A host that supports MCP Apps fetches this resource and renders it in a
37
68
  * sandboxed iframe next to the conversation. */
38
69
  export const CARD_UI_URI = "ui://mcp-context-card/card.html";
39
70
  export const MCP_APP_MIME = "text/html;profile=mcp-app";
40
71
  export const UI_EXTENSION = "io.modelcontextprotocol/ui";
72
+ /** Protocol revisions served beside the SDK's 2025-era list (SUPPORTED_PROTOCOL_VERSIONS):
73
+ * createMcpHandler / serveStdio answer 2026-07-28 too. The SDK exports no constant for it. */
74
+ export const MODERN_PROTOCOL_VERSIONS = ["2026-07-28"];
@@ -1,5 +1,7 @@
1
1
  import type { AgentIdentity } from "./faf/types.js";
2
- export type Theme = "light" | "dark" | "auto";
2
+ import { type BusinessCard, type Theme } from "agent-business-card";
3
+ export { cardInitials, renderBusinessCard, safeAccent } from "agent-business-card";
4
+ export type { BusinessCard, RenderOptions, Theme } from "agent-business-card";
3
5
  export interface CardOptions {
4
6
  theme?: Theme;
5
7
  /**
@@ -23,59 +25,28 @@ export interface CardOptions {
23
25
  }
24
26
  /** AAIF brand orange (aaif.io): this project's own card colour, declared in its `.fafa`. */
25
27
  export declare const AAIF_ACCENT = "#FF702D";
26
- /** A valid hex colour, or undefined. Nothing else ever reaches the stylesheet. */
27
- export declare function safeAccent(a?: string): string | undefined;
28
28
  /** What the front calls this thing, from where it runs: "MCP server", "A2A agent", or both. */
29
29
  export declare function cardKind(id: AgentIdentity | null): string[];
30
30
  /** The front's title line: what it is, then its version. Empty when nothing is known. */
31
31
  export declare function cardTitle(id: AgentIdentity | null): string;
32
- /**
33
- * The front's logo: the first letter of the name's first meaningful word
34
- * (generic words like "mcp", "server", "sdk" skipped), plus a second letter
35
- * only when it's obvious: a known name (github → GH, typescript → TS) or a
36
- * word written with two capitals (GitHub, TypeScript). Never more than two.
37
- */
38
- export declare function cardInitials(name: string): string;
39
32
  /** The front's one-liner: the first sentence of the description. */
40
33
  export declare function cardOneLiner(id: AgentIdentity | null, max?: number): string;
41
34
  /**
42
- * A business card, independent of where its facts came from: everything the
43
- * renderer draws. `readCard` builds one from a project's files; another reader
44
- * (an A2A Agent Card, an MCP Server Card, a person's card) can build one too,
45
- * and `renderBusinessCard` draws any of them the same way.
35
+ * A plain card (tool text, the saved file, GET /card, the CLI, docs/) must
36
+ * not exceed this. The ui:// resource is separate and is not checked here.
46
37
  */
47
- export interface BusinessCard {
48
- name: string;
49
- /** What it is (and its version): "MCP server · v1.5.0", or a person's role. */
50
- title?: string;
51
- oneLiner?: string;
52
- /** Shown bottom-left on the front, e.g. the publisher domain. */
53
- domain?: string;
54
- /** Footer chips; `accent` highlights one (e.g. the status). Plain text. */
55
- chips: {
56
- text: string;
57
- accent?: boolean;
58
- }[];
59
- /** The back's tabs, in order. `key` is [a-z0-9-]; `html` is already-safe markup. */
60
- tabs: {
61
- key: string;
62
- label: string;
63
- heading: string;
64
- html: string;
65
- }[];
66
- /** The (i) panel, as already-safe markup. */
67
- about: string;
68
- /** The owner's colour, a hex. None = ink (black or white). */
69
- accent?: string;
70
- }
71
- /** How to draw a card: the owner's colour and accent, the view, and the flat (print) layout. */
72
- export type RenderOptions = Pick<CardOptions, "theme" | "accent" | "layout" | "expanded">;
73
- /** The project's card: read its files, then draw. */
38
+ export declare const PLAIN_CARD_LIMIT_BYTES: number;
39
+ /** True when a plain card exceeds 64 KB. card:check fails on that. */
40
+ export declare function plainCardExceedsLimit(html: string): boolean;
41
+ /** The project's card: read its files and draw. No helper, no inline view. */
74
42
  export declare function renderCard(root: string, opts?: CardOptions): string;
43
+ /**
44
+ * ui://mcp-context-card/card.html — the same card, plus the hidden inline
45
+ * view and the bundled MCP Apps helper. Nothing else calls this.
46
+ */
47
+ export declare function renderAppsCard(root: string, opts?: CardOptions): string;
75
48
  /** Read a project's AGENTS.md, memory and identity into a business card. */
76
49
  export declare function readCard(root: string, opts?: Pick<CardOptions, "expanded" | "memory">): BusinessCard;
77
- /** Draw any business card as one self-contained HTML page. */
78
- export declare function renderBusinessCard(card: BusinessCard, opts?: RenderOptions): string;
79
50
  /** tl;dr: the first few facts, each cut to about a line. `full`: every fact, whole. */
80
51
  export type Detail = "tldr" | "full";
81
52
  /**