@nyuchi/mzizi-mcp 0.9.1 → 0.10.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.
Files changed (97) hide show
  1. package/LICENSE +202 -0
  2. package/README.md +115 -85
  3. package/dist/access.d.ts +69 -0
  4. package/dist/access.d.ts.map +1 -0
  5. package/dist/access.js +72 -0
  6. package/dist/access.js.map +1 -0
  7. package/dist/auth/authkit-handler.d.ts +4 -3
  8. package/dist/auth/authkit-handler.d.ts.map +1 -1
  9. package/dist/auth/authkit-handler.js +52 -6
  10. package/dist/auth/authkit-handler.js.map +1 -1
  11. package/dist/auth/front.d.ts +17 -0
  12. package/dist/auth/front.d.ts.map +1 -0
  13. package/dist/auth/front.js +25 -0
  14. package/dist/auth/front.js.map +1 -0
  15. package/dist/auth/mcp-api-handler.d.ts +20 -7
  16. package/dist/auth/mcp-api-handler.d.ts.map +1 -1
  17. package/dist/auth/mcp-api-handler.js +43 -29
  18. package/dist/auth/mcp-api-handler.js.map +1 -1
  19. package/dist/desk-context.d.ts +33 -0
  20. package/dist/desk-context.d.ts.map +1 -0
  21. package/dist/desk-context.js +49 -0
  22. package/dist/desk-context.js.map +1 -0
  23. package/dist/docs-federation.d.ts +68 -0
  24. package/dist/docs-federation.d.ts.map +1 -0
  25. package/dist/docs-federation.js +282 -0
  26. package/dist/docs-federation.js.map +1 -0
  27. package/dist/env.d.ts +7 -8
  28. package/dist/env.d.ts.map +1 -1
  29. package/dist/env.js +5 -5
  30. package/dist/fundi-a2a.d.ts +1 -1
  31. package/dist/fundi-a2a.js +2 -2
  32. package/dist/fundi-a2a.js.map +1 -1
  33. package/dist/fundi-client.d.ts +24 -4
  34. package/dist/fundi-client.d.ts.map +1 -1
  35. package/dist/fundi-client.js +91 -4
  36. package/dist/fundi-client.js.map +1 -1
  37. package/dist/generated/registry-pin.d.ts +5 -0
  38. package/dist/generated/registry-pin.d.ts.map +1 -0
  39. package/dist/generated/registry-pin.js +3 -0
  40. package/dist/generated/registry-pin.js.map +1 -0
  41. package/dist/generated/registry.d.ts +23 -0
  42. package/dist/generated/registry.d.ts.map +1 -0
  43. package/dist/generated/registry.js +1204 -0
  44. package/dist/generated/registry.js.map +1 -0
  45. package/dist/generated/skills.d.ts +18 -0
  46. package/dist/generated/skills.d.ts.map +1 -0
  47. package/dist/generated/skills.js +67 -0
  48. package/dist/generated/skills.js.map +1 -0
  49. package/dist/http.d.ts +18 -9
  50. package/dist/http.d.ts.map +1 -1
  51. package/dist/http.js +16 -13
  52. package/dist/http.js.map +1 -1
  53. package/dist/issue-desk.d.ts +152 -0
  54. package/dist/issue-desk.d.ts.map +1 -0
  55. package/dist/issue-desk.js +392 -0
  56. package/dist/issue-desk.js.map +1 -0
  57. package/dist/issue-log.d.ts +80 -0
  58. package/dist/issue-log.d.ts.map +1 -0
  59. package/dist/issue-log.js +146 -0
  60. package/dist/issue-log.js.map +1 -0
  61. package/dist/issue-report.d.ts +138 -0
  62. package/dist/issue-report.d.ts.map +1 -0
  63. package/dist/issue-report.js +112 -0
  64. package/dist/issue-report.js.map +1 -0
  65. package/dist/rate-limit.d.ts +41 -0
  66. package/dist/rate-limit.d.ts.map +1 -0
  67. package/dist/rate-limit.js +58 -0
  68. package/dist/rate-limit.js.map +1 -0
  69. package/dist/registry.d.ts +126 -0
  70. package/dist/registry.d.ts.map +1 -0
  71. package/dist/registry.js +280 -0
  72. package/dist/registry.js.map +1 -0
  73. package/dist/server.d.ts +96 -22
  74. package/dist/server.d.ts.map +1 -1
  75. package/dist/server.js +76 -32
  76. package/dist/server.js.map +1 -1
  77. package/dist/stdio.d.ts +6 -13
  78. package/dist/stdio.d.ts.map +1 -1
  79. package/dist/stdio.js +6 -29
  80. package/dist/stdio.js.map +1 -1
  81. package/dist/tools.d.ts +45 -6
  82. package/dist/tools.d.ts.map +1 -1
  83. package/dist/tools.js +299 -82
  84. package/dist/tools.js.map +1 -1
  85. package/dist/worker.d.ts +26 -14
  86. package/dist/worker.d.ts.map +1 -1
  87. package/dist/worker.js +42 -14
  88. package/dist/worker.js.map +1 -1
  89. package/package.json +24 -19
  90. package/dist/api-client.d.ts +0 -101
  91. package/dist/api-client.d.ts.map +0 -1
  92. package/dist/api-client.js +0 -200
  93. package/dist/api-client.js.map +0 -1
  94. package/dist/defaults.d.ts +0 -29
  95. package/dist/defaults.d.ts.map +0 -1
  96. package/dist/defaults.js +0 -29
  97. package/dist/defaults.js.map +0 -1
@@ -0,0 +1,280 @@
1
+ /**
2
+ * The registry this MCP serves — read from files bundled into the build.
3
+ *
4
+ * `src/generated/registry.ts` is produced at build time by
5
+ * `scripts/generate-registry.mjs` from mzizi-dev/mzizi-registry at the commit
6
+ * pinned in `registry.pin.json`. It holds the exact payloads the registry's own
7
+ * API route handlers produce for that commit, so a tool answering from here and
8
+ * a consumer reading `api.mzizi.dev/v1` at the same commit get the same bytes.
9
+ *
10
+ * There is no network call and no database anywhere below. That is the owner's
11
+ * ruling — nothing but the console touches the database — and it also removes a
12
+ * class of failure: a tool can no longer be "down" because an upstream is.
13
+ *
14
+ * Failure policy is unchanged from the HTTP client this replaced: every method
15
+ * returns a discriminated result, so a tool turns "no such component" into a
16
+ * sentence the caller can act on rather than an exception.
17
+ */
18
+ const ok = (data) => ({ ok: true, data });
19
+ const miss = (message) => ({ ok: false, reason: "not_found", message });
20
+ export function createRegistry(raw) {
21
+ // Parse on first use, once. The whole bundle is ~4 MB of JSON; a request that
22
+ // reads one component should not pay to parse 577.
23
+ const memo = new Map();
24
+ const parsed = (key, json) => {
25
+ if (json === undefined)
26
+ return undefined;
27
+ if (!memo.has(key))
28
+ memo.set(key, JSON.parse(json));
29
+ return memo.get(key);
30
+ };
31
+ const section = (name) => {
32
+ const v = parsed(`section:${name}`, raw.SECTIONS[name]);
33
+ if (v === undefined)
34
+ throw new Error(`registry bundle has no "${name}" section — regenerate it`);
35
+ return v;
36
+ };
37
+ const own = (o, k) => Object.prototype.hasOwnProperty.call(o, k);
38
+ const renames = () => section("renames");
39
+ /**
40
+ * The current name for `name`. Old `nyuchi-*` names were renamed to `mzizi-*`
41
+ * on 2026-09-27 and are baked into links and `components.json` files this
42
+ * repo does not control, so they must keep resolving — the same rule the
43
+ * registry's own `readComponent` applies.
44
+ */
45
+ function resolveName(name) {
46
+ if (own(raw.COMPONENTS, name))
47
+ return name;
48
+ const next = own(renames(), name) ? renames()[name] : undefined;
49
+ return next !== undefined && own(raw.COMPONENTS, next) ? next : undefined;
50
+ }
51
+ /** Every name a component has been known by, current first. */
52
+ function nameHistory(current) {
53
+ const map = renames();
54
+ return [current, ...Object.keys(map).filter((old) => map[old] === current)];
55
+ }
56
+ const notFound = (name) => miss(`The Mzizi registry has no component named "${name}". Check the name — list_components returns the valid set, and search matches on words.`);
57
+ return {
58
+ pin: raw.REGISTRY_PIN,
59
+ resolveName,
60
+ /** The index, filtered and paged exactly as `GET /v1/ui` does it. */
61
+ listComponents(q = {}) {
62
+ const index = section("index");
63
+ const all = index.items;
64
+ const matched = all.filter((c) => (q.node === undefined || c.node === q.node) &&
65
+ (q.owner === undefined || c.owner === q.owner) &&
66
+ (q.collection === undefined || c.collection === q.collection) &&
67
+ (q.type === undefined || c.type === q.type));
68
+ const offset = q.offset ?? 0;
69
+ const page = q.limit === undefined ? matched.slice(offset) : matched.slice(offset, offset + q.limit);
70
+ return ok({
71
+ ...index,
72
+ items: page,
73
+ meta: {
74
+ total: matched.length,
75
+ count: page.length,
76
+ offset,
77
+ limit: q.limit ?? null,
78
+ registryTotal: all.length,
79
+ filters: {
80
+ node: q.node ?? null,
81
+ owner: q.owner ?? null,
82
+ collection: q.collection ?? null,
83
+ type: q.type ?? null,
84
+ },
85
+ },
86
+ });
87
+ },
88
+ /** One component, shadcn-shaped, with its source inline. */
89
+ getComponent(name) {
90
+ const current = resolveName(name);
91
+ if (!current)
92
+ return notFound(name);
93
+ const entry = parsed(`c:${current}`, raw.COMPONENTS[current]);
94
+ if (entry.status !== 200) {
95
+ // The registry itself refuses this item (e.g. a manifest declaring more
96
+ // files than it has). Pass its reason through rather than inventing one.
97
+ return { ok: false, reason: "invalid", message: String(entry.body?.error ?? `The registry cannot serve "${current}".`) };
98
+ }
99
+ return ok(current === name ? entry.body : { ...entry.body, renamedFrom: name });
100
+ },
101
+ /** Use cases, variants, sizes, a11y notes — from the item's `meta` in registry.json. */
102
+ getComponentDocs(name) {
103
+ const current = resolveName(name);
104
+ if (!current)
105
+ return notFound(name);
106
+ return ok(parsed(`d:${current}`, raw.COMPONENT_DOCS[current]));
107
+ },
108
+ /**
109
+ * Version history, derived from the changelog and the rename map.
110
+ *
111
+ * `GET /v1/ui/{name}/versions` reads the database's `component_versions` view,
112
+ * which this server must not touch. The committed changelog records which
113
+ * release added, modified, deprecated or removed each component, and the
114
+ * rename map records every earlier name — together that is the history the
115
+ * files hold. The row shape therefore differs from the database view's; it
116
+ * is documented in the README.
117
+ */
118
+ getComponentVersions(name) {
119
+ const current = resolveName(name);
120
+ if (!current)
121
+ return notFound(name);
122
+ const names = new Set(nameHistory(current));
123
+ const changes = [];
124
+ for (const entry of section("changelog")) {
125
+ for (const change of ["added", "modified", "deprecated", "removed"]) {
126
+ const list = entry[`components_${change}`] ?? [];
127
+ if (list.some((n) => names.has(n))) {
128
+ changes.push({
129
+ version: entry.version,
130
+ title: entry.title ?? null,
131
+ change,
132
+ breaking: entry.breaking ?? null,
133
+ released_at: entry.released_at ?? null,
134
+ });
135
+ }
136
+ }
137
+ }
138
+ const previousNames = [...names].slice(1);
139
+ return ok({
140
+ data: changes,
141
+ meta: {
142
+ total: changes.length,
143
+ component: current,
144
+ previousNames,
145
+ source: "changelog",
146
+ },
147
+ });
148
+ },
149
+ /**
150
+ * Word search over components, conventions, AI instruction sets and releases.
151
+ *
152
+ * Documentation pages are NOT here — they live on docs.mzizi.dev, which this
153
+ * server federates as the `docs_*` tools.
154
+ */
155
+ search(query, limit = 50) {
156
+ const terms = query.toLowerCase().split(/\s+/).filter(Boolean);
157
+ const scored = [];
158
+ const score = (fields) => {
159
+ let total = 0;
160
+ for (const term of terms) {
161
+ let best = 0;
162
+ for (const [value, weight] of fields) {
163
+ if (value?.toLowerCase().includes(term))
164
+ best = Math.max(best, weight);
165
+ }
166
+ if (best === 0)
167
+ return 0; // every term must match somewhere
168
+ total += best;
169
+ }
170
+ return total;
171
+ };
172
+ for (const c of section("index").items) {
173
+ const s = score([
174
+ [c.name, 5],
175
+ [c.title, 4],
176
+ [(c.categories ?? []).join(" "), 3],
177
+ [c.description, 2],
178
+ ]);
179
+ const exact = c.name.toLowerCase() === query.trim().toLowerCase() ? 100 : 0;
180
+ if (s)
181
+ scored.push({ kind: "component", name: c.name, title: c.title, description: c.description, score: s + exact });
182
+ }
183
+ for (const c of section("conventions")) {
184
+ const s = score([
185
+ [c.slug, 4],
186
+ [c.title, 4],
187
+ [c.body, 1],
188
+ ]);
189
+ if (s)
190
+ scored.push({ kind: "convention", name: c.slug, title: c.title, score: s });
191
+ }
192
+ for (const i of section("aiInstructions").data) {
193
+ const s = score([
194
+ [i.name, 4],
195
+ [i.target, 3],
196
+ [i.description, 2],
197
+ ]);
198
+ if (s)
199
+ scored.push({ kind: "ai-instruction", name: i.name, description: i.description, score: s });
200
+ }
201
+ for (const r of section("changelog")) {
202
+ const s = score([
203
+ [r.version, 4],
204
+ [r.title, 2],
205
+ [r.description, 1],
206
+ ]);
207
+ if (s)
208
+ scored.push({ kind: "release", name: r.version, title: r.title, score: s });
209
+ }
210
+ scored.sort((a, b) => b.score - a.score || a.name.localeCompare(b.name));
211
+ const data = scored.slice(0, limit).map(({ score: _s, ...hit }) => hit);
212
+ return ok({
213
+ data,
214
+ meta: {
215
+ total: scored.length,
216
+ count: data.length,
217
+ query,
218
+ hint: "Documentation pages are searched by the docs_* tools (docs.mzizi.dev).",
219
+ },
220
+ });
221
+ },
222
+ getArchitecture() {
223
+ return ok(section("architecture"));
224
+ },
225
+ /** One node or rung. `n` is uncapped — a missing number is a gap, not an error. */
226
+ getNode(n) {
227
+ const key = String(n);
228
+ if (!own(raw.NODES, key)) {
229
+ return miss(`No node or rung numbered ${n}. Node numbers are labels, not a sequence — call get_architecture without a node to list every element.`);
230
+ }
231
+ return ok(parsed(`n:${key}`, raw.NODES[key]));
232
+ },
233
+ getBrand() {
234
+ return ok(section("brand"));
235
+ },
236
+ getUbuntuPillars() {
237
+ return ok(section("ubuntuPillars"));
238
+ },
239
+ getUbuntuPrinciples() {
240
+ return ok(section("ubuntuPrinciples"));
241
+ },
242
+ listAiInstructions() {
243
+ return ok(section("aiInstructions"));
244
+ },
245
+ /** By name, or by target audience (mcp-server, claude-system-prompt, …), as the API resolves it. */
246
+ getAiInstructions(name) {
247
+ if (own(raw.AI_INSTRUCTIONS, name))
248
+ return ok(parsed(`ai:${name}`, raw.AI_INSTRUCTIONS[name]));
249
+ const byTarget = section("aiInstructions").data.find((i) => i.target === name);
250
+ if (byTarget && own(raw.AI_INSTRUCTIONS, byTarget.name)) {
251
+ return ok(parsed(`ai:${byTarget.name}`, raw.AI_INSTRUCTIONS[byTarget.name]));
252
+ }
253
+ const names = section("aiInstructions").data.map((i) => i.name);
254
+ return miss(`No AI instruction set named or targeted "${name}". Available: ${names.join(", ")}.`);
255
+ },
256
+ /** The mzizi conventions — the list omits bodies; pass a name for one in full. */
257
+ listConventions() {
258
+ const rows = section("conventions").map(({ body: _b, ...rest }) => rest);
259
+ return ok({ data: rows, meta: { total: rows.length } });
260
+ },
261
+ getConvention(name) {
262
+ const all = section("conventions");
263
+ const hit = all.find((c) => c.slug === name);
264
+ if (!hit)
265
+ return miss(`No convention named "${name}". Available: ${all.map((c) => c.slug).join(", ")}.`);
266
+ return ok(hit);
267
+ },
268
+ };
269
+ }
270
+ let bundled;
271
+ /**
272
+ * The registry bundled into this build. Imported lazily so a module that only
273
+ * needs the types (or a test with a fixture) does not load 4 MB of strings.
274
+ */
275
+ export async function bundledRegistry() {
276
+ if (!bundled)
277
+ bundled = createRegistry(await import("./generated/registry.js"));
278
+ return bundled;
279
+ }
280
+ //# sourceMappingURL=registry.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"registry.js","sourceRoot":"","sources":["../src/registry.ts"],"names":[],"mappings":"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"}
package/dist/server.d.ts CHANGED
@@ -1,34 +1,108 @@
1
1
  /**
2
2
  * The Mzizi MCP server.
3
3
  *
4
- * Backed by `mzizi.dev/api/v1` over HTTP. There is no Supabase client here.
4
+ * Served from files. The registry tools answer from the bundle generated at build time
5
+ * from mzizi-dev/mzizi-registry at the commit pinned in `registry.pin.json`
6
+ * (`registry.ts`); skills from this repo's skill files (`generated/skills.ts`); docs by
7
+ * federating the Mintlify MCP at docs.mzizi.dev (`docs-federation.ts`). Nothing here
8
+ * talks to a database, and no registry data is fetched at request time.
5
9
  *
6
- * WHAT CHANGED AND WHY. This server used to build its tool catalog at startup from the
7
- * `mcp_tool_registry` table and dispatch each call to a Supabase RPC, edge function or
8
- * table read — 62 enabled tools, defined as data. Two things were wrong with that:
9
- *
10
- * 1. Components are not rows. They are real files in `nyuchi/mzizi` that the Next.js
11
- * app compiles and typechecks, so an error in one fails the build. The app serves
12
- * them over `/api/v1/*`, which makes that API the source of truth and this server
13
- * one of its clients. Reading the database put a second, uncompiled representation
14
- * in the path — one that could disagree with the code while still looking correct.
15
- *
16
- * 2. A tool surface defined in a table changes whenever someone edits a row: no diff,
17
- * no review, no test. The 10 tools live in `tools.ts` as code, so changing them is
18
- * a pull request.
19
- *
20
- * The 10 are specified in `docs/mcp-tool-consolidation.md` (mzizi repo). Each carries its
21
- * `replaces` list in `TOOL_COVERAGE`, so coverage of the old 62 is checkable rather than
22
- * asserted.
10
+ * The tool surface is code, not data: the 10 registry tools live in `tools.ts`, each
11
+ * carrying its `replaces` list in `TOOL_COVERAGE`, and the `docs_*` tools mirror
12
+ * whatever the docs server lists.
23
13
  */
24
14
  import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
15
+ import type { Registry } from "./registry.js";
16
+ import { type DocsFederationOptions } from "./docs-federation.js";
25
17
  import type { FundiToolContext } from "./fundi-client.js";
26
- export declare const MZIZI_MCP_VERSION = "0.9.1";
18
+ import { type IssueDeskContext } from "./tools.js";
19
+ export declare const MZIZI_MCP_VERSION = "0.10.0";
27
20
  export type CreateServerOptions = {
28
21
  fundi?: FundiToolContext;
29
- /** Override the API base — used by tests and by a preview deployment. */
30
- apiBaseUrl?: string;
31
- fetchImpl?: typeof fetch;
22
+ /** The signed-in user's issue desk. See `tools.ts` — absent off the Worker. */
23
+ desk?: IssueDeskContext;
24
+ /** The caller is anonymous on the Worker's free tier. See `tools.ts` and `access.ts`. */
25
+ anonymous?: {
26
+ fundi: boolean;
27
+ };
28
+ /** The registry to answer from — tests pass a fixture. Defaults to the bundled one. */
29
+ registry?: () => Promise<Registry>;
30
+ /** Docs federation settings, or `false` to register no docs tools. */
31
+ docs?: DocsFederationOptions | false;
32
32
  };
33
+ /**
34
+ * What this server exposes, computed from what was actually registered.
35
+ *
36
+ * Shared by three surfaces so they cannot disagree: the `mzizi://tools`
37
+ * resource, the `mzizi_mcp_describe` tool, and the unauthenticated
38
+ * `GET /catalogue.json` route the portal reads for its live tool count. A
39
+ * hand-maintained fourth copy is how the old `mcp_tool_registry` drifted from
40
+ * the tools it claimed to describe.
41
+ */
42
+ export declare function describeTools(registered: string[]): {
43
+ version: string;
44
+ source: {
45
+ registry: string;
46
+ skills: string;
47
+ docs: string;
48
+ };
49
+ note: string;
50
+ access: {
51
+ model: string;
52
+ signIn: {
53
+ tools: string[];
54
+ how: string;
55
+ url: string;
56
+ oauthProtectedResource: string;
57
+ };
58
+ rateLimit: string;
59
+ };
60
+ tools: {
61
+ name: string;
62
+ access: import("./access.js").ToolAccess;
63
+ replaces: readonly string[];
64
+ }[];
65
+ };
66
+ /**
67
+ * The tool catalogue WITHOUT standing up a transport.
68
+ *
69
+ * `registerMziziTools` is pure — it declares tools against an `McpServer`, and the
70
+ * registry is only read when a tool runs. So a throwaway server is a legitimate way to
71
+ * ask "what would an authenticated caller see?", and it is the only way that stays
72
+ * correct when a tool is added. The docs tools come from the same cached list the live
73
+ * server uses, which never throws (see `docsTools`).
74
+ *
75
+ * It registers exactly what an ANONYMOUS caller is offered on the Worker: the free
76
+ * tools, plus the sign-in tools, listed so the reader learns they exist. `fundi` is
77
+ * whether this Worker can reach fundi at all, which is when `mzizi_fundi` is listed.
78
+ * Each entry carries its `access` ("free" or "sign-in"); see `access.ts`.
79
+ */
80
+ export declare function mziziToolCatalogue(opts?: {
81
+ fundi?: boolean;
82
+ docs?: DocsFederationOptions | false;
83
+ }): Promise<{
84
+ version: string;
85
+ source: {
86
+ registry: string;
87
+ skills: string;
88
+ docs: string;
89
+ };
90
+ note: string;
91
+ access: {
92
+ model: string;
93
+ signIn: {
94
+ tools: string[];
95
+ how: string;
96
+ url: string;
97
+ oauthProtectedResource: string;
98
+ };
99
+ rateLimit: string;
100
+ };
101
+ tools: {
102
+ name: string;
103
+ access: import("./access.js").ToolAccess;
104
+ replaces: readonly string[];
105
+ }[];
106
+ }>;
33
107
  export declare function createMziziMcpServer(opts?: CreateServerOptions): Promise<McpServer>;
34
108
  //# sourceMappingURL=server.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"server.d.ts","sourceRoot":"","sources":["../src/server.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;GAsBG;AAEH,OAAO,EAAE,SAAS,EAAE,MAAM,yCAAyC,CAAA;AAEnE,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,mBAAmB,CAAA;AAIzD,eAAO,MAAM,iBAAiB,UAAU,CAAA;AAExC,MAAM,MAAM,mBAAmB,GAAG;IAChC,KAAK,CAAC,EAAE,gBAAgB,CAAA;IACxB,yEAAyE;IACzE,UAAU,CAAC,EAAE,MAAM,CAAA;IACnB,SAAS,CAAC,EAAE,OAAO,KAAK,CAAA;CACzB,CAAA;AAED,wBAAsB,oBAAoB,CAAC,IAAI,GAAE,mBAAwB,GAAG,OAAO,CAAC,SAAS,CAAC,CA+D7F"}
1
+ {"version":3,"file":"server.d.ts","sourceRoot":"","sources":["../src/server.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AAEH,OAAO,EAAE,SAAS,EAAE,MAAM,yCAAyC,CAAA;AACnE,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,eAAe,CAAA;AAE7C,OAAO,EAAmC,KAAK,qBAAqB,EAAE,MAAM,sBAAsB,CAAA;AAClG,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,mBAAmB,CAAA;AACzD,OAAO,EAAkD,KAAK,gBAAgB,EAAE,MAAM,YAAY,CAAA;AAIlG,eAAO,MAAM,iBAAiB,WAAW,CAAA;AAEzC,MAAM,MAAM,mBAAmB,GAAG;IAChC,KAAK,CAAC,EAAE,gBAAgB,CAAA;IACxB,+EAA+E;IAC/E,IAAI,CAAC,EAAE,gBAAgB,CAAA;IACvB,yFAAyF;IACzF,SAAS,CAAC,EAAE;QAAE,KAAK,EAAE,OAAO,CAAA;KAAE,CAAA;IAC9B,uFAAuF;IACvF,QAAQ,CAAC,EAAE,MAAM,OAAO,CAAC,QAAQ,CAAC,CAAA;IAClC,sEAAsE;IACtE,IAAI,CAAC,EAAE,qBAAqB,GAAG,KAAK,CAAA;CACrC,CAAA;AAED;;;;;;;;GAQG;AACH,wBAAgB,aAAa,CAAC,UAAU,EAAE,MAAM,EAAE;;;;;;;;;;;;;;;;;;;;;;;EAgBjD;AAED;;;;;;;;;;;;;GAaG;AACH,wBAAsB,kBAAkB,CAAC,IAAI,GAAE;IAAE,KAAK,CAAC,EAAE,OAAO,CAAC;IAAC,IAAI,CAAC,EAAE,qBAAqB,GAAG,KAAK,CAAA;CAAO;;;;;;;;;;;;;;;;;;;;;;;GAU5G;AAED,wBAAsB,oBAAoB,CAAC,IAAI,GAAE,mBAAwB,GAAG,OAAO,CAAC,SAAS,CAAC,CAmE7F"}
package/dist/server.js CHANGED
@@ -1,31 +1,71 @@
1
1
  /**
2
2
  * The Mzizi MCP server.
3
3
  *
4
- * Backed by `mzizi.dev/api/v1` over HTTP. There is no Supabase client here.
4
+ * Served from files. The registry tools answer from the bundle generated at build time
5
+ * from mzizi-dev/mzizi-registry at the commit pinned in `registry.pin.json`
6
+ * (`registry.ts`); skills from this repo's skill files (`generated/skills.ts`); docs by
7
+ * federating the Mintlify MCP at docs.mzizi.dev (`docs-federation.ts`). Nothing here
8
+ * talks to a database, and no registry data is fetched at request time.
5
9
  *
6
- * WHAT CHANGED AND WHY. This server used to build its tool catalog at startup from the
7
- * `mcp_tool_registry` table and dispatch each call to a Supabase RPC, edge function or
8
- * table read — 62 enabled tools, defined as data. Two things were wrong with that:
9
- *
10
- * 1. Components are not rows. They are real files in `nyuchi/mzizi` that the Next.js
11
- * app compiles and typechecks, so an error in one fails the build. The app serves
12
- * them over `/api/v1/*`, which makes that API the source of truth and this server
13
- * one of its clients. Reading the database put a second, uncompiled representation
14
- * in the path — one that could disagree with the code while still looking correct.
15
- *
16
- * 2. A tool surface defined in a table changes whenever someone edits a row: no diff,
17
- * no review, no test. The 10 tools live in `tools.ts` as code, so changing them is
18
- * a pull request.
19
- *
20
- * The 10 are specified in `docs/mcp-tool-consolidation.md` (mzizi repo). Each carries its
21
- * `replaces` list in `TOOL_COVERAGE`, so coverage of the old 62 is checkable rather than
22
- * asserted.
10
+ * The tool surface is code, not data: the 10 registry tools live in `tools.ts`, each
11
+ * carrying its `replaces` list in `TOOL_COVERAGE`, and the `docs_*` tools mirror
12
+ * whatever the docs server lists.
23
13
  */
24
14
  import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
25
- import { MziziApiClient } from "./api-client.js";
15
+ import { REGISTRY_PIN as REGISTRY_PIN_INFO } from "./generated/registry-pin.js";
16
+ import { registerDocsTools, DOCS_MCP_URL } from "./docs-federation.js";
26
17
  import { registerMziziTools, TOOL_COVERAGE, TOOL_PREFIX } from "./tools.js";
27
18
  import { jsonContent } from "./tool-result.js";
28
- export const MZIZI_MCP_VERSION = "0.9.1";
19
+ import { accessFor, accessSummary } from "./access.js";
20
+ export const MZIZI_MCP_VERSION = "0.10.0";
21
+ /**
22
+ * What this server exposes, computed from what was actually registered.
23
+ *
24
+ * Shared by three surfaces so they cannot disagree: the `mzizi://tools`
25
+ * resource, the `mzizi_mcp_describe` tool, and the unauthenticated
26
+ * `GET /catalogue.json` route the portal reads for its live tool count. A
27
+ * hand-maintained fourth copy is how the old `mcp_tool_registry` drifted from
28
+ * the tools it claimed to describe.
29
+ */
30
+ export function describeTools(registered) {
31
+ return {
32
+ version: MZIZI_MCP_VERSION,
33
+ source: {
34
+ registry: `${REGISTRY_PIN_INFO.repository}/tree/${REGISTRY_PIN_INFO.ref}`,
35
+ skills: "mzizi-dev/agent-tools mzizi-skills/skills (bundled at build time)",
36
+ docs: DOCS_MCP_URL,
37
+ },
38
+ note: "Registry data and skills are files bundled into this build at a pinned commit; docs_* tools are forwarded to the docs.mzizi.dev MCP. This server holds no database credential.",
39
+ access: accessSummary(registered),
40
+ tools: registered.map((name) => ({
41
+ name: name.startsWith("docs_") ? name : `${TOOL_PREFIX}${name}`,
42
+ access: accessFor(name),
43
+ replaces: TOOL_COVERAGE[name] ?? [],
44
+ })),
45
+ };
46
+ }
47
+ /**
48
+ * The tool catalogue WITHOUT standing up a transport.
49
+ *
50
+ * `registerMziziTools` is pure — it declares tools against an `McpServer`, and the
51
+ * registry is only read when a tool runs. So a throwaway server is a legitimate way to
52
+ * ask "what would an authenticated caller see?", and it is the only way that stays
53
+ * correct when a tool is added. The docs tools come from the same cached list the live
54
+ * server uses, which never throws (see `docsTools`).
55
+ *
56
+ * It registers exactly what an ANONYMOUS caller is offered on the Worker: the free
57
+ * tools, plus the sign-in tools, listed so the reader learns they exist. `fundi` is
58
+ * whether this Worker can reach fundi at all, which is when `mzizi_fundi` is listed.
59
+ * Each entry carries its `access` ("free" or "sign-in"); see `access.ts`.
60
+ */
61
+ export async function mziziToolCatalogue(opts = {}) {
62
+ const server = new McpServer({ name: "mzizi-mcp", version: MZIZI_MCP_VERSION, title: "Mzizi" }, { capabilities: { tools: {}, resources: {} } });
63
+ const registered = registerMziziTools(server, { anonymous: { fundi: opts.fundi === true } });
64
+ const docs = opts.docs === false ? [] : await registerDocsTools(server, opts.docs ?? {});
65
+ // Mirrors the direct registration in `createMziziMcpServer`, which is the one
66
+ // tool not declared in `tools.ts`.
67
+ return describeTools([...registered, "mcp_describe", ...docs]);
68
+ }
29
69
  export async function createMziziMcpServer(opts = {}) {
30
70
  const server = new McpServer({
31
71
  name: "mzizi-mcp",
@@ -36,19 +76,15 @@ export async function createMziziMcpServer(opts = {}) {
36
76
  tools: { listChanged: true },
37
77
  resources: { listChanged: true },
38
78
  },
39
- instructions: "Access to the Mzizi design system (a nyuchi-brand project of the Bundu ecosystem) over its public API: components, design tokens, brand, the DNA-helix architecture, Ubuntu doctrine, agent skills and releases. Ten tools. Start with mzizi_search if you do not know the name of what you want; mzizi_get_component returns a component in full in one read; mzizi_get_architecture returns the helix and takes an uncapped node number.",
79
+ instructions: "Access to the Mzizi design system: components, design tokens, brand, the DNA-helix architecture, Ubuntu doctrine and conventions, agent skills and releases (the mzizi_* tools, served from files bundled at a pinned registry commit), plus the documentation site (the docs_* tools, forwarded to docs.mzizi.dev). Start with mzizi_search if you do not know the name of what you want; mzizi_get_component returns a component in full in one read; mzizi_get_architecture returns the helix and takes an uncapped node number; docs_search_mzizi searches the documentation. Every tool is free without an account except mzizi_fundi and mzizi_report_issue, which act as your Mzizi console user and need sign-in; called without it they say how to sign in.",
40
80
  });
41
- const api = new MziziApiClient({ baseUrl: opts.apiBaseUrl, fetchImpl: opts.fetchImpl });
42
- const registered = registerMziziTools(server, { api, fundi: opts.fundi });
43
- const describe = () => ({
44
- version: MZIZI_MCP_VERSION,
45
- source: "https://mzizi.dev/api/v1",
46
- note: "Components are files in nyuchi/mzizi compiled by the Next.js app and served over /api/v1. This server reads that API and holds no database credential.",
47
- tools: registered.map((name) => ({
48
- name: `${TOOL_PREFIX}${name}`,
49
- replaces: TOOL_COVERAGE[name] ?? [],
50
- })),
81
+ const registered = registerMziziTools(server, {
82
+ registry: opts.registry,
83
+ fundi: opts.fundi,
84
+ desk: opts.desk,
85
+ anonymous: opts.anonymous,
51
86
  });
87
+ const describe = () => describeTools(registered);
52
88
  // Computed from what was actually registered, never a hand-maintained list — a
53
89
  // hardcoded catalog is how the old registry drifted from the tools it described.
54
90
  server.registerResource("mzizi-tools", "mzizi://tools", {
@@ -64,11 +100,19 @@ export async function createMziziMcpServer(opts = {}) {
64
100
  },
65
101
  ],
66
102
  }));
103
+ // Registered here rather than in `tools.ts` because it closes over `describe`,
104
+ // but it still has to land in `registered` — otherwise every catalogue surface
105
+ // reports one tool fewer than the server actually answers to.
106
+ registered.push("mcp_describe");
67
107
  server.registerTool(`${TOOL_PREFIX}mcp_describe`, {
68
108
  title: "Describe this server",
69
- description: "What this MCP server exposes: its tools, what each replaces, and where its data comes from.",
109
+ description: "What this MCP server exposes: its tools, which are free and which need sign-in, what each replaces, and where its data comes from.",
70
110
  annotations: { readOnlyHint: true, idempotentHint: true, openWorldHint: false },
71
111
  }, async () => jsonContent(describe()));
112
+ // Last, so the describe tool and resource report them too: `describe` reads
113
+ // `registered` when called, not when defined.
114
+ if (opts.docs !== false)
115
+ registered.push(...(await registerDocsTools(server, opts.docs ?? {})));
72
116
  return server;
73
117
  }
74
118
  //# sourceMappingURL=server.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"server.js","sourceRoot":"","sources":["../src/server.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;GAsBG;AAEH,OAAO,EAAE,SAAS,EAAE,MAAM,yCAAyC,CAAA;AACnE,OAAO,EAAE,cAAc,EAAE,MAAM,iBAAiB,CAAA;AAEhD,OAAO,EAAE,kBAAkB,EAAE,aAAa,EAAE,WAAW,EAAE,MAAM,YAAY,CAAA;AAC3E,OAAO,EAAE,WAAW,EAAE,MAAM,kBAAkB,CAAA;AAE9C,MAAM,CAAC,MAAM,iBAAiB,GAAG,OAAO,CAAA;AASxC,MAAM,CAAC,KAAK,UAAU,oBAAoB,CAAC,OAA4B,EAAE;IACvE,MAAM,MAAM,GAAG,IAAI,SAAS,CAC1B;QACE,IAAI,EAAE,WAAW;QACjB,OAAO,EAAE,iBAAiB;QAC1B,KAAK,EAAE,OAAO;KACf,EACD;QACE,YAAY,EAAE;YACZ,KAAK,EAAE,EAAE,WAAW,EAAE,IAAI,EAAE;YAC5B,SAAS,EAAE,EAAE,WAAW,EAAE,IAAI,EAAE;SACjC;QACD,YAAY,EACV,4aAA4a;KAC/a,CACF,CAAA;IAED,MAAM,GAAG,GAAG,IAAI,cAAc,CAAC,EAAE,OAAO,EAAE,IAAI,CAAC,UAAU,EAAE,SAAS,EAAE,IAAI,CAAC,SAAS,EAAE,CAAC,CAAA;IACvF,MAAM,UAAU,GAAG,kBAAkB,CAAC,MAAM,EAAE,EAAE,GAAG,EAAE,KAAK,EAAE,IAAI,CAAC,KAAK,EAAE,CAAC,CAAA;IAEzE,MAAM,QAAQ,GAAG,GAAG,EAAE,CAAC,CAAC;QACtB,OAAO,EAAE,iBAAiB;QAC1B,MAAM,EAAE,0BAA0B;QAClC,IAAI,EAAE,wJAAwJ;QAC9J,KAAK,EAAE,UAAU,CAAC,GAAG,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,CAAC;YAC/B,IAAI,EAAE,GAAG,WAAW,GAAG,IAAI,EAAE;YAC7B,QAAQ,EAAE,aAAa,CAAC,IAAI,CAAC,IAAI,EAAE;SACpC,CAAC,CAAC;KACJ,CAAC,CAAA;IAEF,+EAA+E;IAC/E,iFAAiF;IACjF,MAAM,CAAC,gBAAgB,CACrB,aAAa,EACb,eAAe,EACf;QACE,KAAK,EAAE,iBAAiB;QACxB,WAAW,EAAE,sEAAsE;QACnF,QAAQ,EAAE,kBAAkB;KAC7B,EACD,KAAK,EAAE,GAAG,EAAE,EAAE,CAAC,CAAC;QACd,QAAQ,EAAE;YACR;gBACE,GAAG,EAAE,GAAG,CAAC,IAAI;gBACb,QAAQ,EAAE,kBAAkB;gBAC5B,IAAI,EAAE,IAAI,CAAC,SAAS,CAAC,QAAQ,EAAE,EAAE,IAAI,EAAE,CAAC,CAAC;aAC1C;SACF;KACF,CAAC,CACH,CAAA;IAED,MAAM,CAAC,YAAY,CACjB,GAAG,WAAW,cAAc,EAC5B;QACE,KAAK,EAAE,sBAAsB;QAC7B,WAAW,EACT,6FAA6F;QAC/F,WAAW,EAAE,EAAE,YAAY,EAAE,IAAI,EAAE,cAAc,EAAE,IAAI,EAAE,aAAa,EAAE,KAAK,EAAE;KAChF,EACD,KAAK,IAAI,EAAE,CAAC,WAAW,CAAC,QAAQ,EAAE,CAAC,CACpC,CAAA;IAED,OAAO,MAAM,CAAA;AACf,CAAC"}
1
+ {"version":3,"file":"server.js","sourceRoot":"","sources":["../src/server.ts"],"names":[],"mappings":"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"}
package/dist/stdio.d.ts CHANGED
@@ -3,20 +3,13 @@
3
3
  * stdio entry — for the MCP registry (`npx mzizi-mcp`) and local MCP clients
4
4
  * (Claude Code, etc.).
5
5
  *
6
- * Spawns the server over the stdio transport, using a long-lived Supabase
7
- * anon client. RLS on `component_documents` enforces read-only.
6
+ * Zero-config and credential-free: the registry data and skills are bundled
7
+ * into this package at build time (from the mzizi-registry commit pinned in
8
+ * `registry.pin.json`), so the registry tools need no network at all. The
9
+ * `docs_*` tools forward to the public docs MCP at docs.mzizi.dev.
8
10
  *
9
- * Zero-config: the public Mzizi registry URL + publishable key are baked in
10
- * as defaults (see defaults.ts — they are not secrets), so `npx mzizi-mcp`
11
- * works with no environment set. This is the sanctioned headless path: the
12
- * hosted mcp.mzizi.dev endpoint sits behind an interactive, browser-only
13
- * WorkOS signup gate that a headless agent cannot complete, whereas this bin
14
- * reads the same public registry directly.
15
- *
16
- * Env (optional — override the defaults to point at a fork / self-hosted
17
- * mirror):
18
- * SUPABASE_URL (or NEXT_PUBLIC_SUPABASE_URL)
19
- * SUPABASE_PUBLISHABLE_KEY (or NEXT_PUBLIC_SUPABASE_ANON_KEY)
11
+ * `MZIZI_API_BASE` is gone: there is no registry API to point at any more. To
12
+ * serve different registry content, build with a different pin.
20
13
  */
21
14
  export {};
22
15
  //# sourceMappingURL=stdio.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"stdio.d.ts","sourceRoot":"","sources":["../src/stdio.ts"],"names":[],"mappings":";AACA;;;;;;;;;;;;;;;;;;GAkBG"}
1
+ {"version":3,"file":"stdio.d.ts","sourceRoot":"","sources":["../src/stdio.ts"],"names":[],"mappings":";AACA;;;;;;;;;;;GAWG"}