@stacksfinder/mcp-server 1.4.0 → 1.6.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.
- package/CHANGELOG.md +23 -4
- package/README.md +64 -4
- package/dist/annotations.d.ts +4 -0
- package/dist/annotations.d.ts.map +1 -1
- package/dist/annotations.js +16 -0
- package/dist/annotations.js.map +1 -1
- package/dist/data/compatibility_matrix.json +1160 -228
- package/dist/data/index.d.ts +2 -2
- package/dist/data/index.d.ts.map +1 -1
- package/dist/data/index.js +52 -43
- package/dist/data/index.js.map +1 -1
- package/dist/data/technology_scores.json +2936 -1030
- package/dist/http.js +16 -3
- package/dist/http.js.map +1 -1
- package/dist/server.d.ts +1 -1
- package/dist/server.d.ts.map +1 -1
- package/dist/server.js +485 -297
- package/dist/server.js.map +1 -1
- package/dist/tools/analyze.d.ts.map +1 -1
- package/dist/tools/analyze.js +14 -1
- package/dist/tools/analyze.js.map +1 -1
- package/dist/tools/api-keys.d.ts +29 -0
- package/dist/tools/api-keys.d.ts.map +1 -1
- package/dist/tools/api-keys.js +133 -3
- package/dist/tools/api-keys.js.map +1 -1
- package/dist/tools/audit.d.ts +81 -1
- package/dist/tools/audit.d.ts.map +1 -1
- package/dist/tools/audit.js +377 -158
- package/dist/tools/audit.js.map +1 -1
- package/dist/tools/blueprint.d.ts.map +1 -1
- package/dist/tools/blueprint.js +12 -4
- package/dist/tools/blueprint.js.map +1 -1
- package/dist/tools/compare.d.ts.map +1 -1
- package/dist/tools/compare.js +19 -1
- package/dist/tools/compare.js.map +1 -1
- package/dist/tools/estimator.d.ts.map +1 -1
- package/dist/tools/estimator.js +15 -15
- package/dist/tools/estimator.js.map +1 -1
- package/dist/tools/list-techs.d.ts +4 -4
- package/dist/tools/list-techs.d.ts.map +1 -1
- package/dist/tools/list-techs.js +13 -2
- package/dist/tools/list-techs.js.map +1 -1
- package/dist/tools/project-kit/generate.d.ts.map +1 -1
- package/dist/tools/project-kit/generate.js +2 -1
- package/dist/tools/project-kit/generate.js.map +1 -1
- package/dist/tools/project-kit/match-mcps.d.ts +1 -1
- package/dist/tools/project-kit/match-mcps.d.ts.map +1 -1
- package/dist/tools/project-kit/match-mcps.js +213 -199
- package/dist/tools/project-kit/match-mcps.js.map +1 -1
- package/dist/tools/recommend-demo.d.ts.map +1 -1
- package/dist/tools/recommend-demo.js +53 -39
- package/dist/tools/recommend-demo.js.map +1 -1
- package/dist/tools/recommend.d.ts.map +1 -1
- package/dist/tools/recommend.js +7 -2
- package/dist/tools/recommend.js.map +1 -1
- package/dist/tools/workflow-guide.d.ts +87 -0
- package/dist/tools/workflow-guide.d.ts.map +1 -0
- package/dist/tools/workflow-guide.js +374 -0
- package/dist/tools/workflow-guide.js.map +1 -0
- package/dist/utils/config.d.ts +43 -0
- package/dist/utils/config.d.ts.map +1 -1
- package/dist/utils/config.js +109 -0
- package/dist/utils/config.js.map +1 -1
- package/dist/utils/errors.d.ts +18 -1
- package/dist/utils/errors.d.ts.map +1 -1
- package/dist/utils/errors.js +35 -1
- package/dist/utils/errors.js.map +1 -1
- package/package.json +75 -75
package/dist/server.js
CHANGED
|
@@ -1,269 +1,328 @@
|
|
|
1
|
-
import { McpServer } from
|
|
2
|
-
import { z } from
|
|
3
|
-
import { DATA_VERSION, CATEGORIES, CONTEXTS } from
|
|
4
|
-
import { listTechsToolDefinition, executeListTechs, ListTechsInputSchema } from
|
|
5
|
-
import { analyzeTechToolDefinition, executeAnalyzeTech, AnalyzeTechInputSchema } from
|
|
6
|
-
import { compareTechsToolDefinition, executeCompareTechs, CompareTechsInputSchema } from
|
|
7
|
-
import { recommendStackToolDefinition, executeRecommendStack, RecommendStackInputSchema } from
|
|
8
|
-
import { getBlueprintToolDefinition, executeGetBlueprint, GetBlueprintInputSchema, createBlueprintToolDefinition, executeCreateBlueprint, CreateBlueprintInputSchema } from
|
|
9
|
-
import { recommendStackDemoToolDefinition, executeRecommendStackDemo, RecommendStackDemoInputSchema } from
|
|
10
|
-
import { setupApiKeyToolDefinition, executeSetupApiKey, SetupApiKeyInputSchema, listApiKeysToolDefinition, executeListApiKeys, revokeApiKeyToolDefinition, executeRevokeApiKey, RevokeApiKeyInputSchema } from
|
|
11
|
-
import { createAuditToolDefinition, executeCreateAudit, CreateAuditInputSchema, getAuditToolDefinition, executeGetAudit, GetAuditInputSchema, listAuditsToolDefinition, executeListAudits, ListAuditsInputSchema, compareAuditsToolDefinition, executeCompareAudits, CompareAuditsInputSchema, getAuditQuotaToolDefinition, executeGetAuditQuota, getMigrationRecommendationToolDefinition, executeGetMigrationRecommendation, GetMigrationRecommendationInputSchema } from
|
|
12
|
-
import { generateMCPKitTool, generateMCPKit, GenerateMCPKitInputSchema, analyzeRepoMcpsTool, analyzeRepo, AnalyzeRepoMCPsInputSchema, PRIORITIES, PROJECT_TYPES, SCALES } from
|
|
13
|
-
import { prepareMCPInstallationTool, prepareMCPInstallation } from
|
|
14
|
-
import { executeMCPInstallationTool, executeMCPInstallation } from
|
|
15
|
-
import { PrepareMCPInstallationInputSchema, ExecuteMCPInstallationInputSchema } from
|
|
16
|
-
import { checkCompatibilityToolDefinition, executeCheckCompatibility, CheckCompatibilityInputSchema } from
|
|
17
|
-
import {
|
|
18
|
-
import {
|
|
19
|
-
import {
|
|
1
|
+
import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
|
|
2
|
+
import { z } from "zod";
|
|
3
|
+
import { DATA_VERSION, CATEGORIES, CONTEXTS } from "./data/index.js";
|
|
4
|
+
import { listTechsToolDefinition, executeListTechs, ListTechsInputSchema, } from "./tools/list-techs.js";
|
|
5
|
+
import { analyzeTechToolDefinition, executeAnalyzeTech, AnalyzeTechInputSchema, } from "./tools/analyze.js";
|
|
6
|
+
import { compareTechsToolDefinition, executeCompareTechs, CompareTechsInputSchema, } from "./tools/compare.js";
|
|
7
|
+
import { recommendStackToolDefinition, executeRecommendStack, RecommendStackInputSchema, } from "./tools/recommend.js";
|
|
8
|
+
import { getBlueprintToolDefinition, executeGetBlueprint, GetBlueprintInputSchema, createBlueprintToolDefinition, executeCreateBlueprint, CreateBlueprintInputSchema, } from "./tools/blueprint.js";
|
|
9
|
+
import { recommendStackDemoToolDefinition, executeRecommendStackDemo, RecommendStackDemoInputSchema, } from "./tools/recommend-demo.js";
|
|
10
|
+
import { setupApiKeyToolDefinition, executeSetupApiKey, SetupApiKeyInputSchema, listApiKeysToolDefinition, executeListApiKeys, revokeApiKeyToolDefinition, executeRevokeApiKey, RevokeApiKeyInputSchema, createApiKeyToolDefinition, executeCreateApiKey, CreateApiKeyInputSchema, } from "./tools/api-keys.js";
|
|
11
|
+
import { createAuditToolDefinition, executeCreateAudit, CreateAuditInputSchema, getAuditToolDefinition, executeGetAudit, GetAuditInputSchema, listAuditsToolDefinition, executeListAudits, ListAuditsInputSchema, compareAuditsToolDefinition, executeCompareAudits, CompareAuditsInputSchema, getAuditQuotaToolDefinition, executeGetAuditQuota, getMigrationRecommendationToolDefinition, executeGetMigrationRecommendation, GetMigrationRecommendationInputSchema, importBetterTStackToolDefinition, executeImportBetterTStack, ImportBetterTStackInputSchema, } 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";
|
|
17
|
+
import { getWorkflowGuideToolDefinition, executeGetWorkflowGuide, GetWorkflowGuideInputSchema, WORKFLOW_GOALS, WORKFLOW_CONTEXTS, USER_TIERS, } from "./tools/workflow-guide.js";
|
|
18
|
+
import { estimateProjectToolDefinition, executeEstimateProject, EstimateProjectInputSchema, getEstimateQuotaToolDefinition, executeGetEstimateQuota, } from "./tools/estimator.js";
|
|
19
|
+
import { info, debug } from "./utils/logger.js";
|
|
20
|
+
import { listTechnologiesAnnotations, analyzeTechAnnotations, compareTechsAnnotations, recommendStackDemoAnnotations, recommendStackAnnotations, getBlueprintAnnotations, createBlueprintAnnotations, setupApiKeyAnnotations, listApiKeysAnnotations, revokeApiKeyAnnotations, createApiKeyAnnotations, createAuditAnnotations, getAuditAnnotations, listAuditsAnnotations, compareAuditsAnnotations, getAuditQuotaAnnotations, getMigrationRecommendationAnnotations, generateMcpKitAnnotations, analyzeRepoMcpsAnnotations, prepareMcpInstallationAnnotations, executeMcpInstallationAnnotations, checkCompatibilityAnnotations, estimateProjectAnnotations, getEstimateQuotaAnnotations, getWorkflowGuideAnnotations, } from "./annotations.js";
|
|
20
21
|
/**
|
|
21
22
|
* Create and configure the MCP server.
|
|
22
23
|
*/
|
|
23
24
|
export function createServer() {
|
|
24
25
|
const server = new McpServer({
|
|
25
|
-
name:
|
|
26
|
-
version:
|
|
26
|
+
name: "stacksfinder",
|
|
27
|
+
version: "1.0.0",
|
|
27
28
|
});
|
|
28
29
|
info(`StacksFinder MCP Server v1.0.0 (data version: ${DATA_VERSION})`);
|
|
29
30
|
// Register list_technologies tool (local, discovery)
|
|
30
31
|
server.registerTool(listTechsToolDefinition.name, {
|
|
31
|
-
title:
|
|
32
|
+
title: "List Technologies",
|
|
32
33
|
description: listTechsToolDefinition.description,
|
|
33
34
|
inputSchema: {
|
|
34
|
-
category: z.enum(CATEGORIES).optional().describe(
|
|
35
|
+
category: z.enum(CATEGORIES).optional().describe("Filter by category"),
|
|
35
36
|
},
|
|
36
|
-
annotations: listTechnologiesAnnotations
|
|
37
|
+
annotations: listTechnologiesAnnotations,
|
|
37
38
|
}, async (args) => {
|
|
38
|
-
debug(
|
|
39
|
+
debug("list_technologies called", args);
|
|
39
40
|
const input = ListTechsInputSchema.parse(args);
|
|
40
41
|
const text = executeListTechs(input);
|
|
41
42
|
return {
|
|
42
|
-
content: [{ type:
|
|
43
|
+
content: [{ type: "text", text }],
|
|
43
44
|
};
|
|
44
45
|
});
|
|
45
46
|
// Register analyze_tech tool (local)
|
|
46
47
|
server.registerTool(analyzeTechToolDefinition.name, {
|
|
47
|
-
title:
|
|
48
|
+
title: "Analyze Technology",
|
|
48
49
|
description: analyzeTechToolDefinition.description,
|
|
49
50
|
inputSchema: {
|
|
50
|
-
technology: z.string().min(1).describe(
|
|
51
|
-
context: z.enum(CONTEXTS).optional().describe(
|
|
51
|
+
technology: z.string().min(1).describe("Technology ID to analyze"),
|
|
52
|
+
context: z.enum(CONTEXTS).optional().describe("Context for scoring"),
|
|
52
53
|
},
|
|
53
|
-
annotations: analyzeTechAnnotations
|
|
54
|
+
annotations: analyzeTechAnnotations,
|
|
54
55
|
}, async (args) => {
|
|
55
|
-
debug(
|
|
56
|
+
debug("analyze_tech called", args);
|
|
56
57
|
const input = AnalyzeTechInputSchema.parse(args);
|
|
57
58
|
const { text, isError } = executeAnalyzeTech(input);
|
|
58
59
|
return {
|
|
59
|
-
content: [{ type:
|
|
60
|
-
isError
|
|
60
|
+
content: [{ type: "text", text }],
|
|
61
|
+
isError,
|
|
61
62
|
};
|
|
62
63
|
});
|
|
63
64
|
// Register compare_techs tool (local)
|
|
64
65
|
server.registerTool(compareTechsToolDefinition.name, {
|
|
65
|
-
title:
|
|
66
|
+
title: "Compare Technologies",
|
|
66
67
|
description: compareTechsToolDefinition.description,
|
|
67
68
|
inputSchema: {
|
|
68
|
-
technologies: z
|
|
69
|
-
|
|
69
|
+
technologies: z
|
|
70
|
+
.array(z.string().min(1))
|
|
71
|
+
.min(2)
|
|
72
|
+
.max(4)
|
|
73
|
+
.describe("Technologies to compare"),
|
|
74
|
+
context: z.enum(CONTEXTS).optional().describe("Context for scoring"),
|
|
70
75
|
},
|
|
71
|
-
annotations: compareTechsAnnotations
|
|
76
|
+
annotations: compareTechsAnnotations,
|
|
72
77
|
}, async (args) => {
|
|
73
|
-
debug(
|
|
78
|
+
debug("compare_techs called", args);
|
|
74
79
|
const input = CompareTechsInputSchema.parse(args);
|
|
75
80
|
const { text, isError } = executeCompareTechs(input);
|
|
76
81
|
return {
|
|
77
|
-
content: [{ type:
|
|
78
|
-
isError
|
|
82
|
+
content: [{ type: "text", text }],
|
|
83
|
+
isError,
|
|
79
84
|
};
|
|
80
85
|
});
|
|
81
86
|
// Register recommend_stack_demo tool (FREE, local scoring, 1/day limit)
|
|
82
87
|
server.registerTool(recommendStackDemoToolDefinition.name, {
|
|
83
|
-
title:
|
|
88
|
+
title: "Recommend Stack (Demo)",
|
|
84
89
|
description: recommendStackDemoToolDefinition.description,
|
|
85
90
|
inputSchema: {
|
|
86
91
|
projectType: z
|
|
87
92
|
.enum([
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
93
|
+
"web-app",
|
|
94
|
+
"mobile-app",
|
|
95
|
+
"api",
|
|
96
|
+
"desktop",
|
|
97
|
+
"cli",
|
|
98
|
+
"library",
|
|
99
|
+
"e-commerce",
|
|
100
|
+
"saas",
|
|
101
|
+
"marketplace",
|
|
97
102
|
])
|
|
98
|
-
.describe(
|
|
99
|
-
scale: z
|
|
103
|
+
.describe("Type of project"),
|
|
104
|
+
scale: z
|
|
105
|
+
.enum(["mvp", "startup", "growth", "enterprise"])
|
|
106
|
+
.optional()
|
|
107
|
+
.describe("Project scale"),
|
|
100
108
|
},
|
|
101
|
-
annotations: recommendStackDemoAnnotations
|
|
109
|
+
annotations: recommendStackDemoAnnotations,
|
|
102
110
|
}, async (args) => {
|
|
103
|
-
debug(
|
|
111
|
+
debug("recommend_stack_demo called", args);
|
|
104
112
|
const input = RecommendStackDemoInputSchema.parse(args);
|
|
105
113
|
const { text, isError } = executeRecommendStackDemo(input);
|
|
106
114
|
return {
|
|
107
|
-
content: [{ type:
|
|
108
|
-
isError
|
|
115
|
+
content: [{ type: "text", text }],
|
|
116
|
+
isError,
|
|
109
117
|
};
|
|
110
118
|
});
|
|
111
119
|
// Register recommend_stack tool (API-based, requires API key)
|
|
112
120
|
server.registerTool(recommendStackToolDefinition.name, {
|
|
113
|
-
title:
|
|
121
|
+
title: "Recommend Stack",
|
|
114
122
|
description: recommendStackToolDefinition.description,
|
|
115
123
|
inputSchema: {
|
|
116
124
|
projectType: z
|
|
117
125
|
.enum([
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
126
|
+
"web-app",
|
|
127
|
+
"mobile-app",
|
|
128
|
+
"api",
|
|
129
|
+
"desktop",
|
|
130
|
+
"cli",
|
|
131
|
+
"library",
|
|
132
|
+
"e-commerce",
|
|
133
|
+
"saas",
|
|
134
|
+
"marketplace",
|
|
127
135
|
])
|
|
128
|
-
.describe(
|
|
129
|
-
scale: z
|
|
136
|
+
.describe("Type of project"),
|
|
137
|
+
scale: z
|
|
138
|
+
.enum(["mvp", "startup", "growth", "enterprise"])
|
|
139
|
+
.optional()
|
|
140
|
+
.describe("Project scale"),
|
|
130
141
|
priorities: z
|
|
131
142
|
.array(z.enum([
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
143
|
+
"time-to-market",
|
|
144
|
+
"scalability",
|
|
145
|
+
"developer-experience",
|
|
146
|
+
"cost-efficiency",
|
|
147
|
+
"performance",
|
|
148
|
+
"security",
|
|
149
|
+
"maintainability",
|
|
139
150
|
]))
|
|
140
151
|
.max(3)
|
|
141
152
|
.optional()
|
|
142
|
-
.describe(
|
|
143
|
-
constraints: z
|
|
153
|
+
.describe("Top priorities (max 3)"),
|
|
154
|
+
constraints: z
|
|
155
|
+
.array(z.string())
|
|
156
|
+
.optional()
|
|
157
|
+
.describe("Project constraints"),
|
|
144
158
|
},
|
|
145
|
-
annotations: recommendStackAnnotations
|
|
159
|
+
annotations: recommendStackAnnotations,
|
|
146
160
|
}, async (args) => {
|
|
147
|
-
debug(
|
|
161
|
+
debug("recommend_stack called", args);
|
|
148
162
|
const input = RecommendStackInputSchema.parse(args);
|
|
149
163
|
const { text, isError } = await executeRecommendStack(input);
|
|
150
164
|
return {
|
|
151
|
-
content: [{ type:
|
|
152
|
-
isError
|
|
165
|
+
content: [{ type: "text", text }],
|
|
166
|
+
isError,
|
|
153
167
|
};
|
|
154
168
|
});
|
|
155
169
|
// Register get_blueprint tool (API-based)
|
|
156
170
|
server.registerTool(getBlueprintToolDefinition.name, {
|
|
157
|
-
title:
|
|
171
|
+
title: "Get Blueprint",
|
|
158
172
|
description: getBlueprintToolDefinition.description,
|
|
159
173
|
inputSchema: {
|
|
160
|
-
blueprintId: z.string().uuid().describe(
|
|
174
|
+
blueprintId: z.string().uuid().describe("Blueprint UUID"),
|
|
161
175
|
},
|
|
162
|
-
annotations: getBlueprintAnnotations
|
|
176
|
+
annotations: getBlueprintAnnotations,
|
|
163
177
|
}, async (args) => {
|
|
164
|
-
debug(
|
|
178
|
+
debug("get_blueprint called", args);
|
|
165
179
|
const input = GetBlueprintInputSchema.parse(args);
|
|
166
180
|
const { text, isError } = await executeGetBlueprint(input);
|
|
167
181
|
return {
|
|
168
|
-
content: [{ type:
|
|
169
|
-
isError
|
|
182
|
+
content: [{ type: "text", text }],
|
|
183
|
+
isError,
|
|
170
184
|
};
|
|
171
185
|
});
|
|
172
186
|
// Register create_blueprint tool (API-based, requires API key with blueprint:write)
|
|
173
187
|
server.registerTool(createBlueprintToolDefinition.name, {
|
|
174
|
-
title:
|
|
188
|
+
title: "Create Blueprint",
|
|
175
189
|
description: createBlueprintToolDefinition.description,
|
|
176
190
|
inputSchema: {
|
|
177
|
-
projectName: z
|
|
191
|
+
projectName: z
|
|
192
|
+
.string()
|
|
193
|
+
.max(100)
|
|
194
|
+
.optional()
|
|
195
|
+
.describe("Project name (optional)"),
|
|
178
196
|
projectType: z
|
|
179
197
|
.enum([
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
198
|
+
"web-app",
|
|
199
|
+
"mobile-app",
|
|
200
|
+
"api",
|
|
201
|
+
"desktop",
|
|
202
|
+
"cli",
|
|
203
|
+
"library",
|
|
204
|
+
"e-commerce",
|
|
205
|
+
"saas",
|
|
206
|
+
"marketplace",
|
|
189
207
|
])
|
|
190
|
-
.describe(
|
|
191
|
-
scale: z
|
|
192
|
-
|
|
208
|
+
.describe("Type of project"),
|
|
209
|
+
scale: z
|
|
210
|
+
.enum(["mvp", "startup", "growth", "enterprise"])
|
|
211
|
+
.describe("Project scale"),
|
|
212
|
+
projectDescription: z
|
|
213
|
+
.string()
|
|
214
|
+
.max(2000)
|
|
215
|
+
.optional()
|
|
216
|
+
.describe("Brief description (optional)"),
|
|
193
217
|
priorities: z
|
|
194
218
|
.array(z.enum([
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
219
|
+
"time-to-market",
|
|
220
|
+
"scalability",
|
|
221
|
+
"developer-experience",
|
|
222
|
+
"cost-efficiency",
|
|
223
|
+
"performance",
|
|
224
|
+
"security",
|
|
225
|
+
"maintainability",
|
|
202
226
|
]))
|
|
203
227
|
.max(3)
|
|
204
228
|
.optional()
|
|
205
|
-
.describe(
|
|
206
|
-
constraints: z
|
|
207
|
-
|
|
229
|
+
.describe("Top 3 priorities (optional)"),
|
|
230
|
+
constraints: z
|
|
231
|
+
.array(z.string())
|
|
232
|
+
.max(20)
|
|
233
|
+
.optional()
|
|
234
|
+
.describe("Technology constraint IDs (optional)"),
|
|
235
|
+
waitForCompletion: z
|
|
236
|
+
.boolean()
|
|
237
|
+
.optional()
|
|
238
|
+
.describe("Wait for completion (default: true)"),
|
|
208
239
|
},
|
|
209
|
-
annotations: createBlueprintAnnotations
|
|
240
|
+
annotations: createBlueprintAnnotations,
|
|
210
241
|
}, async (args) => {
|
|
211
|
-
debug(
|
|
242
|
+
debug("create_blueprint called", args);
|
|
212
243
|
const input = CreateBlueprintInputSchema.parse(args);
|
|
213
244
|
const { text, isError } = await executeCreateBlueprint(input);
|
|
214
245
|
return {
|
|
215
|
-
content: [{ type:
|
|
216
|
-
isError
|
|
246
|
+
content: [{ type: "text", text }],
|
|
247
|
+
isError,
|
|
217
248
|
};
|
|
218
249
|
});
|
|
219
250
|
// Register setup_api_key tool (API-based, no auth required)
|
|
220
251
|
server.registerTool(setupApiKeyToolDefinition.name, {
|
|
221
|
-
title:
|
|
252
|
+
title: "Setup API Key",
|
|
222
253
|
description: setupApiKeyToolDefinition.description,
|
|
223
254
|
inputSchema: {
|
|
224
|
-
email: z.string().email().describe(
|
|
225
|
-
password: z
|
|
226
|
-
|
|
255
|
+
email: z.string().email().describe("Your StacksFinder account email"),
|
|
256
|
+
password: z
|
|
257
|
+
.string()
|
|
258
|
+
.min(1)
|
|
259
|
+
.describe("Your StacksFinder account password"),
|
|
260
|
+
keyName: z
|
|
261
|
+
.string()
|
|
262
|
+
.max(100)
|
|
263
|
+
.optional()
|
|
264
|
+
.describe("Optional name for the API key"),
|
|
227
265
|
},
|
|
228
|
-
annotations: setupApiKeyAnnotations
|
|
266
|
+
annotations: setupApiKeyAnnotations,
|
|
229
267
|
}, async (args) => {
|
|
230
|
-
debug(
|
|
268
|
+
debug("setup_api_key called", args.email);
|
|
231
269
|
const input = SetupApiKeyInputSchema.parse(args);
|
|
232
270
|
const { text, isError } = await executeSetupApiKey(input);
|
|
233
271
|
return {
|
|
234
|
-
content: [{ type:
|
|
235
|
-
isError
|
|
272
|
+
content: [{ type: "text", text }],
|
|
273
|
+
isError,
|
|
236
274
|
};
|
|
237
275
|
});
|
|
238
276
|
// Register list_api_keys tool (API-based, requires API key)
|
|
239
277
|
server.registerTool(listApiKeysToolDefinition.name, {
|
|
240
|
-
title:
|
|
278
|
+
title: "List API Keys",
|
|
241
279
|
description: listApiKeysToolDefinition.description,
|
|
242
280
|
inputSchema: {},
|
|
243
|
-
annotations: listApiKeysAnnotations
|
|
281
|
+
annotations: listApiKeysAnnotations,
|
|
244
282
|
}, async () => {
|
|
245
|
-
debug(
|
|
283
|
+
debug("list_api_keys called");
|
|
246
284
|
const { text, isError } = await executeListApiKeys();
|
|
247
285
|
return {
|
|
248
|
-
content: [{ type:
|
|
249
|
-
isError
|
|
286
|
+
content: [{ type: "text", text }],
|
|
287
|
+
isError,
|
|
250
288
|
};
|
|
251
289
|
});
|
|
252
290
|
// Register revoke_api_key tool (API-based, requires API key)
|
|
253
291
|
server.registerTool(revokeApiKeyToolDefinition.name, {
|
|
254
|
-
title:
|
|
292
|
+
title: "Revoke API Key",
|
|
255
293
|
description: revokeApiKeyToolDefinition.description,
|
|
256
294
|
inputSchema: {
|
|
257
|
-
keyId: z.string().uuid().describe(
|
|
295
|
+
keyId: z.string().uuid().describe("The UUID of the API key to revoke"),
|
|
258
296
|
},
|
|
259
|
-
annotations: revokeApiKeyAnnotations
|
|
297
|
+
annotations: revokeApiKeyAnnotations,
|
|
260
298
|
}, async (args) => {
|
|
261
|
-
debug(
|
|
299
|
+
debug("revoke_api_key called", args.keyId);
|
|
262
300
|
const input = RevokeApiKeyInputSchema.parse(args);
|
|
263
301
|
const { text, isError } = await executeRevokeApiKey(input);
|
|
264
302
|
return {
|
|
265
|
-
content: [{ type:
|
|
266
|
-
isError
|
|
303
|
+
content: [{ type: "text", text }],
|
|
304
|
+
isError,
|
|
305
|
+
};
|
|
306
|
+
});
|
|
307
|
+
// Register create_api_key tool (OAuth-based, no email/password required)
|
|
308
|
+
server.registerTool(createApiKeyToolDefinition.name, {
|
|
309
|
+
title: "Create API Key",
|
|
310
|
+
description: createApiKeyToolDefinition.description,
|
|
311
|
+
inputSchema: {
|
|
312
|
+
keyName: z
|
|
313
|
+
.string()
|
|
314
|
+
.max(100)
|
|
315
|
+
.optional()
|
|
316
|
+
.describe("Optional name for the API key"),
|
|
317
|
+
},
|
|
318
|
+
annotations: createApiKeyAnnotations,
|
|
319
|
+
}, async (args) => {
|
|
320
|
+
debug("create_api_key called");
|
|
321
|
+
const input = CreateApiKeyInputSchema.parse(args);
|
|
322
|
+
const { text, isError } = await executeCreateApiKey(input);
|
|
323
|
+
return {
|
|
324
|
+
content: [{ type: "text", text }],
|
|
325
|
+
isError,
|
|
267
326
|
};
|
|
268
327
|
});
|
|
269
328
|
// ========================================================================
|
|
@@ -271,112 +330,141 @@ export function createServer() {
|
|
|
271
330
|
// ========================================================================
|
|
272
331
|
// Register create_audit tool (API-based, requires API key with audit:write)
|
|
273
332
|
server.registerTool(createAuditToolDefinition.name, {
|
|
274
|
-
title:
|
|
333
|
+
title: "Create Technical Debt Audit",
|
|
275
334
|
description: createAuditToolDefinition.description,
|
|
276
335
|
inputSchema: {
|
|
277
|
-
name: z.string().min(1).max(200).describe(
|
|
336
|
+
name: z.string().min(1).max(200).describe("Name for the audit report"),
|
|
278
337
|
technologies: z
|
|
279
338
|
.array(z.object({
|
|
280
|
-
name: z.string().min(1).describe(
|
|
281
|
-
version: z.string().optional().describe(
|
|
282
|
-
category: z.string().optional().describe(
|
|
339
|
+
name: z.string().min(1).describe("Technology name"),
|
|
340
|
+
version: z.string().optional().describe("Version string"),
|
|
341
|
+
category: z.string().optional().describe("Category"),
|
|
283
342
|
}))
|
|
284
343
|
.min(1)
|
|
285
344
|
.max(50)
|
|
286
|
-
.describe(
|
|
345
|
+
.describe("Technologies to audit"),
|
|
287
346
|
},
|
|
288
|
-
annotations: createAuditAnnotations
|
|
347
|
+
annotations: createAuditAnnotations,
|
|
289
348
|
}, async (args) => {
|
|
290
|
-
debug(
|
|
349
|
+
debug("create_audit called", args);
|
|
291
350
|
const input = CreateAuditInputSchema.parse(args);
|
|
292
351
|
const { text, isError } = await executeCreateAudit(input);
|
|
293
352
|
return {
|
|
294
|
-
content: [{ type:
|
|
295
|
-
isError
|
|
353
|
+
content: [{ type: "text", text }],
|
|
354
|
+
isError,
|
|
296
355
|
};
|
|
297
356
|
});
|
|
298
357
|
// Register get_audit tool (API-based, requires API key with audit:read)
|
|
299
358
|
server.registerTool(getAuditToolDefinition.name, {
|
|
300
|
-
title:
|
|
359
|
+
title: "Get Audit Report",
|
|
301
360
|
description: getAuditToolDefinition.description,
|
|
302
361
|
inputSchema: {
|
|
303
|
-
auditId: z.string().uuid().describe(
|
|
362
|
+
auditId: z.string().uuid().describe("Audit report UUID"),
|
|
304
363
|
},
|
|
305
|
-
annotations: getAuditAnnotations
|
|
364
|
+
annotations: getAuditAnnotations,
|
|
306
365
|
}, async (args) => {
|
|
307
|
-
debug(
|
|
366
|
+
debug("get_audit called", args);
|
|
308
367
|
const input = GetAuditInputSchema.parse(args);
|
|
309
368
|
const { text, isError } = await executeGetAudit(input);
|
|
310
369
|
return {
|
|
311
|
-
content: [{ type:
|
|
312
|
-
isError
|
|
370
|
+
content: [{ type: "text", text }],
|
|
371
|
+
isError,
|
|
313
372
|
};
|
|
314
373
|
});
|
|
315
374
|
// Register list_audits tool (API-based, requires API key with audit:read)
|
|
316
375
|
server.registerTool(listAuditsToolDefinition.name, {
|
|
317
|
-
title:
|
|
376
|
+
title: "List Audit Reports",
|
|
318
377
|
description: listAuditsToolDefinition.description,
|
|
319
378
|
inputSchema: {
|
|
320
|
-
limit: z.number().min(1).max(50).optional().describe(
|
|
321
|
-
offset: z.number().min(0).optional().describe(
|
|
379
|
+
limit: z.number().min(1).max(50).optional().describe("Max results"),
|
|
380
|
+
offset: z.number().min(0).optional().describe("Pagination offset"),
|
|
322
381
|
},
|
|
323
|
-
annotations: listAuditsAnnotations
|
|
382
|
+
annotations: listAuditsAnnotations,
|
|
324
383
|
}, async (args) => {
|
|
325
|
-
debug(
|
|
384
|
+
debug("list_audits called", args);
|
|
326
385
|
const input = ListAuditsInputSchema.parse(args);
|
|
327
386
|
const { text, isError } = await executeListAudits(input);
|
|
328
387
|
return {
|
|
329
|
-
content: [{ type:
|
|
330
|
-
isError
|
|
388
|
+
content: [{ type: "text", text }],
|
|
389
|
+
isError,
|
|
331
390
|
};
|
|
332
391
|
});
|
|
333
392
|
// Register compare_audits tool (API-based, requires API key with audit:read)
|
|
334
393
|
server.registerTool(compareAuditsToolDefinition.name, {
|
|
335
|
-
title:
|
|
394
|
+
title: "Compare Audit Reports",
|
|
336
395
|
description: compareAuditsToolDefinition.description,
|
|
337
396
|
inputSchema: {
|
|
338
|
-
baseAuditId: z.string().uuid().describe(
|
|
339
|
-
compareAuditId: z.string().uuid().describe(
|
|
397
|
+
baseAuditId: z.string().uuid().describe("Base (older) audit ID"),
|
|
398
|
+
compareAuditId: z.string().uuid().describe("Compare (newer) audit ID"),
|
|
340
399
|
},
|
|
341
|
-
annotations: compareAuditsAnnotations
|
|
400
|
+
annotations: compareAuditsAnnotations,
|
|
342
401
|
}, async (args) => {
|
|
343
|
-
debug(
|
|
402
|
+
debug("compare_audits called", args);
|
|
344
403
|
const input = CompareAuditsInputSchema.parse(args);
|
|
345
404
|
const { text, isError } = await executeCompareAudits(input);
|
|
346
405
|
return {
|
|
347
|
-
content: [{ type:
|
|
348
|
-
isError
|
|
406
|
+
content: [{ type: "text", text }],
|
|
407
|
+
isError,
|
|
349
408
|
};
|
|
350
409
|
});
|
|
351
410
|
// Register get_audit_quota tool (API-based, requires API key)
|
|
352
411
|
server.registerTool(getAuditQuotaToolDefinition.name, {
|
|
353
|
-
title:
|
|
412
|
+
title: "Get Audit Quota",
|
|
354
413
|
description: getAuditQuotaToolDefinition.description,
|
|
355
414
|
inputSchema: {},
|
|
356
|
-
annotations: getAuditQuotaAnnotations
|
|
415
|
+
annotations: getAuditQuotaAnnotations,
|
|
357
416
|
}, async () => {
|
|
358
|
-
debug(
|
|
417
|
+
debug("get_audit_quota called");
|
|
359
418
|
const { text, isError } = await executeGetAuditQuota();
|
|
360
419
|
return {
|
|
361
|
-
content: [{ type:
|
|
362
|
-
isError
|
|
420
|
+
content: [{ type: "text", text }],
|
|
421
|
+
isError,
|
|
363
422
|
};
|
|
364
423
|
});
|
|
365
424
|
// Register get_migration_recommendation tool (API-based, requires API key with audit:read)
|
|
366
425
|
server.registerTool(getMigrationRecommendationToolDefinition.name, {
|
|
367
|
-
title:
|
|
426
|
+
title: "Get Migration Recommendation",
|
|
368
427
|
description: getMigrationRecommendationToolDefinition.description,
|
|
369
428
|
inputSchema: {
|
|
370
|
-
auditId: z
|
|
429
|
+
auditId: z
|
|
430
|
+
.string()
|
|
431
|
+
.uuid()
|
|
432
|
+
.describe("Audit report UUID to analyze for migration"),
|
|
371
433
|
},
|
|
372
|
-
annotations: getMigrationRecommendationAnnotations
|
|
434
|
+
annotations: getMigrationRecommendationAnnotations,
|
|
373
435
|
}, async (args) => {
|
|
374
|
-
debug(
|
|
436
|
+
debug("get_migration_recommendation called", args);
|
|
375
437
|
const input = GetMigrationRecommendationInputSchema.parse(args);
|
|
376
438
|
const { text, isError } = await executeGetMigrationRecommendation(input);
|
|
377
439
|
return {
|
|
378
|
-
content: [{ type:
|
|
379
|
-
isError
|
|
440
|
+
content: [{ type: "text", text }],
|
|
441
|
+
isError,
|
|
442
|
+
};
|
|
443
|
+
});
|
|
444
|
+
// Register import_better_t_stack tool (API-based, requires API key with audit:write)
|
|
445
|
+
server.registerTool(importBetterTStackToolDefinition.name, {
|
|
446
|
+
title: "Import Better-T-Stack Project",
|
|
447
|
+
description: importBetterTStackToolDefinition.description,
|
|
448
|
+
inputSchema: {
|
|
449
|
+
type: z.enum(["github", "package-json"]).describe("Import source type"),
|
|
450
|
+
url: z
|
|
451
|
+
.string()
|
|
452
|
+
.optional()
|
|
453
|
+
.describe("GitHub repository URL (for type=github)"),
|
|
454
|
+
content: z
|
|
455
|
+
.string()
|
|
456
|
+
.optional()
|
|
457
|
+
.describe("Raw package.json content (for type=package-json)"),
|
|
458
|
+
name: z.string().max(200).optional().describe("Custom audit name"),
|
|
459
|
+
},
|
|
460
|
+
annotations: createAuditAnnotations, // Reuse audit annotations
|
|
461
|
+
}, async (args) => {
|
|
462
|
+
debug("import_better_t_stack called", args);
|
|
463
|
+
const input = ImportBetterTStackInputSchema.parse(args);
|
|
464
|
+
const { text, isError } = await executeImportBetterTStack(input);
|
|
465
|
+
return {
|
|
466
|
+
content: [{ type: "text", text }],
|
|
467
|
+
isError,
|
|
380
468
|
};
|
|
381
469
|
});
|
|
382
470
|
// ========================================================================
|
|
@@ -384,81 +472,133 @@ export function createServer() {
|
|
|
384
472
|
// ========================================================================
|
|
385
473
|
// Register generate_mcp_kit tool (local, no API key required)
|
|
386
474
|
server.registerTool(generateMCPKitTool.name, {
|
|
387
|
-
title:
|
|
475
|
+
title: "Generate MCP Kit",
|
|
388
476
|
description: generateMCPKitTool.description,
|
|
389
477
|
inputSchema: {
|
|
390
|
-
projectDescription: z
|
|
391
|
-
|
|
392
|
-
|
|
393
|
-
|
|
394
|
-
|
|
478
|
+
projectDescription: z
|
|
479
|
+
.string()
|
|
480
|
+
.min(50)
|
|
481
|
+
.max(5000)
|
|
482
|
+
.describe("Describe your project (50-5000 chars)"),
|
|
483
|
+
priorities: z
|
|
484
|
+
.array(z.enum(PRIORITIES))
|
|
485
|
+
.max(3)
|
|
486
|
+
.optional()
|
|
487
|
+
.describe("Top priorities (max 3)"),
|
|
488
|
+
constraints: z
|
|
489
|
+
.array(z.string())
|
|
490
|
+
.optional()
|
|
491
|
+
.describe("Tech constraints (e.g., must-use-postgresql)"),
|
|
492
|
+
projectType: z
|
|
493
|
+
.enum(PROJECT_TYPES)
|
|
494
|
+
.optional()
|
|
495
|
+
.describe("Project type (if known)"),
|
|
496
|
+
scale: z.enum(SCALES).optional().describe("Project scale (if known)"),
|
|
395
497
|
},
|
|
396
|
-
annotations: generateMcpKitAnnotations
|
|
498
|
+
annotations: generateMcpKitAnnotations,
|
|
397
499
|
}, async (args) => {
|
|
398
|
-
debug(
|
|
500
|
+
debug("generate_mcp_kit called", args);
|
|
399
501
|
const input = GenerateMCPKitInputSchema.parse(args);
|
|
400
502
|
const result = generateMCPKit(input);
|
|
401
503
|
return {
|
|
402
|
-
content: [{ type:
|
|
504
|
+
content: [{ type: "text", text: JSON.stringify(result, null, 2) }],
|
|
403
505
|
};
|
|
404
506
|
});
|
|
405
507
|
// Register analyze_repo_mcps tool (local, no API key required)
|
|
406
508
|
server.registerTool(analyzeRepoMcpsTool.name, {
|
|
407
|
-
title:
|
|
509
|
+
title: "Analyze Repository MCPs",
|
|
408
510
|
description: analyzeRepoMcpsTool.description,
|
|
409
511
|
inputSchema: {
|
|
410
|
-
includeInstalled: z
|
|
411
|
-
|
|
412
|
-
|
|
512
|
+
includeInstalled: z
|
|
513
|
+
.boolean()
|
|
514
|
+
.optional()
|
|
515
|
+
.describe("Include already installed MCPs (default: false)"),
|
|
516
|
+
mcpConfigPath: z
|
|
517
|
+
.string()
|
|
518
|
+
.optional()
|
|
519
|
+
.describe("Override path to MCP configuration file"),
|
|
520
|
+
workspaceRoot: z
|
|
521
|
+
.string()
|
|
522
|
+
.optional()
|
|
523
|
+
.describe("Override workspace root directory (default: current directory)"),
|
|
413
524
|
},
|
|
414
|
-
annotations: analyzeRepoMcpsAnnotations
|
|
525
|
+
annotations: analyzeRepoMcpsAnnotations,
|
|
415
526
|
}, async (args) => {
|
|
416
|
-
debug(
|
|
527
|
+
debug("analyze_repo_mcps called", args);
|
|
417
528
|
const input = AnalyzeRepoMCPsInputSchema.parse(args);
|
|
418
529
|
const result = await analyzeRepo(input);
|
|
419
530
|
// Format as markdown for better readability
|
|
420
531
|
return {
|
|
421
|
-
content: [{ type:
|
|
532
|
+
content: [{ type: "text", text: formatAnalysisResult(result) }],
|
|
422
533
|
};
|
|
423
534
|
});
|
|
424
535
|
// Register prepare_mcp_installation tool (local, no API key required)
|
|
425
536
|
server.registerTool(prepareMCPInstallationTool.name, {
|
|
426
|
-
title:
|
|
537
|
+
title: "Prepare MCP Installation",
|
|
427
538
|
description: prepareMCPInstallationTool.description,
|
|
428
539
|
inputSchema: {
|
|
429
|
-
workspaceRoot: z
|
|
430
|
-
|
|
431
|
-
|
|
432
|
-
|
|
540
|
+
workspaceRoot: z
|
|
541
|
+
.string()
|
|
542
|
+
.optional()
|
|
543
|
+
.describe("Workspace root directory (default: current directory)"),
|
|
544
|
+
mcpConfigPath: z
|
|
545
|
+
.string()
|
|
546
|
+
.optional()
|
|
547
|
+
.describe("Override path to existing MCP configuration file"),
|
|
548
|
+
includeInstalled: z
|
|
549
|
+
.boolean()
|
|
550
|
+
.optional()
|
|
551
|
+
.describe("Include already installed MCPs in the preparation (default: false)"),
|
|
552
|
+
envMcpPath: z
|
|
553
|
+
.string()
|
|
554
|
+
.optional()
|
|
555
|
+
.describe("Path where .env-mcp will be created (default: .env-mcp in workspaceRoot)"),
|
|
433
556
|
},
|
|
434
|
-
annotations: prepareMcpInstallationAnnotations
|
|
557
|
+
annotations: prepareMcpInstallationAnnotations,
|
|
435
558
|
}, async (args) => {
|
|
436
|
-
debug(
|
|
559
|
+
debug("prepare_mcp_installation called", args);
|
|
437
560
|
const input = PrepareMCPInstallationInputSchema.parse(args);
|
|
438
561
|
const result = await prepareMCPInstallation(input);
|
|
439
562
|
return {
|
|
440
|
-
content: [
|
|
563
|
+
content: [
|
|
564
|
+
{
|
|
565
|
+
type: "text",
|
|
566
|
+
text: result.message + "\n\n" + formatPreparationSummary(result),
|
|
567
|
+
},
|
|
568
|
+
],
|
|
441
569
|
};
|
|
442
570
|
});
|
|
443
571
|
// Register execute_mcp_installation tool (local, no API key required)
|
|
444
572
|
server.registerTool(executeMCPInstallationTool.name, {
|
|
445
|
-
title:
|
|
573
|
+
title: "Execute MCP Installation",
|
|
446
574
|
description: executeMCPInstallationTool.description,
|
|
447
575
|
inputSchema: {
|
|
448
|
-
envMcpPath: z
|
|
576
|
+
envMcpPath: z
|
|
577
|
+
.string()
|
|
578
|
+
.optional()
|
|
579
|
+
.describe("Path to .env-mcp file (default: .env-mcp in current directory)"),
|
|
449
580
|
targetClient: z
|
|
450
|
-
.enum([
|
|
581
|
+
.enum([
|
|
582
|
+
"claude-code",
|
|
583
|
+
"claude-desktop",
|
|
584
|
+
"cursor",
|
|
585
|
+
"vscode",
|
|
586
|
+
"windsurf",
|
|
587
|
+
])
|
|
451
588
|
.optional()
|
|
452
|
-
.describe(
|
|
453
|
-
dryRun: z
|
|
589
|
+
.describe("Target IDE/client for installation (default: claude-code)"),
|
|
590
|
+
dryRun: z
|
|
591
|
+
.boolean()
|
|
592
|
+
.optional()
|
|
593
|
+
.describe("Only generate commands without marking ready to execute (default: false)"),
|
|
454
594
|
},
|
|
455
|
-
annotations: executeMcpInstallationAnnotations
|
|
595
|
+
annotations: executeMcpInstallationAnnotations,
|
|
456
596
|
}, async (args) => {
|
|
457
|
-
debug(
|
|
597
|
+
debug("execute_mcp_installation called", args);
|
|
458
598
|
const input = ExecuteMCPInstallationInputSchema.parse(args);
|
|
459
599
|
const result = await executeMCPInstallation(input);
|
|
460
600
|
return {
|
|
461
|
-
content: [{ type:
|
|
601
|
+
content: [{ type: "text", text: formatExecutionResult(result) }],
|
|
462
602
|
};
|
|
463
603
|
});
|
|
464
604
|
// ========================================================================
|
|
@@ -466,26 +606,64 @@ export function createServer() {
|
|
|
466
606
|
// ========================================================================
|
|
467
607
|
// Register check_mcp_compatibility tool (local, no API key required)
|
|
468
608
|
server.registerTool(checkCompatibilityToolDefinition.name, {
|
|
469
|
-
title:
|
|
609
|
+
title: "Check MCP Compatibility",
|
|
470
610
|
description: checkCompatibilityToolDefinition.description,
|
|
471
611
|
inputSchema: {
|
|
472
612
|
mcps: z
|
|
473
613
|
.array(z.string().min(1))
|
|
474
614
|
.min(1)
|
|
475
615
|
.max(20)
|
|
476
|
-
.describe(
|
|
616
|
+
.describe("Array of MCP server IDs to check compatibility between"),
|
|
477
617
|
},
|
|
478
|
-
annotations: checkCompatibilityAnnotations
|
|
618
|
+
annotations: checkCompatibilityAnnotations,
|
|
479
619
|
}, async (args) => {
|
|
480
|
-
debug(
|
|
620
|
+
debug("check_mcp_compatibility called", args);
|
|
481
621
|
const input = CheckCompatibilityInputSchema.parse(args);
|
|
482
622
|
const { text, data, isError } = executeCheckCompatibility(input);
|
|
483
623
|
return {
|
|
484
624
|
content: [
|
|
485
|
-
{ type:
|
|
486
|
-
{
|
|
625
|
+
{ type: "text", text },
|
|
626
|
+
{
|
|
627
|
+
type: "text",
|
|
628
|
+
text: `\n---\n\n**Structured Data:**\n\`\`\`json\n${JSON.stringify(data, null, 2)}\n\`\`\``,
|
|
629
|
+
},
|
|
487
630
|
],
|
|
488
|
-
isError
|
|
631
|
+
isError,
|
|
632
|
+
};
|
|
633
|
+
});
|
|
634
|
+
// Register get_workflow_guide tool (local, FREE, no API key required)
|
|
635
|
+
server.registerTool(getWorkflowGuideToolDefinition.name, {
|
|
636
|
+
title: "Get Workflow Guide",
|
|
637
|
+
description: getWorkflowGuideToolDefinition.description,
|
|
638
|
+
inputSchema: {
|
|
639
|
+
current_goal: z
|
|
640
|
+
.enum(WORKFLOW_GOALS)
|
|
641
|
+
.optional()
|
|
642
|
+
.describe("What the user is trying to accomplish"),
|
|
643
|
+
completed_tools: z
|
|
644
|
+
.array(z.string())
|
|
645
|
+
.optional()
|
|
646
|
+
.describe("Tools already called in this session"),
|
|
647
|
+
user_tier: z
|
|
648
|
+
.enum(USER_TIERS)
|
|
649
|
+
.optional()
|
|
650
|
+
.describe("User tier: free, pro, or unknown"),
|
|
651
|
+
known_constraints: z
|
|
652
|
+
.array(z.string())
|
|
653
|
+
.optional()
|
|
654
|
+
.describe("Constraints like must_use_postgresql"),
|
|
655
|
+
context: z
|
|
656
|
+
.enum(WORKFLOW_CONTEXTS)
|
|
657
|
+
.optional()
|
|
658
|
+
.describe("Client context for adapted snippets"),
|
|
659
|
+
},
|
|
660
|
+
annotations: getWorkflowGuideAnnotations,
|
|
661
|
+
}, async (args) => {
|
|
662
|
+
debug("get_workflow_guide called", args);
|
|
663
|
+
const input = GetWorkflowGuideInputSchema.parse(args);
|
|
664
|
+
const { text } = executeGetWorkflowGuide(input);
|
|
665
|
+
return {
|
|
666
|
+
content: [{ type: "text", text }],
|
|
489
667
|
};
|
|
490
668
|
});
|
|
491
669
|
// ========================================================================
|
|
@@ -493,50 +671,60 @@ export function createServer() {
|
|
|
493
671
|
// ========================================================================
|
|
494
672
|
// Register estimate_project tool (API-based, requires API key with estimate:write)
|
|
495
673
|
server.registerTool(estimateProjectToolDefinition.name, {
|
|
496
|
-
title:
|
|
674
|
+
title: "Estimate Project",
|
|
497
675
|
description: estimateProjectToolDefinition.description,
|
|
498
676
|
inputSchema: {
|
|
499
677
|
specs: z
|
|
500
678
|
.string()
|
|
501
679
|
.min(100)
|
|
502
680
|
.max(10000)
|
|
503
|
-
.describe(
|
|
504
|
-
teamSize: z
|
|
681
|
+
.describe("Project specifications (min 100 chars, max 10,000)"),
|
|
682
|
+
teamSize: z
|
|
683
|
+
.number()
|
|
684
|
+
.min(1)
|
|
685
|
+
.max(100)
|
|
686
|
+
.optional()
|
|
687
|
+
.describe("Number of developers"),
|
|
505
688
|
seniorityLevel: z
|
|
506
|
-
.enum([
|
|
689
|
+
.enum(["junior", "mid", "senior", "expert"])
|
|
507
690
|
.optional()
|
|
508
|
-
.describe(
|
|
691
|
+
.describe("Average team seniority (default: mid)"),
|
|
509
692
|
region: z
|
|
510
|
-
.enum([
|
|
693
|
+
.enum(["france", "us", "uk", "remote-global"])
|
|
694
|
+
.optional()
|
|
695
|
+
.describe("Region for pricing (default: france)"),
|
|
696
|
+
includeMarket: z
|
|
697
|
+
.boolean()
|
|
511
698
|
.optional()
|
|
512
|
-
.describe(
|
|
513
|
-
includeMarket: z.boolean().optional().describe('Include market analysis (default: true, Pro tier only)')
|
|
699
|
+
.describe("Include market analysis (default: true)"),
|
|
514
700
|
},
|
|
515
|
-
annotations: estimateProjectAnnotations
|
|
701
|
+
annotations: estimateProjectAnnotations,
|
|
516
702
|
}, async (args) => {
|
|
517
|
-
debug(
|
|
703
|
+
debug("estimate_project called", {
|
|
704
|
+
specsLength: args.specs?.length,
|
|
705
|
+
});
|
|
518
706
|
const input = EstimateProjectInputSchema.parse(args);
|
|
519
707
|
const { text, isError } = await executeEstimateProject(input);
|
|
520
708
|
return {
|
|
521
|
-
content: [{ type:
|
|
522
|
-
isError
|
|
709
|
+
content: [{ type: "text", text }],
|
|
710
|
+
isError,
|
|
523
711
|
};
|
|
524
712
|
});
|
|
525
713
|
// Register get_estimate_quota tool (API-based, requires API key)
|
|
526
714
|
server.registerTool(getEstimateQuotaToolDefinition.name, {
|
|
527
|
-
title:
|
|
715
|
+
title: "Get Estimate Quota",
|
|
528
716
|
description: getEstimateQuotaToolDefinition.description,
|
|
529
717
|
inputSchema: {},
|
|
530
|
-
annotations: getEstimateQuotaAnnotations
|
|
718
|
+
annotations: getEstimateQuotaAnnotations,
|
|
531
719
|
}, async () => {
|
|
532
|
-
debug(
|
|
720
|
+
debug("get_estimate_quota called");
|
|
533
721
|
const { text, isError } = await executeGetEstimateQuota({});
|
|
534
722
|
return {
|
|
535
|
-
content: [{ type:
|
|
536
|
-
isError
|
|
723
|
+
content: [{ type: "text", text }],
|
|
724
|
+
isError,
|
|
537
725
|
};
|
|
538
726
|
});
|
|
539
|
-
info(
|
|
727
|
+
info("Registered 26 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_api_key, create_audit, get_audit, list_audits, compare_audits, get_audit_quota, get_migration_recommendation, import_better_t_stack, generate_mcp_kit, analyze_repo_mcps, prepare_mcp_installation, execute_mcp_installation, check_mcp_compatibility, get_workflow_guide, estimate_project, get_estimate_quota");
|
|
540
728
|
return server;
|
|
541
729
|
}
|
|
542
730
|
// ============================================================================
|
|
@@ -547,102 +735,102 @@ export function createServer() {
|
|
|
547
735
|
*/
|
|
548
736
|
function formatAnalysisResult(result) {
|
|
549
737
|
const lines = [];
|
|
550
|
-
lines.push(
|
|
738
|
+
lines.push("# Repository Analysis\n");
|
|
551
739
|
// Detected Stack
|
|
552
|
-
lines.push(
|
|
740
|
+
lines.push("## Detected Technologies\n");
|
|
553
741
|
const stackItems = [
|
|
554
742
|
result.detectedStack.frontend &&
|
|
555
|
-
`- **Frontend**: ${result.detectedStack.frontend.name}${result.detectedStack.frontend.version ? ` (${result.detectedStack.frontend.version})` :
|
|
743
|
+
`- **Frontend**: ${result.detectedStack.frontend.name}${result.detectedStack.frontend.version ? ` (${result.detectedStack.frontend.version})` : ""}`,
|
|
556
744
|
result.detectedStack.backend &&
|
|
557
|
-
`- **Backend**: ${result.detectedStack.backend.name}${result.detectedStack.backend.version ? ` (${result.detectedStack.backend.version})` :
|
|
745
|
+
`- **Backend**: ${result.detectedStack.backend.name}${result.detectedStack.backend.version ? ` (${result.detectedStack.backend.version})` : ""}`,
|
|
558
746
|
result.detectedStack.database &&
|
|
559
|
-
`- **Database**: ${result.detectedStack.database.name}${result.detectedStack.database.version ? ` (${result.detectedStack.database.version})` :
|
|
747
|
+
`- **Database**: ${result.detectedStack.database.name}${result.detectedStack.database.version ? ` (${result.detectedStack.database.version})` : ""}`,
|
|
560
748
|
result.detectedStack.orm &&
|
|
561
|
-
`- **ORM**: ${result.detectedStack.orm.name}${result.detectedStack.orm.version ? ` (${result.detectedStack.orm.version})` :
|
|
749
|
+
`- **ORM**: ${result.detectedStack.orm.name}${result.detectedStack.orm.version ? ` (${result.detectedStack.orm.version})` : ""}`,
|
|
562
750
|
result.detectedStack.auth &&
|
|
563
|
-
`- **Auth**: ${result.detectedStack.auth.name}${result.detectedStack.auth.version ? ` (${result.detectedStack.auth.version})` :
|
|
751
|
+
`- **Auth**: ${result.detectedStack.auth.name}${result.detectedStack.auth.version ? ` (${result.detectedStack.auth.version})` : ""}`,
|
|
564
752
|
result.detectedStack.hosting &&
|
|
565
|
-
`- **Hosting**: ${result.detectedStack.hosting.name}${result.detectedStack.hosting.version ? ` (${result.detectedStack.hosting.version})` :
|
|
753
|
+
`- **Hosting**: ${result.detectedStack.hosting.name}${result.detectedStack.hosting.version ? ` (${result.detectedStack.hosting.version})` : ""}`,
|
|
566
754
|
result.detectedStack.payments &&
|
|
567
|
-
`- **Payments**: ${result.detectedStack.payments.name}${result.detectedStack.payments.version ? ` (${result.detectedStack.payments.version})` :
|
|
755
|
+
`- **Payments**: ${result.detectedStack.payments.name}${result.detectedStack.payments.version ? ` (${result.detectedStack.payments.version})` : ""}`,
|
|
568
756
|
].filter((item) => Boolean(item));
|
|
569
757
|
if (stackItems.length > 0) {
|
|
570
758
|
lines.push(...stackItems);
|
|
571
759
|
}
|
|
572
760
|
else {
|
|
573
|
-
lines.push(
|
|
761
|
+
lines.push("_No technologies detected from project files._");
|
|
574
762
|
}
|
|
575
763
|
if (result.detectedStack.services.length > 0) {
|
|
576
|
-
lines.push(
|
|
764
|
+
lines.push("\n**Services**:");
|
|
577
765
|
for (const service of result.detectedStack.services) {
|
|
578
766
|
lines.push(`- ${service.name}`);
|
|
579
767
|
}
|
|
580
768
|
}
|
|
581
|
-
lines.push(
|
|
769
|
+
lines.push("");
|
|
582
770
|
// Files Analyzed
|
|
583
|
-
lines.push(
|
|
771
|
+
lines.push("## Files Analyzed\n");
|
|
584
772
|
if (result.metadata.filesAnalyzed.length > 0) {
|
|
585
|
-
lines.push(result.metadata.filesAnalyzed.map((f) => `- \`${f}\``).join(
|
|
773
|
+
lines.push(result.metadata.filesAnalyzed.map((f) => `- \`${f}\``).join("\n"));
|
|
586
774
|
}
|
|
587
775
|
else {
|
|
588
|
-
lines.push(
|
|
776
|
+
lines.push("_No recognized configuration files found._");
|
|
589
777
|
}
|
|
590
|
-
lines.push(
|
|
778
|
+
lines.push("");
|
|
591
779
|
// Installed MCPs
|
|
592
780
|
if (result.installedMcps.length > 0) {
|
|
593
|
-
lines.push(
|
|
594
|
-
lines.push(result.installedMcps.map((m) => `- ${m}`).join(
|
|
595
|
-
lines.push(
|
|
781
|
+
lines.push("## Already Installed MCPs\n");
|
|
782
|
+
lines.push(result.installedMcps.map((m) => `- ${m}`).join("\n"));
|
|
783
|
+
lines.push("");
|
|
596
784
|
}
|
|
597
785
|
// Recommended MCPs
|
|
598
|
-
lines.push(
|
|
786
|
+
lines.push("## Recommended MCPs\n");
|
|
599
787
|
if (result.recommendedMcps.length === 0) {
|
|
600
|
-
lines.push(
|
|
788
|
+
lines.push("_No additional MCPs recommended. You have everything you need!_");
|
|
601
789
|
}
|
|
602
790
|
else {
|
|
603
791
|
// Group by priority
|
|
604
|
-
const highPriority = result.recommendedMcps.filter((m) => m.priority ===
|
|
605
|
-
const mediumPriority = result.recommendedMcps.filter((m) => m.priority ===
|
|
606
|
-
const lowPriority = result.recommendedMcps.filter((m) => m.priority ===
|
|
792
|
+
const highPriority = result.recommendedMcps.filter((m) => m.priority === "high");
|
|
793
|
+
const mediumPriority = result.recommendedMcps.filter((m) => m.priority === "medium");
|
|
794
|
+
const lowPriority = result.recommendedMcps.filter((m) => m.priority === "low");
|
|
607
795
|
if (highPriority.length > 0) {
|
|
608
|
-
lines.push(
|
|
796
|
+
lines.push("### High Priority\n");
|
|
609
797
|
for (const mcp of highPriority) {
|
|
610
798
|
lines.push(`**${mcp.name}** (\`${mcp.slug}\`)`);
|
|
611
799
|
lines.push(`- ${mcp.description}`);
|
|
612
800
|
lines.push(`- _Matched: ${mcp.matchedTech}_`);
|
|
613
|
-
lines.push(
|
|
801
|
+
lines.push("");
|
|
614
802
|
}
|
|
615
803
|
}
|
|
616
804
|
if (mediumPriority.length > 0) {
|
|
617
|
-
lines.push(
|
|
805
|
+
lines.push("### Medium Priority\n");
|
|
618
806
|
for (const mcp of mediumPriority) {
|
|
619
807
|
lines.push(`**${mcp.name}** (\`${mcp.slug}\`)`);
|
|
620
808
|
lines.push(`- ${mcp.description}`);
|
|
621
809
|
lines.push(`- _Matched: ${mcp.matchedTech}_`);
|
|
622
|
-
lines.push(
|
|
810
|
+
lines.push("");
|
|
623
811
|
}
|
|
624
812
|
}
|
|
625
813
|
if (lowPriority.length > 0) {
|
|
626
|
-
lines.push(
|
|
814
|
+
lines.push("### Low Priority\n");
|
|
627
815
|
for (const mcp of lowPriority) {
|
|
628
816
|
lines.push(`**${mcp.name}** (\`${mcp.slug}\`)`);
|
|
629
817
|
lines.push(`- ${mcp.description}`);
|
|
630
818
|
lines.push(`- _Matched: ${mcp.matchedTech}_`);
|
|
631
|
-
lines.push(
|
|
819
|
+
lines.push("");
|
|
632
820
|
}
|
|
633
821
|
}
|
|
634
822
|
}
|
|
635
823
|
// Quick Install
|
|
636
824
|
if (result.recommendedMcps.length > 0) {
|
|
637
|
-
lines.push(
|
|
638
|
-
lines.push(
|
|
639
|
-
lines.push(
|
|
825
|
+
lines.push("## Quick Install\n");
|
|
826
|
+
lines.push("Add to your Claude Desktop config (`claude_desktop_config.json`):\n");
|
|
827
|
+
lines.push("```json");
|
|
640
828
|
lines.push(JSON.stringify(result.installConfig.claudeDesktop, null, 2));
|
|
641
|
-
lines.push(
|
|
829
|
+
lines.push("```\n");
|
|
642
830
|
}
|
|
643
831
|
// Metadata
|
|
644
832
|
lines.push(`---\n_Analysis completed: ${result.metadata.analysisDate}_`);
|
|
645
|
-
return lines.join(
|
|
833
|
+
return lines.join("\n");
|
|
646
834
|
}
|
|
647
835
|
/**
|
|
648
836
|
* Format prepare_mcp_installation result summary.
|
|
@@ -651,44 +839,44 @@ function formatPreparationSummary(result) {
|
|
|
651
839
|
const lines = [];
|
|
652
840
|
// MCPs to install grouped by priority
|
|
653
841
|
if (result.mcpsToInstall.length > 0) {
|
|
654
|
-
lines.push(
|
|
655
|
-
const highPriority = result.mcpsToInstall.filter((m) => m.priority ===
|
|
656
|
-
const mediumPriority = result.mcpsToInstall.filter((m) => m.priority ===
|
|
657
|
-
const lowPriority = result.mcpsToInstall.filter((m) => m.priority ===
|
|
842
|
+
lines.push("## MCPs to Install\n");
|
|
843
|
+
const highPriority = result.mcpsToInstall.filter((m) => m.priority === "high");
|
|
844
|
+
const mediumPriority = result.mcpsToInstall.filter((m) => m.priority === "medium");
|
|
845
|
+
const lowPriority = result.mcpsToInstall.filter((m) => m.priority === "low");
|
|
658
846
|
if (highPriority.length > 0) {
|
|
659
|
-
lines.push(
|
|
847
|
+
lines.push("### 🔴 High Priority");
|
|
660
848
|
for (const mcp of highPriority) {
|
|
661
|
-
const requiredVars = mcp.envVars.filter((v) => v.requirement ===
|
|
849
|
+
const requiredVars = mcp.envVars.filter((v) => v.requirement === "required").length;
|
|
662
850
|
lines.push(`- **${mcp.name}** (${requiredVars} required vars)`);
|
|
663
851
|
}
|
|
664
|
-
lines.push(
|
|
852
|
+
lines.push("");
|
|
665
853
|
}
|
|
666
854
|
if (mediumPriority.length > 0) {
|
|
667
|
-
lines.push(
|
|
855
|
+
lines.push("### 🟡 Medium Priority");
|
|
668
856
|
for (const mcp of mediumPriority) {
|
|
669
|
-
const requiredVars = mcp.envVars.filter((v) => v.requirement ===
|
|
857
|
+
const requiredVars = mcp.envVars.filter((v) => v.requirement === "required").length;
|
|
670
858
|
lines.push(`- **${mcp.name}** (${requiredVars} required vars)`);
|
|
671
859
|
}
|
|
672
|
-
lines.push(
|
|
860
|
+
lines.push("");
|
|
673
861
|
}
|
|
674
862
|
if (lowPriority.length > 0) {
|
|
675
|
-
lines.push(
|
|
863
|
+
lines.push("### 🟢 Low Priority");
|
|
676
864
|
for (const mcp of lowPriority) {
|
|
677
|
-
const requiredVars = mcp.envVars.filter((v) => v.requirement ===
|
|
865
|
+
const requiredVars = mcp.envVars.filter((v) => v.requirement === "required").length;
|
|
678
866
|
lines.push(`- **${mcp.name}** (${requiredVars} required vars)`);
|
|
679
867
|
}
|
|
680
|
-
lines.push(
|
|
868
|
+
lines.push("");
|
|
681
869
|
}
|
|
682
870
|
}
|
|
683
871
|
// Already installed
|
|
684
872
|
if (result.installedMcps.length > 0) {
|
|
685
|
-
lines.push(
|
|
873
|
+
lines.push("## Already Installed");
|
|
686
874
|
for (const mcp of result.installedMcps) {
|
|
687
875
|
lines.push(`- ✅ ${mcp}`);
|
|
688
876
|
}
|
|
689
|
-
lines.push(
|
|
877
|
+
lines.push("");
|
|
690
878
|
}
|
|
691
|
-
return lines.join(
|
|
879
|
+
return lines.join("\n");
|
|
692
880
|
}
|
|
693
881
|
/**
|
|
694
882
|
* Format execute_mcp_installation result.
|
|
@@ -696,33 +884,33 @@ function formatPreparationSummary(result) {
|
|
|
696
884
|
function formatExecutionResult(result) {
|
|
697
885
|
const lines = [];
|
|
698
886
|
lines.push(result.message);
|
|
699
|
-
lines.push(
|
|
887
|
+
lines.push("");
|
|
700
888
|
// Show aggregate command for Claude Code
|
|
701
889
|
if (result.aggregateCommand) {
|
|
702
|
-
lines.push(
|
|
703
|
-
lines.push(
|
|
704
|
-
lines.push(
|
|
705
|
-
lines.push(
|
|
890
|
+
lines.push("---\n");
|
|
891
|
+
lines.push("## Claude Code Installation\n");
|
|
892
|
+
lines.push("Run this command to install all ready MCPs:\n");
|
|
893
|
+
lines.push("```bash");
|
|
706
894
|
lines.push(result.aggregateCommand);
|
|
707
|
-
lines.push(
|
|
895
|
+
lines.push("```\n");
|
|
708
896
|
}
|
|
709
897
|
// Show JSON config for other clients
|
|
710
898
|
if (result.aggregateConfig && !result.aggregateCommand) {
|
|
711
|
-
lines.push(
|
|
712
|
-
lines.push(
|
|
713
|
-
lines.push(
|
|
714
|
-
lines.push(
|
|
899
|
+
lines.push("---\n");
|
|
900
|
+
lines.push("## JSON Configuration\n");
|
|
901
|
+
lines.push("Add this to your MCP configuration file:\n");
|
|
902
|
+
lines.push("```json");
|
|
715
903
|
lines.push(JSON.stringify(result.aggregateConfig, null, 2));
|
|
716
|
-
lines.push(
|
|
904
|
+
lines.push("```\n");
|
|
717
905
|
}
|
|
718
906
|
// Post-install instructions
|
|
719
907
|
if (result.postInstallInstructions.length > 0) {
|
|
720
|
-
lines.push(
|
|
721
|
-
lines.push(
|
|
908
|
+
lines.push("---\n");
|
|
909
|
+
lines.push("## Post-Installation\n");
|
|
722
910
|
for (const instruction of result.postInstallInstructions) {
|
|
723
911
|
lines.push(instruction);
|
|
724
912
|
}
|
|
725
913
|
}
|
|
726
|
-
return lines.join(
|
|
914
|
+
return lines.join("\n");
|
|
727
915
|
}
|
|
728
916
|
//# sourceMappingURL=server.js.map
|