/ skills / mcpSkillBuilders.ts
mcpSkillBuilders.ts
 1  import type {
 2    createSkillCommand,
 3    parseSkillFrontmatterFields,
 4  } from './loadSkillsDir.js'
 5  
 6  /**
 7   * Write-once registry for the two loadSkillsDir functions that MCP skill
 8   * discovery needs. This module is a dependency-graph leaf: it imports nothing
 9   * but types, so both mcpSkills.ts and loadSkillsDir.ts can depend on it
10   * without forming a cycle (client.ts → mcpSkills.ts → loadSkillsDir.ts → …
11   * → client.ts).
12   *
13   * The non-literal dynamic-import approach ("await import(variable)") fails at
14   * runtime in Bun-bundled binaries — the specifier is resolved against the
15   * chunk's /$bunfs/root/… path, not the original source tree, yielding "Cannot
16   * find module './loadSkillsDir.js'". A literal dynamic import works in bunfs
17   * but dependency-cruiser tracks it, and because loadSkillsDir transitively
18   * reaches almost everything, the single new edge fans out into many new cycle
19   * violations in the diff check.
20   *
21   * Registration happens at loadSkillsDir.ts module init, which is eagerly
22   * evaluated at startup via the static import from commands.ts — long before
23   * any MCP server connects.
24   */
25  
26  export type MCPSkillBuilders = {
27    createSkillCommand: typeof createSkillCommand
28    parseSkillFrontmatterFields: typeof parseSkillFrontmatterFields
29  }
30  
31  let builders: MCPSkillBuilders | null = null
32  
33  export function registerMCPSkillBuilders(b: MCPSkillBuilders): void {
34    builders = b
35  }
36  
37  export function getMCPSkillBuilders(): MCPSkillBuilders {
38    if (!builders) {
39      throw new Error(
40        'MCP skill builders not registered — loadSkillsDir.ts has not been evaluated yet',
41      )
42    }
43    return builders
44  }