@specverse/engines 4.1.5 → 4.1.6

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 (120) hide show
  1. package/dist/libs/instance-factories/applications/templates/generic/backend-env-generator.js +22 -0
  2. package/dist/libs/instance-factories/applications/templates/generic/backend-package-json-generator.js +66 -0
  3. package/dist/libs/instance-factories/applications/templates/generic/backend-tsconfig-generator.js +54 -0
  4. package/dist/libs/instance-factories/applications/templates/generic/main-generator.js +290 -0
  5. package/dist/libs/instance-factories/applications/templates/react/_view-components-source.js +530 -0
  6. package/dist/libs/instance-factories/applications/templates/react/api-client-generator.js +437 -0
  7. package/dist/libs/instance-factories/applications/templates/react/api-types-generator.js +146 -0
  8. package/dist/libs/instance-factories/applications/templates/react/app-tsx-generator.js +73 -0
  9. package/dist/libs/instance-factories/applications/templates/react/env-example-generator.js +18 -0
  10. package/dist/libs/instance-factories/applications/templates/react/field-helpers-generator.js +99 -0
  11. package/dist/libs/instance-factories/applications/templates/react/gitignore-generator.js +35 -0
  12. package/dist/libs/instance-factories/applications/templates/react/index-css-generator.js +9 -0
  13. package/dist/libs/instance-factories/applications/templates/react/index-html-generator.js +23 -0
  14. package/dist/libs/instance-factories/applications/templates/react/main-tsx-generator.js +29 -0
  15. package/dist/libs/instance-factories/applications/templates/react/package-json-generator.js +49 -0
  16. package/dist/libs/instance-factories/applications/templates/react/pattern-adapter-generator.js +156 -0
  17. package/dist/libs/instance-factories/applications/templates/react/react-pattern-adapter.js +935 -0
  18. package/dist/libs/instance-factories/applications/templates/react/relationship-field-generator.js +143 -0
  19. package/dist/libs/instance-factories/applications/templates/react/runtime-app-tsx-generator.js +101 -0
  20. package/dist/libs/instance-factories/applications/templates/react/runtime-package-json-generator.js +50 -0
  21. package/dist/libs/instance-factories/applications/templates/react/tailwind-adapter-generator.js +646 -0
  22. package/dist/libs/instance-factories/applications/templates/react/tailwind-adapter-wrapper-generator.js +65 -0
  23. package/dist/libs/instance-factories/applications/templates/react/tsconfig-generator.js +28 -0
  24. package/dist/libs/instance-factories/applications/templates/react/use-api-hooks-generator.js +132 -0
  25. package/dist/libs/instance-factories/applications/templates/react/view-dashboard-generator.js +143 -0
  26. package/dist/libs/instance-factories/applications/templates/react/view-detail-generator.js +143 -0
  27. package/dist/libs/instance-factories/applications/templates/react/view-form-generator.js +355 -0
  28. package/dist/libs/instance-factories/applications/templates/react/view-list-generator.js +91 -0
  29. package/dist/libs/instance-factories/applications/templates/react/view-router-generator.js +79 -0
  30. package/dist/libs/instance-factories/applications/templates/react/vite-config-generator.js +42 -0
  31. package/dist/libs/instance-factories/cli/templates/commander/cli-bin-wrapper-generator.js +11 -0
  32. package/dist/libs/instance-factories/cli/templates/commander/cli-entry-generator.js +111 -0
  33. package/dist/libs/instance-factories/cli/templates/commander/command-generator.js +928 -0
  34. package/dist/libs/instance-factories/communication/templates/eventemitter/bus-generator.js +83 -0
  35. package/dist/libs/instance-factories/communication/templates/eventemitter/publisher-generator.js +91 -0
  36. package/dist/libs/instance-factories/communication/templates/eventemitter/subscriber-generator.js +86 -0
  37. package/dist/libs/instance-factories/controllers/templates/fastify/meta-routes-generator.js +93 -0
  38. package/dist/libs/instance-factories/controllers/templates/fastify/routes-generator.js +280 -0
  39. package/dist/libs/instance-factories/controllers/templates/fastify/server-generator.js +125 -0
  40. package/dist/libs/instance-factories/infrastructure/templates/docker-k8s/infrastructure-generator.js +25 -0
  41. package/dist/libs/instance-factories/orms/templates/prisma/schema-generator.js +371 -0
  42. package/dist/libs/instance-factories/orms/templates/prisma/services-generator.js +266 -0
  43. package/dist/libs/instance-factories/scaffolding/templates/generic/env-example-generator.js +51 -0
  44. package/dist/libs/instance-factories/scaffolding/templates/generic/env-generator.js +61 -0
  45. package/dist/libs/instance-factories/scaffolding/templates/generic/gitignore-generator.js +59 -0
  46. package/dist/libs/instance-factories/scaffolding/templates/generic/package-json-generator.js +126 -0
  47. package/dist/libs/instance-factories/scaffolding/templates/generic/readme-generator.js +159 -0
  48. package/dist/libs/instance-factories/scaffolding/templates/generic/tsconfig-generator.js +56 -0
  49. package/dist/libs/instance-factories/scaffolding/templates/generic/tsconfig-react-generator.js +37 -0
  50. package/dist/libs/instance-factories/sdks/templates/python/sdk-generator.js +29 -0
  51. package/dist/libs/instance-factories/sdks/templates/typescript/sdk-generator.js +28 -0
  52. package/dist/libs/instance-factories/services/templates/memory/generate-interpreter.js +14 -0
  53. package/dist/libs/instance-factories/services/templates/memory/step-conventions-memory.js +415 -0
  54. package/dist/libs/instance-factories/services/templates/prisma/behavior-generator.js +177 -0
  55. package/dist/libs/instance-factories/services/templates/prisma/controller-generator.js +413 -0
  56. package/dist/libs/instance-factories/services/templates/prisma/service-generator.js +243 -0
  57. package/dist/libs/instance-factories/services/templates/prisma/step-conventions.js +264 -0
  58. package/dist/libs/instance-factories/services/templates/shared-patterns.js +24 -0
  59. package/dist/libs/instance-factories/shared/path-resolver.js +59 -0
  60. package/dist/libs/instance-factories/storage/templates/mongodb/config-generator.js +13 -0
  61. package/dist/libs/instance-factories/storage/templates/mongodb/docker-generator.js +16 -0
  62. package/dist/libs/instance-factories/storage/templates/postgresql/config-generator.js +45 -0
  63. package/dist/libs/instance-factories/storage/templates/postgresql/docker-generator.js +46 -0
  64. package/dist/libs/instance-factories/storage/templates/redis/config-generator.js +14 -0
  65. package/dist/libs/instance-factories/storage/templates/redis/docker-generator.js +16 -0
  66. package/dist/libs/instance-factories/test-generation.js +145 -0
  67. package/dist/libs/instance-factories/testing/templates/vitest/tests-generator.js +30 -0
  68. package/dist/libs/instance-factories/tools/templates/mcp/mcp-server-generator.js +149 -0
  69. package/dist/libs/instance-factories/tools/templates/mcp/static/src/controllers/MCPServerController.js +232 -0
  70. package/dist/libs/instance-factories/tools/templates/mcp/static/src/events/EventEmitter.js +49 -0
  71. package/dist/libs/instance-factories/tools/templates/mcp/static/src/index.js +18 -0
  72. package/dist/libs/instance-factories/tools/templates/mcp/static/src/interfaces/ResourceProvider.js +0 -0
  73. package/dist/libs/instance-factories/tools/templates/mcp/static/src/models/LibrarySuggestion.js +97 -0
  74. package/dist/libs/instance-factories/tools/templates/mcp/static/src/models/SpecVerseResource.js +64 -0
  75. package/dist/libs/instance-factories/tools/templates/mcp/static/src/server/mcp-server.js +182 -0
  76. package/dist/libs/instance-factories/tools/templates/mcp/static/src/services/CLIProxyService.js +1210 -0
  77. package/dist/libs/instance-factories/tools/templates/mcp/static/src/services/EmbeddedResourcesAdapter.js +172 -0
  78. package/dist/libs/instance-factories/tools/templates/mcp/static/src/services/EntityModuleService.js +240 -0
  79. package/dist/libs/instance-factories/tools/templates/mcp/static/src/services/HybridResourcesProvider.js +147 -0
  80. package/dist/libs/instance-factories/tools/templates/mcp/static/src/services/LibraryToolsService.js +281 -0
  81. package/dist/libs/instance-factories/tools/templates/mcp/static/src/services/OrchestratorBridge.js +409 -0
  82. package/dist/libs/instance-factories/tools/templates/mcp/static/src/services/OrchestratorToolsService.js +414 -0
  83. package/dist/libs/instance-factories/tools/templates/mcp/static/src/services/PromptToolsService.js +467 -0
  84. package/dist/libs/instance-factories/tools/templates/mcp/static/src/services/ResourcesProviderService.js +135 -0
  85. package/dist/libs/instance-factories/tools/templates/mcp/static/src/types/index.js +0 -0
  86. package/dist/libs/instance-factories/tools/templates/vscode/static/extension.js +965 -0
  87. package/dist/libs/instance-factories/tools/templates/vscode/vscode-extension-generator.js +238 -0
  88. package/dist/libs/instance-factories/validation/templates/zod/validation-generator.js +25 -0
  89. package/dist/libs/instance-factories/views/index.js +48 -0
  90. package/dist/libs/instance-factories/views/templates/react/adapters/antd-adapter.js +742 -0
  91. package/dist/libs/instance-factories/views/templates/react/adapters/mui-adapter.js +824 -0
  92. package/dist/libs/instance-factories/views/templates/react/adapters/shadcn-adapter.js +719 -0
  93. package/dist/libs/instance-factories/views/templates/react/app-generator.js +45 -0
  94. package/dist/libs/instance-factories/views/templates/react/components-generator.js +779 -0
  95. package/dist/libs/instance-factories/views/templates/react/forms-generator.js +285 -0
  96. package/dist/libs/instance-factories/views/templates/react/frontend-package-json-generator.js +46 -0
  97. package/dist/libs/instance-factories/views/templates/react/hooks-generator.js +111 -0
  98. package/dist/libs/instance-factories/views/templates/react/index-css-generator.js +9 -0
  99. package/dist/libs/instance-factories/views/templates/react/index-html-generator.js +23 -0
  100. package/dist/libs/instance-factories/views/templates/react/main-tsx-generator.js +21 -0
  101. package/dist/libs/instance-factories/views/templates/react/react-component-generator.js +299 -0
  102. package/dist/libs/instance-factories/views/templates/react/router-generator.js +136 -0
  103. package/dist/libs/instance-factories/views/templates/react/router-generic-generator.js +107 -0
  104. package/dist/libs/instance-factories/views/templates/react/shared-utils-generator.js +179 -0
  105. package/dist/libs/instance-factories/views/templates/react/spec-json-generator.js +7 -0
  106. package/dist/libs/instance-factories/views/templates/react/types-generator.js +56 -0
  107. package/dist/libs/instance-factories/views/templates/react/views-metadata-generator.js +27 -0
  108. package/dist/libs/instance-factories/views/templates/react/vite-config-generator.js +29 -0
  109. package/dist/libs/instance-factories/views/templates/runtime/runtime-view-renderer.js +261 -0
  110. package/dist/libs/instance-factories/views/templates/shared/adapter-types.js +34 -0
  111. package/dist/libs/instance-factories/views/templates/shared/atomic-components-registry.js +800 -0
  112. package/dist/libs/instance-factories/views/templates/shared/base-generator.js +305 -0
  113. package/dist/libs/instance-factories/views/templates/shared/component-metadata.js +517 -0
  114. package/dist/libs/instance-factories/views/templates/shared/composite-pattern-types.js +0 -0
  115. package/dist/libs/instance-factories/views/templates/shared/composite-patterns.js +445 -0
  116. package/dist/libs/instance-factories/views/templates/shared/index.js +80 -0
  117. package/dist/libs/instance-factories/views/templates/shared/pattern-validator.js +210 -0
  118. package/dist/libs/instance-factories/views/templates/shared/property-mapper.js +492 -0
  119. package/dist/libs/instance-factories/views/templates/shared/syntax-mapper.js +321 -0
  120. package/package.json +3 -2
@@ -0,0 +1,1210 @@
1
+ async function loadSpecVerseAPI() {
2
+ const { createRequire } = await import("module");
3
+ const { fileURLToPath } = await import("url");
4
+ const { join: join2, dirname } = await import("path");
5
+ const require2 = createRequire(import.meta.url);
6
+ const publishedPackage = "@specverse/engine-entities";
7
+ const __filename = fileURLToPath(import.meta.url);
8
+ const __dirname = dirname(__filename);
9
+ const isInDist = __dirname.includes("/dist/");
10
+ const levelsUp = isInDist ? 5 : 4;
11
+ const pathParts = Array(levelsUp).fill("..").concat(["dist", "index.js"]);
12
+ const localPath = join2(__dirname, ...pathParts);
13
+ try {
14
+ return await import(localPath);
15
+ } catch (localError) {
16
+ try {
17
+ require2.resolve(publishedPackage);
18
+ return await import(publishedPackage);
19
+ } catch (publishedError) {
20
+ throw new Error(`Failed to load SpecVerse API: local (${localError.message}) and published (${publishedError.message})`);
21
+ }
22
+ }
23
+ }
24
+ let specverseAPI = null;
25
+ import { writeFileSync, unlinkSync, mkdtempSync } from "fs";
26
+ import { join } from "path";
27
+ import { tmpdir } from "os";
28
+ class CLIProxyService {
29
+ constructor(workingDirectory) {
30
+ this.workingDirectory = workingDirectory;
31
+ }
32
+ capabilities = null;
33
+ cliPath = null;
34
+ lastDiscovery = 0;
35
+ DISCOVERY_CACHE_TTL = 5 * 60 * 1e3;
36
+ // 5 minutes
37
+ initialized = false;
38
+ /**
39
+ * Initialize the API - called once before first use
40
+ */
41
+ async init() {
42
+ if (this.initialized) return;
43
+ specverseAPI = await loadSpecVerseAPI();
44
+ this.cliPath = specverseAPI.getCliPath(this.workingDirectory);
45
+ if (!this.cliPath && process.env.MCP_DEBUG) {
46
+ console.error("\u26A0\uFE0F SpecVerse CLI not found. CLI proxy functionality will be limited.");
47
+ }
48
+ this.initialized = true;
49
+ }
50
+ /**
51
+ * Discover CLI capabilities (cached for performance)
52
+ */
53
+ async discoverCapabilities() {
54
+ await this.init();
55
+ const now = Date.now();
56
+ if (this.capabilities && now - this.lastDiscovery < this.DISCOVERY_CACHE_TTL) {
57
+ return this.capabilities;
58
+ }
59
+ try {
60
+ this.capabilities = specverseAPI.getAllCliCapabilities(this.cliPath || void 0);
61
+ this.lastDiscovery = now;
62
+ if (process.env.MCP_DEBUG) {
63
+ console.error(`\u{1F50D} Discovered ${this.capabilities.coreCommands.length} core commands, ${this.capabilities.groupedCommands.length} grouped commands, ${this.capabilities.aiCommands.length} AI commands`);
64
+ }
65
+ return this.capabilities;
66
+ } catch (error) {
67
+ if (process.env.MCP_DEBUG) {
68
+ console.error("\u274C Failed to discover CLI capabilities:", error);
69
+ }
70
+ return {
71
+ coreCommands: [],
72
+ groupedCommands: [],
73
+ aiCommands: []
74
+ };
75
+ }
76
+ }
77
+ /**
78
+ * Generate MCP tool definitions from CLI capabilities
79
+ */
80
+ async generateMCPTools() {
81
+ const capabilities = await this.discoverCapabilities();
82
+ const tools = [];
83
+ tools.push({
84
+ name: "specverse_mcp_debug",
85
+ description: "Show MCP server diagnostic information including SpecVerse installation details, path resolution, and environment analysis",
86
+ inputSchema: {
87
+ type: "object",
88
+ properties: {
89
+ verbose: {
90
+ type: "boolean",
91
+ description: "Show detailed path resolution information"
92
+ }
93
+ },
94
+ required: []
95
+ }
96
+ });
97
+ for (const cmd of capabilities.coreCommands) {
98
+ tools.push(this.createMCPToolFromCommand(cmd));
99
+ }
100
+ for (const cmd of capabilities.groupedCommands) {
101
+ tools.push(this.createMCPToolFromGroupedCommand(cmd));
102
+ }
103
+ for (const cmd of capabilities.aiCommands) {
104
+ tools.push(...this.createAIMCPTools());
105
+ break;
106
+ }
107
+ tools.push(...this.createContentBasedTools());
108
+ return tools;
109
+ }
110
+ /**
111
+ * Execute a CLI command via the proxy
112
+ */
113
+ async executeCommand(toolName, args) {
114
+ try {
115
+ await this.init();
116
+ if (toolName === "specverse_mcp_debug") {
117
+ return await this.executeMCPDebugTool(args.verbose || false);
118
+ }
119
+ if (!this.cliPath) {
120
+ return {
121
+ content: [{
122
+ type: "text",
123
+ text: "SpecVerse CLI not found. Please ensure SpecVerse is installed and accessible."
124
+ }],
125
+ isError: true
126
+ };
127
+ }
128
+ if (toolName.endsWith("_content")) {
129
+ return await this.handleContentBasedCommand(toolName, args);
130
+ }
131
+ const baseCommand = this.mapToolNameToCommand(toolName);
132
+ let command = baseCommand;
133
+ let commandArgs = { ...args };
134
+ if (baseCommand.startsWith("ai ") && args.operation) {
135
+ command = `${baseCommand} ${args.operation}`;
136
+ const { operation, ...remainingArgs } = args;
137
+ commandArgs = remainingArgs;
138
+ } else if (baseCommand.startsWith("lib ")) {
139
+ if (baseCommand === "lib search" && args.query) {
140
+ command = `${baseCommand} "${args.query}"`;
141
+ const { query, ...remainingArgs } = args;
142
+ commandArgs = remainingArgs;
143
+ } else if (baseCommand === "lib info" && args.name) {
144
+ command = `${baseCommand} "${args.name}"`;
145
+ const { name, ...remainingArgs } = args;
146
+ commandArgs = remainingArgs;
147
+ }
148
+ } else if (baseCommand === "init") {
149
+ console.error(`MCP Debug: Received args.name: "${args.name}"`);
150
+ console.error(`MCP Debug: Full args object:`, JSON.stringify(args, null, 2));
151
+ if (args.name) {
152
+ const fullPath = args.name;
153
+ const projectName = args.name.includes("/") ? args.name.split("/").pop() : args.name;
154
+ command = `${baseCommand} "${projectName}"`;
155
+ const { name, ...remainingArgs } = args;
156
+ commandArgs = { ...remainingArgs, fullPath };
157
+ }
158
+ try {
159
+ const result2 = await this.executeInitCommand(command, commandArgs);
160
+ return {
161
+ content: [{
162
+ type: "text",
163
+ text: JSON.stringify(result2, null, 2)
164
+ }]
165
+ };
166
+ } catch (error) {
167
+ const errorMessage = error instanceof Error ? error.message : String(error);
168
+ return {
169
+ content: [{
170
+ type: "text",
171
+ text: JSON.stringify({
172
+ status: "error",
173
+ message: "Init command failed",
174
+ details: errorMessage,
175
+ timestamp: (/* @__PURE__ */ new Date()).toISOString()
176
+ }, null, 2)
177
+ }],
178
+ isError: true
179
+ };
180
+ }
181
+ } else if (args.file) {
182
+ command = `${baseCommand} "${args.file}"`;
183
+ const { file, ...remainingArgs } = args;
184
+ commandArgs = remainingArgs;
185
+ }
186
+ const result = await specverseAPI.executeCliCommand(command, commandArgs, {
187
+ cliPath: this.cliPath,
188
+ timeout: 6e4
189
+ // 1 minute timeout
190
+ });
191
+ return {
192
+ content: [{
193
+ type: "text",
194
+ text: JSON.stringify(result, null, 2)
195
+ }]
196
+ };
197
+ } catch (error) {
198
+ const errorMessage = error instanceof Error ? error.message : String(error);
199
+ try {
200
+ const parsedError = JSON.parse(errorMessage);
201
+ return {
202
+ content: [{
203
+ type: "text",
204
+ text: JSON.stringify(parsedError, null, 2)
205
+ }],
206
+ isError: true
207
+ };
208
+ } catch {
209
+ return {
210
+ content: [{
211
+ type: "text",
212
+ text: JSON.stringify({
213
+ status: "error",
214
+ message: "CLI command execution failed",
215
+ details: errorMessage,
216
+ timestamp: (/* @__PURE__ */ new Date()).toISOString()
217
+ }, null, 2)
218
+ }],
219
+ isError: true
220
+ };
221
+ }
222
+ }
223
+ }
224
+ /**
225
+ * Create MCP tool definition from core CLI command
226
+ */
227
+ createMCPToolFromCommand(cmd) {
228
+ const properties = {};
229
+ const required = [];
230
+ if (cmd.args) {
231
+ if (cmd.args.includes("<file>")) {
232
+ properties.file = {
233
+ type: "string",
234
+ description: "SpecVerse specification file path"
235
+ };
236
+ required.push("file");
237
+ }
238
+ if (cmd.args.includes("[name]")) {
239
+ properties.name = {
240
+ type: "string",
241
+ description: "Project name (optional)"
242
+ };
243
+ }
244
+ }
245
+ if (cmd.command === "init") {
246
+ properties.name = {
247
+ type: "string",
248
+ description: "Project name"
249
+ };
250
+ properties.template = {
251
+ type: "string",
252
+ description: 'Template to use (default: "default")'
253
+ };
254
+ properties.zip = {
255
+ type: "boolean",
256
+ description: "Return project as ZIP file"
257
+ };
258
+ properties.json = {
259
+ type: "boolean",
260
+ description: "Return project as JSON file structure"
261
+ };
262
+ } else if (cmd.command === "validate" || cmd.command === "infer") {
263
+ properties.verbose = {
264
+ type: "boolean",
265
+ description: "Show detailed output"
266
+ };
267
+ }
268
+ if (this.isFileGeneratingCommand(cmd.command)) {
269
+ properties.zip = {
270
+ type: "boolean",
271
+ description: "Return files as ZIP package instead of creating locally (useful for remote servers or consistent delivery)"
272
+ };
273
+ }
274
+ return {
275
+ name: `specverse_${cmd.command}`,
276
+ description: cmd.description,
277
+ inputSchema: {
278
+ type: "object",
279
+ properties,
280
+ required
281
+ }
282
+ };
283
+ }
284
+ /**
285
+ * Check if a command generates files that could benefit from ZIP packaging
286
+ */
287
+ isFileGeneratingCommand(command) {
288
+ return ["init"].includes(command);
289
+ }
290
+ /**
291
+ * Check if a grouped command generates files that could benefit from ZIP packaging
292
+ */
293
+ isFileGeneratingGroupedCommand(cmd) {
294
+ if (cmd.group === "gen") {
295
+ return true;
296
+ }
297
+ return false;
298
+ }
299
+ /**
300
+ * Create MCP tool definition from grouped command
301
+ */
302
+ createMCPToolFromGroupedCommand(cmd) {
303
+ const properties = {};
304
+ const required = [];
305
+ if (cmd.args?.includes("<file>")) {
306
+ properties.file = {
307
+ type: "string",
308
+ description: "SpecVerse specification file path"
309
+ };
310
+ required.push("file");
311
+ }
312
+ if (cmd.group === "gen") {
313
+ properties.output = {
314
+ type: "string",
315
+ description: "Output file or directory path"
316
+ };
317
+ } else if (cmd.group === "dev" && cmd.subcommand === "watch") {
318
+ properties.directory = {
319
+ type: "string",
320
+ description: "Directory to watch for changes"
321
+ };
322
+ } else if (cmd.group === "lib") {
323
+ if (cmd.subcommand === "search") {
324
+ if (cmd.args?.includes("[query]")) {
325
+ properties.query = {
326
+ type: "string",
327
+ description: "Search term (name, description, tags)"
328
+ };
329
+ }
330
+ properties.type = {
331
+ type: "string",
332
+ enum: ["component", "deployment", "manifest"],
333
+ description: "Filter by type"
334
+ };
335
+ properties.category = {
336
+ type: "string",
337
+ description: "Filter by category"
338
+ };
339
+ properties.tags = {
340
+ type: "string",
341
+ description: "Filter by tags (comma-separated: auth,jwt,session)"
342
+ };
343
+ properties.limit = {
344
+ type: "number",
345
+ description: "Results limit (default: 20)"
346
+ };
347
+ properties.format = {
348
+ type: "string",
349
+ enum: ["table", "json"],
350
+ description: "Output format (default: table)"
351
+ };
352
+ } else if (cmd.subcommand === "info") {
353
+ if (cmd.args?.includes("<name>")) {
354
+ properties.name = {
355
+ type: "string",
356
+ description: "Library name"
357
+ };
358
+ required.push("name");
359
+ }
360
+ properties.version = {
361
+ type: "string",
362
+ description: "Specific version (default: latest)"
363
+ };
364
+ properties.format = {
365
+ type: "string",
366
+ enum: ["table", "json"],
367
+ description: "Output format (default: table)"
368
+ };
369
+ properties.content = {
370
+ type: "boolean",
371
+ description: "Show library content"
372
+ };
373
+ } else if (cmd.subcommand === "list") {
374
+ properties.cached = {
375
+ type: "boolean",
376
+ description: "Show locally cached libraries"
377
+ };
378
+ properties.used = {
379
+ type: "boolean",
380
+ description: "Show libraries used in current project"
381
+ };
382
+ properties.format = {
383
+ type: "string",
384
+ enum: ["table", "json"],
385
+ description: "Output format (default: table)"
386
+ };
387
+ } else if (cmd.subcommand === "tags") {
388
+ properties.format = {
389
+ type: "string",
390
+ enum: ["table", "json"],
391
+ description: "Output format (default: table)"
392
+ };
393
+ }
394
+ }
395
+ if (this.isFileGeneratingGroupedCommand(cmd)) {
396
+ properties.zip = {
397
+ type: "boolean",
398
+ description: "Return files as ZIP package instead of creating locally (useful for remote servers or consistent delivery)"
399
+ };
400
+ }
401
+ return {
402
+ name: `specverse_${cmd.command.replace(/\s+/g, "_")}`,
403
+ description: cmd.description,
404
+ inputSchema: {
405
+ type: "object",
406
+ properties,
407
+ required
408
+ }
409
+ };
410
+ }
411
+ /**
412
+ * Create MCP tools for AI commands
413
+ */
414
+ createAIMCPTools() {
415
+ return [
416
+ {
417
+ name: "specverse_ai_template",
418
+ description: "Get AI prompt templates for SpecVerse operations",
419
+ inputSchema: {
420
+ type: "object",
421
+ properties: {
422
+ operation: {
423
+ type: "string",
424
+ enum: ["analyse", "create", "materialise", "realize"],
425
+ description: "AI operation type"
426
+ },
427
+ pver: {
428
+ type: "string",
429
+ description: "Prompt version (v1|v2|v3|v4|v5|v6|v7) (default: v1)"
430
+ },
431
+ output: {
432
+ type: "string",
433
+ description: "Output file path"
434
+ },
435
+ copy: {
436
+ type: "boolean",
437
+ description: "Copy result to clipboard"
438
+ }
439
+ },
440
+ required: ["operation"]
441
+ }
442
+ },
443
+ {
444
+ name: "specverse_ai_fill",
445
+ description: "Fill AI prompt templates with requirements",
446
+ inputSchema: {
447
+ type: "object",
448
+ properties: {
449
+ operation: {
450
+ type: "string",
451
+ enum: ["analyse", "create", "materialise", "realize"],
452
+ description: "AI operation type"
453
+ },
454
+ requirements: {
455
+ type: "string",
456
+ description: "Project requirements"
457
+ },
458
+ scale: {
459
+ type: "string",
460
+ enum: ["personal", "business", "enterprise"],
461
+ description: "Project scale (default: business)"
462
+ },
463
+ framework: {
464
+ type: "string",
465
+ description: "Framework preference"
466
+ },
467
+ domain: {
468
+ type: "string",
469
+ description: "Project domain"
470
+ },
471
+ compliance: {
472
+ type: "string",
473
+ description: "Compliance requirements (comma-separated)"
474
+ },
475
+ tech: {
476
+ type: "string",
477
+ description: "Technology preferences (comma-separated)"
478
+ },
479
+ pver: {
480
+ type: "string",
481
+ description: "Prompt version (v1|v2|v3|v4|v5|v6|v7) (default: v1)"
482
+ },
483
+ output: {
484
+ type: "string",
485
+ description: "Output file path"
486
+ },
487
+ copy: {
488
+ type: "boolean",
489
+ description: "Copy result to clipboard"
490
+ }
491
+ },
492
+ required: ["operation", "requirements"]
493
+ }
494
+ },
495
+ {
496
+ name: "specverse_ai_suggest",
497
+ description: "Get AI library suggestions for project requirements",
498
+ inputSchema: {
499
+ type: "object",
500
+ properties: {
501
+ requirements: {
502
+ type: "string",
503
+ description: "Project requirements"
504
+ },
505
+ domain: {
506
+ type: "string",
507
+ description: "Project domain"
508
+ },
509
+ scale: {
510
+ type: "string",
511
+ enum: ["personal", "business", "enterprise"],
512
+ default: "business",
513
+ description: "Project scale"
514
+ }
515
+ },
516
+ required: ["requirements"]
517
+ }
518
+ },
519
+ {
520
+ name: "specverse_ai_enhance",
521
+ description: "Get enhanced AI prompts with library context (BEST)",
522
+ inputSchema: {
523
+ type: "object",
524
+ properties: {
525
+ operation: {
526
+ type: "string",
527
+ enum: ["analyse", "create", "materialise", "realize"],
528
+ description: "AI operation type"
529
+ },
530
+ requirements: {
531
+ type: "string",
532
+ description: "Project requirements"
533
+ },
534
+ scale: {
535
+ type: "string",
536
+ enum: ["personal", "business", "enterprise"],
537
+ description: "Project scale (default: business)"
538
+ },
539
+ framework: {
540
+ type: "string",
541
+ description: "Framework preference"
542
+ },
543
+ domain: {
544
+ type: "string",
545
+ description: "Project domain"
546
+ },
547
+ compliance: {
548
+ type: "string",
549
+ description: "Compliance requirements (comma-separated)"
550
+ },
551
+ tech: {
552
+ type: "string",
553
+ description: "Technology preferences (comma-separated)"
554
+ },
555
+ pver: {
556
+ type: "string",
557
+ description: "Prompt version (v1|v2|v3|v4|v5|v6|v7) (default: v1)"
558
+ },
559
+ output: {
560
+ type: "string",
561
+ description: "Output file path"
562
+ },
563
+ copy: {
564
+ type: "boolean",
565
+ description: "Copy result to clipboard"
566
+ }
567
+ },
568
+ required: ["operation", "requirements"]
569
+ }
570
+ }
571
+ ];
572
+ }
573
+ /**
574
+ * Create content-based tools for direct LLM interaction
575
+ */
576
+ createContentBasedTools() {
577
+ return [
578
+ {
579
+ name: "specverse_validate_content",
580
+ description: "Validate SpecVerse specification content directly (no file required)",
581
+ inputSchema: {
582
+ type: "object",
583
+ properties: {
584
+ content: {
585
+ type: "string",
586
+ description: "SpecVerse specification content (.specly format)"
587
+ },
588
+ filename: {
589
+ type: "string",
590
+ description: "Optional filename for error reporting (default: temp.specly)"
591
+ },
592
+ verbose: {
593
+ type: "boolean",
594
+ description: "Show detailed validation results"
595
+ }
596
+ },
597
+ required: ["content"]
598
+ }
599
+ },
600
+ {
601
+ name: "specverse_infer_content",
602
+ description: "Generate complete specification from content using AI inference",
603
+ inputSchema: {
604
+ type: "object",
605
+ properties: {
606
+ content: {
607
+ type: "string",
608
+ description: "Minimal SpecVerse specification content (.specly format)"
609
+ },
610
+ filename: {
611
+ type: "string",
612
+ description: "Optional filename (default: temp.specly)"
613
+ },
614
+ controllers: {
615
+ type: "boolean",
616
+ description: "Generate controllers (default: true)"
617
+ },
618
+ services: {
619
+ type: "boolean",
620
+ description: "Generate services (default: true)"
621
+ },
622
+ events: {
623
+ type: "boolean",
624
+ description: "Generate events (default: true)"
625
+ },
626
+ views: {
627
+ type: "boolean",
628
+ description: "Generate views (default: true)"
629
+ },
630
+ deployment: {
631
+ type: "boolean",
632
+ description: "Generate deployment specification (default: false)"
633
+ },
634
+ environment: {
635
+ type: "string",
636
+ enum: ["development", "staging", "production"],
637
+ description: "Target environment for deployment"
638
+ },
639
+ verbose: {
640
+ type: "boolean",
641
+ description: "Show detailed inference process"
642
+ }
643
+ },
644
+ required: ["content"]
645
+ }
646
+ },
647
+ {
648
+ name: "specverse_gen_yaml_content",
649
+ description: "Generate YAML from SpecVerse specification content",
650
+ inputSchema: {
651
+ type: "object",
652
+ properties: {
653
+ content: {
654
+ type: "string",
655
+ description: "SpecVerse specification content (.specly format)"
656
+ },
657
+ filename: {
658
+ type: "string",
659
+ description: "Optional filename (default: temp.specly)"
660
+ }
661
+ },
662
+ required: ["content"]
663
+ }
664
+ }
665
+ ];
666
+ }
667
+ /**
668
+ * Handle content-based commands by creating temporary files
669
+ */
670
+ async handleContentBasedCommand(toolName, args) {
671
+ const { content, filename = "temp.specly", ...otherArgs } = args;
672
+ if (!content) {
673
+ return {
674
+ content: [{
675
+ type: "text",
676
+ text: JSON.stringify({
677
+ status: "error",
678
+ message: "Content is required for content-based commands",
679
+ timestamp: (/* @__PURE__ */ new Date()).toISOString()
680
+ }, null, 2)
681
+ }],
682
+ isError: true
683
+ };
684
+ }
685
+ let tempDir;
686
+ let tempFile;
687
+ try {
688
+ tempDir = mkdtempSync(join(tmpdir(), "specverse-mcp-"));
689
+ tempFile = join(tempDir, filename);
690
+ writeFileSync(tempFile, content, "utf8");
691
+ const cliCommand = this.mapContentToolToCommand(toolName);
692
+ const result = await specverseAPI.executeCliCommand(`${cliCommand} "${tempFile}"`, otherArgs, {
693
+ cliPath: this.cliPath,
694
+ timeout: 6e4
695
+ });
696
+ return {
697
+ content: [{
698
+ type: "text",
699
+ text: JSON.stringify(result, null, 2)
700
+ }]
701
+ };
702
+ } catch (error) {
703
+ const errorMessage = error instanceof Error ? error.message : String(error);
704
+ try {
705
+ const parsedError = JSON.parse(errorMessage);
706
+ return {
707
+ content: [{
708
+ type: "text",
709
+ text: JSON.stringify(parsedError, null, 2)
710
+ }],
711
+ isError: true
712
+ };
713
+ } catch {
714
+ return {
715
+ content: [{
716
+ type: "text",
717
+ text: JSON.stringify({
718
+ status: "error",
719
+ message: "Content-based command execution failed",
720
+ details: errorMessage,
721
+ timestamp: (/* @__PURE__ */ new Date()).toISOString()
722
+ }, null, 2)
723
+ }],
724
+ isError: true
725
+ };
726
+ }
727
+ } finally {
728
+ try {
729
+ if (tempFile) unlinkSync(tempFile);
730
+ } catch {
731
+ }
732
+ }
733
+ }
734
+ /**
735
+ * Map content-based tool names to CLI commands
736
+ */
737
+ mapContentToolToCommand(toolName) {
738
+ const mapping = {
739
+ "specverse_validate_content": "validate",
740
+ "specverse_infer_content": "infer",
741
+ "specverse_gen_yaml_content": "gen yaml"
742
+ };
743
+ return mapping[toolName] || toolName.replace(/^specverse_/, "").replace(/_content$/, "").replace(/_/g, " ");
744
+ }
745
+ /**
746
+ * Check if we're running in a remote environment where local file creation won't work
747
+ */
748
+ async isRemoteEnvironment() {
749
+ if (process.env.MCP_FORCE_LOCAL === "true") {
750
+ return false;
751
+ }
752
+ return (
753
+ // Vercel/Netlify/similar serverless
754
+ process.env.VERCEL === "1" || process.env.NETLIFY === "true" || process.env.AWS_LAMBDA_FUNCTION_NAME !== void 0 || // Web deployment mode indicators
755
+ process.env.NODE_ENV === "production" && (process.env.PORT !== void 0 || process.env.HOST !== void 0) || // Environment explicitly marked as remote
756
+ process.env.MCP_REMOTE === "true" || // Detect if we can't write to current directory (more reliable than just checking root)
757
+ await this.isDirectoryReadOnly()
758
+ );
759
+ }
760
+ /**
761
+ * Check if we should use remote environment detection specifically for root directory
762
+ * Only triggers if running from root AND no full paths are provided
763
+ */
764
+ isProblematicRootEnvironment(args) {
765
+ if (process.cwd() !== "/") {
766
+ return false;
767
+ }
768
+ const hasFullPaths = args.name && args.name.startsWith("/") || // /full/path/project
769
+ args.file && args.file.startsWith("/") || // /full/path/file.specly
770
+ args.output && args.output.startsWith("/") || // /full/path/output
771
+ args.directory && args.directory.startsWith("/");
772
+ if (hasFullPaths) {
773
+ return false;
774
+ }
775
+ const hasRelativeName = args.name && !args.name.startsWith("/");
776
+ return hasRelativeName;
777
+ }
778
+ /**
779
+ * Check if current directory is read-only
780
+ */
781
+ async isDirectoryReadOnly() {
782
+ try {
783
+ const { writeFileSync: writeFileSync2, unlinkSync: unlinkSync2 } = await import("fs");
784
+ const testFile = ".mcp-write-test-" + Date.now();
785
+ writeFileSync2(testFile, "test");
786
+ unlinkSync2(testFile);
787
+ return false;
788
+ } catch {
789
+ return true;
790
+ }
791
+ }
792
+ /**
793
+ * Read project files into structured format for direct delivery
794
+ */
795
+ async readProjectFilesStructured(projectPath) {
796
+ const { readdir, readFile, stat } = await import("fs/promises");
797
+ const { join: join2, relative, extname } = await import("path");
798
+ const files = [];
799
+ let totalSize = 0;
800
+ const directories = [];
801
+ const readDirectory = async (dirPath) => {
802
+ const entries = await readdir(dirPath, { withFileTypes: true });
803
+ for (const entry of entries) {
804
+ const fullPath = join2(dirPath, entry.name);
805
+ const relativePath = relative(projectPath, fullPath);
806
+ if (entry.isDirectory()) {
807
+ directories.push(relativePath + "/");
808
+ await readDirectory(fullPath);
809
+ } else if (entry.isFile()) {
810
+ try {
811
+ const content = await readFile(fullPath, "utf8");
812
+ const stats = await stat(fullPath);
813
+ const extension = extname(entry.name).toLowerCase();
814
+ let fileType = "text";
815
+ if (extension === ".js" || extension === ".ts") fileType = "javascript";
816
+ else if (extension === ".py") fileType = "python";
817
+ else if (extension === ".md") fileType = "markdown";
818
+ else if (extension === ".json") fileType = "json";
819
+ else if (extension === ".yaml" || extension === ".yml") fileType = "yaml";
820
+ else if (extension === ".specly") fileType = "specverse";
821
+ else if (extension === ".sh") fileType = "shell";
822
+ else if (extension === ".html") fileType = "html";
823
+ else if (extension === ".css") fileType = "css";
824
+ files.push({
825
+ path: relativePath,
826
+ content,
827
+ type: fileType,
828
+ size: stats.size,
829
+ encoding: "utf-8"
830
+ });
831
+ totalSize += stats.size;
832
+ } catch (error) {
833
+ console.error(`Failed to read file ${fullPath}:`, error);
834
+ }
835
+ }
836
+ }
837
+ };
838
+ await readDirectory(projectPath);
839
+ return {
840
+ files,
841
+ summary: {
842
+ total_files: files.length,
843
+ total_size: totalSize < 1024 ? `${totalSize}B` : totalSize < 1024 * 1024 ? `${(totalSize / 1024).toFixed(1)}KB` : `${(totalSize / 1024 / 1024).toFixed(2)}MB`,
844
+ directories: [...new Set(directories)].sort(),
845
+ file_types: [...new Set(files.map((f) => f.type))].sort()
846
+ }
847
+ };
848
+ }
849
+ /**
850
+ * Package project files into ZIP for remote delivery (DEPRECATED - keeping for fallback)
851
+ */
852
+ async packageProjectFiles(projectPath) {
853
+ const { execSync } = await import("child_process");
854
+ const { readFile, unlink } = await import("fs/promises");
855
+ const { basename, dirname, join: join2 } = await import("path");
856
+ const { tmpdir: tmpdir2 } = await import("os");
857
+ const projectName = basename(projectPath);
858
+ const parentDir = dirname(projectPath);
859
+ const tempZipPath = join2(tmpdir2(), `${projectName}-${Date.now()}.zip`);
860
+ console.error(`MCP Packaging Debug: Project path: ${projectPath}`);
861
+ console.error(`MCP Packaging Debug: Project name: ${projectName}`);
862
+ console.error(`MCP Packaging Debug: Parent dir: ${parentDir}`);
863
+ console.error(`MCP Packaging Debug: Temp ZIP path: ${tempZipPath}`);
864
+ try {
865
+ const zipCommand = `cd "${parentDir}" && zip -r "${tempZipPath}" "${projectName}"`;
866
+ console.error(`MCP Packaging Debug: Running command: ${zipCommand}`);
867
+ execSync(zipCommand, {
868
+ encoding: "utf8",
869
+ stdio: "pipe"
870
+ });
871
+ console.error(`MCP Packaging Debug: ZIP file created successfully`);
872
+ const zipBuffer = await readFile(tempZipPath);
873
+ console.error(`MCP Packaging Debug: ZIP buffer size: ${zipBuffer.length} bytes`);
874
+ console.error(`MCP Packaging Debug: ZIP buffer size: ${(zipBuffer.length / 1024 / 1024).toFixed(2)} MB`);
875
+ const zipData = zipBuffer.toString("base64");
876
+ console.error(`MCP Packaging Debug: Base64 string length: ${zipData.length} chars`);
877
+ await unlink(tempZipPath);
878
+ console.error(`MCP Packaging Debug: Temp file cleaned up`);
879
+ return {
880
+ zipData,
881
+ fileName: `${projectName}.zip`,
882
+ size: zipBuffer.length
883
+ };
884
+ } catch (error) {
885
+ console.error(`MCP Packaging Debug: ZIP command failed, trying fallback:`, error);
886
+ return await this.createZipFallback(projectPath);
887
+ }
888
+ }
889
+ /**
890
+ * Fallback ZIP creation using pure Node.js
891
+ */
892
+ async createZipFallback(projectPath) {
893
+ const { execSync } = await import("child_process");
894
+ const { readFile, unlink } = await import("fs/promises");
895
+ const { basename, dirname, join: join2 } = await import("path");
896
+ const { tmpdir: tmpdir2 } = await import("os");
897
+ const projectName = basename(projectPath);
898
+ const parentDir = dirname(projectPath);
899
+ const tempTarPath = join2(tmpdir2(), `${projectName}-${Date.now()}.tar.gz`);
900
+ try {
901
+ execSync(`cd "${parentDir}" && tar -czf "${tempTarPath}" "${projectName}"`, {
902
+ encoding: "utf8",
903
+ stdio: "pipe"
904
+ });
905
+ const tarBuffer = await readFile(tempTarPath);
906
+ const tarData = tarBuffer.toString("base64");
907
+ await unlink(tempTarPath);
908
+ return {
909
+ zipData: tarData,
910
+ fileName: `${projectName}.tar.gz`,
911
+ size: tarBuffer.length
912
+ };
913
+ } catch (error) {
914
+ throw new Error(`Failed to create project archive: ${error}`);
915
+ }
916
+ }
917
+ /**
918
+ * Execute init command without --json flag (not supported)
919
+ * For remote deployments, returns project files as JSON structure
920
+ */
921
+ async executeInitCommand(command, args) {
922
+ const { execSync } = await import("child_process");
923
+ const argString = Object.entries(args).filter(
924
+ ([key, value]) => value !== void 0 && value !== null && key !== "zip" && // ZIP is handled by MCP service, not CLI
925
+ key !== "local" && // Local is MCP server flag, not CLI flag
926
+ key !== "fullPath" && // fullPath is used internally for directory handling
927
+ key !== "name"
928
+ // name is passed as positional argument, not flag
929
+ ).map(([key, value]) => {
930
+ if (typeof value === "boolean") {
931
+ return value ? `--${key}` : "";
932
+ } else {
933
+ return `--${key} "${value}"`;
934
+ }
935
+ }).filter(Boolean).join(" ");
936
+ const baseCommand = this.cliPath === "specverse" ? "specverse" : `node ${this.cliPath}`;
937
+ const fullCommand = `${baseCommand} ${command} ${argString}`.trim();
938
+ const rawName = args.fullPath || command.match(/"([^"]+)"/)?.[1] || args.name || "project";
939
+ let projectName;
940
+ let targetWorkingDir;
941
+ if (rawName.startsWith("/")) {
942
+ const { dirname, basename } = await import("path");
943
+ projectName = basename(rawName);
944
+ targetWorkingDir = dirname(rawName);
945
+ } else {
946
+ projectName = rawName;
947
+ targetWorkingDir = process.cwd();
948
+ }
949
+ const forceZip = args.zip === true;
950
+ const forceJson = args.json === true;
951
+ console.error(`MCP Init Debug: Working directory: ${process.cwd()}`);
952
+ console.error(`MCP Init Debug: Target working directory: ${targetWorkingDir}`);
953
+ console.error(`MCP Init Debug: Raw name: ${rawName}`);
954
+ console.error(`MCP Init Debug: Project name: ${projectName}`);
955
+ console.error(`MCP Init Debug: Force ZIP: ${forceZip}`);
956
+ console.error(`MCP Init Debug: Force JSON: ${forceJson}`);
957
+ console.error(`MCP Init Debug: Executing command: ${fullCommand}`);
958
+ if (forceZip) {
959
+ console.error(`MCP Init Debug: ZIP requested - will return ZIP file`);
960
+ return await this.executeInitWithZip(fullCommand, projectName, args);
961
+ } else if (forceJson) {
962
+ console.error(`MCP Init Debug: JSON requested - will return JSON structure`);
963
+ return await this.executeInitWithJson(fullCommand, projectName, args);
964
+ } else if (await this.canCreateLocalFiles(projectName, targetWorkingDir)) {
965
+ console.error(`MCP Init Debug: Local filesystem - will create files locally`);
966
+ return await this.executeInitLocal(fullCommand, projectName, targetWorkingDir);
967
+ } else {
968
+ console.error(`MCP Init Debug: Cannot create local files - will return JSON structure`);
969
+ return await this.executeInitWithJson(fullCommand, projectName, args);
970
+ }
971
+ }
972
+ async canCreateLocalFiles(projectName, targetWorkingDir) {
973
+ try {
974
+ const targetDir = targetWorkingDir || await (async () => {
975
+ const cwd = process.cwd();
976
+ if (projectName.startsWith("/")) {
977
+ const { dirname } = await import("path");
978
+ return dirname(projectName);
979
+ } else {
980
+ if (cwd === "/") {
981
+ return null;
982
+ }
983
+ return cwd;
984
+ }
985
+ })();
986
+ if (!targetDir) {
987
+ return false;
988
+ }
989
+ const { writeFileSync: writeFileSync2, unlinkSync: unlinkSync2 } = await import("fs");
990
+ const { join: join2 } = await import("path");
991
+ const testFile = join2(targetDir, ".mcp-write-test-" + Date.now());
992
+ writeFileSync2(testFile, "test");
993
+ unlinkSync2(testFile);
994
+ return true;
995
+ } catch {
996
+ return false;
997
+ }
998
+ }
999
+ async executeInitLocal(fullCommand, projectName, targetWorkingDir) {
1000
+ const { execSync } = await import("child_process");
1001
+ const { join: join2 } = await import("path");
1002
+ const workingDir = targetWorkingDir || process.cwd();
1003
+ try {
1004
+ const result = execSync(fullCommand, {
1005
+ encoding: "utf8",
1006
+ timeout: 3e4,
1007
+ stdio: "pipe",
1008
+ cwd: workingDir
1009
+ });
1010
+ return {
1011
+ status: "success",
1012
+ message: `Project '${projectName}' created successfully`,
1013
+ project_path: join2(workingDir, projectName),
1014
+ delivery_method: "local_filesystem",
1015
+ created: true
1016
+ };
1017
+ } catch (error) {
1018
+ const errorOutput = error.stdout || error.stderr || error.message;
1019
+ throw new Error(`Failed to create project '${projectName}': ${errorOutput}`);
1020
+ }
1021
+ }
1022
+ async executeInitWithZip(fullCommand, projectName, args) {
1023
+ const { execSync } = await import("child_process");
1024
+ const { mkdtemp, rm } = await import("fs/promises");
1025
+ const { tmpdir: tmpdir2 } = await import("os");
1026
+ const { join: join2 } = await import("path");
1027
+ const tempDir = await mkdtemp(join2(tmpdir2(), "specverse-zip-"));
1028
+ try {
1029
+ const result = execSync(fullCommand, {
1030
+ encoding: "utf8",
1031
+ timeout: 3e4,
1032
+ stdio: "pipe",
1033
+ cwd: tempDir
1034
+ });
1035
+ const projectPath = join2(tempDir, projectName);
1036
+ const zipData = await this.packageProjectFiles(projectPath);
1037
+ await rm(tempDir, { recursive: true, force: true });
1038
+ return {
1039
+ status: "success",
1040
+ message: `Project '${projectName}' packaged as ZIP`,
1041
+ delivery_method: "zip_file",
1042
+ zip_data: zipData.zipData,
1043
+ file_name: zipData.fileName,
1044
+ size: zipData.size
1045
+ };
1046
+ } catch (error) {
1047
+ await rm(tempDir, { recursive: true, force: true }).catch(() => {
1048
+ });
1049
+ const errorOutput = error.stdout || error.stderr || error.message;
1050
+ throw new Error(`Failed to create project '${projectName}': ${errorOutput}`);
1051
+ }
1052
+ }
1053
+ async executeInitWithJson(fullCommand, projectName, args) {
1054
+ const { execSync } = await import("child_process");
1055
+ const { mkdtemp, rm } = await import("fs/promises");
1056
+ const { tmpdir: tmpdir2 } = await import("os");
1057
+ const { join: join2 } = await import("path");
1058
+ const tempDir = await mkdtemp(join2(tmpdir2(), "specverse-json-"));
1059
+ try {
1060
+ const result = execSync(fullCommand, {
1061
+ encoding: "utf8",
1062
+ timeout: 3e4,
1063
+ stdio: "pipe",
1064
+ cwd: tempDir
1065
+ });
1066
+ const projectPath = join2(tempDir, projectName);
1067
+ const structuredFiles = await this.readProjectFilesStructured(projectPath);
1068
+ await rm(tempDir, { recursive: true, force: true });
1069
+ return {
1070
+ status: "success",
1071
+ instruction: "create_file_attachments_for_each_file_described_in_files",
1072
+ message: `Project '${projectName}' created successfully`,
1073
+ project: projectName,
1074
+ files: structuredFiles.files,
1075
+ summary: structuredFiles.summary,
1076
+ delivery_method: "json_structure"
1077
+ };
1078
+ } catch (error) {
1079
+ await rm(tempDir, { recursive: true, force: true }).catch(() => {
1080
+ });
1081
+ const errorOutput = error.stdout || error.stderr || error.message;
1082
+ throw new Error(`Failed to create project '${projectName}': ${errorOutput}`);
1083
+ }
1084
+ }
1085
+ /**
1086
+ * Map MCP tool name back to CLI command
1087
+ */
1088
+ mapToolNameToCommand(toolName) {
1089
+ const command = toolName.replace(/^specverse_/, "").replace(/_/g, " ");
1090
+ if (command.startsWith("ai ")) {
1091
+ return command;
1092
+ }
1093
+ return command;
1094
+ }
1095
+ /**
1096
+ * Get MCP package version using Node.js built-in package resolution
1097
+ */
1098
+ async getMCPVersion() {
1099
+ try {
1100
+ const { readFile } = await import("fs/promises");
1101
+ const { join: join2, dirname } = await import("path");
1102
+ const { fileURLToPath } = await import("url");
1103
+ const __filename = fileURLToPath(import.meta.url);
1104
+ const __dirname = dirname(__filename);
1105
+ const packagePaths = [
1106
+ join2(__dirname, "..", "..", "package.json"),
1107
+ // dist/services -> root
1108
+ join2(__dirname, "..", "..", "..", "package.json")
1109
+ // dist/target/services -> root
1110
+ ];
1111
+ for (const packagePath of packagePaths) {
1112
+ try {
1113
+ const content = await readFile(packagePath, "utf8");
1114
+ const packageInfo = JSON.parse(content);
1115
+ if (packageInfo.name === "@specverse/mcp") {
1116
+ return packageInfo.version;
1117
+ }
1118
+ } catch {
1119
+ continue;
1120
+ }
1121
+ }
1122
+ try {
1123
+ const { createRequire } = await import("module");
1124
+ const require2 = createRequire(import.meta.url);
1125
+ const packageInfo = require2("@specverse/mcp/package.json");
1126
+ return packageInfo.version;
1127
+ } catch {
1128
+ try {
1129
+ const packageJsonUrl = import.meta.resolve("@specverse/mcp/package.json");
1130
+ const content = await readFile(new URL(packageJsonUrl), "utf8");
1131
+ const packageInfo = JSON.parse(content);
1132
+ return packageInfo.version;
1133
+ } catch {
1134
+ return process.env.MCP_VERSION || "unknown";
1135
+ }
1136
+ }
1137
+ } catch {
1138
+ return process.env.MCP_VERSION || "unknown";
1139
+ }
1140
+ }
1141
+ /**
1142
+ * Execute MCP-specific debug tool
1143
+ */
1144
+ async executeMCPDebugTool(verbose) {
1145
+ try {
1146
+ const mcpVersion = await this.getMCPVersion();
1147
+ const diagnostics = {
1148
+ timestamp: (/* @__PURE__ */ new Date()).toISOString(),
1149
+ mcp_server: {
1150
+ version: mcpVersion,
1151
+ mode: "diagnostic"
1152
+ }
1153
+ };
1154
+ try {
1155
+ const { resolvePackageRoot } = specverseAPI;
1156
+ const packageRoot = resolvePackageRoot();
1157
+ const { readFile } = await import("fs/promises");
1158
+ const { join: join2 } = await import("path");
1159
+ const packageJsonPath = join2(packageRoot, "package.json");
1160
+ const packageContent = await readFile(packageJsonPath, "utf8");
1161
+ const packageData = JSON.parse(packageContent);
1162
+ diagnostics.specverse_installation = {
1163
+ type: "npm_package",
1164
+ version: packageData.version,
1165
+ location: packageRoot,
1166
+ package_name: packageData.name,
1167
+ status: "found"
1168
+ };
1169
+ } catch (error) {
1170
+ diagnostics.specverse_installation = {
1171
+ status: "error",
1172
+ error: error instanceof Error ? error.message : String(error)
1173
+ };
1174
+ }
1175
+ diagnostics.cli_detection = {
1176
+ cli_path: this.cliPath,
1177
+ working_directory: this.workingDirectory || process.cwd(),
1178
+ status: this.cliPath ? "found" : "not_found"
1179
+ };
1180
+ diagnostics.health_check = {
1181
+ can_import_specverse: !!diagnostics.specverse_installation.version,
1182
+ cli_accessible: !!this.cliPath,
1183
+ capabilities_loaded: !!this.capabilities,
1184
+ overall_status: !!diagnostics.specverse_installation.version && !!this.cliPath ? "healthy" : "degraded"
1185
+ };
1186
+ return {
1187
+ content: [{
1188
+ type: "text",
1189
+ text: JSON.stringify(diagnostics, null, 2)
1190
+ }]
1191
+ };
1192
+ } catch (error) {
1193
+ return {
1194
+ content: [{
1195
+ type: "text",
1196
+ text: JSON.stringify({
1197
+ status: "error",
1198
+ message: "MCP debug tool execution failed",
1199
+ error: error instanceof Error ? error.message : String(error),
1200
+ timestamp: (/* @__PURE__ */ new Date()).toISOString()
1201
+ }, null, 2)
1202
+ }],
1203
+ isError: true
1204
+ };
1205
+ }
1206
+ }
1207
+ }
1208
+ export {
1209
+ CLIProxyService
1210
+ };