wiki-formant 0.2.1 → 0.4.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.
@@ -0,0 +1,83 @@
1
+ export interface RegistryAuthRecord {
2
+ body: string;
3
+ contentType: string;
4
+ cacheControl: string;
5
+ }
6
+ /**
7
+ * The `v=MCPv1` record the official MCP registry fetches from
8
+ * `/.well-known/mcp-registry-auth` to prove domain ownership. `mcp-publisher
9
+ * login http --domain=<host>` checks the key here against the private key
10
+ * signing the login, which is what grants publish rights over the reversed-
11
+ * domain namespace the server's name sits in.
12
+ *
13
+ * Returns null when no key is configured, so the caller can 404 rather than
14
+ * serve a malformed record — a missing key should read as "not configured",
15
+ * not as a verification failure nobody can explain.
16
+ *
17
+ * The key material belongs in an env var rather than the repo: the public half
18
+ * is harmless to serve but pointless to commit, and keeping it out gives the
19
+ * private half an obvious home too (a keychain, never git).
20
+ *
21
+ * openssl genpkey -algorithm Ed25519 -out key.pem
22
+ * openssl pkey -in key.pem -pubout -outform DER | tail -c 32 | base64
23
+ */
24
+ export declare function registryAuthRecord(publicKey?: string, keyType?: string): RegistryAuthRecord | null;
25
+ /** A day at the edge, a week stale-while-revalidate. A card changes rarely. */
26
+ export declare const AGENT_CARD_CACHE_CONTROL = "public, s-maxage=86400, stale-while-revalidate=604800";
27
+ export interface AgentSkill {
28
+ id: string;
29
+ name: string;
30
+ description: string;
31
+ tags: string[];
32
+ examples?: string[];
33
+ authentication?: unknown;
34
+ }
35
+ /** The shape a tool needs to carry to become a skill. */
36
+ export interface SkillSource {
37
+ name: string;
38
+ description: string;
39
+ skill?: {
40
+ id: string;
41
+ tags: string[];
42
+ examples?: string[];
43
+ } | undefined;
44
+ auth?: unknown;
45
+ }
46
+ /**
47
+ * Skills derived from the MCP tool manifest, so a card can never advertise a
48
+ * capability the server does not have. `search_pages` becomes "Search Pages".
49
+ */
50
+ export declare function skillsFromTools(tools: readonly SkillSource[]): AgentSkill[];
51
+ export interface AgentCardLicense {
52
+ name: string;
53
+ url: string;
54
+ spdx?: string;
55
+ /** What the licence covers, e.g. `'content'`. */
56
+ scope?: string;
57
+ }
58
+ export interface AgentCardConfig {
59
+ name: string;
60
+ description: string;
61
+ /** Origin, no trailing slash. Every derived URL below hangs off it. */
62
+ url: string;
63
+ version: string;
64
+ skills: AgentSkill[];
65
+ license?: AgentCardLicense;
66
+ /** Defaults to `name`. */
67
+ organization?: string;
68
+ /** Defaults to `${url}/llms.txt`. */
69
+ documentationUrl?: string;
70
+ /** Defaults to `${url}/api/mcp`. Pass null for an origin with no MCP server. */
71
+ mcpEndpoint?: string | null;
72
+ /** Anything this origin advertises that the others do not. */
73
+ extra?: Record<string, unknown>;
74
+ }
75
+ /**
76
+ * An A2A Agent Card. Serve the same object at both `/.well-known/agent.json`
77
+ * and `/.well-known/agent-card.json`: v0.3 renamed the path and defined no
78
+ * fallback in either direction, so a spec-current client probes only the new
79
+ * one and a client on an older SDK probes only the old one. Serving one path
80
+ * means half the callers conclude the origin has no agent at all.
81
+ */
82
+ export declare function agentCard(config: AgentCardConfig): Record<string, unknown>;
83
+ //# sourceMappingURL=well-known.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"well-known.d.ts","sourceRoot":"","sources":["../src/well-known.ts"],"names":[],"mappings":"AAcA,MAAM,WAAW,kBAAkB;IACjC,IAAI,EAAE,MAAM,CAAC;IACb,WAAW,EAAE,MAAM,CAAC;IACpB,YAAY,EAAE,MAAM,CAAC;CACtB;AAED;;;;;;;;;;;;;;;;;GAiBG;AACH,wBAAgB,kBAAkB,CAAC,SAAS,CAAC,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,MAAM,GAAG,kBAAkB,GAAG,IAAI,CAQlG;AAID,+EAA+E;AAC/E,eAAO,MAAM,wBAAwB,0DAA0D,CAAC;AAEhG,MAAM,WAAW,UAAU;IACzB,EAAE,EAAE,MAAM,CAAC;IACX,IAAI,EAAE,MAAM,CAAC;IACb,WAAW,EAAE,MAAM,CAAC;IACpB,IAAI,EAAE,MAAM,EAAE,CAAC;IACf,QAAQ,CAAC,EAAE,MAAM,EAAE,CAAC;IACpB,cAAc,CAAC,EAAE,OAAO,CAAC;CAC1B;AAED,yDAAyD;AACzD,MAAM,WAAW,WAAW;IAC1B,IAAI,EAAE,MAAM,CAAC;IACb,WAAW,EAAE,MAAM,CAAC;IACpB,KAAK,CAAC,EAAE;QAAE,EAAE,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,MAAM,EAAE,CAAC;QAAC,QAAQ,CAAC,EAAE,MAAM,EAAE,CAAA;KAAE,GAAG,SAAS,CAAC;IACxE,IAAI,CAAC,EAAE,OAAO,CAAC;CAChB;AAED;;;GAGG;AACH,wBAAgB,eAAe,CAAC,KAAK,EAAE,SAAS,WAAW,EAAE,GAAG,UAAU,EAAE,CAW3E;AAED,MAAM,WAAW,gBAAgB;IAC/B,IAAI,EAAE,MAAM,CAAC;IACb,GAAG,EAAE,MAAM,CAAC;IACZ,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,iDAAiD;IACjD,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB;AAED,MAAM,WAAW,eAAe;IAC9B,IAAI,EAAE,MAAM,CAAC;IACb,WAAW,EAAE,MAAM,CAAC;IACpB,uEAAuE;IACvE,GAAG,EAAE,MAAM,CAAC;IACZ,OAAO,EAAE,MAAM,CAAC;IAChB,MAAM,EAAE,UAAU,EAAE,CAAC;IACrB,OAAO,CAAC,EAAE,gBAAgB,CAAC;IAC3B,0BAA0B;IAC1B,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,qCAAqC;IACrC,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAC1B,gFAAgF;IAChF,WAAW,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAC5B,8DAA8D;IAC9D,KAAK,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;CACjC;AAED;;;;;;GAMG;AACH,wBAAgB,SAAS,CAAC,MAAM,EAAE,eAAe,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAiB1E"}
@@ -0,0 +1,84 @@
1
+ // well-known.ts — the descriptors an agent finds before it knows anything else
2
+ // about an origin: the A2A Agent Card and the MCP registry's domain proof.
3
+ //
4
+ // All three apps here serve both, and all three had written them out. The
5
+ // registry-auth handler was identical bar a domain named in a comment; the
6
+ // agent cards shared an envelope, a skills mapping and a cache header, and
7
+ // differed only in the fields a card is *supposed* to differ in.
8
+ //
9
+ // Nothing here touches a framework: these return plain values, and the caller
10
+ // wraps them in whatever its router wants. That keeps this package free of a
11
+ // Next dependency and keeps each app's route a two-liner.
12
+ /**
13
+ * The `v=MCPv1` record the official MCP registry fetches from
14
+ * `/.well-known/mcp-registry-auth` to prove domain ownership. `mcp-publisher
15
+ * login http --domain=<host>` checks the key here against the private key
16
+ * signing the login, which is what grants publish rights over the reversed-
17
+ * domain namespace the server's name sits in.
18
+ *
19
+ * Returns null when no key is configured, so the caller can 404 rather than
20
+ * serve a malformed record — a missing key should read as "not configured",
21
+ * not as a verification failure nobody can explain.
22
+ *
23
+ * The key material belongs in an env var rather than the repo: the public half
24
+ * is harmless to serve but pointless to commit, and keeping it out gives the
25
+ * private half an obvious home too (a keychain, never git).
26
+ *
27
+ * openssl genpkey -algorithm Ed25519 -out key.pem
28
+ * openssl pkey -in key.pem -pubout -outform DER | tail -c 32 | base64
29
+ */
30
+ export function registryAuthRecord(publicKey, keyType) {
31
+ if (!publicKey)
32
+ return null;
33
+ return {
34
+ // ed25519 unless a P-384 key was used instead (the LibreSSL-friendly path).
35
+ body: `v=MCPv1; k=${keyType || 'ed25519'}; p=${publicKey}\n`,
36
+ contentType: 'text/plain; charset=utf-8',
37
+ cacheControl: 'no-store',
38
+ };
39
+ }
40
+ // ---- A2A Agent Card ---------------------------------------------------------
41
+ /** A day at the edge, a week stale-while-revalidate. A card changes rarely. */
42
+ export const AGENT_CARD_CACHE_CONTROL = 'public, s-maxage=86400, stale-while-revalidate=604800';
43
+ /**
44
+ * Skills derived from the MCP tool manifest, so a card can never advertise a
45
+ * capability the server does not have. `search_pages` becomes "Search Pages".
46
+ */
47
+ export function skillsFromTools(tools) {
48
+ return tools
49
+ .filter(t => t.skill)
50
+ .map(t => ({
51
+ id: t.skill.id,
52
+ name: t.name.replace(/_/g, ' ').replace(/\b\w/g, c => c.toUpperCase()),
53
+ description: t.description,
54
+ tags: t.skill.tags,
55
+ ...(t.skill.examples ? { examples: t.skill.examples } : {}),
56
+ ...(t.auth ? { authentication: t.auth } : {}),
57
+ }));
58
+ }
59
+ /**
60
+ * An A2A Agent Card. Serve the same object at both `/.well-known/agent.json`
61
+ * and `/.well-known/agent-card.json`: v0.3 renamed the path and defined no
62
+ * fallback in either direction, so a spec-current client probes only the new
63
+ * one and a client on an older SDK probes only the old one. Serving one path
64
+ * means half the callers conclude the origin has no agent at all.
65
+ */
66
+ export function agentCard(config) {
67
+ const { name, description, url, version, skills, license, organization, documentationUrl, mcpEndpoint, extra } = config;
68
+ return {
69
+ name,
70
+ description,
71
+ url,
72
+ version,
73
+ capabilities: { streaming: false, pushNotifications: false },
74
+ skills,
75
+ provider: { organization: organization ?? name, url },
76
+ documentationUrl: documentationUrl ?? `${url}/llms.txt`,
77
+ ...(mcpEndpoint === null ? {} : { mcpEndpoint: mcpEndpoint ?? `${url}/api/mcp` }),
78
+ ...(license ? { license } : {}),
79
+ ...extra,
80
+ defaultInputModes: ['text/plain', 'application/json'],
81
+ defaultOutputModes: ['text/plain', 'application/json', 'text/markdown'],
82
+ };
83
+ }
84
+ //# sourceMappingURL=well-known.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"well-known.js","sourceRoot":"","sources":["../src/well-known.ts"],"names":[],"mappings":"AAAA,+EAA+E;AAC/E,2EAA2E;AAC3E,EAAE;AACF,0EAA0E;AAC1E,2EAA2E;AAC3E,2EAA2E;AAC3E,iEAAiE;AACjE,EAAE;AACF,8EAA8E;AAC9E,6EAA6E;AAC7E,0DAA0D;AAU1D;;;;;;;;;;;;;;;;;GAiBG;AACH,MAAM,UAAU,kBAAkB,CAAC,SAAkB,EAAE,OAAgB;IACrE,IAAI,CAAC,SAAS;QAAE,OAAO,IAAI,CAAC;IAC5B,OAAO;QACL,4EAA4E;QAC5E,IAAI,EAAE,cAAc,OAAO,IAAI,SAAS,OAAO,SAAS,IAAI;QAC5D,WAAW,EAAE,2BAA2B;QACxC,YAAY,EAAE,UAAU;KACzB,CAAC;AACJ,CAAC;AAED,gFAAgF;AAEhF,+EAA+E;AAC/E,MAAM,CAAC,MAAM,wBAAwB,GAAG,uDAAuD,CAAC;AAmBhG;;;GAGG;AACH,MAAM,UAAU,eAAe,CAAC,KAA6B;IAC3D,OAAO,KAAK;SACT,MAAM,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,KAAK,CAAC;SACpB,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC;QACT,EAAE,EAAE,CAAC,CAAC,KAAM,CAAC,EAAE;QACf,IAAI,EAAE,CAAC,CAAC,IAAI,CAAC,OAAO,CAAC,IAAI,EAAE,GAAG,CAAC,CAAC,OAAO,CAAC,OAAO,EAAE,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,WAAW,EAAE,CAAC;QACtE,WAAW,EAAE,CAAC,CAAC,WAAW;QAC1B,IAAI,EAAE,CAAC,CAAC,KAAM,CAAC,IAAI;QACnB,GAAG,CAAC,CAAC,CAAC,KAAM,CAAC,QAAQ,CAAC,CAAC,CAAC,EAAE,QAAQ,EAAE,CAAC,CAAC,KAAM,CAAC,QAAQ,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;QAC7D,GAAG,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,cAAc,EAAE,CAAC,CAAC,IAAI,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;KAC9C,CAAC,CAAC,CAAC;AACR,CAAC;AA4BD;;;;;;GAMG;AACH,MAAM,UAAU,SAAS,CAAC,MAAuB;IAC/C,MAAM,EAAE,IAAI,EAAE,WAAW,EAAE,GAAG,EAAE,OAAO,EAAE,MAAM,EAAE,OAAO,EAAE,YAAY,EAAE,gBAAgB,EAAE,WAAW,EAAE,KAAK,EAAE,GAAG,MAAM,CAAC;IACxH,OAAO;QACL,IAAI;QACJ,WAAW;QACX,GAAG;QACH,OAAO;QACP,YAAY,EAAE,EAAE,SAAS,EAAE,KAAK,EAAE,iBAAiB,EAAE,KAAK,EAAE;QAC5D,MAAM;QACN,QAAQ,EAAE,EAAE,YAAY,EAAE,YAAY,IAAI,IAAI,EAAE,GAAG,EAAE;QACrD,gBAAgB,EAAE,gBAAgB,IAAI,GAAG,GAAG,WAAW;QACvD,GAAG,CAAC,WAAW,KAAK,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,WAAW,EAAE,WAAW,IAAI,GAAG,GAAG,UAAU,EAAE,CAAC;QACjF,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,EAAE,OAAO,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;QAC/B,GAAG,KAAK;QACR,iBAAiB,EAAE,CAAC,YAAY,EAAE,kBAAkB,CAAC;QACrD,kBAAkB,EAAE,CAAC,YAAY,EAAE,kBAAkB,EAAE,eAAe,CAAC;KACxE,CAAC;AACJ,CAAC"}
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "wiki-formant",
3
- "version": "0.2.1",
4
- "description": "The portable half of a wiki: derived taxonomy, a spec-correct MCP transport, markdown twins, block rendering, rate limiting, and the conditional-GET plumbing agent surfaces need. Zero runtime dependencies.",
3
+ "version": "0.4.0",
4
+ "description": "The portable half of a wiki: derived taxonomy, a spec-correct MCP transport, markdown twins, block rendering, link normalisation, freshness, rate limiting, and the conditional-GET plumbing agent surfaces need. Zero runtime dependencies.",
5
5
  "type": "module",
6
6
  "license": "MIT",
7
7
  "repository": {
@@ -18,7 +18,9 @@
18
18
  "markdown",
19
19
  "agent",
20
20
  "rate-limit",
21
- "plausible"
21
+ "plausible",
22
+ "links",
23
+ "freshness"
22
24
  ],
23
25
  "sideEffects": false,
24
26
  "exports": {
@@ -34,6 +36,10 @@
34
36
  "types": "./dist/mcp.d.ts",
35
37
  "import": "./dist/mcp.js"
36
38
  },
39
+ "./headings": {
40
+ "types": "./dist/headings.d.ts",
41
+ "import": "./dist/headings.js"
42
+ },
37
43
  "./markdown": {
38
44
  "types": "./dist/markdown.d.ts",
39
45
  "import": "./dist/markdown.js"
@@ -61,6 +67,34 @@
61
67
  "./blocks": {
62
68
  "types": "./dist/blocks.d.ts",
63
69
  "import": "./dist/blocks.js"
70
+ },
71
+ "./links": {
72
+ "types": "./dist/links.d.ts",
73
+ "import": "./dist/links.js"
74
+ },
75
+ "./maps": {
76
+ "types": "./dist/maps.d.ts",
77
+ "import": "./dist/maps.js"
78
+ },
79
+ "./freshness": {
80
+ "types": "./dist/freshness.d.ts",
81
+ "import": "./dist/freshness.js"
82
+ },
83
+ "./text": {
84
+ "types": "./dist/text.d.ts",
85
+ "import": "./dist/text.js"
86
+ },
87
+ "./validation": {
88
+ "types": "./dist/validation.d.ts",
89
+ "import": "./dist/validation.js"
90
+ },
91
+ "./well-known": {
92
+ "types": "./dist/well-known.d.ts",
93
+ "import": "./dist/well-known.js"
94
+ },
95
+ "./conformance": {
96
+ "types": "./dist/conformance.d.ts",
97
+ "import": "./dist/conformance.js"
64
98
  }
65
99
  },
66
100
  "files": [