@stacksfinder/mcp-server 1.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (65) hide show
  1. package/README.md +262 -0
  2. package/dist/data/compatibility_matrix.json +230 -0
  3. package/dist/data/index.d.ts +109 -0
  4. package/dist/data/index.d.ts.map +1 -0
  5. package/dist/data/index.js +203 -0
  6. package/dist/data/index.js.map +1 -0
  7. package/dist/data/technology_scores.json +1031 -0
  8. 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
  9. package/dist/index.d.ts +3 -0
  10. package/dist/index.d.ts.map +1 -0
  11. package/dist/index.js +50 -0
  12. package/dist/index.js.map +1 -0
  13. package/dist/server.d.ts +6 -0
  14. package/dist/server.d.ts.map +1 -0
  15. package/dist/server.js +254 -0
  16. package/dist/server.js.map +1 -0
  17. package/dist/tools/analyze.d.ts +45 -0
  18. package/dist/tools/analyze.d.ts.map +1 -0
  19. package/dist/tools/analyze.js +110 -0
  20. package/dist/tools/analyze.js.map +1 -0
  21. package/dist/tools/api-keys.d.ts +78 -0
  22. package/dist/tools/api-keys.d.ts.map +1 -0
  23. package/dist/tools/api-keys.js +238 -0
  24. package/dist/tools/api-keys.js.map +1 -0
  25. package/dist/tools/blueprint.d.ts +129 -0
  26. package/dist/tools/blueprint.d.ts.map +1 -0
  27. package/dist/tools/blueprint.js +320 -0
  28. package/dist/tools/blueprint.js.map +1 -0
  29. package/dist/tools/compare.d.ts +50 -0
  30. package/dist/tools/compare.d.ts.map +1 -0
  31. package/dist/tools/compare.js +168 -0
  32. package/dist/tools/compare.js.map +1 -0
  33. package/dist/tools/list-techs.d.ts +34 -0
  34. package/dist/tools/list-techs.d.ts.map +1 -0
  35. package/dist/tools/list-techs.js +70 -0
  36. package/dist/tools/list-techs.js.map +1 -0
  37. package/dist/tools/recommend-demo.d.ts +46 -0
  38. package/dist/tools/recommend-demo.d.ts.map +1 -0
  39. package/dist/tools/recommend-demo.js +202 -0
  40. package/dist/tools/recommend-demo.js.map +1 -0
  41. package/dist/tools/recommend.d.ts +68 -0
  42. package/dist/tools/recommend.d.ts.map +1 -0
  43. package/dist/tools/recommend.js +135 -0
  44. package/dist/tools/recommend.js.map +1 -0
  45. package/dist/utils/api-client.d.ts +80 -0
  46. package/dist/utils/api-client.d.ts.map +1 -0
  47. package/dist/utils/api-client.js +197 -0
  48. package/dist/utils/api-client.js.map +1 -0
  49. package/dist/utils/config.d.ts +35 -0
  50. package/dist/utils/config.d.ts.map +1 -0
  51. package/dist/utils/config.js +45 -0
  52. package/dist/utils/config.js.map +1 -0
  53. package/dist/utils/device-id.d.ts +21 -0
  54. package/dist/utils/device-id.d.ts.map +1 -0
  55. package/dist/utils/device-id.js +101 -0
  56. package/dist/utils/device-id.js.map +1 -0
  57. package/dist/utils/errors.d.ts +46 -0
  58. package/dist/utils/errors.d.ts.map +1 -0
  59. package/dist/utils/errors.js +125 -0
  60. package/dist/utils/errors.js.map +1 -0
  61. package/dist/utils/logger.d.ts +37 -0
  62. package/dist/utils/logger.d.ts.map +1 -0
  63. package/dist/utils/logger.js +73 -0
  64. package/dist/utils/logger.js.map +1 -0
  65. package/package.json +63 -0
@@ -0,0 +1,320 @@
1
+ import { z } from 'zod';
2
+ import { getBlueprintRequest, createBlueprintRequest, getJobStatusRequest } from '../utils/api-client.js';
3
+ import { McpError, ErrorCode } from '../utils/errors.js';
4
+ import { debug } from '../utils/logger.js';
5
+ /**
6
+ * Input schema for get_blueprint tool.
7
+ */
8
+ export const GetBlueprintInputSchema = z.object({
9
+ blueprintId: z.string().uuid().describe('Blueprint UUID')
10
+ });
11
+ /**
12
+ * Tool definition for MCP registration.
13
+ */
14
+ export const getBlueprintToolDefinition = {
15
+ name: 'get_blueprint',
16
+ description: 'Fetches an existing blueprint by ID. Blueprints are generated via the StacksFinder web UI. Requires API key.',
17
+ inputSchema: {
18
+ type: 'object',
19
+ properties: {
20
+ blueprintId: {
21
+ type: 'string',
22
+ format: 'uuid',
23
+ description: 'Blueprint UUID'
24
+ }
25
+ },
26
+ required: ['blueprintId']
27
+ }
28
+ };
29
+ /**
30
+ * Format blueprint for MCP output.
31
+ */
32
+ function formatBlueprint(blueprint) {
33
+ const projectName = blueprint.projectContext?.projectName || 'Unnamed Project';
34
+ const projectType = blueprint.projectContext?.projectType || 'Unknown';
35
+ const scale = blueprint.projectContext?.scale || 'mvp';
36
+ const createdDate = new Date(blueprint.createdAt).toLocaleDateString('en-US', {
37
+ year: 'numeric',
38
+ month: 'long',
39
+ day: 'numeric'
40
+ });
41
+ let text = `## Blueprint: ${projectName}
42
+
43
+ **ID**: ${blueprint.id}
44
+ **Type**: ${projectType}
45
+ **Scale**: ${scale}
46
+ **Created**: ${createdDate}
47
+
48
+ ### Selected Stack
49
+ | Category | Technology |
50
+ |----------|------------|
51
+ `;
52
+ for (const tech of blueprint.selectedTechs) {
53
+ text += `| ${tech.category} | ${tech.technology} |\n`;
54
+ }
55
+ if (blueprint.narrative) {
56
+ text += `
57
+ ### Narrative
58
+ ${blueprint.narrative}`;
59
+ }
60
+ return text;
61
+ }
62
+ /**
63
+ * Execute get_blueprint tool.
64
+ */
65
+ export async function executeGetBlueprint(input) {
66
+ const { blueprintId } = input;
67
+ debug('Fetching blueprint', { blueprintId });
68
+ try {
69
+ const response = await getBlueprintRequest(blueprintId);
70
+ const text = formatBlueprint(response);
71
+ return { text };
72
+ }
73
+ catch (err) {
74
+ if (err instanceof McpError) {
75
+ // Add helpful suggestion for NOT_FOUND
76
+ if (err.code === ErrorCode.NOT_FOUND) {
77
+ err.suggestions = [
78
+ 'Blueprints are generated via the StacksFinder web UI.',
79
+ 'Visit https://stacksfinder.com to create a new blueprint.'
80
+ ];
81
+ }
82
+ return { text: err.toResponseText(), isError: true };
83
+ }
84
+ const error = new McpError(ErrorCode.API_ERROR, err instanceof Error ? err.message : 'Failed to fetch blueprint');
85
+ return { text: error.toResponseText(), isError: true };
86
+ }
87
+ }
88
+ // ============================================================================
89
+ // CREATE BLUEPRINT TOOL
90
+ // ============================================================================
91
+ /**
92
+ * Valid project types for blueprint creation.
93
+ */
94
+ const PROJECT_TYPES = [
95
+ 'web-app',
96
+ 'mobile-app',
97
+ 'api',
98
+ 'desktop',
99
+ 'cli',
100
+ 'library',
101
+ 'e-commerce',
102
+ 'saas',
103
+ 'marketplace'
104
+ ];
105
+ /**
106
+ * Valid scales for blueprint creation.
107
+ */
108
+ const SCALES = ['mvp', 'startup', 'growth', 'enterprise'];
109
+ /**
110
+ * Valid priorities for blueprint creation.
111
+ */
112
+ const PRIORITIES = [
113
+ 'time-to-market',
114
+ 'scalability',
115
+ 'developer-experience',
116
+ 'cost-efficiency',
117
+ 'performance',
118
+ 'security',
119
+ 'maintainability'
120
+ ];
121
+ /**
122
+ * Input schema for create_blueprint tool.
123
+ */
124
+ export const CreateBlueprintInputSchema = z.object({
125
+ projectName: z.string().min(1).max(100).optional().describe('Project name (optional)'),
126
+ projectType: z
127
+ .enum(PROJECT_TYPES)
128
+ .describe('Type of project (e.g., web-app, saas, api)'),
129
+ scale: z.enum(SCALES).describe('Project scale (mvp, startup, growth, enterprise)'),
130
+ projectDescription: z
131
+ .string()
132
+ .max(2000)
133
+ .optional()
134
+ .describe('Brief project description (optional)'),
135
+ priorities: z
136
+ .array(z.enum(PRIORITIES))
137
+ .max(3)
138
+ .optional()
139
+ .describe('Top 3 priorities (optional)'),
140
+ constraints: z
141
+ .array(z.string())
142
+ .max(20)
143
+ .optional()
144
+ .describe('Technology constraint IDs (optional)'),
145
+ waitForCompletion: z
146
+ .boolean()
147
+ .optional()
148
+ .default(true)
149
+ .describe('Wait for blueprint generation to complete (default: true)')
150
+ });
151
+ /**
152
+ * Tool definition for MCP registration.
153
+ */
154
+ export const createBlueprintToolDefinition = {
155
+ name: 'create_blueprint',
156
+ description: `Creates a new tech stack blueprint for a project. Requires API key with 'blueprint:write' scope.
157
+
158
+ The blueprint generation is asynchronous. By default, this tool waits for completion and returns the full blueprint.
159
+ Set waitForCompletion=false to get the job ID immediately for manual polling.
160
+
161
+ Example usage:
162
+ - Create a SaaS MVP: projectType="saas", scale="mvp", priorities=["time-to-market", "cost-efficiency"]
163
+ - Create an enterprise API: projectType="api", scale="enterprise", priorities=["security", "scalability"]`,
164
+ inputSchema: {
165
+ type: 'object',
166
+ properties: {
167
+ projectName: {
168
+ type: 'string',
169
+ description: 'Project name (optional)',
170
+ maxLength: 100
171
+ },
172
+ projectType: {
173
+ type: 'string',
174
+ enum: PROJECT_TYPES,
175
+ description: 'Type of project'
176
+ },
177
+ scale: {
178
+ type: 'string',
179
+ enum: SCALES,
180
+ description: 'Project scale'
181
+ },
182
+ projectDescription: {
183
+ type: 'string',
184
+ description: 'Brief project description (optional)',
185
+ maxLength: 2000
186
+ },
187
+ priorities: {
188
+ type: 'array',
189
+ items: { type: 'string', enum: PRIORITIES },
190
+ maxItems: 3,
191
+ description: 'Top 3 priorities (optional)'
192
+ },
193
+ constraints: {
194
+ type: 'array',
195
+ items: { type: 'string' },
196
+ maxItems: 20,
197
+ description: 'Technology constraint IDs (optional)'
198
+ },
199
+ waitForCompletion: {
200
+ type: 'boolean',
201
+ description: 'Wait for blueprint generation to complete (default: true)',
202
+ default: true
203
+ }
204
+ },
205
+ required: ['projectType', 'scale']
206
+ }
207
+ };
208
+ /**
209
+ * Poll job status until completion or failure.
210
+ */
211
+ async function pollJobUntilComplete(jobId, maxAttempts = 30, intervalMs = 2000) {
212
+ for (let attempt = 0; attempt < maxAttempts; attempt++) {
213
+ const status = await getJobStatusRequest(jobId);
214
+ if (status.status === 'completed') {
215
+ return status;
216
+ }
217
+ if (status.status === 'failed' || status.status === 'cancelled') {
218
+ throw new McpError(ErrorCode.API_ERROR, status.errorMessage || `Job ${status.status}: ${status.errorCode || 'Unknown error'}`);
219
+ }
220
+ // Wait before next poll
221
+ await new Promise((resolve) => setTimeout(resolve, intervalMs));
222
+ }
223
+ throw new McpError(ErrorCode.TIMEOUT, `Blueprint generation timed out after ${(maxAttempts * intervalMs) / 1000} seconds`, ['The job is still running. Use get_blueprint with the job resultRef to check later.']);
224
+ }
225
+ /**
226
+ * Execute create_blueprint tool.
227
+ */
228
+ export async function executeCreateBlueprint(input) {
229
+ const { projectName, projectType, scale, projectDescription, priorities, constraints, waitForCompletion = true } = input;
230
+ debug('Creating blueprint', { projectType, scale, waitForCompletion });
231
+ try {
232
+ // Build request body
233
+ const requestBody = {
234
+ projectName,
235
+ projectContext: {
236
+ projectName,
237
+ projectType,
238
+ projectDescription,
239
+ scale,
240
+ priorities: priorities,
241
+ constraintIds: constraints
242
+ },
243
+ source: 'mcp',
244
+ mcpToolName: 'create_blueprint'
245
+ };
246
+ // Create the blueprint job
247
+ const createResponse = await createBlueprintRequest(requestBody);
248
+ // If already completed (cached result), fetch and return
249
+ if (createResponse.status === 'completed' && createResponse.resultRef) {
250
+ const blueprint = await getBlueprintRequest(createResponse.resultRef);
251
+ const text = formatBlueprint(blueprint);
252
+ return {
253
+ text: `## Blueprint Created (Cached)\n\n${text}\n\n---\n*Source: MCP Server*`
254
+ };
255
+ }
256
+ // If not waiting, return job info
257
+ if (!waitForCompletion) {
258
+ return {
259
+ text: `## Blueprint Generation Started
260
+
261
+ **Job ID**: ${createResponse.jobId}
262
+ **Project ID**: ${createResponse.projectId}
263
+ **Status**: ${createResponse.status}
264
+ **Progress**: ${createResponse.progress}%
265
+
266
+ Poll the job status at: ${createResponse._links.job}
267
+ Once complete, fetch the blueprint at: ${createResponse._links.blueprint || 'TBD'}
268
+
269
+ ---
270
+ *Source: MCP Server*`
271
+ };
272
+ }
273
+ // Poll until completion
274
+ debug('Polling job until completion', { jobId: createResponse.jobId });
275
+ const finalStatus = await pollJobUntilComplete(createResponse.jobId);
276
+ if (!finalStatus.resultRef) {
277
+ throw new McpError(ErrorCode.API_ERROR, 'Job completed but no blueprint ID returned');
278
+ }
279
+ // Fetch the completed blueprint
280
+ const blueprint = await getBlueprintRequest(finalStatus.resultRef);
281
+ const text = formatBlueprint(blueprint);
282
+ return {
283
+ text: `## Blueprint Created Successfully
284
+
285
+ ${text}
286
+
287
+ ---
288
+ **Job ID**: ${createResponse.jobId}
289
+ **Project ID**: ${createResponse.projectId}
290
+ *Source: MCP Server*`
291
+ };
292
+ }
293
+ catch (err) {
294
+ if (err instanceof McpError) {
295
+ // Add helpful suggestions for common errors
296
+ if (err.code === ErrorCode.CONFIG_ERROR) {
297
+ err.suggestions = [
298
+ 'Ensure STACKSFINDER_API_KEY is set with a valid Pro or Team API key.',
299
+ 'Get your API key from https://stacksfinder.com/settings/api'
300
+ ];
301
+ }
302
+ else if (err.code === ErrorCode.UNAUTHORIZED) {
303
+ err.suggestions = [
304
+ "Your API key may be invalid or missing the 'blueprint:write' scope.",
305
+ 'Generate a new API key with the correct permissions at https://stacksfinder.com/settings/api'
306
+ ];
307
+ }
308
+ else if (err.code === ErrorCode.RATE_LIMITED) {
309
+ err.suggestions = [
310
+ 'You have exceeded your monthly blueprint quota.',
311
+ 'Upgrade your plan at https://stacksfinder.com/pricing'
312
+ ];
313
+ }
314
+ return { text: err.toResponseText(), isError: true };
315
+ }
316
+ const error = new McpError(ErrorCode.API_ERROR, err instanceof Error ? err.message : 'Failed to create blueprint');
317
+ return { text: error.toResponseText(), isError: true };
318
+ }
319
+ }
320
+ //# sourceMappingURL=blueprint.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"blueprint.js","sourceRoot":"","sources":["../../src/tools/blueprint.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,50 @@
1
+ import { z } from 'zod';
2
+ /**
3
+ * Input schema for compare_techs tool.
4
+ */
5
+ export declare const CompareTechsInputSchema: z.ZodObject<{
6
+ technologies: z.ZodArray<z.ZodString, "many">;
7
+ context: z.ZodDefault<z.ZodOptional<z.ZodEnum<["default", "mvp", "enterprise"]>>>;
8
+ }, "strip", z.ZodTypeAny, {
9
+ context: "default" | "mvp" | "enterprise";
10
+ technologies: string[];
11
+ }, {
12
+ technologies: string[];
13
+ context?: "default" | "mvp" | "enterprise" | undefined;
14
+ }>;
15
+ export type CompareTechsInput = z.infer<typeof CompareTechsInputSchema>;
16
+ /**
17
+ * Tool definition for MCP registration.
18
+ */
19
+ export declare const compareTechsToolDefinition: {
20
+ name: string;
21
+ description: string;
22
+ inputSchema: {
23
+ type: "object";
24
+ properties: {
25
+ technologies: {
26
+ type: string;
27
+ items: {
28
+ type: string;
29
+ };
30
+ minItems: number;
31
+ maxItems: number;
32
+ description: string;
33
+ };
34
+ context: {
35
+ type: string;
36
+ enum: readonly ["default", "mvp", "enterprise"];
37
+ description: string;
38
+ };
39
+ };
40
+ required: string[];
41
+ };
42
+ };
43
+ /**
44
+ * Execute compare_techs tool.
45
+ */
46
+ export declare function executeCompareTechs(input: CompareTechsInput): {
47
+ text: string;
48
+ isError?: boolean;
49
+ };
50
+ //# sourceMappingURL=compare.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"compare.d.ts","sourceRoot":"","sources":["../../src/tools/compare.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAkBxB;;GAEG;AACH,eAAO,MAAM,uBAAuB;;;;;;;;;EAOlC,CAAC;AAEH,MAAM,MAAM,iBAAiB,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,uBAAuB,CAAC,CAAC;AAExE;;GAEG;AACH,eAAO,MAAM,0BAA0B;;;;;;;;;;;;;;;;;;;;;;;CAqBtC,CAAC;AAuDF;;GAEG;AACH,wBAAgB,mBAAmB,CAAC,KAAK,EAAE,iBAAiB,GAAG;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,OAAO,CAAC,EAAE,OAAO,CAAA;CAAE,CA4GjG"}
@@ -0,0 +1,168 @@
1
+ import { z } from 'zod';
2
+ import { CONTEXTS, DATA_VERSION, DIMENSION_LABELS, SCORE_DIMENSIONS, calculateOverallScore, getAllTechIds, getCompatibility, getCompatibilityVerdict, getScores, getTechnology, scoreToGrade, techExists } from '../data/index.js';
3
+ import { McpError, ErrorCode, techNotFoundError } from '../utils/errors.js';
4
+ /**
5
+ * Input schema for compare_techs tool.
6
+ */
7
+ export const CompareTechsInputSchema = z.object({
8
+ technologies: z
9
+ .array(z.string().min(1))
10
+ .min(2)
11
+ .max(4)
12
+ .describe('Technology IDs to compare (2-4 technologies)'),
13
+ context: z.enum(CONTEXTS).optional().default('default').describe('Context for score lookup')
14
+ });
15
+ /**
16
+ * Tool definition for MCP registration.
17
+ */
18
+ export const compareTechsToolDefinition = {
19
+ name: 'compare_techs',
20
+ description: 'Side-by-side comparison of 2-4 technologies with per-dimension winners and compatibility matrix.',
21
+ inputSchema: {
22
+ type: 'object',
23
+ properties: {
24
+ technologies: {
25
+ type: 'array',
26
+ items: { type: 'string' },
27
+ minItems: 2,
28
+ maxItems: 4,
29
+ description: 'Technology IDs to compare (e.g., ["nextjs", "sveltekit", "nuxt"])'
30
+ },
31
+ context: {
32
+ type: 'string',
33
+ enum: CONTEXTS,
34
+ description: 'Context for scoring (default, mvp, enterprise)'
35
+ }
36
+ },
37
+ required: ['technologies']
38
+ }
39
+ };
40
+ /**
41
+ * Determine winner for each dimension.
42
+ */
43
+ function determineDimensionWinners(techs) {
44
+ const winners = [];
45
+ for (const dim of SCORE_DIMENSIONS) {
46
+ const sorted = [...techs].sort((a, b) => b.scores[dim] - a.scores[dim]);
47
+ const first = sorted[0];
48
+ const second = sorted[1];
49
+ const margin = first.scores[dim] - second.scores[dim];
50
+ let winner;
51
+ let notes;
52
+ if (margin < 3) {
53
+ // Tie if margin is less than 3
54
+ winner = null;
55
+ notes = 'Tie';
56
+ }
57
+ else if (margin < 10) {
58
+ winner = first.name;
59
+ notes = 'Close competition';
60
+ }
61
+ else {
62
+ winner = first.name;
63
+ notes = 'Clear winner';
64
+ }
65
+ winners.push({
66
+ dimension: DIMENSION_LABELS[dim],
67
+ winner,
68
+ margin,
69
+ notes
70
+ });
71
+ }
72
+ return winners;
73
+ }
74
+ /**
75
+ * Execute compare_techs tool.
76
+ */
77
+ export function executeCompareTechs(input) {
78
+ const { technologies, context = 'default' } = input;
79
+ // Validate all technologies exist
80
+ const allTechIds = getAllTechIds();
81
+ const invalidTechs = [];
82
+ for (const techId of technologies) {
83
+ if (!techExists(techId)) {
84
+ invalidTechs.push(techId);
85
+ }
86
+ }
87
+ if (invalidTechs.length > 0) {
88
+ const error = techNotFoundError(invalidTechs[0], allTechIds);
89
+ return { text: error.toResponseText(), isError: true };
90
+ }
91
+ // Check for duplicates
92
+ const uniqueTechs = [...new Set(technologies)];
93
+ if (uniqueTechs.length !== technologies.length) {
94
+ const error = new McpError(ErrorCode.INVALID_INPUT, 'Duplicate technologies in comparison list');
95
+ return { text: error.toResponseText(), isError: true };
96
+ }
97
+ // Build comparison data
98
+ const comparisons = technologies.map((techId) => {
99
+ const tech = getTechnology(techId);
100
+ const scores = getScores(techId, context);
101
+ const overall = calculateOverallScore(scores);
102
+ return {
103
+ id: techId,
104
+ name: tech.name,
105
+ scores,
106
+ overall,
107
+ grade: scoreToGrade(overall)
108
+ };
109
+ });
110
+ // Sort by overall score
111
+ const sorted = [...comparisons].sort((a, b) => b.overall - a.overall);
112
+ // Determine dimension winners
113
+ const dimensionWinners = determineDimensionWinners(comparisons);
114
+ // Build response
115
+ const techNames = comparisons.map((t) => t.name).join(' vs ');
116
+ let text = `## Comparison: ${techNames} (context: ${context})
117
+
118
+ ### Overall Scores
119
+ | Technology | Score | Grade |
120
+ |------------|-------|-------|
121
+ `;
122
+ for (const tech of sorted) {
123
+ text += `| ${tech.name} | ${tech.overall} | ${tech.grade} |\n`;
124
+ }
125
+ // Per-dimension breakdown
126
+ text += `
127
+ ### Per-Dimension Winners
128
+ | Dimension | Winner | Margin | Notes |
129
+ |-----------|--------|--------|-------|
130
+ `;
131
+ for (const w of dimensionWinners) {
132
+ const winnerDisplay = w.winner ?? 'Tie';
133
+ const marginDisplay = w.winner ? `+${w.margin}` : '-';
134
+ text += `| ${w.dimension} | ${winnerDisplay} | ${marginDisplay} | ${w.notes} |\n`;
135
+ }
136
+ // Compatibility matrix (for all pairs)
137
+ text += '\n### Compatibility Matrix\n| Pair | Score | Verdict |\n|------|-------|---------|\n';
138
+ for (let i = 0; i < comparisons.length; i++) {
139
+ for (let j = i + 1; j < comparisons.length; j++) {
140
+ const a = comparisons[i];
141
+ const b = comparisons[j];
142
+ const score = getCompatibility(a.id, b.id);
143
+ const verdict = getCompatibilityVerdict(score);
144
+ text += `| ${a.id} ↔ ${b.id} | ${score} | ${verdict} |\n`;
145
+ }
146
+ }
147
+ // Verdict
148
+ const leader = sorted[0];
149
+ const runnerUp = sorted[1];
150
+ const overallMargin = leader.overall - runnerUp.overall;
151
+ text += '\n';
152
+ if (overallMargin < 3) {
153
+ text += `**Verdict**: Close call between ${leader.name} and ${runnerUp.name}\n`;
154
+ text += `**Recommendation**: Both are strong choices; consider your specific priorities.`;
155
+ }
156
+ else {
157
+ text += `**Verdict**: ${leader.name} leads with ${leader.overall}/100\n`;
158
+ // Find what leader is best at
159
+ const leaderStrengths = dimensionWinners.filter((w) => w.winner === leader.name).map((w) => w.dimension);
160
+ if (leaderStrengths.length > 0) {
161
+ const strengthsText = leaderStrengths.slice(0, 2).join(' and ');
162
+ text += `**Recommendation**: Consider ${leader.name} for ${strengthsText} priorities.`;
163
+ }
164
+ }
165
+ text += `\n\nData version: ${DATA_VERSION}`;
166
+ return { text };
167
+ }
168
+ //# sourceMappingURL=compare.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"compare.js","sourceRoot":"","sources":["../../src/tools/compare.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,34 @@
1
+ import { z } from 'zod';
2
+ /**
3
+ * Input schema for list_technologies tool.
4
+ */
5
+ export declare const ListTechsInputSchema: z.ZodObject<{
6
+ category: z.ZodOptional<z.ZodEnum<["frontend", "backend", "meta-framework", "database", "orm", "auth", "hosting", "payments"]>>;
7
+ }, "strip", z.ZodTypeAny, {
8
+ category?: "frontend" | "backend" | "meta-framework" | "database" | "orm" | "auth" | "hosting" | "payments" | undefined;
9
+ }, {
10
+ category?: "frontend" | "backend" | "meta-framework" | "database" | "orm" | "auth" | "hosting" | "payments" | undefined;
11
+ }>;
12
+ export type ListTechsInput = z.infer<typeof ListTechsInputSchema>;
13
+ /**
14
+ * Tool definition for MCP registration.
15
+ */
16
+ export declare const listTechsToolDefinition: {
17
+ name: string;
18
+ description: string;
19
+ inputSchema: {
20
+ type: "object";
21
+ properties: {
22
+ category: {
23
+ type: string;
24
+ enum: readonly ["frontend", "backend", "meta-framework", "database", "orm", "auth", "hosting", "payments"];
25
+ description: string;
26
+ };
27
+ };
28
+ };
29
+ };
30
+ /**
31
+ * Execute list_technologies tool.
32
+ */
33
+ export declare function executeListTechs(input: ListTechsInput): string;
34
+ //# sourceMappingURL=list-techs.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"list-techs.d.ts","sourceRoot":"","sources":["../../src/tools/list-techs.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AASxB;;GAEG;AACH,eAAO,MAAM,oBAAoB;;;;;;EAK/B,CAAC;AAEH,MAAM,MAAM,cAAc,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,oBAAoB,CAAC,CAAC;AAElE;;GAEG;AACH,eAAO,MAAM,uBAAuB;;;;;;;;;;;;;CAcnC,CAAC;AAYF;;GAEG;AACH,wBAAgB,gBAAgB,CAAC,KAAK,EAAE,cAAc,GAAG,MAAM,CAyC9D"}
@@ -0,0 +1,70 @@
1
+ import { z } from 'zod';
2
+ import { CATEGORIES, DATA_VERSION, getTechnologiesByCategory, getTechnologiesGroupedByCategory } from '../data/index.js';
3
+ /**
4
+ * Input schema for list_technologies tool.
5
+ */
6
+ export const ListTechsInputSchema = z.object({
7
+ category: z
8
+ .enum(CATEGORIES)
9
+ .optional()
10
+ .describe('Filter by category. Omit to list all technologies.')
11
+ });
12
+ /**
13
+ * Tool definition for MCP registration.
14
+ */
15
+ export const listTechsToolDefinition = {
16
+ name: 'list_technologies',
17
+ description: 'Lists all available technology IDs for use with other tools. Essential for discovering valid technology identifiers.',
18
+ inputSchema: {
19
+ type: 'object',
20
+ properties: {
21
+ category: {
22
+ type: 'string',
23
+ enum: CATEGORIES,
24
+ description: 'Filter by category (optional)'
25
+ }
26
+ }
27
+ }
28
+ };
29
+ /**
30
+ * Format technologies for a single category.
31
+ */
32
+ function formatCategory(category, techs) {
33
+ if (techs.length === 0)
34
+ return '';
35
+ const lines = techs.map((t) => `- ${t.id} (${t.name})`);
36
+ return `## ${category}\n${lines.join('\n')}`;
37
+ }
38
+ /**
39
+ * Execute list_technologies tool.
40
+ */
41
+ export function executeListTechs(input) {
42
+ const { category } = input;
43
+ if (category) {
44
+ // Filter by specific category
45
+ const techs = getTechnologiesByCategory(category);
46
+ const formatted = formatCategory(category, techs.map((t) => ({ id: t.id, name: t.name })));
47
+ return `Available technologies in "${category}" (${techs.length} total):
48
+
49
+ ${formatted}
50
+
51
+ Data version: ${DATA_VERSION}`;
52
+ }
53
+ // List all technologies grouped by category
54
+ const grouped = getTechnologiesGroupedByCategory();
55
+ const sections = [];
56
+ let total = 0;
57
+ for (const cat of CATEGORIES) {
58
+ const techs = grouped[cat];
59
+ if (techs.length > 0) {
60
+ sections.push(formatCategory(cat, techs.map((t) => ({ id: t.id, name: t.name }))));
61
+ total += techs.length;
62
+ }
63
+ }
64
+ return `Available technologies (${total} total):
65
+
66
+ ${sections.join('\n\n')}
67
+
68
+ Data version: ${DATA_VERSION}`;
69
+ }
70
+ //# sourceMappingURL=list-techs.js.map