mcp-context-card 0.5.1 → 0.6.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.well-known/ai-catalog.json +2 -2
- package/.well-known/fafa +5 -4
- package/AGENTS.md +11 -9
- package/CHANGELOG.md +87 -9
- package/README.md +82 -49
- package/dist/author.d.ts +11 -2
- package/dist/author.js +73 -14
- package/dist/bin.d.ts +1 -1
- package/dist/card-gen.js +15 -2
- package/dist/constants.d.ts +1 -1
- package/dist/constants.js +1 -1
- package/dist/identity.d.ts +1 -1
- package/dist/identity.js +1 -1
- package/dist/render-card.js +8 -3
- package/dist/server.d.ts +4 -4
- package/dist/server.js +10 -9
- package/dist/transport/http.js +1 -1
- package/docs/MECHANISMS.md +21 -4
- package/docs/TRANSPORT.md +1 -1
- package/docs/WIRING.md +3 -3
- package/docs/card-dark.html +126 -0
- package/docs/card-light.html +126 -0
- package/docs/card.html +12 -7
- package/docs/img/card-context.png +0 -0
- package/docs/img/card-dark.png +0 -0
- package/docs/img/card-identity.png +0 -0
- package/docs/img/card-light.png +0 -0
- package/docs/img/card-memory.png +0 -0
- package/docs/index.html +126 -0
- package/package.json +4 -3
- package/project.faf +6 -6
- package/project.fafm +9 -0
- package/server.json +4 -4
- package/docs/img/card.png +0 -0
|
@@ -18,7 +18,7 @@
|
|
|
18
18
|
"displayName": "mcp-context-card — persistent memory (.fafm)",
|
|
19
19
|
"type": "application/vnd.fafm+yaml",
|
|
20
20
|
"mediaType": "application/vnd.fafm+yaml",
|
|
21
|
-
"description": "Cross-session memory —
|
|
21
|
+
"description": "Cross-session memory — 4 fact(s), profile \"knowledge\". Recall survives a process restart. No de-facto standard for this concern yet.",
|
|
22
22
|
"url": "./project.fafm",
|
|
23
23
|
"_meta": {
|
|
24
24
|
"io.github.wolfe-jam.mcp-context-card/iana": "https://www.iana.org/assignments/media-types/application/vnd.fafm+yaml"
|
|
@@ -29,7 +29,7 @@
|
|
|
29
29
|
"displayName": "mcp-context-card — agent identity (.fafa)",
|
|
30
30
|
"type": "application/vnd.fafa+yaml",
|
|
31
31
|
"mediaType": "application/vnd.fafa+yaml",
|
|
32
|
-
"description": "
|
|
32
|
+
"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 a self-published ai-catalog.json.",
|
|
33
33
|
"url": "./.well-known/fafa",
|
|
34
34
|
"_meta": {
|
|
35
35
|
"io.github.wolfe-jam.mcp-context-card/iana": "https://www.iana.org/assignments/media-types/application/vnd.fafa+yaml"
|
package/.well-known/fafa
CHANGED
|
@@ -9,10 +9,11 @@ agent:
|
|
|
9
9
|
name: "mcp-context-card"
|
|
10
10
|
displayName: "mcp-context-card"
|
|
11
11
|
vendor: "io.github.wolfe-jam"
|
|
12
|
-
version: "0.
|
|
12
|
+
version: "0.6.0"
|
|
13
13
|
description: >-
|
|
14
|
-
|
|
15
|
-
memory, and identity
|
|
16
|
-
|
|
14
|
+
The essential MCP components for a project's context (AGENTS.md),
|
|
15
|
+
cross-session memory, and identity — a base MCP on its own, or a
|
|
16
|
+
drop-in extension for any existing MCP server, discoverable through the
|
|
17
|
+
Server Card _meta block and a self-published ai-catalog.json.
|
|
17
18
|
status: "published"
|
|
18
19
|
license: "MIT"
|
package/AGENTS.md
CHANGED
|
@@ -1,9 +1,10 @@
|
|
|
1
1
|
# AGENTS.md
|
|
2
2
|
|
|
3
|
-
`mcp-context-card` is
|
|
4
|
-
(this file), **memory**, and **identity**
|
|
5
|
-
|
|
6
|
-
|
|
3
|
+
`mcp-context-card` is the essential MCP server for a project's **context**
|
|
4
|
+
(this file), **memory**, and **identity** — usable as your base MCP, or
|
|
5
|
+
dropped into any existing MCP server as an extension. Discoverable to any
|
|
6
|
+
MCP client through the two surfaces already in the ecosystem: the Server
|
|
7
|
+
Card `_meta` block and `ai-catalog.json` sibling entries.
|
|
7
8
|
|
|
8
9
|
`read_agents_md` serves this file, section by section, over the same MCP
|
|
9
10
|
connection.
|
|
@@ -40,14 +41,14 @@ Windows for every push and PR to `main` (`.github/workflows/ci.yml`).
|
|
|
40
41
|
|---|---|
|
|
41
42
|
| `src/server.ts` | the MCP server — the nine tools + the Server Card resource |
|
|
42
43
|
| `src/agents-md.ts` | reads and section-splits this file |
|
|
43
|
-
| `src/author.ts` | `author_agents_md` —
|
|
44
|
+
| `src/author.ts` | `author_agents_md` — BETTER via `agents-md-facts`, BEST when `project.faf` exists |
|
|
44
45
|
| `src/md.ts` | a minimal dependency-free Markdown → HTML renderer |
|
|
45
46
|
| `src/render-card.ts` | the card — identity + this file + memory + discovery, as one HTML page |
|
|
46
47
|
| `src/memory.ts` → `src/faf/parse-fafm.ts` | file-backed `remember` / `recall` / `forget` |
|
|
47
48
|
| `src/identity.ts` | `whoami` (`.fafa` → `package.json` fallback) + the `_meta` context block |
|
|
48
49
|
| `src/catalog-gen.ts` | writes `.well-known/ai-catalog.json` from the same three sources |
|
|
49
50
|
| `src/transport/http.ts` | the stateless Streamable HTTP app (Hono) |
|
|
50
|
-
| `src/bin.ts` | the entry point (`resolveLaunch`) — `stdio` · `--http` · `card` |
|
|
51
|
+
| `src/bin.ts` | the entry point (`resolveLaunch`) — `stdio` · `--http` · `card` · `--help` · `--version` |
|
|
51
52
|
| `src/faf/parse-fafm.ts` · `parse-fafa.ts` | the `.fafm` / `.fafa` parsers |
|
|
52
53
|
|
|
53
54
|
## Conventions
|
|
@@ -80,6 +81,7 @@ plus `npm run catalog:check` and `npm run card:check` clean if you touched
|
|
|
80
81
|
|
|
81
82
|
## Authoring this file
|
|
82
83
|
|
|
83
|
-
`AGENTS.md` here is maintained by hand.
|
|
84
|
-
|
|
85
|
-
|
|
84
|
+
`AGENTS.md` here is maintained by hand. The `author_agents_md` tool (or
|
|
85
|
+
`faf export --agents`) would draft a BEST version straight from this repo's
|
|
86
|
+
own `project.faf` plus its detected facts — the server doesn't care how the
|
|
87
|
+
file was authored, only that it's valid Markdown.
|
package/CHANGELOG.md
CHANGED
|
@@ -2,6 +2,92 @@
|
|
|
2
2
|
|
|
3
3
|
All notable changes to this project. Adheres to [Semantic Versioning](https://semver.org).
|
|
4
4
|
|
|
5
|
+
## 0.6.0
|
|
6
|
+
|
|
7
|
+
The README as a hero, not just a description. Everything visual this repo
|
|
8
|
+
claims is now backed by a real screenshot from the actual rendered card —
|
|
9
|
+
nothing hand-drawn, nothing mocked up.
|
|
10
|
+
|
|
11
|
+
- **The card leads the README** — a side-by-side "Light | Dark" table right
|
|
12
|
+
at the top, instead of one fixed screenshot. Shows the real range to
|
|
13
|
+
every viewer regardless of their own GitHub theme.
|
|
14
|
+
- **Each of the three concerns gets its own proof** — context, memory, and
|
|
15
|
+
identity are each followed by a real crop from the card: the `AGENTS.md`
|
|
16
|
+
section + the `read_agents_md` line, an actual tagged and verified
|
|
17
|
+
memory fact, and the title + pills.
|
|
18
|
+
- **"Pick one"** — a table right after the hero: add an `AGENTS.md`,
|
|
19
|
+
improve one to BEST, get a new MCP server base, or extend an MCP you
|
|
20
|
+
already run. Replaces the old "Who it's for" table.
|
|
21
|
+
- The dark card no longer blends into GitHub's own dark mode — added a
|
|
22
|
+
visible ring plus a soft accent-tinted glow so it reads as a distinct
|
|
23
|
+
card regardless of backdrop.
|
|
24
|
+
- **GitHub Pages, live** — `wolfe-jam.github.io/mcp-context-card/` serves
|
|
25
|
+
the card in auto/light/dark. The GitHub repo's own "Website" field links
|
|
26
|
+
there. `package.json`'s `homepage` is a different field and stays on the
|
|
27
|
+
repo itself — that's where install steps and the tools table live, not a
|
|
28
|
+
bare rendered card.
|
|
29
|
+
- "Vendor-free," not "Not tied to FAF" — dropped a defensive clause nobody
|
|
30
|
+
needed, and reworded the vendor-boundary line to state the property
|
|
31
|
+
without naming a vendor to disclaim against.
|
|
32
|
+
- An external README review caught four real gaps, fixed before publish:
|
|
33
|
+
the identity line said "agent card" — reworded to **Server Card**, the
|
|
34
|
+
term this repo already documents and owns (SEP‑2127), so it can't be read
|
|
35
|
+
as A2A's own, distinctly-specified AgentCard; the "Wire it into a host"
|
|
36
|
+
example now states the Node ≥22 requirement and cross-references the
|
|
37
|
+
documented `npx` `ENOENT` fix (Cursor) instead of leaving it undiscoverable
|
|
38
|
+
until WIRING; `docs/WIRING.md`'s `list_agents_md_sections` example showed
|
|
39
|
+
`sections: 9` — the real, parser-verified count is 10 (it includes the
|
|
40
|
+
`AGENTS.md` H1, not just its nine `##` headings).
|
|
41
|
+
- `docs/MECHANISMS.md` states the A2A position: Server Card is what this
|
|
42
|
+
server has. A2A's AgentCard is a different thing — a live agent, an
|
|
43
|
+
endpoint, skills, auth. We're ready for A2A: the same `.fafa` source
|
|
44
|
+
publishes a real AgentCard alongside it the day a project here is
|
|
45
|
+
reachable over one, not a reshape of `.fafa` itself.
|
|
46
|
+
- Bumped straight to 0.6.0 — 0.5.3 was committed but never published;
|
|
47
|
+
no reason to leave a changelog entry for a version nobody received.
|
|
48
|
+
|
|
49
|
+
No functional change — README, docs, and card assets only. 102 tests,
|
|
50
|
+
typecheck/build/demo clean, `card:check` + `catalog:check` green.
|
|
51
|
+
|
|
52
|
+
## 0.5.2
|
|
53
|
+
|
|
54
|
+
The soak, closed out. Two Cursor host checks — a real bug found and fixed, a
|
|
55
|
+
real gap found and fixed, both confirmed against a real independent MCP host
|
|
56
|
+
on the current build.
|
|
57
|
+
|
|
58
|
+
- **`author_agents_md` now authors BEST, not just BETTER, when it can.**
|
|
59
|
+
BETTER is the facts-only draft from `agents-md-facts` (build/test
|
|
60
|
+
commands, entry points, conventions — nothing invented). **BEST** is that
|
|
61
|
+
plus a `## Project` section ahead of it — goal, who it's for, why, and a
|
|
62
|
+
"start here" file list — read straight from `project.faf` when one
|
|
63
|
+
exists. This is the point of the app: give the best AGENTS.md the
|
|
64
|
+
project has the material for, not a fixed floor. The tool's response
|
|
65
|
+
names the tier it produced.
|
|
66
|
+
- **Fix:** `remember` on a project that had never had a `project.fafm`
|
|
67
|
+
threw `ENOENT` instead of starting one — the single most common
|
|
68
|
+
first-use case. `remember` now creates a fresh `.fafm` on first write;
|
|
69
|
+
`forget` / `parseFafm` were already safe and are unchanged. A real
|
|
70
|
+
child-process e2e test (a cold root, two separate OS processes) makes
|
|
71
|
+
this a permanent regression guard, not just a fix.
|
|
72
|
+
- `docs/WIRING.md`: a note on hosts whose spawn `PATH` lacks `npx`
|
|
73
|
+
(`spawn npx ENOENT`, observed in Cursor) — point `command` at `node` +
|
|
74
|
+
the installed `dist/bin.js` instead.
|
|
75
|
+
- **The README / AGENTS.md / `project.faf` / manifest reframe** — dropped
|
|
76
|
+
"Small, MIT…" / "a piece, not the toolbox" for the real positioning:
|
|
77
|
+
essential context, memory, and identity components, usable as a base MCP
|
|
78
|
+
on their own, or a drop-in extension for any existing MCP server.
|
|
79
|
+
- An accuracy pass across every shipped surface, caught by re-reading
|
|
80
|
+
rather than by any check: stale test/tool counts (README, CHANGELOG,
|
|
81
|
+
and `project.faf`'s own `human_context.what` — it undercounted its own
|
|
82
|
+
tools), 3-release-old version strings sitting in two hand-shown examples
|
|
83
|
+
(`examples/README.md`, `docs/MECHANISMS.md`), a pre-rename
|
|
84
|
+
docker-compose service name (`trinity` → `context-card`), an internal
|
|
85
|
+
function that still carried the pre-rename product name (`trinityMeta` →
|
|
86
|
+
`serverCardMeta` — not a public export). `project.faf` itself rechecked
|
|
87
|
+
against the current architecture (`tech_stack`, `key_files`, `cicd`).
|
|
88
|
+
- 102 tests, coverage gate held, `card:check` / `catalog:check` green,
|
|
89
|
+
`faf-cli check`: ✪ Trophy 100%, 15/15 slots.
|
|
90
|
+
|
|
5
91
|
## 0.5.1
|
|
6
92
|
|
|
7
93
|
First-hour ergonomics and wording, from the 0.5.0 soak.
|
|
@@ -19,14 +105,6 @@ First-hour ergonomics and wording, from the 0.5.0 soak.
|
|
|
19
105
|
to the LICENSE holder.
|
|
20
106
|
- `.well-known/fafa` — `vendor: io.github.wolfe-jam`, `status: published`
|
|
21
107
|
(were both `reference`). Shows in `whoami` and as the card's pills.
|
|
22
|
-
- **Fix:** `remember` on a project that has never had a `project.fafm` threw
|
|
23
|
-
`ENOENT` instead of starting one — the single most common first-use case.
|
|
24
|
-
Found by a real host check (Cursor, 2026-09-04). `remember` now creates a
|
|
25
|
-
fresh `.fafm` on first write; `forget` and `parseFafm` were already safe on
|
|
26
|
-
a missing file and are unchanged in behaviour.
|
|
27
|
-
- `docs/WIRING.md`: a note on hosts whose spawn `PATH` lacks `npx`
|
|
28
|
-
(`spawn npx ENOENT`, observed in Cursor) — point `command` at `node` +
|
|
29
|
-
the installed `dist/bin.js` instead.
|
|
30
108
|
|
|
31
109
|
## 0.5.0
|
|
32
110
|
|
|
@@ -73,7 +151,7 @@ tested server.
|
|
|
73
151
|
|
|
74
152
|
### Engineering
|
|
75
153
|
|
|
76
|
-
-
|
|
154
|
+
- 90 tests across Linux / macOS / Windows, coverage-gated
|
|
77
155
|
(lines 90 / funcs 85 / branches 80, `src/` only). A real `child_process`
|
|
78
156
|
spawn proves memory across a genuine process boundary; stdio/HTTP
|
|
79
157
|
tool-surface parity is asserted.
|
package/README.md
CHANGED
|
@@ -3,44 +3,73 @@
|
|
|
3
3
|
[](https://github.com/Wolfe-Jam/mcp-context-card/actions/workflows/ci.yml)
|
|
4
4
|
[](./LICENSE)
|
|
5
5
|
|
|
6
|
-
|
|
7
|
-
|
|
6
|
+
**Get one. Or add it to yours.** The essential MCP server for a project's
|
|
7
|
+
context, memory, and identity — discoverable to any MCP client, and
|
|
8
|
+
rendered as one card you can read.
|
|
8
9
|
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
10
|
+
| Light | Dark |
|
|
11
|
+
|---|---|
|
|
12
|
+
|  |  |
|
|
13
|
+
|
|
14
|
+
**context** — the project's `AGENTS.md`, served whole or one section at a time.
|
|
15
|
+
|
|
16
|
+

|
|
17
|
+
|
|
18
|
+
**memory** — facts that persist across sessions, in a file.
|
|
19
|
+
|
|
20
|
+

|
|
21
|
+
|
|
22
|
+
**identity** — what this server is, from its own Server Card.
|
|
23
|
+
|
|
24
|
+

|
|
12
25
|
|
|
13
26
|
Discovery goes through two surfaces already in the ecosystem: the Server Card
|
|
14
27
|
`_meta` block and `ai-catalog.json` sibling entries.
|
|
15
28
|
|
|
16
|
-
##
|
|
29
|
+
## Pick one
|
|
30
|
+
|
|
31
|
+
| You want to… | |
|
|
32
|
+
|---|---|
|
|
33
|
+
| **Add an `AGENTS.md`** — you don't have one | `author_agents_md` drafts one from your repo's real facts |
|
|
34
|
+
| **Improve an `AGENTS.md`** — you have one, make it the best it can be | the same tool, automatically — drop in a `project.faf` and it upgrades to BEST: goal, who it's for, why |
|
|
35
|
+
| **Get a new MCP server base** — context, memory, identity, wired | stand this up as-is; a host has all three before you write a tool of your own |
|
|
36
|
+
| **Improve your MCP with context, memory, ID** — you already run one | run it alongside your existing server; nothing to migrate, it composes |
|
|
37
|
+
|
|
38
|
+
## A base MCP — or an extension for any other
|
|
17
39
|
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
40
|
+
Context, memory, and identity are essential — every MCP host needs an agent
|
|
41
|
+
that knows a project's instructions, remembers facts across sessions, and can
|
|
42
|
+
say what it is. `mcp-context-card` is those three, done once:
|
|
21
43
|
|
|
22
|
-
**
|
|
44
|
+
- **Stand it up as your base MCP.** Point a host at it and an agent already
|
|
45
|
+
has `AGENTS.md` served section‑by‑section, `remember` / `recall` / `forget`
|
|
46
|
+
memory that survives a restart, and a `whoami` identity — before a single
|
|
47
|
+
tool of your own is written.
|
|
48
|
+
- **Or extend any existing MCP with it.** Run it alongside a server you
|
|
49
|
+
already have — filesystem, git, a database, your own — and that agent
|
|
50
|
+
gains context, memory, and identity discovery it didn't have. Nothing to
|
|
51
|
+
migrate; it composes.
|
|
23
52
|
|
|
24
|
-
|
|
25
|
-
-
|
|
26
|
-
- tied to FAF — context is plain Markdown (`AGENTS.md`); the memory and identity
|
|
27
|
-
formats are swappable examples
|
|
53
|
+
Nine tools, two discovery surfaces already in the ecosystem (Server Card
|
|
54
|
+
`_meta`, `ai-catalog.json`), and a rendered [card](#the-card). MIT, on npm.
|
|
28
55
|
|
|
29
56
|
It composes:
|
|
30
57
|
|
|
31
58
|
- **serve · discover · render** — this server
|
|
32
|
-
- **author
|
|
59
|
+
- **author BETTER, keep true** — [`agents-md-facts`](https://github.com/Wolfe-Jam/agents-md-facts) (`author_agents_md` wraps it for the facts layer; adds a BEST layer of its own from `project.faf` when one exists)
|
|
33
60
|
- **files · shell · git** — [`server-filesystem`](https://github.com/modelcontextprotocol/servers), [`server-git`](https://github.com/modelcontextprotocol/servers) / github‑mcp‑server, your test runner's MCP
|
|
34
61
|
|
|
35
|
-
|
|
62
|
+
Vendor-free — context is plain Markdown (`AGENTS.md`); the memory and
|
|
63
|
+
identity formats are swappable examples. It reads and writes only its own
|
|
64
|
+
three files (`AGENTS.md`, `project.fafm`, `.well-known/fafa`) — no general
|
|
65
|
+
file access, no shell, no search.
|
|
36
66
|
|
|
37
67
|
## The card
|
|
38
68
|
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
screenshot it, drop it in a PR, put it on a status page.
|
|
69
|
+
The screenshot at the top of this page is exactly this — the same three
|
|
70
|
+
sources rendered as one self‑contained HTML page: identity, `AGENTS.md`,
|
|
71
|
+
memory, and how a machine fetches it. The view for people: screenshot it,
|
|
72
|
+
drop it in a PR, put it on a status page.
|
|
44
73
|
|
|
45
74
|
```
|
|
46
75
|
GET /card # live, on the HTTP transport
|
|
@@ -49,36 +78,30 @@ npx mcp-context-card card # or: npm run card → docs/card.html
|
|
|
49
78
|
```
|
|
50
79
|
|
|
51
80
|
Light, dark, or auto; the accent defaults to the AAIF palette and takes any hex.
|
|
52
|
-
[
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
| You want… | Reach for |
|
|
57
|
-
|---|---|
|
|
58
|
-
| an `AGENTS.md` and you don't have one | `author_agents_md` — or [`npx agents-md-facts`](https://github.com/Wolfe-Jam/agents-md-facts) |
|
|
59
|
-
| your agent to pull *one* `AGENTS.md` section on demand, not the whole file | `read_agents_md` · `list_agents_md_sections` |
|
|
60
|
-
| a persistent notepad for your agent — survives restarts, no setup | `remember` · `recall` · `forget` |
|
|
61
|
-
| a shareable view of what your MCP server exposes to agents | `GET /card` · `npx mcp-context-card card` |
|
|
62
|
-
| the two‑surface discovery pattern to copy into your own server | read `src/` |
|
|
81
|
+
This repo's own card, live: [auto](https://wolfe-jam.github.io/mcp-context-card/) ·
|
|
82
|
+
[light](https://wolfe-jam.github.io/mcp-context-card/card-light.html) ·
|
|
83
|
+
[dark](https://wolfe-jam.github.io/mcp-context-card/card-dark.html)
|
|
84
|
+
(all in the AAIF accent shown here — pass any hex to change it).
|
|
63
85
|
|
|
64
86
|
## Add it to your setup
|
|
65
87
|
|
|
66
88
|
### No `AGENTS.md` yet?
|
|
67
89
|
|
|
68
|
-
The `author_agents_md` tool authors one from your repo's
|
|
69
|
-
build/test commands, entry points, toolchain conventions
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
90
|
+
The `author_agents_md` tool authors one — **BETTER** from your repo's real
|
|
91
|
+
facts (build/test commands, entry points, toolchain conventions, via
|
|
92
|
+
[`agents-md-facts`](https://github.com/Wolfe-Jam/agents-md-facts)), or
|
|
93
|
+
**BEST** when a `project.faf` exists: the same facts, plus its structured
|
|
94
|
+
goal, who it's for, and why, as a section ahead of them. Nothing to
|
|
95
|
+
configure — the tier follows what's actually there.
|
|
96
|
+
([The ladder this follows.](https://github.com/Wolfe-Jam/agents-md-facts/blob/main/docs/BETTER-BEST.md))
|
|
97
|
+
|
|
98
|
+
To author or keep the facts layer true outside a session:
|
|
73
99
|
|
|
74
100
|
```bash
|
|
75
101
|
npx agents-md-facts # author / refresh AGENTS.md
|
|
76
102
|
npx agents-md-facts --check # fail if missing or stale (CI, pre-commit)
|
|
77
103
|
```
|
|
78
104
|
|
|
79
|
-
A `project.faf` is the next rung — a structured source that refreshes the file.
|
|
80
|
-
Short model: [`agents-md-facts/docs/BETTER-BEST.md`](https://github.com/Wolfe-Jam/agents-md-facts/blob/main/docs/BETTER-BEST.md).
|
|
81
|
-
|
|
82
105
|
### See the card
|
|
83
106
|
|
|
84
107
|
One command, no host, no config:
|
|
@@ -105,9 +128,18 @@ Claude Desktop, Cursor, or any stdio host:
|
|
|
105
128
|
|
|
106
129
|
`MCP_CONTEXT_CARD_ROOT` points at the directory with your `AGENTS.md`. The
|
|
107
130
|
memory tools work with or without it; identity is optional. Over HTTP instead:
|
|
108
|
-
`PORT=8080 npx mcp-context-card`.
|
|
109
|
-
|
|
110
|
-
|
|
131
|
+
`PORT=8080 npx mcp-context-card`. Requires Node ≥22.
|
|
132
|
+
|
|
133
|
+
If `command: "npx"` fails to spawn (`spawn npx ENOENT` — seen on Cursor, whose
|
|
134
|
+
host process doesn't inherit a shell `PATH`), point `command` at `node` and
|
|
135
|
+
the installed `dist/bin.js` instead — see
|
|
136
|
+
[docs/WIRING.md](./docs/WIRING.md#1-running-it-in-a-host). Transport choice is
|
|
137
|
+
in [docs/TRANSPORT.md](./docs/TRANSPORT.md).
|
|
138
|
+
|
|
139
|
+
Extending an MCP you already run: most hosts accept more than one
|
|
140
|
+
`mcpServers` entry — add `context-card` alongside `server-filesystem`,
|
|
141
|
+
`server-git`, or your own, and every agent in that host gains context,
|
|
142
|
+
memory, and identity discovery without anything else changing.
|
|
111
143
|
|
|
112
144
|
## Why
|
|
113
145
|
|
|
@@ -137,7 +169,7 @@ The wire‑level detail is in [docs/MECHANISMS.md](./docs/MECHANISMS.md).
|
|
|
137
169
|
|
|
138
170
|
| Tool | What it's for |
|
|
139
171
|
|---|---|
|
|
140
|
-
| `author_agents_md` | draft an `AGENTS.md` from the repo's facts (via `agents-md-facts`)
|
|
172
|
+
| `author_agents_md` | draft an `AGENTS.md` — BETTER from the repo's facts (via `agents-md-facts`), BEST when a `project.faf` exists — ready to drop in |
|
|
141
173
|
| `read_agents_md` | return the project's `AGENTS.md` — whole, or one section by heading |
|
|
142
174
|
| `list_agents_md_sections` | the headings, so a client pulls one section instead of the whole file |
|
|
143
175
|
| `remember` | write a fact that will still be there next session |
|
|
@@ -159,9 +191,10 @@ The wire‑level detail is in [docs/MECHANISMS.md](./docs/MECHANISMS.md).
|
|
|
159
191
|
4. **Discovery** — `list_context_sources()`, then the same server over stateless
|
|
160
192
|
HTTP with its `.well-known` routes and `GET /card`.
|
|
161
193
|
|
|
162
|
-
|
|
163
|
-
child process and
|
|
164
|
-
|
|
194
|
+
102 tests on Linux, macOS, and Windows, coverage‑gated in CI. Two spawn a real
|
|
195
|
+
child process and check a remembered fact survives the restart — one against
|
|
196
|
+
an existing `project.fafm`, one starting from a project that has never had
|
|
197
|
+
one; another checks the stdio and HTTP tool surfaces match.
|
|
165
198
|
|
|
166
199
|
## Layout
|
|
167
200
|
|
|
@@ -169,14 +202,14 @@ the stdio and HTTP tool surfaces match.
|
|
|
169
202
|
|---|---|
|
|
170
203
|
| `src/server.ts` | the nine tools + the Server Card resource |
|
|
171
204
|
| `src/agents-md.ts` | reads and section‑splits `AGENTS.md` |
|
|
172
|
-
| `src/author.ts` | `author_agents_md` —
|
|
205
|
+
| `src/author.ts` | `author_agents_md` — BETTER via [`agents-md-facts`](https://github.com/Wolfe-Jam/agents-md-facts), BEST when `project.faf` exists |
|
|
173
206
|
| `src/md.ts` | a minimal dependency‑free Markdown → HTML renderer |
|
|
174
207
|
| `src/render-card.ts` | the card — identity + `AGENTS.md` + memory + discovery, as one HTML page |
|
|
175
208
|
| `src/memory.ts` | file‑backed `remember` / `recall` / `forget` |
|
|
176
209
|
| `src/identity.ts` | `whoami` (`.fafa` → `package.json` fallback) + the `_meta` block |
|
|
177
210
|
| `src/catalog-gen.ts` | writes `ai-catalog.json` from the same three sources |
|
|
178
211
|
| `src/transport/http.ts` | the stateless Streamable HTTP app (Hono) |
|
|
179
|
-
| `src/bin.ts` | the entry point — `stdio` · `--http` · `card` |
|
|
212
|
+
| `src/bin.ts` | the entry point — `stdio` · `--http` · `card` · `--help` · `--version` |
|
|
180
213
|
|
|
181
214
|
## Related
|
|
182
215
|
|
package/dist/author.d.ts
CHANGED
|
@@ -1,11 +1,20 @@
|
|
|
1
1
|
/** The markers `agents-md-facts` uses to bound its managed block. */
|
|
2
2
|
export declare const BLOCK_START = "<!-- agents:from-facts:start -->";
|
|
3
3
|
export declare const BLOCK_END = "<!-- agents:from-facts:end -->";
|
|
4
|
+
/** The markers this file uses to bound the project.faf-sourced intent block. */
|
|
5
|
+
export declare const FAF_BLOCK_START = "<!-- context:from-faf:start -->";
|
|
6
|
+
export declare const FAF_BLOCK_END = "<!-- context:from-faf:end -->";
|
|
4
7
|
export interface Authored {
|
|
5
|
-
/** the AGENTS.md text —
|
|
8
|
+
/** the AGENTS.md text — one or two managed blocks, ready to drop in */
|
|
6
9
|
markdown: string;
|
|
7
10
|
/** whether an AGENTS.md already exists at the target */
|
|
8
11
|
exists: boolean;
|
|
12
|
+
/** which tier was authored — BEST only when a readable project.faf was found */
|
|
13
|
+
tier: "better" | "best";
|
|
9
14
|
}
|
|
10
|
-
/**
|
|
15
|
+
/**
|
|
16
|
+
* Author AGENTS.md for `root`. BETTER from repo facts alone; BEST — facts
|
|
17
|
+
* plus the project.faf intent block, ahead of it — when a project.faf with
|
|
18
|
+
* real content exists.
|
|
19
|
+
*/
|
|
11
20
|
export declare function authorAgentsMd(root: string): Authored;
|
package/dist/author.js
CHANGED
|
@@ -1,27 +1,86 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* author — author an AGENTS.md for a project
|
|
2
|
+
* author — author an AGENTS.md for a project, at the tier the project earns.
|
|
3
3
|
*
|
|
4
|
-
*
|
|
5
|
-
*
|
|
6
|
-
*
|
|
7
|
-
* markers so `agents-md-facts --check` (or its Action / pre-commit hook) can
|
|
8
|
-
* keep the result true afterwards.
|
|
4
|
+
* BETTER: the engine is `agents-md-facts` (a published, standalone tool) —
|
|
5
|
+
* it detects real build/test commands, entry points, toolchain conventions
|
|
6
|
+
* and nothing invented. Every project gets at least this.
|
|
9
7
|
*
|
|
10
|
-
*
|
|
11
|
-
*
|
|
12
|
-
*
|
|
8
|
+
* BEST: when `project.faf` exists, its structured intent — goal, who it's
|
|
9
|
+
* for, why it exists, the files that matter most — is real, human-authored
|
|
10
|
+
* truth that no amount of repo-scanning can detect. A project with a
|
|
11
|
+
* `project.faf` gets BOTH: the facts block, unchanged, plus this intent as
|
|
12
|
+
* its own managed block ahead of it. This is the whole point of the app:
|
|
13
|
+
* give the BEST AGENTS.md when the structured source to build it from is
|
|
14
|
+
* sitting right there.
|
|
13
15
|
*/
|
|
14
|
-
import { existsSync } from "node:fs";
|
|
16
|
+
import { existsSync, readFileSync } from "node:fs";
|
|
15
17
|
import { join } from "node:path";
|
|
18
|
+
import { parse } from "yaml";
|
|
16
19
|
import { authorAgentsMd as authorBlock, buildRepoContext } from "agents-md-facts";
|
|
17
20
|
/** The markers `agents-md-facts` uses to bound its managed block. */
|
|
18
21
|
export const BLOCK_START = "<!-- agents:from-facts:start -->";
|
|
19
22
|
export const BLOCK_END = "<!-- agents:from-facts:end -->";
|
|
20
|
-
/**
|
|
23
|
+
/** The markers this file uses to bound the project.faf-sourced intent block. */
|
|
24
|
+
export const FAF_BLOCK_START = "<!-- context:from-faf:start -->";
|
|
25
|
+
export const FAF_BLOCK_END = "<!-- context:from-faf:end -->";
|
|
26
|
+
/** Read the structured intent out of `root`'s project.faf, or null if there isn't one to read. */
|
|
27
|
+
function readFafIntent(root) {
|
|
28
|
+
const path = join(root, "project.faf");
|
|
29
|
+
if (!existsSync(path))
|
|
30
|
+
return null;
|
|
31
|
+
try {
|
|
32
|
+
const doc = (parse(readFileSync(path, "utf8")) ?? {});
|
|
33
|
+
const project = doc.project ?? {};
|
|
34
|
+
const humanContext = doc.human_context ?? {};
|
|
35
|
+
const intent = {
|
|
36
|
+
name: str(project.name),
|
|
37
|
+
goal: str(project.goal),
|
|
38
|
+
who: str(humanContext.who),
|
|
39
|
+
why: str(humanContext.why),
|
|
40
|
+
keyFiles: Array.isArray(doc.key_files) ? doc.key_files.map(String).filter(Boolean) : undefined,
|
|
41
|
+
};
|
|
42
|
+
// A .faf with nothing usable in it isn't a real intent source.
|
|
43
|
+
return intent.goal || intent.who || intent.why ? intent : null;
|
|
44
|
+
}
|
|
45
|
+
catch {
|
|
46
|
+
return null;
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
function str(v) {
|
|
50
|
+
const s = typeof v === "string" ? v.trim() : "";
|
|
51
|
+
return s || undefined;
|
|
52
|
+
}
|
|
53
|
+
/** Render the project.faf-sourced intent as its own managed block. */
|
|
54
|
+
function fafIntentBlock(intent) {
|
|
55
|
+
const lines = ["## Project", ""];
|
|
56
|
+
if (intent.goal)
|
|
57
|
+
lines.push(intent.goal, "");
|
|
58
|
+
if (intent.who)
|
|
59
|
+
lines.push(`**Who it's for:** ${intent.who}`, "");
|
|
60
|
+
if (intent.why)
|
|
61
|
+
lines.push(`**Why:** ${intent.why}`, "");
|
|
62
|
+
if (intent.keyFiles?.length) {
|
|
63
|
+
lines.push("**Start here:**", "");
|
|
64
|
+
for (const f of intent.keyFiles)
|
|
65
|
+
lines.push(`- \`${f}\``);
|
|
66
|
+
lines.push("");
|
|
67
|
+
}
|
|
68
|
+
return `${FAF_BLOCK_START}\n${lines.join("\n").trimEnd()}\n${FAF_BLOCK_END}\n`;
|
|
69
|
+
}
|
|
70
|
+
/**
|
|
71
|
+
* Author AGENTS.md for `root`. BETTER from repo facts alone; BEST — facts
|
|
72
|
+
* plus the project.faf intent block, ahead of it — when a project.faf with
|
|
73
|
+
* real content exists.
|
|
74
|
+
*/
|
|
21
75
|
export function authorAgentsMd(root) {
|
|
22
|
-
const
|
|
76
|
+
const factsBlock = `${BLOCK_START}\n${authorBlock(buildRepoContext(root)).trim()}\n${BLOCK_END}\n`;
|
|
77
|
+
const exists = existsSync(join(root, "AGENTS.md"));
|
|
78
|
+
const intent = readFafIntent(root);
|
|
79
|
+
if (!intent)
|
|
80
|
+
return { markdown: factsBlock, exists, tier: "better" };
|
|
23
81
|
return {
|
|
24
|
-
markdown: `${
|
|
25
|
-
exists
|
|
82
|
+
markdown: `${fafIntentBlock(intent)}\n${factsBlock}`,
|
|
83
|
+
exists,
|
|
84
|
+
tier: "best",
|
|
26
85
|
};
|
|
27
86
|
}
|
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 0.
|
|
11
|
+
export declare const HELP = "mcp-context-card 0.6.0\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 [> f.html] render this directory's context card to stdout\n --theme light|dark --accent #hex\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` or `--http` to see output directly.\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/card-gen.js
CHANGED
|
@@ -2,6 +2,15 @@
|
|
|
2
2
|
* card-gen - write docs/card.html from the three sources, so the card is
|
|
3
3
|
* browsable on GitHub and screenshot-able for the README. Same renderer as
|
|
4
4
|
* GET /card and the render_context_card tool.
|
|
5
|
+
*
|
|
6
|
+
* Also writes two theme-pinned siblings (docs/card-light.html,
|
|
7
|
+
* docs/card-dark.html) — docs/card.html stays "auto" (follows the viewer's
|
|
8
|
+
* OS preference); the two siblings are for linking a forced theme from the
|
|
9
|
+
* README, since a static host can't answer a `?theme=` query param.
|
|
10
|
+
*
|
|
11
|
+
* GitHub Pages serves this repo from main /docs (wolfe-jam.github.io/
|
|
12
|
+
* mcp-context-card/) — docs/index.html (a copy of the auto card) is what
|
|
13
|
+
* answers the bare root, so it isn't a 404.
|
|
5
14
|
*/
|
|
6
15
|
import { writeFileSync } from "node:fs";
|
|
7
16
|
import { dirname, join } from "node:path";
|
|
@@ -9,6 +18,10 @@ import { fileURLToPath, pathToFileURL } from "node:url";
|
|
|
9
18
|
import { renderCard } from "./render-card.js";
|
|
10
19
|
if (process.argv[1] && import.meta.url === pathToFileURL(process.argv[1]).href) {
|
|
11
20
|
const root = join(dirname(fileURLToPath(import.meta.url)), "..");
|
|
12
|
-
|
|
13
|
-
|
|
21
|
+
const auto = renderCard(root);
|
|
22
|
+
writeFileSync(join(root, "docs/card.html"), auto);
|
|
23
|
+
writeFileSync(join(root, "docs/index.html"), auto);
|
|
24
|
+
writeFileSync(join(root, "docs/card-light.html"), renderCard(root, { theme: "light" }));
|
|
25
|
+
writeFileSync(join(root, "docs/card-dark.html"), renderCard(root, { theme: "dark" }));
|
|
26
|
+
console.log("wrote docs/card.html + docs/index.html (auto) + card-light.html + card-dark.html — the context card, rendered from AGENTS.md / project.fafm / .well-known/fafa");
|
|
14
27
|
}
|
package/dist/constants.d.ts
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 declare const NAME = "mcp-context-card";
|
|
4
|
-
export declare const VERSION = "0.
|
|
4
|
+
export declare const VERSION = "0.6.0";
|
|
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 = "0.
|
|
4
|
+
export const VERSION = "0.6.0";
|
|
5
5
|
export const SERVER_CARD_URI = "mcp-context-card://server-card";
|
package/dist/identity.d.ts
CHANGED
|
@@ -16,7 +16,7 @@ export declare function whoami(root: string): string;
|
|
|
16
16
|
* other two point at their worked-example artifacts; `memory` carries a note
|
|
17
17
|
* because there is no de-facto standard for it yet.
|
|
18
18
|
*/
|
|
19
|
-
export declare function
|
|
19
|
+
export declare function serverCardMeta(): {
|
|
20
20
|
readonly "io.github.wolfe-jam.mcp-context-card/context": {
|
|
21
21
|
readonly source: "AGENTS.md";
|
|
22
22
|
readonly mediaType: "text/markdown";
|
package/dist/identity.js
CHANGED
|
@@ -61,7 +61,7 @@ export function whoami(root) {
|
|
|
61
61
|
* other two point at their worked-example artifacts; `memory` carries a note
|
|
62
62
|
* because there is no de-facto standard for it yet.
|
|
63
63
|
*/
|
|
64
|
-
export function
|
|
64
|
+
export function serverCardMeta() {
|
|
65
65
|
return {
|
|
66
66
|
[`${META_NS}/context`]: {
|
|
67
67
|
source: "AGENTS.md",
|