@stacksfinder/mcp-server 1.1.0 → 1.2.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 (94) hide show
  1. package/LICENSE +16 -16
  2. package/README.md +92 -3
  3. package/dist/compatibility/index.d.ts +11 -0
  4. package/dist/compatibility/index.d.ts.map +1 -0
  5. package/dist/compatibility/index.js +13 -0
  6. package/dist/compatibility/index.js.map +1 -0
  7. package/dist/compatibility/rules.d.ts +29 -0
  8. package/dist/compatibility/rules.d.ts.map +1 -0
  9. package/dist/compatibility/rules.js +419 -0
  10. package/dist/compatibility/rules.js.map +1 -0
  11. package/dist/compatibility/scoring.d.ts +54 -0
  12. package/dist/compatibility/scoring.d.ts.map +1 -0
  13. package/dist/compatibility/scoring.js +209 -0
  14. package/dist/compatibility/scoring.js.map +1 -0
  15. package/dist/compatibility/types.d.ts +176 -0
  16. package/dist/compatibility/types.d.ts.map +1 -0
  17. package/dist/compatibility/types.js +26 -0
  18. package/dist/compatibility/types.js.map +1 -0
  19. package/dist/compatibility/utils.d.ts +82 -0
  20. package/dist/compatibility/utils.d.ts.map +1 -0
  21. package/dist/compatibility/utils.js +269 -0
  22. package/dist/compatibility/utils.js.map +1 -0
  23. package/dist/data/357/200/242/357/200/212cp H:bac_/303/240_guigui_v2stack_finderpackagesmcp-serversrcdatacompatibility_matrix.json H:bac_/303/240_guigui_v2stack_finderpackagesmcp-serverdistdata/357/200/242" +226 -0
  24. package/dist/http.d.ts +7 -0
  25. package/dist/http.d.ts.map +1 -0
  26. package/dist/http.js +69 -0
  27. package/dist/http.js.map +1 -0
  28. package/dist/lib/mcp-compatibility/index.d.ts +33 -0
  29. package/dist/lib/mcp-compatibility/index.d.ts.map +1 -0
  30. package/dist/lib/mcp-compatibility/index.js +35 -0
  31. package/dist/lib/mcp-compatibility/index.js.map +1 -0
  32. package/dist/lib/mcp-compatibility/rules.d.ts +29 -0
  33. package/dist/lib/mcp-compatibility/rules.d.ts.map +1 -0
  34. package/dist/lib/mcp-compatibility/rules.js +419 -0
  35. package/dist/lib/mcp-compatibility/rules.js.map +1 -0
  36. package/dist/lib/mcp-compatibility/scoring.d.ts +54 -0
  37. package/dist/lib/mcp-compatibility/scoring.d.ts.map +1 -0
  38. package/dist/lib/mcp-compatibility/scoring.js +209 -0
  39. package/dist/lib/mcp-compatibility/scoring.js.map +1 -0
  40. package/dist/lib/mcp-compatibility/types.d.ts +176 -0
  41. package/dist/lib/mcp-compatibility/types.d.ts.map +1 -0
  42. package/dist/lib/mcp-compatibility/types.js +26 -0
  43. package/dist/lib/mcp-compatibility/types.js.map +1 -0
  44. package/dist/lib/mcp-compatibility/utils.d.ts +82 -0
  45. package/dist/lib/mcp-compatibility/utils.d.ts.map +1 -0
  46. package/dist/lib/mcp-compatibility/utils.js +269 -0
  47. package/dist/lib/mcp-compatibility/utils.js.map +1 -0
  48. package/dist/server.d.ts.map +1 -1
  49. package/dist/server.js +296 -1
  50. package/dist/server.js.map +1 -1
  51. package/dist/tools/check-compatibility.d.ts +43 -0
  52. package/dist/tools/check-compatibility.d.ts.map +1 -0
  53. package/dist/tools/check-compatibility.js +133 -0
  54. package/dist/tools/check-compatibility.js.map +1 -0
  55. package/dist/tools/project-kit/analyze-repo.d.ts +50 -0
  56. package/dist/tools/project-kit/analyze-repo.d.ts.map +1 -0
  57. package/dist/tools/project-kit/analyze-repo.js +456 -0
  58. package/dist/tools/project-kit/analyze-repo.js.map +1 -0
  59. package/dist/tools/project-kit/detect-stack.d.ts +16 -0
  60. package/dist/tools/project-kit/detect-stack.d.ts.map +1 -0
  61. package/dist/tools/project-kit/detect-stack.js +572 -0
  62. package/dist/tools/project-kit/detect-stack.js.map +1 -0
  63. package/dist/tools/project-kit/execute-installation.d.ts +50 -0
  64. package/dist/tools/project-kit/execute-installation.d.ts.map +1 -0
  65. package/dist/tools/project-kit/execute-installation.js +440 -0
  66. package/dist/tools/project-kit/execute-installation.js.map +1 -0
  67. package/dist/tools/project-kit/generate.d.ts +70 -0
  68. package/dist/tools/project-kit/generate.d.ts.map +1 -0
  69. package/dist/tools/project-kit/generate.js +455 -0
  70. package/dist/tools/project-kit/generate.js.map +1 -0
  71. package/dist/tools/project-kit/index.d.ts +18 -0
  72. package/dist/tools/project-kit/index.d.ts.map +1 -0
  73. package/dist/tools/project-kit/index.js +21 -0
  74. package/dist/tools/project-kit/index.js.map +1 -0
  75. package/dist/tools/project-kit/installation-types.d.ts +147 -0
  76. package/dist/tools/project-kit/installation-types.d.ts.map +1 -0
  77. package/dist/tools/project-kit/installation-types.js +491 -0
  78. package/dist/tools/project-kit/installation-types.js.map +1 -0
  79. package/dist/tools/project-kit/match-mcps.d.ts +67 -0
  80. package/dist/tools/project-kit/match-mcps.d.ts.map +1 -0
  81. package/dist/tools/project-kit/match-mcps.js +497 -0
  82. package/dist/tools/project-kit/match-mcps.js.map +1 -0
  83. package/dist/tools/project-kit/prepare-installation.d.ts +54 -0
  84. package/dist/tools/project-kit/prepare-installation.d.ts.map +1 -0
  85. package/dist/tools/project-kit/prepare-installation.js +382 -0
  86. package/dist/tools/project-kit/prepare-installation.js.map +1 -0
  87. package/dist/tools/project-kit/types.d.ts +200 -0
  88. package/dist/tools/project-kit/types.d.ts.map +1 -0
  89. package/dist/tools/project-kit/types.js +76 -0
  90. package/dist/tools/project-kit/types.js.map +1 -0
  91. package/dist/tools/recommend.d.ts.map +1 -1
  92. package/dist/tools/recommend.js +26 -10
  93. package/dist/tools/recommend.js.map +1 -1
  94. package/package.json +8 -3
@@ -0,0 +1,269 @@
1
+ /**
2
+ * MCP Compatibility Utilities
3
+ *
4
+ * Canonical matching utilities for consistent MCP identification.
5
+ */
6
+ /**
7
+ * Aliases map for common MCP name variations.
8
+ * Keys are normalized (lowercase, trimmed), values are canonical IDs.
9
+ */
10
+ export const MCP_ALIASES = {
11
+ // Database MCPs
12
+ supabase: 'supabase-mcp',
13
+ '@supabase/mcp': 'supabase-mcp',
14
+ '@supabase/mcp-server': 'supabase-mcp',
15
+ neon: 'neon-mcp',
16
+ '@neondatabase/mcp': 'neon-mcp',
17
+ '@neondatabase/mcp-server': 'neon-mcp',
18
+ planetscale: 'planetscale-mcp',
19
+ '@planetscale/mcp': 'planetscale-mcp',
20
+ turso: 'turso-mcp',
21
+ '@tursodb/mcp': 'turso-mcp',
22
+ mongodb: 'mongodb-mcp',
23
+ '@mongodb/mcp': 'mongodb-mcp',
24
+ // ORM MCPs
25
+ prisma: 'prisma-mcp',
26
+ '@prisma/mcp': 'prisma-mcp',
27
+ drizzle: 'drizzle-mcp',
28
+ 'drizzle-orm': 'drizzle-mcp',
29
+ typeorm: 'typeorm-mcp',
30
+ // Auth MCPs
31
+ clerk: 'clerk-mcp',
32
+ '@clerk/mcp': 'clerk-mcp',
33
+ auth0: 'auth0-mcp',
34
+ '@auth0/mcp': 'auth0-mcp',
35
+ 'supabase-auth': 'supabase-auth-mcp',
36
+ lucia: 'lucia-mcp',
37
+ // Payments MCPs
38
+ stripe: 'stripe-mcp',
39
+ '@stripe/mcp': 'stripe-mcp',
40
+ paddle: 'paddle-mcp',
41
+ '@paddle/mcp': 'paddle-mcp',
42
+ lemonsqueezy: 'lemonsqueezy-mcp',
43
+ 'lemon-squeezy': 'lemonsqueezy-mcp',
44
+ // Deployment MCPs
45
+ vercel: 'vercel-mcp',
46
+ '@vercel/mcp': 'vercel-mcp',
47
+ netlify: 'netlify-mcp',
48
+ '@netlify/mcp': 'netlify-mcp',
49
+ cloudflare: 'cloudflare-mcp',
50
+ '@cloudflare/mcp': 'cloudflare-mcp',
51
+ railway: 'railway-mcp',
52
+ fly: 'fly-mcp',
53
+ 'fly.io': 'fly-mcp',
54
+ render: 'render-mcp',
55
+ // Storage MCPs
56
+ r2: 'r2-mcp',
57
+ 'cloudflare-r2': 'r2-mcp',
58
+ s3: 's3-mcp',
59
+ 'aws-s3': 's3-mcp',
60
+ uploadthing: 'uploadthing-mcp',
61
+ // Email MCPs
62
+ resend: 'resend-mcp',
63
+ '@resend/mcp': 'resend-mcp',
64
+ sendgrid: 'sendgrid-mcp',
65
+ postmark: 'postmark-mcp',
66
+ // Version Control MCPs
67
+ github: 'github-mcp',
68
+ '@github/mcp': 'github-mcp',
69
+ gitlab: 'gitlab-mcp',
70
+ '@gitlab/mcp': 'gitlab-mcp',
71
+ // AI MCPs
72
+ openai: 'openai-mcp',
73
+ '@openai/mcp': 'openai-mcp',
74
+ anthropic: 'anthropic-mcp',
75
+ '@anthropic/mcp': 'anthropic-mcp',
76
+ perplexity: 'perplexity-mcp',
77
+ context7: 'context7-mcp',
78
+ // Communication MCPs
79
+ slack: 'slack-mcp',
80
+ '@slack/mcp': 'slack-mcp',
81
+ discord: 'discord-mcp',
82
+ telegram: 'telegram-mcp',
83
+ // Monitoring MCPs
84
+ sentry: 'sentry-mcp',
85
+ '@sentry/mcp': 'sentry-mcp',
86
+ datadog: 'datadog-mcp',
87
+ // Testing MCPs
88
+ playwright: 'playwright-mcp',
89
+ '@playwright/mcp': 'playwright-mcp',
90
+ puppeteer: 'puppeteer-mcp',
91
+ // Documentation MCPs
92
+ obsidian: 'obsidian-mcp',
93
+ notion: 'notion-mcp',
94
+ confluence: 'confluence-mcp',
95
+ // General MCPs
96
+ filesystem: 'filesystem-mcp',
97
+ 'sequential-thinking': 'sequential-thinking-mcp',
98
+ 'brave-search': 'brave-search-mcp',
99
+ };
100
+ /**
101
+ * Canonicalize an MCP ID to a consistent format.
102
+ *
103
+ * @param id - The MCP ID to canonicalize (e.g., "supabase", "@supabase/mcp")
104
+ * @returns The canonical ID (e.g., "supabase-mcp")
105
+ */
106
+ export function canonicalizeMcpId(id) {
107
+ const normalized = id.toLowerCase().trim();
108
+ return MCP_ALIASES[normalized] ?? normalized;
109
+ }
110
+ /**
111
+ * Generate a consistent pair key for two MCPs.
112
+ * The key is ordered alphabetically to ensure A/B and B/A produce the same key.
113
+ *
114
+ * @param a - First MCP ID
115
+ * @param b - Second MCP ID
116
+ * @returns Pair key in format "mcpA::mcpB" (alphabetically ordered)
117
+ */
118
+ export function pairKey(a, b) {
119
+ const canonA = canonicalizeMcpId(a);
120
+ const canonB = canonicalizeMcpId(b);
121
+ const [first, second] = [canonA, canonB].sort();
122
+ return `${first}::${second}`;
123
+ }
124
+ /**
125
+ * Rules indexed by pair key for O(1) lookup.
126
+ * Populated by initRulesIndex().
127
+ */
128
+ let RULES_BY_PAIR = new Map();
129
+ /**
130
+ * Initialize the rules index from an array of rules.
131
+ * Must be called before using findRule().
132
+ *
133
+ * @param rules - Array of compatibility rules
134
+ */
135
+ export function initRulesIndex(rules) {
136
+ RULES_BY_PAIR = new Map();
137
+ for (const rule of rules) {
138
+ const key = pairKey(rule.mcpA, rule.mcpB);
139
+ RULES_BY_PAIR.set(key, rule);
140
+ }
141
+ }
142
+ /**
143
+ * Get the rules index (for testing).
144
+ */
145
+ export function getRulesIndex() {
146
+ return RULES_BY_PAIR;
147
+ }
148
+ /**
149
+ * Find a compatibility rule for two MCPs.
150
+ * Order doesn't matter: findRule(A, B) === findRule(B, A)
151
+ *
152
+ * @param a - First MCP ID (can be any alias)
153
+ * @param b - Second MCP ID (can be any alias)
154
+ * @returns The matching rule, or undefined if no rule exists
155
+ */
156
+ export function findRule(a, b) {
157
+ const key = pairKey(a, b);
158
+ return RULES_BY_PAIR.get(key);
159
+ }
160
+ /**
161
+ * Generate all unique pairs from an array of MCPs.
162
+ * Used to check all nC2 combinations.
163
+ *
164
+ * @param mcps - Array of MCP IDs
165
+ * @returns Array of [mcpA, mcpB] pairs
166
+ */
167
+ export function generatePairs(mcps) {
168
+ const pairs = [];
169
+ for (let i = 0; i < mcps.length; i++) {
170
+ for (let j = i + 1; j < mcps.length; j++) {
171
+ pairs.push([mcps[i], mcps[j]]);
172
+ }
173
+ }
174
+ return pairs;
175
+ }
176
+ /**
177
+ * Check all pairs of MCPs for compatibility issues.
178
+ *
179
+ * @param mcps - Array of MCP IDs to check
180
+ * @returns Object with categorized matched rules
181
+ */
182
+ export function checkAllPairs(mcps) {
183
+ const conflicts = [];
184
+ const redundancies = [];
185
+ const synergies = [];
186
+ const conditionals = [];
187
+ const pairs = generatePairs(mcps);
188
+ for (const [a, b] of pairs) {
189
+ const rule = findRule(a, b);
190
+ if (rule) {
191
+ const matched = {
192
+ rule,
193
+ inputA: a,
194
+ inputB: b,
195
+ };
196
+ switch (rule.status) {
197
+ case 'conflict':
198
+ conflicts.push(matched);
199
+ break;
200
+ case 'redundant':
201
+ redundancies.push(matched);
202
+ break;
203
+ case 'synergy':
204
+ synergies.push(matched);
205
+ break;
206
+ case 'conditional':
207
+ conditionals.push(matched);
208
+ break;
209
+ // 'compatible' - no action needed
210
+ }
211
+ }
212
+ }
213
+ return { conflicts, redundancies, synergies, conditionals };
214
+ }
215
+ /**
216
+ * Get suggestions based on synergy rules.
217
+ * If user has MCP A and rule says A+B is a synergy,
218
+ * suggest B if user doesn't have it.
219
+ *
220
+ * @param mcps - Array of installed MCP IDs
221
+ * @param allRules - All compatibility rules
222
+ * @returns Array of suggestions
223
+ */
224
+ export function getSuggestions(mcps, allRules) {
225
+ const suggestions = [];
226
+ const canonicalMcps = new Set(mcps.map(canonicalizeMcpId));
227
+ const suggestedSet = new Set();
228
+ // Find synergy rules where user has one but not the other
229
+ for (const rule of allRules) {
230
+ if (rule.status !== 'synergy')
231
+ continue;
232
+ const hasA = canonicalMcps.has(rule.mcpA);
233
+ const hasB = canonicalMcps.has(rule.mcpB);
234
+ // If user has A but not B
235
+ if (hasA && !hasB && !suggestedSet.has(rule.mcpB)) {
236
+ suggestions.push({
237
+ mcp: rule.mcpB,
238
+ reason: rule.reason,
239
+ basedOn: rule.mcpA,
240
+ });
241
+ suggestedSet.add(rule.mcpB);
242
+ }
243
+ // If user has B but not A
244
+ if (hasB && !hasA && !suggestedSet.has(rule.mcpA)) {
245
+ suggestions.push({
246
+ mcp: rule.mcpA,
247
+ reason: rule.reason,
248
+ basedOn: rule.mcpB,
249
+ });
250
+ suggestedSet.add(rule.mcpA);
251
+ }
252
+ // Check suggestWhenMissing field
253
+ if (rule.suggestWhenMissing && (hasA || hasB)) {
254
+ for (const suggested of rule.suggestWhenMissing) {
255
+ const canonSuggested = canonicalizeMcpId(suggested);
256
+ if (!canonicalMcps.has(canonSuggested) && !suggestedSet.has(canonSuggested)) {
257
+ suggestions.push({
258
+ mcp: canonSuggested,
259
+ reason: `Pairs well with ${hasA ? rule.mcpA : rule.mcpB}`,
260
+ basedOn: hasA ? rule.mcpA : rule.mcpB,
261
+ });
262
+ suggestedSet.add(canonSuggested);
263
+ }
264
+ }
265
+ }
266
+ }
267
+ return suggestions;
268
+ }
269
+ //# sourceMappingURL=utils.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"utils.js","sourceRoot":"","sources":["../../../src/lib/mcp-compatibility/utils.ts"],"names":[],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"server.d.ts","sourceRoot":"","sources":["../src/server.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,yCAAyC,CAAC;AAoDpE;;GAEG;AACH,wBAAgB,YAAY,IAAI,SAAS,CAmbxC"}
1
+ {"version":3,"file":"server.d.ts","sourceRoot":"","sources":["../src/server.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,yCAAyC,CAAC;AAiFpE;;GAEG;AACH,wBAAgB,YAAY,IAAI,SAAS,CAsjBxC"}
package/dist/server.js CHANGED
@@ -9,6 +9,11 @@ import { getBlueprintToolDefinition, executeGetBlueprint, GetBlueprintInputSchem
9
9
  import { recommendStackDemoToolDefinition, executeRecommendStackDemo, RecommendStackDemoInputSchema } from './tools/recommend-demo.js';
10
10
  import { setupApiKeyToolDefinition, executeSetupApiKey, SetupApiKeyInputSchema, listApiKeysToolDefinition, executeListApiKeys, revokeApiKeyToolDefinition, executeRevokeApiKey, RevokeApiKeyInputSchema } from './tools/api-keys.js';
11
11
  import { createAuditToolDefinition, executeCreateAudit, CreateAuditInputSchema, getAuditToolDefinition, executeGetAudit, GetAuditInputSchema, listAuditsToolDefinition, executeListAudits, ListAuditsInputSchema, compareAuditsToolDefinition, executeCompareAudits, CompareAuditsInputSchema, getAuditQuotaToolDefinition, executeGetAuditQuota, getMigrationRecommendationToolDefinition, executeGetMigrationRecommendation, GetMigrationRecommendationInputSchema } from './tools/audit.js';
12
+ import { generateMCPKitTool, generateMCPKit, GenerateMCPKitInputSchema, analyzeRepoMcpsTool, analyzeRepo, AnalyzeRepoMCPsInputSchema, PRIORITIES, PROJECT_TYPES, SCALES } from './tools/project-kit/index.js';
13
+ import { prepareMCPInstallationTool, prepareMCPInstallation } from './tools/project-kit/prepare-installation.js';
14
+ import { executeMCPInstallationTool, executeMCPInstallation } from './tools/project-kit/execute-installation.js';
15
+ import { PrepareMCPInstallationInputSchema, ExecuteMCPInstallationInputSchema } from './tools/project-kit/installation-types.js';
16
+ import { checkCompatibilityToolDefinition, executeCheckCompatibility, CheckCompatibilityInputSchema } from './tools/check-compatibility.js';
12
17
  import { info, debug } from './utils/logger.js';
13
18
  /**
14
19
  * Create and configure the MCP server.
@@ -356,7 +361,297 @@ export function createServer() {
356
361
  isError
357
362
  };
358
363
  });
359
- info('Registered 16 tools: list_technologies, analyze_tech, compare_techs, recommend_stack_demo, recommend_stack, get_blueprint, create_blueprint, setup_api_key, list_api_keys, revoke_api_key, create_audit, get_audit, list_audits, compare_audits, get_audit_quota, get_migration_recommendation');
364
+ // ========================================================================
365
+ // PROJECT-KIT TOOLS (MCPFinder)
366
+ // ========================================================================
367
+ // Register generate_mcp_kit tool (local, no API key required)
368
+ server.registerTool(generateMCPKitTool.name, {
369
+ title: 'Generate MCP Kit',
370
+ description: generateMCPKitTool.description,
371
+ inputSchema: {
372
+ projectDescription: z.string().min(50).max(5000).describe('Describe your project (50-5000 chars)'),
373
+ priorities: z.array(z.enum(PRIORITIES)).max(3).optional().describe('Top priorities (max 3)'),
374
+ constraints: z.array(z.string()).optional().describe('Tech constraints (e.g., must-use-postgresql)'),
375
+ projectType: z.enum(PROJECT_TYPES).optional().describe('Project type (if known)'),
376
+ scale: z.enum(SCALES).optional().describe('Project scale (if known)')
377
+ }
378
+ }, async (args) => {
379
+ debug('generate_mcp_kit called', args);
380
+ const input = GenerateMCPKitInputSchema.parse(args);
381
+ const result = generateMCPKit(input);
382
+ return {
383
+ content: [{ type: 'text', text: JSON.stringify(result, null, 2) }]
384
+ };
385
+ });
386
+ // Register analyze_repo_mcps tool (local, no API key required)
387
+ server.registerTool(analyzeRepoMcpsTool.name, {
388
+ title: 'Analyze Repository MCPs',
389
+ description: analyzeRepoMcpsTool.description,
390
+ inputSchema: {
391
+ includeInstalled: z.boolean().optional().describe('Include already installed MCPs (default: false)'),
392
+ mcpConfigPath: z.string().optional().describe('Override path to MCP configuration file'),
393
+ workspaceRoot: z.string().optional().describe('Override workspace root directory (default: current directory)')
394
+ }
395
+ }, async (args) => {
396
+ debug('analyze_repo_mcps called', args);
397
+ const input = AnalyzeRepoMCPsInputSchema.parse(args);
398
+ const result = await analyzeRepo(input);
399
+ // Format as markdown for better readability
400
+ return {
401
+ content: [{ type: 'text', text: formatAnalysisResult(result) }]
402
+ };
403
+ });
404
+ // Register prepare_mcp_installation tool (local, no API key required)
405
+ server.registerTool(prepareMCPInstallationTool.name, {
406
+ title: 'Prepare MCP Installation',
407
+ description: prepareMCPInstallationTool.description,
408
+ inputSchema: {
409
+ workspaceRoot: z.string().optional().describe('Workspace root directory (default: current directory)'),
410
+ mcpConfigPath: z.string().optional().describe('Override path to existing MCP configuration file'),
411
+ includeInstalled: z.boolean().optional().describe('Include already installed MCPs in the preparation (default: false)'),
412
+ envMcpPath: z.string().optional().describe('Path where .env-mcp will be created (default: .env-mcp in workspaceRoot)')
413
+ }
414
+ }, async (args) => {
415
+ debug('prepare_mcp_installation called', args);
416
+ const input = PrepareMCPInstallationInputSchema.parse(args);
417
+ const result = await prepareMCPInstallation(input);
418
+ return {
419
+ content: [{ type: 'text', text: result.message + '\n\n' + formatPreparationSummary(result) }]
420
+ };
421
+ });
422
+ // Register execute_mcp_installation tool (local, no API key required)
423
+ server.registerTool(executeMCPInstallationTool.name, {
424
+ title: 'Execute MCP Installation',
425
+ description: executeMCPInstallationTool.description,
426
+ inputSchema: {
427
+ envMcpPath: z.string().optional().describe('Path to .env-mcp file (default: .env-mcp in current directory)'),
428
+ targetClient: z
429
+ .enum(['claude-code', 'claude-desktop', 'cursor', 'vscode', 'windsurf'])
430
+ .optional()
431
+ .describe('Target IDE/client for installation (default: claude-code)'),
432
+ dryRun: z.boolean().optional().describe('Only generate commands without marking ready to execute (default: false)')
433
+ }
434
+ }, async (args) => {
435
+ debug('execute_mcp_installation called', args);
436
+ const input = ExecuteMCPInstallationInputSchema.parse(args);
437
+ const result = await executeMCPInstallation(input);
438
+ return {
439
+ content: [{ type: 'text', text: formatExecutionResult(result) }]
440
+ };
441
+ });
442
+ // ========================================================================
443
+ // COMPATIBILITY TOOL (MCP Conflict Detection)
444
+ // ========================================================================
445
+ // Register check_mcp_compatibility tool (local, no API key required)
446
+ server.registerTool(checkCompatibilityToolDefinition.name, {
447
+ title: 'Check MCP Compatibility',
448
+ description: checkCompatibilityToolDefinition.description,
449
+ inputSchema: {
450
+ mcps: z
451
+ .array(z.string().min(1))
452
+ .min(1)
453
+ .max(20)
454
+ .describe('Array of MCP server IDs to check compatibility between')
455
+ }
456
+ }, async (args) => {
457
+ debug('check_mcp_compatibility called', args);
458
+ const input = CheckCompatibilityInputSchema.parse(args);
459
+ const { text, data, isError } = executeCheckCompatibility(input);
460
+ return {
461
+ content: [
462
+ { type: 'text', text },
463
+ { type: 'text', text: `\n---\n\n**Structured Data:**\n\`\`\`json\n${JSON.stringify(data, null, 2)}\n\`\`\`` }
464
+ ],
465
+ isError
466
+ };
467
+ });
468
+ info('Registered 21 tools: list_technologies, analyze_tech, compare_techs, recommend_stack_demo, recommend_stack, get_blueprint, create_blueprint, setup_api_key, list_api_keys, revoke_api_key, create_audit, get_audit, list_audits, compare_audits, get_audit_quota, get_migration_recommendation, generate_mcp_kit, analyze_repo_mcps, prepare_mcp_installation, execute_mcp_installation, check_mcp_compatibility');
360
469
  return server;
361
470
  }
471
+ // ============================================================================
472
+ // HELPER FUNCTIONS
473
+ // ============================================================================
474
+ /**
475
+ * Format analyze_repo_mcps result as readable markdown.
476
+ */
477
+ function formatAnalysisResult(result) {
478
+ const lines = [];
479
+ lines.push('# Repository Analysis\n');
480
+ // Detected Stack
481
+ lines.push('## Detected Technologies\n');
482
+ const stackItems = [
483
+ result.detectedStack.frontend &&
484
+ `- **Frontend**: ${result.detectedStack.frontend.name}${result.detectedStack.frontend.version ? ` (${result.detectedStack.frontend.version})` : ''}`,
485
+ result.detectedStack.backend &&
486
+ `- **Backend**: ${result.detectedStack.backend.name}${result.detectedStack.backend.version ? ` (${result.detectedStack.backend.version})` : ''}`,
487
+ result.detectedStack.database &&
488
+ `- **Database**: ${result.detectedStack.database.name}${result.detectedStack.database.version ? ` (${result.detectedStack.database.version})` : ''}`,
489
+ result.detectedStack.orm &&
490
+ `- **ORM**: ${result.detectedStack.orm.name}${result.detectedStack.orm.version ? ` (${result.detectedStack.orm.version})` : ''}`,
491
+ result.detectedStack.auth &&
492
+ `- **Auth**: ${result.detectedStack.auth.name}${result.detectedStack.auth.version ? ` (${result.detectedStack.auth.version})` : ''}`,
493
+ result.detectedStack.hosting &&
494
+ `- **Hosting**: ${result.detectedStack.hosting.name}${result.detectedStack.hosting.version ? ` (${result.detectedStack.hosting.version})` : ''}`,
495
+ result.detectedStack.payments &&
496
+ `- **Payments**: ${result.detectedStack.payments.name}${result.detectedStack.payments.version ? ` (${result.detectedStack.payments.version})` : ''}`
497
+ ].filter((item) => Boolean(item));
498
+ if (stackItems.length > 0) {
499
+ lines.push(...stackItems);
500
+ }
501
+ else {
502
+ lines.push('_No technologies detected from project files._');
503
+ }
504
+ if (result.detectedStack.services.length > 0) {
505
+ lines.push('\n**Services**:');
506
+ for (const service of result.detectedStack.services) {
507
+ lines.push(`- ${service.name}`);
508
+ }
509
+ }
510
+ lines.push('');
511
+ // Files Analyzed
512
+ lines.push('## Files Analyzed\n');
513
+ if (result.metadata.filesAnalyzed.length > 0) {
514
+ lines.push(result.metadata.filesAnalyzed.map((f) => `- \`${f}\``).join('\n'));
515
+ }
516
+ else {
517
+ lines.push('_No recognized configuration files found._');
518
+ }
519
+ lines.push('');
520
+ // Installed MCPs
521
+ if (result.installedMcps.length > 0) {
522
+ lines.push('## Already Installed MCPs\n');
523
+ lines.push(result.installedMcps.map((m) => `- ${m}`).join('\n'));
524
+ lines.push('');
525
+ }
526
+ // Recommended MCPs
527
+ lines.push('## Recommended MCPs\n');
528
+ if (result.recommendedMcps.length === 0) {
529
+ lines.push('_No additional MCPs recommended. You have everything you need!_');
530
+ }
531
+ else {
532
+ // Group by priority
533
+ const highPriority = result.recommendedMcps.filter((m) => m.priority === 'high');
534
+ const mediumPriority = result.recommendedMcps.filter((m) => m.priority === 'medium');
535
+ const lowPriority = result.recommendedMcps.filter((m) => m.priority === 'low');
536
+ if (highPriority.length > 0) {
537
+ lines.push('### High Priority\n');
538
+ for (const mcp of highPriority) {
539
+ lines.push(`**${mcp.name}** (\`${mcp.slug}\`)`);
540
+ lines.push(`- ${mcp.description}`);
541
+ lines.push(`- _Matched: ${mcp.matchedTech}_`);
542
+ lines.push('');
543
+ }
544
+ }
545
+ if (mediumPriority.length > 0) {
546
+ lines.push('### Medium Priority\n');
547
+ for (const mcp of mediumPriority) {
548
+ lines.push(`**${mcp.name}** (\`${mcp.slug}\`)`);
549
+ lines.push(`- ${mcp.description}`);
550
+ lines.push(`- _Matched: ${mcp.matchedTech}_`);
551
+ lines.push('');
552
+ }
553
+ }
554
+ if (lowPriority.length > 0) {
555
+ lines.push('### Low Priority\n');
556
+ for (const mcp of lowPriority) {
557
+ lines.push(`**${mcp.name}** (\`${mcp.slug}\`)`);
558
+ lines.push(`- ${mcp.description}`);
559
+ lines.push(`- _Matched: ${mcp.matchedTech}_`);
560
+ lines.push('');
561
+ }
562
+ }
563
+ }
564
+ // Quick Install
565
+ if (result.recommendedMcps.length > 0) {
566
+ lines.push('## Quick Install\n');
567
+ lines.push('Add to your Claude Desktop config (`claude_desktop_config.json`):\n');
568
+ lines.push('```json');
569
+ lines.push(JSON.stringify(result.installConfig.claudeDesktop, null, 2));
570
+ lines.push('```\n');
571
+ }
572
+ // Metadata
573
+ lines.push(`---\n_Analysis completed: ${result.metadata.analysisDate}_`);
574
+ return lines.join('\n');
575
+ }
576
+ /**
577
+ * Format prepare_mcp_installation result summary.
578
+ */
579
+ function formatPreparationSummary(result) {
580
+ const lines = [];
581
+ // MCPs to install grouped by priority
582
+ if (result.mcpsToInstall.length > 0) {
583
+ lines.push('## MCPs to Install\n');
584
+ const highPriority = result.mcpsToInstall.filter((m) => m.priority === 'high');
585
+ const mediumPriority = result.mcpsToInstall.filter((m) => m.priority === 'medium');
586
+ const lowPriority = result.mcpsToInstall.filter((m) => m.priority === 'low');
587
+ if (highPriority.length > 0) {
588
+ lines.push('### 🔴 High Priority');
589
+ for (const mcp of highPriority) {
590
+ const requiredVars = mcp.envVars.filter((v) => v.requirement === 'required').length;
591
+ lines.push(`- **${mcp.name}** (${requiredVars} required vars)`);
592
+ }
593
+ lines.push('');
594
+ }
595
+ if (mediumPriority.length > 0) {
596
+ lines.push('### 🟡 Medium Priority');
597
+ for (const mcp of mediumPriority) {
598
+ const requiredVars = mcp.envVars.filter((v) => v.requirement === 'required').length;
599
+ lines.push(`- **${mcp.name}** (${requiredVars} required vars)`);
600
+ }
601
+ lines.push('');
602
+ }
603
+ if (lowPriority.length > 0) {
604
+ lines.push('### 🟢 Low Priority');
605
+ for (const mcp of lowPriority) {
606
+ const requiredVars = mcp.envVars.filter((v) => v.requirement === 'required').length;
607
+ lines.push(`- **${mcp.name}** (${requiredVars} required vars)`);
608
+ }
609
+ lines.push('');
610
+ }
611
+ }
612
+ // Already installed
613
+ if (result.installedMcps.length > 0) {
614
+ lines.push('## Already Installed');
615
+ for (const mcp of result.installedMcps) {
616
+ lines.push(`- ✅ ${mcp}`);
617
+ }
618
+ lines.push('');
619
+ }
620
+ return lines.join('\n');
621
+ }
622
+ /**
623
+ * Format execute_mcp_installation result.
624
+ */
625
+ function formatExecutionResult(result) {
626
+ const lines = [];
627
+ lines.push(result.message);
628
+ lines.push('');
629
+ // Show aggregate command for Claude Code
630
+ if (result.aggregateCommand) {
631
+ lines.push('---\n');
632
+ lines.push('## Claude Code Installation\n');
633
+ lines.push('Run this command to install all ready MCPs:\n');
634
+ lines.push('```bash');
635
+ lines.push(result.aggregateCommand);
636
+ lines.push('```\n');
637
+ }
638
+ // Show JSON config for other clients
639
+ if (result.aggregateConfig && !result.aggregateCommand) {
640
+ lines.push('---\n');
641
+ lines.push('## JSON Configuration\n');
642
+ lines.push('Add this to your MCP configuration file:\n');
643
+ lines.push('```json');
644
+ lines.push(JSON.stringify(result.aggregateConfig, null, 2));
645
+ lines.push('```\n');
646
+ }
647
+ // Post-install instructions
648
+ if (result.postInstallInstructions.length > 0) {
649
+ lines.push('---\n');
650
+ lines.push('## Post-Installation\n');
651
+ for (const instruction of result.postInstallInstructions) {
652
+ lines.push(instruction);
653
+ }
654
+ }
655
+ return lines.join('\n');
656
+ }
362
657
  //# sourceMappingURL=server.js.map