@teamix-evo/mcp 0.3.0 → 0.4.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +1 -1
- package/dist/cli.js +161 -162
- package/dist/cli.js.map +1 -1
- package/dist/data/adr/0001-three-layer-alignment.md +54 -0
- package/dist/data/adr/0002-package-naming.md +50 -0
- package/dist/data/adr/0003-update-strategy-tri-state.md +62 -0
- package/dist/data/adr/0004-cli-command-structure.md +61 -0
- package/dist/data/adr/0005-ui-no-variant.md +67 -0
- package/dist/data/adr/0006-ui-upgrade-no-baseline.md +67 -0
- package/dist/data/adr/0007-governance-docs-at-root.md +62 -0
- package/dist/data/adr/0008-eslint-visual-rules-warn-baseline.md +110 -0
- package/dist/data/adr/0009-registry-mcp-protocol-layer.md +87 -0
- package/dist/data/adr/0010-design-default-and-variants.md +319 -0
- package/dist/data/adr/0011-mcp-single-package-multi-group.md +169 -0
- package/dist/data/adr/0012-lint-shared-core.md +215 -0
- package/dist/data/adr/0013-skills-source-mirror.md +154 -0
- package/dist/data/adr/0014-ui-biz-ui-templates-tier.md +274 -0
- package/dist/data/adr/0015-skill-description-trigger-contract.md +122 -0
- package/dist/data/adr/0016-design-md-brand-charter.md +93 -0
- package/dist/data/adr/0017-mcp-design-group.md +107 -0
- package/dist/data/adr/0018-ai-context-routing.md +112 -0
- package/dist/data/adr/0019-project-upgrade-flow.md +156 -0
- package/dist/data/adr/0020-design-to-tokens-skill-fusion.md +139 -0
- package/dist/data/adr/README.md +70 -0
- package/dist/data/adr/_template.md +36 -0
- package/dist/index.d.ts +64 -59
- package/dist/index.js +168 -170
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/server.ts","../src/groups/registry.ts","../src/manifest-loader.ts","../src/groups/adr.ts","../src/adr-loader.ts","../src/groups/skills.ts","../src/skills-loader.ts","../src/groups/design.ts","../src/design-loader.ts"],"sourcesContent":["/**\n * Main MCP server — composes multiple tool groups into one stdio process.\n *\n * Architecture per [ADR 0011](../../../docs/adr/0011-mcp-single-package-multi-group.md):\n * single package / single bin / multiple tool groups. Groups added in later\n * milestones (design v0.6, adr v0.7, scenario v0.8) plug in here without\n * touching the transport or ListTools/CallTool handler logic.\n *\n * Tool dispatch:\n * - `tools/list` returns the union of all groups' tools.\n * - `tools/call` walks the group list in registration order; the first group\n * whose `handle` returns a non-`undefined` result wins. Tool-name uniqueness\n * across groups is the responsibility of group authors (see ADR 0011 §5\n * for the `<group>_<verb>_<noun>` naming convention; `registry` is the\n * historical exception).\n */\nimport { Server } from '@modelcontextprotocol/sdk/server/index.js';\nimport {\n CallToolRequestSchema,\n ListToolsRequestSchema,\n} from '@modelcontextprotocol/sdk/types.js';\nimport { createRegistryGroup, type RegistryGroupOptions } from './groups/registry.js';\nimport { createAdrGroup, type AdrGroupOptions } from './groups/adr.js';\nimport { createSkillsGroup, type SkillsGroupOptions } from './groups/skills.js';\nimport { createDesignGroup, type DesignGroupOptions } from './groups/design.js';\nimport type { ToolGroup } from './types.js';\n\nexport interface ServerOptions {\n /** Options forwarded to the registry group. Pass `loaded` in tests. */\n registry?: RegistryGroupOptions;\n /** Options forwarded to the adr group. Pass `loaded` in tests. */\n adr?: AdrGroupOptions;\n /** Options forwarded to the skills group. Pass `loaded` in tests. */\n skills?: SkillsGroupOptions;\n /** Options forwarded to the design group. Pass `loaded` in tests. */\n design?: DesignGroupOptions;\n}\n\nexport function createServer(opts: ServerOptions = {}): Server {\n const groups: ToolGroup[] = [\n createRegistryGroup(opts.registry),\n createAdrGroup(opts.adr),\n createSkillsGroup(opts.skills),\n createDesignGroup(opts.design),\n // Future: createScenarioGroup(opts.scenario), // ADR 0011, v0.8\n ];\n\n // Sanity check: tool names must be unique across groups.\n const seen = new Set<string>();\n for (const group of groups) {\n for (const tool of group.tools) {\n if (seen.has(tool.name)) {\n throw new Error(\n `Duplicate MCP tool name across groups: ${tool.name}. ` +\n `Each group must use unique tool names — see ADR 0011 §5.`,\n );\n }\n seen.add(tool.name);\n }\n }\n\n const allTools = groups.flatMap((g) => g.tools);\n\n const server = new Server(\n {\n name: '@teamix-evo/mcp',\n version: '0.2.0',\n },\n {\n capabilities: { tools: {} },\n },\n );\n\n server.setRequestHandler(ListToolsRequestSchema, async () => ({\n tools: allTools,\n }));\n\n server.setRequestHandler(CallToolRequestSchema, async (req) => {\n const { name, arguments: args } = req.params;\n for (const group of groups) {\n const result = await group.handle(name, args);\n if (result !== undefined) return result;\n }\n return {\n content: [\n {\n type: 'text',\n text: `Unknown tool: ${name}. Use tools/list to discover available tools.`,\n },\n ],\n isError: true,\n };\n });\n\n return server;\n}\n","/**\n * Registry tool group — exposes the @teamix-evo/ui component registry to AI\n * editors.\n *\n * Originally `src/server.ts` of `@teamix-evo/registry-mcp`. Moved here as part\n * of [ADR 0011](../../../../docs/adr/0011-mcp-single-package-multi-group.md)\n * single-package / multi-group restructure.\n *\n * Tool naming is the **historical exception**: `list_components` /\n * `get_component_meta` / `find_components` keep their unprefixed names because\n * they're already in production AI client memory (see ADR 0011 §5). All\n * future groups (`design_*`, `adr_*`, `scenario_*`) MUST use the\n * `<group>_<verb>_<noun>` prefix convention.\n */\nimport { z } from 'zod';\nimport type { Tool } from '@modelcontextprotocol/sdk/types.js';\nimport {\n loadManifest,\n loadMeta,\n type LoadedManifest,\n} from '../manifest-loader.js';\nimport type { ToolGroup, ToolResult } from '../types.js';\nimport type { UiEntry } from '@teamix-evo/registry';\n\nconst ListComponentsInput = z.object({\n status: z.enum(['stable', 'experimental', 'deprecated']).optional(),\n});\n\nconst GetComponentMetaInput = z.object({\n id: z.string().min(1),\n});\n\nconst FindComponentsInput = z.object({\n query: z.string().min(1),\n limit: z.number().int().positive().max(100).optional(),\n});\n\nconst TOOLS: Tool[] = [\n {\n name: 'list_components',\n description:\n 'List all UI components in the @teamix-evo/ui registry. Optionally filter by status (stable / experimental / deprecated). Returns id, name, description, status, registryDependencies — small enough for the model to scan whole.',\n inputSchema: {\n type: 'object',\n properties: {\n status: {\n type: 'string',\n enum: ['stable', 'experimental', 'deprecated'],\n description: 'Filter by maturity status.',\n },\n },\n },\n },\n {\n name: 'get_component_meta',\n description:\n 'Fetch the full registry entry + parsed meta.md for a single component by id. Returns props schema reference, registryDependencies, npm dependencies, AI generation rules, and the component description.',\n inputSchema: {\n type: 'object',\n properties: {\n id: {\n type: 'string',\n description: 'Component id (e.g. \"button\", \"data-table\").',\n },\n },\n required: ['id'],\n },\n },\n {\n name: 'find_components',\n description:\n 'Substring match over component id / name / description. Use when you need a component but don\\'t know its exact id (e.g. \"find a component supporting async search and pagination\"). Returns up to `limit` matches (default 10). Note: substring match is a v0.1 implementation; semantic search is planned for v0.7 (see ADR 0009).',\n inputSchema: {\n type: 'object',\n properties: {\n query: {\n type: 'string',\n description: 'Free-text query.',\n },\n limit: {\n type: 'integer',\n minimum: 1,\n maximum: 100,\n description: 'Max matches to return (default 10).',\n },\n },\n required: ['query'],\n },\n },\n];\n\nconst TOOL_NAMES = new Set(TOOLS.map((t) => t.name));\n\nfunction pickListEntry(entry: UiEntry) {\n return {\n id: entry.id,\n name: entry.name,\n type: entry.type,\n description: entry.description,\n status: entry.status,\n deprecatedReason: entry.deprecatedReason,\n replacedBy: entry.replacedBy,\n registryDependencies: entry.registryDependencies ?? [],\n };\n}\n\nexport interface RegistryGroupOptions {\n /** Pre-loaded manifest (used in tests to avoid filesystem). */\n loaded?: LoadedManifest;\n}\n\nexport function createRegistryGroup(opts: RegistryGroupOptions = {}): ToolGroup {\n // Lazy-load the manifest so failures yield a tool-call error rather than\n // blocking server startup (which would prevent the MCP client from even\n // discovering the tools and seeing a usable error message).\n let cache: LoadedManifest | null = opts.loaded ?? null;\n function getManifest(): LoadedManifest {\n if (!cache) cache = loadManifest();\n return cache;\n }\n\n return {\n name: 'registry',\n tools: TOOLS,\n async handle(name, args): Promise<ToolResult | undefined> {\n if (!TOOL_NAMES.has(name)) return undefined;\n\n if (name === 'list_components') {\n const input = ListComponentsInput.parse(args ?? {});\n const { manifest } = getManifest();\n const entries = manifest.entries\n .filter((e) => e.type === 'component')\n .filter((e) => (input.status ? e.status === input.status : true))\n .map(pickListEntry);\n return {\n content: [{ type: 'text', text: JSON.stringify(entries, null, 2) }],\n };\n }\n\n if (name === 'get_component_meta') {\n const input = GetComponentMetaInput.parse(args);\n const { manifest, rootDir } = getManifest();\n const entry = manifest.entries.find((e) => e.id === input.id);\n if (!entry) {\n return {\n content: [\n {\n type: 'text',\n text: `Component not found: ${input.id}. Use list_components to discover ids.`,\n },\n ],\n isError: true,\n };\n }\n const meta = loadMeta(entry, rootDir);\n const payload = {\n entry,\n meta: meta ?? null,\n };\n return {\n content: [{ type: 'text', text: JSON.stringify(payload, null, 2) }],\n };\n }\n\n if (name === 'find_components') {\n const input = FindComponentsInput.parse(args);\n const limit = input.limit ?? 10;\n const q = input.query.toLowerCase();\n const { manifest } = getManifest();\n const matches = manifest.entries\n .filter((e) => e.type === 'component')\n .filter((e) => {\n return (\n e.id.toLowerCase().includes(q) ||\n e.name.toLowerCase().includes(q) ||\n e.description.toLowerCase().includes(q)\n );\n })\n .slice(0, limit)\n .map(pickListEntry);\n return {\n content: [\n {\n type: 'text',\n text: JSON.stringify(\n {\n query: input.query,\n limit,\n count: matches.length,\n results: matches,\n },\n null,\n 2,\n ),\n },\n ],\n };\n }\n\n // Unreachable — TOOL_NAMES guard above ensures we only enter known names.\n return undefined;\n },\n };\n}\n","import { readFileSync, existsSync } from 'node:fs';\nimport { dirname, join, resolve } from 'node:path';\nimport { UiPackageManifestSchema } from '@teamix-evo/registry';\nimport type { UiEntry, UiPackageManifest } from '@teamix-evo/registry';\n\n/**\n * Resolves the `@teamix-evo/ui/manifest.json` path using a layered strategy:\n *\n * 1. `TEAMIX_EVO_UI_MANIFEST` env var (absolute path)\n * 2. `<cwd>/node_modules/@teamix-evo/ui/manifest.json`\n * 3. Walking up parent directories until a matching `node_modules/...` is found\n * 4. Throws with a clear error message\n */\nexport function resolveManifestPath(startDir: string = process.cwd()): string {\n const envPath = process.env.TEAMIX_EVO_UI_MANIFEST;\n if (envPath && existsSync(envPath)) {\n return envPath;\n }\n\n let dir = resolve(startDir);\n // Limit walk to prevent runaway in pathological filesystems.\n for (let i = 0; i < 16; i++) {\n const candidate = join(\n dir,\n 'node_modules',\n '@teamix-evo',\n 'ui',\n 'manifest.json',\n );\n if (existsSync(candidate)) {\n return candidate;\n }\n const parent = dirname(dir);\n if (parent === dir) break; // reached filesystem root\n dir = parent;\n }\n\n throw new Error(\n [\n 'Could not locate @teamix-evo/ui/manifest.json.',\n `Tried env TEAMIX_EVO_UI_MANIFEST + walking up from ${startDir}.`,\n 'Either install @teamix-evo/ui in the consumer project, or set TEAMIX_EVO_UI_MANIFEST to an absolute path.',\n ].join(' '),\n );\n}\n\nexport interface LoadedManifest {\n manifest: UiPackageManifest;\n /** Directory of the manifest.json itself; used to resolve `meta.md` paths. */\n rootDir: string;\n}\n\n/**\n * Loads and Zod-validates the UI package manifest.\n * Throws on invalid manifest with the underlying Zod error attached.\n */\nexport function loadManifest(path?: string): LoadedManifest {\n const manifestPath = path ?? resolveManifestPath();\n const raw = JSON.parse(readFileSync(manifestPath, 'utf-8')) as unknown;\n const result = UiPackageManifestSchema.safeParse(raw);\n if (!result.success) {\n throw new Error(\n `Invalid manifest at ${manifestPath}: ${result.error.message}`,\n );\n }\n return {\n manifest: result.data,\n rootDir: dirname(manifestPath),\n };\n}\n\n/**\n * Frontmatter + body extracted from a `<id>.meta.md` file.\n * Frontmatter is parsed as a flat key/value map (no YAML library dep —\n * meta.md frontmatters are intentionally simple).\n */\nexport interface ParsedMeta {\n frontmatter: Record<string, string>;\n body: string;\n}\n\n/**\n * Reads and minimally parses a `<id>.meta.md` file. Returns `null` if the\n * meta file is missing or the entry didn't declare one.\n *\n * Frontmatter parser is minimal (single-line `key: value` pairs only). It\n * does NOT support nested or array YAML — sufficient for the meta.md format\n * documented in packages/ui/AGENTS.md §三.E.\n */\nexport function loadMeta(\n entry: UiEntry,\n rootDir: string,\n): ParsedMeta | null {\n if (!entry.meta) return null;\n const path = join(rootDir, entry.meta);\n if (!existsSync(path)) return null;\n const text = readFileSync(path, 'utf-8');\n return parseFrontmatter(text);\n}\n\nfunction parseFrontmatter(text: string): ParsedMeta {\n const FM_RE = /^---\\s*\\n([\\s\\S]*?)\\n---\\s*\\n?/;\n const match = text.match(FM_RE);\n if (!match) {\n return { frontmatter: {}, body: text };\n }\n const fm: Record<string, string> = {};\n // Capture group [1] is guaranteed when match succeeds.\n for (const line of match[1]!.split('\\n')) {\n const m = line.match(/^([A-Za-z_][\\w-]*)\\s*:\\s*(.+?)\\s*$/);\n if (m) fm[m[1]!] = m[2]!.replace(/^['\"]|['\"]$/g, '');\n }\n return {\n frontmatter: fm,\n body: text.slice(match[0].length),\n };\n}\n","/**\n * ADR tool group — exposes Architecture Decision Records to AI editors.\n *\n * Per [ADR 0011 §5](../../../../docs/adr/0011-mcp-single-package-multi-group.md),\n * new groups use the `<group>_<verb>` prefix convention:\n *\n * - `adr_list` — index of all ADRs (id, title, status, date)\n * - `adr_get` — full markdown body for one ADR\n * - `adr_find` — substring search across title + body\n *\n * Use this group to let AI agents:\n *\n * - Cite ADRs in PR reviews (\"this change violates ADR 0008 §2.B\")\n * - Resolve \"why was this done?\" questions before recommending refactors\n * - Discover related ADRs when proposing a new decision\n */\nimport { z } from 'zod';\nimport type { Tool } from '@modelcontextprotocol/sdk/types.js';\nimport {\n loadAdrIndex,\n loadAdrContent,\n findAdr,\n type LoadedAdrs,\n} from '../adr-loader.js';\nimport type { ToolGroup, ToolResult } from '../types.js';\n\nconst ListInput = z.object({\n /** Match `Status` line by substring (case-insensitive). */\n status: z.string().min(1).optional(),\n});\n\nconst GetInput = z.object({\n /** ADR id (\"0011\") or full slug (\"0011-mcp-single-package-multi-group\"). */\n id: z.string().min(1),\n});\n\nconst FindInput = z.object({\n query: z.string().min(1),\n limit: z.number().int().positive().max(50).optional(),\n /**\n * When true, returns a snippet (~200 chars) around each match so the model\n * can decide whether to fetch the full ADR. Defaults to true.\n */\n withSnippets: z.boolean().optional(),\n});\n\nconst TOOLS: Tool[] = [\n {\n name: 'adr_list',\n description:\n 'List all Architecture Decision Records (ADRs) in docs/adr/. Returns id (4-digit), slug, title, status, date, region for each. Use this as the first call to discover which decisions exist before drilling into one with adr_get. Filter by status substring (e.g. \"Accepted\" / \"Proposed\" / \"Superseded\") to narrow down.',\n inputSchema: {\n type: 'object',\n properties: {\n status: {\n type: 'string',\n description:\n 'Optional case-insensitive substring filter against the ADR Status line. Examples: \"Accepted\", \"Proposed\", \"Superseded\".',\n },\n },\n },\n },\n {\n name: 'adr_get',\n description:\n 'Fetch the full markdown body of one ADR by id (\"0011\") or slug (\"0011-mcp-single-package-multi-group\"). Returns the entry metadata + raw markdown so the model can cite specific sections (Context / Decision / Consequences / Source). Use after adr_list / adr_find to read a specific decision in full.',\n inputSchema: {\n type: 'object',\n properties: {\n id: {\n type: 'string',\n description:\n 'ADR id (\"0011\") or full slug (\"0011-mcp-single-package-multi-group\").',\n },\n },\n required: ['id'],\n },\n },\n {\n name: 'adr_find',\n description:\n 'Substring search across ADR titles and bodies (case-insensitive). Use when you remember a phrase (\"source-mirror\", \"lint-core\", \"no baseline\") but not which ADR it lives in. Returns up to `limit` matches (default 10) with optional snippets (~200 chars around each match). Combine with adr_get for the full text.',\n inputSchema: {\n type: 'object',\n properties: {\n query: { type: 'string', description: 'Free-text query.' },\n limit: {\n type: 'integer',\n minimum: 1,\n maximum: 50,\n description: 'Max matches to return (default 10).',\n },\n withSnippets: {\n type: 'boolean',\n description: 'Include ~200-char snippet around each match (default true).',\n },\n },\n required: ['query'],\n },\n },\n];\n\nconst TOOL_NAMES = new Set(TOOLS.map((t) => t.name));\n\nfunction pickEntry(e: {\n id: string;\n slug: string;\n title: string;\n status: string;\n date: string;\n region: string;\n}) {\n return {\n id: e.id,\n slug: e.slug,\n title: e.title,\n status: e.status,\n date: e.date,\n region: e.region,\n };\n}\n\nconst SNIPPET_RADIUS = 100;\n\nfunction snippet(text: string, index: number): string {\n const start = Math.max(0, index - SNIPPET_RADIUS);\n const end = Math.min(text.length, index + SNIPPET_RADIUS);\n const prefix = start > 0 ? '…' : '';\n const suffix = end < text.length ? '…' : '';\n return prefix + text.slice(start, end).replace(/\\s+/g, ' ').trim() + suffix;\n}\n\nexport interface AdrGroupOptions {\n /** Pre-loaded index (used in tests to avoid filesystem). */\n loaded?: LoadedAdrs;\n}\n\nexport function createAdrGroup(opts: AdrGroupOptions = {}): ToolGroup {\n let cache: LoadedAdrs | null = opts.loaded ?? null;\n function getIndex(): LoadedAdrs {\n if (!cache) cache = loadAdrIndex();\n return cache;\n }\n\n return {\n name: 'adr',\n tools: TOOLS,\n async handle(name, args): Promise<ToolResult | undefined> {\n if (!TOOL_NAMES.has(name)) return undefined;\n\n if (name === 'adr_list') {\n const input = ListInput.parse(args ?? {});\n const idx = getIndex();\n const needle = input.status?.toLowerCase();\n const entries = idx.entries\n .filter((e) =>\n needle ? e.status.toLowerCase().includes(needle) : true,\n )\n .map(pickEntry);\n return {\n content: [{ type: 'text', text: JSON.stringify(entries, null, 2) }],\n };\n }\n\n if (name === 'adr_get') {\n const input = GetInput.parse(args);\n const idx = getIndex();\n const entry = findAdr(idx, input.id);\n if (!entry) {\n return {\n content: [\n {\n type: 'text',\n text: `ADR not found: ${input.id}. Use adr_list to discover ids.`,\n },\n ],\n isError: true,\n };\n }\n const text = loadAdrContent(entry);\n return {\n content: [\n {\n type: 'text',\n text: JSON.stringify(\n { entry: pickEntry(entry), content: text },\n null,\n 2,\n ),\n },\n ],\n };\n }\n\n if (name === 'adr_find') {\n const input = FindInput.parse(args);\n const limit = input.limit ?? 10;\n const withSnippets = input.withSnippets ?? true;\n const needle = input.query.toLowerCase();\n const idx = getIndex();\n\n const matches: Array<{\n entry: ReturnType<typeof pickEntry>;\n snippets?: string[];\n hitCount: number;\n }> = [];\n for (const entry of idx.entries) {\n const body = loadAdrContent(entry).toLowerCase();\n const titleHit = entry.title.toLowerCase().includes(needle);\n if (!titleHit && !body.includes(needle)) continue;\n\n const snippets: string[] = [];\n if (withSnippets) {\n const rawBody = loadAdrContent(entry);\n let from = 0;\n // Up to 3 snippets per ADR to keep response compact.\n for (let i = 0; i < 3; i++) {\n const at = rawBody.toLowerCase().indexOf(needle, from);\n if (at < 0) break;\n snippets.push(snippet(rawBody, at));\n from = at + needle.length;\n }\n }\n // Count total hits in body for ranking.\n let hits = titleHit ? 1 : 0;\n let from = 0;\n for (;;) {\n const at = body.indexOf(needle, from);\n if (at < 0) break;\n hits++;\n from = at + needle.length;\n }\n matches.push({\n entry: pickEntry(entry),\n ...(withSnippets ? { snippets } : {}),\n hitCount: hits,\n });\n }\n matches.sort((a, b) => b.hitCount - a.hitCount);\n const sliced = matches.slice(0, limit);\n return {\n content: [\n {\n type: 'text',\n text: JSON.stringify(\n {\n query: input.query,\n limit,\n count: sliced.length,\n totalMatchingAdrs: matches.length,\n results: sliced,\n },\n null,\n 2,\n ),\n },\n ],\n };\n }\n\n return undefined;\n },\n };\n}\n","/**\n * Loader for ADR (Architecture Decision Record) markdown files.\n *\n * ADRs live in `docs/adr/<NNNN>-<slug>.md` per [ADR 0007](../../../docs/adr/0007-governance-docs-at-root.md).\n * Each file has the shape:\n *\n * ```md\n * # 0011. <title>\n *\n * - **Status**: Proposed | Accepted | Superseded by NNNN | Deprecated\n * - **Date**: YYYY-MM-DD\n * - **Region**: 0100–0999 协议与工具\n * - **Related ADR**: [0007 ...](...)\n *\n * ## Context\n * ...\n * ```\n *\n * This loader parses just enough metadata to power the `adr_list` /\n * `adr_get` / `adr_find` MCP tools (see [`groups/adr.ts`](./groups/adr.ts)).\n * `README.md` and `_template.md` are skipped — they are not ADRs.\n */\nimport { existsSync, readFileSync, readdirSync } from 'node:fs';\nimport { dirname, join, resolve } from 'node:path';\n\nexport interface AdrEntry {\n /** Numeric id, e.g. \"0011\". Derived from the filename prefix. */\n id: string;\n /** Filename without `.md`, e.g. \"0011-mcp-single-package-multi-group\". */\n slug: string;\n /** Title after \"NNNN. \" in the H1 line. */\n title: string;\n /** Raw status string from the `- **Status**:` line. Empty if missing. */\n status: string;\n /** Date from the `- **Date**:` line (YYYY-MM-DD). Empty if missing. */\n date: string;\n /** Optional region label (`0100–0999 协议与工具`). Empty if missing. */\n region: string;\n /** Absolute path to the source file (for `adr_get`). */\n filePath: string;\n}\n\nexport interface LoadedAdrs {\n /** Directory containing the ADR `.md` files. */\n rootDir: string;\n entries: AdrEntry[];\n}\n\n/**\n * Resolves the ADR directory using a layered strategy:\n *\n * 1. `TEAMIX_EVO_ADR_ROOT` env var (absolute path)\n * 2. Walk up from cwd looking for `docs/adr/` (monorepo layout)\n * 3. Walk up from cwd looking for `.teamix-evo/adr/` (consumer layout — future)\n * 4. Throws with a clear error\n */\nexport function resolveAdrRoot(startDir: string = process.cwd()): string {\n const envPath = process.env.TEAMIX_EVO_ADR_ROOT;\n if (envPath && existsSync(envPath)) {\n return envPath;\n }\n\n let dir = resolve(startDir);\n for (let i = 0; i < 16; i++) {\n const candidates = [\n join(dir, 'docs', 'adr'),\n join(dir, '.teamix-evo', 'adr'),\n ];\n for (const c of candidates) {\n if (existsSync(c)) return c;\n }\n const parent = dirname(dir);\n if (parent === dir) break;\n dir = parent;\n }\n\n throw new Error(\n [\n 'Could not locate ADR directory.',\n `Tried env TEAMIX_EVO_ADR_ROOT + walking up from ${startDir} for docs/adr/ or .teamix-evo/adr/.`,\n 'Either run from a teamix-evo monorepo, or set TEAMIX_EVO_ADR_ROOT to an absolute path.',\n ].join(' '),\n );\n}\n\nconst SKIP_FILES = new Set(['README.md', '_template.md']);\nconst ID_RE = /^(\\d{4})-/;\nconst H1_RE = /^#\\s+\\d{4}\\.\\s+(.+?)\\s*$/m;\nconst STATUS_RE = /^-\\s+\\*\\*Status\\*\\*:\\s*(.+?)\\s*$/m;\nconst DATE_RE = /^-\\s+\\*\\*Date\\*\\*:\\s*(.+?)\\s*$/m;\nconst REGION_RE = /^-\\s+\\*\\*Region\\*\\*:\\s*(.+?)\\s*$/m;\n\nfunction parseAdr(slug: string, filePath: string): AdrEntry | null {\n const idMatch = slug.match(ID_RE);\n if (!idMatch) return null;\n const id = idMatch[1]!;\n\n const text = readFileSync(filePath, 'utf-8');\n const titleMatch = text.match(H1_RE);\n const statusMatch = text.match(STATUS_RE);\n const dateMatch = text.match(DATE_RE);\n const regionMatch = text.match(REGION_RE);\n\n return {\n id,\n slug,\n title: titleMatch?.[1] ?? slug,\n status: statusMatch?.[1] ?? '',\n date: dateMatch?.[1] ?? '',\n region: regionMatch?.[1] ?? '',\n filePath,\n };\n}\n\nexport function loadAdrIndex(rootDir?: string): LoadedAdrs {\n const root = rootDir ?? resolveAdrRoot();\n const files = readdirSync(root).filter(\n (f) => f.endsWith('.md') && !SKIP_FILES.has(f),\n );\n const entries: AdrEntry[] = [];\n for (const f of files) {\n const slug = f.replace(/\\.md$/, '');\n const entry = parseAdr(slug, join(root, f));\n if (entry) entries.push(entry);\n }\n entries.sort((a, b) => a.id.localeCompare(b.id));\n return { rootDir: root, entries };\n}\n\n/**\n * Look up one ADR by id (\"0011\") or full slug (\"0011-mcp-single-package-multi-group\").\n * Returns `null` if no match.\n */\nexport function findAdr(\n loaded: LoadedAdrs,\n idOrSlug: string,\n): AdrEntry | null {\n const needle = idOrSlug.trim();\n if (/^\\d{4}$/.test(needle)) {\n return loaded.entries.find((e) => e.id === needle) ?? null;\n }\n return (\n loaded.entries.find((e) => e.slug === needle) ??\n loaded.entries.find((e) => e.id === needle) ??\n null\n );\n}\n\nexport function loadAdrContent(entry: AdrEntry): string {\n return readFileSync(entry.filePath, 'utf-8');\n}\n","/**\n * Skills tool group — exposes `@teamix-evo/skills` SKILL.md content to AI editors.\n *\n * Per [ADR 0011 §5](../../../../docs/adr/0011-mcp-single-package-multi-group.md):\n *\n * - `skills_list` — index of all shipped skills (id, name, description, version)\n * - `skills_get` — full SKILL.md content + attachment names for one skill\n * - `skills_find` — substring search across `description` (the AI trigger) + body\n *\n * `description` in SKILL.md frontmatter is the AI trigger contract per\n * [ADR 0013](../../../../docs/adr/0013-skills-source-mirror.md). Searching it\n * is the primary use of `skills_find`.\n */\nimport { z } from 'zod';\nimport type { Tool } from '@modelcontextprotocol/sdk/types.js';\nimport {\n loadSkillsManifest,\n loadSkillContent,\n findSkill,\n type LoadedSkills,\n} from '../skills-loader.js';\nimport type { ToolGroup, ToolResult } from '../types.js';\nimport type { SkillEntry } from '@teamix-evo/registry';\n\nconst ListInput = z.object({});\n\nconst GetInput = z.object({\n id: z.string().min(1),\n});\n\nconst FindInput = z.object({\n query: z.string().min(1),\n limit: z.number().int().positive().max(50).optional(),\n /**\n * Scope: 'description' (default — fast, only matches the AI trigger contract)\n * or 'body' (slower — matches across SKILL.md prose, useful for \"where do we\n * mention X\" questions).\n */\n scope: z.enum(['description', 'body', 'all']).optional(),\n});\n\nconst TOOLS: Tool[] = [\n {\n name: 'skills_list',\n description:\n 'List all SKILL.md entries shipped by @teamix-evo/skills. Returns id, name, description (the AI trigger contract), version, source path, ides, updateStrategy. Use this to discover which skills exist before invoking one via the IDE\\'s skill mechanism.',\n inputSchema: { type: 'object', properties: {} },\n },\n {\n name: 'skills_get',\n description:\n 'Fetch the full SKILL.md content (frontmatter + body) for one skill by id or name. Also lists attachment files (sibling .md docs the skill references). Use after skills_list / skills_find to read the actual rules / decision tree / checklist that the skill encodes.',\n inputSchema: {\n type: 'object',\n properties: {\n id: {\n type: 'string',\n description: 'Skill id or name (matches manifest.skills[].id or .name).',\n },\n },\n required: ['id'],\n },\n },\n {\n name: 'skills_find',\n description:\n 'Substring search across skill descriptions and bodies. Default scope is `description` (matches the AI trigger contract — fast). Set `scope: \"body\"` to search SKILL.md prose, or `scope: \"all\"` for both. Use when you remember a phrase (\"token refresh\", \"design review\", \"drift scan\") but not the skill id.',\n inputSchema: {\n type: 'object',\n properties: {\n query: { type: 'string', description: 'Free-text query.' },\n limit: {\n type: 'integer',\n minimum: 1,\n maximum: 50,\n description: 'Max matches to return (default 10).',\n },\n scope: {\n type: 'string',\n enum: ['description', 'body', 'all'],\n description:\n 'Where to search: \"description\" (frontmatter, default), \"body\" (SKILL.md prose), or \"all\".',\n },\n },\n required: ['query'],\n },\n },\n];\n\nconst TOOL_NAMES = new Set(TOOLS.map((t) => t.name));\n\nfunction pickEntry(s: SkillEntry) {\n return {\n id: s.id,\n name: s.name,\n description: s.description,\n version: s.version,\n source: s.source,\n ides: s.ides ?? [],\n updateStrategy: s.updateStrategy ?? 'managed',\n template: s.template ?? false,\n };\n}\n\nexport interface SkillsGroupOptions {\n loaded?: LoadedSkills;\n}\n\nexport function createSkillsGroup(opts: SkillsGroupOptions = {}): ToolGroup {\n let cache: LoadedSkills | null = opts.loaded ?? null;\n function getManifest(): LoadedSkills {\n if (!cache) cache = loadSkillsManifest();\n return cache;\n }\n\n return {\n name: 'skills',\n tools: TOOLS,\n async handle(name, args): Promise<ToolResult | undefined> {\n if (!TOOL_NAMES.has(name)) return undefined;\n\n if (name === 'skills_list') {\n ListInput.parse(args ?? {});\n const { manifest } = getManifest();\n return {\n content: [\n {\n type: 'text',\n text: JSON.stringify(manifest.skills.map(pickEntry), null, 2),\n },\n ],\n };\n }\n\n if (name === 'skills_get') {\n const input = GetInput.parse(args);\n const loaded = getManifest();\n const entry = findSkill(loaded, input.id);\n if (!entry) {\n return {\n content: [\n {\n type: 'text',\n text: `Skill not found: ${input.id}. Use skills_list to discover ids.`,\n },\n ],\n isError: true,\n };\n }\n const content = loadSkillContent(entry, loaded.rootDir);\n if (!content) {\n return {\n content: [\n {\n type: 'text',\n text: `Skill source missing on disk for \"${entry.id}\" (expected at ${entry.source}). Check packages/skills installation.`,\n },\n ],\n isError: true,\n };\n }\n return {\n content: [\n {\n type: 'text',\n text: JSON.stringify(\n {\n entry: pickEntry(entry),\n attachments: content.attachments,\n content: content.text,\n },\n null,\n 2,\n ),\n },\n ],\n };\n }\n\n if (name === 'skills_find') {\n const input = FindInput.parse(args);\n const limit = input.limit ?? 10;\n const scope = input.scope ?? 'description';\n const needle = input.query.toLowerCase();\n const loaded = getManifest();\n\n const matches: Array<{\n entry: ReturnType<typeof pickEntry>;\n hitIn: 'description' | 'body' | 'both';\n }> = [];\n\n for (const entry of loaded.manifest.skills) {\n const descHit =\n scope !== 'body' &&\n entry.description.toLowerCase().includes(needle);\n let bodyHit = false;\n if (scope === 'body' || scope === 'all') {\n const content = loadSkillContent(entry, loaded.rootDir);\n if (content) {\n bodyHit = content.text.toLowerCase().includes(needle);\n }\n }\n if (!descHit && !bodyHit) continue;\n matches.push({\n entry: pickEntry(entry),\n hitIn:\n descHit && bodyHit\n ? 'both'\n : descHit\n ? 'description'\n : 'body',\n });\n }\n\n return {\n content: [\n {\n type: 'text',\n text: JSON.stringify(\n {\n query: input.query,\n scope,\n limit,\n count: Math.min(matches.length, limit),\n totalMatches: matches.length,\n results: matches.slice(0, limit),\n },\n null,\n 2,\n ),\n },\n ],\n };\n }\n\n return undefined;\n },\n };\n}\n","/**\n * Loader for `@teamix-evo/skills` (the skills source-of-truth package).\n *\n * Reads `packages/skills/manifest.json` + each `skills/<id>/SKILL.md`. The\n * frontmatter `description` is the AI trigger contract (see ADR 0013) and is\n * what `skills_find` searches over.\n *\n * In a consumer project, the same shape lives under `node_modules/@teamix-evo/skills/`.\n * Resolution order mirrors the registry/adr loaders:\n *\n * 1. `TEAMIX_EVO_SKILLS_ROOT` env var (absolute path to the package dir)\n * 2. Walk up from cwd looking for `packages/skills/` (monorepo)\n * 3. Walk up from cwd looking for `node_modules/@teamix-evo/skills/` (consumer)\n * 4. Throws with a clear error\n */\nimport { existsSync, readFileSync, readdirSync, statSync } from 'node:fs';\nimport { dirname, join, resolve } from 'node:path';\nimport {\n SkillsPackageManifestSchema,\n type SkillsPackageManifest,\n type SkillEntry,\n} from '@teamix-evo/registry';\n\nexport interface LoadedSkills {\n /** Absolute path to the package root containing manifest.json. */\n rootDir: string;\n manifest: SkillsPackageManifest;\n}\n\nexport function resolveSkillsRoot(startDir: string = process.cwd()): string {\n const envPath = process.env.TEAMIX_EVO_SKILLS_ROOT;\n if (envPath && existsSync(join(envPath, 'manifest.json'))) {\n return envPath;\n }\n\n let dir = resolve(startDir);\n for (let i = 0; i < 16; i++) {\n const candidates = [\n join(dir, 'packages', 'skills'),\n join(dir, 'node_modules', '@teamix-evo', 'skills'),\n ];\n for (const c of candidates) {\n if (existsSync(join(c, 'manifest.json'))) return c;\n }\n const parent = dirname(dir);\n if (parent === dir) break;\n dir = parent;\n }\n\n throw new Error(\n [\n 'Could not locate @teamix-evo/skills root.',\n `Tried env TEAMIX_EVO_SKILLS_ROOT + walking up from ${startDir}.`,\n 'Either install @teamix-evo/skills or run from a monorepo, or set TEAMIX_EVO_SKILLS_ROOT to an absolute path.',\n ].join(' '),\n );\n}\n\nexport function loadSkillsManifest(rootDir?: string): LoadedSkills {\n const root = rootDir ?? resolveSkillsRoot();\n const manifestPath = join(root, 'manifest.json');\n const raw = JSON.parse(readFileSync(manifestPath, 'utf-8')) as unknown;\n const parsed = SkillsPackageManifestSchema.safeParse(raw);\n if (!parsed.success) {\n throw new Error(\n `Invalid skills manifest at ${manifestPath}: ${parsed.error.message}`,\n );\n }\n return { rootDir: root, manifest: parsed.data };\n}\n\nexport interface SkillContent {\n entry: SkillEntry;\n /** Full SKILL.md text (frontmatter + body). */\n text: string;\n /** Just the body, frontmatter stripped. Null if SKILL.md missing. */\n body: string | null;\n /** Parsed frontmatter as flat string map. */\n frontmatter: Record<string, string>;\n /** Absolute path to SKILL.md. */\n filePath: string;\n /**\n * Other markdown files attached to the skill (siblings of SKILL.md), e.g.\n * generation-flow.md / boundaries.md / checklist.md. Just the relative names —\n * the model can fetch them by name via a follow-up tool call.\n */\n attachments: string[];\n}\n\nconst FM_RE = /^---\\s*\\n([\\s\\S]*?)\\n---\\s*\\n?/;\n\nfunction parseFrontmatter(text: string): {\n frontmatter: Record<string, string>;\n body: string;\n} {\n const m = text.match(FM_RE);\n if (!m) return { frontmatter: {}, body: text };\n const fm: Record<string, string> = {};\n for (const line of m[1]!.split('\\n')) {\n const kv = line.match(/^([A-Za-z_][\\w-]*)\\s*:\\s*(.+?)\\s*$/);\n if (kv) fm[kv[1]!] = kv[2]!.replace(/^['\"]|['\"]$/g, '');\n }\n return { frontmatter: fm, body: text.slice(m[0].length) };\n}\n\nexport function loadSkillContent(\n entry: SkillEntry,\n rootDir: string,\n): SkillContent | null {\n const sourcePath = join(rootDir, entry.source);\n if (!existsSync(sourcePath)) return null;\n\n // Skills are typically directories with SKILL.md inside.\n let skillMdPath: string;\n let attachments: string[] = [];\n const dirCandidate = join(sourcePath, 'SKILL.md');\n if (existsSync(dirCandidate)) {\n skillMdPath = dirCandidate;\n // Light attachment scan: top-level .md siblings of SKILL.md.\n try {\n attachments = readdirSync(sourcePath)\n .filter((f) => f.endsWith('.md') && f !== 'SKILL.md')\n .filter((f) => {\n try {\n return statSync(join(sourcePath, f)).isFile();\n } catch {\n return false;\n }\n });\n } catch {\n attachments = [];\n }\n } else {\n // Single-file skill (entry.source points directly at a .md).\n skillMdPath = sourcePath;\n }\n\n const text = readFileSync(skillMdPath, 'utf-8');\n const { frontmatter, body } = parseFrontmatter(text);\n return {\n entry,\n text,\n body,\n frontmatter,\n filePath: skillMdPath,\n attachments,\n };\n}\n\nexport function findSkill(\n loaded: LoadedSkills,\n idOrName: string,\n): SkillEntry | null {\n const needle = idOrName.trim();\n return (\n loaded.manifest.skills.find((s) => s.id === needle) ??\n loaded.manifest.skills.find((s) => s.name === needle) ??\n null\n );\n}\n","/**\n * Design tool group — exposes the consumer project's `.teamix-evo/design/**`\n * tree to AI editors via MCP.\n *\n * Per [ADR 0017](../../../../docs/adr/0017-mcp-design-group.md) the group\n * reads the **installed** design system in the consumer project (not the\n * upstream `@teamix-evo/design` source). Tools:\n *\n * - `design_list_principles` — parsed principles from `philosophy/principles.md`\n * - `design_get_tokens` — base/semantic JSON + theme/overrides CSS\n * - `design_list_patterns` — index of `patterns/*.md` (with variantSpecific flag)\n * - `design_get_pattern` — full markdown of one pattern\n * - `design_get_brand` — tone / voice / examples (variant-scoped, optional)\n *\n * When `.teamix-evo/design/` is absent (project hasn't run `design init`), the\n * group does not throw — each tool returns an empty result with a `note`\n * field telling the caller what's missing.\n */\nimport { z } from 'zod';\nimport type { Tool } from '@modelcontextprotocol/sdk/types.js';\nimport {\n loadDesign,\n readPrinciples,\n readTokens,\n readPatternIndex,\n readPatternContent,\n readBrand,\n type LoadedDesign,\n} from '../design-loader.js';\nimport type { ToolGroup, ToolResult } from '../types.js';\n\nconst EmptyInput = z.object({});\n\nconst GetPatternInput = z.object({\n id: z.string().min(1),\n});\n\nconst TOOLS: Tool[] = [\n {\n name: 'design_list_principles',\n description:\n \"List the design principles defined by the consumer project's installed design variant. Reads `.teamix-evo/design/philosophy/principles.md` and parses headings of the form `## P1 · Name`. Returns id, display name, and a one-line definition for each. Use this when the user asks about \\\"the four principles\\\", \\\"design philosophy\\\", or to ground a design review in the variant's stated values. Returns `{ principles: [], note: \\\"...\\\" }` if the project hasn't installed a design pack.\",\n inputSchema: { type: 'object', properties: {} },\n },\n {\n name: 'design_get_tokens',\n description:\n \"Fetch the consumer project's design tokens — parsed JSON from `.teamix-evo/tokens/base.tokens.json` and `semantic.tokens.json`, plus raw text of `tokens.theme.css` (variant theme) and `tokens.overrides.css` (user-owned overrides) when present. Use when AI needs to know what semantic colors / spacing / radii are available before writing component styles. JSON is for introspection; CSS is for copy-paste. Each tool result lists `sources` so you can cite paths.\",\n inputSchema: { type: 'object', properties: {} },\n },\n {\n name: 'design_list_patterns',\n description:\n \"Index every pattern in `.teamix-evo/design/patterns/*.md` (page types, journeys, flows, plus variant-specific markers like `cloud-*`, `opentrek-*`, `uni-manager-*`). Returns `{ id, title, sourcePath, variantSpecific }` for each. Use this before `design_get_pattern` to discover which patterns exist. When both a baseline (`page-types`) and a variant-specific (`cloud-page-types`) entry are available, prefer the variant-specific one for projects that match.\",\n inputSchema: { type: 'object', properties: {} },\n },\n {\n name: 'design_get_pattern',\n description:\n 'Fetch the full markdown body of one pattern by id (filename stem, e.g. `page-types` or `cloud-page-types`). Use after `design_list_patterns` discovered the id. Returns the raw markdown plus `sourcePath`. Returns isError if the id does not exist — call `design_list_patterns` first to discover available ids.',\n inputSchema: {\n type: 'object',\n properties: {\n id: {\n type: 'string',\n description:\n 'Pattern id — filename stem under `patterns/`, e.g. \"page-types\", \"cloud-page-types\".',\n },\n },\n required: ['id'],\n },\n },\n {\n name: 'design_get_brand',\n description:\n \"Fetch the consumer project's variant-specific brand voice — `brand/tone.md`, `brand/voice.md`, `brand/examples.md`. Each is optional; the response contains only the files that exist. Some variants (like `_template` or `default`) ship no brand content — that's not an error, the response simply lists no entries. Use this when generating or reviewing user-facing copy, error messages, empty states, or onboarding text where brand voice matters.\",\n inputSchema: { type: 'object', properties: {} },\n },\n];\n\nconst TOOL_NAMES = new Set(TOOLS.map((t) => t.name));\n\nexport interface DesignGroupOptions {\n /** Pre-loaded design snapshot (used by tests). When omitted, the loader walks cwd. */\n loaded?: LoadedDesign | null;\n /** Override the start directory for cwd-relative resolution (used by tests). */\n rootDir?: string;\n}\n\nconst NO_DESIGN_NOTE =\n '.teamix-evo/design/ not found in this project. Run `npx teamix-evo design init <variant>` to install a design pack.';\n\nexport function createDesignGroup(opts: DesignGroupOptions = {}): ToolGroup {\n let cache: LoadedDesign | null | undefined =\n opts.loaded === undefined ? undefined : opts.loaded;\n function getDesign(): LoadedDesign | null {\n if (cache === undefined) cache = loadDesign(opts.rootDir);\n return cache;\n }\n\n return {\n name: 'design',\n tools: TOOLS,\n async handle(name, args): Promise<ToolResult | undefined> {\n if (!TOOL_NAMES.has(name)) return undefined;\n\n const loaded = getDesign();\n\n if (name === 'design_list_principles') {\n EmptyInput.parse(args ?? {});\n if (!loaded) {\n return jsonResult({ principles: [], sourcePath: null, note: NO_DESIGN_NOTE });\n }\n return jsonResult(readPrinciples(loaded));\n }\n\n if (name === 'design_get_tokens') {\n EmptyInput.parse(args ?? {});\n if (!loaded) {\n return jsonResult({ sources: [], note: NO_DESIGN_NOTE });\n }\n return jsonResult(readTokens(loaded));\n }\n\n if (name === 'design_list_patterns') {\n EmptyInput.parse(args ?? {});\n if (!loaded) {\n return jsonResult({ patterns: [], note: NO_DESIGN_NOTE });\n }\n return jsonResult({\n variant: loaded.variant,\n patterns: readPatternIndex(loaded),\n });\n }\n\n if (name === 'design_get_pattern') {\n const input = GetPatternInput.parse(args);\n if (!loaded) {\n return {\n content: [{ type: 'text', text: NO_DESIGN_NOTE }],\n isError: true,\n };\n }\n const result = readPatternContent(loaded, input.id);\n if (!result) {\n return {\n content: [\n {\n type: 'text',\n text: `Pattern not found: ${input.id}. Use design_list_patterns to discover available ids.`,\n },\n ],\n isError: true,\n };\n }\n return jsonResult(result);\n }\n\n if (name === 'design_get_brand') {\n EmptyInput.parse(args ?? {});\n if (!loaded) {\n return jsonResult({ note: NO_DESIGN_NOTE });\n }\n return jsonResult(readBrand(loaded));\n }\n\n return undefined;\n },\n };\n}\n\nfunction jsonResult(payload: unknown): ToolResult {\n return {\n content: [{ type: 'text', text: JSON.stringify(payload, null, 2) }],\n };\n}\n","/**\n * Loader for the consumer project's `.teamix-evo/design/**` tree.\n *\n * Per [ADR 0017](../../../docs/adr/0017-mcp-design-group.md) the design MCP\n * group reads the **installed** design system, not the upstream package. The\n * loader walks `.teamix-evo/design/` from the project root (cwd by default)\n * and returns a typed snapshot the group's tools can serve.\n *\n * Resolution order:\n *\n * 1. `TEAMIX_EVO_DESIGN_ROOT` env var (absolute path to the .teamix-evo/design dir)\n * 2. Walk up from cwd looking for `.teamix-evo/design/`\n * 3. Returns `null` (not an error — projects without design init should get\n * empty tool results with a `note`, not a thrown exception)\n */\nimport { existsSync, readFileSync, readdirSync, statSync } from 'node:fs';\nimport { dirname, join, resolve } from 'node:path';\n\nexport interface LoadedDesign {\n /** Absolute path to `.teamix-evo/design/` in the consumer project. */\n rootDir: string;\n /** Variant name read from `pack.lock.json`, or null if missing. */\n variant: string | null;\n}\n\nexport function resolveDesignRoot(startDir: string = process.cwd()): string | null {\n const envPath = process.env.TEAMIX_EVO_DESIGN_ROOT;\n if (envPath && existsSync(envPath)) {\n return envPath;\n }\n\n let dir = resolve(startDir);\n for (let i = 0; i < 16; i++) {\n const candidate = join(dir, '.teamix-evo', 'design');\n if (existsSync(candidate)) return candidate;\n const parent = dirname(dir);\n if (parent === dir) break;\n dir = parent;\n }\n return null;\n}\n\nexport function loadDesign(rootDir?: string): LoadedDesign | null {\n const root = rootDir ?? resolveDesignRoot();\n if (!root) return null;\n\n let variant: string | null = null;\n const lockPath = join(root, 'pack.lock.json');\n if (existsSync(lockPath)) {\n try {\n const raw = JSON.parse(readFileSync(lockPath, 'utf-8')) as {\n variant?: string;\n };\n variant = typeof raw.variant === 'string' ? raw.variant : null;\n } catch {\n variant = null;\n }\n }\n return { rootDir: root, variant };\n}\n\nexport interface PrincipleEntry {\n id: string;\n name: string;\n oneLineDef: string;\n}\n\nconst PRINCIPLE_HEADING_RE = /^#{2,3}\\s+(P\\d+)\\s*[·:]\\s*(.+?)\\s*$/;\n\n/**\n * Parse `philosophy/principles.md` for headings of the form `## P1 · Name`.\n * Returns the principle id, display name, and the first non-blank line below\n * the heading as a one-line definition.\n */\nexport function readPrinciples(loaded: LoadedDesign): {\n principles: PrincipleEntry[];\n sourcePath: string | null;\n note?: string;\n} {\n const filePath = join(loaded.rootDir, 'philosophy', 'principles.md');\n if (!existsSync(filePath)) {\n return {\n principles: [],\n sourcePath: null,\n note:\n 'philosophy/principles.md not found in this project. Run `teamix-evo design init <variant>` to install it.',\n };\n }\n const text = readFileSync(filePath, 'utf-8');\n const lines = text.split(/\\r?\\n/);\n const out: PrincipleEntry[] = [];\n for (let i = 0; i < lines.length; i++) {\n const m = lines[i]!.match(PRINCIPLE_HEADING_RE);\n if (!m) continue;\n let def = '';\n for (let j = i + 1; j < lines.length && j < i + 8; j++) {\n const candidate = lines[j]!.trim();\n if (!candidate) continue;\n if (/^#{1,6}\\s/.test(candidate)) break;\n def = candidate.replace(/^[*_>\\s-]+/, '').trim();\n break;\n }\n out.push({ id: m[1]!, name: m[2]!.trim(), oneLineDef: def });\n }\n return { principles: out, sourcePath: filePath };\n}\n\nexport interface TokenSnapshot {\n /** Parsed contents of `base.tokens.json` if present. */\n base?: unknown;\n /** Parsed contents of `semantic.tokens.json` if present. */\n semantic?: unknown;\n /** Raw text of `tokens.theme.css` if present. */\n themeCss?: string;\n /** Raw text of `tokens.overrides.css` if present (user-owned overrides). */\n overridesCss?: string;\n /** Source paths discovered, in load order. */\n sources: string[];\n note?: string;\n}\n\n/**\n * Locate the tokens directory. Tokens live at `<projectRoot>/.teamix-evo/tokens/`\n * since v0.7 (lifted out of `design/foundations/tokens/`). Falls back to the\n * legacy in-design location for projects installed before the lift.\n */\nfunction resolveTokensDir(loaded: LoadedDesign): string | null {\n const projectRoot = dirname(loaded.rootDir); // .teamix-evo/\n const lifted = join(projectRoot, 'tokens');\n if (existsSync(lifted)) return lifted;\n const legacy = join(loaded.rootDir, 'foundations', 'tokens');\n if (existsSync(legacy)) return legacy;\n return null;\n}\n\nexport function readTokens(loaded: LoadedDesign): TokenSnapshot {\n const tokensDir = resolveTokensDir(loaded);\n const out: TokenSnapshot = { sources: [] };\n if (!tokensDir) {\n out.note =\n '.teamix-evo/tokens/ not found in this project (and no legacy foundations/tokens/).';\n return out;\n }\n const tryJson = (rel: string): unknown | undefined => {\n const fp = join(tokensDir, rel);\n if (!existsSync(fp)) return undefined;\n out.sources.push(fp);\n try {\n return JSON.parse(readFileSync(fp, 'utf-8'));\n } catch {\n return undefined;\n }\n };\n const tryText = (rel: string): string | undefined => {\n const fp = join(tokensDir, rel);\n if (!existsSync(fp)) return undefined;\n out.sources.push(fp);\n return readFileSync(fp, 'utf-8');\n };\n out.base = tryJson('base.tokens.json');\n out.semantic = tryJson('semantic.tokens.json');\n out.themeCss = tryText('tokens.theme.css');\n out.overridesCss = tryText('tokens.overrides.css');\n return out;\n}\n\nexport interface PatternIndexEntry {\n id: string; // file stem, e.g. \"page-types\" or \"cloud-page-types\"\n title: string; // first H1 in the file, fallback to id\n sourcePath: string;\n variantSpecific: boolean; // true for files prefixed with a known variant marker\n}\n\nconst VARIANT_PREFIX_RE = /^(cloud|opentrek|uni-manager|enterprise)-/i;\n\nexport function readPatternIndex(loaded: LoadedDesign): PatternIndexEntry[] {\n const patternsDir = join(loaded.rootDir, 'patterns');\n if (!existsSync(patternsDir)) return [];\n const out: PatternIndexEntry[] = [];\n for (const name of readdirSync(patternsDir)) {\n if (!name.endsWith('.md')) continue;\n const fp = join(patternsDir, name);\n try {\n if (!statSync(fp).isFile()) continue;\n } catch {\n continue;\n }\n const stem = name.replace(/\\.md$/, '');\n const text = readFileSync(fp, 'utf-8');\n const titleMatch = text.match(/^#\\s+(.+?)\\s*$/m);\n out.push({\n id: stem,\n title: titleMatch ? titleMatch[1]! : stem,\n sourcePath: fp,\n variantSpecific: VARIANT_PREFIX_RE.test(stem),\n });\n }\n return out.sort((a, b) => a.id.localeCompare(b.id));\n}\n\nexport function readPatternContent(\n loaded: LoadedDesign,\n id: string,\n): { id: string; sourcePath: string; content: string } | null {\n const stem = id.replace(/\\.md$/, '');\n const fp = join(loaded.rootDir, 'patterns', `${stem}.md`);\n if (!existsSync(fp)) return null;\n return {\n id: stem,\n sourcePath: fp,\n content: readFileSync(fp, 'utf-8'),\n };\n}\n\nexport interface BrandSnapshot {\n tone?: { sourcePath: string; content: string };\n voice?: { sourcePath: string; content: string };\n examples?: { sourcePath: string; content: string };\n note?: string;\n}\n\nexport function readBrand(loaded: LoadedDesign): BrandSnapshot {\n const brandDir = join(loaded.rootDir, 'brand');\n const out: BrandSnapshot = {};\n if (!existsSync(brandDir)) {\n out.note =\n 'brand/ not present — this design variant does not ship brand-specific tone / voice / examples.';\n return out;\n }\n for (const key of ['tone', 'voice', 'examples'] as const) {\n const fp = join(brandDir, `${key}.md`);\n if (existsSync(fp)) {\n out[key] = { sourcePath: fp, content: readFileSync(fp, 'utf-8') };\n }\n }\n return out;\n}\n"],"mappings":"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","names":["FM_RE","z","existsSync","readFileSync","dirname","join","resolve","z","TOOLS","TOOL_NAMES","from","z","existsSync","readFileSync","readdirSync","dirname","join","resolve","parseFrontmatter","ListInput","z","GetInput","FindInput","TOOLS","TOOL_NAMES","pickEntry","z","existsSync","readFileSync","readdirSync","statSync","dirname","join","resolve","z","TOOLS","TOOL_NAMES"]}
|
|
1
|
+
{"version":3,"sources":["../src/server.ts","../src/groups/registry.ts","../src/manifest-loader.ts","../src/groups/adr.ts","../src/adr-loader.ts","../src/groups/skills.ts","../src/skills-loader.ts","../src/groups/tokens.ts","../src/tokens-loader.ts"],"sourcesContent":["/**\n * Main MCP server — composes multiple tool groups into one stdio process.\n *\n * Architecture per [ADR 0011](../../../docs/adr/0011-mcp-single-package-multi-group.md):\n * single package / single bin / multiple tool groups. Groups added in later\n * milestones (tokens v0.6, adr v0.7, scenario v0.8) plug in here without\n * touching the transport or ListTools/CallTool handler logic.\n *\n * Tool dispatch:\n * - `tools/list` returns the union of all groups' tools.\n * - `tools/call` walks the group list in registration order; the first group\n * whose `handle` returns a non-`undefined` result wins. Tool-name uniqueness\n * across groups is the responsibility of group authors (see ADR 0011 §5\n * for the `<group>_<verb>_<noun>` naming convention; `registry` is the\n * historical exception).\n */\nimport { Server } from '@modelcontextprotocol/sdk/server/index.js';\nimport {\n CallToolRequestSchema,\n ListToolsRequestSchema,\n} from '@modelcontextprotocol/sdk/types.js';\nimport { createRegistryGroup, type RegistryGroupOptions } from './groups/registry.js';\nimport { createAdrGroup, type AdrGroupOptions } from './groups/adr.js';\nimport { createSkillsGroup, type SkillsGroupOptions } from './groups/skills.js';\nimport { createTokensGroup, type TokensGroupOptions } from './groups/tokens.js';\nimport type { ToolGroup } from './types.js';\n\nexport interface ServerOptions {\n /** Options forwarded to the registry group. Pass `loaded` in tests. */\n registry?: RegistryGroupOptions;\n /** Options forwarded to the adr group. Pass `loaded` in tests. */\n adr?: AdrGroupOptions;\n /** Options forwarded to the skills group. Pass `loaded` in tests. */\n skills?: SkillsGroupOptions;\n /** Options forwarded to the tokens group. Pass `loaded` in tests. */\n tokens?: TokensGroupOptions;\n}\n\nexport function createServer(opts: ServerOptions = {}): Server {\n const groups: ToolGroup[] = [\n createRegistryGroup(opts.registry),\n createAdrGroup(opts.adr),\n createSkillsGroup(opts.skills),\n createTokensGroup(opts.tokens),\n // Future: createScenarioGroup(opts.scenario), // ADR 0011, v0.8\n ];\n\n // Sanity check: tool names must be unique across groups.\n const seen = new Set<string>();\n for (const group of groups) {\n for (const tool of group.tools) {\n if (seen.has(tool.name)) {\n throw new Error(\n `Duplicate MCP tool name across groups: ${tool.name}. ` +\n `Each group must use unique tool names — see ADR 0011 §5.`,\n );\n }\n seen.add(tool.name);\n }\n }\n\n const allTools = groups.flatMap((g) => g.tools);\n\n const server = new Server(\n {\n name: '@teamix-evo/mcp',\n version: '0.2.0',\n },\n {\n capabilities: { tools: {} },\n },\n );\n\n server.setRequestHandler(ListToolsRequestSchema, async () => ({\n tools: allTools,\n }));\n\n server.setRequestHandler(CallToolRequestSchema, async (req) => {\n const { name, arguments: args } = req.params;\n for (const group of groups) {\n const result = await group.handle(name, args);\n if (result !== undefined) return result;\n }\n return {\n content: [\n {\n type: 'text',\n text: `Unknown tool: ${name}. Use tools/list to discover available tools.`,\n },\n ],\n isError: true,\n };\n });\n\n return server;\n}\n","/**\n * Registry tool group — exposes the @teamix-evo/ui component registry to AI\n * editors.\n *\n * Originally `src/server.ts` of `@teamix-evo/registry-mcp`. Moved here as part\n * of [ADR 0011](../../../../docs/adr/0011-mcp-single-package-multi-group.md)\n * single-package / multi-group restructure.\n *\n * Tool naming is the **historical exception**: `list_components` /\n * `get_component_meta` / `find_components` keep their unprefixed names because\n * they're already in production AI client memory (see ADR 0011 §5). All\n * future groups (`design_*`, `adr_*`, `scenario_*`) MUST use the\n * `<group>_<verb>_<noun>` prefix convention.\n */\nimport { z } from 'zod';\nimport type { Tool } from '@modelcontextprotocol/sdk/types.js';\nimport {\n loadManifest,\n loadMeta,\n type LoadedManifest,\n} from '../manifest-loader.js';\nimport type { ToolGroup, ToolResult } from '../types.js';\nimport type { UiEntry } from '@teamix-evo/registry';\n\nconst ListComponentsInput = z.object({\n status: z.enum(['stable', 'experimental', 'deprecated']).optional(),\n});\n\nconst GetComponentMetaInput = z.object({\n id: z.string().min(1),\n});\n\nconst FindComponentsInput = z.object({\n query: z.string().min(1),\n limit: z.number().int().positive().max(100).optional(),\n});\n\nconst TOOLS: Tool[] = [\n {\n name: 'list_components',\n description:\n 'List all UI components in the @teamix-evo/ui registry. Optionally filter by status (stable / experimental / deprecated). Returns id, name, description, status, registryDependencies — small enough for the model to scan whole.',\n inputSchema: {\n type: 'object',\n properties: {\n status: {\n type: 'string',\n enum: ['stable', 'experimental', 'deprecated'],\n description: 'Filter by maturity status.',\n },\n },\n },\n },\n {\n name: 'get_component_meta',\n description:\n 'Fetch the full registry entry + parsed meta.md for a single component by id. Returns props schema reference, registryDependencies, npm dependencies, AI generation rules, and the component description.',\n inputSchema: {\n type: 'object',\n properties: {\n id: {\n type: 'string',\n description: 'Component id (e.g. \"button\", \"data-table\").',\n },\n },\n required: ['id'],\n },\n },\n {\n name: 'find_components',\n description:\n 'Substring match over component id / name / description. Use when you need a component but don\\'t know its exact id (e.g. \"find a component supporting async search and pagination\"). Returns up to `limit` matches (default 10). Note: substring match is a v0.1 implementation; semantic search is planned for v0.7 (see ADR 0009).',\n inputSchema: {\n type: 'object',\n properties: {\n query: {\n type: 'string',\n description: 'Free-text query.',\n },\n limit: {\n type: 'integer',\n minimum: 1,\n maximum: 100,\n description: 'Max matches to return (default 10).',\n },\n },\n required: ['query'],\n },\n },\n];\n\nconst TOOL_NAMES = new Set(TOOLS.map((t) => t.name));\n\nfunction pickListEntry(entry: UiEntry) {\n return {\n id: entry.id,\n name: entry.name,\n type: entry.type,\n description: entry.description,\n status: entry.status,\n deprecatedReason: entry.deprecatedReason,\n replacedBy: entry.replacedBy,\n registryDependencies: entry.registryDependencies ?? [],\n };\n}\n\nexport interface RegistryGroupOptions {\n /** Pre-loaded manifest (used in tests to avoid filesystem). */\n loaded?: LoadedManifest;\n}\n\nexport function createRegistryGroup(opts: RegistryGroupOptions = {}): ToolGroup {\n // Lazy-load the manifest so failures yield a tool-call error rather than\n // blocking server startup (which would prevent the MCP client from even\n // discovering the tools and seeing a usable error message).\n let cache: LoadedManifest | null = opts.loaded ?? null;\n function getManifest(): LoadedManifest {\n if (!cache) cache = loadManifest();\n return cache;\n }\n\n return {\n name: 'registry',\n tools: TOOLS,\n async handle(name, args): Promise<ToolResult | undefined> {\n if (!TOOL_NAMES.has(name)) return undefined;\n\n if (name === 'list_components') {\n const input = ListComponentsInput.parse(args ?? {});\n const { manifest } = getManifest();\n const entries = manifest.entries\n .filter((e) => e.type === 'component')\n .filter((e) => (input.status ? e.status === input.status : true))\n .map(pickListEntry);\n return {\n content: [{ type: 'text', text: JSON.stringify(entries, null, 2) }],\n };\n }\n\n if (name === 'get_component_meta') {\n const input = GetComponentMetaInput.parse(args);\n const { manifest, rootDir } = getManifest();\n const entry = manifest.entries.find((e) => e.id === input.id);\n if (!entry) {\n return {\n content: [\n {\n type: 'text',\n text: `Component not found: ${input.id}. Use list_components to discover ids.`,\n },\n ],\n isError: true,\n };\n }\n const meta = loadMeta(entry, rootDir);\n const payload = {\n entry,\n meta: meta ?? null,\n };\n return {\n content: [{ type: 'text', text: JSON.stringify(payload, null, 2) }],\n };\n }\n\n if (name === 'find_components') {\n const input = FindComponentsInput.parse(args);\n const limit = input.limit ?? 10;\n const q = input.query.toLowerCase();\n const { manifest } = getManifest();\n const matches = manifest.entries\n .filter((e) => e.type === 'component')\n .filter((e) => {\n return (\n e.id.toLowerCase().includes(q) ||\n e.name.toLowerCase().includes(q) ||\n e.description.toLowerCase().includes(q)\n );\n })\n .slice(0, limit)\n .map(pickListEntry);\n return {\n content: [\n {\n type: 'text',\n text: JSON.stringify(\n {\n query: input.query,\n limit,\n count: matches.length,\n results: matches,\n },\n null,\n 2,\n ),\n },\n ],\n };\n }\n\n // Unreachable — TOOL_NAMES guard above ensures we only enter known names.\n return undefined;\n },\n };\n}\n","import { readFileSync, existsSync } from 'node:fs';\nimport { dirname, join, resolve } from 'node:path';\nimport { UiPackageManifestSchema } from '@teamix-evo/registry';\nimport type { UiEntry, UiPackageManifest } from '@teamix-evo/registry';\n\n/**\n * Resolves the `@teamix-evo/ui/manifest.json` path using a layered strategy:\n *\n * 1. `TEAMIX_EVO_UI_MANIFEST` env var (absolute path)\n * 2. `<cwd>/node_modules/@teamix-evo/ui/manifest.json`\n * 3. Walking up parent directories until a matching `node_modules/...` is found\n * 4. Throws with a clear error message\n */\nexport function resolveManifestPath(startDir: string = process.cwd()): string {\n const envPath = process.env.TEAMIX_EVO_UI_MANIFEST;\n if (envPath && existsSync(envPath)) {\n return envPath;\n }\n\n let dir = resolve(startDir);\n // Limit walk to prevent runaway in pathological filesystems.\n for (let i = 0; i < 16; i++) {\n const candidate = join(\n dir,\n 'node_modules',\n '@teamix-evo',\n 'ui',\n 'manifest.json',\n );\n if (existsSync(candidate)) {\n return candidate;\n }\n const parent = dirname(dir);\n if (parent === dir) break; // reached filesystem root\n dir = parent;\n }\n\n throw new Error(\n [\n 'Could not locate @teamix-evo/ui/manifest.json — the UI registry is not installed in this project.',\n '',\n 'Fix one of:',\n ` 1. Install the package: pnpm add @teamix-evo/ui (or npm/yarn equivalent)`,\n ` 2. Point env at an existing manifest: export TEAMIX_EVO_UI_MANIFEST=/abs/path/to/manifest.json`,\n '',\n `Searched: $TEAMIX_EVO_UI_MANIFEST, then walked up from ${startDir} looking for node_modules/@teamix-evo/ui/manifest.json (16 levels).`,\n 'Note: MCP currently has no online fallback — it does not fetch from the npm registry / unpkg.',\n ].join('\\n'),\n );\n}\n\nexport interface LoadedManifest {\n manifest: UiPackageManifest;\n /** Directory of the manifest.json itself; used to resolve `meta.md` paths. */\n rootDir: string;\n}\n\n/**\n * Loads and Zod-validates the UI package manifest.\n * Throws on invalid manifest with the underlying Zod error attached.\n */\nexport function loadManifest(path?: string): LoadedManifest {\n const manifestPath = path ?? resolveManifestPath();\n const raw = JSON.parse(readFileSync(manifestPath, 'utf-8')) as unknown;\n const result = UiPackageManifestSchema.safeParse(raw);\n if (!result.success) {\n throw new Error(\n `Invalid manifest at ${manifestPath}: ${result.error.message}`,\n );\n }\n return {\n manifest: result.data,\n rootDir: dirname(manifestPath),\n };\n}\n\n/**\n * Frontmatter + body extracted from a `<id>.meta.md` file.\n * Frontmatter is parsed as a flat key/value map (no YAML library dep —\n * meta.md frontmatters are intentionally simple).\n */\nexport interface ParsedMeta {\n frontmatter: Record<string, string>;\n body: string;\n}\n\n/**\n * Reads and minimally parses a `<id>.meta.md` file. Returns `null` if the\n * meta file is missing or the entry didn't declare one.\n *\n * Frontmatter parser is minimal (single-line `key: value` pairs only). It\n * does NOT support nested or array YAML — sufficient for the meta.md format\n * documented in packages/ui/AGENTS.md §三.E.\n */\nexport function loadMeta(\n entry: UiEntry,\n rootDir: string,\n): ParsedMeta | null {\n if (!entry.meta) return null;\n const path = join(rootDir, entry.meta);\n if (!existsSync(path)) return null;\n const text = readFileSync(path, 'utf-8');\n return parseFrontmatter(text);\n}\n\nfunction parseFrontmatter(text: string): ParsedMeta {\n const FM_RE = /^---\\s*\\n([\\s\\S]*?)\\n---\\s*\\n?/;\n const match = text.match(FM_RE);\n if (!match) {\n return { frontmatter: {}, body: text };\n }\n const fm: Record<string, string> = {};\n // Capture group [1] is guaranteed when match succeeds.\n for (const line of match[1]!.split('\\n')) {\n const m = line.match(/^([A-Za-z_][\\w-]*)\\s*:\\s*(.+?)\\s*$/);\n if (m) fm[m[1]!] = m[2]!.replace(/^['\"]|['\"]$/g, '');\n }\n return {\n frontmatter: fm,\n body: text.slice(match[0].length),\n };\n}\n","/**\n * ADR tool group — exposes Architecture Decision Records to AI editors.\n *\n * Per [ADR 0011 §5](../../../../docs/adr/0011-mcp-single-package-multi-group.md),\n * new groups use the `<group>_<verb>` prefix convention:\n *\n * - `adr_list` — index of all ADRs (id, title, status, date)\n * - `adr_get` — full markdown body for one ADR\n * - `adr_find` — substring search across title + body\n *\n * Use this group to let AI agents:\n *\n * - Cite ADRs in PR reviews (\"this change violates ADR 0008 §2.B\")\n * - Resolve \"why was this done?\" questions before recommending refactors\n * - Discover related ADRs when proposing a new decision\n */\nimport { z } from 'zod';\nimport type { Tool } from '@modelcontextprotocol/sdk/types.js';\nimport {\n loadAdrIndex,\n loadAdrContent,\n findAdr,\n type LoadedAdrs,\n} from '../adr-loader.js';\nimport type { ToolGroup, ToolResult } from '../types.js';\n\nconst ListInput = z.object({\n /** Match `Status` line by substring (case-insensitive). */\n status: z.string().min(1).optional(),\n});\n\nconst GetInput = z.object({\n /** ADR id (\"0011\") or full slug (\"0011-mcp-single-package-multi-group\"). */\n id: z.string().min(1),\n});\n\nconst FindInput = z.object({\n query: z.string().min(1),\n limit: z.number().int().positive().max(50).optional(),\n /**\n * When true, returns a snippet (~200 chars) around each match so the model\n * can decide whether to fetch the full ADR. Defaults to true.\n */\n withSnippets: z.boolean().optional(),\n});\n\nconst TOOLS: Tool[] = [\n {\n name: 'adr_list',\n description:\n 'List all Architecture Decision Records (ADRs) in docs/adr/. Returns id (4-digit), slug, title, status, date, region for each. Use this as the first call to discover which decisions exist before drilling into one with adr_get. Filter by status substring (e.g. \"Accepted\" / \"Proposed\" / \"Superseded\") to narrow down.',\n inputSchema: {\n type: 'object',\n properties: {\n status: {\n type: 'string',\n description:\n 'Optional case-insensitive substring filter against the ADR Status line. Examples: \"Accepted\", \"Proposed\", \"Superseded\".',\n },\n },\n },\n },\n {\n name: 'adr_get',\n description:\n 'Fetch the full markdown body of one ADR by id (\"0011\") or slug (\"0011-mcp-single-package-multi-group\"). Returns the entry metadata + raw markdown so the model can cite specific sections (Context / Decision / Consequences / Source). Use after adr_list / adr_find to read a specific decision in full.',\n inputSchema: {\n type: 'object',\n properties: {\n id: {\n type: 'string',\n description:\n 'ADR id (\"0011\") or full slug (\"0011-mcp-single-package-multi-group\").',\n },\n },\n required: ['id'],\n },\n },\n {\n name: 'adr_find',\n description:\n 'Substring search across ADR titles and bodies (case-insensitive). Use when you remember a phrase (\"source-mirror\", \"lint-core\", \"no baseline\") but not which ADR it lives in. Returns up to `limit` matches (default 10) with optional snippets (~200 chars around each match). Combine with adr_get for the full text.',\n inputSchema: {\n type: 'object',\n properties: {\n query: { type: 'string', description: 'Free-text query.' },\n limit: {\n type: 'integer',\n minimum: 1,\n maximum: 50,\n description: 'Max matches to return (default 10).',\n },\n withSnippets: {\n type: 'boolean',\n description: 'Include ~200-char snippet around each match (default true).',\n },\n },\n required: ['query'],\n },\n },\n];\n\nconst TOOL_NAMES = new Set(TOOLS.map((t) => t.name));\n\nfunction pickEntry(e: {\n id: string;\n slug: string;\n title: string;\n status: string;\n date: string;\n region: string;\n}) {\n return {\n id: e.id,\n slug: e.slug,\n title: e.title,\n status: e.status,\n date: e.date,\n region: e.region,\n };\n}\n\nconst SNIPPET_RADIUS = 100;\n\nfunction snippet(text: string, index: number): string {\n const start = Math.max(0, index - SNIPPET_RADIUS);\n const end = Math.min(text.length, index + SNIPPET_RADIUS);\n const prefix = start > 0 ? '…' : '';\n const suffix = end < text.length ? '…' : '';\n return prefix + text.slice(start, end).replace(/\\s+/g, ' ').trim() + suffix;\n}\n\nexport interface AdrGroupOptions {\n /** Pre-loaded index (used in tests to avoid filesystem). */\n loaded?: LoadedAdrs;\n}\n\nexport function createAdrGroup(opts: AdrGroupOptions = {}): ToolGroup {\n let cache: LoadedAdrs | null = opts.loaded ?? null;\n function getIndex(): LoadedAdrs {\n if (!cache) cache = loadAdrIndex();\n return cache;\n }\n\n return {\n name: 'adr',\n tools: TOOLS,\n async handle(name, args): Promise<ToolResult | undefined> {\n if (!TOOL_NAMES.has(name)) return undefined;\n\n if (name === 'adr_list') {\n const input = ListInput.parse(args ?? {});\n const idx = getIndex();\n const needle = input.status?.toLowerCase();\n const entries = idx.entries\n .filter((e) =>\n needle ? e.status.toLowerCase().includes(needle) : true,\n )\n .map(pickEntry);\n return {\n content: [{ type: 'text', text: JSON.stringify(entries, null, 2) }],\n };\n }\n\n if (name === 'adr_get') {\n const input = GetInput.parse(args);\n const idx = getIndex();\n const entry = findAdr(idx, input.id);\n if (!entry) {\n return {\n content: [\n {\n type: 'text',\n text: `ADR not found: ${input.id}. Use adr_list to discover ids.`,\n },\n ],\n isError: true,\n };\n }\n const text = loadAdrContent(entry);\n return {\n content: [\n {\n type: 'text',\n text: JSON.stringify(\n { entry: pickEntry(entry), content: text },\n null,\n 2,\n ),\n },\n ],\n };\n }\n\n if (name === 'adr_find') {\n const input = FindInput.parse(args);\n const limit = input.limit ?? 10;\n const withSnippets = input.withSnippets ?? true;\n const needle = input.query.toLowerCase();\n const idx = getIndex();\n\n const matches: Array<{\n entry: ReturnType<typeof pickEntry>;\n snippets?: string[];\n hitCount: number;\n }> = [];\n for (const entry of idx.entries) {\n const body = loadAdrContent(entry).toLowerCase();\n const titleHit = entry.title.toLowerCase().includes(needle);\n if (!titleHit && !body.includes(needle)) continue;\n\n const snippets: string[] = [];\n if (withSnippets) {\n const rawBody = loadAdrContent(entry);\n let from = 0;\n // Up to 3 snippets per ADR to keep response compact.\n for (let i = 0; i < 3; i++) {\n const at = rawBody.toLowerCase().indexOf(needle, from);\n if (at < 0) break;\n snippets.push(snippet(rawBody, at));\n from = at + needle.length;\n }\n }\n // Count total hits in body for ranking.\n let hits = titleHit ? 1 : 0;\n let from = 0;\n for (;;) {\n const at = body.indexOf(needle, from);\n if (at < 0) break;\n hits++;\n from = at + needle.length;\n }\n matches.push({\n entry: pickEntry(entry),\n ...(withSnippets ? { snippets } : {}),\n hitCount: hits,\n });\n }\n matches.sort((a, b) => b.hitCount - a.hitCount);\n const sliced = matches.slice(0, limit);\n return {\n content: [\n {\n type: 'text',\n text: JSON.stringify(\n {\n query: input.query,\n limit,\n count: sliced.length,\n totalMatchingAdrs: matches.length,\n results: sliced,\n },\n null,\n 2,\n ),\n },\n ],\n };\n }\n\n return undefined;\n },\n };\n}\n","/**\n * Loader for ADR (Architecture Decision Record) markdown files.\n *\n * ADRs live in `docs/adr/<NNNN>-<slug>.md` per [ADR 0007](../../../docs/adr/0007-governance-docs-at-root.md).\n * Each file has the shape:\n *\n * ```md\n * # 0011. <title>\n *\n * - **Status**: Proposed | Accepted | Superseded by NNNN | Deprecated\n * - **Date**: YYYY-MM-DD\n * - **Region**: 0100–0999 协议与工具\n * - **Related ADR**: [0007 ...](...)\n *\n * ## Context\n * ...\n * ```\n *\n * This loader parses just enough metadata to power the `adr_list` /\n * `adr_get` / `adr_find` MCP tools (see [`groups/adr.ts`](./groups/adr.ts)).\n * `README.md` and `_template.md` are skipped — they are not ADRs.\n */\nimport { existsSync, readFileSync, readdirSync } from 'node:fs';\nimport { dirname, join, resolve } from 'node:path';\nimport { fileURLToPath } from 'node:url';\n\nexport interface AdrEntry {\n /** Numeric id, e.g. \"0011\". Derived from the filename prefix. */\n id: string;\n /** Filename without `.md`, e.g. \"0011-mcp-single-package-multi-group\". */\n slug: string;\n /** Title after \"NNNN. \" in the H1 line. */\n title: string;\n /** Raw status string from the `- **Status**:` line. Empty if missing. */\n status: string;\n /** Date from the `- **Date**:` line (YYYY-MM-DD). Empty if missing. */\n date: string;\n /** Optional region label (`0100–0999 协议与工具`). Empty if missing. */\n region: string;\n /** Absolute path to the source file (for `adr_get`). */\n filePath: string;\n}\n\nexport interface LoadedAdrs {\n /** Directory containing the ADR `.md` files. */\n rootDir: string;\n entries: AdrEntry[];\n}\n\n/**\n * Resolves the ADR directory using a layered strategy:\n *\n * 1. `TEAMIX_EVO_ADR_ROOT` env var (absolute path)\n * 2. Bundled snapshot at `<mcp-pkg>/dist/data/adr/` (works in consumer projects\n * after `pnpm add @teamix-evo/mcp` — see tsup.config.ts onSuccess copy)\n * 3. Walk up from cwd looking for `docs/adr/` (monorepo layout)\n * 4. Walk up from cwd looking for `.teamix-evo/adr/` (consumer override)\n * 5. Throws with a clear error\n */\nexport function resolveAdrRoot(startDir: string = process.cwd()): string {\n const envPath = process.env.TEAMIX_EVO_ADR_ROOT;\n if (envPath && existsSync(envPath)) {\n return envPath;\n }\n\n // Bundled snapshot inside the mcp package itself. import.meta.url at\n // runtime resolves to dist/cli.js or dist/index.js inside the published\n // package; its sibling `data/adr/` is populated by tsup onSuccess.\n try {\n const here = dirname(fileURLToPath(import.meta.url));\n const bundled = join(here, 'data', 'adr');\n if (existsSync(bundled)) return bundled;\n } catch {\n // import.meta.url may be unavailable in some test environments.\n }\n\n let dir = resolve(startDir);\n for (let i = 0; i < 16; i++) {\n const candidates = [\n join(dir, 'docs', 'adr'),\n join(dir, '.teamix-evo', 'adr'),\n ];\n for (const c of candidates) {\n if (existsSync(c)) return c;\n }\n const parent = dirname(dir);\n if (parent === dir) break;\n dir = parent;\n }\n\n throw new Error(\n [\n 'Could not locate ADR directory.',\n `Tried env TEAMIX_EVO_ADR_ROOT, mcp-bundled snapshot, and walked up from ${startDir} for docs/adr/ or .teamix-evo/adr/.`,\n 'Either install @teamix-evo/mcp (carries ADR snapshot) or set TEAMIX_EVO_ADR_ROOT to an absolute path.',\n ].join(' '),\n );\n}\n\nconst SKIP_FILES = new Set(['README.md', '_template.md']);\nconst ID_RE = /^(\\d{4})-/;\nconst H1_RE = /^#\\s+\\d{4}\\.\\s+(.+?)\\s*$/m;\nconst STATUS_RE = /^-\\s+\\*\\*Status\\*\\*:\\s*(.+?)\\s*$/m;\nconst DATE_RE = /^-\\s+\\*\\*Date\\*\\*:\\s*(.+?)\\s*$/m;\nconst REGION_RE = /^-\\s+\\*\\*Region\\*\\*:\\s*(.+?)\\s*$/m;\n\nfunction parseAdr(slug: string, filePath: string): AdrEntry | null {\n const idMatch = slug.match(ID_RE);\n if (!idMatch) return null;\n const id = idMatch[1]!;\n\n const text = readFileSync(filePath, 'utf-8');\n const titleMatch = text.match(H1_RE);\n const statusMatch = text.match(STATUS_RE);\n const dateMatch = text.match(DATE_RE);\n const regionMatch = text.match(REGION_RE);\n\n return {\n id,\n slug,\n title: titleMatch?.[1] ?? slug,\n status: statusMatch?.[1] ?? '',\n date: dateMatch?.[1] ?? '',\n region: regionMatch?.[1] ?? '',\n filePath,\n };\n}\n\nexport function loadAdrIndex(rootDir?: string): LoadedAdrs {\n const root = rootDir ?? resolveAdrRoot();\n const files = readdirSync(root).filter(\n (f) => f.endsWith('.md') && !SKIP_FILES.has(f),\n );\n const entries: AdrEntry[] = [];\n for (const f of files) {\n const slug = f.replace(/\\.md$/, '');\n const entry = parseAdr(slug, join(root, f));\n if (entry) entries.push(entry);\n }\n entries.sort((a, b) => a.id.localeCompare(b.id));\n return { rootDir: root, entries };\n}\n\n/**\n * Look up one ADR by id (\"0011\") or full slug (\"0011-mcp-single-package-multi-group\").\n * Returns `null` if no match.\n */\nexport function findAdr(\n loaded: LoadedAdrs,\n idOrSlug: string,\n): AdrEntry | null {\n const needle = idOrSlug.trim();\n if (/^\\d{4}$/.test(needle)) {\n return loaded.entries.find((e) => e.id === needle) ?? null;\n }\n return (\n loaded.entries.find((e) => e.slug === needle) ??\n loaded.entries.find((e) => e.id === needle) ??\n null\n );\n}\n\nexport function loadAdrContent(entry: AdrEntry): string {\n return readFileSync(entry.filePath, 'utf-8');\n}\n","/**\n * Skills tool group — exposes `@teamix-evo/skills` SKILL.md content to AI editors.\n *\n * Per [ADR 0011 §5](../../../../docs/adr/0011-mcp-single-package-multi-group.md):\n *\n * - `skills_list` — index of all shipped skills (id, name, description, version)\n * - `skills_get` — full SKILL.md content + attachment names for one skill\n * - `skills_find` — substring search across `description` (the AI trigger) + body\n *\n * `description` in SKILL.md frontmatter is the AI trigger contract per\n * [ADR 0013](../../../../docs/adr/0013-skills-source-mirror.md). Searching it\n * is the primary use of `skills_find`.\n */\nimport { z } from 'zod';\nimport type { Tool } from '@modelcontextprotocol/sdk/types.js';\nimport {\n loadSkillsManifest,\n loadSkillContent,\n findSkill,\n type LoadedSkills,\n} from '../skills-loader.js';\nimport type { ToolGroup, ToolResult } from '../types.js';\nimport type { SkillEntry } from '@teamix-evo/registry';\n\nconst ListInput = z.object({});\n\nconst GetInput = z.object({\n id: z.string().min(1),\n});\n\nconst FindInput = z.object({\n query: z.string().min(1),\n limit: z.number().int().positive().max(50).optional(),\n /**\n * Scope: 'description' (default — fast, only matches the AI trigger contract)\n * or 'body' (slower — matches across SKILL.md prose, useful for \"where do we\n * mention X\" questions).\n */\n scope: z.enum(['description', 'body', 'all']).optional(),\n});\n\nconst TOOLS: Tool[] = [\n {\n name: 'skills_list',\n description:\n 'List all SKILL.md entries shipped by @teamix-evo/skills. Returns id, name, description (the AI trigger contract), version, source path, ides, updateStrategy. Use this to discover which skills exist before invoking one via the IDE\\'s skill mechanism.',\n inputSchema: { type: 'object', properties: {} },\n },\n {\n name: 'skills_get',\n description:\n 'Fetch the full SKILL.md content (frontmatter + body) for one skill by id or name. Also lists attachment files (sibling .md docs the skill references). Use after skills_list / skills_find to read the actual rules / decision tree / checklist that the skill encodes.',\n inputSchema: {\n type: 'object',\n properties: {\n id: {\n type: 'string',\n description: 'Skill id or name (matches manifest.skills[].id or .name).',\n },\n },\n required: ['id'],\n },\n },\n {\n name: 'skills_find',\n description:\n 'Substring search across skill descriptions and bodies. Default scope is `description` (matches the AI trigger contract — fast). Set `scope: \"body\"` to search SKILL.md prose, or `scope: \"all\"` for both. Use when you remember a phrase (\"token refresh\", \"design review\", \"drift scan\") but not the skill id.',\n inputSchema: {\n type: 'object',\n properties: {\n query: { type: 'string', description: 'Free-text query.' },\n limit: {\n type: 'integer',\n minimum: 1,\n maximum: 50,\n description: 'Max matches to return (default 10).',\n },\n scope: {\n type: 'string',\n enum: ['description', 'body', 'all'],\n description:\n 'Where to search: \"description\" (frontmatter, default), \"body\" (SKILL.md prose), or \"all\".',\n },\n },\n required: ['query'],\n },\n },\n];\n\nconst TOOL_NAMES = new Set(TOOLS.map((t) => t.name));\n\nfunction pickEntry(s: SkillEntry) {\n return {\n id: s.id,\n name: s.name,\n description: s.description,\n version: s.version,\n source: s.source,\n ides: s.ides ?? [],\n updateStrategy: s.updateStrategy ?? 'managed',\n template: s.template ?? false,\n };\n}\n\nexport interface SkillsGroupOptions {\n loaded?: LoadedSkills;\n}\n\nexport function createSkillsGroup(opts: SkillsGroupOptions = {}): ToolGroup {\n let cache: LoadedSkills | null = opts.loaded ?? null;\n function getManifest(): LoadedSkills {\n if (!cache) cache = loadSkillsManifest();\n return cache;\n }\n\n return {\n name: 'skills',\n tools: TOOLS,\n async handle(name, args): Promise<ToolResult | undefined> {\n if (!TOOL_NAMES.has(name)) return undefined;\n\n if (name === 'skills_list') {\n ListInput.parse(args ?? {});\n const { manifest } = getManifest();\n return {\n content: [\n {\n type: 'text',\n text: JSON.stringify(manifest.skills.map(pickEntry), null, 2),\n },\n ],\n };\n }\n\n if (name === 'skills_get') {\n const input = GetInput.parse(args);\n const loaded = getManifest();\n const entry = findSkill(loaded, input.id);\n if (!entry) {\n return {\n content: [\n {\n type: 'text',\n text: `Skill not found: ${input.id}. Use skills_list to discover ids.`,\n },\n ],\n isError: true,\n };\n }\n const content = loadSkillContent(entry, loaded.rootDir);\n if (!content) {\n return {\n content: [\n {\n type: 'text',\n text: `Skill source missing on disk for \"${entry.id}\" (expected at ${entry.source}). Check packages/skills installation.`,\n },\n ],\n isError: true,\n };\n }\n return {\n content: [\n {\n type: 'text',\n text: JSON.stringify(\n {\n entry: pickEntry(entry),\n attachments: content.attachments,\n content: content.text,\n },\n null,\n 2,\n ),\n },\n ],\n };\n }\n\n if (name === 'skills_find') {\n const input = FindInput.parse(args);\n const limit = input.limit ?? 10;\n const scope = input.scope ?? 'description';\n const needle = input.query.toLowerCase();\n const loaded = getManifest();\n\n const matches: Array<{\n entry: ReturnType<typeof pickEntry>;\n hitIn: 'description' | 'body' | 'both';\n }> = [];\n\n for (const entry of loaded.manifest.skills) {\n const descHit =\n scope !== 'body' &&\n entry.description.toLowerCase().includes(needle);\n let bodyHit = false;\n if (scope === 'body' || scope === 'all') {\n const content = loadSkillContent(entry, loaded.rootDir);\n if (content) {\n bodyHit = content.text.toLowerCase().includes(needle);\n }\n }\n if (!descHit && !bodyHit) continue;\n matches.push({\n entry: pickEntry(entry),\n hitIn:\n descHit && bodyHit\n ? 'both'\n : descHit\n ? 'description'\n : 'body',\n });\n }\n\n return {\n content: [\n {\n type: 'text',\n text: JSON.stringify(\n {\n query: input.query,\n scope,\n limit,\n count: Math.min(matches.length, limit),\n totalMatches: matches.length,\n results: matches.slice(0, limit),\n },\n null,\n 2,\n ),\n },\n ],\n };\n }\n\n return undefined;\n },\n };\n}\n","/**\n * Loader for `@teamix-evo/skills` (the skills source-of-truth package).\n *\n * Reads `packages/skills/manifest.json` + each `skills/<id>/SKILL.md`. The\n * frontmatter `description` is the AI trigger contract (see ADR 0013) and is\n * what `skills_find` searches over.\n *\n * In a consumer project, the same shape lives under `node_modules/@teamix-evo/skills/`.\n * Resolution order mirrors the registry/adr loaders:\n *\n * 1. `TEAMIX_EVO_SKILLS_ROOT` env var (absolute path to the package dir)\n * 2. Walk up from cwd looking for `packages/skills/` (monorepo)\n * 3. Walk up from cwd looking for `node_modules/@teamix-evo/skills/` (consumer)\n * 4. Throws with a clear error\n */\nimport { existsSync, readFileSync, readdirSync, statSync } from 'node:fs';\nimport { dirname, join, resolve } from 'node:path';\nimport {\n SkillsPackageManifestSchema,\n type SkillsPackageManifest,\n type SkillEntry,\n} from '@teamix-evo/registry';\n\nexport interface LoadedSkills {\n /** Absolute path to the package root containing manifest.json. */\n rootDir: string;\n manifest: SkillsPackageManifest;\n}\n\nexport function resolveSkillsRoot(startDir: string = process.cwd()): string {\n const envPath = process.env.TEAMIX_EVO_SKILLS_ROOT;\n if (envPath && existsSync(join(envPath, 'manifest.json'))) {\n return envPath;\n }\n\n let dir = resolve(startDir);\n for (let i = 0; i < 16; i++) {\n const candidates = [\n join(dir, 'packages', 'skills'),\n join(dir, 'node_modules', '@teamix-evo', 'skills'),\n ];\n for (const c of candidates) {\n if (existsSync(join(c, 'manifest.json'))) return c;\n }\n const parent = dirname(dir);\n if (parent === dir) break;\n dir = parent;\n }\n\n throw new Error(\n [\n 'Could not locate @teamix-evo/skills root.',\n `Tried env TEAMIX_EVO_SKILLS_ROOT and walked up from ${startDir} for packages/skills/ or node_modules/@teamix-evo/skills/.`,\n 'Install @teamix-evo/skills as a devDependency in your project (the scaffold adds it automatically).',\n ].join(' '),\n );\n}\n\nexport function loadSkillsManifest(rootDir?: string): LoadedSkills {\n const root = rootDir ?? resolveSkillsRoot();\n const manifestPath = join(root, 'manifest.json');\n const raw = JSON.parse(readFileSync(manifestPath, 'utf-8')) as unknown;\n const parsed = SkillsPackageManifestSchema.safeParse(raw);\n if (!parsed.success) {\n throw new Error(\n `Invalid skills manifest at ${manifestPath}: ${parsed.error.message}`,\n );\n }\n return { rootDir: root, manifest: parsed.data };\n}\n\nexport interface SkillContent {\n entry: SkillEntry;\n /** Full SKILL.md text (frontmatter + body). */\n text: string;\n /** Just the body, frontmatter stripped. Null if SKILL.md missing. */\n body: string | null;\n /** Parsed frontmatter as flat string map. */\n frontmatter: Record<string, string>;\n /** Absolute path to SKILL.md. */\n filePath: string;\n /**\n * Other markdown files attached to the skill (siblings of SKILL.md), e.g.\n * generation-flow.md / boundaries.md / checklist.md. Just the relative names —\n * the model can fetch them by name via a follow-up tool call.\n */\n attachments: string[];\n}\n\nconst FM_RE = /^---\\s*\\n([\\s\\S]*?)\\n---\\s*\\n?/;\n\nfunction parseFrontmatter(text: string): {\n frontmatter: Record<string, string>;\n body: string;\n} {\n const m = text.match(FM_RE);\n if (!m) return { frontmatter: {}, body: text };\n const fm: Record<string, string> = {};\n for (const line of m[1]!.split('\\n')) {\n const kv = line.match(/^([A-Za-z_][\\w-]*)\\s*:\\s*(.+?)\\s*$/);\n if (kv) fm[kv[1]!] = kv[2]!.replace(/^['\"]|['\"]$/g, '');\n }\n return { frontmatter: fm, body: text.slice(m[0].length) };\n}\n\nexport function loadSkillContent(\n entry: SkillEntry,\n rootDir: string,\n): SkillContent | null {\n const sourcePath = join(rootDir, entry.source);\n if (!existsSync(sourcePath)) return null;\n\n // Skills are typically directories with SKILL.md inside.\n let skillMdPath: string;\n let attachments: string[] = [];\n const dirCandidate = join(sourcePath, 'SKILL.md');\n if (existsSync(dirCandidate)) {\n skillMdPath = dirCandidate;\n // Light attachment scan: top-level .md siblings of SKILL.md.\n try {\n attachments = readdirSync(sourcePath)\n .filter((f) => f.endsWith('.md') && f !== 'SKILL.md')\n .filter((f) => {\n try {\n return statSync(join(sourcePath, f)).isFile();\n } catch {\n return false;\n }\n });\n } catch {\n attachments = [];\n }\n } else {\n // Single-file skill (entry.source points directly at a .md).\n skillMdPath = sourcePath;\n }\n\n const text = readFileSync(skillMdPath, 'utf-8');\n const { frontmatter, body } = parseFrontmatter(text);\n return {\n entry,\n text,\n body,\n frontmatter,\n filePath: skillMdPath,\n attachments,\n };\n}\n\nexport function findSkill(\n loaded: LoadedSkills,\n idOrName: string,\n): SkillEntry | null {\n const needle = idOrName.trim();\n return (\n loaded.manifest.skills.find((s) => s.id === needle) ??\n loaded.manifest.skills.find((s) => s.name === needle) ??\n null\n );\n}\n","/**\n * Tokens tool group — exposes the consumer project's design tokens\n * to AI editors via MCP.\n *\n * Per [ADR 0020](../../../../docs/adr/0020-design-to-tokens-skill-fusion.md),\n * design knowledge now lives in @teamix-evo/skills (AI reads skill files\n * directly). MCP only provides token value lookup — the one thing AI\n * can't get from a static skill file.\n *\n * - `tokens_get` — full snapshot (base JSON + theme/overrides CSS) for copy-paste\n * - `tokens_list` — flat list of token entries for introspection (category/name/values)\n * - `tokens_search` — substring search across category / name / description / values\n *\n * When `tokens/` directory is absent (project hasn't run `tokens init`),\n * the tools return empty results with a `note` field.\n */\nimport { z } from 'zod';\nimport type { Tool } from '@modelcontextprotocol/sdk/types.js';\nimport {\n loadTokens,\n readTokens,\n listTokens,\n searchTokens,\n type LoadedTokens,\n} from '../tokens-loader.js';\nimport type { ToolGroup, ToolResult } from '../types.js';\n\nconst EmptyInput = z.object({});\nconst SearchInput = z.object({\n query: z.string().min(1),\n limit: z.number().int().min(1).max(100).optional(),\n});\n\nconst TOOLS: Tool[] = [\n {\n name: 'tokens_get',\n description:\n \"Fetch the consumer project's design tokens — parsed JSON from `tokens/base.tokens.json`, plus raw text of `tokens.theme.css` (variant theme) and `tokens.overrides.css` (user-owned overrides) when present. Use when AI needs to know what semantic colors / spacing / radii are available before writing component styles. JSON is for introspection; CSS is for copy-paste. Each result lists `sources` so you can cite paths.\",\n inputSchema: { type: 'object', properties: {} },\n },\n {\n name: 'tokens_list',\n description:\n 'List ALL design tokens as a flat array of entries `{ category, name, type, values, description }`. Categories come from top-level keys of base.tokens.json (e.g. `color`, `radius`, `spacing`). Each entry exposes resolved values keyed by mode (e.g. `light` / `dark` / `default`). Use this BEFORE writing styles to discover what semantic names are available — much cheaper than parsing the whole CSS file. Use `tokens_search` instead when you have a keyword.',\n inputSchema: { type: 'object', properties: {} },\n },\n {\n name: 'tokens_search',\n description:\n 'Substring match across token category / name / description / values (case-insensitive). Use when you remember a phrase (\"primary\" / \"destructive\" / \"card-gap\") but not the exact path. Returns up to `limit` matches (default 20). Combine with `tokens_get` if you need raw CSS text after locating an entry.',\n inputSchema: {\n type: 'object',\n properties: {\n query: { type: 'string', description: 'Free-text query.' },\n limit: {\n type: 'integer',\n minimum: 1,\n maximum: 100,\n description: 'Max matches to return (default 20).',\n },\n },\n required: ['query'],\n },\n },\n];\n\nconst TOOL_NAMES = new Set(TOOLS.map((t) => t.name));\n\nexport interface TokensGroupOptions {\n /** Pre-loaded tokens snapshot (used by tests). When omitted, the loader walks cwd. */\n loaded?: LoadedTokens | null;\n /** Override the start directory for cwd-relative resolution (used by tests). */\n rootDir?: string;\n}\n\nconst NO_TOKENS_NOTE =\n 'tokens/ directory not found in this project. Run `npx teamix-evo tokens init <variant>` to install design tokens.';\n\nexport function createTokensGroup(opts: TokensGroupOptions = {}): ToolGroup {\n let cache: LoadedTokens | null | undefined =\n opts.loaded === undefined ? undefined : opts.loaded;\n function getLoaded(): LoadedTokens | null {\n if (cache === undefined) cache = loadTokens(opts.rootDir);\n return cache;\n }\n\n return {\n name: 'tokens',\n tools: TOOLS,\n async handle(name, args): Promise<ToolResult | undefined> {\n if (!TOOL_NAMES.has(name)) return undefined;\n\n const loaded = getLoaded();\n\n if (name === 'tokens_get') {\n EmptyInput.parse(args ?? {});\n if (!loaded) {\n return jsonResult({ sources: [], note: NO_TOKENS_NOTE });\n }\n return jsonResult(readTokens(loaded));\n }\n\n if (name === 'tokens_list') {\n EmptyInput.parse(args ?? {});\n if (!loaded) {\n return jsonResult({\n variant: null,\n tokens: [],\n sources: [],\n note: NO_TOKENS_NOTE,\n });\n }\n return jsonResult(listTokens(loaded));\n }\n\n if (name === 'tokens_search') {\n const parsed = SearchInput.parse(args ?? {});\n if (!loaded) {\n return jsonResult({\n variant: null,\n query: parsed.query,\n matches: [],\n sources: [],\n note: NO_TOKENS_NOTE,\n });\n }\n return jsonResult(searchTokens(loaded, parsed.query, parsed.limit));\n }\n\n return undefined;\n },\n };\n}\n\nfunction jsonResult(payload: unknown): ToolResult {\n return {\n content: [{ type: 'text', text: JSON.stringify(payload, null, 2) }],\n };\n}\n","/**\n * Loader for the consumer project's `.teamix-evo/` state.\n *\n * Per [ADR 0020](../../../docs/adr/0020-design-to-tokens-skill-fusion.md) the\n * MCP `tokens` group reads the **installed** tokens of a teamix-evo project.\n * The loader walks up from the cwd looking for `.teamix-evo/` and, if a\n * `tokens-lock.json` is present, records the variant for downstream tools.\n *\n * Resolution order:\n *\n * 1. `TEAMIX_EVO_TOKENS_ROOT` env var (absolute path to the `.teamix-evo/` dir)\n * 2. Walk up from cwd looking for `.teamix-evo/`\n * 3. Returns `null` (not an error — projects without teamix-evo init should\n * get empty tool results with a `note`, not a thrown exception)\n */\nimport { existsSync, readFileSync } from 'node:fs';\nimport { dirname, join, resolve } from 'node:path';\n\nexport interface LoadedTokens {\n /** Absolute path to `.teamix-evo/` in the consumer project. */\n rootDir: string;\n /** Variant name read from `tokens-lock.json`, or null if missing. */\n variant: string | null;\n}\n\nexport function resolveTokensRoot(\n startDir: string = process.cwd(),\n): string | null {\n const envPath = process.env.TEAMIX_EVO_TOKENS_ROOT;\n if (envPath && existsSync(envPath)) {\n return envPath;\n }\n\n let dir = resolve(startDir);\n for (let i = 0; i < 16; i++) {\n const candidate = join(dir, '.teamix-evo');\n if (existsSync(candidate)) return candidate;\n const parent = dirname(dir);\n if (parent === dir) break;\n dir = parent;\n }\n return null;\n}\n\nexport function loadTokens(rootDir?: string): LoadedTokens | null {\n const root = rootDir ?? resolveTokensRoot();\n if (!root) return null;\n\n let variant: string | null = null;\n const lockPath = join(root, 'tokens-lock.json');\n if (existsSync(lockPath)) {\n try {\n const raw = JSON.parse(readFileSync(lockPath, 'utf-8')) as {\n variant?: string;\n };\n variant = typeof raw.variant === 'string' ? raw.variant : null;\n } catch {\n variant = null;\n }\n }\n return { rootDir: root, variant };\n}\n\nexport interface TokenSnapshot {\n /** Parsed contents of `base.tokens.json` if present. */\n base?: unknown;\n /** Raw text of `tokens.theme.css` if present. */\n themeCss?: string;\n /** Raw text of `tokens.overrides.css` if present (user-owned overrides). */\n overridesCss?: string;\n /** Source paths discovered, in load order. */\n sources: string[];\n note?: string;\n}\n\n/**\n * Locate the tokens directory. Tokens live at `<projectRoot>/tokens/`\n * (root-level, per ADR 0020).\n */\nfunction resolveTokensDir(loaded: LoadedTokens): string | null {\n const projectRoot = dirname(loaded.rootDir);\n const rootTokens = join(projectRoot, 'tokens');\n if (existsSync(rootTokens)) return rootTokens;\n return null;\n}\n\nexport function readTokens(loaded: LoadedTokens): TokenSnapshot {\n const tokensDir = resolveTokensDir(loaded);\n const out: TokenSnapshot = { sources: [] };\n if (!tokensDir) {\n out.note = 'tokens/ not found at project root.';\n return out;\n }\n const tryJson = (rel: string): unknown | undefined => {\n const fp = join(tokensDir, rel);\n if (!existsSync(fp)) return undefined;\n out.sources.push(fp);\n try {\n return JSON.parse(readFileSync(fp, 'utf-8'));\n } catch {\n return undefined;\n }\n };\n const tryText = (rel: string): string | undefined => {\n const fp = join(tokensDir, rel);\n if (!existsSync(fp)) return undefined;\n out.sources.push(fp);\n return readFileSync(fp, 'utf-8');\n };\n out.base = tryJson('base.tokens.json');\n out.themeCss = tryText('tokens.theme.css');\n out.overridesCss = tryText('tokens.overrides.css');\n return out;\n}\n\nexport interface TokenEntry {\n /** Top-level group from base.tokens.json, e.g. \"color\" / \"radius\" / \"spacing\". */\n category: string;\n /** Token leaf name within the category, e.g. \"primary\" / \"card-foreground\". */\n name: string;\n /** W3C `$type` declared on the token, when present. */\n type?: string;\n /**\n * Resolved values keyed by mode. For W3C tokens with `light` / `dark`\n * sub-objects we emit both; for flat tokens (single `$value`) we emit\n * `default`.\n */\n values: Record<string, string>;\n /** First non-empty `$description` found on the token or its modes. */\n description?: string;\n}\n\nconst W3C_KEYS = new Set(['$value', '$type', '$description', '$extensions']);\n\nfunction isPlainObject(v: unknown): v is Record<string, unknown> {\n return typeof v === 'object' && v !== null && !Array.isArray(v);\n}\n\n/**\n * Flatten a W3C-format design-token JSON tree into a list of token entries.\n *\n * The format we ingest is the one shipped by `@teamix-evo/tokens`:\n *\n * { color: { primary: { $type, light: { $value, $description }, dark: { ... } } } }\n *\n * For tokens with `$value` directly under the leaf (no light/dark split) we\n * emit `values = { default: <value> }`.\n *\n * Top-level keys starting with `$` (e.g. `$schema`, `$version`) are skipped.\n */\nexport function flattenTokens(base: unknown): TokenEntry[] {\n if (!isPlainObject(base)) return [];\n const out: TokenEntry[] = [];\n\n for (const [category, group] of Object.entries(base)) {\n if (category.startsWith('$')) continue;\n if (!isPlainObject(group)) continue;\n\n for (const [name, leaf] of Object.entries(group)) {\n if (name.startsWith('$')) continue;\n if (!isPlainObject(leaf)) continue;\n\n const type =\n typeof leaf.$type === 'string' ? (leaf.$type as string) : undefined;\n const values: Record<string, string> = {};\n let description =\n typeof leaf.$description === 'string'\n ? (leaf.$description as string)\n : undefined;\n\n if (typeof leaf.$value === 'string') {\n values.default = leaf.$value as string;\n }\n\n for (const [modeKey, modeVal] of Object.entries(leaf)) {\n if (W3C_KEYS.has(modeKey)) continue;\n if (!isPlainObject(modeVal)) continue;\n if (typeof modeVal.$value === 'string') {\n values[modeKey] = modeVal.$value as string;\n }\n if (\n !description &&\n typeof modeVal.$description === 'string'\n ) {\n description = modeVal.$description as string;\n }\n }\n\n if (Object.keys(values).length === 0) continue;\n\n out.push({\n category,\n name,\n ...(type ? { type } : {}),\n values,\n ...(description ? { description } : {}),\n });\n }\n }\n\n return out;\n}\n\nexport interface TokenListResult {\n variant: string | null;\n tokens: TokenEntry[];\n sources: string[];\n note?: string;\n}\n\nexport function listTokens(loaded: LoadedTokens): TokenListResult {\n const snapshot = readTokens(loaded);\n if (!snapshot.base) {\n return {\n variant: loaded.variant,\n tokens: [],\n sources: snapshot.sources,\n note: snapshot.note ?? 'base.tokens.json not found.',\n };\n }\n return {\n variant: loaded.variant,\n tokens: flattenTokens(snapshot.base),\n sources: snapshot.sources,\n };\n}\n\nexport interface TokenSearchResult {\n variant: string | null;\n query: string;\n matches: TokenEntry[];\n sources: string[];\n note?: string;\n}\n\n/**\n * Substring match across category / name / description / values. Case-insensitive.\n * Returns up to `limit` (default 20) matches ordered by category > name.\n */\nexport function searchTokens(\n loaded: LoadedTokens,\n query: string,\n limit = 20,\n): TokenSearchResult {\n const list = listTokens(loaded);\n const q = query.trim().toLowerCase();\n if (!q) {\n return {\n variant: list.variant,\n query,\n matches: [],\n sources: list.sources,\n note: 'query is empty.',\n };\n }\n if (list.note && list.tokens.length === 0) {\n return {\n variant: list.variant,\n query,\n matches: [],\n sources: list.sources,\n note: list.note,\n };\n }\n const hits = list.tokens.filter((t) => {\n if (t.category.toLowerCase().includes(q)) return true;\n if (t.name.toLowerCase().includes(q)) return true;\n if (t.description?.toLowerCase().includes(q)) return true;\n return Object.values(t.values).some((v) => v.toLowerCase().includes(q));\n });\n hits.sort((a, b) => {\n const c = a.category.localeCompare(b.category);\n return c !== 0 ? c : a.name.localeCompare(b.name);\n });\n return {\n variant: list.variant,\n query,\n matches: hits.slice(0, limit),\n sources: list.sources,\n };\n}\n"],"mappings":"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","names":["FM_RE","z","existsSync","readFileSync","dirname","join","resolve","z","TOOLS","TOOL_NAMES","from","z","existsSync","readFileSync","readdirSync","dirname","join","resolve","parseFrontmatter","ListInput","z","GetInput","FindInput","TOOLS","TOOL_NAMES","pickEntry","z","existsSync","readFileSync","dirname","join","resolve","z","TOOLS","TOOL_NAMES"]}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@teamix-evo/mcp",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.4.0",
|
|
4
4
|
"description": "Model Context Protocol server for teamix-evo. Single bin / single process / multiple tool groups (registry now; design / adr / scenario coming v0.6-v0.8). Renamed from @teamix-evo/registry-mcp per ADR 0011.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"exports": {
|