@zaai-dev/mcp 0.1.0 → 0.3.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 @@
1
+ {"version":3,"sources":["../../src/bin/http.ts","../../src/server.ts","../../src/tools/health.ts","../../src/version.ts","../../src/tools/whoami.ts","../../src/util/auth.ts","../../src/util/api.ts","../../src/tools/list-captures.ts","../../src/tools/get-capture.ts","../../src/tools/search-captures.ts","../../src/tools/_focused-getter.ts","../../src/tools/get-palette.ts","../../src/tools/get-html.ts","../../src/tools/get-animation.ts","../../src/tools/get-media.ts","../../src/tools/get-brand-brief.ts","../../src/tools/get-voice.ts","../../src/tools/get-audience.ts","../../src/tools/get-design-intent.ts","../../src/tools/get-brand-tokens.ts","../../src/tools/get-decisions.ts","../../src/tools/get-references.ts","../../src/tools/search-references.ts","../../src/store/http-store.ts","../../src/store/project-store.ts","../../src/resources/capture-resource.ts","../../src/log.ts","../../src/config.ts"],"sourcesContent":["#!/usr/bin/env node\nimport { createServer as createHttpServer, IncomingMessage, ServerResponse } from \"node:http\";\nimport { randomUUID } from \"node:crypto\";\nimport { StreamableHTTPServerTransport } from \"@modelcontextprotocol/sdk/server/streamableHttp.js\";\nimport { createServer } from \"../server.js\";\nimport { loadConfig, ConfigError } from \"../config.js\";\nimport { PKG_VERSION } from \"../version.js\";\nimport * as log from \"../log.js\";\n\n// Streamable HTTP entry point. Use this when you want to run Zaai Dev\n// MCP as a network service rather than as a per-user subprocess —\n// e.g. behind a reverse proxy on Fly / Cloudflare / Render so that\n// hosted agents (Claude.ai web, OpenAI Assistants, custom agent\n// frameworks) can reach it without a local install.\n//\n// Run via the new bin alias:\n// ZAAI_API_TOKEN=zaai_mcp_... npx -y @zaai-dev/mcp-http\n//\n// Or directly:\n// ZAAI_API_TOKEN=... node dist/bin/http.js\n//\n// ──────────────────────────────────────────────────────────────────\n// v1.5 scope: SINGLE-TENANT.\n// ──────────────────────────────────────────────────────────────────\n//\n// One process serves one workspace token (the one in\n// ZAAI_API_TOKEN). Every MCP session this process accepts is bound to\n// that single token. To run a multi-tenant gateway (each connecting\n// client paying with its own token), deploy one process per token OR\n// wait for v2 multi-tenant mode that reads the bearer per-request.\n//\n// Single-tenant is the right v1.5 shape because:\n// 1. The vast majority of \"I want HTTP\" use cases is \"run on a server\n// for one user's hosted agent\" — exactly this shape.\n// 2. Multi-tenant requires solving session→token binding, request\n// authentication independent of session, and a way to expose\n// per-token credit balance — non-trivial. Better to ship\n// single-tenant now and learn from real usage.\n//\n// Stateful mode: sessions persist across requests so streaming\n// notifications, tool subscriptions, and resource updates work\n// correctly. The transport tracks session IDs internally; clients\n// must include them on follow-up requests per the spec.\n\nconst DEFAULT_PORT = 3001;\n\nasync function main(): Promise<void> {\n let config;\n try {\n config = loadConfig();\n } catch (err) {\n if (err instanceof ConfigError) {\n log.error(\"FATAL: \" + err.message);\n process.exit(1);\n }\n throw err;\n }\n\n const port = parseInt(process.env.ZAAI_HTTP_PORT ?? String(DEFAULT_PORT), 10);\n if (!Number.isFinite(port) || port < 1 || port > 65535) {\n log.error(`FATAL: ZAAI_HTTP_PORT must be a valid port number, got ${process.env.ZAAI_HTTP_PORT}`);\n process.exit(1);\n }\n\n // One transport instance per process — stateful sessions live inside\n // it. The factory pattern in src/server.ts means we can also rebuild\n // a fresh server per session if needed; for v1.5 single-tenant a\n // shared server is fine.\n const transport = new StreamableHTTPServerTransport({\n sessionIdGenerator: () => randomUUID(),\n });\n const server = createServer(config);\n await server.connect(transport);\n\n const httpServer = createHttpServer(async (req: IncomingMessage, res: ServerResponse) => {\n // CORS — permissive in single-tenant mode since the operator\n // chose to expose this process publicly. Lock down via reverse\n // proxy headers if you need per-origin restrictions.\n res.setHeader(\"Access-Control-Allow-Origin\", \"*\");\n res.setHeader(\"Access-Control-Allow-Methods\", \"GET, POST, OPTIONS, DELETE\");\n res.setHeader(\n \"Access-Control-Allow-Headers\",\n \"Content-Type, Authorization, Mcp-Session-Id, Last-Event-ID\",\n );\n res.setHeader(\"Access-Control-Expose-Headers\", \"Mcp-Session-Id\");\n if (req.method === \"OPTIONS\") {\n res.writeHead(204).end();\n return;\n }\n\n // /healthz — liveness probe for orchestrators. Doesn't touch the\n // MCP transport so it works even if the workspace is down.\n if (req.method === \"GET\" && req.url === \"/healthz\") {\n res.writeHead(200, { \"Content-Type\": \"application/json\" }).end(\n JSON.stringify({ ok: true, version: PKG_VERSION, transport: \"streamable-http\" }),\n );\n return;\n }\n\n // MCP requests land here. Default path is /mcp; the SDK transport\n // handles the protocol details (initialise, tools/call, etc.)\n // including session ID validation.\n if (req.url === \"/mcp\" || req.url?.startsWith(\"/mcp?\")) {\n try {\n await transport.handleRequest(req, res);\n } catch (err) {\n log.error(\"transport.handleRequest threw\", err);\n if (!res.headersSent) {\n res.writeHead(500, { \"Content-Type\": \"application/json\" }).end(\n JSON.stringify({ error: \"internal_error\" }),\n );\n }\n }\n return;\n }\n\n res.writeHead(404, { \"Content-Type\": \"application/json\" }).end(\n JSON.stringify({ error: \"not_found\", expected: [\"/mcp\", \"/healthz\"] }),\n );\n });\n\n httpServer.listen(port, () => {\n log.info(\"streamable-http transport listening\", {\n port,\n version: PKG_VERSION,\n mode: \"single-tenant\",\n });\n });\n\n // Graceful shutdown — SIGTERM from orchestrator (Fly/Cloudflare/Render)\n // gives us a window to close open sessions cleanly.\n const shutdown = (signal: string) => {\n log.info(`received ${signal}, closing http server`);\n httpServer.close(() => {\n transport.close().catch((err) => log.error(\"transport close failed\", err));\n process.exit(0);\n });\n // Force-exit after 10s if close hangs (e.g. dangling SSE\n // connection). The orchestrator's own SIGKILL would do this\n // anyway after a longer window, but a clean self-exit is nicer\n // for logs.\n setTimeout(() => process.exit(0), 10_000).unref();\n };\n process.on(\"SIGTERM\", () => shutdown(\"SIGTERM\"));\n process.on(\"SIGINT\", () => shutdown(\"SIGINT\"));\n}\n\nmain().catch((err) => {\n log.error(\"fatal startup error\", err);\n process.exit(1);\n});\n","import { McpServer } from \"@modelcontextprotocol/sdk/server/mcp.js\";\r\nimport {\r\n health,\r\n healthInputSchema,\r\n healthOutputSchema,\r\n} from \"./tools/health.js\";\r\nimport {\r\n whoami,\r\n whoamiInputSchema,\r\n whoamiOutputSchema,\r\n} from \"./tools/whoami.js\";\r\nimport {\r\n listCaptures,\r\n listCapturesInputSchema,\r\n listCapturesOutputSchema,\r\n} from \"./tools/list-captures.js\";\r\nimport {\r\n getCapture,\r\n getCaptureInputSchema,\r\n getCaptureOutputSchema,\r\n} from \"./tools/get-capture.js\";\r\nimport {\r\n searchCaptures,\r\n searchCapturesInputSchema,\r\n searchCapturesOutputSchema,\r\n} from \"./tools/search-captures.js\";\r\nimport {\r\n getPalette,\r\n getPaletteInputSchema,\r\n getPaletteOutputSchema,\r\n} from \"./tools/get-palette.js\";\r\nimport {\r\n getHtml,\r\n getHtmlInputSchema,\r\n getHtmlOutputSchema,\r\n} from \"./tools/get-html.js\";\r\nimport {\r\n getAnimation,\r\n getAnimationInputSchema,\r\n getAnimationOutputSchema,\r\n} from \"./tools/get-animation.js\";\r\nimport {\r\n getMedia,\r\n getMediaInputSchema,\r\n getMediaOutputSchema,\r\n} from \"./tools/get-media.js\";\r\nimport {\r\n getBrandBrief,\r\n getBrandBriefInputSchema,\r\n getBrandBriefOutputSchema,\r\n} from \"./tools/get-brand-brief.js\";\r\nimport {\r\n getVoice,\r\n getVoiceInputSchema,\r\n getVoiceOutputSchema,\r\n} from \"./tools/get-voice.js\";\r\nimport {\r\n getAudience,\r\n getAudienceInputSchema,\r\n getAudienceOutputSchema,\r\n} from \"./tools/get-audience.js\";\r\nimport {\r\n getDesignIntent,\r\n getDesignIntentInputSchema,\r\n getDesignIntentOutputSchema,\r\n} from \"./tools/get-design-intent.js\";\r\nimport {\r\n getBrandTokens,\r\n getBrandTokensInputSchema,\r\n getBrandTokensOutputSchema,\r\n} from \"./tools/get-brand-tokens.js\";\r\nimport {\r\n getDecisions,\r\n getDecisionsInputSchema,\r\n getDecisionsOutputSchema,\r\n} from \"./tools/get-decisions.js\";\r\nimport {\r\n getReferences,\r\n getReferencesInputSchema,\r\n getReferencesOutputSchema,\r\n} from \"./tools/get-references.js\";\r\nimport {\r\n searchReferences,\r\n searchReferencesInputSchema,\r\n searchReferencesOutputSchema,\r\n} from \"./tools/search-references.js\";\r\nimport { HttpCaptureStore } from \"./store/http-store.js\";\r\nimport { HttpProjectStore } from \"./store/project-store.js\";\r\nimport { registerCaptureResource } from \"./resources/capture-resource.js\";\r\nimport { WorkspaceApiError } from \"./util/api.js\";\r\nimport type { Config } from \"./config.js\";\r\nimport { PKG_VERSION } from \"./version.js\";\r\nimport * as log from \"./log.js\";\r\n\r\n// Factory: produces a fully-configured MCP server instance. The\r\n// stdio entry today calls this; the HTTP transport added in v1.5\r\n// will call the same factory. Keep the function pure so tests can\r\n// drive it with an in-process transport.\r\nexport function createServer(config: Config): McpServer {\r\n const server = new McpServer({\r\n name: \"zaai-dev-mcp\",\r\n version: PKG_VERSION,\r\n });\r\n\r\n const captureStore = new HttpCaptureStore(config);\r\n const projectStore = new HttpProjectStore(config);\r\n\r\n server.registerTool(\r\n \"health\",\r\n {\r\n title: \"Health check\",\r\n description:\r\n \"Returns the Zaai Dev MCP server's status, version, and uptime. \" +\r\n \"Use this to confirm the server is running before relying on auth-\" +\r\n \"gated tools. No workspace access required. Useful as a smoke test \" +\r\n \"from the MCP Inspector before configuring credentials.\",\r\n inputSchema: healthInputSchema.shape,\r\n outputSchema: healthOutputSchema.shape,\r\n },\r\n async () => {\r\n const result = health();\r\n return {\r\n structuredContent: result,\r\n // Human-readable summary for clients that haven't adopted\r\n // structuredContent yet. Spec 2025-06-18 still requires both.\r\n content: [\r\n {\r\n type: \"text\",\r\n text:\r\n `Zaai Dev MCP ${result.version} · node ${result.node}` +\r\n ` · uptime ${result.uptimeSeconds}s`,\r\n },\r\n ],\r\n };\r\n },\r\n );\r\n\r\n server.registerTool(\r\n \"whoami\",\r\n {\r\n title: \"Who am I\",\r\n description:\r\n \"Returns the Zaai Dev workspace account this server is bound to: \" +\r\n \"user id, organisation id, project scope, and current credit balance. \" +\r\n \"Use this to confirm the configured ZAAI_API_TOKEN is valid before \" +\r\n \"calling any other workspace tool. Does NOT debit credits — the \" +\r\n \"workspace treats /me as a heartbeat, not user-facing work.\",\r\n inputSchema: whoamiInputSchema.shape,\r\n outputSchema: whoamiOutputSchema.shape,\r\n },\r\n async () => {\r\n try {\r\n const result = await whoami(config);\r\n return {\r\n structuredContent: result,\r\n content: [\r\n {\r\n type: \"text\",\r\n text: summariseWhoami(result),\r\n },\r\n ],\r\n };\r\n } catch (err) {\r\n return toolErrorResponse(err);\r\n }\r\n },\r\n );\r\n\r\n server.registerTool(\r\n \"list_captures\",\r\n {\r\n title: \"List captures\",\r\n description:\r\n \"List the user's Zaai Dev captures (newest first, paginated). \" +\r\n \"Use this to discover what's in the library before calling \" +\r\n \"get_capture for specifics. Each row carries id, type, title, \" +\r\n \"URL, capturedAt, tags, and a thumbnail URL — but NOT the full \" +\r\n \"HTML, computed style, or animation data. Use get_capture for \" +\r\n \"those. Costs 1 credit per call.\",\r\n inputSchema: listCapturesInputSchema.shape,\r\n outputSchema: listCapturesOutputSchema.shape,\r\n },\r\n async (args) => {\r\n try {\r\n const result = await listCaptures(captureStore, args);\r\n return {\r\n // Cast: SDK's structuredContent param wants\r\n // Record<string,unknown> but our typed DTO doesn't carry\r\n // an index signature. Runtime shape is identical.\r\n structuredContent: result as unknown as Record<string, unknown>,\r\n content: [\r\n {\r\n type: \"text\",\r\n text:\r\n result.captures.length === 0\r\n ? \"No captures yet. The user can push captures from the Zaai Dev Chrome extension.\"\r\n : `${result.captures.length} capture${result.captures.length === 1 ? \"\" : \"s\"}${result.nextCursor ? \" (more available — pass nextCursor for the next page)\" : \"\"}.`,\r\n },\r\n ],\r\n };\r\n } catch (err) {\r\n return toolErrorResponse(err);\r\n }\r\n },\r\n );\r\n\r\n server.registerTool(\r\n \"get_capture\",\r\n {\r\n title: \"Get capture\",\r\n description:\r\n \"Fetch the full payload for one capture by id. Includes everything \" +\r\n \"the extension extracted (HTML, computed CSS, palette, fonts, \" +\r\n \"animation data, media inventory, ancestry, page sections, manual \" +\r\n \"eyedropper picks) plus fresh-signed Supabase URLs for the \" +\r\n \"screenshot and thumbnail. Use list_captures or search_captures \" +\r\n \"first to discover ids. Costs 1 credit per call; the 404 path \" +\r\n \"(unknown id) doesn't bill.\",\r\n inputSchema: getCaptureInputSchema.shape,\r\n outputSchema: getCaptureOutputSchema.shape,\r\n },\r\n async (args) => {\r\n try {\r\n const result = await getCapture(captureStore, args);\r\n return {\r\n structuredContent: result as unknown as Record<string, unknown>,\r\n content: [\r\n {\r\n type: \"text\",\r\n text:\r\n `${result.type} capture \"${result.sourceTitle || result.sourceUrl}\"` +\r\n ` (${result.tags.length} tag${result.tags.length === 1 ? \"\" : \"s\"})` +\r\n (result.screenshotUrl ? \" — screenshot URL included.\" : \"\"),\r\n },\r\n ],\r\n };\r\n } catch (err) {\r\n return toolErrorResponse(err);\r\n }\r\n },\r\n );\r\n\r\n server.registerTool(\r\n \"search_captures\",\r\n {\r\n title: \"Search captures\",\r\n description:\r\n \"Find captures matching a text query (case-insensitive substring \" +\r\n \"match against source_title, source_url, and note). Returns the \" +\r\n \"same summary shape as list_captures. Use this when you have a \" +\r\n \"specific concept in mind ('hero', 'pricing table', 'stripe'); \" +\r\n \"use list_captures to browse instead. Costs 1 credit per call.\",\r\n inputSchema: searchCapturesInputSchema.shape,\r\n outputSchema: searchCapturesOutputSchema.shape,\r\n },\r\n async (args) => {\r\n try {\r\n const result = await searchCaptures(captureStore, args);\r\n return {\r\n structuredContent: result as unknown as Record<string, unknown>,\r\n content: [\r\n {\r\n type: \"text\",\r\n text:\r\n result.captures.length === 0\r\n ? `No captures match \"${args.q}\".`\r\n : `${result.captures.length} capture${result.captures.length === 1 ? \"\" : \"s\"} matching \"${args.q}\"${result.nextCursor ? \" (more available — pass nextCursor for the next page)\" : \"\"}.`,\r\n },\r\n ],\r\n };\r\n } catch (err) {\r\n return toolErrorResponse(err);\r\n }\r\n },\r\n );\r\n\r\n server.registerTool(\r\n \"get_palette\",\r\n {\r\n title: \"Get capture palette\",\r\n description:\r\n \"Returns just the colour palette for a capture. Page captures \" +\r\n \"carry a 6-colour extracted palette (`palette`); element + \" +\r\n \"composite captures carry the user's eyedropper picks \" +\r\n \"(`manualPalette`). Use this when the LLM needs colour context \" +\r\n \"without loading the full payload. Costs 1 credit.\",\r\n inputSchema: getPaletteInputSchema.shape,\r\n outputSchema: getPaletteOutputSchema.shape,\r\n },\r\n makeFocusedGetterHandler(captureStore, getPalette, \"palette\"),\r\n );\r\n\r\n server.registerTool(\r\n \"get_html\",\r\n {\r\n title: \"Get capture HTML\",\r\n description:\r\n \"Returns just the HTML for a capture. Page → full page HTML; \" +\r\n \"element → outerHTML of the picked element; composite → \" +\r\n \"concatenated outerHTMLs with `<!-- Element N: selector -->` \" +\r\n \"markers. Use this for component-extraction prompts ('rebuild \" +\r\n \"this in Tailwind'). Costs 1 credit. Page captures can be large \" +\r\n \"— budget your context accordingly.\",\r\n inputSchema: getHtmlInputSchema.shape,\r\n outputSchema: getHtmlOutputSchema.shape,\r\n },\r\n makeFocusedGetterHandler(captureStore, getHtml, \"html\"),\r\n );\r\n\r\n server.registerTool(\r\n \"get_animation\",\r\n {\r\n title: \"Get capture animation data\",\r\n description:\r\n \"Returns just the animation data. Page → pageAnimations \" +\r\n \"(keyframes vocabulary + detected motion libraries like Framer \" +\r\n \"Motion, GSAP, AOS, anime.js, Lenis, Locomotive). Element → \" +\r\n \"the element's CSS transitions, keyframes, hover/focus/active \" +\r\n \"state diffs, and per-element library hints. Composite → \" +\r\n \"per-element variants. Use this to give the LLM motion context \" +\r\n \"without loading HTML and computed style. Costs 1 credit.\",\r\n inputSchema: getAnimationInputSchema.shape,\r\n outputSchema: getAnimationOutputSchema.shape,\r\n },\r\n makeFocusedGetterHandler(captureStore, getAnimation, \"animation\"),\r\n );\r\n\r\n server.registerTool(\r\n \"get_media\",\r\n {\r\n title: \"Get capture media inventory\",\r\n description:\r\n \"Returns just the rich-media inventory for element + composite \" +\r\n \"captures: videos (src/poster/autoplay/loop), images (src/\" +\r\n \"srcset/alt), background-image URLs across the subtree, and \" +\r\n \"carousel containers (Swiper, Glide, Splide, Slick, Flickity, \" +\r\n \"Embla, `[data-carousel]`) with slide counts. Page captures \" +\r\n \"return media:null (page-level palette/fonts only). Costs 1 credit.\",\r\n inputSchema: getMediaInputSchema.shape,\r\n outputSchema: getMediaOutputSchema.shape,\r\n },\r\n makeFocusedGetterHandler(captureStore, getMedia, \"media\"),\r\n );\r\n\r\n // ──────────────────────────────────────────────────────────\r\n // Brief + references tools — v0.2.0\r\n // ──────────────────────────────────────────────────────────\r\n // Each one wraps a workspace /api/mcp/projects/[projectId]/* endpoint.\r\n // Workspace owns the contract; the MCP relays + bills 1 credit.\r\n\r\n server.registerTool(\r\n \"get_brand_brief\",\r\n {\r\n title: \"Get brand brief\",\r\n description:\r\n \"Returns the full published brand brief for a project: positioning, \" +\r\n \"values, voice, audience, design intent, and decisions. Use this \" +\r\n \"when the LLM needs the whole picture before writing copy or \" +\r\n \"designing a component. If the project has no brief yet, the response \" +\r\n \"still validates — most fields are empty strings or empty arrays.\",\r\n inputSchema: getBrandBriefInputSchema.shape,\r\n outputSchema: getBrandBriefOutputSchema.shape,\r\n },\r\n makeProjectToolHandler(projectStore, getBrandBrief, (r) =>\r\n `Brief v${r.version} (${r.status}) for \"${r.project_name}\". ` +\r\n `Voice: ${r.voice.one_liner || \"—\"}.`,\r\n ),\r\n );\r\n\r\n server.registerTool(\r\n \"get_voice\",\r\n {\r\n title: \"Get voice guidelines\",\r\n description:\r\n \"Returns only the voice slice: one-liner, tone descriptors, \" +\r\n \"do-say / don't-say lists, example phrases. Lighter than the full \" +\r\n \"brief when the LLM is only writing copy. Costs 1 credit.\",\r\n inputSchema: getVoiceInputSchema.shape,\r\n outputSchema: getVoiceOutputSchema.shape,\r\n },\r\n makeProjectToolHandler(projectStore, getVoice, (r) =>\r\n `Voice for project ${r.project_id.slice(0, 8)}…: \"${r.one_liner || \"—\"}\". ` +\r\n `${r.tone_descriptors.length} tone descriptor${r.tone_descriptors.length === 1 ? \"\" : \"s\"}.`,\r\n ),\r\n );\r\n\r\n server.registerTool(\r\n \"get_audience\",\r\n {\r\n title: \"Get audience profile\",\r\n description:\r\n \"Returns only the audience slice: primary segment, optional \" +\r\n \"secondary, needs / pain points, channels. Use when targeting copy \" +\r\n \"or design at a specific audience. Costs 1 credit.\",\r\n inputSchema: getAudienceInputSchema.shape,\r\n outputSchema: getAudienceOutputSchema.shape,\r\n },\r\n makeProjectToolHandler(projectStore, getAudience, (r) =>\r\n `Audience: ${r.primary || \"—\"}` +\r\n (r.secondary ? ` (secondary: ${r.secondary})` : \"\") +\r\n `. ${r.needs.length} stated need${r.needs.length === 1 ? \"\" : \"s\"}.`,\r\n ),\r\n );\r\n\r\n server.registerTool(\r\n \"get_design_intent\",\r\n {\r\n title: \"Get design intent\",\r\n description:\r\n \"Returns the visual descriptors and anti-descriptors that constrain \" +\r\n \"design exploration, plus the inspiration_summary. Use this before \" +\r\n \"generating layouts, palettes, or component styles — it's the \" +\r\n \"guardrail set the brief encodes. Costs 1 credit.\",\r\n inputSchema: getDesignIntentInputSchema.shape,\r\n outputSchema: getDesignIntentOutputSchema.shape,\r\n },\r\n makeProjectToolHandler(projectStore, getDesignIntent, (r) =>\r\n `${r.descriptors.length} descriptor${r.descriptors.length === 1 ? \"\" : \"s\"}, ` +\r\n `${r.anti_descriptors.length} anti-descriptor${r.anti_descriptors.length === 1 ? \"\" : \"s\"}.`,\r\n ),\r\n );\r\n\r\n server.registerTool(\r\n \"get_brand_tokens\",\r\n {\r\n title: \"Get brand tokens\",\r\n description:\r\n \"Returns the brand's design tokens: colors (with optional role), \" +\r\n \"fonts (role / family / weights), radius scale, shadow scale. Use \" +\r\n \"this when generating CSS, Tailwind config, or component styles \" +\r\n \"that should match the brand. Costs 1 credit.\",\r\n inputSchema: getBrandTokensInputSchema.shape,\r\n outputSchema: getBrandTokensOutputSchema.shape,\r\n },\r\n makeProjectToolHandler(projectStore, getBrandTokens, (r) =>\r\n `${r.colors.length} color${r.colors.length === 1 ? \"\" : \"s\"}, ` +\r\n `${r.fonts.length} font${r.fonts.length === 1 ? \"\" : \"s\"}, ` +\r\n `${r.radius.length} radius, ${r.shadows.length} shadow${r.shadows.length === 1 ? \"\" : \"s\"}.`,\r\n ),\r\n );\r\n\r\n server.registerTool(\r\n \"get_decisions\",\r\n {\r\n title: \"Get decisions log\",\r\n description:\r\n \"Returns the brand + design decisions log for a project: what was \" +\r\n \"decided, why, who decided, when, and which brief field (if any) it \" +\r\n \"concerns. Use this to avoid re-litigating settled questions. Costs \" +\r\n \"1 credit.\",\r\n inputSchema: getDecisionsInputSchema.shape,\r\n outputSchema: getDecisionsOutputSchema.shape,\r\n },\r\n makeProjectToolHandler(projectStore, getDecisions, (r) =>\r\n `${r.items.length} decision${r.items.length === 1 ? \"\" : \"s\"} returned (newest first).`,\r\n ),\r\n );\r\n\r\n server.registerTool(\r\n \"get_references\",\r\n {\r\n title: \"Get project references\",\r\n description:\r\n \"Paginated list of references (captures) for one project. Use this \" +\r\n \"when the LLM needs to know what visual / interaction references the \" +\r\n \"user has saved for a specific project — different from \" +\r\n \"list_captures which is org-wide. Costs 1 credit per call.\",\r\n inputSchema: getReferencesInputSchema.shape,\r\n outputSchema: getReferencesOutputSchema.shape,\r\n },\r\n makeProjectToolHandler(projectStore, getReferences, (r) =>\r\n `${r.items.length} reference${r.items.length === 1 ? \"\" : \"s\"} returned` +\r\n (r.next_cursor ? \" (more available — pass next_cursor for the next page).\" : \".\"),\r\n ),\r\n );\r\n\r\n server.registerTool(\r\n \"search_references\",\r\n {\r\n title: \"Search project references\",\r\n description:\r\n \"Keyword search over a project's references (title / url / note in \" +\r\n \"v1; pgvector ranking in v1.5). Returns scored matches with \" +\r\n \"matched_field signals. Use when the LLM has a specific concept in \" +\r\n \"mind ('hero', 'pricing table'). Costs 1 credit.\",\r\n inputSchema: searchReferencesInputSchema.shape,\r\n outputSchema: searchReferencesOutputSchema.shape,\r\n },\r\n makeProjectToolHandler(projectStore, searchReferences, (r) =>\r\n r.items.length === 0\r\n ? `No references match \"${r.query}\".`\r\n : `${r.items.length} reference${r.items.length === 1 ? \"\" : \"s\"} matching \"${r.query}\".`,\r\n ),\r\n );\r\n\r\n registerCaptureResource(server, captureStore);\r\n\r\n log.info(\"server initialized\", {\r\n version: PKG_VERSION,\r\n tools: [\r\n \"health\",\r\n \"whoami\",\r\n \"list_captures\",\r\n \"search_captures\",\r\n \"get_capture\",\r\n \"get_palette\",\r\n \"get_html\",\r\n \"get_animation\",\r\n \"get_media\",\r\n \"get_brand_brief\",\r\n \"get_voice\",\r\n \"get_audience\",\r\n \"get_design_intent\",\r\n \"get_brand_tokens\",\r\n \"get_decisions\",\r\n \"get_references\",\r\n \"search_references\",\r\n ],\r\n resources: [\"zaai-capture://{id}\"],\r\n });\r\n return server;\r\n}\r\n\r\n// Shared handler factory for the project-scoped tools (brief, voice,\r\n// audience, design-intent, brand-tokens, decisions, references,\r\n// search_references). Each tool differs only in (a) the store method\r\n// it calls and (b) the human-readable text summary it produces.\r\nfunction makeProjectToolHandler<Args, Result>(\r\n store: import(\"./store/project-store.js\").HttpProjectStore,\r\n fn: (s: import(\"./store/project-store.js\").HttpProjectStore, args: Args) => Promise<Result>,\r\n summary: (r: Result) => string,\r\n) {\r\n return async (args: Args) => {\r\n try {\r\n const result = await fn(store, args);\r\n return {\r\n structuredContent: result as unknown as Record<string, unknown>,\r\n content: [{ type: \"text\" as const, text: summary(result) }],\r\n };\r\n } catch (err) {\r\n return toolErrorResponse(err);\r\n }\r\n };\r\n}\r\n\r\n// Shared handler factory for the four focused-getter tools — they\r\n// differ only in the `field` they pass to the store + the tool's\r\n// LLM-facing description, which is set at registerTool time.\r\nfunction makeFocusedGetterHandler(\r\n store: HttpCaptureStore,\r\n fn: (\r\n s: HttpCaptureStore,\r\n args: { id: string },\r\n ) => Promise<{ id: string; type: string; field: string; data: unknown }>,\r\n label: string,\r\n) {\r\n return async (args: { id: string }) => {\r\n try {\r\n const result = await fn(store, args);\r\n return {\r\n structuredContent: result as unknown as Record<string, unknown>,\r\n content: [\r\n {\r\n type: \"text\" as const,\r\n text: `${result.type} capture · ${label} slice for id ${result.id.slice(0, 8)}…`,\r\n },\r\n ],\r\n };\r\n } catch (err) {\r\n return toolErrorResponse(err);\r\n }\r\n };\r\n}\r\n\r\nfunction summariseWhoami(r: {\r\n userId: string;\r\n orgId: string;\r\n projectScope: string[] | null;\r\n balance: { totalBalance: number };\r\n mcpCallCost: number;\r\n}): string {\r\n const scope =\r\n r.projectScope === null\r\n ? \"all projects in org\"\r\n : `${r.projectScope.length} project${r.projectScope.length === 1 ? \"\" : \"s\"}`;\r\n return (\r\n `Zaai Dev workspace · user ${r.userId.slice(0, 8)}… · ` +\r\n `org ${r.orgId.slice(0, 8)}… · ${scope} · ` +\r\n `${r.balance.totalBalance} credits (${r.mcpCallCost}/call)`\r\n );\r\n}\r\n\r\n// Convert a workspace API failure into an MCP tool result the LLM\r\n// can read and act on. Returning isError:true is preferred over\r\n// throwing because the LLM sees the message and can fix the\r\n// underlying issue (e.g. \"ask the user to reconnect\").\r\nfunction toolErrorResponse(err: unknown): {\r\n isError: true;\r\n content: Array<{ type: \"text\"; text: string }>;\r\n} {\r\n if (err instanceof WorkspaceApiError) {\r\n switch (err.status) {\r\n case 401:\r\n return errorContent(\r\n \"Authentication failed. Your ZAAI_API_TOKEN is invalid, expired, \" +\r\n \"or revoked. Mint a new MCP token at \" +\r\n \"https://www.zaaistudio.com/dev/settings/tokens and update \" +\r\n \"your MCP client config.\",\r\n );\r\n case 402:\r\n return errorContent(\r\n \"Out of credits. Top up at \" +\r\n \"https://www.zaaistudio.com/dev/settings/billing.\",\r\n );\r\n case 0:\r\n return errorContent(\r\n `Network failure reaching the Zaai Dev workspace: ${describe(err.body)}. ` +\r\n \"Check your connection or ZAAI_API_URL setting.\",\r\n );\r\n default:\r\n return errorContent(\r\n `Workspace returned ${err.status} for ${err.path}: ${describe(err.body)}.`,\r\n );\r\n }\r\n }\r\n return errorContent(`Unexpected MCP tool failure: ${describe(err)}`);\r\n}\r\n\r\nfunction errorContent(text: string): {\r\n isError: true;\r\n content: Array<{ type: \"text\"; text: string }>;\r\n} {\r\n return { isError: true, content: [{ type: \"text\", text }] };\r\n}\r\n\r\nfunction describe(value: unknown): string {\r\n if (value instanceof Error) return value.message;\r\n if (typeof value === \"string\") return value;\r\n try {\r\n return JSON.stringify(value);\r\n } catch {\r\n return String(value);\r\n }\r\n}\r\n","import { z } from \"zod\";\r\nimport { PKG_VERSION } from \"../version.js\";\r\n\r\n// Health-check tool. No auth, no workspace access, no Supabase round\r\n// trip — useful for two cases:\r\n// 1. The MCP Inspector smoke test before configuring credentials\r\n// (M-MCP1 acceptance criteria)\r\n// 2. A future MCP client's own up/down probe — clients can call\r\n// health() to confirm the server is reachable without needing\r\n// to call something user-scoped first.\r\n//\r\n// Returns { ok, version, node, uptimeSeconds } — small, fixed shape.\r\n// Updates here should be backward-compatible (additive only) because\r\n// clients depending on the probe shouldn't break across versions.\r\n\r\nexport const healthInputSchema = z.object({});\r\n\r\nexport const healthOutputSchema = z.object({\r\n ok: z.boolean().describe(\"Always true — health is the server admitting it answered.\"),\r\n version: z.string().describe(\"The MCP server's package version.\"),\r\n node: z.string().describe(\"The Node.js runtime version the server is running on.\"),\r\n uptimeSeconds: z\r\n .number()\r\n .describe(\"Seconds since this server process started.\"),\r\n});\r\n\r\nexport type HealthOutput = z.infer<typeof healthOutputSchema>;\r\n\r\nexport function health(): HealthOutput {\r\n return {\r\n ok: true,\r\n version: PKG_VERSION,\r\n node: process.versions.node,\r\n uptimeSeconds: Math.round(process.uptime()),\r\n };\r\n}\r\n","// Build-time-substituted package version. tsup's `define` config in\r\n// tsup.config.ts replaces `__PKG_VERSION__` at bundle time with the\r\n// version from package.json. The fallback is for `tsc --noEmit` and\r\n// the dev-time editor — those don't run through tsup, so they see\r\n// the raw token. Runtime always sees the real version.\r\ndeclare const __PKG_VERSION__: string;\r\n\r\nexport const PKG_VERSION: string =\r\n typeof __PKG_VERSION__ === \"string\" ? __PKG_VERSION__ : \"0.0.0-dev\";\r\n","import { z } from \"zod\";\r\nimport type { Config } from \"../config.js\";\r\nimport { mcpApiFetch } from \"../util/api.js\";\r\n\r\n// First auth-gated tool. Calls GET /api/mcp/me — verifies the\r\n// configured ZAAI_API_TOKEN works against the workspace and\r\n// surfaces the user/org/balance so the LLM (and the human in the\r\n// MCP Inspector) can confirm what account it's bound to.\r\n//\r\n// Cheap, doesn't bill — `/me` is the protocol heartbeat per\r\n// docs/zaai-dev-mcp-plan.md § M-MCP2 in the extension repo.\r\n\r\nexport const whoamiInputSchema = z.object({});\r\n\r\nexport const whoamiOutputSchema = z.object({\r\n userId: z.string().describe(\"Workspace user id this token belongs to.\"),\r\n orgId: z.string().describe(\"Organisation id the token is scoped to.\"),\r\n projectScope: z\r\n .array(z.string())\r\n .nullable()\r\n .describe(\r\n \"List of project ids the token can access, or null when scoped to every project in the org.\",\r\n ),\r\n balance: z\r\n .object({\r\n currentBalance: z\r\n .number()\r\n .describe(\"Top-up credits (never expire).\"),\r\n monthlyGrantRemaining: z\r\n .number()\r\n .describe(\"Monthly grant remaining (resets on the 1st).\"),\r\n totalBalance: z\r\n .number()\r\n .describe(\"Sum of the two — what's available right now.\"),\r\n })\r\n .describe(\"Credit balance available for MCP calls.\"),\r\n mcpCallCost: z\r\n .number()\r\n .describe(\"Credits debited per successful MCP tool call.\"),\r\n});\r\n\r\nexport type WhoamiOutput = z.infer<typeof whoamiOutputSchema>;\r\n\r\nexport async function whoami(config: Config): Promise<WhoamiOutput> {\r\n return mcpApiFetch<WhoamiOutput>(config, \"/api/mcp/me\");\r\n}\r\n","// Bearer-header builder. Single place to format `Authorization`\r\n// so every HTTP call has identical shape — useful when grepping\r\n// for \"who sets the bearer\" later.\r\n\r\nexport function bearerHeader(token: string): Record<string, string> {\r\n return { Authorization: `Bearer ${token}` };\r\n}\r\n","import type { Config } from \"../config.js\";\r\nimport { bearerHeader } from \"./auth.js\";\r\n\r\n// Structured failure from a workspace API call. Tools branch on\r\n// `.status` to render LLM-friendly recovery hints (401 → \"reauth\",\r\n// 402 → \"out of credits\", 404 → \"not found\", 5xx → \"try again\").\r\n\r\nexport class WorkspaceApiError extends Error {\r\n constructor(\r\n public readonly status: number,\r\n public readonly body: unknown,\r\n public readonly path: string,\r\n ) {\r\n super(`${path} → ${status}`);\r\n this.name = \"WorkspaceApiError\";\r\n }\r\n}\r\n\r\n// Typed HTTPS wrapper. Prepends the configured workspace base URL,\r\n// adds the bearer header, parses JSON, throws WorkspaceApiError on\r\n// non-2xx so callers don't have to inspect Response objects.\r\n//\r\n// Default method is GET (set `init.method` to override). Caller is\r\n// responsible for JSON-encoding any body — pass via init.body as a\r\n// string and set init.headers['Content-Type'].\r\n//\r\n// Retries transient failures up to 3 attempts with exponential\r\n// backoff (250ms → 500ms → 1000ms). A failure is \"transient\" if it\r\n// can plausibly succeed on retry without user intervention:\r\n// - Network errors (status 0 — DNS, offline, TLS handshake)\r\n// - 5xx server errors (workspace temporarily unhappy)\r\n// - 429 rate-limited responses from any upstream\r\n//\r\n// 4xx auth/validation errors (401, 402, 403, 404, 4xx generally) are\r\n// NOT retried — the user has to do something (re-mint token, top up,\r\n// fix args). Retrying would mask the real problem.\r\n//\r\n// Retries are transparent to callers — the LLM only sees the final\r\n// outcome. Successful retries don't double-bill because workspace\r\n// only records mcp_calls on the request that actually reached + ran\r\n// the tool implementation (the 5xx failures never got that far).\r\n\r\nconst MAX_ATTEMPTS = 3;\r\nconst BASE_BACKOFF_MS = 250;\r\n\r\nconst RETRYABLE_STATUSES = new Set([429, 502, 503, 504]);\r\n\r\nexport async function mcpApiFetch<T>(\r\n config: Config,\r\n path: string,\r\n init: RequestInit = {},\r\n): Promise<T> {\r\n const url = `${config.apiUrl}${path}`;\r\n let lastErr: WorkspaceApiError | null = null;\r\n\r\n for (let attempt = 1; attempt <= MAX_ATTEMPTS; attempt++) {\r\n let res: Response;\r\n try {\r\n res = await fetch(url, {\r\n ...init,\r\n headers: {\r\n ...bearerHeader(config.apiToken),\r\n ...(init.headers ?? {}),\r\n },\r\n });\r\n } catch (err) {\r\n // Network failure (DNS, offline, TLS). Always retryable.\r\n lastErr = new WorkspaceApiError(0, { message: String(err) }, path);\r\n if (attempt < MAX_ATTEMPTS) {\r\n await sleep(BASE_BACKOFF_MS * 2 ** (attempt - 1));\r\n continue;\r\n }\r\n throw lastErr;\r\n }\r\n\r\n if (res.ok) {\r\n return (await res.json()) as T;\r\n }\r\n\r\n const body = await res\r\n .json()\r\n .catch(() => ({ error: `Non-JSON ${res.status} response` }));\r\n const err = new WorkspaceApiError(res.status, body, path);\r\n\r\n // 5xx + 429 → retry with backoff. Everything else (401, 402, 4xx\r\n // generally, 500 — actual server bugs) is surfaced immediately so\r\n // the LLM can act on it.\r\n if (\r\n RETRYABLE_STATUSES.has(res.status) ||\r\n (res.status >= 502 && res.status <= 504)\r\n ) {\r\n lastErr = err;\r\n if (attempt < MAX_ATTEMPTS) {\r\n await sleep(BASE_BACKOFF_MS * 2 ** (attempt - 1));\r\n continue;\r\n }\r\n }\r\n\r\n throw err;\r\n }\r\n\r\n // Defensive: the loop above always either returns or throws. This\r\n // line only runs if MAX_ATTEMPTS = 0 (it isn't).\r\n throw lastErr ?? new WorkspaceApiError(0, { message: \"no attempts\" }, path);\r\n}\r\n\r\nfunction sleep(ms: number): Promise<void> {\r\n return new Promise((resolve) => setTimeout(resolve, ms));\r\n}\r\n","import { z } from \"zod\";\r\nimport type { CaptureStore, ListCapturesResult } from \"../store/types.js\";\r\n\r\n// Discovery tool. The LLM uses this to enumerate the user's library\r\n// before fetching specifics with get_capture. Paginated; returns\r\n// summaries only (no HTML / computed style / full payload — those\r\n// land via get_capture or the focused getters in M-MCP4).\r\n//\r\n// Charges 1 credit per successful call (workspace-side enforcement).\r\n\r\nexport const listCapturesInputSchema = z.object({\r\n q: z\r\n .string()\r\n .optional()\r\n .describe(\r\n \"Optional text filter applied to source_title, source_url, and note (case-insensitive substring match). Leave blank to list all.\",\r\n ),\r\n cursor: z\r\n .string()\r\n .optional()\r\n .describe(\r\n \"Opaque pagination cursor from a previous response's nextCursor field. Omit on the first page.\",\r\n ),\r\n limit: z\r\n .number()\r\n .int()\r\n .min(1)\r\n .max(50)\r\n .optional()\r\n .describe(\"Max captures to return. Default 20, max 50.\"),\r\n});\r\n\r\nexport const listCapturesOutputSchema = z.object({\r\n captures: z.array(\r\n z.object({\r\n id: z.string().describe(\"Capture UUID. Pass to get_capture for the full payload.\"),\r\n type: z\r\n .enum([\"page\", \"element\", \"composite\"])\r\n .describe(\r\n \"page = full-page screenshot + DOM context; element = a single picked element; composite = multiple elements stacked.\",\r\n ),\r\n sourceTitle: z.string(),\r\n sourceUrl: z.string(),\r\n capturedAt: z\r\n .string()\r\n .describe(\"ISO 8601 timestamp from the extension at capture time.\"),\r\n tags: z.array(z.string()),\r\n thumbnailUrl: z\r\n .string()\r\n .nullable()\r\n .describe(\r\n \"Signed Supabase Storage URL (1h TTL). Fetch fresh by re-calling list_captures or get_capture.\",\r\n ),\r\n }),\r\n ),\r\n nextCursor: z\r\n .string()\r\n .optional()\r\n .describe(\r\n \"When present, pass back as `cursor` to fetch the next page. Absent = no more rows.\",\r\n ),\r\n});\r\n\r\nexport type ListCapturesArgs = z.infer<typeof listCapturesInputSchema>;\r\n\r\nexport async function listCaptures(\r\n store: CaptureStore,\r\n args: ListCapturesArgs,\r\n): Promise<ListCapturesResult> {\r\n return store.list({\r\n q: args.q,\r\n cursor: args.cursor,\r\n limit: args.limit,\r\n });\r\n}\r\n","import { z } from \"zod\";\r\nimport type { CaptureFull, CaptureStore } from \"../store/types.js\";\r\n\r\n// Returns the full payload for one capture id — everything the\r\n// extension extracted (HTML, computed style, palette, fonts,\r\n// animation, media, ancestry, page sections, eyedropper picks) plus\r\n// fresh-signed Supabase URLs for the screenshot, thumbnail, and\r\n// (page captures only) the full-page stitch.\r\n//\r\n// Charges 1 credit per successful call. 404 (CaptureNotFound)\r\n// doesn't bill but is audited.\r\n\r\nconst UUID_RE =\r\n /^[0-9a-f]{8}-[0-9a-f]{4}-[1-5][0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$/i;\r\n\r\nexport const getCaptureInputSchema = z.object({\r\n id: z\r\n .string()\r\n .regex(UUID_RE, \"id must be a UUID\")\r\n .describe(\"Capture id from list_captures.\"),\r\n});\r\n\r\n// Output schema is intentionally loose. The `payload` field's shape\r\n// is the extension's Capture union (page / element / composite),\r\n// which is too rich to declare fully here without dragging the\r\n// whole type tree from @zaai/types. Clients that need typed access\r\n// can navigate via z.unknown() + their own narrowing.\r\nexport const getCaptureOutputSchema = z\r\n .object({\r\n id: z.string(),\r\n type: z.enum([\"page\", \"element\", \"composite\"]),\r\n projectId: z.string(),\r\n sourceTitle: z.string(),\r\n sourceUrl: z.string(),\r\n capturedAt: z.string(),\r\n note: z.string().nullable(),\r\n tags: z.array(z.string()),\r\n screenshotUrl: z\r\n .string()\r\n .nullable()\r\n .describe(\"Signed PNG URL, 1h TTL.\"),\r\n thumbnailUrl: z.string().nullable(),\r\n fullPageScreenshotUrl: z\r\n .string()\r\n .nullable()\r\n .describe(\r\n \"Page captures with the M9 stitch get a full-page PNG too. Null for element + composite + page captures without a stitch.\",\r\n ),\r\n payload: z\r\n .unknown()\r\n .describe(\r\n \"Full extension-side Capture JSON. Shape depends on `type` — see https://github.com/POLONIBOI/ZAAI_STUDIO-ext/blob/main/src/shared/types.ts for the union.\",\r\n ),\r\n })\r\n .passthrough();\r\n\r\nexport type GetCaptureArgs = z.infer<typeof getCaptureInputSchema>;\r\n\r\nexport async function getCapture(\r\n store: CaptureStore,\r\n args: GetCaptureArgs,\r\n): Promise<CaptureFull> {\r\n return store.get(args.id);\r\n}\r\n","import { z } from \"zod\";\r\nimport type { CaptureStore, ListCapturesResult } from \"../store/types.js\";\r\n\r\n// Search variant of list_captures with `q` REQUIRED. Same workspace\r\n// endpoint, same output shape — the win is a tool description tuned\r\n// for \"I have a specific concept to find\" so the LLM picks it over\r\n// list_captures when the user's intent is targeted retrieval.\r\n\r\nexport const searchCapturesInputSchema = z.object({\r\n q: z\r\n .string()\r\n .min(1)\r\n .describe(\r\n \"Case-insensitive substring match against source_title, source_url, and note. Required — use list_captures if you don't have a query.\",\r\n ),\r\n cursor: z.string().optional(),\r\n limit: z.number().int().min(1).max(50).optional(),\r\n});\r\n\r\nexport const searchCapturesOutputSchema = z.object({\r\n captures: z.array(\r\n z.object({\r\n id: z.string(),\r\n type: z.enum([\"page\", \"element\", \"composite\"]),\r\n sourceTitle: z.string(),\r\n sourceUrl: z.string(),\r\n capturedAt: z.string(),\r\n tags: z.array(z.string()),\r\n thumbnailUrl: z.string().nullable(),\r\n }),\r\n ),\r\n nextCursor: z.string().optional(),\r\n});\r\n\r\nexport type SearchCapturesArgs = z.infer<typeof searchCapturesInputSchema>;\r\n\r\nexport async function searchCaptures(\r\n store: CaptureStore,\r\n args: SearchCapturesArgs,\r\n): Promise<ListCapturesResult> {\r\n return store.list({ q: args.q, cursor: args.cursor, limit: args.limit });\r\n}\r\n","// Shared Zod shapes for the four focused-getter tools (get_palette,\r\n// get_html, get_animation, get_media). The tools differ only in\r\n// which `field` they pass through — schemas are identical otherwise,\r\n// so they live here to avoid copy-paste drift.\r\n\r\nimport { z } from \"zod\";\r\n\r\nconst UUID_RE =\r\n /^[0-9a-f]{8}-[0-9a-f]{4}-[1-5][0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$/i;\r\n\r\nexport const focusedGetterInputSchema = z.object({\r\n id: z\r\n .string()\r\n .regex(UUID_RE, \"id must be a UUID\")\r\n .describe(\r\n \"Capture id from list_captures or search_captures. UUID format.\",\r\n ),\r\n});\r\n\r\n// Shape of `data` varies per (capture.type, field) — see workspace\r\n// route lib/mcp/captures.ts → extractField() for the per-combination\r\n// shape. Using z.unknown() keeps the schema flexible; the LLM reads\r\n// structuredContent and the workspace docs are the source of truth.\r\nexport const focusedGetterOutputSchema = z\r\n .object({\r\n id: z.string(),\r\n type: z.enum([\"page\", \"element\", \"composite\"]),\r\n field: z.string(),\r\n data: z.unknown(),\r\n })\r\n .passthrough();\r\n\r\nexport type FocusedGetterArgs = z.infer<typeof focusedGetterInputSchema>;\r\n","import type { CaptureFieldResult, CaptureStore } from \"../store/types.js\";\r\nimport {\r\n focusedGetterInputSchema,\r\n focusedGetterOutputSchema,\r\n type FocusedGetterArgs,\r\n} from \"./_focused-getter.js\";\r\n\r\nexport {\r\n focusedGetterInputSchema as getPaletteInputSchema,\r\n focusedGetterOutputSchema as getPaletteOutputSchema,\r\n};\r\n\r\n// Returns the capture's colour palette.\r\n// page → 6 dominant hex colours extracted at capture time\r\n// element → manualPalette: eyedropper picks (Alt-held in inspect)\r\n// composite → primary slot's manualPalette\r\nexport async function getPalette(\r\n store: CaptureStore,\r\n args: FocusedGetterArgs,\r\n): Promise<CaptureFieldResult> {\r\n return store.getField(args.id, \"palette\");\r\n}\r\n","import type { CaptureFieldResult, CaptureStore } from \"../store/types.js\";\r\nimport {\r\n focusedGetterInputSchema,\r\n focusedGetterOutputSchema,\r\n type FocusedGetterArgs,\r\n} from \"./_focused-getter.js\";\r\n\r\nexport {\r\n focusedGetterInputSchema as getHtmlInputSchema,\r\n focusedGetterOutputSchema as getHtmlOutputSchema,\r\n};\r\n\r\n// Returns the capture's HTML.\r\n// page → full page HTML (large — wrap consumption appropriately)\r\n// element → outerHTML of the picked element\r\n// composite → outerHTML of each element joined with\r\n// `<!-- Element N: selector -->` markers\r\nexport async function getHtml(\r\n store: CaptureStore,\r\n args: FocusedGetterArgs,\r\n): Promise<CaptureFieldResult> {\r\n return store.getField(args.id, \"html\");\r\n}\r\n","import type { CaptureFieldResult, CaptureStore } from \"../store/types.js\";\r\nimport {\r\n focusedGetterInputSchema,\r\n focusedGetterOutputSchema,\r\n type FocusedGetterArgs,\r\n} from \"./_focused-getter.js\";\r\n\r\nexport {\r\n focusedGetterInputSchema as getAnimationInputSchema,\r\n focusedGetterOutputSchema as getAnimationOutputSchema,\r\n};\r\n\r\n// Returns the capture's animation data.\r\n// page → pageAnimations: keyframes vocabulary + detected\r\n// motion libraries (Framer Motion, GSAP, AOS, etc.)\r\n// element → element.animation (CSS transitions, keyframes,\r\n// hover/focus/active state diffs, live-observed flag)\r\n// + libraryHints (per-element data-attribute scan)\r\n// composite → per-element animation + libraryHints array\r\nexport async function getAnimation(\r\n store: CaptureStore,\r\n args: FocusedGetterArgs,\r\n): Promise<CaptureFieldResult> {\r\n return store.getField(args.id, \"animation\");\r\n}\r\n","import type { CaptureFieldResult, CaptureStore } from \"../store/types.js\";\r\nimport {\r\n focusedGetterInputSchema,\r\n focusedGetterOutputSchema,\r\n type FocusedGetterArgs,\r\n} from \"./_focused-getter.js\";\r\n\r\nexport {\r\n focusedGetterInputSchema as getMediaInputSchema,\r\n focusedGetterOutputSchema as getMediaOutputSchema,\r\n};\r\n\r\n// Returns the capture's rich-media inventory.\r\n// page → null (page captures don't carry per-element media)\r\n// element → videos (src/poster/autoplay/loop), images (src/srcset/\r\n// alt), backgrounds (computed background-image URLs),\r\n// carousels (Swiper/Glide/Splide/Slick/Flickity/Embla\r\n// with slide counts)\r\n// composite → per-element media object\r\nexport async function getMedia(\r\n store: CaptureStore,\r\n args: FocusedGetterArgs,\r\n): Promise<CaptureFieldResult> {\r\n return store.getField(args.id, \"media\");\r\n}\r\n","import { z } from \"zod\";\r\nimport type { ProjectStore, BrandBriefResult } from \"../store/types.js\";\r\n\r\nexport const getBrandBriefInputSchema = z.object({\r\n project_id: z\r\n .string()\r\n .uuid()\r\n .describe(\r\n \"Zaai Dev project UUID. Find via the workspace at zaaistudio.com/dev/projects.\",\r\n ),\r\n});\r\n\r\nexport const getBrandBriefOutputSchema = z\r\n .object({\r\n project_id: z.string(),\r\n project_name: z.string(),\r\n version: z.string().describe(\"Brief version number, or '0' if no brief has been generated yet.\"),\r\n status: z.enum([\"draft\", \"published\", \"archived\"]),\r\n positioning: z.string(),\r\n values: z.array(z.string()),\r\n voice: z.object({\r\n one_liner: z.string(),\r\n do_say: z.array(z.string()),\r\n dont_say: z.array(z.string()),\r\n }),\r\n audience: z.object({\r\n primary: z.string(),\r\n secondary: z.string().nullable(),\r\n needs: z.array(z.string()),\r\n }),\r\n design_intent: z.object({\r\n descriptors: z.array(z.string()),\r\n anti_descriptors: z.array(z.string()),\r\n }),\r\n decisions: z.array(\r\n z.object({\r\n id: z.string(),\r\n title: z.string(),\r\n decided_at: z.string(),\r\n rationale: z.string(),\r\n }),\r\n ),\r\n updated_at: z.string(),\r\n })\r\n .passthrough();\r\n\r\nexport async function getBrandBrief(\r\n store: ProjectStore,\r\n args: { project_id: string },\r\n): Promise<BrandBriefResult> {\r\n return store.getBrandBrief(args.project_id);\r\n}\r\n","import { z } from \"zod\";\r\nimport type { ProjectStore, VoiceResult } from \"../store/types.js\";\r\n\r\nexport const getVoiceInputSchema = z.object({\r\n project_id: z.string().uuid().describe(\"Zaai Dev project UUID.\"),\r\n});\r\n\r\nexport const getVoiceOutputSchema = z\r\n .object({\r\n project_id: z.string(),\r\n one_liner: z.string().describe(\"One-sentence summary of how the brand sounds.\"),\r\n tone_descriptors: z.array(z.string()).describe(\"Adjectives the brand voice aims for.\"),\r\n do_say: z.array(z.string()).describe(\"Phrasings / patterns the brand actively uses.\"),\r\n dont_say: z.array(z.string()).describe(\"Phrasings / patterns the brand explicitly avoids.\"),\r\n example_phrases: z.array(z.string()).describe(\"Concrete phrases that exemplify the voice.\"),\r\n })\r\n .passthrough();\r\n\r\nexport async function getVoice(\r\n store: ProjectStore,\r\n args: { project_id: string },\r\n): Promise<VoiceResult> {\r\n return store.getVoice(args.project_id);\r\n}\r\n","import { z } from \"zod\";\r\nimport type { ProjectStore, AudienceResult } from \"../store/types.js\";\r\n\r\nexport const getAudienceInputSchema = z.object({\r\n project_id: z.string().uuid().describe(\"Zaai Dev project UUID.\"),\r\n});\r\n\r\nexport const getAudienceOutputSchema = z\r\n .object({\r\n project_id: z.string(),\r\n primary: z.string().describe(\"Primary audience segment.\"),\r\n secondary: z.string().nullable().describe(\"Secondary audience segment, or null.\"),\r\n needs: z.array(z.string()).describe(\"Jobs-to-be-done / pain points the audience has.\"),\r\n channels: z.array(z.string()).describe(\"Where this audience consumes content.\"),\r\n })\r\n .passthrough();\r\n\r\nexport async function getAudience(\r\n store: ProjectStore,\r\n args: { project_id: string },\r\n): Promise<AudienceResult> {\r\n return store.getAudience(args.project_id);\r\n}\r\n","import { z } from \"zod\";\r\nimport type { ProjectStore, DesignIntentResult } from \"../store/types.js\";\r\n\r\nexport const getDesignIntentInputSchema = z.object({\r\n project_id: z.string().uuid().describe(\"Zaai Dev project UUID.\"),\r\n});\r\n\r\nexport const getDesignIntentOutputSchema = z\r\n .object({\r\n project_id: z.string(),\r\n descriptors: z\r\n .array(z.string())\r\n .describe(\r\n \"Visual adjectives the brand aims for (e.g. 'editorial', 'spacious', 'monochrome').\",\r\n ),\r\n anti_descriptors: z\r\n .array(z.string())\r\n .describe(\"Visual adjectives the brand explicitly avoids.\"),\r\n inspiration_summary: z\r\n .string()\r\n .describe(\"Free-form summary of the inspiration the brief points at.\"),\r\n })\r\n .passthrough();\r\n\r\nexport async function getDesignIntent(\r\n store: ProjectStore,\r\n args: { project_id: string },\r\n): Promise<DesignIntentResult> {\r\n return store.getDesignIntent(args.project_id);\r\n}\r\n","import { z } from \"zod\";\r\nimport type { ProjectStore, BrandTokensResult } from \"../store/types.js\";\r\n\r\nexport const getBrandTokensInputSchema = z.object({\r\n project_id: z.string().uuid().describe(\"Zaai Dev project UUID.\"),\r\n});\r\n\r\nexport const getBrandTokensOutputSchema = z\r\n .object({\r\n project_id: z.string(),\r\n colors: z.array(\r\n z.object({\r\n name: z.string(),\r\n value: z.string().describe(\"Hex / rgba / hsl value as authored.\"),\r\n role: z.string().optional().describe(\"Role like 'primary' / 'accent' / 'surface'.\"),\r\n }),\r\n ),\r\n fonts: z.array(\r\n z.object({\r\n role: z.string().describe(\"'display', 'body', 'mono', etc.\"),\r\n family: z.string(),\r\n weights: z.array(z.number().int()),\r\n }),\r\n ),\r\n radius: z.array(z.object({ name: z.string(), value: z.string() })),\r\n shadows: z.array(z.object({ name: z.string(), value: z.string() })),\r\n })\r\n .passthrough();\r\n\r\nexport async function getBrandTokens(\r\n store: ProjectStore,\r\n args: { project_id: string },\r\n): Promise<BrandTokensResult> {\r\n return store.getBrandTokens(args.project_id);\r\n}\r\n","import { z } from \"zod\";\r\nimport type { ProjectStore, DecisionsResult } from \"../store/types.js\";\r\n\r\nexport const getDecisionsInputSchema = z.object({\r\n project_id: z.string().uuid().describe(\"Zaai Dev project UUID.\"),\r\n limit: z\r\n .number()\r\n .int()\r\n .min(1)\r\n .max(200)\r\n .optional()\r\n .describe(\"Max decisions to return. Default 50, max 200, newest first.\"),\r\n});\r\n\r\nexport const getDecisionsOutputSchema = z\r\n .object({\r\n project_id: z.string(),\r\n items: z.array(\r\n z\r\n .object({\r\n id: z.string(),\r\n title: z.string(),\r\n rationale: z.string(),\r\n attribution: z\r\n .string()\r\n .describe(\r\n \"Who decided. 'mcp:<token_id>' for AI-logged decisions; user email / id for workspace-authored ones.\",\r\n ),\r\n brief_field: z\r\n .string()\r\n .nullable()\r\n .describe(\"Which brief slice this decision concerns, if any (e.g. 'voice.tone').\"),\r\n reference_capture_id: z.string().nullable(),\r\n created_at: z.string(),\r\n })\r\n .passthrough(),\r\n ),\r\n })\r\n .passthrough();\r\n\r\nexport async function getDecisions(\r\n store: ProjectStore,\r\n args: { project_id: string; limit?: number },\r\n): Promise<DecisionsResult> {\r\n return store.getDecisions(args.project_id, args.limit);\r\n}\r\n","import { z } from \"zod\";\r\nimport type { ProjectStore, ReferencesResult } from \"../store/types.js\";\r\n\r\nexport const getReferencesInputSchema = z.object({\r\n project_id: z.string().uuid().describe(\"Zaai Dev project UUID.\"),\r\n limit: z\r\n .number()\r\n .int()\r\n .min(1)\r\n .max(100)\r\n .optional()\r\n .describe(\"Max references to return. Default 20, max 100, newest first.\"),\r\n cursor: z\r\n .string()\r\n .optional()\r\n .describe(\"Opaque pagination cursor from the previous response's next_cursor.\"),\r\n});\r\n\r\nconst referenceItem = z\r\n .object({\r\n id: z.string(),\r\n type: z.enum([\"page\", \"element\", \"composite\"]),\r\n source_url: z.string(),\r\n source_title: z.string(),\r\n note: z.string().nullable(),\r\n captured_at: z.string(),\r\n thumbnail_url: z.string().nullable(),\r\n screenshot_url: z.string().nullable(),\r\n })\r\n .passthrough();\r\n\r\nexport const getReferencesOutputSchema = z\r\n .object({\r\n project_id: z.string(),\r\n items: z.array(referenceItem),\r\n next_cursor: z.string().nullable(),\r\n })\r\n .passthrough();\r\n\r\nexport async function getReferences(\r\n store: ProjectStore,\r\n args: { project_id: string; limit?: number; cursor?: string },\r\n): Promise<ReferencesResult> {\r\n return store.getReferences(args.project_id, {\r\n limit: args.limit,\r\n cursor: args.cursor,\r\n });\r\n}\r\n","import { z } from \"zod\";\r\nimport type { ProjectStore, SearchReferencesResult } from \"../store/types.js\";\r\n\r\nexport const searchReferencesInputSchema = z.object({\r\n project_id: z.string().uuid().describe(\"Zaai Dev project UUID.\"),\r\n q: z\r\n .string()\r\n .min(1)\r\n .max(200)\r\n .describe(\"Keyword query — matched against title / url / note (case-insensitive substring).\"),\r\n limit: z\r\n .number()\r\n .int()\r\n .min(1)\r\n .max(50)\r\n .optional()\r\n .describe(\"Max results to return. Default 10, max 50.\"),\r\n});\r\n\r\nconst searchReferenceItem = z\r\n .object({\r\n id: z.string(),\r\n type: z.enum([\"page\", \"element\", \"composite\"]),\r\n source_url: z.string(),\r\n source_title: z.string(),\r\n note: z.string().nullable(),\r\n captured_at: z.string(),\r\n thumbnail_url: z.string().nullable(),\r\n screenshot_url: z.string().nullable(),\r\n score: z\r\n .number()\r\n .describe(\"Relevance score 0..1. v1 keyword scoring: 1.0 title / 0.7 url / 0.5 note.\"),\r\n matched_field: z.enum([\"title\", \"url\", \"note\", \"tag\"]),\r\n })\r\n .passthrough();\r\n\r\nexport const searchReferencesOutputSchema = z\r\n .object({\r\n project_id: z.string(),\r\n query: z.string(),\r\n items: z.array(searchReferenceItem),\r\n })\r\n .passthrough();\r\n\r\nexport async function searchReferences(\r\n store: ProjectStore,\r\n args: { project_id: string; q: string; limit?: number },\r\n): Promise<SearchReferencesResult> {\r\n return store.searchReferences(args.project_id, {\r\n q: args.q,\r\n limit: args.limit,\r\n });\r\n}\r\n","import type { Config } from \"../config.js\";\r\nimport { mcpApiFetch } from \"../util/api.js\";\r\nimport type {\r\n CaptureField,\r\n CaptureFieldResult,\r\n CaptureFull,\r\n CaptureStore,\r\n ListCapturesArgs,\r\n ListCapturesResult,\r\n} from \"./types.js\";\r\n\r\n// HTTP shim against the workspace's /api/mcp/captures endpoints.\r\n// Each method is one mcpApiFetch call — bearer header + WorkspaceApiError\r\n// wrapping handled there. The thinness is the point: every store\r\n// method maps 1:1 to a workspace endpoint, so the surface is grep-able\r\n// and easy to mock for tests.\r\n\r\nexport class HttpCaptureStore implements CaptureStore {\r\n constructor(private readonly config: Config) {}\r\n\r\n async list(args: ListCapturesArgs): Promise<ListCapturesResult> {\r\n const sp = new URLSearchParams();\r\n if (args.q) sp.set(\"q\", args.q);\r\n if (args.cursor) sp.set(\"cursor\", args.cursor);\r\n if (args.limit !== undefined) sp.set(\"limit\", String(args.limit));\r\n const qs = sp.toString();\r\n return mcpApiFetch<ListCapturesResult>(\r\n this.config,\r\n `/api/mcp/captures${qs ? `?${qs}` : \"\"}`,\r\n );\r\n }\r\n\r\n async get(id: string): Promise<CaptureFull> {\r\n return mcpApiFetch<CaptureFull>(\r\n this.config,\r\n `/api/mcp/captures/${encodeURIComponent(id)}`,\r\n );\r\n }\r\n\r\n async getField(\r\n id: string,\r\n field: CaptureField,\r\n ): Promise<CaptureFieldResult> {\r\n return mcpApiFetch<CaptureFieldResult>(\r\n this.config,\r\n `/api/mcp/captures/${encodeURIComponent(id)}/${field}`,\r\n );\r\n }\r\n}\r\n","import type { Config } from \"../config.js\";\r\nimport { mcpApiFetch } from \"../util/api.js\";\r\nimport type {\r\n AudienceResult,\r\n BrandBriefResult,\r\n BrandTokensResult,\r\n DecisionsResult,\r\n DesignIntentResult,\r\n ProjectStore,\r\n ReferencesResult,\r\n SearchReferencesResult,\r\n VoiceResult,\r\n} from \"./types.js\";\r\n\r\n// HTTP shim against the workspace's per-project MCP endpoints\r\n// (/api/mcp/projects/[projectId]/*). Same shape as HttpCaptureStore\r\n// — each method is one mcpApiFetch call so the surface stays\r\n// grep-friendly + easy to mock. Project access enforcement +\r\n// credit billing happen workspace-side; this shim is transport only.\r\n\r\nexport class HttpProjectStore implements ProjectStore {\r\n constructor(private readonly config: Config) {}\r\n\r\n async getBrandBrief(projectId: string): Promise<BrandBriefResult> {\r\n return mcpApiFetch<BrandBriefResult>(\r\n this.config,\r\n `/api/mcp/projects/${encodeURIComponent(projectId)}/brief`,\r\n );\r\n }\r\n\r\n async getVoice(projectId: string): Promise<VoiceResult> {\r\n return mcpApiFetch<VoiceResult>(\r\n this.config,\r\n `/api/mcp/projects/${encodeURIComponent(projectId)}/voice`,\r\n );\r\n }\r\n\r\n async getAudience(projectId: string): Promise<AudienceResult> {\r\n return mcpApiFetch<AudienceResult>(\r\n this.config,\r\n `/api/mcp/projects/${encodeURIComponent(projectId)}/audience`,\r\n );\r\n }\r\n\r\n async getDesignIntent(projectId: string): Promise<DesignIntentResult> {\r\n return mcpApiFetch<DesignIntentResult>(\r\n this.config,\r\n `/api/mcp/projects/${encodeURIComponent(projectId)}/design-intent`,\r\n );\r\n }\r\n\r\n async getBrandTokens(projectId: string): Promise<BrandTokensResult> {\r\n return mcpApiFetch<BrandTokensResult>(\r\n this.config,\r\n `/api/mcp/projects/${encodeURIComponent(projectId)}/brand-tokens`,\r\n );\r\n }\r\n\r\n async getDecisions(projectId: string, limit?: number): Promise<DecisionsResult> {\r\n const sp = new URLSearchParams();\r\n if (limit !== undefined) sp.set(\"limit\", String(limit));\r\n const qs = sp.toString();\r\n return mcpApiFetch<DecisionsResult>(\r\n this.config,\r\n `/api/mcp/projects/${encodeURIComponent(projectId)}/decisions${qs ? `?${qs}` : \"\"}`,\r\n );\r\n }\r\n\r\n async getReferences(\r\n projectId: string,\r\n args: { limit?: number; cursor?: string },\r\n ): Promise<ReferencesResult> {\r\n const sp = new URLSearchParams();\r\n if (args.limit !== undefined) sp.set(\"limit\", String(args.limit));\r\n if (args.cursor) sp.set(\"cursor\", args.cursor);\r\n const qs = sp.toString();\r\n return mcpApiFetch<ReferencesResult>(\r\n this.config,\r\n `/api/mcp/projects/${encodeURIComponent(projectId)}/references${qs ? `?${qs}` : \"\"}`,\r\n );\r\n }\r\n\r\n async searchReferences(\r\n projectId: string,\r\n args: { q: string; limit?: number },\r\n ): Promise<SearchReferencesResult> {\r\n const sp = new URLSearchParams();\r\n sp.set(\"q\", args.q);\r\n if (args.limit !== undefined) sp.set(\"limit\", String(args.limit));\r\n return mcpApiFetch<SearchReferencesResult>(\r\n this.config,\r\n `/api/mcp/projects/${encodeURIComponent(projectId)}/references/search?${sp.toString()}`,\r\n );\r\n }\r\n}\r\n","import {\r\n McpServer,\r\n ResourceTemplate,\r\n} from \"@modelcontextprotocol/sdk/server/mcp.js\";\r\nimport type { CaptureStore } from \"../store/types.js\";\r\n\r\n// Resource: zaai-capture://{id}\r\n//\r\n// Lets the user attach a specific capture to a Claude Desktop /\r\n// Cursor conversation via the resource picker without invoking a\r\n// tool first. The body is the same JSON the get_capture tool\r\n// returns, served as application/json.\r\n//\r\n// Resource reads bypass the credit charge — they're user-driven\r\n// attachments, not LLM-driven tool calls. Workspace currently\r\n// routes both through GET /api/mcp/captures/[id] which DOES debit.\r\n// For v1 we accept the charge: it's still bounded by the user's own\r\n// attachment behaviour and folds into the same audit trail. If\r\n// resource reads ever outpace tool calls we can split into a\r\n// non-billing endpoint.\r\n\r\nexport function registerCaptureResource(\r\n server: McpServer,\r\n store: CaptureStore,\r\n): void {\r\n server.registerResource(\r\n \"capture\",\r\n new ResourceTemplate(\"zaai-capture://{id}\", {\r\n list: undefined,\r\n }),\r\n {\r\n title: \"Zaai Dev capture\",\r\n description:\r\n \"Attach one capture from the user's Zaai Dev library as JSON. \" +\r\n \"URI: zaai-capture://<capture-id>. The id comes from list_captures.\",\r\n mimeType: \"application/json\",\r\n },\r\n async (uri, variables) => {\r\n const rawId = variables.id;\r\n const id = Array.isArray(rawId) ? rawId[0] : rawId;\r\n const capture = await store.get(id);\r\n return {\r\n contents: [\r\n {\r\n uri: uri.href,\r\n mimeType: \"application/json\",\r\n text: JSON.stringify(capture, null, 2),\r\n },\r\n ],\r\n };\r\n },\r\n );\r\n}\r\n","// stderr-only logger.\r\n//\r\n// MCP servers using the stdio transport MUST NOT write anything to\r\n// stdout other than the JSON-RPC framing produced by the SDK. A\r\n// stray byte — a banner, console.log, unhandled rejection, even a\r\n// trailing newline from a misconfigured shebang — closes the\r\n// transport with `-32000 connection closed`. This is the #1\r\n// production failure mode for MCP servers (research memory\r\n// `project_mcp_build_plan` § Don't-make-these-mistakes #1).\r\n//\r\n// Use this module instead of console.* anywhere in src/.\r\n\r\nconst PREFIX = \"[zaai-mcp]\";\r\n\r\nfunction write(level: string, message: string, meta?: unknown): void {\r\n let line = `${PREFIX} ${level} ${message}`;\r\n if (meta !== undefined) {\r\n line += \" \" + safeStringify(meta);\r\n }\r\n process.stderr.write(line + \"\\n\");\r\n}\r\n\r\nfunction safeStringify(value: unknown): string {\r\n try {\r\n if (value instanceof Error) {\r\n return value.stack ?? `${value.name}: ${value.message}`;\r\n }\r\n return JSON.stringify(value);\r\n } catch {\r\n return String(value);\r\n }\r\n}\r\n\r\nexport function info(message: string, meta?: unknown): void {\r\n write(\"INFO\", message, meta);\r\n}\r\n\r\nexport function warn(message: string, meta?: unknown): void {\r\n write(\"WARN\", message, meta);\r\n}\r\n\r\nexport function error(message: string, meta?: unknown): void {\r\n write(\"ERROR\", message, meta);\r\n}\r\n","import * as log from \"./log.js\";\r\n\r\n// Runtime config — parsed from env vars at startup. The MCP server\r\n// fails fast in src/bin/stdio.ts if required values are missing,\r\n// because launching without them produces opaque downstream errors\r\n// (the first tool call 401s, and the user has no signal why).\r\n//\r\n// Env vars are the only config primitive every MCP client supports\r\n// uniformly. Claude Desktop / Cursor / Claude Code all let users\r\n// set them in their per-server config.\r\n\r\nexport interface Config {\r\n /** Bearer token. Must start with `zaai_mcp_`. */\r\n apiToken: string;\r\n /** Base URL of the workspace API (no trailing slash). */\r\n apiUrl: string;\r\n}\r\n\r\nconst DEFAULT_API_URL = \"https://www.zaaistudio.com\";\r\n\r\nexport class ConfigError extends Error {\r\n constructor(message: string) {\r\n super(message);\r\n this.name = \"ConfigError\";\r\n }\r\n}\r\n\r\nexport function loadConfig(): Config {\r\n const apiToken = process.env.ZAAI_API_TOKEN;\r\n if (!apiToken) {\r\n throw new ConfigError(\r\n \"ZAAI_API_TOKEN is not set. Mint a token at \" +\r\n \"https://www.zaaistudio.com/dev/settings/tokens (kind = mcp) \" +\r\n \"and pass it via the env in your MCP client config.\",\r\n );\r\n }\r\n if (!apiToken.startsWith(\"zaai_mcp_\")) {\r\n throw new ConfigError(\r\n \"ZAAI_API_TOKEN must start with 'zaai_mcp_'. Did you paste an \" +\r\n \"extension token (zaai_ext_*) by accident? Issue an AI tool \" +\r\n \"token at https://www.zaaistudio.com/dev/settings/tokens.\",\r\n );\r\n }\r\n\r\n const rawUrl = process.env.ZAAI_API_URL ?? DEFAULT_API_URL;\r\n const apiUrl = rawUrl.replace(/\\/+$/, \"\");\r\n\r\n log.info(\"config loaded\", { apiUrl });\r\n return { apiToken, apiUrl };\r\n}\r\n"],"mappings":"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","names":["McpServer","z","err","z","z","z","z","z","UUID_RE","z","z","z","z","z","z","z","z","McpServer"]}