mcp-context-card 1.0.1 → 1.1.1

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/.well-known/fafa CHANGED
@@ -9,7 +9,7 @@ agent:
9
9
  name: "mcp-context-card"
10
10
  displayName: "mcp-context-card"
11
11
  vendor: "io.github.Wolfe-Jam"
12
- version: "1.0.1"
12
+ version: "1.1.1"
13
13
  description: >-
14
14
  The essential MCP components for a project's context (AGENTS.md),
15
15
  cross-session memory, and identity — a base MCP on its own, or a
package/AGENTS.md CHANGED
@@ -15,7 +15,7 @@ connection.
15
15
  npm ci
16
16
  ```
17
17
 
18
- Node 22 or newer. No other system dependencies.
18
+ Node 20 or newer. No other system dependencies.
19
19
 
20
20
  ## Build
21
21
 
package/CHANGELOG.md CHANGED
@@ -2,6 +2,55 @@
2
2
 
3
3
  All notable changes to this project. Adheres to [Semantic Versioning](https://semver.org).
4
4
 
5
+ ## 1.1.1
6
+
7
+ Every tool now says what it is and what it does to your project.
8
+
9
+ Each of the nine tools carries a human-readable `title` and MCP tool
10
+ annotations, so a host can label it properly and decide whether to ask
11
+ before running it:
12
+
13
+ - **Read-only (7):** `read_agents_md`, `list_agents_md_sections`,
14
+ `author_agents_md` (returns a draft, writes nothing), `recall`, `whoami`,
15
+ `list_context_sources`, `render_context_card`.
16
+ - **Writes the memory file (2):** `remember` and `forget` are marked
17
+ `destructiveHint: true`. `remember` replaces a fact when an id is reused;
18
+ `forget` removes one.
19
+ - All nine are `idempotentHint: true` (repeating a call changes nothing more)
20
+ and `openWorldHint: false` (they only touch the local project).
21
+
22
+ A new test checks every tool's title and hints against what it actually does,
23
+ so a tool added later can't ship without them. 106 tests, all green on
24
+ Linux, macOS, and Windows.
25
+
26
+ No API change to the nine tools: same names, same inputs, same behaviour.
27
+
28
+ ## 1.1.0
29
+
30
+ The card scans in one screen — AGENTS.md sections collapse by default.
31
+
32
+ Every AGENTS.md section is now its own `<details>`, closed on load: the card
33
+ opens as identity → the section list → memory count → discovery, one screen,
34
+ scannable. Click a section to read it; the section index stays sticky at the
35
+ top so it's always one click away, not a scroll back up.
36
+
37
+ - **Expand all / Collapse all** — a control in the sticky nav, from one
38
+ ~16-line inline script (no external resources; the card is still one
39
+ self-contained file). It's a progressive enhancement: the button ships
40
+ `hidden` and the script reveals it, so with JavaScript off every section
41
+ still opens and closes on its own.
42
+ - **`--expanded` / `?expand=all` / `expanded: true`** — the full-page render,
43
+ for a screenshot or a PR. Available on the CLI (`npx mcp-context-card card
44
+ --expanded`), the HTTP transport (`GET /card?expand=all`), and the
45
+ `render_context_card` tool. This path renders `<details open>` server-side —
46
+ no script involved.
47
+ - **A section index link opens its section** — `#section` in the URL, or a
48
+ click in the nav.
49
+ - **Print / save-as-PDF** opens every section first, then restores.
50
+
51
+ No API change to the nine tools. `render_context_card` gains an optional
52
+ `expanded` boolean; everything else is unchanged.
53
+
5
54
  ## 1.0.1
6
55
 
7
56
  `npx mcp-context-card` now runs — it silently no-op'd when launched through
package/README.md CHANGED
@@ -70,14 +70,21 @@ file access, no shell, no search.
70
70
 
71
71
  The screenshot at the top of this page is exactly this — the same three
72
72
  sources rendered as one self‑contained HTML page: identity, `AGENTS.md`,
73
- memory, and how a machine fetches it. The view for people: screenshot it,
74
- drop it in a PR, put it on a status page.
73
+ memory, and how a machine fetches it. The view for people: read it, screenshot
74
+ it, drop it in a PR, put it on a status page.
75
+
76
+ `AGENTS.md` sections are collapsed by default, so the card scans in one screen;
77
+ a sticky index jumps to any section, **Expand all** opens everything. Sections
78
+ toggle natively — the one small inline script only adds the bulk button and the
79
+ print handler. `--expanded` / `?expand=all` renders it fully open, script-free,
80
+ for a screenshot.
75
81
 
76
82
  ```
77
- npx mcp-context-card card # at a terminal: writes context-card.html and opens it
83
+ npx mcp-context-card card # at a terminal: writes context-card.html and opens it
84
+ npx mcp-context-card card --expanded # every section open
78
85
  npx mcp-context-card card > x.html # piped/redirected: raw HTML to stdout
79
- GET /card # live, on the HTTP transport
80
- GET /card?theme=light&accent=%230066cc
86
+ GET /card # live, on the HTTP transport
87
+ GET /card?expand=all&theme=light&accent=%230066cc
81
88
  ```
82
89
 
83
90
  Light, dark, or auto; the accent defaults to the AAIF palette and takes any hex.
@@ -115,7 +122,7 @@ npx mcp-context-card card
115
122
 
116
123
  At a terminal it writes `context-card.html` and opens it in your browser. Piped
117
124
  or redirected (`> card.html`, a script, CI) it writes raw HTML to stdout instead;
118
- `--stdout` forces that from a terminal too.
125
+ `--stdout` forces that from a terminal too. `--expanded` opens every section.
119
126
 
120
127
  ### Wire it into a host
121
128
 
@@ -186,6 +193,10 @@ The wire‑level detail is in [docs/MECHANISMS.md](./docs/MECHANISMS.md).
186
193
  | `list_context_sources` | what this project publishes, in what media types, via which surface |
187
194
  | `render_context_card` | the whole card as one self‑contained HTML page (also `GET /card`) |
188
195
 
196
+ Seven tools only read. `remember` and `forget` write the memory file, so they're
197
+ marked destructive and a host can ask before running them. Every tool carries a
198
+ title and MCP tool annotations.
199
+
189
200
  ## The demo
190
201
 
191
202
  `npm run demo` runs every tool over both transports:
@@ -198,10 +209,11 @@ The wire‑level detail is in [docs/MECHANISMS.md](./docs/MECHANISMS.md).
198
209
  4. **Discovery** — `list_context_sources()`, then the same server over stateless
199
210
  HTTP with its `.well-known` routes and `GET /card`.
200
211
 
201
- 104 tests on Linux, macOS, and Windows, coverage‑gated in CI. Two spawn a real
212
+ 106 tests on Linux, macOS, and Windows, coverage‑gated in CI. Two spawn a real
202
213
  child process and check a remembered fact survives the restart — one against
203
214
  an existing `project.fafm`, one starting from a project that has never had
204
- one; another checks the stdio and HTTP tool surfaces match.
215
+ one; another checks the stdio and HTTP tool surfaces match, and another checks
216
+ every tool's title and behaviour hints against what it actually does.
205
217
 
206
218
  ## Layout
207
219
 
package/dist/bin.d.ts CHANGED
@@ -8,7 +8,7 @@ export interface Launch {
8
8
  root: string;
9
9
  }
10
10
  /** what a bare `--help` / `help` prints. */
11
- export declare const HELP = "mcp-context-card 1.0.1\nServe a project's context (AGENTS.md), memory, and identity over MCP.\n\nUSAGE\n mcp-context-card stdio MCP server \u2014 what an MCP host spawns (default)\n mcp-context-card --http stateless Streamable HTTP on PORT (default 3000)\n mcp-context-card --stdio force stdio even when PORT is set\n mcp-context-card card this dir's context card \u2014 opens it in your browser\n at a terminal; HTML to stdout when piped ( > f.html )\n --theme light|dark --accent #hex --stdout\n mcp-context-card --help this text\n mcp-context-card --version print version\n\nENV\n MCP_CONTEXT_CARD_ROOT read AGENTS.md / project.fafm / .well-known/ from here\n PORT if set, run HTTP instead of stdio\n\nA bare run is an stdio server: it waits for a host to speak JSON-RPC on stdin,\nso it looks idle at a terminal. Try `card` (opens your context in a browser) or `--http`.\nhttps://github.com/Wolfe-Jam/mcp-context-card\n";
11
+ export declare const HELP = "mcp-context-card 1.1.1\nServe a project's context (AGENTS.md), memory, and identity over MCP.\n\nUSAGE\n mcp-context-card stdio MCP server \u2014 what an MCP host spawns (default)\n mcp-context-card --http stateless Streamable HTTP on PORT (default 3000)\n mcp-context-card --stdio force stdio even when PORT is set\n mcp-context-card card this dir's context card \u2014 opens it in your browser\n at a terminal; HTML to stdout when piped ( > f.html )\n --theme light|dark --accent #hex\n --expanded (all sections open) --stdout\n mcp-context-card --help this text\n mcp-context-card --version print version\n\nENV\n MCP_CONTEXT_CARD_ROOT read AGENTS.md / project.fafm / .well-known/ from here\n PORT if set, run HTTP instead of stdio\n\nA bare run is an stdio server: it waits for a host to speak JSON-RPC on stdin,\nso it looks idle at a terminal. Try `card` (opens your context in a browser) or `--http`.\nhttps://github.com/Wolfe-Jam/mcp-context-card\n";
12
12
  /**
13
13
  * Decide how to launch, from argv + env. Pure — so the mode matrix is unit
14
14
  * tested without spawning a process.
package/dist/bin.js CHANGED
@@ -9,7 +9,8 @@
9
9
  * mcp-context-card card → this directory's context card. At a terminal:
10
10
  * writes context-card.html and opens it. Piped
11
11
  * or redirected: HTML to stdout ( > card.html ).
12
- * --theme light|dark · --accent #hex · --stdout
12
+ * --theme light|dark · --accent #hex
13
+ * --expanded (all sections open) · --stdout
13
14
  * mcp-context-card --help → usage
14
15
  * mcp-context-card --version → version
15
16
  *
@@ -32,7 +33,8 @@ USAGE
32
33
  mcp-context-card --stdio force stdio even when PORT is set
33
34
  mcp-context-card card this dir's context card — opens it in your browser
34
35
  at a terminal; HTML to stdout when piped ( > f.html )
35
- --theme light|dark --accent #hex --stdout
36
+ --theme light|dark --accent #hex
37
+ --expanded (all sections open) --stdout
36
38
  mcp-context-card --help this text
37
39
  mcp-context-card --version print version
38
40
 
@@ -109,6 +111,7 @@ if (entryPath && import.meta.url === pathToFileURL(entryPath).href) {
109
111
  const html = renderCard(root, {
110
112
  theme: theme === "light" || theme === "dark" ? theme : "auto",
111
113
  accent: safeAccent(flagValue(argv, "--accent")),
114
+ expanded: argv.includes("--expanded"),
112
115
  });
113
116
  // Piped / redirected (or --stdout) → raw HTML on stdout, unchanged.
114
117
  // A bare run at a terminal → the HTML is noise; write a file and open it.
@@ -1,5 +1,5 @@
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.0.1";
4
+ export declare const VERSION = "1.1.1";
5
5
  export declare const SERVER_CARD_URI = "mcp-context-card://server-card";
package/dist/constants.js CHANGED
@@ -1,5 +1,5 @@
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.0.1";
4
+ export const VERSION = "1.1.1";
5
5
  export const SERVER_CARD_URI = "mcp-context-card://server-card";
@@ -3,6 +3,12 @@ export interface CardOptions {
3
3
  theme?: Theme;
4
4
  /** CSS hex colour for the accent. Validated; invalid falls back to AAIF. */
5
5
  accent?: string;
6
+ /**
7
+ * Render every AGENTS.md section open. Default: sections collapse to their
8
+ * headings (`<details>`), click one to read it — the card scans in one screen.
9
+ * `expanded` is the whole-page render, for a screenshot or a PR.
10
+ */
11
+ expanded?: boolean;
6
12
  }
7
13
  /** AAIF brand orange (aaif.io). The default accent. */
8
14
  export declare const AAIF_ACCENT = "#FF702D";
@@ -6,8 +6,9 @@
6
6
  * or drop into a PR. Same three sources as the Server Card _meta block and
7
7
  * ai-catalog; this is the view for people.
8
8
  *
9
- * Self-contained: inline CSS, no JS, no external fonts. Renders anywhere,
10
- * including as a data: URI.
9
+ * Self-contained: inline CSS, no external fonts or resources. The only script
10
+ * is the expand-all / print helper (TOGGLE_SCRIPT) — a progressive enhancement;
11
+ * every section still opens on its own without it. Renders anywhere.
11
12
  */
12
13
  import { join } from "node:path";
13
14
  import { parseAgentsMd } from "./agents-md.js";
@@ -47,7 +48,7 @@ body{margin:0;background:var(--bg);color:var(--fg);
47
48
  font:15px/1.6 -apple-system,BlinkMacSystemFont,"Segoe UI",Roboto,Helvetica,Arial,sans-serif;
48
49
  padding:40px 18px}
49
50
  .card{max-width:760px;margin:0 auto;background:var(--card);border:1px solid var(--line);
50
- border-radius:14px;overflow:hidden;box-shadow:var(--card-shadow)}
51
+ border-radius:14px;overflow:clip;box-shadow:var(--card-shadow)}
51
52
  .card>*{padding:26px 30px}
52
53
  .top{border-top:4px solid var(--accent);border-bottom:1px solid var(--line)}
53
54
  h1{margin:0 0 10px;font-size:1.7rem;letter-spacing:-.02em}
@@ -58,9 +59,31 @@ section{border-bottom:1px solid var(--line)}
58
59
  section:last-child{border-bottom:0}
59
60
  .label{font-size:.7rem;font-weight:700;letter-spacing:.16em;text-transform:uppercase;
60
61
  color:var(--accent);margin:0 0 14px}
61
- .toc{display:flex;flex-wrap:wrap;gap:6px 14px;margin:0 0 20px;padding:0;list-style:none}
62
+ .toc{display:flex;flex-wrap:wrap;gap:6px 14px;margin:0;padding:0;list-style:none}
62
63
  .toc a{font-size:.82rem;color:var(--muted);text-decoration:none}
63
64
  .toc a:hover{color:var(--accent)}
65
+ /* ── collapsible context ─────────────────────────────────────────── */
66
+ .ctx-nav{position:sticky;top:0;z-index:3;background:var(--card);
67
+ margin:0 -30px 16px;padding:11px 30px;border-bottom:1px solid var(--line);
68
+ display:flex;flex-wrap:wrap;align-items:flex-start;gap:8px 16px}
69
+ .xall{margin-left:auto;flex:none;font:inherit;font-size:.76rem;font-weight:600;
70
+ white-space:nowrap;padding:3px 11px;border-radius:20px;border:1px solid var(--line);
71
+ background:var(--chip);color:var(--muted);cursor:pointer}
72
+ .xall:hover{color:var(--accent);border-color:var(--accent)}
73
+ .ctx-preamble{padding-bottom:4px}
74
+ details.ctx-section{border-top:1px solid var(--line)}
75
+ details.ctx-section>summary{cursor:pointer;list-style:none;padding:11px 0;
76
+ font-weight:600;font-size:1rem;letter-spacing:-.01em;display:flex;gap:9px}
77
+ details.ctx-section>summary::-webkit-details-marker{display:none}
78
+ details.ctx-section>summary::before{content:"›";color:var(--accent);font-weight:700;
79
+ transition:transform .15s ease}
80
+ details.ctx-section[open]>summary::before{transform:rotate(90deg)}
81
+ details.ctx-section>.md{padding:0 0 16px}
82
+ @media print{
83
+ .ctx-nav{display:none}
84
+ details.ctx-section:not([open])>.md{display:block!important}
85
+ details.ctx-section>summary::before{content:""}
86
+ }
64
87
  .md h1,.md h2,.md h3,.md h4{margin:22px 0 8px;font-size:1rem;letter-spacing:-.01em}
65
88
  .md h1{font-size:1.15rem}
66
89
  .md p{margin:8px 0}
@@ -107,21 +130,28 @@ export function renderCard(root, opts = {}) {
107
130
  ]
108
131
  .filter(Boolean)
109
132
  .join("");
110
- // CONTEXT — drop the redundant top-level "# AGENTS.md" heading, keep its intro
133
+ // CONTEXT — one <details> per AGENTS.md section, collapsed by default (the card
134
+ // scans in one screen); `expanded` renders them all open. The "# AGENTS.md"
135
+ // top-level heading is dropped; its intro rides above the sections.
111
136
  const bodySections = agents?.sections.filter((s) => s.level > 1) ?? [];
112
137
  const toc = bodySections.length
113
138
  ? `<ul class="toc">${bodySections
114
139
  .map((s) => `<li><a href="#${slug(s.heading)}">${escapeHtml(s.heading)}</a></li>`)
115
140
  .join("")}</ul>`
116
141
  : "";
142
+ const preamble = [agents?.preamble, agents?.sections.find((s) => s.level === 1)?.body ?? ""]
143
+ .filter(Boolean)
144
+ .join("\n\n");
145
+ const openAttr = opts.expanded ? " open" : "";
146
+ const sections = bodySections
147
+ .map((s) => `<details class="ctx-section"${openAttr} id="${slug(s.heading)}"><summary>${escapeHtml(s.heading)}</summary><div class="md">${renderMarkdown(s.body)}</div></details>`)
148
+ .join("");
117
149
  const contextBody = agents
118
- ? `${toc}<div class="md">${renderMarkdown([
119
- agents.preamble,
120
- agents.sections.find((s) => s.level === 1)?.body ?? "",
121
- ...bodySections.map((s) => `${"#".repeat(s.level)} ${s.heading}\n\n${s.body}`),
122
- ]
123
- .filter(Boolean)
124
- .join("\n\n"))}</div>`
150
+ ? `<div class="ctx-nav">${toc}${bodySections.length
151
+ ? `<button type="button" class="xall" hidden>${opts.expanded ? "Collapse all" : "Expand all"}</button>`
152
+ : ""}</div>
153
+ ${preamble ? `<div class="ctx-preamble md">${renderMarkdown(preamble)}</div>` : ""}
154
+ <div class="ctx-body">${sections}</div>`
125
155
  : `<p class="none">No AGENTS.md in this project.</p>`;
126
156
  // MEMORY
127
157
  const memoryBody = mem.facts.length
@@ -174,7 +204,35 @@ export function renderCard(root, opts = {}) {
174
204
  </section>
175
205
  <div class="foot">${escapeHtml(name)} · context card</div>
176
206
  </main>
207
+ ${bodySections.length ? TOGGLE_SCRIPT : ""}
177
208
  </body>
178
209
  </html>
179
210
  `;
180
211
  }
212
+ /**
213
+ * Expand-all / Collapse-all. The only script in the card — a progressive
214
+ * enhancement: with it off, every section still opens and closes on its own
215
+ * (native `<details>`), just without the bulk button. It also opens every
216
+ * section for printing, since browsers don't agree on whether a closed
217
+ * `<details>` prints its content.
218
+ */
219
+ const TOGGLE_SCRIPT = `<script>
220
+ (function(){
221
+ var btn=document.querySelector(".xall");
222
+ var secs=[].slice.call(document.querySelectorAll("details.ctx-section"));
223
+ if(!btn||!secs.length)return;
224
+ var sync=function(){btn.textContent=secs.every(function(d){return d.open})?"Collapse all":"Expand all"};
225
+ btn.hidden=false;
226
+ btn.addEventListener("click",function(){
227
+ var open=!secs.every(function(d){return d.open});
228
+ secs.forEach(function(d){d.open=open});sync();
229
+ });
230
+ secs.forEach(function(d){d.addEventListener("toggle",sync)});
231
+ var openHash=function(){var d=document.getElementById(location.hash.slice(1));if(d&&d.tagName==="DETAILS")d.open=true};
232
+ addEventListener("hashchange",openHash);openHash();
233
+ var pre=[];
234
+ addEventListener("beforeprint",function(){pre=secs.map(function(d){return d.open});secs.forEach(function(d){d.open=true})});
235
+ addEventListener("afterprint",function(){secs.forEach(function(d,i){d.open=pre[i]});sync()});
236
+ sync();
237
+ })();
238
+ </script>`;
package/dist/server.js CHANGED
@@ -82,6 +82,8 @@ export function createServer(root = ROOT) {
82
82
  tools: [
83
83
  {
84
84
  name: "read_agents_md",
85
+ title: "Read AGENTS.md",
86
+ annotations: { title: "Read AGENTS.md", readOnlyHint: true, idempotentHint: true, openWorldHint: false },
85
87
  description: "Return this project's AGENTS.md — the whole file, or one section by heading. The instructions a client would otherwise have to know to look for and read wholesale.",
86
88
  inputSchema: {
87
89
  type: "object",
@@ -95,16 +97,22 @@ export function createServer(root = ROOT) {
95
97
  },
96
98
  {
97
99
  name: "author_agents_md",
100
+ title: "Draft an AGENTS.md",
101
+ annotations: { title: "Draft an AGENTS.md", readOnlyHint: true, idempotentHint: true, openWorldHint: false },
98
102
  description: "Author an AGENTS.md for this project and return the draft — BETTER from repo facts alone (via agents-md-facts: real build/test commands, entry points, toolchain conventions, nothing invented), or BEST when a project.faf exists (facts plus its structured goal/who/why as a second managed block ahead of them). Does not write a file.",
99
103
  inputSchema: { type: "object", properties: {} },
100
104
  },
101
105
  {
102
106
  name: "list_agents_md_sections",
107
+ title: "List AGENTS.md Sections",
108
+ annotations: { title: "List AGENTS.md Sections", readOnlyHint: true, idempotentHint: true, openWorldHint: false },
103
109
  description: "List the headings in this project's AGENTS.md, so a client can pull one section instead of spending context on the whole file.",
104
110
  inputSchema: { type: "object", properties: {} },
105
111
  },
106
112
  {
107
113
  name: "remember",
114
+ title: "Remember a Fact",
115
+ annotations: { title: "Remember a Fact", readOnlyHint: false, destructiveHint: true, idempotentHint: true, openWorldHint: false },
108
116
  description: "Persist a fact past the session boundary — written to a .fafm file, not held in memory. Reusing an existing id replaces that fact's text in place (no duplicate); a new id appends. Facts are written verification_status: unverified.",
109
117
  inputSchema: {
110
118
  type: "object",
@@ -123,6 +131,8 @@ export function createServer(root = ROOT) {
123
131
  },
124
132
  {
125
133
  name: "recall",
134
+ title: "Recall a Fact",
135
+ annotations: { title: "Recall a Fact", readOnlyHint: true, idempotentHint: true, openWorldHint: false },
126
136
  description: "Retrieve a fact stored in a previous session by id. Exact lookup — not fuzzy or substring.",
127
137
  inputSchema: {
128
138
  type: "object",
@@ -137,6 +147,8 @@ export function createServer(root = ROOT) {
137
147
  },
138
148
  {
139
149
  name: "forget",
150
+ title: "Forget a Fact",
151
+ annotations: { title: "Forget a Fact", readOnlyHint: false, destructiveHint: true, idempotentHint: true, openWorldHint: false },
140
152
  description: "Remove a fact by id — to correct or drop something stale. A missing id is reported, not an error.",
141
153
  inputSchema: {
142
154
  type: "object",
@@ -151,22 +163,29 @@ export function createServer(root = ROOT) {
151
163
  },
152
164
  {
153
165
  name: "whoami",
166
+ title: "Who Am I",
167
+ annotations: { title: "Who Am I", readOnlyHint: true, idempotentHint: true, openWorldHint: false },
154
168
  description: "This server's own identity — name, vendor, version, status, license — from its .fafa card.",
155
169
  inputSchema: { type: "object", properties: {} },
156
170
  },
157
171
  {
158
172
  name: "list_context_sources",
173
+ title: "List Context Sources",
174
+ annotations: { title: "List Context Sources", readOnlyHint: true, idempotentHint: true, openWorldHint: false },
159
175
  description: "What context does this project publish (AGENTS.md, memory, identity), in what media types, and through which discovery surface. For a client connecting cold.",
160
176
  inputSchema: { type: "object", properties: {} },
161
177
  },
162
178
  {
163
179
  name: "render_context_card",
164
- description: "Render the whole card — identity, AGENTS.md, memory, discovery — as one self-contained HTML page a person can read or screenshot. Also served at GET /card over the HTTP transport.",
180
+ title: "Render Context Card",
181
+ annotations: { title: "Render Context Card", readOnlyHint: true, idempotentHint: true, openWorldHint: false },
182
+ description: "Render the whole card — identity, AGENTS.md, memory, discovery — as one self-contained HTML page a person can read or screenshot. AGENTS.md sections collapse by default; pass expanded:true for the full render. Also served at GET /card (?expand=all) over the HTTP transport.",
165
183
  inputSchema: {
166
184
  type: "object",
167
185
  properties: {
168
186
  theme: { type: "string", enum: ["light", "dark", "auto"], description: "default: auto" },
169
187
  accent: { type: "string", description: "CSS hex colour, e.g. #FF702D (default: the AAIF palette)" },
188
+ expanded: { type: "boolean", description: "render every AGENTS.md section open (default: collapsed)" },
170
189
  },
171
190
  },
172
191
  },
@@ -215,7 +234,8 @@ export function createServer(root = ROOT) {
215
234
  }
216
235
  case "whoami":
217
236
  return text(whoami(root));
218
- case "render_context_card":
237
+ case "render_context_card": {
238
+ const rawExpanded = args.expanded;
219
239
  return {
220
240
  content: [
221
241
  {
@@ -223,10 +243,12 @@ export function createServer(root = ROOT) {
223
243
  text: renderCard(root, {
224
244
  theme: (["light", "dark", "auto"].includes(args.theme) ? args.theme : "auto"),
225
245
  accent: safeAccent(args.accent),
246
+ expanded: rawExpanded === true || rawExpanded === "true",
226
247
  }),
227
248
  },
228
249
  ],
229
250
  };
251
+ }
230
252
  case "list_context_sources": {
231
253
  const doc = parseAgentsMd(AGENTS);
232
254
  const mem = parseFafm(FAFM);
@@ -56,7 +56,7 @@ export function httpApp(root = ROOT) {
56
56
  const q = c.req.query();
57
57
  const theme = (["light", "dark", "auto"].includes(q.theme ?? "") ? q.theme : "auto");
58
58
  c.header("content-type", "text/html; charset=utf-8");
59
- return c.body(renderCard(root, { theme, accent: safeAccent(q.accent) }));
59
+ return c.body(renderCard(root, { theme, accent: safeAccent(q.accent), expanded: q.expand === "all" }));
60
60
  });
61
61
  // ── Index ───────────────────────────────────────────────────────────
62
62
  app.get("/", (c) => c.json({
@@ -29,7 +29,7 @@ Both return:
29
29
  ```jsonc
30
30
  {
31
31
  "name": "mcp-context-card",
32
- "version": "1.0.1",
32
+ "version": "1.1.1",
33
33
  "_meta": {
34
34
  "io.github.Wolfe-Jam.mcp-context-card/context": {
35
35
  "source": "AGENTS.md",
@@ -30,7 +30,7 @@ body{margin:0;background:var(--bg);color:var(--fg);
30
30
  font:15px/1.6 -apple-system,BlinkMacSystemFont,"Segoe UI",Roboto,Helvetica,Arial,sans-serif;
31
31
  padding:40px 18px}
32
32
  .card{max-width:760px;margin:0 auto;background:var(--card);border:1px solid var(--line);
33
- border-radius:14px;overflow:hidden;box-shadow:var(--card-shadow)}
33
+ border-radius:14px;overflow:clip;box-shadow:var(--card-shadow)}
34
34
  .card>*{padding:26px 30px}
35
35
  .top{border-top:4px solid var(--accent);border-bottom:1px solid var(--line)}
36
36
  h1{margin:0 0 10px;font-size:1.7rem;letter-spacing:-.02em}
@@ -41,9 +41,31 @@ section{border-bottom:1px solid var(--line)}
41
41
  section:last-child{border-bottom:0}
42
42
  .label{font-size:.7rem;font-weight:700;letter-spacing:.16em;text-transform:uppercase;
43
43
  color:var(--accent);margin:0 0 14px}
44
- .toc{display:flex;flex-wrap:wrap;gap:6px 14px;margin:0 0 20px;padding:0;list-style:none}
44
+ .toc{display:flex;flex-wrap:wrap;gap:6px 14px;margin:0;padding:0;list-style:none}
45
45
  .toc a{font-size:.82rem;color:var(--muted);text-decoration:none}
46
46
  .toc a:hover{color:var(--accent)}
47
+ /* ── collapsible context ─────────────────────────────────────────── */
48
+ .ctx-nav{position:sticky;top:0;z-index:3;background:var(--card);
49
+ margin:0 -30px 16px;padding:11px 30px;border-bottom:1px solid var(--line);
50
+ display:flex;flex-wrap:wrap;align-items:flex-start;gap:8px 16px}
51
+ .xall{margin-left:auto;flex:none;font:inherit;font-size:.76rem;font-weight:600;
52
+ white-space:nowrap;padding:3px 11px;border-radius:20px;border:1px solid var(--line);
53
+ background:var(--chip);color:var(--muted);cursor:pointer}
54
+ .xall:hover{color:var(--accent);border-color:var(--accent)}
55
+ .ctx-preamble{padding-bottom:4px}
56
+ details.ctx-section{border-top:1px solid var(--line)}
57
+ details.ctx-section>summary{cursor:pointer;list-style:none;padding:11px 0;
58
+ font-weight:600;font-size:1rem;letter-spacing:-.01em;display:flex;gap:9px}
59
+ details.ctx-section>summary::-webkit-details-marker{display:none}
60
+ details.ctx-section>summary::before{content:"›";color:var(--accent);font-weight:700;
61
+ transition:transform .15s ease}
62
+ details.ctx-section[open]>summary::before{transform:rotate(90deg)}
63
+ details.ctx-section>.md{padding:0 0 16px}
64
+ @media print{
65
+ .ctx-nav{display:none}
66
+ details.ctx-section:not([open])>.md{display:block!important}
67
+ details.ctx-section>summary::before{content:""}
68
+ }
47
69
  .md h1,.md h2,.md h3,.md h4{margin:22px 0 8px;font-size:1rem;letter-spacing:-.01em}
48
70
  .md h1{font-size:1.15rem}
49
71
  .md p{margin:8px 0}
@@ -78,37 +100,21 @@ section:last-child{border-bottom:0}
78
100
  <main class="card">
79
101
  <div class="top">
80
102
  <h1>mcp-context-card</h1>
81
- <div class="pills"><span class="pill">io.github.Wolfe-Jam</span><span class="pill">v1.0.1</span><span class="pill accent">published</span><span class="pill">MIT</span></div>
103
+ <div class="pills"><span class="pill">io.github.Wolfe-Jam</span><span class="pill">v1.1.1</span><span class="pill accent">published</span><span class="pill">MIT</span></div>
82
104
  </div>
83
105
  <section>
84
106
  <p class="label">Context — AGENTS.md</p>
85
- <ul class="toc"><li><a href="#setup">Setup</a></li><li><a href="#build">Build</a></li><li><a href="#test">Test</a></li><li><a href="#layout">Layout</a></li><li><a href="#conventions">Conventions</a></li><li><a href="#the-invariant">The invariant</a></li><li><a href="#safety">Safety</a></li><li><a href="#definition-of-done">Definition of done</a></li><li><a href="#authoring-this-file">Authoring this file</a></li></ul><div class="md"><p><code>mcp-context-card</code> is the essential MCP server for a project's <strong>context</strong> (this file), <strong>memory</strong>, and <strong>identity</strong> — usable as your base MCP, or dropped into any existing MCP server as an extension. Discoverable to any MCP client through the two surfaces already in the ecosystem: the Server Card <code>_meta</code> block and <code>ai-catalog.json</code> sibling entries.</p>
86
- <p><code>read_agents_md</code> serves this file, section by section, over the same MCP connection.</p>
87
- <h2 id="setup">Setup</h2>
88
- <pre><code class="language-bash">npm ci</code></pre>
89
- <p>Node 22 or newer. No other system dependencies.</p>
90
- <h2 id="build">Build</h2>
91
- <pre><code class="language-bash">npm run build # tsc -p tsconfig.build.json → dist/
92
- npm run typecheck # tsc --noEmit over src/ + test/</code></pre>
93
- <h2 id="test">Test</h2>
94
- <pre><code class="language-bash">npm test # node:test — every test/*.test.ts
107
+ <div class="ctx-nav"><ul class="toc"><li><a href="#setup">Setup</a></li><li><a href="#build">Build</a></li><li><a href="#test">Test</a></li><li><a href="#layout">Layout</a></li><li><a href="#conventions">Conventions</a></li><li><a href="#the-invariant">The invariant</a></li><li><a href="#safety">Safety</a></li><li><a href="#definition-of-done">Definition of done</a></li><li><a href="#authoring-this-file">Authoring this file</a></li></ul><button type="button" class="xall" hidden>Expand all</button></div>
108
+ <div class="ctx-preamble md"><p><code>mcp-context-card</code> is the essential MCP server for a project's <strong>context</strong> (this file), <strong>memory</strong>, and <strong>identity</strong> — usable as your base MCP, or dropped into any existing MCP server as an extension. Discoverable to any MCP client through the two surfaces already in the ecosystem: the Server Card <code>_meta</code> block and <code>ai-catalog.json</code> sibling entries.</p>
109
+ <p><code>read_agents_md</code> serves this file, section by section, over the same MCP connection.</p></div>
110
+ <div class="ctx-body"><details class="ctx-section" id="setup"><summary>Setup</summary><div class="md"><pre><code class="language-bash">npm ci</code></pre>
111
+ <p>Node 20 or newer. No other system dependencies.</p></div></details><details class="ctx-section" id="build"><summary>Build</summary><div class="md"><pre><code class="language-bash">npm run build # tsc -p tsconfig.build.json → dist/
112
+ npm run typecheck # tsc --noEmit over src/ + test/</code></pre></div></details><details class="ctx-section" id="test"><summary>Test</summary><div class="md"><pre><code class="language-bash">npm test # node:test — every test/*.test.ts
95
113
  npm run test:coverage # + the coverage gate (lines 90 / funcs 85 / branches 80, src/ only)
96
114
  npm run demo # end to end: all tools over stdio, then over stateless HTTP
97
115
  npm run version:check # every version-bearing spot agrees with package.json
98
116
  npm run faf:check # project.faf / project.fafm / .well-known/fafa still describe the project</code></pre>
99
- <p>CI runs <code>version:check → faf:check → typecheck → build → test:coverage → demo</code> on Linux, macOS, and Windows for every push and PR to <code>main</code> (<code>.github/workflows/ci.yml</code>), plus <code>catalog:check</code> / <code>card:check</code>, <code>faf-cli check project.faf --strict</code> (the repo dogfoods a <code>project.faf</code> — this keeps it Trophy), and <code>faf:nudge</code> (PR-only, non-blocking — warns if the code's shape moved without <code>project.faf</code>) on Linux.</p>
100
- <h2 id="layout">Layout</h2>
101
- <table><thead><tr><th>Path</th><th>What</th></tr></thead><tbody><tr><td><code>src/server.ts</code></td><td>the MCP server — the nine tools + the Server Card resource</td></tr><tr><td><code>src/agents-md.ts</code></td><td>reads and section-splits this file</td></tr><tr><td><code>src/author.ts</code></td><td><code>author_agents_md</code> — BETTER via <code>agents-md-facts</code>, BEST when <code>project.faf</code> exists</td></tr><tr><td><code>src/md.ts</code></td><td>a minimal dependency-free Markdown → HTML renderer</td></tr><tr><td><code>src/render-card.ts</code></td><td>the card — identity + this file + memory + discovery, as one HTML page</td></tr><tr><td><code>src/memory.ts</code> → <code>src/faf/parse-fafm.ts</code></td><td>file-backed <code>remember</code> / <code>recall</code> / <code>forget</code></td></tr><tr><td><code>src/identity.ts</code></td><td><code>whoami</code> (<code>.fafa</code> → <code>package.json</code> fallback) + the <code>_meta</code> context block</td></tr><tr><td><code>src/catalog-gen.ts</code></td><td>writes <code>.well-known/ai-catalog.json</code> from the same three sources</td></tr><tr><td><code>src/transport/http.ts</code></td><td>the stateless Streamable HTTP app (Hono)</td></tr><tr><td><code>src/bin.ts</code></td><td>the entry point (<code>resolveLaunch</code>) — <code>stdio</code> · <code>--http</code> · <code>card</code> · <code>--help</code> · <code>--version</code></td></tr><tr><td><code>src/faf/parse-fafm.ts</code> · <code>parse-fafa.ts</code></td><td>the <code>.fafm</code> / <code>.fafa</code> parsers</td></tr></tbody></table>
102
- <h2 id="conventions">Conventions</h2>
103
- <ul><li>TypeScript strict, ESM only (<code>&quot;type&quot;: &quot;module&quot;</code>, <code>.js</code> import specifiers).</li><li>Tests use <code>node:test</code> + <code>node:assert/strict</code> — no test framework.</li><li>Every source file opens with a comment stating what it is and why.</li><li>Conventional Commit messages (<code>feat:</code>, <code>fix:</code>, <code>chore:</code>, <code>test:</code>, <code>docs:</code>).</li></ul>
104
- <h2 id="the-invariant">The invariant</h2>
105
- <p><code>src/identity.ts</code>, <code>src/catalog-gen.ts</code>, and <code>src/render-card.ts</code> all describe the <strong>same three sources</strong>: this file, <code>project.fafm</code>, <code>.well-known/fafa</code>. Change what one exposes and you must change the others. <code>npm run catalog:check</code> and <code>npm run card:check</code> enforce it in CI — each regenerates its surface and fails on any diff.</p>
106
- <h2 id="safety">Safety</h2>
107
- <ul><li>Branch off <code>main</code>; CI must be green before merge.</li><li><code>npm run demo</code> writes a fact to <code>project.fafm</code> and restores the file on exit — don't kill it mid-run.</li><li>No secrets live in this repo; never add any.</li></ul>
108
- <h2 id="definition-of-done">Definition of done</h2>
109
- <p><code>npm run typecheck &amp;&amp; npm run build &amp;&amp; npm test &amp;&amp; npm run demo</code> all green, plus <code>npm run catalog:check</code> and <code>npm run card:check</code> clean if you touched <code>AGENTS.md</code>, <code>project.fafm</code>, or <code>.well-known/fafa</code>, and <code>npm run faf:check</code> green if you changed the layout, a dependency, or the identity. On a version bump, <code>npm run version:check</code> green (it lists every spot that must move together) and <code>project.faf</code> still Trophy (<code>faf-cli check project.faf --strict</code>). If CI's <code>faf:nudge</code> warns on your PR, reconcile <code>project.faf</code> (and re-check <code>project.fafm</code> facts if <code>AGENTS.md</code> moved) or say why it's fine.</p>
110
- <h2 id="authoring-this-file">Authoring this file</h2>
111
- <p><code>AGENTS.md</code> here is maintained by hand. The <code>author_agents_md</code> tool (or <code>faf export --agents</code>) would draft a BEST version straight from this repo's own <code>project.faf</code> plus its detected facts — the server doesn't care how the file was authored, only that it's valid Markdown.</p></div>
117
+ <p>CI runs <code>version:check → faf:check → typecheck → build → test:coverage → demo</code> on Linux, macOS, and Windows for every push and PR to <code>main</code> (<code>.github/workflows/ci.yml</code>), plus <code>catalog:check</code> / <code>card:check</code>, <code>faf-cli check project.faf --strict</code> (the repo dogfoods a <code>project.faf</code> — this keeps it Trophy), and <code>faf:nudge</code> (PR-only, non-blocking — warns if the code's shape moved without <code>project.faf</code>) on Linux.</p></div></details><details class="ctx-section" id="layout"><summary>Layout</summary><div class="md"><table><thead><tr><th>Path</th><th>What</th></tr></thead><tbody><tr><td><code>src/server.ts</code></td><td>the MCP server — the nine tools + the Server Card resource</td></tr><tr><td><code>src/agents-md.ts</code></td><td>reads and section-splits this file</td></tr><tr><td><code>src/author.ts</code></td><td><code>author_agents_md</code> — BETTER via <code>agents-md-facts</code>, BEST when <code>project.faf</code> exists</td></tr><tr><td><code>src/md.ts</code></td><td>a minimal dependency-free Markdown → HTML renderer</td></tr><tr><td><code>src/render-card.ts</code></td><td>the card — identity + this file + memory + discovery, as one HTML page</td></tr><tr><td><code>src/memory.ts</code> → <code>src/faf/parse-fafm.ts</code></td><td>file-backed <code>remember</code> / <code>recall</code> / <code>forget</code></td></tr><tr><td><code>src/identity.ts</code></td><td><code>whoami</code> (<code>.fafa</code> → <code>package.json</code> fallback) + the <code>_meta</code> context block</td></tr><tr><td><code>src/catalog-gen.ts</code></td><td>writes <code>.well-known/ai-catalog.json</code> from the same three sources</td></tr><tr><td><code>src/transport/http.ts</code></td><td>the stateless Streamable HTTP app (Hono)</td></tr><tr><td><code>src/bin.ts</code></td><td>the entry point (<code>resolveLaunch</code>) — <code>stdio</code> · <code>--http</code> · <code>card</code> · <code>--help</code> · <code>--version</code></td></tr><tr><td><code>src/faf/parse-fafm.ts</code> · <code>parse-fafa.ts</code></td><td>the <code>.fafm</code> / <code>.fafa</code> parsers</td></tr></tbody></table></div></details><details class="ctx-section" id="conventions"><summary>Conventions</summary><div class="md"><ul><li>TypeScript strict, ESM only (<code>&quot;type&quot;: &quot;module&quot;</code>, <code>.js</code> import specifiers).</li><li>Tests use <code>node:test</code> + <code>node:assert/strict</code> — no test framework.</li><li>Every source file opens with a comment stating what it is and why.</li><li>Conventional Commit messages (<code>feat:</code>, <code>fix:</code>, <code>chore:</code>, <code>test:</code>, <code>docs:</code>).</li></ul></div></details><details class="ctx-section" id="the-invariant"><summary>The invariant</summary><div class="md"><p><code>src/identity.ts</code>, <code>src/catalog-gen.ts</code>, and <code>src/render-card.ts</code> all describe the <strong>same three sources</strong>: this file, <code>project.fafm</code>, <code>.well-known/fafa</code>. Change what one exposes and you must change the others. <code>npm run catalog:check</code> and <code>npm run card:check</code> enforce it in CI — each regenerates its surface and fails on any diff.</p></div></details><details class="ctx-section" id="safety"><summary>Safety</summary><div class="md"><ul><li>Branch off <code>main</code>; CI must be green before merge.</li><li><code>npm run demo</code> writes a fact to <code>project.fafm</code> and restores the file on exit — don't kill it mid-run.</li><li>No secrets live in this repo; never add any.</li></ul></div></details><details class="ctx-section" id="definition-of-done"><summary>Definition of done</summary><div class="md"><p><code>npm run typecheck &amp;&amp; npm run build &amp;&amp; npm test &amp;&amp; npm run demo</code> all green, plus <code>npm run catalog:check</code> and <code>npm run card:check</code> clean if you touched <code>AGENTS.md</code>, <code>project.fafm</code>, or <code>.well-known/fafa</code>, and <code>npm run faf:check</code> green if you changed the layout, a dependency, or the identity. On a version bump, <code>npm run version:check</code> green (it lists every spot that must move together) and <code>project.faf</code> still Trophy (<code>faf-cli check project.faf --strict</code>). If CI's <code>faf:nudge</code> warns on your PR, reconcile <code>project.faf</code> (and re-check <code>project.fafm</code> facts if <code>AGENTS.md</code> moved) or say why it's fine.</p></div></details><details class="ctx-section" id="authoring-this-file"><summary>Authoring this file</summary><div class="md"><p><code>AGENTS.md</code> here is maintained by hand. The <code>author_agents_md</code> tool (or <code>faf export --agents</code>) would draft a BEST version straight from this repo's own <code>project.faf</code> plus its detected facts — the server doesn't care how the file was authored, only that it's valid Markdown.</p></div></details></div>
112
118
  </section>
113
119
  <section>
114
120
  <p class="label">Memory — 4 facts</p>
@@ -124,5 +130,25 @@ npm run faf:check # project.faf / project.fafm / .well-known/fafa still desc
124
130
  </section>
125
131
  <div class="foot">mcp-context-card · context card</div>
126
132
  </main>
133
+ <script>
134
+ (function(){
135
+ var btn=document.querySelector(".xall");
136
+ var secs=[].slice.call(document.querySelectorAll("details.ctx-section"));
137
+ if(!btn||!secs.length)return;
138
+ var sync=function(){btn.textContent=secs.every(function(d){return d.open})?"Collapse all":"Expand all"};
139
+ btn.hidden=false;
140
+ btn.addEventListener("click",function(){
141
+ var open=!secs.every(function(d){return d.open});
142
+ secs.forEach(function(d){d.open=open});sync();
143
+ });
144
+ secs.forEach(function(d){d.addEventListener("toggle",sync)});
145
+ var openHash=function(){var d=document.getElementById(location.hash.slice(1));if(d&&d.tagName==="DETAILS")d.open=true};
146
+ addEventListener("hashchange",openHash);openHash();
147
+ var pre=[];
148
+ addEventListener("beforeprint",function(){pre=secs.map(function(d){return d.open});secs.forEach(function(d){d.open=true})});
149
+ addEventListener("afterprint",function(){secs.forEach(function(d,i){d.open=pre[i]});sync()});
150
+ sync();
151
+ })();
152
+ </script>
127
153
  </body>
128
154
  </html>
@@ -30,7 +30,7 @@ body{margin:0;background:var(--bg);color:var(--fg);
30
30
  font:15px/1.6 -apple-system,BlinkMacSystemFont,"Segoe UI",Roboto,Helvetica,Arial,sans-serif;
31
31
  padding:40px 18px}
32
32
  .card{max-width:760px;margin:0 auto;background:var(--card);border:1px solid var(--line);
33
- border-radius:14px;overflow:hidden;box-shadow:var(--card-shadow)}
33
+ border-radius:14px;overflow:clip;box-shadow:var(--card-shadow)}
34
34
  .card>*{padding:26px 30px}
35
35
  .top{border-top:4px solid var(--accent);border-bottom:1px solid var(--line)}
36
36
  h1{margin:0 0 10px;font-size:1.7rem;letter-spacing:-.02em}
@@ -41,9 +41,31 @@ section{border-bottom:1px solid var(--line)}
41
41
  section:last-child{border-bottom:0}
42
42
  .label{font-size:.7rem;font-weight:700;letter-spacing:.16em;text-transform:uppercase;
43
43
  color:var(--accent);margin:0 0 14px}
44
- .toc{display:flex;flex-wrap:wrap;gap:6px 14px;margin:0 0 20px;padding:0;list-style:none}
44
+ .toc{display:flex;flex-wrap:wrap;gap:6px 14px;margin:0;padding:0;list-style:none}
45
45
  .toc a{font-size:.82rem;color:var(--muted);text-decoration:none}
46
46
  .toc a:hover{color:var(--accent)}
47
+ /* ── collapsible context ─────────────────────────────────────────── */
48
+ .ctx-nav{position:sticky;top:0;z-index:3;background:var(--card);
49
+ margin:0 -30px 16px;padding:11px 30px;border-bottom:1px solid var(--line);
50
+ display:flex;flex-wrap:wrap;align-items:flex-start;gap:8px 16px}
51
+ .xall{margin-left:auto;flex:none;font:inherit;font-size:.76rem;font-weight:600;
52
+ white-space:nowrap;padding:3px 11px;border-radius:20px;border:1px solid var(--line);
53
+ background:var(--chip);color:var(--muted);cursor:pointer}
54
+ .xall:hover{color:var(--accent);border-color:var(--accent)}
55
+ .ctx-preamble{padding-bottom:4px}
56
+ details.ctx-section{border-top:1px solid var(--line)}
57
+ details.ctx-section>summary{cursor:pointer;list-style:none;padding:11px 0;
58
+ font-weight:600;font-size:1rem;letter-spacing:-.01em;display:flex;gap:9px}
59
+ details.ctx-section>summary::-webkit-details-marker{display:none}
60
+ details.ctx-section>summary::before{content:"›";color:var(--accent);font-weight:700;
61
+ transition:transform .15s ease}
62
+ details.ctx-section[open]>summary::before{transform:rotate(90deg)}
63
+ details.ctx-section>.md{padding:0 0 16px}
64
+ @media print{
65
+ .ctx-nav{display:none}
66
+ details.ctx-section:not([open])>.md{display:block!important}
67
+ details.ctx-section>summary::before{content:""}
68
+ }
47
69
  .md h1,.md h2,.md h3,.md h4{margin:22px 0 8px;font-size:1rem;letter-spacing:-.01em}
48
70
  .md h1{font-size:1.15rem}
49
71
  .md p{margin:8px 0}
@@ -78,37 +100,21 @@ section:last-child{border-bottom:0}
78
100
  <main class="card">
79
101
  <div class="top">
80
102
  <h1>mcp-context-card</h1>
81
- <div class="pills"><span class="pill">io.github.Wolfe-Jam</span><span class="pill">v1.0.1</span><span class="pill accent">published</span><span class="pill">MIT</span></div>
103
+ <div class="pills"><span class="pill">io.github.Wolfe-Jam</span><span class="pill">v1.1.1</span><span class="pill accent">published</span><span class="pill">MIT</span></div>
82
104
  </div>
83
105
  <section>
84
106
  <p class="label">Context — AGENTS.md</p>
85
- <ul class="toc"><li><a href="#setup">Setup</a></li><li><a href="#build">Build</a></li><li><a href="#test">Test</a></li><li><a href="#layout">Layout</a></li><li><a href="#conventions">Conventions</a></li><li><a href="#the-invariant">The invariant</a></li><li><a href="#safety">Safety</a></li><li><a href="#definition-of-done">Definition of done</a></li><li><a href="#authoring-this-file">Authoring this file</a></li></ul><div class="md"><p><code>mcp-context-card</code> is the essential MCP server for a project's <strong>context</strong> (this file), <strong>memory</strong>, and <strong>identity</strong> — usable as your base MCP, or dropped into any existing MCP server as an extension. Discoverable to any MCP client through the two surfaces already in the ecosystem: the Server Card <code>_meta</code> block and <code>ai-catalog.json</code> sibling entries.</p>
86
- <p><code>read_agents_md</code> serves this file, section by section, over the same MCP connection.</p>
87
- <h2 id="setup">Setup</h2>
88
- <pre><code class="language-bash">npm ci</code></pre>
89
- <p>Node 22 or newer. No other system dependencies.</p>
90
- <h2 id="build">Build</h2>
91
- <pre><code class="language-bash">npm run build # tsc -p tsconfig.build.json → dist/
92
- npm run typecheck # tsc --noEmit over src/ + test/</code></pre>
93
- <h2 id="test">Test</h2>
94
- <pre><code class="language-bash">npm test # node:test — every test/*.test.ts
107
+ <div class="ctx-nav"><ul class="toc"><li><a href="#setup">Setup</a></li><li><a href="#build">Build</a></li><li><a href="#test">Test</a></li><li><a href="#layout">Layout</a></li><li><a href="#conventions">Conventions</a></li><li><a href="#the-invariant">The invariant</a></li><li><a href="#safety">Safety</a></li><li><a href="#definition-of-done">Definition of done</a></li><li><a href="#authoring-this-file">Authoring this file</a></li></ul><button type="button" class="xall" hidden>Expand all</button></div>
108
+ <div class="ctx-preamble md"><p><code>mcp-context-card</code> is the essential MCP server for a project's <strong>context</strong> (this file), <strong>memory</strong>, and <strong>identity</strong> — usable as your base MCP, or dropped into any existing MCP server as an extension. Discoverable to any MCP client through the two surfaces already in the ecosystem: the Server Card <code>_meta</code> block and <code>ai-catalog.json</code> sibling entries.</p>
109
+ <p><code>read_agents_md</code> serves this file, section by section, over the same MCP connection.</p></div>
110
+ <div class="ctx-body"><details class="ctx-section" id="setup"><summary>Setup</summary><div class="md"><pre><code class="language-bash">npm ci</code></pre>
111
+ <p>Node 20 or newer. No other system dependencies.</p></div></details><details class="ctx-section" id="build"><summary>Build</summary><div class="md"><pre><code class="language-bash">npm run build # tsc -p tsconfig.build.json → dist/
112
+ npm run typecheck # tsc --noEmit over src/ + test/</code></pre></div></details><details class="ctx-section" id="test"><summary>Test</summary><div class="md"><pre><code class="language-bash">npm test # node:test — every test/*.test.ts
95
113
  npm run test:coverage # + the coverage gate (lines 90 / funcs 85 / branches 80, src/ only)
96
114
  npm run demo # end to end: all tools over stdio, then over stateless HTTP
97
115
  npm run version:check # every version-bearing spot agrees with package.json
98
116
  npm run faf:check # project.faf / project.fafm / .well-known/fafa still describe the project</code></pre>
99
- <p>CI runs <code>version:check → faf:check → typecheck → build → test:coverage → demo</code> on Linux, macOS, and Windows for every push and PR to <code>main</code> (<code>.github/workflows/ci.yml</code>), plus <code>catalog:check</code> / <code>card:check</code>, <code>faf-cli check project.faf --strict</code> (the repo dogfoods a <code>project.faf</code> — this keeps it Trophy), and <code>faf:nudge</code> (PR-only, non-blocking — warns if the code's shape moved without <code>project.faf</code>) on Linux.</p>
100
- <h2 id="layout">Layout</h2>
101
- <table><thead><tr><th>Path</th><th>What</th></tr></thead><tbody><tr><td><code>src/server.ts</code></td><td>the MCP server — the nine tools + the Server Card resource</td></tr><tr><td><code>src/agents-md.ts</code></td><td>reads and section-splits this file</td></tr><tr><td><code>src/author.ts</code></td><td><code>author_agents_md</code> — BETTER via <code>agents-md-facts</code>, BEST when <code>project.faf</code> exists</td></tr><tr><td><code>src/md.ts</code></td><td>a minimal dependency-free Markdown → HTML renderer</td></tr><tr><td><code>src/render-card.ts</code></td><td>the card — identity + this file + memory + discovery, as one HTML page</td></tr><tr><td><code>src/memory.ts</code> → <code>src/faf/parse-fafm.ts</code></td><td>file-backed <code>remember</code> / <code>recall</code> / <code>forget</code></td></tr><tr><td><code>src/identity.ts</code></td><td><code>whoami</code> (<code>.fafa</code> → <code>package.json</code> fallback) + the <code>_meta</code> context block</td></tr><tr><td><code>src/catalog-gen.ts</code></td><td>writes <code>.well-known/ai-catalog.json</code> from the same three sources</td></tr><tr><td><code>src/transport/http.ts</code></td><td>the stateless Streamable HTTP app (Hono)</td></tr><tr><td><code>src/bin.ts</code></td><td>the entry point (<code>resolveLaunch</code>) — <code>stdio</code> · <code>--http</code> · <code>card</code> · <code>--help</code> · <code>--version</code></td></tr><tr><td><code>src/faf/parse-fafm.ts</code> · <code>parse-fafa.ts</code></td><td>the <code>.fafm</code> / <code>.fafa</code> parsers</td></tr></tbody></table>
102
- <h2 id="conventions">Conventions</h2>
103
- <ul><li>TypeScript strict, ESM only (<code>&quot;type&quot;: &quot;module&quot;</code>, <code>.js</code> import specifiers).</li><li>Tests use <code>node:test</code> + <code>node:assert/strict</code> — no test framework.</li><li>Every source file opens with a comment stating what it is and why.</li><li>Conventional Commit messages (<code>feat:</code>, <code>fix:</code>, <code>chore:</code>, <code>test:</code>, <code>docs:</code>).</li></ul>
104
- <h2 id="the-invariant">The invariant</h2>
105
- <p><code>src/identity.ts</code>, <code>src/catalog-gen.ts</code>, and <code>src/render-card.ts</code> all describe the <strong>same three sources</strong>: this file, <code>project.fafm</code>, <code>.well-known/fafa</code>. Change what one exposes and you must change the others. <code>npm run catalog:check</code> and <code>npm run card:check</code> enforce it in CI — each regenerates its surface and fails on any diff.</p>
106
- <h2 id="safety">Safety</h2>
107
- <ul><li>Branch off <code>main</code>; CI must be green before merge.</li><li><code>npm run demo</code> writes a fact to <code>project.fafm</code> and restores the file on exit — don't kill it mid-run.</li><li>No secrets live in this repo; never add any.</li></ul>
108
- <h2 id="definition-of-done">Definition of done</h2>
109
- <p><code>npm run typecheck &amp;&amp; npm run build &amp;&amp; npm test &amp;&amp; npm run demo</code> all green, plus <code>npm run catalog:check</code> and <code>npm run card:check</code> clean if you touched <code>AGENTS.md</code>, <code>project.fafm</code>, or <code>.well-known/fafa</code>, and <code>npm run faf:check</code> green if you changed the layout, a dependency, or the identity. On a version bump, <code>npm run version:check</code> green (it lists every spot that must move together) and <code>project.faf</code> still Trophy (<code>faf-cli check project.faf --strict</code>). If CI's <code>faf:nudge</code> warns on your PR, reconcile <code>project.faf</code> (and re-check <code>project.fafm</code> facts if <code>AGENTS.md</code> moved) or say why it's fine.</p>
110
- <h2 id="authoring-this-file">Authoring this file</h2>
111
- <p><code>AGENTS.md</code> here is maintained by hand. The <code>author_agents_md</code> tool (or <code>faf export --agents</code>) would draft a BEST version straight from this repo's own <code>project.faf</code> plus its detected facts — the server doesn't care how the file was authored, only that it's valid Markdown.</p></div>
117
+ <p>CI runs <code>version:check → faf:check → typecheck → build → test:coverage → demo</code> on Linux, macOS, and Windows for every push and PR to <code>main</code> (<code>.github/workflows/ci.yml</code>), plus <code>catalog:check</code> / <code>card:check</code>, <code>faf-cli check project.faf --strict</code> (the repo dogfoods a <code>project.faf</code> — this keeps it Trophy), and <code>faf:nudge</code> (PR-only, non-blocking — warns if the code's shape moved without <code>project.faf</code>) on Linux.</p></div></details><details class="ctx-section" id="layout"><summary>Layout</summary><div class="md"><table><thead><tr><th>Path</th><th>What</th></tr></thead><tbody><tr><td><code>src/server.ts</code></td><td>the MCP server — the nine tools + the Server Card resource</td></tr><tr><td><code>src/agents-md.ts</code></td><td>reads and section-splits this file</td></tr><tr><td><code>src/author.ts</code></td><td><code>author_agents_md</code> — BETTER via <code>agents-md-facts</code>, BEST when <code>project.faf</code> exists</td></tr><tr><td><code>src/md.ts</code></td><td>a minimal dependency-free Markdown → HTML renderer</td></tr><tr><td><code>src/render-card.ts</code></td><td>the card — identity + this file + memory + discovery, as one HTML page</td></tr><tr><td><code>src/memory.ts</code> → <code>src/faf/parse-fafm.ts</code></td><td>file-backed <code>remember</code> / <code>recall</code> / <code>forget</code></td></tr><tr><td><code>src/identity.ts</code></td><td><code>whoami</code> (<code>.fafa</code> → <code>package.json</code> fallback) + the <code>_meta</code> context block</td></tr><tr><td><code>src/catalog-gen.ts</code></td><td>writes <code>.well-known/ai-catalog.json</code> from the same three sources</td></tr><tr><td><code>src/transport/http.ts</code></td><td>the stateless Streamable HTTP app (Hono)</td></tr><tr><td><code>src/bin.ts</code></td><td>the entry point (<code>resolveLaunch</code>) — <code>stdio</code> · <code>--http</code> · <code>card</code> · <code>--help</code> · <code>--version</code></td></tr><tr><td><code>src/faf/parse-fafm.ts</code> · <code>parse-fafa.ts</code></td><td>the <code>.fafm</code> / <code>.fafa</code> parsers</td></tr></tbody></table></div></details><details class="ctx-section" id="conventions"><summary>Conventions</summary><div class="md"><ul><li>TypeScript strict, ESM only (<code>&quot;type&quot;: &quot;module&quot;</code>, <code>.js</code> import specifiers).</li><li>Tests use <code>node:test</code> + <code>node:assert/strict</code> — no test framework.</li><li>Every source file opens with a comment stating what it is and why.</li><li>Conventional Commit messages (<code>feat:</code>, <code>fix:</code>, <code>chore:</code>, <code>test:</code>, <code>docs:</code>).</li></ul></div></details><details class="ctx-section" id="the-invariant"><summary>The invariant</summary><div class="md"><p><code>src/identity.ts</code>, <code>src/catalog-gen.ts</code>, and <code>src/render-card.ts</code> all describe the <strong>same three sources</strong>: this file, <code>project.fafm</code>, <code>.well-known/fafa</code>. Change what one exposes and you must change the others. <code>npm run catalog:check</code> and <code>npm run card:check</code> enforce it in CI — each regenerates its surface and fails on any diff.</p></div></details><details class="ctx-section" id="safety"><summary>Safety</summary><div class="md"><ul><li>Branch off <code>main</code>; CI must be green before merge.</li><li><code>npm run demo</code> writes a fact to <code>project.fafm</code> and restores the file on exit — don't kill it mid-run.</li><li>No secrets live in this repo; never add any.</li></ul></div></details><details class="ctx-section" id="definition-of-done"><summary>Definition of done</summary><div class="md"><p><code>npm run typecheck &amp;&amp; npm run build &amp;&amp; npm test &amp;&amp; npm run demo</code> all green, plus <code>npm run catalog:check</code> and <code>npm run card:check</code> clean if you touched <code>AGENTS.md</code>, <code>project.fafm</code>, or <code>.well-known/fafa</code>, and <code>npm run faf:check</code> green if you changed the layout, a dependency, or the identity. On a version bump, <code>npm run version:check</code> green (it lists every spot that must move together) and <code>project.faf</code> still Trophy (<code>faf-cli check project.faf --strict</code>). If CI's <code>faf:nudge</code> warns on your PR, reconcile <code>project.faf</code> (and re-check <code>project.fafm</code> facts if <code>AGENTS.md</code> moved) or say why it's fine.</p></div></details><details class="ctx-section" id="authoring-this-file"><summary>Authoring this file</summary><div class="md"><p><code>AGENTS.md</code> here is maintained by hand. The <code>author_agents_md</code> tool (or <code>faf export --agents</code>) would draft a BEST version straight from this repo's own <code>project.faf</code> plus its detected facts — the server doesn't care how the file was authored, only that it's valid Markdown.</p></div></details></div>
112
118
  </section>
113
119
  <section>
114
120
  <p class="label">Memory — 4 facts</p>
@@ -124,5 +130,25 @@ npm run faf:check # project.faf / project.fafm / .well-known/fafa still desc
124
130
  </section>
125
131
  <div class="foot">mcp-context-card · context card</div>
126
132
  </main>
133
+ <script>
134
+ (function(){
135
+ var btn=document.querySelector(".xall");
136
+ var secs=[].slice.call(document.querySelectorAll("details.ctx-section"));
137
+ if(!btn||!secs.length)return;
138
+ var sync=function(){btn.textContent=secs.every(function(d){return d.open})?"Collapse all":"Expand all"};
139
+ btn.hidden=false;
140
+ btn.addEventListener("click",function(){
141
+ var open=!secs.every(function(d){return d.open});
142
+ secs.forEach(function(d){d.open=open});sync();
143
+ });
144
+ secs.forEach(function(d){d.addEventListener("toggle",sync)});
145
+ var openHash=function(){var d=document.getElementById(location.hash.slice(1));if(d&&d.tagName==="DETAILS")d.open=true};
146
+ addEventListener("hashchange",openHash);openHash();
147
+ var pre=[];
148
+ addEventListener("beforeprint",function(){pre=secs.map(function(d){return d.open});secs.forEach(function(d){d.open=true})});
149
+ addEventListener("afterprint",function(){secs.forEach(function(d,i){d.open=pre[i]});sync()});
150
+ sync();
151
+ })();
152
+ </script>
127
153
  </body>
128
154
  </html>
package/docs/card.html CHANGED
@@ -30,7 +30,7 @@ body{margin:0;background:var(--bg);color:var(--fg);
30
30
  font:15px/1.6 -apple-system,BlinkMacSystemFont,"Segoe UI",Roboto,Helvetica,Arial,sans-serif;
31
31
  padding:40px 18px}
32
32
  .card{max-width:760px;margin:0 auto;background:var(--card);border:1px solid var(--line);
33
- border-radius:14px;overflow:hidden;box-shadow:var(--card-shadow)}
33
+ border-radius:14px;overflow:clip;box-shadow:var(--card-shadow)}
34
34
  .card>*{padding:26px 30px}
35
35
  .top{border-top:4px solid var(--accent);border-bottom:1px solid var(--line)}
36
36
  h1{margin:0 0 10px;font-size:1.7rem;letter-spacing:-.02em}
@@ -41,9 +41,31 @@ section{border-bottom:1px solid var(--line)}
41
41
  section:last-child{border-bottom:0}
42
42
  .label{font-size:.7rem;font-weight:700;letter-spacing:.16em;text-transform:uppercase;
43
43
  color:var(--accent);margin:0 0 14px}
44
- .toc{display:flex;flex-wrap:wrap;gap:6px 14px;margin:0 0 20px;padding:0;list-style:none}
44
+ .toc{display:flex;flex-wrap:wrap;gap:6px 14px;margin:0;padding:0;list-style:none}
45
45
  .toc a{font-size:.82rem;color:var(--muted);text-decoration:none}
46
46
  .toc a:hover{color:var(--accent)}
47
+ /* ── collapsible context ─────────────────────────────────────────── */
48
+ .ctx-nav{position:sticky;top:0;z-index:3;background:var(--card);
49
+ margin:0 -30px 16px;padding:11px 30px;border-bottom:1px solid var(--line);
50
+ display:flex;flex-wrap:wrap;align-items:flex-start;gap:8px 16px}
51
+ .xall{margin-left:auto;flex:none;font:inherit;font-size:.76rem;font-weight:600;
52
+ white-space:nowrap;padding:3px 11px;border-radius:20px;border:1px solid var(--line);
53
+ background:var(--chip);color:var(--muted);cursor:pointer}
54
+ .xall:hover{color:var(--accent);border-color:var(--accent)}
55
+ .ctx-preamble{padding-bottom:4px}
56
+ details.ctx-section{border-top:1px solid var(--line)}
57
+ details.ctx-section>summary{cursor:pointer;list-style:none;padding:11px 0;
58
+ font-weight:600;font-size:1rem;letter-spacing:-.01em;display:flex;gap:9px}
59
+ details.ctx-section>summary::-webkit-details-marker{display:none}
60
+ details.ctx-section>summary::before{content:"›";color:var(--accent);font-weight:700;
61
+ transition:transform .15s ease}
62
+ details.ctx-section[open]>summary::before{transform:rotate(90deg)}
63
+ details.ctx-section>.md{padding:0 0 16px}
64
+ @media print{
65
+ .ctx-nav{display:none}
66
+ details.ctx-section:not([open])>.md{display:block!important}
67
+ details.ctx-section>summary::before{content:""}
68
+ }
47
69
  .md h1,.md h2,.md h3,.md h4{margin:22px 0 8px;font-size:1rem;letter-spacing:-.01em}
48
70
  .md h1{font-size:1.15rem}
49
71
  .md p{margin:8px 0}
@@ -78,37 +100,21 @@ section:last-child{border-bottom:0}
78
100
  <main class="card">
79
101
  <div class="top">
80
102
  <h1>mcp-context-card</h1>
81
- <div class="pills"><span class="pill">io.github.Wolfe-Jam</span><span class="pill">v1.0.1</span><span class="pill accent">published</span><span class="pill">MIT</span></div>
103
+ <div class="pills"><span class="pill">io.github.Wolfe-Jam</span><span class="pill">v1.1.1</span><span class="pill accent">published</span><span class="pill">MIT</span></div>
82
104
  </div>
83
105
  <section>
84
106
  <p class="label">Context — AGENTS.md</p>
85
- <ul class="toc"><li><a href="#setup">Setup</a></li><li><a href="#build">Build</a></li><li><a href="#test">Test</a></li><li><a href="#layout">Layout</a></li><li><a href="#conventions">Conventions</a></li><li><a href="#the-invariant">The invariant</a></li><li><a href="#safety">Safety</a></li><li><a href="#definition-of-done">Definition of done</a></li><li><a href="#authoring-this-file">Authoring this file</a></li></ul><div class="md"><p><code>mcp-context-card</code> is the essential MCP server for a project's <strong>context</strong> (this file), <strong>memory</strong>, and <strong>identity</strong> — usable as your base MCP, or dropped into any existing MCP server as an extension. Discoverable to any MCP client through the two surfaces already in the ecosystem: the Server Card <code>_meta</code> block and <code>ai-catalog.json</code> sibling entries.</p>
86
- <p><code>read_agents_md</code> serves this file, section by section, over the same MCP connection.</p>
87
- <h2 id="setup">Setup</h2>
88
- <pre><code class="language-bash">npm ci</code></pre>
89
- <p>Node 22 or newer. No other system dependencies.</p>
90
- <h2 id="build">Build</h2>
91
- <pre><code class="language-bash">npm run build # tsc -p tsconfig.build.json → dist/
92
- npm run typecheck # tsc --noEmit over src/ + test/</code></pre>
93
- <h2 id="test">Test</h2>
94
- <pre><code class="language-bash">npm test # node:test — every test/*.test.ts
107
+ <div class="ctx-nav"><ul class="toc"><li><a href="#setup">Setup</a></li><li><a href="#build">Build</a></li><li><a href="#test">Test</a></li><li><a href="#layout">Layout</a></li><li><a href="#conventions">Conventions</a></li><li><a href="#the-invariant">The invariant</a></li><li><a href="#safety">Safety</a></li><li><a href="#definition-of-done">Definition of done</a></li><li><a href="#authoring-this-file">Authoring this file</a></li></ul><button type="button" class="xall" hidden>Expand all</button></div>
108
+ <div class="ctx-preamble md"><p><code>mcp-context-card</code> is the essential MCP server for a project's <strong>context</strong> (this file), <strong>memory</strong>, and <strong>identity</strong> — usable as your base MCP, or dropped into any existing MCP server as an extension. Discoverable to any MCP client through the two surfaces already in the ecosystem: the Server Card <code>_meta</code> block and <code>ai-catalog.json</code> sibling entries.</p>
109
+ <p><code>read_agents_md</code> serves this file, section by section, over the same MCP connection.</p></div>
110
+ <div class="ctx-body"><details class="ctx-section" id="setup"><summary>Setup</summary><div class="md"><pre><code class="language-bash">npm ci</code></pre>
111
+ <p>Node 20 or newer. No other system dependencies.</p></div></details><details class="ctx-section" id="build"><summary>Build</summary><div class="md"><pre><code class="language-bash">npm run build # tsc -p tsconfig.build.json → dist/
112
+ npm run typecheck # tsc --noEmit over src/ + test/</code></pre></div></details><details class="ctx-section" id="test"><summary>Test</summary><div class="md"><pre><code class="language-bash">npm test # node:test — every test/*.test.ts
95
113
  npm run test:coverage # + the coverage gate (lines 90 / funcs 85 / branches 80, src/ only)
96
114
  npm run demo # end to end: all tools over stdio, then over stateless HTTP
97
115
  npm run version:check # every version-bearing spot agrees with package.json
98
116
  npm run faf:check # project.faf / project.fafm / .well-known/fafa still describe the project</code></pre>
99
- <p>CI runs <code>version:check → faf:check → typecheck → build → test:coverage → demo</code> on Linux, macOS, and Windows for every push and PR to <code>main</code> (<code>.github/workflows/ci.yml</code>), plus <code>catalog:check</code> / <code>card:check</code>, <code>faf-cli check project.faf --strict</code> (the repo dogfoods a <code>project.faf</code> — this keeps it Trophy), and <code>faf:nudge</code> (PR-only, non-blocking — warns if the code's shape moved without <code>project.faf</code>) on Linux.</p>
100
- <h2 id="layout">Layout</h2>
101
- <table><thead><tr><th>Path</th><th>What</th></tr></thead><tbody><tr><td><code>src/server.ts</code></td><td>the MCP server — the nine tools + the Server Card resource</td></tr><tr><td><code>src/agents-md.ts</code></td><td>reads and section-splits this file</td></tr><tr><td><code>src/author.ts</code></td><td><code>author_agents_md</code> — BETTER via <code>agents-md-facts</code>, BEST when <code>project.faf</code> exists</td></tr><tr><td><code>src/md.ts</code></td><td>a minimal dependency-free Markdown → HTML renderer</td></tr><tr><td><code>src/render-card.ts</code></td><td>the card — identity + this file + memory + discovery, as one HTML page</td></tr><tr><td><code>src/memory.ts</code> → <code>src/faf/parse-fafm.ts</code></td><td>file-backed <code>remember</code> / <code>recall</code> / <code>forget</code></td></tr><tr><td><code>src/identity.ts</code></td><td><code>whoami</code> (<code>.fafa</code> → <code>package.json</code> fallback) + the <code>_meta</code> context block</td></tr><tr><td><code>src/catalog-gen.ts</code></td><td>writes <code>.well-known/ai-catalog.json</code> from the same three sources</td></tr><tr><td><code>src/transport/http.ts</code></td><td>the stateless Streamable HTTP app (Hono)</td></tr><tr><td><code>src/bin.ts</code></td><td>the entry point (<code>resolveLaunch</code>) — <code>stdio</code> · <code>--http</code> · <code>card</code> · <code>--help</code> · <code>--version</code></td></tr><tr><td><code>src/faf/parse-fafm.ts</code> · <code>parse-fafa.ts</code></td><td>the <code>.fafm</code> / <code>.fafa</code> parsers</td></tr></tbody></table>
102
- <h2 id="conventions">Conventions</h2>
103
- <ul><li>TypeScript strict, ESM only (<code>&quot;type&quot;: &quot;module&quot;</code>, <code>.js</code> import specifiers).</li><li>Tests use <code>node:test</code> + <code>node:assert/strict</code> — no test framework.</li><li>Every source file opens with a comment stating what it is and why.</li><li>Conventional Commit messages (<code>feat:</code>, <code>fix:</code>, <code>chore:</code>, <code>test:</code>, <code>docs:</code>).</li></ul>
104
- <h2 id="the-invariant">The invariant</h2>
105
- <p><code>src/identity.ts</code>, <code>src/catalog-gen.ts</code>, and <code>src/render-card.ts</code> all describe the <strong>same three sources</strong>: this file, <code>project.fafm</code>, <code>.well-known/fafa</code>. Change what one exposes and you must change the others. <code>npm run catalog:check</code> and <code>npm run card:check</code> enforce it in CI — each regenerates its surface and fails on any diff.</p>
106
- <h2 id="safety">Safety</h2>
107
- <ul><li>Branch off <code>main</code>; CI must be green before merge.</li><li><code>npm run demo</code> writes a fact to <code>project.fafm</code> and restores the file on exit — don't kill it mid-run.</li><li>No secrets live in this repo; never add any.</li></ul>
108
- <h2 id="definition-of-done">Definition of done</h2>
109
- <p><code>npm run typecheck &amp;&amp; npm run build &amp;&amp; npm test &amp;&amp; npm run demo</code> all green, plus <code>npm run catalog:check</code> and <code>npm run card:check</code> clean if you touched <code>AGENTS.md</code>, <code>project.fafm</code>, or <code>.well-known/fafa</code>, and <code>npm run faf:check</code> green if you changed the layout, a dependency, or the identity. On a version bump, <code>npm run version:check</code> green (it lists every spot that must move together) and <code>project.faf</code> still Trophy (<code>faf-cli check project.faf --strict</code>). If CI's <code>faf:nudge</code> warns on your PR, reconcile <code>project.faf</code> (and re-check <code>project.fafm</code> facts if <code>AGENTS.md</code> moved) or say why it's fine.</p>
110
- <h2 id="authoring-this-file">Authoring this file</h2>
111
- <p><code>AGENTS.md</code> here is maintained by hand. The <code>author_agents_md</code> tool (or <code>faf export --agents</code>) would draft a BEST version straight from this repo's own <code>project.faf</code> plus its detected facts — the server doesn't care how the file was authored, only that it's valid Markdown.</p></div>
117
+ <p>CI runs <code>version:check → faf:check → typecheck → build → test:coverage → demo</code> on Linux, macOS, and Windows for every push and PR to <code>main</code> (<code>.github/workflows/ci.yml</code>), plus <code>catalog:check</code> / <code>card:check</code>, <code>faf-cli check project.faf --strict</code> (the repo dogfoods a <code>project.faf</code> — this keeps it Trophy), and <code>faf:nudge</code> (PR-only, non-blocking — warns if the code's shape moved without <code>project.faf</code>) on Linux.</p></div></details><details class="ctx-section" id="layout"><summary>Layout</summary><div class="md"><table><thead><tr><th>Path</th><th>What</th></tr></thead><tbody><tr><td><code>src/server.ts</code></td><td>the MCP server — the nine tools + the Server Card resource</td></tr><tr><td><code>src/agents-md.ts</code></td><td>reads and section-splits this file</td></tr><tr><td><code>src/author.ts</code></td><td><code>author_agents_md</code> — BETTER via <code>agents-md-facts</code>, BEST when <code>project.faf</code> exists</td></tr><tr><td><code>src/md.ts</code></td><td>a minimal dependency-free Markdown → HTML renderer</td></tr><tr><td><code>src/render-card.ts</code></td><td>the card — identity + this file + memory + discovery, as one HTML page</td></tr><tr><td><code>src/memory.ts</code> → <code>src/faf/parse-fafm.ts</code></td><td>file-backed <code>remember</code> / <code>recall</code> / <code>forget</code></td></tr><tr><td><code>src/identity.ts</code></td><td><code>whoami</code> (<code>.fafa</code> → <code>package.json</code> fallback) + the <code>_meta</code> context block</td></tr><tr><td><code>src/catalog-gen.ts</code></td><td>writes <code>.well-known/ai-catalog.json</code> from the same three sources</td></tr><tr><td><code>src/transport/http.ts</code></td><td>the stateless Streamable HTTP app (Hono)</td></tr><tr><td><code>src/bin.ts</code></td><td>the entry point (<code>resolveLaunch</code>) — <code>stdio</code> · <code>--http</code> · <code>card</code> · <code>--help</code> · <code>--version</code></td></tr><tr><td><code>src/faf/parse-fafm.ts</code> · <code>parse-fafa.ts</code></td><td>the <code>.fafm</code> / <code>.fafa</code> parsers</td></tr></tbody></table></div></details><details class="ctx-section" id="conventions"><summary>Conventions</summary><div class="md"><ul><li>TypeScript strict, ESM only (<code>&quot;type&quot;: &quot;module&quot;</code>, <code>.js</code> import specifiers).</li><li>Tests use <code>node:test</code> + <code>node:assert/strict</code> — no test framework.</li><li>Every source file opens with a comment stating what it is and why.</li><li>Conventional Commit messages (<code>feat:</code>, <code>fix:</code>, <code>chore:</code>, <code>test:</code>, <code>docs:</code>).</li></ul></div></details><details class="ctx-section" id="the-invariant"><summary>The invariant</summary><div class="md"><p><code>src/identity.ts</code>, <code>src/catalog-gen.ts</code>, and <code>src/render-card.ts</code> all describe the <strong>same three sources</strong>: this file, <code>project.fafm</code>, <code>.well-known/fafa</code>. Change what one exposes and you must change the others. <code>npm run catalog:check</code> and <code>npm run card:check</code> enforce it in CI — each regenerates its surface and fails on any diff.</p></div></details><details class="ctx-section" id="safety"><summary>Safety</summary><div class="md"><ul><li>Branch off <code>main</code>; CI must be green before merge.</li><li><code>npm run demo</code> writes a fact to <code>project.fafm</code> and restores the file on exit — don't kill it mid-run.</li><li>No secrets live in this repo; never add any.</li></ul></div></details><details class="ctx-section" id="definition-of-done"><summary>Definition of done</summary><div class="md"><p><code>npm run typecheck &amp;&amp; npm run build &amp;&amp; npm test &amp;&amp; npm run demo</code> all green, plus <code>npm run catalog:check</code> and <code>npm run card:check</code> clean if you touched <code>AGENTS.md</code>, <code>project.fafm</code>, or <code>.well-known/fafa</code>, and <code>npm run faf:check</code> green if you changed the layout, a dependency, or the identity. On a version bump, <code>npm run version:check</code> green (it lists every spot that must move together) and <code>project.faf</code> still Trophy (<code>faf-cli check project.faf --strict</code>). If CI's <code>faf:nudge</code> warns on your PR, reconcile <code>project.faf</code> (and re-check <code>project.fafm</code> facts if <code>AGENTS.md</code> moved) or say why it's fine.</p></div></details><details class="ctx-section" id="authoring-this-file"><summary>Authoring this file</summary><div class="md"><p><code>AGENTS.md</code> here is maintained by hand. The <code>author_agents_md</code> tool (or <code>faf export --agents</code>) would draft a BEST version straight from this repo's own <code>project.faf</code> plus its detected facts — the server doesn't care how the file was authored, only that it's valid Markdown.</p></div></details></div>
112
118
  </section>
113
119
  <section>
114
120
  <p class="label">Memory — 4 facts</p>
@@ -124,5 +130,25 @@ npm run faf:check # project.faf / project.fafm / .well-known/fafa still desc
124
130
  </section>
125
131
  <div class="foot">mcp-context-card · context card</div>
126
132
  </main>
133
+ <script>
134
+ (function(){
135
+ var btn=document.querySelector(".xall");
136
+ var secs=[].slice.call(document.querySelectorAll("details.ctx-section"));
137
+ if(!btn||!secs.length)return;
138
+ var sync=function(){btn.textContent=secs.every(function(d){return d.open})?"Collapse all":"Expand all"};
139
+ btn.hidden=false;
140
+ btn.addEventListener("click",function(){
141
+ var open=!secs.every(function(d){return d.open});
142
+ secs.forEach(function(d){d.open=open});sync();
143
+ });
144
+ secs.forEach(function(d){d.addEventListener("toggle",sync)});
145
+ var openHash=function(){var d=document.getElementById(location.hash.slice(1));if(d&&d.tagName==="DETAILS")d.open=true};
146
+ addEventListener("hashchange",openHash);openHash();
147
+ var pre=[];
148
+ addEventListener("beforeprint",function(){pre=secs.map(function(d){return d.open});secs.forEach(function(d){d.open=true})});
149
+ addEventListener("afterprint",function(){secs.forEach(function(d,i){d.open=pre[i]});sync()});
150
+ sync();
151
+ })();
152
+ </script>
127
153
  </body>
128
154
  </html>
Binary file
Binary file
Binary file
package/docs/index.html CHANGED
@@ -30,7 +30,7 @@ body{margin:0;background:var(--bg);color:var(--fg);
30
30
  font:15px/1.6 -apple-system,BlinkMacSystemFont,"Segoe UI",Roboto,Helvetica,Arial,sans-serif;
31
31
  padding:40px 18px}
32
32
  .card{max-width:760px;margin:0 auto;background:var(--card);border:1px solid var(--line);
33
- border-radius:14px;overflow:hidden;box-shadow:var(--card-shadow)}
33
+ border-radius:14px;overflow:clip;box-shadow:var(--card-shadow)}
34
34
  .card>*{padding:26px 30px}
35
35
  .top{border-top:4px solid var(--accent);border-bottom:1px solid var(--line)}
36
36
  h1{margin:0 0 10px;font-size:1.7rem;letter-spacing:-.02em}
@@ -41,9 +41,31 @@ section{border-bottom:1px solid var(--line)}
41
41
  section:last-child{border-bottom:0}
42
42
  .label{font-size:.7rem;font-weight:700;letter-spacing:.16em;text-transform:uppercase;
43
43
  color:var(--accent);margin:0 0 14px}
44
- .toc{display:flex;flex-wrap:wrap;gap:6px 14px;margin:0 0 20px;padding:0;list-style:none}
44
+ .toc{display:flex;flex-wrap:wrap;gap:6px 14px;margin:0;padding:0;list-style:none}
45
45
  .toc a{font-size:.82rem;color:var(--muted);text-decoration:none}
46
46
  .toc a:hover{color:var(--accent)}
47
+ /* ── collapsible context ─────────────────────────────────────────── */
48
+ .ctx-nav{position:sticky;top:0;z-index:3;background:var(--card);
49
+ margin:0 -30px 16px;padding:11px 30px;border-bottom:1px solid var(--line);
50
+ display:flex;flex-wrap:wrap;align-items:flex-start;gap:8px 16px}
51
+ .xall{margin-left:auto;flex:none;font:inherit;font-size:.76rem;font-weight:600;
52
+ white-space:nowrap;padding:3px 11px;border-radius:20px;border:1px solid var(--line);
53
+ background:var(--chip);color:var(--muted);cursor:pointer}
54
+ .xall:hover{color:var(--accent);border-color:var(--accent)}
55
+ .ctx-preamble{padding-bottom:4px}
56
+ details.ctx-section{border-top:1px solid var(--line)}
57
+ details.ctx-section>summary{cursor:pointer;list-style:none;padding:11px 0;
58
+ font-weight:600;font-size:1rem;letter-spacing:-.01em;display:flex;gap:9px}
59
+ details.ctx-section>summary::-webkit-details-marker{display:none}
60
+ details.ctx-section>summary::before{content:"›";color:var(--accent);font-weight:700;
61
+ transition:transform .15s ease}
62
+ details.ctx-section[open]>summary::before{transform:rotate(90deg)}
63
+ details.ctx-section>.md{padding:0 0 16px}
64
+ @media print{
65
+ .ctx-nav{display:none}
66
+ details.ctx-section:not([open])>.md{display:block!important}
67
+ details.ctx-section>summary::before{content:""}
68
+ }
47
69
  .md h1,.md h2,.md h3,.md h4{margin:22px 0 8px;font-size:1rem;letter-spacing:-.01em}
48
70
  .md h1{font-size:1.15rem}
49
71
  .md p{margin:8px 0}
@@ -78,37 +100,21 @@ section:last-child{border-bottom:0}
78
100
  <main class="card">
79
101
  <div class="top">
80
102
  <h1>mcp-context-card</h1>
81
- <div class="pills"><span class="pill">io.github.Wolfe-Jam</span><span class="pill">v1.0.1</span><span class="pill accent">published</span><span class="pill">MIT</span></div>
103
+ <div class="pills"><span class="pill">io.github.Wolfe-Jam</span><span class="pill">v1.1.1</span><span class="pill accent">published</span><span class="pill">MIT</span></div>
82
104
  </div>
83
105
  <section>
84
106
  <p class="label">Context — AGENTS.md</p>
85
- <ul class="toc"><li><a href="#setup">Setup</a></li><li><a href="#build">Build</a></li><li><a href="#test">Test</a></li><li><a href="#layout">Layout</a></li><li><a href="#conventions">Conventions</a></li><li><a href="#the-invariant">The invariant</a></li><li><a href="#safety">Safety</a></li><li><a href="#definition-of-done">Definition of done</a></li><li><a href="#authoring-this-file">Authoring this file</a></li></ul><div class="md"><p><code>mcp-context-card</code> is the essential MCP server for a project's <strong>context</strong> (this file), <strong>memory</strong>, and <strong>identity</strong> — usable as your base MCP, or dropped into any existing MCP server as an extension. Discoverable to any MCP client through the two surfaces already in the ecosystem: the Server Card <code>_meta</code> block and <code>ai-catalog.json</code> sibling entries.</p>
86
- <p><code>read_agents_md</code> serves this file, section by section, over the same MCP connection.</p>
87
- <h2 id="setup">Setup</h2>
88
- <pre><code class="language-bash">npm ci</code></pre>
89
- <p>Node 22 or newer. No other system dependencies.</p>
90
- <h2 id="build">Build</h2>
91
- <pre><code class="language-bash">npm run build # tsc -p tsconfig.build.json → dist/
92
- npm run typecheck # tsc --noEmit over src/ + test/</code></pre>
93
- <h2 id="test">Test</h2>
94
- <pre><code class="language-bash">npm test # node:test — every test/*.test.ts
107
+ <div class="ctx-nav"><ul class="toc"><li><a href="#setup">Setup</a></li><li><a href="#build">Build</a></li><li><a href="#test">Test</a></li><li><a href="#layout">Layout</a></li><li><a href="#conventions">Conventions</a></li><li><a href="#the-invariant">The invariant</a></li><li><a href="#safety">Safety</a></li><li><a href="#definition-of-done">Definition of done</a></li><li><a href="#authoring-this-file">Authoring this file</a></li></ul><button type="button" class="xall" hidden>Expand all</button></div>
108
+ <div class="ctx-preamble md"><p><code>mcp-context-card</code> is the essential MCP server for a project's <strong>context</strong> (this file), <strong>memory</strong>, and <strong>identity</strong> — usable as your base MCP, or dropped into any existing MCP server as an extension. Discoverable to any MCP client through the two surfaces already in the ecosystem: the Server Card <code>_meta</code> block and <code>ai-catalog.json</code> sibling entries.</p>
109
+ <p><code>read_agents_md</code> serves this file, section by section, over the same MCP connection.</p></div>
110
+ <div class="ctx-body"><details class="ctx-section" id="setup"><summary>Setup</summary><div class="md"><pre><code class="language-bash">npm ci</code></pre>
111
+ <p>Node 20 or newer. No other system dependencies.</p></div></details><details class="ctx-section" id="build"><summary>Build</summary><div class="md"><pre><code class="language-bash">npm run build # tsc -p tsconfig.build.json → dist/
112
+ npm run typecheck # tsc --noEmit over src/ + test/</code></pre></div></details><details class="ctx-section" id="test"><summary>Test</summary><div class="md"><pre><code class="language-bash">npm test # node:test — every test/*.test.ts
95
113
  npm run test:coverage # + the coverage gate (lines 90 / funcs 85 / branches 80, src/ only)
96
114
  npm run demo # end to end: all tools over stdio, then over stateless HTTP
97
115
  npm run version:check # every version-bearing spot agrees with package.json
98
116
  npm run faf:check # project.faf / project.fafm / .well-known/fafa still describe the project</code></pre>
99
- <p>CI runs <code>version:check → faf:check → typecheck → build → test:coverage → demo</code> on Linux, macOS, and Windows for every push and PR to <code>main</code> (<code>.github/workflows/ci.yml</code>), plus <code>catalog:check</code> / <code>card:check</code>, <code>faf-cli check project.faf --strict</code> (the repo dogfoods a <code>project.faf</code> — this keeps it Trophy), and <code>faf:nudge</code> (PR-only, non-blocking — warns if the code's shape moved without <code>project.faf</code>) on Linux.</p>
100
- <h2 id="layout">Layout</h2>
101
- <table><thead><tr><th>Path</th><th>What</th></tr></thead><tbody><tr><td><code>src/server.ts</code></td><td>the MCP server — the nine tools + the Server Card resource</td></tr><tr><td><code>src/agents-md.ts</code></td><td>reads and section-splits this file</td></tr><tr><td><code>src/author.ts</code></td><td><code>author_agents_md</code> — BETTER via <code>agents-md-facts</code>, BEST when <code>project.faf</code> exists</td></tr><tr><td><code>src/md.ts</code></td><td>a minimal dependency-free Markdown → HTML renderer</td></tr><tr><td><code>src/render-card.ts</code></td><td>the card — identity + this file + memory + discovery, as one HTML page</td></tr><tr><td><code>src/memory.ts</code> → <code>src/faf/parse-fafm.ts</code></td><td>file-backed <code>remember</code> / <code>recall</code> / <code>forget</code></td></tr><tr><td><code>src/identity.ts</code></td><td><code>whoami</code> (<code>.fafa</code> → <code>package.json</code> fallback) + the <code>_meta</code> context block</td></tr><tr><td><code>src/catalog-gen.ts</code></td><td>writes <code>.well-known/ai-catalog.json</code> from the same three sources</td></tr><tr><td><code>src/transport/http.ts</code></td><td>the stateless Streamable HTTP app (Hono)</td></tr><tr><td><code>src/bin.ts</code></td><td>the entry point (<code>resolveLaunch</code>) — <code>stdio</code> · <code>--http</code> · <code>card</code> · <code>--help</code> · <code>--version</code></td></tr><tr><td><code>src/faf/parse-fafm.ts</code> · <code>parse-fafa.ts</code></td><td>the <code>.fafm</code> / <code>.fafa</code> parsers</td></tr></tbody></table>
102
- <h2 id="conventions">Conventions</h2>
103
- <ul><li>TypeScript strict, ESM only (<code>&quot;type&quot;: &quot;module&quot;</code>, <code>.js</code> import specifiers).</li><li>Tests use <code>node:test</code> + <code>node:assert/strict</code> — no test framework.</li><li>Every source file opens with a comment stating what it is and why.</li><li>Conventional Commit messages (<code>feat:</code>, <code>fix:</code>, <code>chore:</code>, <code>test:</code>, <code>docs:</code>).</li></ul>
104
- <h2 id="the-invariant">The invariant</h2>
105
- <p><code>src/identity.ts</code>, <code>src/catalog-gen.ts</code>, and <code>src/render-card.ts</code> all describe the <strong>same three sources</strong>: this file, <code>project.fafm</code>, <code>.well-known/fafa</code>. Change what one exposes and you must change the others. <code>npm run catalog:check</code> and <code>npm run card:check</code> enforce it in CI — each regenerates its surface and fails on any diff.</p>
106
- <h2 id="safety">Safety</h2>
107
- <ul><li>Branch off <code>main</code>; CI must be green before merge.</li><li><code>npm run demo</code> writes a fact to <code>project.fafm</code> and restores the file on exit — don't kill it mid-run.</li><li>No secrets live in this repo; never add any.</li></ul>
108
- <h2 id="definition-of-done">Definition of done</h2>
109
- <p><code>npm run typecheck &amp;&amp; npm run build &amp;&amp; npm test &amp;&amp; npm run demo</code> all green, plus <code>npm run catalog:check</code> and <code>npm run card:check</code> clean if you touched <code>AGENTS.md</code>, <code>project.fafm</code>, or <code>.well-known/fafa</code>, and <code>npm run faf:check</code> green if you changed the layout, a dependency, or the identity. On a version bump, <code>npm run version:check</code> green (it lists every spot that must move together) and <code>project.faf</code> still Trophy (<code>faf-cli check project.faf --strict</code>). If CI's <code>faf:nudge</code> warns on your PR, reconcile <code>project.faf</code> (and re-check <code>project.fafm</code> facts if <code>AGENTS.md</code> moved) or say why it's fine.</p>
110
- <h2 id="authoring-this-file">Authoring this file</h2>
111
- <p><code>AGENTS.md</code> here is maintained by hand. The <code>author_agents_md</code> tool (or <code>faf export --agents</code>) would draft a BEST version straight from this repo's own <code>project.faf</code> plus its detected facts — the server doesn't care how the file was authored, only that it's valid Markdown.</p></div>
117
+ <p>CI runs <code>version:check → faf:check → typecheck → build → test:coverage → demo</code> on Linux, macOS, and Windows for every push and PR to <code>main</code> (<code>.github/workflows/ci.yml</code>), plus <code>catalog:check</code> / <code>card:check</code>, <code>faf-cli check project.faf --strict</code> (the repo dogfoods a <code>project.faf</code> — this keeps it Trophy), and <code>faf:nudge</code> (PR-only, non-blocking — warns if the code's shape moved without <code>project.faf</code>) on Linux.</p></div></details><details class="ctx-section" id="layout"><summary>Layout</summary><div class="md"><table><thead><tr><th>Path</th><th>What</th></tr></thead><tbody><tr><td><code>src/server.ts</code></td><td>the MCP server — the nine tools + the Server Card resource</td></tr><tr><td><code>src/agents-md.ts</code></td><td>reads and section-splits this file</td></tr><tr><td><code>src/author.ts</code></td><td><code>author_agents_md</code> — BETTER via <code>agents-md-facts</code>, BEST when <code>project.faf</code> exists</td></tr><tr><td><code>src/md.ts</code></td><td>a minimal dependency-free Markdown → HTML renderer</td></tr><tr><td><code>src/render-card.ts</code></td><td>the card — identity + this file + memory + discovery, as one HTML page</td></tr><tr><td><code>src/memory.ts</code> → <code>src/faf/parse-fafm.ts</code></td><td>file-backed <code>remember</code> / <code>recall</code> / <code>forget</code></td></tr><tr><td><code>src/identity.ts</code></td><td><code>whoami</code> (<code>.fafa</code> → <code>package.json</code> fallback) + the <code>_meta</code> context block</td></tr><tr><td><code>src/catalog-gen.ts</code></td><td>writes <code>.well-known/ai-catalog.json</code> from the same three sources</td></tr><tr><td><code>src/transport/http.ts</code></td><td>the stateless Streamable HTTP app (Hono)</td></tr><tr><td><code>src/bin.ts</code></td><td>the entry point (<code>resolveLaunch</code>) — <code>stdio</code> · <code>--http</code> · <code>card</code> · <code>--help</code> · <code>--version</code></td></tr><tr><td><code>src/faf/parse-fafm.ts</code> · <code>parse-fafa.ts</code></td><td>the <code>.fafm</code> / <code>.fafa</code> parsers</td></tr></tbody></table></div></details><details class="ctx-section" id="conventions"><summary>Conventions</summary><div class="md"><ul><li>TypeScript strict, ESM only (<code>&quot;type&quot;: &quot;module&quot;</code>, <code>.js</code> import specifiers).</li><li>Tests use <code>node:test</code> + <code>node:assert/strict</code> — no test framework.</li><li>Every source file opens with a comment stating what it is and why.</li><li>Conventional Commit messages (<code>feat:</code>, <code>fix:</code>, <code>chore:</code>, <code>test:</code>, <code>docs:</code>).</li></ul></div></details><details class="ctx-section" id="the-invariant"><summary>The invariant</summary><div class="md"><p><code>src/identity.ts</code>, <code>src/catalog-gen.ts</code>, and <code>src/render-card.ts</code> all describe the <strong>same three sources</strong>: this file, <code>project.fafm</code>, <code>.well-known/fafa</code>. Change what one exposes and you must change the others. <code>npm run catalog:check</code> and <code>npm run card:check</code> enforce it in CI — each regenerates its surface and fails on any diff.</p></div></details><details class="ctx-section" id="safety"><summary>Safety</summary><div class="md"><ul><li>Branch off <code>main</code>; CI must be green before merge.</li><li><code>npm run demo</code> writes a fact to <code>project.fafm</code> and restores the file on exit — don't kill it mid-run.</li><li>No secrets live in this repo; never add any.</li></ul></div></details><details class="ctx-section" id="definition-of-done"><summary>Definition of done</summary><div class="md"><p><code>npm run typecheck &amp;&amp; npm run build &amp;&amp; npm test &amp;&amp; npm run demo</code> all green, plus <code>npm run catalog:check</code> and <code>npm run card:check</code> clean if you touched <code>AGENTS.md</code>, <code>project.fafm</code>, or <code>.well-known/fafa</code>, and <code>npm run faf:check</code> green if you changed the layout, a dependency, or the identity. On a version bump, <code>npm run version:check</code> green (it lists every spot that must move together) and <code>project.faf</code> still Trophy (<code>faf-cli check project.faf --strict</code>). If CI's <code>faf:nudge</code> warns on your PR, reconcile <code>project.faf</code> (and re-check <code>project.fafm</code> facts if <code>AGENTS.md</code> moved) or say why it's fine.</p></div></details><details class="ctx-section" id="authoring-this-file"><summary>Authoring this file</summary><div class="md"><p><code>AGENTS.md</code> here is maintained by hand. The <code>author_agents_md</code> tool (or <code>faf export --agents</code>) would draft a BEST version straight from this repo's own <code>project.faf</code> plus its detected facts — the server doesn't care how the file was authored, only that it's valid Markdown.</p></div></details></div>
112
118
  </section>
113
119
  <section>
114
120
  <p class="label">Memory — 4 facts</p>
@@ -124,5 +130,25 @@ npm run faf:check # project.faf / project.fafm / .well-known/fafa still desc
124
130
  </section>
125
131
  <div class="foot">mcp-context-card · context card</div>
126
132
  </main>
133
+ <script>
134
+ (function(){
135
+ var btn=document.querySelector(".xall");
136
+ var secs=[].slice.call(document.querySelectorAll("details.ctx-section"));
137
+ if(!btn||!secs.length)return;
138
+ var sync=function(){btn.textContent=secs.every(function(d){return d.open})?"Collapse all":"Expand all"};
139
+ btn.hidden=false;
140
+ btn.addEventListener("click",function(){
141
+ var open=!secs.every(function(d){return d.open});
142
+ secs.forEach(function(d){d.open=open});sync();
143
+ });
144
+ secs.forEach(function(d){d.addEventListener("toggle",sync)});
145
+ var openHash=function(){var d=document.getElementById(location.hash.slice(1));if(d&&d.tagName==="DETAILS")d.open=true};
146
+ addEventListener("hashchange",openHash);openHash();
147
+ var pre=[];
148
+ addEventListener("beforeprint",function(){pre=secs.map(function(d){return d.open});secs.forEach(function(d){d.open=true})});
149
+ addEventListener("afterprint",function(){secs.forEach(function(d,i){d.open=pre[i]});sync()});
150
+ sync();
151
+ })();
152
+ </script>
127
153
  </body>
128
154
  </html>
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "mcp-context-card",
3
- "version": "1.0.1",
3
+ "version": "1.1.1",
4
4
  "mcpName": "io.github.Wolfe-Jam/mcp-context-card",
5
5
  "description": "The essential MCP components for a project's context (AGENTS.md), cross-session memory, and identity — a base MCP on its own, or a drop-in extension for any existing MCP server. Discoverable through the Server Card _meta block and ai-catalog.json sibling entries.",
6
6
  "keywords": [
package/server.json CHANGED
@@ -3,7 +3,7 @@
3
3
  "name": "io.github.Wolfe-Jam/mcp-context-card",
4
4
  "title": "mcp-context-card",
5
5
  "description": "MCP server for a project's context (AGENTS.md), memory, and identity — base or drop-in extension.",
6
- "version": "1.0.1",
6
+ "version": "1.1.1",
7
7
  "repository": {
8
8
  "url": "https://github.com/Wolfe-Jam/mcp-context-card",
9
9
  "source": "github"
@@ -13,7 +13,7 @@
13
13
  "registryType": "npm",
14
14
  "registryBaseUrl": "https://registry.npmjs.org",
15
15
  "identifier": "mcp-context-card",
16
- "version": "1.0.1",
16
+ "version": "1.1.1",
17
17
  "runtimeHint": "npx",
18
18
  "transport": {
19
19
  "type": "stdio"