mcp-context-card 1.4.0 → 1.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 +39 -17
- package/.well-known/fafa +10 -1
- package/CHANGELOG.md +86 -0
- package/README.md +66 -23
- package/dist/bin.d.ts +6 -1
- package/dist/bin.js +29 -4
- package/dist/catalog-gen.d.ts +58 -7
- package/dist/catalog-gen.js +51 -26
- package/dist/conformance/discovery.d.ts +60 -0
- package/dist/conformance/discovery.js +281 -0
- package/dist/constants.d.ts +30 -1
- package/dist/constants.js +30 -1
- package/dist/faf/parse-fafa.js +21 -0
- package/dist/faf/types.d.ts +15 -0
- package/dist/identity.d.ts +13 -0
- package/dist/identity.js +16 -0
- package/dist/render-card.d.ts +51 -0
- package/dist/render-card.js +325 -98
- package/dist/server-card.d.ts +39 -0
- package/dist/server-card.js +38 -0
- package/dist/server.d.ts +6 -25
- package/dist/server.js +16 -14
- package/dist/transport/guard.d.ts +35 -0
- package/dist/transport/guard.js +63 -0
- package/dist/transport/http.d.ts +19 -2
- package/dist/transport/http.js +95 -24
- package/docs/MECHANISMS.md +38 -18
- package/docs/TRANSPORT.md +40 -7
- package/docs/WIRING.md +10 -5
- package/docs/card-dark.html +180 -62
- package/docs/card-light.html +180 -62
- package/docs/card.html +178 -60
- 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 +178 -60
- package/package.json +7 -4
- package/server.json +2 -2
package/docs/card.html
CHANGED
|
@@ -3,50 +3,139 @@
|
|
|
3
3
|
<head>
|
|
4
4
|
<meta charset="utf-8">
|
|
5
5
|
<meta name="viewport" content="width=device-width,initial-scale=1">
|
|
6
|
-
<title>mcp-context-card —
|
|
6
|
+
<title>mcp-context-card — business card</title>
|
|
7
7
|
<style>
|
|
8
|
+
/* The page and the card are themed independently. The page follows the
|
|
9
|
+
viewer's OS. The card is the owner's choice: body[data-theme] (light | dark;
|
|
10
|
+
none = follow the OS), and the reader can switch it with the ◐ toggle (#ink). */
|
|
8
11
|
:root{
|
|
9
12
|
--accent:#FF702D;
|
|
10
|
-
--bg:#f4f4f5
|
|
11
|
-
--line:rgba(0,0,0,.09); --chip:rgba(0,0,0,.05);
|
|
12
|
-
--card-shadow:0 1px 3px rgba(0,0,0,.06), 0 12px 32px rgba(0,0,0,.10);
|
|
13
|
+
--page-bg:#f4f4f5;--page-muted:#6b6b70;--page-line:rgba(0,0,0,.09);--page-chip:rgba(0,0,0,.05);
|
|
13
14
|
}
|
|
14
|
-
:
|
|
15
|
-
--bg:#000
|
|
16
|
-
--line:rgba(255,255,255,.13); --chip:rgba(255,255,255,.07);
|
|
17
|
-
--card-shadow:0 0 0 1px rgba(255,255,255,.16),
|
|
18
|
-
0 8px 40px color-mix(in srgb, var(--accent) 20%, transparent);
|
|
15
|
+
@media (prefers-color-scheme:dark){
|
|
16
|
+
:root{--page-bg:#000;--page-muted:#9a9aa0;--page-line:rgba(255,255,255,.13);--page-chip:rgba(255,255,255,.07)}
|
|
19
17
|
}
|
|
18
|
+
.bcard{--card:#fff;--fg:#0a0a0a;--muted:#6b6b70;--line:rgba(0,0,0,.09);--chip:rgba(0,0,0,.05);--card-shadow:0 1px 3px rgba(0,0,0,.06),0 12px 32px rgba(0,0,0,.10)}
|
|
19
|
+
body[data-theme="dark"] .bcard,
|
|
20
|
+
body[data-theme="light"] #ink:checked~.stage .bcard{--card:#0d0d0d;--fg:#fafafa;--muted:#9a9aa0;--line:rgba(255,255,255,.13);--chip:rgba(255,255,255,.07);--card-shadow:0 0 0 1px rgba(255,255,255,.16),0 8px 40px color-mix(in srgb,var(--accent) 20%,transparent)}
|
|
21
|
+
body[data-theme="dark"] #ink:checked~.stage .bcard{--card:#fff;--fg:#0a0a0a;--muted:#6b6b70;--line:rgba(0,0,0,.09);--chip:rgba(0,0,0,.05);--card-shadow:0 1px 3px rgba(0,0,0,.06),0 12px 32px rgba(0,0,0,.10)}
|
|
20
22
|
@media (prefers-color-scheme:dark){
|
|
21
|
-
:
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
}
|
|
23
|
+
body:not([data-theme]) .bcard{--card:#0d0d0d;--fg:#fafafa;--muted:#9a9aa0;--line:rgba(255,255,255,.13);--chip:rgba(255,255,255,.07);--card-shadow:0 0 0 1px rgba(255,255,255,.16),0 8px 40px color-mix(in srgb,var(--accent) 20%,transparent)}
|
|
24
|
+
body:not([data-theme]) #ink:checked~.stage .bcard{--card:#fff;--fg:#0a0a0a;--muted:#6b6b70;--line:rgba(0,0,0,.09);--chip:rgba(0,0,0,.05);--card-shadow:0 1px 3px rgba(0,0,0,.06),0 12px 32px rgba(0,0,0,.10)}
|
|
25
|
+
}
|
|
26
|
+
@media (prefers-color-scheme:light){
|
|
27
|
+
body:not([data-theme]) #ink:checked~.stage .bcard{--card:#0d0d0d;--fg:#fafafa;--muted:#9a9aa0;--line:rgba(255,255,255,.13);--chip:rgba(255,255,255,.07);--card-shadow:0 0 0 1px rgba(255,255,255,.16),0 8px 40px color-mix(in srgb,var(--accent) 20%,transparent)}
|
|
27
28
|
}
|
|
29
|
+
.bcard{color:var(--fg)}
|
|
28
30
|
*{box-sizing:border-box}
|
|
29
|
-
body{margin:0;background:var(--bg);color:var(--
|
|
31
|
+
body{margin:0;background:var(--page-bg);color:var(--page-muted);
|
|
30
32
|
font:15px/1.6 -apple-system,BlinkMacSystemFont,"Segoe UI",Roboto,Helvetica,Arial,sans-serif;
|
|
31
|
-
padding:40px
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
.
|
|
35
|
-
.
|
|
36
|
-
|
|
33
|
+
padding:40px 16px}
|
|
34
|
+
/* ── the business card: two faces, flip, two views ─────────────────── */
|
|
35
|
+
.sr{position:absolute;width:1px;height:1px;margin:-1px;overflow:hidden;clip:rect(0 0 0 0);white-space:nowrap}
|
|
36
|
+
.stage{max-width:760px;margin:0 auto}
|
|
37
|
+
.views{display:flex;justify-content:flex-end;margin:0 0 10px}
|
|
38
|
+
.view,.hint label{cursor:pointer}
|
|
39
|
+
.view{font-size:.78rem;font-weight:600;padding:3px 11px;border-radius:20px;border:1px solid var(--page-line);
|
|
40
|
+
background:var(--page-chip);color:var(--page-muted);letter-spacing:.2em}
|
|
41
|
+
.views{gap:8px}
|
|
42
|
+
.view:hover,.hint label:hover{color:var(--accent);border-color:var(--accent)}
|
|
43
|
+
.bcard{margin:0 auto;width:100%;aspect-ratio:7/4;perspective:1600px}
|
|
44
|
+
#portrait:checked~.stage{max-width:480px}
|
|
45
|
+
#portrait:checked~.stage .bcard{aspect-ratio:4/7}
|
|
46
|
+
.faces{position:relative;width:100%;height:100%;transform-style:preserve-3d;transition:transform .6s ease}
|
|
47
|
+
#flip:checked~.stage .faces{transform:rotateY(180deg)}
|
|
48
|
+
.face{position:absolute;inset:0;background:var(--card);border:1px solid var(--line);border-radius:16px;
|
|
49
|
+
box-shadow:var(--card-shadow);backface-visibility:hidden;-webkit-backface-visibility:hidden;overflow:hidden}
|
|
50
|
+
.back{transform:rotateY(180deg) translateZ(1px);display:flex;flex-direction:column}
|
|
51
|
+
/* The face turned away takes no pointer or wheel events, so the visible face
|
|
52
|
+
scrolls (a hidden backface can still win hit-testing, notably in Chrome/Safari on macOS). */
|
|
53
|
+
#flip:checked~.stage .front,#flip:not(:checked)~.stage .back{pointer-events:none;visibility:hidden;transition:visibility 0s .3s}
|
|
54
|
+
#flip:checked~.stage .back,#flip:not(:checked)~.stage .front{visibility:visible;transition:visibility 0s .3s}
|
|
55
|
+
.panes{overscroll-behavior:contain;-webkit-overflow-scrolling:touch}
|
|
56
|
+
.front{display:flex;flex-direction:column;justify-content:center;padding:34px 44px;
|
|
57
|
+
border-top:5px solid var(--accent);
|
|
58
|
+
background:linear-gradient(135deg,color-mix(in srgb,var(--accent) 10%,var(--card)) 0%,var(--card) 55%)}
|
|
59
|
+
.front .id{max-width:34em}
|
|
60
|
+
h1{margin:0;font-size:2.1rem;line-height:1.15;letter-spacing:-.025em}
|
|
61
|
+
.title{margin:8px 0 0;font-size:.82rem;font-weight:700;letter-spacing:.14em;text-transform:uppercase;color:var(--accent)}
|
|
62
|
+
.oneliner{margin:16px 0 0;font-size:1.05rem;color:var(--muted);line-height:1.5}
|
|
63
|
+
.foot-front{position:absolute;left:44px;right:130px;bottom:22px;display:flex;flex-wrap:wrap;align-items:center;gap:6px 12px}
|
|
64
|
+
.domain{font:.8rem ui-monospace,SFMono-Regular,Menlo,monospace;color:var(--muted)}
|
|
65
|
+
.corner{position:absolute;width:30px;height:30px;border-radius:50%;display:grid;place-items:center;
|
|
66
|
+
cursor:pointer;font-weight:700;font-size:.9rem;color:var(--muted);background:var(--chip);border:1px solid var(--line);z-index:4}
|
|
67
|
+
.corner:hover{color:var(--accent);border-color:var(--accent)}
|
|
68
|
+
.corner.tr{top:16px;right:16px;font-family:Georgia,serif;font-style:italic}
|
|
69
|
+
.logo{position:absolute;top:34px;left:44px;width:84px;height:84px;border-radius:50%;display:grid;place-items:center;
|
|
70
|
+
color:#fff;font-weight:800;font-size:2rem;letter-spacing:-.02em;line-height:1;
|
|
71
|
+
background:radial-gradient(circle at 30% 25%,color-mix(in srgb,var(--accent) 80%,#fff),var(--accent) 45%,color-mix(in srgb,var(--accent) 50%,#000));
|
|
72
|
+
box-shadow:0 0 0 3px var(--card),0 0 0 4px color-mix(in srgb,var(--accent) 45%,transparent),0 6px 20px color-mix(in srgb,var(--accent) 30%,transparent)}
|
|
73
|
+
.front .id{margin-top:70px}
|
|
74
|
+
.corner.br{bottom:16px;right:16px}
|
|
75
|
+
.flipbtn{position:absolute;right:18px;bottom:16px;z-index:4;cursor:pointer;width:42px;height:42px;border-radius:50%;
|
|
76
|
+
display:grid;place-items:center;color:var(--fg);background:transparent;box-shadow:inset 0 0 0 2px var(--fg);
|
|
77
|
+
transition:transform .2s ease}
|
|
78
|
+
.flipbtn span{font-size:1.3rem;line-height:1;font-weight:700}
|
|
79
|
+
|
|
80
|
+
/* the back's button: same spot and outline as the front's; ↺ instead of ↻. Over
|
|
81
|
+
scrolling text it takes the card's colour, so the arrow stays readable. */
|
|
82
|
+
.flipbtn.back-btn{background:var(--card)}
|
|
83
|
+
/* fast tooltip: shows at once on hover or keyboard focus (a title tooltip waits ~1 s) */
|
|
84
|
+
.flipbtn[data-tip]::after{content:attr(data-tip);position:absolute;right:0;bottom:calc(100% + 8px);white-space:nowrap;
|
|
85
|
+
font:600 .74rem/1 -apple-system,BlinkMacSystemFont,"Segoe UI",Roboto,sans-serif;letter-spacing:0;padding:6px 9px;border-radius:7px;
|
|
86
|
+
color:var(--card);background:var(--fg);opacity:0;transform:translateY(3px);pointer-events:none;transition:opacity .08s,transform .08s}
|
|
87
|
+
.flipbtn[data-tip]:hover::after,#flip:focus-visible~.stage .flipbtn[data-tip]::after{opacity:1;transform:none}
|
|
88
|
+
.flipbtn:hover{transform:none}.flipbtn:hover span{transform:rotate(-25deg)}.flipbtn span{transition:transform .2s ease}
|
|
89
|
+
.whatis{position:absolute;top:16px;right:16px;z-index:5}
|
|
90
|
+
.whatis>summary{position:static;list-style:none}
|
|
91
|
+
.whatis>summary::-webkit-details-marker{display:none}
|
|
92
|
+
.whatis[open]>summary{color:var(--accent);border-color:var(--accent)}
|
|
93
|
+
.whatis-panel{position:absolute;right:0;top:38px;width:min(320px,70vw);padding:14px 16px;border-radius:12px;
|
|
94
|
+
background:var(--card);border:1px solid var(--line);box-shadow:var(--card-shadow);font-size:.84rem;line-height:1.5}
|
|
95
|
+
.whatis-panel p{margin:0 0 8px}.whatis-head{font-weight:800;color:var(--accent);letter-spacing:-.01em;font-size:.95rem}
|
|
96
|
+
.whatis-foot{color:var(--muted);margin:0!important}.whatis-panel code{font:.86em ui-monospace,SFMono-Regular,Menlo,monospace}
|
|
97
|
+
.tabbar{display:flex;flex-wrap:wrap;gap:4px;padding:14px 60px 0 18px;border-bottom:1px solid var(--line);border-top:5px solid var(--accent)}
|
|
98
|
+
.tabbar label{cursor:pointer;font-size:.8rem;font-weight:600;color:var(--muted);padding:6px 11px;border-radius:8px 8px 0 0}
|
|
99
|
+
.tabbar label:hover{color:var(--fg)}
|
|
100
|
+
.panes{flex:1;overflow:auto;padding:20px 26px 72px}
|
|
101
|
+
.pane{display:none}
|
|
102
|
+
.lead{margin:0 0 14px;font-size:1rem;line-height:1.6}
|
|
103
|
+
.kv{border-collapse:collapse;font-size:.86rem;width:100%}
|
|
104
|
+
.kv th{text-align:left;font-weight:600;color:var(--muted);padding:6px 14px 6px 0;white-space:nowrap;vertical-align:top}
|
|
105
|
+
.kv td{padding:6px 0;border-bottom:1px solid var(--line)}
|
|
106
|
+
.kv code,.lead code{font:.86em ui-monospace,SFMono-Regular,Menlo,monospace}
|
|
107
|
+
.hint{text-align:center;color:var(--page-muted);font-size:.78rem;margin:14px 0 0}
|
|
108
|
+
.hint label{color:var(--accent)}
|
|
109
|
+
#flip:focus-visible~.stage .flipbtn,#portrait:focus-visible~.stage .view[for=portrait],#ink:focus-visible~.stage .view[for=ink]{outline:2px solid var(--accent);outline-offset:2px}
|
|
110
|
+
@media (max-width:640px){
|
|
111
|
+
.bcard,#portrait:checked~.stage .bcard{aspect-ratio:auto;height:min(78vh,720px)}
|
|
112
|
+
.front{padding:28px 26px}.foot-front{left:26px}
|
|
113
|
+
.logo{top:24px;left:26px;width:64px;height:64px;font-size:1.5rem}.front .id{margin-top:56px}
|
|
114
|
+
h1{font-size:1.7rem}
|
|
115
|
+
}
|
|
116
|
+
/* flat: expanded render and print — both faces, every tab, no flip */
|
|
117
|
+
.flat .faces,.flat .face{position:static;transform:none!important;height:auto}
|
|
118
|
+
.flat .bcard{aspect-ratio:auto;perspective:none}
|
|
119
|
+
.flat .face{margin:0 0 18px}.flat .front{min-height:260px;position:relative}
|
|
120
|
+
.flat .pane{display:block;margin:0 0 22px}.flat .bcard{color:var(--fg)}.flat .tabbar,.flat .views,.flat .hint,.flat .corner,.flat .flipbtn,.flat .whatis{display:none}
|
|
121
|
+
.flat .panes{overflow:visible}
|
|
122
|
+
@media print{
|
|
123
|
+
.faces,.face{position:static!important;transform:none!important;height:auto!important}
|
|
124
|
+
.bcard{aspect-ratio:auto!important}.face{margin:0 0 18px;box-shadow:none}
|
|
125
|
+
.pane{display:block!important;margin:0 0 22px}.tabbar,.views,.hint,.corner,.flipbtn,.whatis{display:none!important}
|
|
126
|
+
.panes{overflow:visible}
|
|
127
|
+
}
|
|
37
128
|
.pills{display:flex;flex-wrap:wrap;gap:6px}
|
|
38
129
|
.pill{font-size:.74rem;font-weight:600;padding:3px 9px;border-radius:20px;background:var(--chip);color:var(--muted)}
|
|
39
130
|
.pill.accent{background:color-mix(in srgb,var(--accent) 16%,transparent);color:var(--accent)}
|
|
40
|
-
section{border-bottom:1px solid var(--line)}
|
|
41
|
-
section:last-child{border-bottom:0}
|
|
42
131
|
.label{font-size:.7rem;font-weight:700;letter-spacing:.16em;text-transform:uppercase;
|
|
43
132
|
color:var(--accent);margin:0 0 14px}
|
|
44
133
|
.toc{display:flex;flex-wrap:wrap;gap:6px 14px;margin:0;padding:0;list-style:none}
|
|
45
134
|
.toc a{font-size:.82rem;color:var(--muted);text-decoration:none}
|
|
46
135
|
.toc a:hover{color:var(--accent)}
|
|
47
136
|
/* ── collapsible context ─────────────────────────────────────────── */
|
|
48
|
-
.ctx-nav{position:sticky;top
|
|
49
|
-
margin:0 -
|
|
137
|
+
.ctx-nav{position:sticky;top:-20px;z-index:3;background:var(--card);
|
|
138
|
+
margin:0 -26px 16px;padding:11px 26px;border-bottom:1px solid var(--line);
|
|
50
139
|
display:flex;flex-wrap:wrap;align-items:flex-start;gap:8px 16px}
|
|
51
140
|
.xall{margin-left:auto;flex:none;font:inherit;font-size:.76rem;font-weight:600;
|
|
52
141
|
white-space:nowrap;padding:3px 11px;border-radius:20px;border:1px solid var(--line);
|
|
@@ -92,19 +181,49 @@ details.ctx-section>.md{padding:0 0 16px}
|
|
|
92
181
|
.disc code{font:.86em ui-monospace,SFMono-Regular,Menlo,monospace;color:var(--muted)}
|
|
93
182
|
.fetch{margin:14px 0 0;font-size:.82rem;color:var(--muted)}
|
|
94
183
|
.fetch code{background:var(--chip);padding:1px 5px;border-radius:5px}
|
|
95
|
-
.foot{color:var(--muted);font-size:.78rem;text-align:center;border-top:1px solid var(--line)}
|
|
96
184
|
.none{color:var(--muted);font-style:italic}
|
|
97
|
-
</style>
|
|
185
|
+
#t-about:checked~.panes .p-about{display:block}#t-about:checked~.tabbar label[for=t-about]{color:var(--accent);background:var(--chip)}#t-context:checked~.panes .p-context{display:block}#t-context:checked~.tabbar label[for=t-context]{color:var(--accent);background:var(--chip)}#t-memory:checked~.panes .p-memory{display:block}#t-memory:checked~.tabbar label[for=t-memory]{color:var(--accent);background:var(--chip)}#t-discovery:checked~.panes .p-discovery{display:block}#t-discovery:checked~.tabbar label[for=t-discovery]{color:var(--accent);background:var(--chip)}</style>
|
|
98
186
|
</head>
|
|
99
187
|
<body>
|
|
100
|
-
<
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
<
|
|
106
|
-
<
|
|
107
|
-
|
|
188
|
+
<input type="checkbox" id="flip" class="sr" aria-label="Flip the card">
|
|
189
|
+
<input type="checkbox" id="ink" class="sr" aria-label="Switch the card between light and dark">
|
|
190
|
+
<input type="checkbox" id="portrait" class="sr" aria-label="Portrait view">
|
|
191
|
+
<div class="stage">
|
|
192
|
+
<div class="views"><label for="ink" class="view" title="Card: light or dark">◐</label><label for="portrait" class="view" title="Landscape or portrait">▭ ▯</label></div>
|
|
193
|
+
<main class="bcard">
|
|
194
|
+
<div class="faces">
|
|
195
|
+
<section class="face front">
|
|
196
|
+
<div class="logo" aria-hidden="true">MC</div>
|
|
197
|
+
<details class="whatis">
|
|
198
|
+
<summary class="corner tr" title="About this card" aria-label="About this card">i</summary>
|
|
199
|
+
<div class="whatis-panel">
|
|
200
|
+
<p class="whatis-head">Business Cards for Agents</p>
|
|
201
|
+
<p>This is the public card of an AI agent or MCP server: who it is, what it does, where to reach it. Flip it for the detail.</p>
|
|
202
|
+
<p>People read it here. Machines read the same facts from its MCP Server Card and AI Catalog, before they ever connect.</p>
|
|
203
|
+
<p class="whatis-foot">Made with <code>mcp-context-card</code></p>
|
|
204
|
+
</div>
|
|
205
|
+
</details>
|
|
206
|
+
<div class="id">
|
|
207
|
+
<h1>mcp-context-card</h1>
|
|
208
|
+
<p class="title">MCP server · v1.6.0</p>
|
|
209
|
+
<p class="oneliner">The essential MCP components for a project's context (AGENTS.md), cross-session memory, and identity</p>
|
|
210
|
+
</div>
|
|
211
|
+
<div class="foot-front"><span class="domain">faf.one</span><div class="pills"><span class="pill">io.github.Wolfe-Jam</span><span class="pill accent">published</span><span class="pill">MIT</span></div></div>
|
|
212
|
+
<label for="flip" class="flipbtn" data-tip="Flip the card" aria-label="Flip the card"><span aria-hidden="true">↻</span></label>
|
|
213
|
+
</section>
|
|
214
|
+
<section class="face back">
|
|
215
|
+
<input type="radio" name="tab" id="t-about" class="sr" checked><input type="radio" name="tab" id="t-context" class="sr"><input type="radio" name="tab" id="t-memory" class="sr"><input type="radio" name="tab" id="t-discovery" class="sr">
|
|
216
|
+
<details class="whatis">
|
|
217
|
+
<summary class="corner tr" title="About this card" aria-label="About this card">i</summary>
|
|
218
|
+
<div class="whatis-panel">
|
|
219
|
+
<p class="whatis-head">Business Cards for Agents</p>
|
|
220
|
+
<p>This is the public card of an AI agent or MCP server: who it is, what it does, where to reach it. Flip it for the detail.</p>
|
|
221
|
+
<p>People read it here. Machines read the same facts from its MCP Server Card and AI Catalog, before they ever connect.</p>
|
|
222
|
+
<p class="whatis-foot">Made with <code>mcp-context-card</code></p>
|
|
223
|
+
</div>
|
|
224
|
+
</details>
|
|
225
|
+
<div class="tabbar"><label for="t-about">About</label><label for="t-context">Context</label><label for="t-memory">Memory</label><label for="t-discovery">Discovery</label></div>
|
|
226
|
+
<div class="panes"><div class="pane p-about"><p class="label">About</p><p class="lead">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.</p><table class="kv"><tbody><tr><th>Agent ID</th><td><code>urn:air:faf.one:agent:mcp-context-card</code></td></tr><tr><th>Publisher</th><td>io.github.Wolfe-Jam</td></tr><tr><th>Version</th><td>v1.6.0</td></tr><tr><th>Status</th><td>published</td></tr><tr><th>License</th><td>MIT</td></tr><tr><th>Package (npm)</th><td><code>mcp-context-card</code></td></tr></tbody></table></div><div class="pane p-context"><p class="label">Context — AGENTS.md</p><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
227
|
<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
228
|
<p><code>read_agents_md</code> serves this file, section by section, over the same MCP connection.</p></div>
|
|
110
229
|
<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>
|
|
@@ -114,35 +233,34 @@ npm run test:coverage # + the coverage gate (lines 90 / funcs 85 / branches 80,
|
|
|
114
233
|
npm run demo # end to end: all tools over stdio, then over stateless HTTP
|
|
115
234
|
npm run version:check # every version-bearing spot agrees with package.json
|
|
116
235
|
npm run faf:check # project.faf / project.fafm / .well-known/fafa still describe the project</code></pre>
|
|
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 ten tools + the Server Card and card resources</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>"type": "module"</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 && npm run build && npm test && 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>
|
|
118
|
-
</section>
|
|
119
|
-
<section>
|
|
120
|
-
<p class="label">Memory — 4 facts</p>
|
|
121
|
-
<div class="fact"><p>The context concern points at AGENTS.md — the de-facto standard for agent instructions. read_agents_md serves it whole or one section at a time, so a client pulls '## Test' without spending its context window on the whole file. Memory and identity have no de-facto standard, so this server uses .fafm and .fafa as one instantiation each.</p><div class="meta"><span class="tag">scope</span><span class="tag">agents-md</span><span class="dot" title="verified"></span></div></div><div class="fact"><p>Both exposure mechanisms — the Server Card _meta block and a self-published ai-catalog.json — already exist in the MCP ecosystem. This server wires all three concerns through them, from one set of source files, with a CI check (catalog:check) that fails if the two surfaces drift apart.</p><div class="meta"><span class="tag">mcp</span><span class="tag">server-card</span><span class="tag">ai-catalog</span><span class="dot" title="verified"></span></div></div><div class="fact"><p>Distribution: a published npm package (bin <code>mcp-context-card</code>, dual transport). The three source files (AGENTS.md, project.fafm, .well-known/fafa) ship with the package so it is a working discovery target on install. MCP_CONTEXT_CARD_ROOT points it at a real project.</p><div class="meta"><span class="tag">distribution</span><span class="tag">mit</span><span class="tag">npm</span><span class="dot" title="verified"></span></div></div><div class="fact"><p>author_agents_md authors the best AGENTS.md the project has the material for, not a fixed floor. BETTER is the facts-only draft (via agents-md-facts: build/test commands, entry points, conventions — nothing invented). BEST is that plus a '## Project' section ahead of it, read straight from project.faf when one exists — goal, who it's for, why, and a start-here file list. The rule is concrete: project.faf present means BEST, absent means BETTER.</p><div class="meta"><span class="tag">agents-md</span><span class="tag">author_agents_md</span><span class="tag">faf</span><span class="dot" title="verified"></span></div></div>
|
|
122
|
-
</section>
|
|
123
|
-
<section>
|
|
124
|
-
<p class="label">Discovery</p>
|
|
125
|
-
<table class="disc"><thead><tr><th>concern</th><th>source</th><th>media type</th></tr></thead><tbody><tr><td>context</td><td><code>AGENTS.md</code></td><td><code>text/markdown</code></td></tr><tr><td>memory</td><td><code>project.fafm</code></td><td><code>application/vnd.fafm+yaml</code></td></tr><tr><td>identity</td><td><code>.well-known/fafa</code></td><td><code>application/vnd.fafa+yaml</code></td></tr></tbody></table>
|
|
236
|
+
<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 ten tools + the Server Card and card resources</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>"type": "module"</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 && npm run build && npm test && 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></div><div class="pane p-memory"><p class="label">Memory — 4 facts</p><div class="fact"><p>The context concern points at AGENTS.md — the de-facto standard for agent instructions. read_agents_md serves it whole or one section at a time, so a client pulls '## Test' without spending its context window on the whole file. Memory and identity have no de-facto standard, so this server uses .fafm and .fafa as one instantiation each.</p><div class="meta"><span class="tag">scope</span><span class="tag">agents-md</span><span class="dot" title="verified"></span></div></div><div class="fact"><p>Both exposure mechanisms — the Server Card _meta block and a self-published ai-catalog.json — already exist in the MCP ecosystem. This server wires all three concerns through them, from one set of source files, with a CI check (catalog:check) that fails if the two surfaces drift apart.</p><div class="meta"><span class="tag">mcp</span><span class="tag">server-card</span><span class="tag">ai-catalog</span><span class="dot" title="verified"></span></div></div><div class="fact"><p>Distribution: a published npm package (bin <code>mcp-context-card</code>, dual transport). The three source files (AGENTS.md, project.fafm, .well-known/fafa) ship with the package so it is a working discovery target on install. MCP_CONTEXT_CARD_ROOT points it at a real project.</p><div class="meta"><span class="tag">distribution</span><span class="tag">mit</span><span class="tag">npm</span><span class="dot" title="verified"></span></div></div><div class="fact"><p>author_agents_md authors the best AGENTS.md the project has the material for, not a fixed floor. BETTER is the facts-only draft (via agents-md-facts: build/test commands, entry points, conventions — nothing invented). BEST is that plus a '## Project' section ahead of it, read straight from project.faf when one exists — goal, who it's for, why, and a start-here file list. The rule is concrete: project.faf present means BEST, absent means BETTER.</p><div class="meta"><span class="tag">agents-md</span><span class="tag">author_agents_md</span><span class="tag">faf</span><span class="dot" title="verified"></span></div></div></div><div class="pane p-discovery"><p class="label">Discovery</p><table class="disc"><thead><tr><th>concern</th><th>source</th><th>media type</th></tr></thead><tbody><tr><td>context</td><td><code>AGENTS.md</code></td><td><code>text/markdown</code></td></tr><tr><td>memory</td><td><code>project.fafm</code></td><td><code>application/vnd.fafm+yaml</code></td></tr><tr><td>identity</td><td><code>.well-known/fafa</code></td><td><code>application/vnd.fafa+yaml</code></td></tr></tbody></table>
|
|
126
237
|
<p class="fetch">A machine reads this over <b>MCP</b> from the
|
|
127
238
|
<code>mcp-context-card://server-card</code> resource; over <b>HTTP</b> also
|
|
128
|
-
from <code>GET
|
|
129
|
-
<code>GET /.well-known/ai-catalog.json</code>.</p>
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
</
|
|
239
|
+
from <code>GET /mcp/server-card</code> and
|
|
240
|
+
<code>GET /.well-known/ai-catalog.json</code>.</p></div></div>
|
|
241
|
+
<label for="flip" class="flipbtn back-btn" data-tip="Flip back" aria-label="Flip back"><span aria-hidden="true">↺</span></label>
|
|
242
|
+
</section>
|
|
243
|
+
</div>
|
|
244
|
+
</main>
|
|
245
|
+
<p class="hint">mcp-context-card · business card · <label for="flip">flip it over</label></p>
|
|
246
|
+
</div>
|
|
133
247
|
<script>
|
|
134
248
|
(function(){
|
|
135
|
-
var btn=document.querySelector(".xall");
|
|
136
249
|
var secs=[].slice.call(document.querySelectorAll("details.ctx-section"));
|
|
137
|
-
|
|
138
|
-
var sync=function(){btn.textContent=secs.every(function(d){return d.open})?"Collapse all":"Expand all"};
|
|
139
|
-
btn.
|
|
140
|
-
|
|
141
|
-
var open=!secs.every(function(d){return d.open});
|
|
142
|
-
secs.forEach(function(d){d.
|
|
143
|
-
}
|
|
144
|
-
|
|
145
|
-
|
|
250
|
+
var btn=document.querySelector(".xall");
|
|
251
|
+
var sync=function(){if(btn)btn.textContent=secs.every(function(d){return d.open})?"Collapse all":"Expand all"};
|
|
252
|
+
if(btn&&secs.length){
|
|
253
|
+
btn.hidden=false;
|
|
254
|
+
btn.addEventListener("click",function(){var open=!secs.every(function(d){return d.open});secs.forEach(function(d){d.open=open});sync()});
|
|
255
|
+
secs.forEach(function(d){d.addEventListener("toggle",sync)});
|
|
256
|
+
}
|
|
257
|
+
var openHash=function(){
|
|
258
|
+
var d=document.getElementById(decodeURIComponent(location.hash.slice(1)));
|
|
259
|
+
if(!d||d.tagName!=="DETAILS")return;
|
|
260
|
+
var f=document.getElementById("flip"),t=document.getElementById("t-context");
|
|
261
|
+
if(f)f.checked=true;if(t)t.checked=true;d.open=true;sync();
|
|
262
|
+
setTimeout(function(){d.scrollIntoView({block:"nearest"})},620);
|
|
263
|
+
};
|
|
146
264
|
addEventListener("hashchange",openHash);openHash();
|
|
147
265
|
var pre=[];
|
|
148
266
|
addEventListener("beforeprint",function(){pre=secs.map(function(d){return d.open});secs.forEach(function(d){d.open=true})});
|
|
Binary file
|
package/docs/img/card-dark.png
CHANGED
|
Binary file
|
|
Binary file
|
package/docs/img/card-light.png
CHANGED
|
Binary file
|
package/docs/img/card-memory.png
CHANGED
|
Binary file
|