@2amtech/hai 0.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (239) hide show
  1. package/README.md +212 -0
  2. package/dist/ai/agent-info.d.ts +1 -0
  3. package/dist/ai/agent-info.js +42 -0
  4. package/dist/ai/agent-info.js.map +1 -0
  5. package/dist/ai/agents/architect.d.ts +3 -0
  6. package/dist/ai/agents/architect.js +107 -0
  7. package/dist/ai/agents/architect.js.map +1 -0
  8. package/dist/ai/agents/backend-dev.d.ts +3 -0
  9. package/dist/ai/agents/backend-dev.js +33 -0
  10. package/dist/ai/agents/backend-dev.js.map +1 -0
  11. package/dist/ai/agents/frontend-dev.d.ts +3 -0
  12. package/dist/ai/agents/frontend-dev.js +31 -0
  13. package/dist/ai/agents/frontend-dev.js.map +1 -0
  14. package/dist/ai/agents/index.d.ts +3 -0
  15. package/dist/ai/agents/index.js +17 -0
  16. package/dist/ai/agents/index.js.map +1 -0
  17. package/dist/ai/agents/refactorer.d.ts +3 -0
  18. package/dist/ai/agents/refactorer.js +38 -0
  19. package/dist/ai/agents/refactorer.js.map +1 -0
  20. package/dist/ai/agents/researcher.d.ts +3 -0
  21. package/dist/ai/agents/researcher.js +28 -0
  22. package/dist/ai/agents/researcher.js.map +1 -0
  23. package/dist/ai/agents/security-reviewer.d.ts +3 -0
  24. package/dist/ai/agents/security-reviewer.js +99 -0
  25. package/dist/ai/agents/security-reviewer.js.map +1 -0
  26. package/dist/ai/agents/types.d.ts +6 -0
  27. package/dist/ai/agents/types.js +2 -0
  28. package/dist/ai/agents/types.js.map +1 -0
  29. package/dist/ai/agents/verifier.d.ts +3 -0
  30. package/dist/ai/agents/verifier.js +28 -0
  31. package/dist/ai/agents/verifier.js.map +1 -0
  32. package/dist/ai/prompts/document.d.ts +3 -0
  33. package/dist/ai/prompts/document.js +57 -0
  34. package/dist/ai/prompts/document.js.map +1 -0
  35. package/dist/ai/prompts/implement.d.ts +3 -0
  36. package/dist/ai/prompts/implement.js +128 -0
  37. package/dist/ai/prompts/implement.js.map +1 -0
  38. package/dist/ai/prompts/index.d.ts +3 -0
  39. package/dist/ai/prompts/index.js +17 -0
  40. package/dist/ai/prompts/index.js.map +1 -0
  41. package/dist/ai/prompts/optimize-ai.d.ts +3 -0
  42. package/dist/ai/prompts/optimize-ai.js +104 -0
  43. package/dist/ai/prompts/optimize-ai.js.map +1 -0
  44. package/dist/ai/prompts/pull-specs.d.ts +3 -0
  45. package/dist/ai/prompts/pull-specs.js +10 -0
  46. package/dist/ai/prompts/pull-specs.js.map +1 -0
  47. package/dist/ai/prompts/pull-tickets.d.ts +3 -0
  48. package/dist/ai/prompts/pull-tickets.js +11 -0
  49. package/dist/ai/prompts/pull-tickets.js.map +1 -0
  50. package/dist/ai/prompts/pull.d.ts +3 -0
  51. package/dist/ai/prompts/pull.js +9 -0
  52. package/dist/ai/prompts/pull.js.map +1 -0
  53. package/dist/ai/prompts/review-changes.d.ts +3 -0
  54. package/dist/ai/prompts/review-changes.js +88 -0
  55. package/dist/ai/prompts/review-changes.js.map +1 -0
  56. package/dist/ai/prompts/types.d.ts +6 -0
  57. package/dist/ai/prompts/types.js +2 -0
  58. package/dist/ai/prompts/types.js.map +1 -0
  59. package/dist/app.d.ts +14 -0
  60. package/dist/app.js +40 -0
  61. package/dist/app.js.map +1 -0
  62. package/dist/cli.d.ts +2 -0
  63. package/dist/cli.js +79 -0
  64. package/dist/cli.js.map +1 -0
  65. package/dist/commands/get.d.ts +8 -0
  66. package/dist/commands/get.js +73 -0
  67. package/dist/commands/get.js.map +1 -0
  68. package/dist/commands/init.d.ts +3 -0
  69. package/dist/commands/init.js +113 -0
  70. package/dist/commands/init.js.map +1 -0
  71. package/dist/commands/mcp/helpers.d.ts +15 -0
  72. package/dist/commands/mcp/helpers.js +21 -0
  73. package/dist/commands/mcp/helpers.js.map +1 -0
  74. package/dist/commands/mcp/pull.d.ts +3 -0
  75. package/dist/commands/mcp/pull.js +85 -0
  76. package/dist/commands/mcp/pull.js.map +1 -0
  77. package/dist/commands/mcp/server.d.ts +2 -0
  78. package/dist/commands/mcp/server.js +80 -0
  79. package/dist/commands/mcp/server.js.map +1 -0
  80. package/dist/commands/mcp/specs.d.ts +2 -0
  81. package/dist/commands/mcp/specs.js +325 -0
  82. package/dist/commands/mcp/specs.js.map +1 -0
  83. package/dist/commands/mcp/tickets.d.ts +3 -0
  84. package/dist/commands/mcp/tickets.js +77 -0
  85. package/dist/commands/mcp/tickets.js.map +1 -0
  86. package/dist/commands/pull.d.ts +10 -0
  87. package/dist/commands/pull.js +61 -0
  88. package/dist/commands/pull.js.map +1 -0
  89. package/dist/commands/status.d.ts +2 -0
  90. package/dist/commands/status.js +102 -0
  91. package/dist/commands/status.js.map +1 -0
  92. package/dist/components/ticket-renderer.d.ts +5 -0
  93. package/dist/components/ticket-renderer.js +89 -0
  94. package/dist/components/ticket-renderer.js.map +1 -0
  95. package/dist/contexts/config-context.d.ts +17 -0
  96. package/dist/contexts/config-context.js +77 -0
  97. package/dist/contexts/config-context.js.map +1 -0
  98. package/dist/contexts/error-context.d.ts +12 -0
  99. package/dist/contexts/error-context.js +28 -0
  100. package/dist/contexts/error-context.js.map +1 -0
  101. package/dist/helpers/config.d.ts +4 -0
  102. package/dist/helpers/config.js +29 -0
  103. package/dist/helpers/config.js.map +1 -0
  104. package/dist/helpers/fs.d.ts +8 -0
  105. package/dist/helpers/fs.js +83 -0
  106. package/dist/helpers/fs.js.map +1 -0
  107. package/dist/helpers/init.d.ts +2 -0
  108. package/dist/helpers/init.js +18 -0
  109. package/dist/helpers/init.js.map +1 -0
  110. package/dist/helpers/preflight.d.ts +8 -0
  111. package/dist/helpers/preflight.js +77 -0
  112. package/dist/helpers/preflight.js.map +1 -0
  113. package/dist/helpers/pull.d.ts +9 -0
  114. package/dist/helpers/pull.js +79 -0
  115. package/dist/helpers/pull.js.map +1 -0
  116. package/dist/helpers/symlink.d.ts +9 -0
  117. package/dist/helpers/symlink.js +104 -0
  118. package/dist/helpers/symlink.js.map +1 -0
  119. package/dist/helpers/tickets.d.ts +4 -0
  120. package/dist/helpers/tickets.js +56 -0
  121. package/dist/helpers/tickets.js.map +1 -0
  122. package/dist/hooks/use-async.d.ts +6 -0
  123. package/dist/hooks/use-async.js +37 -0
  124. package/dist/hooks/use-async.js.map +1 -0
  125. package/dist/plugins/atlassian/adf-to-markdown.d.ts +11 -0
  126. package/dist/plugins/atlassian/adf-to-markdown.js +121 -0
  127. package/dist/plugins/atlassian/adf-to-markdown.js.map +1 -0
  128. package/dist/plugins/atlassian/auth-step.d.ts +10 -0
  129. package/dist/plugins/atlassian/auth-step.js +59 -0
  130. package/dist/plugins/atlassian/auth-step.js.map +1 -0
  131. package/dist/plugins/atlassian/confluence-client.d.ts +24 -0
  132. package/dist/plugins/atlassian/confluence-client.js +250 -0
  133. package/dist/plugins/atlassian/confluence-client.js.map +1 -0
  134. package/dist/plugins/atlassian/data.d.ts +18 -0
  135. package/dist/plugins/atlassian/data.js +12 -0
  136. package/dist/plugins/atlassian/data.js.map +1 -0
  137. package/dist/plugins/atlassian/index.d.ts +2 -0
  138. package/dist/plugins/atlassian/index.js +57 -0
  139. package/dist/plugins/atlassian/index.js.map +1 -0
  140. package/dist/plugins/atlassian/init-step.d.ts +11 -0
  141. package/dist/plugins/atlassian/init-step.js +54 -0
  142. package/dist/plugins/atlassian/init-step.js.map +1 -0
  143. package/dist/plugins/atlassian/jira-client.d.ts +38 -0
  144. package/dist/plugins/atlassian/jira-client.js +308 -0
  145. package/dist/plugins/atlassian/jira-client.js.map +1 -0
  146. package/dist/plugins/atlassian/specs-step.d.ts +13 -0
  147. package/dist/plugins/atlassian/specs-step.js +71 -0
  148. package/dist/plugins/atlassian/specs-step.js.map +1 -0
  149. package/dist/plugins/atlassian/tickets-step.d.ts +8 -0
  150. package/dist/plugins/atlassian/tickets-step.js +45 -0
  151. package/dist/plugins/atlassian/tickets-step.js.map +1 -0
  152. package/dist/plugins/claude-code/agents.d.ts +4 -0
  153. package/dist/plugins/claude-code/agents.js +56 -0
  154. package/dist/plugins/claude-code/agents.js.map +1 -0
  155. package/dist/plugins/claude-code/commands.d.ts +4 -0
  156. package/dist/plugins/claude-code/commands.js +54 -0
  157. package/dist/plugins/claude-code/commands.js.map +1 -0
  158. package/dist/plugins/claude-code/index.d.ts +2 -0
  159. package/dist/plugins/claude-code/index.js +57 -0
  160. package/dist/plugins/claude-code/index.js.map +1 -0
  161. package/dist/plugins/cursor/index.d.ts +2 -0
  162. package/dist/plugins/cursor/index.js +60 -0
  163. package/dist/plugins/cursor/index.js.map +1 -0
  164. package/dist/plugins/index.d.ts +1 -0
  165. package/dist/plugins/index.js +16 -0
  166. package/dist/plugins/index.js.map +1 -0
  167. package/dist/plugins/local/index.d.ts +2 -0
  168. package/dist/plugins/local/index.js +53 -0
  169. package/dist/plugins/local/index.js.map +1 -0
  170. package/dist/plugins/local/init-step.d.ts +9 -0
  171. package/dist/plugins/local/init-step.js +24 -0
  172. package/dist/plugins/local/init-step.js.map +1 -0
  173. package/dist/plugins/local/local-spec-provider.d.ts +9 -0
  174. package/dist/plugins/local/local-spec-provider.js +66 -0
  175. package/dist/plugins/local/local-spec-provider.js.map +1 -0
  176. package/dist/plugins/local/local-ticket-provider.d.ts +24 -0
  177. package/dist/plugins/local/local-ticket-provider.js +89 -0
  178. package/dist/plugins/local/local-ticket-provider.js.map +1 -0
  179. package/dist/plugins/none/index.d.ts +2 -0
  180. package/dist/plugins/none/index.js +78 -0
  181. package/dist/plugins/none/index.js.map +1 -0
  182. package/dist/plugins/other-ai/index.d.ts +2 -0
  183. package/dist/plugins/other-ai/index.js +48 -0
  184. package/dist/plugins/other-ai/index.js.map +1 -0
  185. package/dist/plugins/registry.d.ts +4 -0
  186. package/dist/plugins/registry.js +18 -0
  187. package/dist/plugins/registry.js.map +1 -0
  188. package/dist/plugins/resolve.d.ts +8 -0
  189. package/dist/plugins/resolve.js +23 -0
  190. package/dist/plugins/resolve.js.map +1 -0
  191. package/dist/plugins/types.d.ts +36 -0
  192. package/dist/plugins/types.js +2 -0
  193. package/dist/plugins/types.js.map +1 -0
  194. package/dist/plugins/vscode-copilot/agents.d.ts +4 -0
  195. package/dist/plugins/vscode-copilot/agents.js +51 -0
  196. package/dist/plugins/vscode-copilot/agents.js.map +1 -0
  197. package/dist/plugins/vscode-copilot/index.d.ts +2 -0
  198. package/dist/plugins/vscode-copilot/index.js +59 -0
  199. package/dist/plugins/vscode-copilot/index.js.map +1 -0
  200. package/dist/plugins/vscode-copilot/prompts.d.ts +4 -0
  201. package/dist/plugins/vscode-copilot/prompts.js +60 -0
  202. package/dist/plugins/vscode-copilot/prompts.js.map +1 -0
  203. package/dist/schemas/config.d.ts +24 -0
  204. package/dist/schemas/config.js +38 -0
  205. package/dist/schemas/config.js.map +1 -0
  206. package/dist/types.d.ts +84 -0
  207. package/dist/types.js +2 -0
  208. package/dist/types.js.map +1 -0
  209. package/dist/ui/confirm.d.ts +7 -0
  210. package/dist/ui/confirm.js +19 -0
  211. package/dist/ui/confirm.js.map +1 -0
  212. package/dist/ui/error-display.d.ts +6 -0
  213. package/dist/ui/error-display.js +23 -0
  214. package/dist/ui/error-display.js.map +1 -0
  215. package/dist/ui/masked-input.d.ts +9 -0
  216. package/dist/ui/masked-input.js +25 -0
  217. package/dist/ui/masked-input.js.map +1 -0
  218. package/dist/ui/multi-select.d.ts +13 -0
  219. package/dist/ui/multi-select.js +127 -0
  220. package/dist/ui/multi-select.js.map +1 -0
  221. package/dist/ui/select-input.d.ts +12 -0
  222. package/dist/ui/select-input.js +81 -0
  223. package/dist/ui/select-input.js.map +1 -0
  224. package/dist/ui/spinner.d.ts +6 -0
  225. package/dist/ui/spinner.js +18 -0
  226. package/dist/ui/spinner.js.map +1 -0
  227. package/dist/ui/text-input.d.ts +9 -0
  228. package/dist/ui/text-input.js +23 -0
  229. package/dist/ui/text-input.js.map +1 -0
  230. package/dist/wizard/passthrough-step.d.ts +6 -0
  231. package/dist/wizard/passthrough-step.js +8 -0
  232. package/dist/wizard/passthrough-step.js.map +1 -0
  233. package/dist/wizard/plugin-select-step.d.ts +10 -0
  234. package/dist/wizard/plugin-select-step.js +31 -0
  235. package/dist/wizard/plugin-select-step.js.map +1 -0
  236. package/dist/wizard/summary-step.d.ts +2 -0
  237. package/dist/wizard/summary-step.js +97 -0
  238. package/dist/wizard/summary-step.js.map +1 -0
  239. package/package.json +79 -0
@@ -0,0 +1,80 @@
1
+ import { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';
2
+ import { StdioServerTransport } from '@modelcontextprotocol/sdk/server/stdio.js';
3
+ import { registerPullTool } from './pull.js';
4
+ import { registerTicketTools } from './tickets.js';
5
+ import { readConfig } from '../../helpers/config.js';
6
+ import '../../plugins/index.js';
7
+ import { findPluginForCapability, extractPluginData, } from '../../schemas/config.js';
8
+ import { getPlugin } from '../../plugins/registry.js';
9
+ function summarizeCapability(config, capability) {
10
+ const entry = findPluginForCapability(config, capability);
11
+ if (!entry)
12
+ return 'not configured';
13
+ try {
14
+ const plugin = getPlugin(entry.plugin);
15
+ const data = extractPluginData(entry);
16
+ const detail = plugin.summarize?.(capability, data) ?? '';
17
+ return detail ? `${plugin.name} (${detail})` : plugin.name;
18
+ }
19
+ catch {
20
+ return `${entry.plugin} (unknown)`;
21
+ }
22
+ }
23
+ function buildProviders(config) {
24
+ if (!config) {
25
+ return "No configuration found. Run 'hai init' to set up providers.";
26
+ }
27
+ return [
28
+ `- **Tickets**: ${summarizeCapability(config, 'tickets')}`,
29
+ `- **Specs**: ${summarizeCapability(config, 'specs')}`,
30
+ ].join('\n');
31
+ }
32
+ function buildInstructions(config) {
33
+ return `Hai is a project management integration server that syncs tickets and specifications from remote providers to local markdown files.
34
+
35
+ ## Configured providers
36
+ ${buildProviders(config)}
37
+
38
+ ## Available tools
39
+
40
+ ### pullcover available specifications, then read files from \`.ai/specs/\`.
41
+ 3. Read \`.ai/ticket-index.md\` to discover available tickets, then read files from \`.ai/tickets/\`.
42
+ 4. Use \`ticket_pull\` to pull a specific tick
43
+ Syncs tickets and/or specs from remote providers to local \`.ai/\` markdown files. Use this first to populate local data. Supports dry-run mode and selective sync (tickets only, specs only, or both).
44
+
45
+ ### ticket_pull
46
+ Pulls a specific ticket by key (e.g. PROJ-123) from the remote provider and saves it locally. Only use this when the ticket is not already present in \`.ai/tickets/\`. Supports recursive fetching of linked issues.
47
+
48
+ ## Local data
49
+
50
+ After pulling, all data is stored as markdown under \`.ai/\` for direct file access:
51
+
52
+ - **Specifications**: read \`.ai/specification-index.md\` for the spec index, individual specs are in \`.ai/specs/\`
53
+ - **Tickets**: read \`.ai/ticket-index.md\` for the ticket index, individual tickets are in \`.ai/tickets/\`
54
+
55
+ To browse or search specs and tickets, read these files directly from the filesystem — no MCP tool is needed.
56
+
57
+ ## Typical workflow
58
+ 1. Run \`pull\` to sync tickets and specs from remote providers to local markdown files.
59
+ 2. Read \`.ai/specification-index.md\` to diset by key only if it is not already in \`.ai/tickets/\`.`;
60
+ }
61
+ export async function mcp(workspaceFolder) {
62
+ const configPath = `${workspaceFolder}/hai.json`;
63
+ let config = null;
64
+ try {
65
+ config = await readConfig(configPath);
66
+ }
67
+ catch {
68
+ // Config may not exist yet — that's fine, instructions will note it
69
+ }
70
+ const server = new McpServer({
71
+ name: 'hai',
72
+ version: '1.0.0',
73
+ }, {
74
+ instructions: buildInstructions(config),
75
+ });
76
+ registerPullTool(server, workspaceFolder);
77
+ registerTicketTools(server, workspaceFolder);
78
+ await server.connect(new StdioServerTransport());
79
+ }
80
+ //# sourceMappingURL=server.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"server.js","sourceRoot":"","sources":["../../../source/commands/mcp/server.ts"],"names":[],"mappings":"AAAA,OAAO,EAAC,SAAS,EAAC,MAAM,yCAAyC,CAAC;AAClE,OAAO,EAAC,oBAAoB,EAAC,MAAM,2CAA2C,CAAC;AAC/E,OAAO,EAAC,gBAAgB,EAAC,MAAM,WAAW,CAAC;AAC3C,OAAO,EAAC,mBAAmB,EAAC,MAAM,cAAc,CAAC;AACjD,OAAO,EAAC,UAAU,EAAC,MAAM,yBAAyB,CAAC;AACnD,OAAO,wBAAwB,CAAC;AAEhC,OAAO,EACN,uBAAuB,EACvB,iBAAiB,GACjB,MAAM,yBAAyB,CAAC;AACjC,OAAO,EAAC,SAAS,EAAC,MAAM,2BAA2B,CAAC;AAGpD,SAAS,mBAAmB,CAC3B,MAAiB,EACjB,UAA0B;IAE1B,MAAM,KAAK,GAAG,uBAAuB,CAAC,MAAM,EAAE,UAAU,CAAC,CAAC;IAC1D,IAAI,CAAC,KAAK;QAAE,OAAO,gBAAgB,CAAC;IACpC,IAAI,CAAC;QACJ,MAAM,MAAM,GAAG,SAAS,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC;QACvC,MAAM,IAAI,GAAG,iBAAiB,CAAC,KAAK,CAAC,CAAC;QACtC,MAAM,MAAM,GAAG,MAAM,CAAC,SAAS,EAAE,CAAC,UAAU,EAAE,IAAI,CAAC,IAAI,EAAE,CAAC;QAC1D,OAAO,MAAM,CAAC,CAAC,CAAC,GAAG,MAAM,CAAC,IAAI,KAAK,MAAM,GAAG,CAAC,CAAC,CAAC,MAAM,CAAC,IAAI,CAAC;IAC5D,CAAC;IAAC,MAAM,CAAC;QACR,OAAO,GAAG,KAAK,CAAC,MAAM,YAAY,CAAC;IACpC,CAAC;AACF,CAAC;AAED,SAAS,cAAc,CAAC,MAAwB;IAC/C,IAAI,CAAC,MAAM,EAAE,CAAC;QACb,OAAO,6DAA6D,CAAC;IACtE,CAAC;IAED,OAAO;QACN,kBAAkB,mBAAmB,CAAC,MAAM,EAAE,SAAS,CAAC,EAAE;QAC1D,gBAAgB,mBAAmB,CAAC,MAAM,EAAE,OAAO,CAAC,EAAE;KACtD,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;AACd,CAAC;AAED,SAAS,iBAAiB,CAAC,MAAwB;IAClD,OAAO;;;EAGN,cAAc,CAAC,MAAM,CAAC;;;;;;;;;;;;;;;;;;;;;;;sGAuB8E,CAAC;AACvG,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,GAAG,CAAC,eAAuB;IAChD,MAAM,UAAU,GAAG,GAAG,eAAe,WAAW,CAAC;IAEjD,IAAI,MAAM,GAAqB,IAAI,CAAC;IACpC,IAAI,CAAC;QACJ,MAAM,GAAG,MAAM,UAAU,CAAC,UAAU,CAAC,CAAC;IACvC,CAAC;IAAC,MAAM,CAAC;QACR,oEAAoE;IACrE,CAAC;IAED,MAAM,MAAM,GAAG,IAAI,SAAS,CAC3B;QACC,IAAI,EAAE,KAAK;QACX,OAAO,EAAE,OAAO;KAChB,EACD;QACC,YAAY,EAAE,iBAAiB,CAAC,MAAM,CAAC;KACvC,CACD,CAAC;IAEF,gBAAgB,CAAC,MAAM,EAAE,eAAe,CAAC,CAAC;IAC1C,mBAAmB,CAAC,MAAM,EAAE,eAAe,CAAC,CAAC;IAE7C,MAAM,MAAM,CAAC,OAAO,CAAC,IAAI,oBAAoB,EAAE,CAAC,CAAC;AAClD,CAAC"}
@@ -0,0 +1,2 @@
1
+ import type { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';
2
+ export declare function registerSpecTools(server: McpServer, workspaceFolder: string): void;
@@ -0,0 +1,325 @@
1
+ import { z } from 'zod';
2
+ import { readFile } from 'node:fs/promises';
3
+ import { join, relative } from 'node:path';
4
+ import { walkMdFiles } from '../../helpers/fs.js';
5
+ import { mcpError, mcpSuccess, errorText } from './helpers.js';
6
+ export function registerSpecTools(server, workspaceFolder) {
7
+ const specsDir = join(workspaceFolder, '.ai', 'specs');
8
+ server.registerTool('spec_get', {
9
+ description: 'Read a local spec file by path (relative to .ai/specs/)',
10
+ inputSchema: {
11
+ path: z
12
+ .string()
13
+ .describe("File path relative to .ai/specs/, e.g. 'my-project/overview.md'"),
14
+ },
15
+ outputSchema: {
16
+ path: z.string().describe('The requested spec file path'),
17
+ content: z
18
+ .string()
19
+ .describe('Markdown content of the spec file'),
20
+ },
21
+ }, async ({ path }) => {
22
+ try {
23
+ const fullPath = join(specsDir, path);
24
+ const content = await readFile(fullPath, 'utf-8');
25
+ return mcpSuccess({ path, content }, content);
26
+ }
27
+ catch (error) {
28
+ return mcpError(errorText(error));
29
+ }
30
+ });
31
+ server.registerTool('spec_list', {
32
+ description: 'List all local spec files under .ai/specs/',
33
+ inputSchema: {},
34
+ outputSchema: {
35
+ files: z
36
+ .array(z.string())
37
+ .describe('List of spec file paths relative to .ai/specs/'),
38
+ count: z.number().describe('Total number of spec files'),
39
+ },
40
+ }, async () => {
41
+ try {
42
+ const files = [];
43
+ for await (const fullPath of walkMdFiles(specsDir)) {
44
+ files.push(relative(specsDir, fullPath));
45
+ }
46
+ files.sort();
47
+ const structuredContent = {
48
+ files,
49
+ count: files.length,
50
+ };
51
+ return mcpSuccess(structuredContent, files.length > 0
52
+ ? files.join('\n')
53
+ : 'No spec files found. Run pull first.');
54
+ }
55
+ catch (error) {
56
+ return mcpError(errorText(error));
57
+ }
58
+ });
59
+ server.registerTool('spec_get_many', {
60
+ description: 'Read multiple spec files at once by paths (relative to .ai/specs/)',
61
+ inputSchema: {
62
+ paths: z
63
+ .array(z.string())
64
+ .describe("File paths relative to .ai/specs/, e.g. ['overview.md', 'api/auth.md']"),
65
+ },
66
+ outputSchema: {
67
+ results: z
68
+ .array(z.object({
69
+ path: z.string().describe('The requested spec file path'),
70
+ content: z.string().describe('Markdown content of the spec file'),
71
+ }))
72
+ .describe('Successfully read files'),
73
+ errors: z
74
+ .array(z.object({
75
+ path: z.string().describe('The requested spec file path'),
76
+ error: z.string().describe('Error message'),
77
+ }))
78
+ .describe('Files that could not be read'),
79
+ },
80
+ }, async ({ paths }) => {
81
+ const results = [];
82
+ const errors = [];
83
+ await Promise.all(paths.map(async (p) => {
84
+ try {
85
+ const fullPath = join(specsDir, p);
86
+ const content = await readFile(fullPath, 'utf-8');
87
+ results.push({ path: p, content });
88
+ }
89
+ catch (error) {
90
+ errors.push({ path: p, error: errorText(error) });
91
+ }
92
+ }));
93
+ results.sort((a, b) => a.path.localeCompare(b.path));
94
+ const structuredContent = { results, errors };
95
+ return mcpSuccess(structuredContent, results.map((r) => `--- ${r.path} ---\n${r.content}`).join('\n\n') +
96
+ (errors.length > 0
97
+ ? `\n\nErrors:\n${errors.map((e) => `${e.path}: ${e.error}`).join('\n')}`
98
+ : ''));
99
+ });
100
+ server.registerTool('spec_get_lines', {
101
+ description: 'Read specific line ranges from one or more spec files (relative to .ai/specs/)',
102
+ inputSchema: {
103
+ files: z
104
+ .array(z.object({
105
+ path: z
106
+ .string()
107
+ .describe("File path relative to .ai/specs/, e.g. 'overview.md'"),
108
+ start: z.number().describe('Start line number (1-based)'),
109
+ end: z.number().describe('End line number (1-based, inclusive)'),
110
+ }))
111
+ .describe('Files and line ranges to read'),
112
+ },
113
+ outputSchema: {
114
+ results: z
115
+ .array(z.object({
116
+ path: z.string().describe('The spec file path'),
117
+ totalLines: z
118
+ .number()
119
+ .describe('Total number of lines in the file'),
120
+ start: z.number().describe('Actual start line returned'),
121
+ end: z.number().describe('Actual end line returned'),
122
+ lines: z
123
+ .string()
124
+ .describe('The requested lines with line numbers'),
125
+ }))
126
+ .describe('Line range results'),
127
+ errors: z
128
+ .array(z.object({
129
+ path: z.string().describe('The spec file path'),
130
+ error: z.string().describe('Error message'),
131
+ }))
132
+ .describe('Files that could not be read'),
133
+ },
134
+ }, async ({ files }) => {
135
+ const results = [];
136
+ const errors = [];
137
+ await Promise.all(files.map(async ({ path: p, start, end }) => {
138
+ try {
139
+ const fullPath = join(specsDir, p);
140
+ const content = await readFile(fullPath, 'utf-8');
141
+ const allLines = content.split('\n');
142
+ const totalLines = allLines.length;
143
+ const clampedStart = Math.max(1, start);
144
+ const clampedEnd = Math.min(totalLines, end);
145
+ const selected = allLines.slice(clampedStart - 1, clampedEnd);
146
+ const numbered = selected
147
+ .map((line, i) => `${clampedStart + i}: ${line}`)
148
+ .join('\n');
149
+ results.push({
150
+ path: p,
151
+ totalLines,
152
+ start: clampedStart,
153
+ end: clampedEnd,
154
+ lines: numbered,
155
+ });
156
+ }
157
+ catch (error) {
158
+ errors.push({ path: p, error: errorText(error) });
159
+ }
160
+ }));
161
+ const structuredContent = { results, errors };
162
+ return mcpSuccess(structuredContent, results
163
+ .map((r) => `--- ${r.path} (${r.totalLines} lines) [${r.start}-${r.end}] ---\n${r.lines}`)
164
+ .join('\n\n') +
165
+ (errors.length > 0
166
+ ? `\n\nErrors:\n${errors.map((e) => `${e.path}: ${e.error}`).join('\n')}`
167
+ : ''));
168
+ });
169
+ const specSearchResultSchema = z.object({
170
+ file: z.string().describe('Spec file path relative to .ai/specs/'),
171
+ matches: z
172
+ .array(z.string())
173
+ .describe('Matching lines with line numbers'),
174
+ });
175
+ server.registerTool('spec_search', {
176
+ description: 'Search all local spec files for a regex pattern',
177
+ inputSchema: {
178
+ pattern: z
179
+ .string()
180
+ .describe('Regular expression pattern to search for'),
181
+ caseSensitive: z
182
+ .boolean()
183
+ .optional()
184
+ .default(false)
185
+ .describe('Whether the search is case-sensitive'),
186
+ },
187
+ outputSchema: {
188
+ results: z
189
+ .array(specSearchResultSchema)
190
+ .describe('Files with matching lines'),
191
+ count: z
192
+ .number()
193
+ .describe('Total number of files with matches'),
194
+ },
195
+ }, async ({ pattern, caseSensitive }) => {
196
+ try {
197
+ const regex = new RegExp(pattern, caseSensitive ? 'g' : 'gi');
198
+ const results = [];
199
+ for await (const fullPath of walkMdFiles(specsDir)) {
200
+ const relativePath = relative(specsDir, fullPath);
201
+ const content = await readFile(fullPath, 'utf-8');
202
+ const lines = content.split('\n');
203
+ const matchingLines = [];
204
+ for (let i = 0; i < lines.length; i++) {
205
+ if (regex.test(lines[i])) {
206
+ matchingLines.push(`${i + 1}: ${lines[i]}`);
207
+ }
208
+ regex.lastIndex = 0;
209
+ }
210
+ if (matchingLines.length > 0) {
211
+ results.push({
212
+ file: relativePath,
213
+ matches: matchingLines,
214
+ });
215
+ }
216
+ }
217
+ results.sort((a, b) => a.file.localeCompare(b.file));
218
+ const structuredContent = {
219
+ results,
220
+ count: results.length,
221
+ };
222
+ return mcpSuccess(structuredContent, results.length > 0
223
+ ? JSON.stringify(results, null, 2)
224
+ : 'No matches found.');
225
+ }
226
+ catch (error) {
227
+ return mcpError(errorText(error));
228
+ }
229
+ });
230
+ const excerptChunkSchema = z.object({
231
+ file: z.string().describe('Spec file path (use with spec_get)'),
232
+ totalLines: z.number().describe('Total number of lines in the file'),
233
+ lines: z
234
+ .array(z.object({
235
+ number: z.number().describe('Line number (1-based)'),
236
+ text: z.string().describe('Line content'),
237
+ isMatch: z
238
+ .boolean()
239
+ .describe('Whether this line contains the match'),
240
+ }))
241
+ .describe('Excerpt lines around the match (-5 to +5)'),
242
+ });
243
+ server.registerTool('spec_search_excerpt', {
244
+ description: 'Search spec files and return 10-line excerpts around each match (5 lines before and after)',
245
+ inputSchema: {
246
+ pattern: z
247
+ .string()
248
+ .describe('Regular expression pattern to search for'),
249
+ caseSensitive: z
250
+ .boolean()
251
+ .optional()
252
+ .default(false)
253
+ .describe('Whether the search is case-sensitive'),
254
+ },
255
+ outputSchema: {
256
+ results: z
257
+ .array(excerptChunkSchema)
258
+ .describe('Excerpt chunks with context around matches'),
259
+ count: z.number().describe('Total number of excerpt chunks'),
260
+ },
261
+ }, async ({ pattern, caseSensitive }) => {
262
+ try {
263
+ const regex = new RegExp(pattern, caseSensitive ? 'g' : 'gi');
264
+ const results = [];
265
+ for await (const fullPath of walkMdFiles(specsDir)) {
266
+ const relativePath = relative(specsDir, fullPath);
267
+ const content = await readFile(fullPath, 'utf-8');
268
+ const allLines = content.split('\n');
269
+ const totalLines = allLines.length;
270
+ // Collect matching line indices
271
+ const matchIndices = [];
272
+ for (let i = 0; i < allLines.length; i++) {
273
+ if (regex.test(allLines[i])) {
274
+ matchIndices.push(i);
275
+ }
276
+ regex.lastIndex = 0;
277
+ }
278
+ if (matchIndices.length === 0)
279
+ continue;
280
+ // Merge overlapping ranges and build chunks
281
+ const ranges = [];
282
+ for (const idx of matchIndices) {
283
+ const start = Math.max(0, idx - 5);
284
+ const end = Math.min(allLines.length - 1, idx + 5);
285
+ const last = ranges[ranges.length - 1];
286
+ if (last && start <= last.end + 1) {
287
+ last.end = Math.max(last.end, end);
288
+ last.matchSet.add(idx);
289
+ }
290
+ else {
291
+ ranges.push({ start, end, matchSet: new Set([idx]) });
292
+ }
293
+ }
294
+ for (const range of ranges) {
295
+ const lines = [];
296
+ for (let i = range.start; i <= range.end; i++) {
297
+ lines.push({
298
+ number: i + 1,
299
+ text: allLines[i],
300
+ isMatch: range.matchSet.has(i),
301
+ });
302
+ }
303
+ results.push({ file: relativePath, totalLines, lines });
304
+ }
305
+ }
306
+ results.sort((a, b) => a.file.localeCompare(b.file));
307
+ const structuredContent = { results, count: results.length };
308
+ return mcpSuccess(structuredContent, results.length > 0
309
+ ? results
310
+ .map((r) => {
311
+ const header = `--- ${r.file} (${r.totalLines} lines) ---`;
312
+ const body = r.lines
313
+ .map((l) => `${l.isMatch ? '>' : ' '} ${l.number}: ${l.text}`)
314
+ .join('\n');
315
+ return `${header}\n${body}`;
316
+ })
317
+ .join('\n\n')
318
+ : 'No matches found.');
319
+ }
320
+ catch (error) {
321
+ return mcpError(errorText(error));
322
+ }
323
+ });
324
+ }
325
+ //# sourceMappingURL=specs.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"specs.js","sourceRoot":"","sources":["../../../source/commands/mcp/specs.ts"],"names":[],"mappings":"AACA,OAAO,EAAC,CAAC,EAAC,MAAM,KAAK,CAAC;AACtB,OAAO,EAAC,QAAQ,EAAC,MAAM,kBAAkB,CAAC;AAC1C,OAAO,EAAC,IAAI,EAAE,QAAQ,EAAC,MAAM,WAAW,CAAC;AACzC,OAAO,EAAC,WAAW,EAAC,MAAM,qBAAqB,CAAC;AAChD,OAAO,EAAC,QAAQ,EAAE,UAAU,EAAE,SAAS,EAAC,MAAM,cAAc,CAAC;AAE7D,MAAM,UAAU,iBAAiB,CAChC,MAAiB,EACjB,eAAuB;IAEvB,MAAM,QAAQ,GAAG,IAAI,CAAC,eAAe,EAAE,KAAK,EAAE,OAAO,CAAC,CAAC;IAEvD,MAAM,CAAC,YAAY,CAClB,UAAU,EACV;QACC,WAAW,EACV,yDAAyD;QAC1D,WAAW,EAAE;YACZ,IAAI,EAAE,CAAC;iBACL,MAAM,EAAE;iBACR,QAAQ,CACR,iEAAiE,CACjE;SACF;QACD,YAAY,EAAE;YACb,IAAI,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,CAAC,8BAA8B,CAAC;YACzD,OAAO,EAAE,CAAC;iBACR,MAAM,EAAE;iBACR,QAAQ,CAAC,mCAAmC,CAAC;SAC/C;KACD,EACD,KAAK,EAAE,EAAC,IAAI,EAAC,EAAE,EAAE;QAChB,IAAI,CAAC;YACJ,MAAM,QAAQ,GAAG,IAAI,CAAC,QAAQ,EAAE,IAAI,CAAC,CAAC;YACtC,MAAM,OAAO,GAAG,MAAM,QAAQ,CAAC,QAAQ,EAAE,OAAO,CAAC,CAAC;YAClD,OAAO,UAAU,CAAC,EAAC,IAAI,EAAE,OAAO,EAAC,EAAE,OAAO,CAAC,CAAC;QAC7C,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YAChB,OAAO,QAAQ,CAAC,SAAS,CAAC,KAAK,CAAC,CAAC,CAAC;QACnC,CAAC;IACF,CAAC,CACD,CAAC;IAEF,MAAM,CAAC,YAAY,CAClB,WAAW,EACX;QACC,WAAW,EAAE,4CAA4C;QACzD,WAAW,EAAE,EAAE;QACf,YAAY,EAAE;YACb,KAAK,EAAE,CAAC;iBACN,KAAK,CAAC,CAAC,CAAC,MAAM,EAAE,CAAC;iBACjB,QAAQ,CAAC,gDAAgD,CAAC;YAC5D,KAAK,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,CAAC,4BAA4B,CAAC;SACxD;KACD,EACD,KAAK,IAAI,EAAE;QACV,IAAI,CAAC;YACJ,MAAM,KAAK,GAAa,EAAE,CAAC;YAE3B,IAAI,KAAK,EAAE,MAAM,QAAQ,IAAI,WAAW,CAAC,QAAQ,CAAC,EAAE,CAAC;gBACpD,KAAK,CAAC,IAAI,CAAC,QAAQ,CAAC,QAAQ,EAAE,QAAQ,CAAC,CAAC,CAAC;YAC1C,CAAC;YAED,KAAK,CAAC,IAAI,EAAE,CAAC;YAEb,MAAM,iBAAiB,GAAG;gBACzB,KAAK;gBACL,KAAK,EAAE,KAAK,CAAC,MAAM;aACnB,CAAC;YAEF,OAAO,UAAU,CAChB,iBAAiB,EACjB,KAAK,CAAC,MAAM,GAAG,CAAC;gBACf,CAAC,CAAC,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC;gBAClB,CAAC,CAAC,sCAAsC,CACzC,CAAC;QACH,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YAChB,OAAO,QAAQ,CAAC,SAAS,CAAC,KAAK,CAAC,CAAC,CAAC;QACnC,CAAC;IACF,CAAC,CACD,CAAC;IAEF,MAAM,CAAC,YAAY,CAClB,eAAe,EACf;QACC,WAAW,EACV,oEAAoE;QACrE,WAAW,EAAE;YACZ,KAAK,EAAE,CAAC;iBACN,KAAK,CAAC,CAAC,CAAC,MAAM,EAAE,CAAC;iBACjB,QAAQ,CACR,wEAAwE,CACxE;SACF;QACD,YAAY,EAAE;YACb,OAAO,EAAE,CAAC;iBACR,KAAK,CACL,CAAC,CAAC,MAAM,CAAC;gBACR,IAAI,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,CAAC,8BAA8B,CAAC;gBACzD,OAAO,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,CAAC,mCAAmC,CAAC;aACjE,CAAC,CACF;iBACA,QAAQ,CAAC,yBAAyB,CAAC;YACrC,MAAM,EAAE,CAAC;iBACP,KAAK,CACL,CAAC,CAAC,MAAM,CAAC;gBACR,IAAI,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,CAAC,8BAA8B,CAAC;gBACzD,KAAK,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,CAAC,eAAe,CAAC;aAC3C,CAAC,CACF;iBACA,QAAQ,CAAC,8BAA8B,CAAC;SAC1C;KACD,EACD,KAAK,EAAE,EAAC,KAAK,EAAC,EAAE,EAAE;QACjB,MAAM,OAAO,GAA2C,EAAE,CAAC;QAC3D,MAAM,MAAM,GAAyC,EAAE,CAAC;QAExD,MAAM,OAAO,CAAC,GAAG,CAChB,KAAK,CAAC,GAAG,CAAC,KAAK,EAAE,CAAC,EAAE,EAAE;YACrB,IAAI,CAAC;gBACJ,MAAM,QAAQ,GAAG,IAAI,CAAC,QAAQ,EAAE,CAAC,CAAC,CAAC;gBACnC,MAAM,OAAO,GAAG,MAAM,QAAQ,CAAC,QAAQ,EAAE,OAAO,CAAC,CAAC;gBAClD,OAAO,CAAC,IAAI,CAAC,EAAC,IAAI,EAAE,CAAC,EAAE,OAAO,EAAC,CAAC,CAAC;YAClC,CAAC;YAAC,OAAO,KAAK,EAAE,CAAC;gBAChB,MAAM,CAAC,IAAI,CAAC,EAAC,IAAI,EAAE,CAAC,EAAE,KAAK,EAAE,SAAS,CAAC,KAAK,CAAC,EAAC,CAAC,CAAC;YACjD,CAAC;QACF,CAAC,CAAC,CACF,CAAC;QAEF,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,aAAa,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC;QAErD,MAAM,iBAAiB,GAAG,EAAC,OAAO,EAAE,MAAM,EAAC,CAAC;QAE5C,OAAO,UAAU,CAChB,iBAAiB,EACjB,OAAO,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,OAAO,CAAC,CAAC,IAAI,SAAS,CAAC,CAAC,OAAO,EAAE,CAAC,CAAC,IAAI,CAAC,MAAM,CAAC;YACjE,CAAC,MAAM,CAAC,MAAM,GAAG,CAAC;gBACjB,CAAC,CAAC,gBAAgB,MAAM,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,GAAG,CAAC,CAAC,IAAI,KAAK,CAAC,CAAC,KAAK,EAAE,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE;gBACzE,CAAC,CAAC,EAAE,CAAC,CACP,CAAC;IACH,CAAC,CACD,CAAC;IAEF,MAAM,CAAC,YAAY,CAClB,gBAAgB,EAChB;QACC,WAAW,EACV,gFAAgF;QACjF,WAAW,EAAE;YACZ,KAAK,EAAE,CAAC;iBACN,KAAK,CACL,CAAC,CAAC,MAAM,CAAC;gBACR,IAAI,EAAE,CAAC;qBACL,MAAM,EAAE;qBACR,QAAQ,CACR,sDAAsD,CACtD;gBACF,KAAK,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,CAAC,6BAA6B,CAAC;gBACzD,GAAG,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,CAAC,sCAAsC,CAAC;aAChE,CAAC,CACF;iBACA,QAAQ,CAAC,+BAA+B,CAAC;SAC3C;QACD,YAAY,EAAE;YACb,OAAO,EAAE,CAAC;iBACR,KAAK,CACL,CAAC,CAAC,MAAM,CAAC;gBACR,IAAI,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,CAAC,oBAAoB,CAAC;gBAC/C,UAAU,EAAE,CAAC;qBACX,MAAM,EAAE;qBACR,QAAQ,CAAC,mCAAmC,CAAC;gBAC/C,KAAK,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,CAAC,4BAA4B,CAAC;gBACxD,GAAG,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,CAAC,0BAA0B,CAAC;gBACpD,KAAK,EAAE,CAAC;qBACN,MAAM,EAAE;qBACR,QAAQ,CAAC,uCAAuC,CAAC;aACnD,CAAC,CACF;iBACA,QAAQ,CAAC,oBAAoB,CAAC;YAChC,MAAM,EAAE,CAAC;iBACP,KAAK,CACL,CAAC,CAAC,MAAM,CAAC;gBACR,IAAI,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,CAAC,oBAAoB,CAAC;gBAC/C,KAAK,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,CAAC,eAAe,CAAC;aAC3C,CAAC,CACF;iBACA,QAAQ,CAAC,8BAA8B,CAAC;SAC1C;KACD,EACD,KAAK,EAAE,EAAC,KAAK,EAAC,EAAE,EAAE;QACjB,MAAM,OAAO,GAMR,EAAE,CAAC;QACR,MAAM,MAAM,GAAyC,EAAE,CAAC;QAExD,MAAM,OAAO,CAAC,GAAG,CAChB,KAAK,CAAC,GAAG,CAAC,KAAK,EAAE,EAAC,IAAI,EAAE,CAAC,EAAE,KAAK,EAAE,GAAG,EAAC,EAAE,EAAE;YACzC,IAAI,CAAC;gBACJ,MAAM,QAAQ,GAAG,IAAI,CAAC,QAAQ,EAAE,CAAC,CAAC,CAAC;gBACnC,MAAM,OAAO,GAAG,MAAM,QAAQ,CAAC,QAAQ,EAAE,OAAO,CAAC,CAAC;gBAClD,MAAM,QAAQ,GAAG,OAAO,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;gBACrC,MAAM,UAAU,GAAG,QAAQ,CAAC,MAAM,CAAC;gBACnC,MAAM,YAAY,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,KAAK,CAAC,CAAC;gBACxC,MAAM,UAAU,GAAG,IAAI,CAAC,GAAG,CAAC,UAAU,EAAE,GAAG,CAAC,CAAC;gBAC7C,MAAM,QAAQ,GAAG,QAAQ,CAAC,KAAK,CAAC,YAAY,GAAG,CAAC,EAAE,UAAU,CAAC,CAAC;gBAC9D,MAAM,QAAQ,GAAG,QAAQ;qBACvB,GAAG,CAAC,CAAC,IAAI,EAAE,CAAC,EAAE,EAAE,CAAC,GAAG,YAAY,GAAG,CAAC,KAAK,IAAI,EAAE,CAAC;qBAChD,IAAI,CAAC,IAAI,CAAC,CAAC;gBACb,OAAO,CAAC,IAAI,CAAC;oBACZ,IAAI,EAAE,CAAC;oBACP,UAAU;oBACV,KAAK,EAAE,YAAY;oBACnB,GAAG,EAAE,UAAU;oBACf,KAAK,EAAE,QAAQ;iBACf,CAAC,CAAC;YACJ,CAAC;YAAC,OAAO,KAAK,EAAE,CAAC;gBAChB,MAAM,CAAC,IAAI,CAAC,EAAC,IAAI,EAAE,CAAC,EAAE,KAAK,EAAE,SAAS,CAAC,KAAK,CAAC,EAAC,CAAC,CAAC;YACjD,CAAC;QACF,CAAC,CAAC,CACF,CAAC;QAEF,MAAM,iBAAiB,GAAG,EAAC,OAAO,EAAE,MAAM,EAAC,CAAC;QAE5C,OAAO,UAAU,CAChB,iBAAiB,EACjB,OAAO;aACL,GAAG,CACH,CAAC,CAAC,EAAE,EAAE,CACL,OAAO,CAAC,CAAC,IAAI,KAAK,CAAC,CAAC,UAAU,YAAY,CAAC,CAAC,KAAK,IAAI,CAAC,CAAC,GAAG,UAAU,CAAC,CAAC,KAAK,EAAE,CAC9E;aACA,IAAI,CAAC,MAAM,CAAC;YACb,CAAC,MAAM,CAAC,MAAM,GAAG,CAAC;gBACjB,CAAC,CAAC,gBAAgB,MAAM,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,GAAG,CAAC,CAAC,IAAI,KAAK,CAAC,CAAC,KAAK,EAAE,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE;gBACzE,CAAC,CAAC,EAAE,CAAC,CACP,CAAC;IACH,CAAC,CACD,CAAC;IAEF,MAAM,sBAAsB,GAAG,CAAC,CAAC,MAAM,CAAC;QACvC,IAAI,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,CAAC,uCAAuC,CAAC;QAClE,OAAO,EAAE,CAAC;aACR,KAAK,CAAC,CAAC,CAAC,MAAM,EAAE,CAAC;aACjB,QAAQ,CAAC,kCAAkC,CAAC;KAC9C,CAAC,CAAC;IAEH,MAAM,CAAC,YAAY,CAClB,aAAa,EACb;QACC,WAAW,EAAE,iDAAiD;QAC9D,WAAW,EAAE;YACZ,OAAO,EAAE,CAAC;iBACR,MAAM,EAAE;iBACR,QAAQ,CAAC,0CAA0C,CAAC;YACtD,aAAa,EAAE,CAAC;iBACd,OAAO,EAAE;iBACT,QAAQ,EAAE;iBACV,OAAO,CAAC,KAAK,CAAC;iBACd,QAAQ,CAAC,sCAAsC,CAAC;SAClD;QACD,YAAY,EAAE;YACb,OAAO,EAAE,CAAC;iBACR,KAAK,CAAC,sBAAsB,CAAC;iBAC7B,QAAQ,CAAC,2BAA2B,CAAC;YACvC,KAAK,EAAE,CAAC;iBACN,MAAM,EAAE;iBACR,QAAQ,CAAC,oCAAoC,CAAC;SAChD;KACD,EACD,KAAK,EAAE,EAAC,OAAO,EAAE,aAAa,EAAC,EAAE,EAAE;QAClC,IAAI,CAAC;YACJ,MAAM,KAAK,GAAG,IAAI,MAAM,CAAC,OAAO,EAAE,aAAa,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC;YAC9D,MAAM,OAAO,GAA6C,EAAE,CAAC;YAE7D,IAAI,KAAK,EAAE,MAAM,QAAQ,IAAI,WAAW,CAAC,QAAQ,CAAC,EAAE,CAAC;gBACpD,MAAM,YAAY,GAAG,QAAQ,CAAC,QAAQ,EAAE,QAAQ,CAAC,CAAC;gBAClD,MAAM,OAAO,GAAG,MAAM,QAAQ,CAAC,QAAQ,EAAE,OAAO,CAAC,CAAC;gBAClD,MAAM,KAAK,GAAG,OAAO,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;gBAClC,MAAM,aAAa,GAAa,EAAE,CAAC;gBACnC,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,KAAK,CAAC,MAAM,EAAE,CAAC,EAAE,EAAE,CAAC;oBACvC,IAAI,KAAK,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,CAAE,CAAC,EAAE,CAAC;wBAC3B,aAAa,CAAC,IAAI,CAAC,GAAG,CAAC,GAAG,CAAC,KAAK,KAAK,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC;oBAC7C,CAAC;oBAED,KAAK,CAAC,SAAS,GAAG,CAAC,CAAC;gBACrB,CAAC;gBAED,IAAI,aAAa,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;oBAC9B,OAAO,CAAC,IAAI,CAAC;wBACZ,IAAI,EAAE,YAAY;wBAClB,OAAO,EAAE,aAAa;qBACtB,CAAC,CAAC;gBACJ,CAAC;YACF,CAAC;YAED,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,aAAa,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC;YAErD,MAAM,iBAAiB,GAAG;gBACzB,OAAO;gBACP,KAAK,EAAE,OAAO,CAAC,MAAM;aACrB,CAAC;YAEF,OAAO,UAAU,CAChB,iBAAiB,EACjB,OAAO,CAAC,MAAM,GAAG,CAAC;gBACjB,CAAC,CAAC,IAAI,CAAC,SAAS,CAAC,OAAO,EAAE,IAAI,EAAE,CAAC,CAAC;gBAClC,CAAC,CAAC,mBAAmB,CACtB,CAAC;QACH,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YAChB,OAAO,QAAQ,CAAC,SAAS,CAAC,KAAK,CAAC,CAAC,CAAC;QACnC,CAAC;IACF,CAAC,CACD,CAAC;IAEF,MAAM,kBAAkB,GAAG,CAAC,CAAC,MAAM,CAAC;QACnC,IAAI,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,CAAC,oCAAoC,CAAC;QAC/D,UAAU,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,CAAC,mCAAmC,CAAC;QACpE,KAAK,EAAE,CAAC;aACN,KAAK,CACL,CAAC,CAAC,MAAM,CAAC;YACR,MAAM,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,CAAC,uBAAuB,CAAC;YACpD,IAAI,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,CAAC,cAAc,CAAC;YACzC,OAAO,EAAE,CAAC;iBACR,OAAO,EAAE;iBACT,QAAQ,CAAC,sCAAsC,CAAC;SAClD,CAAC,CACF;aACA,QAAQ,CAAC,2CAA2C,CAAC;KACvD,CAAC,CAAC;IAEH,MAAM,CAAC,YAAY,CAClB,qBAAqB,EACrB;QACC,WAAW,EACV,4FAA4F;QAC7F,WAAW,EAAE;YACZ,OAAO,EAAE,CAAC;iBACR,MAAM,EAAE;iBACR,QAAQ,CAAC,0CAA0C,CAAC;YACtD,aAAa,EAAE,CAAC;iBACd,OAAO,EAAE;iBACT,QAAQ,EAAE;iBACV,OAAO,CAAC,KAAK,CAAC;iBACd,QAAQ,CAAC,sCAAsC,CAAC;SAClD;QACD,YAAY,EAAE;YACb,OAAO,EAAE,CAAC;iBACR,KAAK,CAAC,kBAAkB,CAAC;iBACzB,QAAQ,CAAC,4CAA4C,CAAC;YACxD,KAAK,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,CAAC,gCAAgC,CAAC;SAC5D;KACD,EACD,KAAK,EAAE,EAAC,OAAO,EAAE,aAAa,EAAC,EAAE,EAAE;QAClC,IAAI,CAAC;YACJ,MAAM,KAAK,GAAG,IAAI,MAAM,CAAC,OAAO,EAAE,aAAa,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC;YAC9D,MAAM,OAAO,GAIR,EAAE,CAAC;YAER,IAAI,KAAK,EAAE,MAAM,QAAQ,IAAI,WAAW,CAAC,QAAQ,CAAC,EAAE,CAAC;gBACpD,MAAM,YAAY,GAAG,QAAQ,CAAC,QAAQ,EAAE,QAAQ,CAAC,CAAC;gBAClD,MAAM,OAAO,GAAG,MAAM,QAAQ,CAAC,QAAQ,EAAE,OAAO,CAAC,CAAC;gBAClD,MAAM,QAAQ,GAAG,OAAO,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;gBACrC,MAAM,UAAU,GAAG,QAAQ,CAAC,MAAM,CAAC;gBAEnC,gCAAgC;gBAChC,MAAM,YAAY,GAAa,EAAE,CAAC;gBAClC,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,QAAQ,CAAC,MAAM,EAAE,CAAC,EAAE,EAAE,CAAC;oBAC1C,IAAI,KAAK,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC,CAAE,CAAC,EAAE,CAAC;wBAC9B,YAAY,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;oBACtB,CAAC;oBAED,KAAK,CAAC,SAAS,GAAG,CAAC,CAAC;gBACrB,CAAC;gBAED,IAAI,YAAY,CAAC,MAAM,KAAK,CAAC;oBAAE,SAAS;gBAExC,4CAA4C;gBAC5C,MAAM,MAAM,GAA+D,EAAE,CAAC;gBAC9E,KAAK,MAAM,GAAG,IAAI,YAAY,EAAE,CAAC;oBAChC,MAAM,KAAK,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,GAAG,GAAG,CAAC,CAAC,CAAC;oBACnC,MAAM,GAAG,GAAG,IAAI,CAAC,GAAG,CAAC,QAAQ,CAAC,MAAM,GAAG,CAAC,EAAE,GAAG,GAAG,CAAC,CAAC,CAAC;oBACnD,MAAM,IAAI,GAAG,MAAM,CAAC,MAAM,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC;oBACvC,IAAI,IAAI,IAAI,KAAK,IAAI,IAAI,CAAC,GAAG,GAAG,CAAC,EAAE,CAAC;wBACnC,IAAI,CAAC,GAAG,GAAG,IAAI,CAAC,GAAG,CAAC,IAAI,CAAC,GAAG,EAAE,GAAG,CAAC,CAAC;wBACnC,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC;oBACxB,CAAC;yBAAM,CAAC;wBACP,MAAM,CAAC,IAAI,CAAC,EAAC,KAAK,EAAE,GAAG,EAAE,QAAQ,EAAE,IAAI,GAAG,CAAC,CAAC,GAAG,CAAC,CAAC,EAAC,CAAC,CAAC;oBACrD,CAAC;gBACF,CAAC;gBAED,KAAK,MAAM,KAAK,IAAI,MAAM,EAAE,CAAC;oBAC5B,MAAM,KAAK,GAIN,EAAE,CAAC;oBACR,KAAK,IAAI,CAAC,GAAG,KAAK,CAAC,KAAK,EAAE,CAAC,IAAI,KAAK,CAAC,GAAG,EAAE,CAAC,EAAE,EAAE,CAAC;wBAC/C,KAAK,CAAC,IAAI,CAAC;4BACV,MAAM,EAAE,CAAC,GAAG,CAAC;4BACb,IAAI,EAAE,QAAQ,CAAC,CAAC,CAAE;4BAClB,OAAO,EAAE,KAAK,CAAC,QAAQ,CAAC,GAAG,CAAC,CAAC,CAAC;yBAC9B,CAAC,CAAC;oBACJ,CAAC;oBAED,OAAO,CAAC,IAAI,CAAC,EAAC,IAAI,EAAE,YAAY,EAAE,UAAU,EAAE,KAAK,EAAC,CAAC,CAAC;gBACvD,CAAC;YACF,CAAC;YAED,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,aAAa,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC;YAErD,MAAM,iBAAiB,GAAG,EAAC,OAAO,EAAE,KAAK,EAAE,OAAO,CAAC,MAAM,EAAC,CAAC;YAE3D,OAAO,UAAU,CAChB,iBAAiB,EACjB,OAAO,CAAC,MAAM,GAAG,CAAC;gBACjB,CAAC,CAAC,OAAO;qBACN,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE;oBACV,MAAM,MAAM,GAAG,OAAO,CAAC,CAAC,IAAI,KAAK,CAAC,CAAC,UAAU,aAAa,CAAC;oBAC3D,MAAM,IAAI,GAAG,CAAC,CAAC,KAAK;yBAClB,GAAG,CACH,CAAC,CAAC,EAAE,EAAE,CACL,GAAG,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,GAAG,IAAI,CAAC,CAAC,MAAM,KAAK,CAAC,CAAC,IAAI,EAAE,CAClD;yBACA,IAAI,CAAC,IAAI,CAAC,CAAC;oBACb,OAAO,GAAG,MAAM,KAAK,IAAI,EAAE,CAAC;gBAC7B,CAAC,CAAC;qBACD,IAAI,CAAC,MAAM,CAAC;gBACf,CAAC,CAAC,mBAAmB,CACtB,CAAC;QACH,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YAChB,OAAO,QAAQ,CAAC,SAAS,CAAC,KAAK,CAAC,CAAC,CAAC;QACnC,CAAC;IACF,CAAC,CACD,CAAC;AACH,CAAC"}
@@ -0,0 +1,3 @@
1
+ import type { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';
2
+ import '../../plugins/index.js';
3
+ export declare function registerTicketTools(server: McpServer, workspaceFolder: string): void;
@@ -0,0 +1,77 @@
1
+ import { z } from 'zod';
2
+ import { writeFile, mkdir } from 'node:fs/promises';
3
+ import { join } from 'node:path';
4
+ import { readConfig } from '../../helpers/config.js';
5
+ import '../../plugins/index.js';
6
+ import { resolveTicketProvider } from '../../plugins/resolve.js';
7
+ import { renderTicket } from '../../components/ticket-renderer.js';
8
+ import { projectFromKey, fetchAllIssues, listLocalTicketKeys, } from '../../helpers/tickets.js';
9
+ import { mcpError, mcpSuccess } from './helpers.js';
10
+ async function writeTickets(tickets, localFiles, ticketsDir) {
11
+ const results = [];
12
+ for (const ticket of tickets) {
13
+ const project = projectFromKey(ticket.key);
14
+ const dir = join(ticketsDir, project);
15
+ await mkdir(dir, { recursive: true });
16
+ const filePath = join(ticketsDir, project, `${ticket.key}.md`);
17
+ const content = renderTicket(ticket, { localFiles });
18
+ await writeFile(filePath, content, 'utf-8');
19
+ results.push({ key: ticket.key, filePath, content });
20
+ }
21
+ return results;
22
+ }
23
+ export function registerTicketTools(server, workspaceFolder) {
24
+ const ticketsDir = join(workspaceFolder, '.ai', 'tickets');
25
+ const ticketEntrySchema = z.object({
26
+ key: z.string().describe('The ticket key, e.g. PROJ-123'),
27
+ filePath: z.string().describe('Local file path of the ticket'),
28
+ content: z.string().describe('Markdown content of the ticket'),
29
+ });
30
+ server.registerTool('ticket_pull', {
31
+ description: 'Pull a specific ticket by key from the remote provider and save it locally. Only use this when the ticket is not already present in .ai/tickets/.',
32
+ inputSchema: {
33
+ issueKey: z.string().describe('The issue key, e.g. PROJ-123'),
34
+ recursive: z
35
+ .boolean()
36
+ .optional()
37
+ .default(false)
38
+ .describe('Fetch linked issues recursively'),
39
+ },
40
+ outputSchema: {
41
+ tickets: z
42
+ .array(ticketEntrySchema)
43
+ .describe('Pulled ticket(s)'),
44
+ },
45
+ }, async ({ issueKey, recursive }) => {
46
+ try {
47
+ const config = await readConfig(join(workspaceFolder, 'hai.json'));
48
+ const provider = resolveTicketProvider(config);
49
+ const tickets = await fetchAllIssues(provider, issueKey, recursive);
50
+ const localFiles = await listLocalTicketKeys(ticketsDir);
51
+ for (const t of tickets)
52
+ localFiles.add(t.key);
53
+ const written = await writeTickets(tickets, localFiles, ticketsDir);
54
+ return mcpSuccess({ tickets: written });
55
+ }
56
+ catch (error) {
57
+ const message = error instanceof Error ? error.message : String(error);
58
+ let text;
59
+ if (message.includes('(404)')) {
60
+ text = `Issue '${issueKey}' not found.`;
61
+ }
62
+ else if (message.includes('(401)') ||
63
+ message.includes('(403)')) {
64
+ text =
65
+ "Authentication failed. Run 'hai init' to update your credentials.";
66
+ }
67
+ else if (message.includes('not found')) {
68
+ text = `${message}\nRun 'hai init' to set up your configuration.`;
69
+ }
70
+ else {
71
+ text = message;
72
+ }
73
+ return mcpError(text);
74
+ }
75
+ });
76
+ }
77
+ //# sourceMappingURL=tickets.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"tickets.js","sourceRoot":"","sources":["../../../source/commands/mcp/tickets.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,10 @@
1
+ import React from 'react';
2
+ import '../plugins/index.js';
3
+ type Props = {
4
+ dryRun: boolean;
5
+ tickets: boolean;
6
+ specs: boolean;
7
+ updateLocal: boolean;
8
+ };
9
+ export default function PullCommand({ dryRun, tickets, specs, updateLocal, }: Props): React.JSX.Element;
10
+ export {};
@@ -0,0 +1,61 @@
1
+ import React, { useState, useEffect } from 'react';
2
+ import { Text } from 'ink';
3
+ import '../plugins/index.js';
4
+ import Spinner from '../ui/spinner.js';
5
+ import { useConfigContext } from '../contexts/config-context.js';
6
+ import { pullTickets, pullSpecs } from '../helpers/pull.js';
7
+ const PHASE_FLOW = ['tickets', 'specs', 'done'];
8
+ export default function PullCommand({ dryRun, tickets, specs, updateLocal, }) {
9
+ const [phases, setPhases] = useState([...PHASE_FLOW]);
10
+ const [error, setError] = useState(null);
11
+ useEffect(() => {
12
+ if (tickets) {
13
+ setPhases(prev => prev.slice(1));
14
+ }
15
+ else if (specs) {
16
+ setPhases(prev => prev.slice(2));
17
+ }
18
+ else {
19
+ setPhases(['done']);
20
+ }
21
+ }, [tickets, specs]);
22
+ if (error) {
23
+ return React.createElement(Text, { color: "red" },
24
+ "Error during pull: ",
25
+ error.message);
26
+ }
27
+ return (React.createElement(RenderPhase, { key: phases[0], phase: phases[0], isDryRun: dryRun, shouldUpdateLocal: updateLocal, onNextPhase: () => setPhases(prev => prev.slice(1)), onError: setError }));
28
+ }
29
+ function RenderPhase({ phase, onNextPhase, onError, isDryRun, shouldUpdateLocal, }) {
30
+ switch (phase) {
31
+ case 'init':
32
+ return React.createElement(Text, null, "Loading...");
33
+ case 'tickets':
34
+ return (React.createElement(TicketSync, { phase: phase, onNextPhase: onNextPhase, isDryRun: isDryRun, shouldUpdateLocal: shouldUpdateLocal, onError: onError }));
35
+ case 'specs':
36
+ return (React.createElement(SpecSync, { phase: phase, onNextPhase: onNextPhase, isDryRun: isDryRun, shouldUpdateLocal: shouldUpdateLocal, onError: onError }));
37
+ default:
38
+ return React.createElement(Text, null, "All done!");
39
+ }
40
+ }
41
+ function TicketSync({ onNextPhase, onError, isDryRun, shouldUpdateLocal, }) {
42
+ const { config } = useConfigContext();
43
+ useEffect(() => {
44
+ pullTickets(config, {
45
+ dryRun: isDryRun,
46
+ updateLocal: shouldUpdateLocal,
47
+ }).then(onNextPhase, onError);
48
+ }, [config, isDryRun, shouldUpdateLocal, onNextPhase, onError]);
49
+ return React.createElement(Spinner, { label: "Syncing tickets..." });
50
+ }
51
+ function SpecSync({ onNextPhase, onError, isDryRun, shouldUpdateLocal, }) {
52
+ const { config } = useConfigContext();
53
+ useEffect(() => {
54
+ pullSpecs(config, {
55
+ dryRun: isDryRun,
56
+ updateLocal: shouldUpdateLocal,
57
+ }).then(onNextPhase, onError);
58
+ }, [config, isDryRun, shouldUpdateLocal, onNextPhase, onError]);
59
+ return React.createElement(Spinner, { label: "Syncing specs..." });
60
+ }
61
+ //# sourceMappingURL=pull.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"pull.js","sourceRoot":"","sources":["../../source/commands/pull.tsx"],"names":[],"mappings":"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"}
@@ -0,0 +1,2 @@
1
+ import React from 'react';
2
+ export default function StatusCommand(): React.JSX.Element;