@nyuchi/mzizi-mcp 0.5.0 → 0.7.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,86 @@
1
+ /**
2
+ * HTTP client for the Mzizi API — the MCP's only data source.
3
+ *
4
+ * The architecture: the Next.js app at mzizi.dev builds the registry from files at
5
+ * build time and serves it over `/api/v1/*`. This MCP is a client of that API. It does
6
+ * NOT talk to Supabase, and it does not hold a database credential, because component
7
+ * documents and doctrine are files in `nyuchi/mzizi` — not rows.
8
+ *
9
+ * What that buys, beyond matching the architecture:
10
+ *
11
+ * - One source of truth. The API and the MCP answer from the same build, so an agent
12
+ * over MCP and a consumer over HTTP cannot get different answers.
13
+ * - No credential. The previous design read `mcp_tool_registry` and dispatched to
14
+ * Supabase RPCs with an anon key; there is nothing to leak or rotate here.
15
+ * - The tool surface stops being data. It was built at startup from a table, which
16
+ * meant a row edit silently changed what the server exposed with no review. The
17
+ * tools are now code (see `tools.ts`), so a change to them is a diff.
18
+ *
19
+ * Failure policy: every method returns a discriminated result rather than throwing, so
20
+ * a tool can turn an upstream outage into a sentence the caller can act on. An MCP tool
21
+ * that throws an opaque fetch error teaches the agent nothing.
22
+ */
23
+ export declare const DEFAULT_API_BASE = "https://mzizi.dev/api/v1";
24
+ export type ApiOk<T> = {
25
+ ok: true;
26
+ data: T;
27
+ };
28
+ export type ApiErr = {
29
+ ok: false;
30
+ /** Machine-readable reason, for a tool to branch on. */
31
+ reason: "not_found" | "timeout" | "network" | "bad_status" | "bad_body";
32
+ /** A sentence for the caller. Not a status code. */
33
+ message: string;
34
+ status?: number;
35
+ };
36
+ export type ApiResult<T> = ApiOk<T> | ApiErr;
37
+ export type MziziApiOptions = {
38
+ /** Base URL, no trailing slash. Defaults to the public API. */
39
+ baseUrl?: string;
40
+ timeoutMs?: number;
41
+ /** Injectable for tests and for a Worker's bound fetch. */
42
+ fetchImpl?: typeof fetch;
43
+ };
44
+ export declare class MziziApiClient {
45
+ private readonly baseUrl;
46
+ private readonly timeoutMs;
47
+ private readonly fetchImpl;
48
+ constructor(opts?: MziziApiOptions);
49
+ /**
50
+ * GET a JSON path under the API base.
51
+ *
52
+ * `path` is appended verbatim, so every caller must encode its own segments —
53
+ * a component name arriving from an agent is untrusted input, and an unencoded
54
+ * `../` would climb out of /api/v1.
55
+ */
56
+ get<T>(path: string, query?: Record<string, string | number | undefined>): Promise<ApiResult<T>>;
57
+ /** Registry index. */
58
+ listComponents(): Promise<ApiResult<unknown>>;
59
+ /** One component, shadcn-shaped, with metadata and files. */
60
+ getComponent(name: string): Promise<ApiResult<unknown>>;
61
+ /** Per-component docs: use cases, variants, a11y. */
62
+ getComponentDocs(name: string): Promise<ApiResult<unknown>>;
63
+ /** Per-component version history. */
64
+ getComponentVersions(name: string): Promise<ApiResult<unknown>>;
65
+ /** Cross-resource search — components, docs, changelog. */
66
+ search(query: string): Promise<ApiResult<unknown>>;
67
+ /** The DNA double helix: nodes, rungs, strands, live counts. */
68
+ getArchitecture(): Promise<ApiResult<unknown>>;
69
+ /** One node. `n` is uncapped — the node set grows, so never bound it here. */
70
+ getNode(n: number): Promise<ApiResult<unknown>>;
71
+ /** Brand system: minerals, heritage, typography, spacing, ecosystem. */
72
+ getBrand(): Promise<ApiResult<unknown>>;
73
+ getUbuntuPillars(): Promise<ApiResult<unknown>>;
74
+ getUbuntuPrinciples(): Promise<ApiResult<unknown>>;
75
+ listAiInstructions(): Promise<ApiResult<unknown>>;
76
+ getAiInstructions(name: string): Promise<ApiResult<unknown>>;
77
+ listSkills(): Promise<ApiResult<unknown>>;
78
+ getSkill(name: string): Promise<ApiResult<unknown>>;
79
+ listChangelog(): Promise<ApiResult<unknown>>;
80
+ getRelease(version: string): Promise<ApiResult<unknown>>;
81
+ /** Live counts + usage metrics. Derived upstream, never a stored number. */
82
+ getStats(): Promise<ApiResult<unknown>>;
83
+ /** Service health. */
84
+ getHealth(): Promise<ApiResult<unknown>>;
85
+ }
86
+ //# sourceMappingURL=api-client.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"api-client.d.ts","sourceRoot":"","sources":["../src/api-client.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;GAqBG;AAEH,eAAO,MAAM,gBAAgB,6BAA6B,CAAA;AAK1D,MAAM,MAAM,KAAK,CAAC,CAAC,IAAI;IAAE,EAAE,EAAE,IAAI,CAAC;IAAC,IAAI,EAAE,CAAC,CAAA;CAAE,CAAA;AAC5C,MAAM,MAAM,MAAM,GAAG;IACnB,EAAE,EAAE,KAAK,CAAA;IACT,wDAAwD;IACxD,MAAM,EAAE,WAAW,GAAG,SAAS,GAAG,SAAS,GAAG,YAAY,GAAG,UAAU,CAAA;IACvE,oDAAoD;IACpD,OAAO,EAAE,MAAM,CAAA;IACf,MAAM,CAAC,EAAE,MAAM,CAAA;CAChB,CAAA;AACD,MAAM,MAAM,SAAS,CAAC,CAAC,IAAI,KAAK,CAAC,CAAC,CAAC,GAAG,MAAM,CAAA;AAE5C,MAAM,MAAM,eAAe,GAAG;IAC5B,+DAA+D;IAC/D,OAAO,CAAC,EAAE,MAAM,CAAA;IAChB,SAAS,CAAC,EAAE,MAAM,CAAA;IAClB,2DAA2D;IAC3D,SAAS,CAAC,EAAE,OAAO,KAAK,CAAA;CACzB,CAAA;AAED,qBAAa,cAAc;IACzB,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAQ;IAChC,OAAO,CAAC,QAAQ,CAAC,SAAS,CAAQ;IAClC,OAAO,CAAC,QAAQ,CAAC,SAAS,CAAc;gBAE5B,IAAI,GAAE,eAAoB;IAMtC;;;;;;OAMG;IACG,GAAG,CAAC,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,KAAK,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,GAAG,SAAS,CAAC,GAAG,OAAO,CAAC,SAAS,CAAC,CAAC,CAAC,CAAC;IAyEtG,sBAAsB;IACtB,cAAc;IAId,6DAA6D;IAC7D,YAAY,CAAC,IAAI,EAAE,MAAM;IAIzB,qDAAqD;IACrD,gBAAgB,CAAC,IAAI,EAAE,MAAM;IAI7B,qCAAqC;IACrC,oBAAoB,CAAC,IAAI,EAAE,MAAM;IAIjC,2DAA2D;IAC3D,MAAM,CAAC,KAAK,EAAE,MAAM;IAIpB,gEAAgE;IAChE,eAAe;IAIf,8EAA8E;IAC9E,OAAO,CAAC,CAAC,EAAE,MAAM;IAIjB,wEAAwE;IACxE,QAAQ;IAIR,gBAAgB;IAIhB,mBAAmB;IAInB,kBAAkB;IAIlB,iBAAiB,CAAC,IAAI,EAAE,MAAM;IAI9B,UAAU;IAIV,QAAQ,CAAC,IAAI,EAAE,MAAM;IAIrB,aAAa;IAIb,UAAU,CAAC,OAAO,EAAE,MAAM;IAI1B,4EAA4E;IAC5E,QAAQ;IAIR,sBAAsB;IACtB,SAAS;CAGV"}
@@ -0,0 +1,179 @@
1
+ /**
2
+ * HTTP client for the Mzizi API — the MCP's only data source.
3
+ *
4
+ * The architecture: the Next.js app at mzizi.dev builds the registry from files at
5
+ * build time and serves it over `/api/v1/*`. This MCP is a client of that API. It does
6
+ * NOT talk to Supabase, and it does not hold a database credential, because component
7
+ * documents and doctrine are files in `nyuchi/mzizi` — not rows.
8
+ *
9
+ * What that buys, beyond matching the architecture:
10
+ *
11
+ * - One source of truth. The API and the MCP answer from the same build, so an agent
12
+ * over MCP and a consumer over HTTP cannot get different answers.
13
+ * - No credential. The previous design read `mcp_tool_registry` and dispatched to
14
+ * Supabase RPCs with an anon key; there is nothing to leak or rotate here.
15
+ * - The tool surface stops being data. It was built at startup from a table, which
16
+ * meant a row edit silently changed what the server exposed with no review. The
17
+ * tools are now code (see `tools.ts`), so a change to them is a diff.
18
+ *
19
+ * Failure policy: every method returns a discriminated result rather than throwing, so
20
+ * a tool can turn an upstream outage into a sentence the caller can act on. An MCP tool
21
+ * that throws an opaque fetch error teaches the agent nothing.
22
+ */
23
+ export const DEFAULT_API_BASE = "https://mzizi.dev/api/v1";
24
+ /** How long any single upstream call may take before it is abandoned. */
25
+ const DEFAULT_TIMEOUT_MS = 10_000;
26
+ export class MziziApiClient {
27
+ baseUrl;
28
+ timeoutMs;
29
+ fetchImpl;
30
+ constructor(opts = {}) {
31
+ this.baseUrl = (opts.baseUrl ?? DEFAULT_API_BASE).replace(/\/+$/, "");
32
+ this.timeoutMs = opts.timeoutMs ?? DEFAULT_TIMEOUT_MS;
33
+ this.fetchImpl = opts.fetchImpl ?? fetch;
34
+ }
35
+ /**
36
+ * GET a JSON path under the API base.
37
+ *
38
+ * `path` is appended verbatim, so every caller must encode its own segments —
39
+ * a component name arriving from an agent is untrusted input, and an unencoded
40
+ * `../` would climb out of /api/v1.
41
+ */
42
+ async get(path, query) {
43
+ let url = `${this.baseUrl}${path.startsWith("/") ? path : `/${path}`}`;
44
+ if (query) {
45
+ const qs = new URLSearchParams();
46
+ for (const [k, v] of Object.entries(query)) {
47
+ if (v !== undefined && v !== "")
48
+ qs.set(k, String(v));
49
+ }
50
+ const s = qs.toString();
51
+ if (s)
52
+ url += `?${s}`;
53
+ }
54
+ const controller = new AbortController();
55
+ const timer = setTimeout(() => controller.abort(), this.timeoutMs);
56
+ try {
57
+ const res = await this.fetchImpl(url, {
58
+ signal: controller.signal,
59
+ headers: { accept: "application/json" },
60
+ });
61
+ if (res.status === 404) {
62
+ return {
63
+ ok: false,
64
+ reason: "not_found",
65
+ status: 404,
66
+ message: `The Mzizi API has no record at ${path}. Check the name — list_components returns the valid set.`,
67
+ };
68
+ }
69
+ if (!res.ok) {
70
+ // 503 is the API's documented "database not configured" signal. It is worth
71
+ // distinguishing in words, because it means the deployment is misconfigured
72
+ // rather than that the caller asked for something wrong.
73
+ const hint = res.status === 503
74
+ ? " The API reports it is not fully configured; this is a deployment problem, not a bad request."
75
+ : "";
76
+ return {
77
+ ok: false,
78
+ reason: "bad_status",
79
+ status: res.status,
80
+ message: `The Mzizi API answered ${res.status} for ${path}.${hint}`,
81
+ };
82
+ }
83
+ try {
84
+ return { ok: true, data: (await res.json()) };
85
+ }
86
+ catch {
87
+ return {
88
+ ok: false,
89
+ reason: "bad_body",
90
+ status: res.status,
91
+ message: `The Mzizi API returned a non-JSON body for ${path}. The endpoint may be behind a redirect or an auth gate.`,
92
+ };
93
+ }
94
+ }
95
+ catch (err) {
96
+ if (err?.name === "AbortError") {
97
+ return {
98
+ ok: false,
99
+ reason: "timeout",
100
+ message: `The Mzizi API did not respond within ${this.timeoutMs}ms for ${path}.`,
101
+ };
102
+ }
103
+ return {
104
+ ok: false,
105
+ reason: "network",
106
+ message: `Could not reach the Mzizi API at ${this.baseUrl}: ${err?.message ?? "unknown error"}.`,
107
+ };
108
+ }
109
+ finally {
110
+ clearTimeout(timer);
111
+ }
112
+ }
113
+ // ── The endpoints the 10 tools are built from ──────────────────────
114
+ /** Registry index. */
115
+ listComponents() {
116
+ return this.get("/ui");
117
+ }
118
+ /** One component, shadcn-shaped, with metadata and files. */
119
+ getComponent(name) {
120
+ return this.get(`/ui/${encodeURIComponent(name)}`);
121
+ }
122
+ /** Per-component docs: use cases, variants, a11y. */
123
+ getComponentDocs(name) {
124
+ return this.get(`/ui/${encodeURIComponent(name)}/docs`);
125
+ }
126
+ /** Per-component version history. */
127
+ getComponentVersions(name) {
128
+ return this.get(`/ui/${encodeURIComponent(name)}/versions`);
129
+ }
130
+ /** Cross-resource search — components, docs, changelog. */
131
+ search(query) {
132
+ return this.get("/search", { q: query });
133
+ }
134
+ /** The DNA double helix: nodes, rungs, strands, live counts. */
135
+ getArchitecture() {
136
+ return this.get("/architecture");
137
+ }
138
+ /** One node. `n` is uncapped — the node set grows, so never bound it here. */
139
+ getNode(n) {
140
+ return this.get(`/architecture/nodes/${encodeURIComponent(String(n))}`);
141
+ }
142
+ /** Brand system: minerals, heritage, typography, spacing, ecosystem. */
143
+ getBrand() {
144
+ return this.get("/brand");
145
+ }
146
+ getUbuntuPillars() {
147
+ return this.get("/ubuntu/pillars");
148
+ }
149
+ getUbuntuPrinciples() {
150
+ return this.get("/ubuntu/principles");
151
+ }
152
+ listAiInstructions() {
153
+ return this.get("/ai/instructions");
154
+ }
155
+ getAiInstructions(name) {
156
+ return this.get(`/ai/instructions/${encodeURIComponent(name)}`);
157
+ }
158
+ listSkills() {
159
+ return this.get("/skills");
160
+ }
161
+ getSkill(name) {
162
+ return this.get(`/skills/${encodeURIComponent(name)}`);
163
+ }
164
+ listChangelog() {
165
+ return this.get("/changelog");
166
+ }
167
+ getRelease(version) {
168
+ return this.get(`/changelog/${encodeURIComponent(version)}`);
169
+ }
170
+ /** Live counts + usage metrics. Derived upstream, never a stored number. */
171
+ getStats() {
172
+ return this.get("/stats");
173
+ }
174
+ /** Service health. */
175
+ getHealth() {
176
+ return this.get("/health");
177
+ }
178
+ }
179
+ //# sourceMappingURL=api-client.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"api-client.js","sourceRoot":"","sources":["../src/api-client.ts"],"names":[],"mappings":"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"}
package/dist/env.d.ts CHANGED
@@ -19,6 +19,7 @@ export interface Env {
19
19
  WORKOS_M2M_CLIENT_ID?: string;
20
20
  WORKOS_M2M_CLIENT_SECRET?: string;
21
21
  FUNDI_URL?: string;
22
+ FUNDI_SERVICE?: Fetcher;
22
23
  COOKIE_ENCRYPTION_KEY: string;
23
24
  OAUTH_KV: KVNamespace;
24
25
  OAUTH_PROVIDER: OAuthHelpers;
package/dist/env.d.ts.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"env.d.ts","sourceRoot":"","sources":["../src/env.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AAEH,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,oCAAoC,CAAA;AAEtE,MAAM,WAAW,GAAG;IAElB,YAAY,EAAE,MAAM,CAAA;IACpB,wBAAwB,EAAE,MAAM,CAAA;IAChC,mBAAmB,CAAC,EAAE,MAAM,CAAA;IAM5B,gBAAgB,EAAE,MAAM,CAAA;IACxB,qBAAqB,EAAE,MAAM,CAAA;IAO7B,oBAAoB,CAAC,EAAE,MAAM,CAAA;IAC7B,wBAAwB,CAAC,EAAE,MAAM,CAAA;IACjC,SAAS,CAAC,EAAE,MAAM,CAAA;IAGlB,qBAAqB,EAAE,MAAM,CAAA;IAG7B,QAAQ,EAAE,WAAW,CAAA;IACrB,cAAc,EAAE,YAAY,CAAA;CAC7B"}
1
+ {"version":3,"file":"env.d.ts","sourceRoot":"","sources":["../src/env.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AAEH,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,oCAAoC,CAAA;AAEtE,MAAM,WAAW,GAAG;IAElB,YAAY,EAAE,MAAM,CAAA;IACpB,wBAAwB,EAAE,MAAM,CAAA;IAChC,mBAAmB,CAAC,EAAE,MAAM,CAAA;IAM5B,gBAAgB,EAAE,MAAM,CAAA;IACxB,qBAAqB,EAAE,MAAM,CAAA;IAO7B,oBAAoB,CAAC,EAAE,MAAM,CAAA;IAC7B,wBAAwB,CAAC,EAAE,MAAM,CAAA;IACjC,SAAS,CAAC,EAAE,MAAM,CAAA;IAUlB,aAAa,CAAC,EAAE,OAAO,CAAA;IAGvB,qBAAqB,EAAE,MAAM,CAAA;IAG7B,QAAQ,EAAE,WAAW,CAAA;IACrB,cAAc,EAAE,YAAY,CAAA;CAC7B"}
@@ -18,7 +18,21 @@ export interface FundiToolContext {
18
18
  /** The signed-in user's WorkOS access token (from ctx.props). */
19
19
  userAccessToken: string;
20
20
  }
21
- /** True when every binding needed to call fundi is present. */
21
+ /** True when either path to fundi is wired: the Service Binding or HTTP + M2M. */
22
22
  export declare function fundiConfigured(env: Env): boolean;
23
+ /**
24
+ * Build the transport to fundi.
25
+ *
26
+ * The branch is here, at construction, and nowhere else — every call site keeps
27
+ * calling `FundiCaller.call(path, userToken, init)` and never learns which path
28
+ * it got. Preferring the binding is what lets `WORKOS_M2M_CLIENT_SECRET` be
29
+ * deleted from this Worker once the binding is proven (docs/service-bindings.md);
30
+ * the HTTP fallback stays because `wrangler dev` and the stdio bin have no
31
+ * binding to use.
32
+ *
33
+ * The user token is forwarded on BOTH paths. A binding removes the machine
34
+ * credential, not the human one: fundi's entitlement is per-user and it still
35
+ * refuses a call that acts for nobody.
36
+ */
23
37
  export declare function createFundiCaller(env: Env): FundiCaller;
24
38
  //# sourceMappingURL=fundi-client.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"fundi-client.d.ts","sourceRoot":"","sources":["../src/fundi-client.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAGH,OAAO,KAAK,EAAE,GAAG,EAAE,MAAM,UAAU,CAAA;AA+BnC,MAAM,WAAW,WAAW;IAC1B,qEAAqE;IACrE,IAAI,CAAC,IAAI,EAAE,MAAM,EAAE,eAAe,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,WAAW,GAAG,OAAO,CAAC,QAAQ,CAAC,CAAA;CACnF;AAED,MAAM,WAAW,gBAAgB;IAC/B,MAAM,EAAE,WAAW,CAAA;IACnB,iEAAiE;IACjE,eAAe,EAAE,MAAM,CAAA;CACxB;AAED,+DAA+D;AAC/D,wBAAgB,eAAe,CAAC,GAAG,EAAE,GAAG,GAAG,OAAO,CAOjD;AAED,wBAAgB,iBAAiB,CAAC,GAAG,EAAE,GAAG,GAAG,WAAW,CAUvD"}
1
+ {"version":3,"file":"fundi-client.d.ts","sourceRoot":"","sources":["../src/fundi-client.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAGH,OAAO,KAAK,EAAE,GAAG,EAAE,MAAM,UAAU,CAAA;AA+BnC,MAAM,WAAW,WAAW;IAC1B,qEAAqE;IACrE,IAAI,CAAC,IAAI,EAAE,MAAM,EAAE,eAAe,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,WAAW,GAAG,OAAO,CAAC,QAAQ,CAAC,CAAA;CACnF;AAED,MAAM,WAAW,gBAAgB;IAC/B,MAAM,EAAE,WAAW,CAAA;IACnB,iEAAiE;IACjE,eAAe,EAAE,MAAM,CAAA;CACxB;AASD,kFAAkF;AAClF,wBAAgB,eAAe,CAAC,GAAG,EAAE,GAAG,GAAG,OAAO,CAQjD;AAED;;;;;;;;;;;;;GAaG;AACH,wBAAgB,iBAAiB,CAAC,GAAG,EAAE,GAAG,GAAG,WAAW,CAuBvD"}
@@ -39,14 +39,49 @@ async function mintM2MToken(env) {
39
39
  cached = { jwt: data.access_token, exp };
40
40
  return data.access_token;
41
41
  }
42
- /** True when every binding needed to call fundi is present. */
42
+ /**
43
+ * Origin the bound request is addressed to. A `Fetcher` still needs a
44
+ * well-formed absolute URL to build a `Request` from; the host is never
45
+ * resolved, because the binding routes by service, not by DNS.
46
+ */
47
+ const BINDING_ORIGIN = "https://fundi.internal";
48
+ /** True when either path to fundi is wired: the Service Binding or HTTP + M2M. */
43
49
  export function fundiConfigured(env) {
50
+ if (env.FUNDI_SERVICE)
51
+ return true;
44
52
  return Boolean(env.WORKOS_M2M_CLIENT_ID &&
45
53
  env.WORKOS_M2M_CLIENT_SECRET &&
46
54
  env.FUNDI_URL &&
47
55
  env.WORKOS_AUTHKIT_DOMAIN);
48
56
  }
57
+ /**
58
+ * Build the transport to fundi.
59
+ *
60
+ * The branch is here, at construction, and nowhere else — every call site keeps
61
+ * calling `FundiCaller.call(path, userToken, init)` and never learns which path
62
+ * it got. Preferring the binding is what lets `WORKOS_M2M_CLIENT_SECRET` be
63
+ * deleted from this Worker once the binding is proven (docs/service-bindings.md);
64
+ * the HTTP fallback stays because `wrangler dev` and the stdio bin have no
65
+ * binding to use.
66
+ *
67
+ * The user token is forwarded on BOTH paths. A binding removes the machine
68
+ * credential, not the human one: fundi's entitlement is per-user and it still
69
+ * refuses a call that acts for nobody.
70
+ */
49
71
  export function createFundiCaller(env) {
72
+ const service = env.FUNDI_SERVICE;
73
+ if (service) {
74
+ return {
75
+ async call(path, userAccessToken, init = {}) {
76
+ const headers = new Headers(init.headers);
77
+ headers.set("X-Fundi-User-Token", userAccessToken);
78
+ // No Authorization header: the binding IS the machine credential.
79
+ // Cloudflare will not route a public request to a named entrypoint, so
80
+ // there is no token to mint, replay, or leak.
81
+ return service.fetch(new Request(new URL(path, BINDING_ORIGIN), { ...init, headers }));
82
+ },
83
+ };
84
+ }
50
85
  return {
51
86
  async call(path, userAccessToken, init = {}) {
52
87
  const m2m = await mintM2MToken(env);
@@ -1 +1 @@
1
- {"version":3,"file":"fundi-client.js","sourceRoot":"","sources":["../src/fundi-client.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAEH,OAAO,EAAE,SAAS,EAAE,MAAM,MAAM,CAAA;AAGhC,IAAI,MAAM,GAAwC,IAAI,CAAA;AAEtD,KAAK,UAAU,YAAY,CAAC,GAAQ;IAClC,MAAM,GAAG,GAAG,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,GAAG,EAAE,GAAG,IAAI,CAAC,CAAA;IACzC,IAAI,MAAM,IAAI,MAAM,CAAC,GAAG,GAAG,GAAG,GAAG,EAAE;QAAE,OAAO,MAAM,CAAC,GAAG,CAAA;IACtD,MAAM,GAAG,GAAG,MAAM,KAAK,CAAC,IAAI,GAAG,CAAC,eAAe,EAAE,GAAG,CAAC,qBAAqB,CAAC,EAAE;QAC3E,MAAM,EAAE,MAAM;QACd,OAAO,EAAE,EAAE,cAAc,EAAE,mCAAmC,EAAE;QAChE,IAAI,EAAE,IAAI,eAAe,CAAC;YACxB,UAAU,EAAE,oBAAoB;YAChC,SAAS,EAAE,GAAG,CAAC,oBAAoB,IAAI,EAAE;YACzC,aAAa,EAAE,GAAG,CAAC,wBAAwB,IAAI,EAAE;SAClD,CAAC;KACH,CAAC,CAAA;IACF,IAAI,CAAC,GAAG,CAAC,EAAE,EAAE,CAAC;QACZ,MAAM,IAAI,KAAK,CAAC,gCAAgC,GAAG,CAAC,MAAM,MAAM,CAAC,MAAM,GAAG,CAAC,IAAI,EAAE,CAAC,CAAC,KAAK,CAAC,CAAC,EAAE,GAAG,CAAC,EAAE,CAAC,CAAA;IACrG,CAAC;IACD,MAAM,IAAI,GAAG,CAAC,MAAM,GAAG,CAAC,IAAI,EAAE,CAAkD,CAAA;IAChF,IAAI,GAAG,GAAG,GAAG,GAAG,CAAC,IAAI,CAAC,UAAU,IAAI,IAAI,CAAC,CAAA;IACzC,IAAI,CAAC;QACH,MAAM,MAAM,GAAG,SAAS,CAAC,IAAI,CAAC,YAAY,CAAC,CAAA;QAC3C,IAAI,OAAO,MAAM,CAAC,GAAG,KAAK,QAAQ;YAAE,GAAG,GAAG,MAAM,CAAC,GAAG,CAAA;IACtD,CAAC;IAAC,MAAM,CAAC;QACP,+BAA+B;IACjC,CAAC;IACD,MAAM,GAAG,EAAE,GAAG,EAAE,IAAI,CAAC,YAAY,EAAE,GAAG,EAAE,CAAA;IACxC,OAAO,IAAI,CAAC,YAAY,CAAA;AAC1B,CAAC;AAaD,+DAA+D;AAC/D,MAAM,UAAU,eAAe,CAAC,GAAQ;IACtC,OAAO,OAAO,CACZ,GAAG,CAAC,oBAAoB;QACtB,GAAG,CAAC,wBAAwB;QAC5B,GAAG,CAAC,SAAS;QACb,GAAG,CAAC,qBAAqB,CAC5B,CAAA;AACH,CAAC;AAED,MAAM,UAAU,iBAAiB,CAAC,GAAQ;IACxC,OAAO;QACL,KAAK,CAAC,IAAI,CAAC,IAAI,EAAE,eAAe,EAAE,IAAI,GAAG,EAAE;YACzC,MAAM,GAAG,GAAG,MAAM,YAAY,CAAC,GAAG,CAAC,CAAA;YACnC,MAAM,OAAO,GAAG,IAAI,OAAO,CAAC,IAAI,CAAC,OAAO,CAAC,CAAA;YACzC,OAAO,CAAC,GAAG,CAAC,eAAe,EAAE,UAAU,GAAG,EAAE,CAAC,CAAA;YAC7C,OAAO,CAAC,GAAG,CAAC,oBAAoB,EAAE,eAAe,CAAC,CAAA;YAClD,OAAO,KAAK,CAAC,IAAI,GAAG,CAAC,IAAI,EAAE,GAAG,CAAC,SAAS,CAAC,EAAE,EAAE,GAAG,IAAI,EAAE,OAAO,EAAE,CAAC,CAAA;QAClE,CAAC;KACF,CAAA;AACH,CAAC"}
1
+ {"version":3,"file":"fundi-client.js","sourceRoot":"","sources":["../src/fundi-client.ts"],"names":[],"mappings":"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"}
package/dist/http.js CHANGED
@@ -63,7 +63,7 @@ export function createMziziHttpHandler(options = {}) {
63
63
  sessionIdGenerator: undefined,
64
64
  enableJsonResponse: true,
65
65
  });
66
- const server = await createMziziMcpServer(ctx.supabase, { fundi: options.fundi });
66
+ const server = await createMziziMcpServer({ fundi: options.fundi });
67
67
  await server.connect(transport);
68
68
  const response = await transport.handleRequest(request);
69
69
  return withCors(response);
package/dist/http.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"http.js","sourceRoot":"","sources":["../src/http.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"http.js","sourceRoot":"","sources":["../src/http.ts"],"names":[],"mappings":"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"}
package/dist/server.d.ts CHANGED
@@ -1,36 +1,34 @@
1
1
  /**
2
- * Mzizi MCP — registry-driven server factory.
2
+ * The Mzizi MCP server.
3
3
  *
4
- * The tool surface is NOT hardcoded. It is read at startup from the public
5
- * `mcp_tool_registry` table (the same registry that powers the design system's
6
- * MCP), and each tool is dispatched dynamically to its backing implementation:
4
+ * Backed by `mzizi.dev/api/v1` over HTTP. There is no Supabase client here.
7
5
  *
8
- * • `sql_function` → `supabase.rpc(fn, args)` (the common case)
9
- * • `edge_function` → `supabase.functions.invoke(fn, { body: args })`
10
- * • `source_table` → `supabase.from(table).select()` (fallback)
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:
11
9
  *
12
- * This makes mzizi-mcp a drop-in replacement for the legacy design MCP: adding,
13
- * renaming, or retiring a tool is a registry edit, not a code change. Argument
14
- * names in the registry's `input_schema` (and in the curated fallback schemas
15
- * below) match the SQL function parameters exactly, so arguments pass straight
16
- * through to `rpc()` with no remapping.
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.
17
15
  *
18
- * The factory takes a pre-built `SupabaseClient` so the same factory works
19
- * across transports (HTTP per-request anon client; stdio long-lived anon
20
- * client). RLS grants public read on `mcp_tool_registry`, `component_documents`,
21
- * and EXECUTE on the document/registry RPCs.
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.
22
23
  */
23
24
  import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
24
- import type { SupabaseClient } from "@supabase/supabase-js";
25
25
  import type { FundiToolContext } from "./fundi-client.js";
26
- export declare const MZIZI_MCP_VERSION = "0.5.0";
27
- /**
28
- * Build the Mzizi MCP server bound to a Supabase client with public read on
29
- * `mcp_tool_registry` / `component_documents` and EXECUTE on the backing RPCs.
30
- * The tool catalog is loaded from the registry; write-kind tools are excluded
31
- * from this (anonymous, public) surface.
32
- */
33
- export declare function createMziziMcpServer(supabase: SupabaseClient, opts?: {
26
+ export declare const MZIZI_MCP_VERSION = "0.7.0";
27
+ export type CreateServerOptions = {
34
28
  fundi?: FundiToolContext;
35
- }): Promise<McpServer>;
29
+ /** Override the API base — used by tests and by a preview deployment. */
30
+ apiBaseUrl?: string;
31
+ fetchImpl?: typeof fetch;
32
+ };
33
+ export declare function createMziziMcpServer(opts?: CreateServerOptions): Promise<McpServer>;
36
34
  //# sourceMappingURL=server.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"server.d.ts","sourceRoot":"","sources":["../src/server.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;GAqBG;AAEH,OAAO,EAAE,SAAS,EAAE,MAAM,yCAAyC,CAAC;AAMpE,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,uBAAuB,CAAC;AAC5D,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,mBAAmB,CAAC;AAQ1D,eAAO,MAAM,iBAAiB,UAAU,CAAC;AAwezC;;;;;GAKG;AACH,wBAAsB,oBAAoB,CACxC,QAAQ,EAAE,cAAc,EACxB,IAAI,GAAE;IAAE,KAAK,CAAC,EAAE,gBAAgB,CAAA;CAAO,GACtC,OAAO,CAAC,SAAS,CAAC,CAwTpB"}
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"}