mcp-new 1.2.1 → 1.5.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/README.md +48 -1
- package/dist/{chunk-BHGUGEHE.js → chunk-YISSMIHU.js} +223 -46
- package/dist/cli.js +817 -51
- package/dist/index.d.ts +25 -7
- package/dist/index.js +17 -3
- package/package.json +1 -1
- package/templates/csharp/.env.example +6 -0
- package/templates/csharp/.gitignore.ejs +53 -0
- package/templates/csharp/McpServer.csproj.ejs +19 -0
- package/templates/csharp/README.md.ejs +136 -0
- package/templates/csharp/src/Program.cs.ejs +117 -0
- package/templates/elixir/.env.example +6 -0
- package/templates/elixir/.gitignore.ejs +33 -0
- package/templates/elixir/README.md.ejs +154 -0
- package/templates/elixir/config/config.exs.ejs +9 -0
- package/templates/elixir/config/dev.exs.ejs +3 -0
- package/templates/elixir/config/prod.exs.ejs +3 -0
- package/templates/elixir/lib/application.ex.ejs +19 -0
- package/templates/elixir/lib/cli.ex.ejs +17 -0
- package/templates/elixir/lib/server.ex.ejs +112 -0
- package/templates/elixir/mix.exs.ejs +32 -0
- package/templates/java/gradle/.env.example +6 -0
- package/templates/java/gradle/.gitignore.ejs +48 -0
- package/templates/java/gradle/README.md.ejs +132 -0
- package/templates/java/gradle/build.gradle.ejs +46 -0
- package/templates/java/gradle/settings.gradle.ejs +1 -0
- package/templates/java/gradle/src/main/java/com/example/mcp/McpServer.java.ejs +149 -0
- package/templates/java/gradle/src/main/resources/logback.xml +13 -0
- package/templates/java/maven/.env.example +6 -0
- package/templates/java/maven/.gitignore.ejs +53 -0
- package/templates/java/maven/README.md.ejs +131 -0
- package/templates/java/maven/pom.xml.ejs +86 -0
- package/templates/java/maven/src/main/java/com/example/mcp/McpServer.java.ejs +149 -0
- package/templates/java/maven/src/main/resources/logback.xml +13 -0
- package/templates/kotlin/gradle/.env.example +6 -0
- package/templates/kotlin/gradle/.gitignore.ejs +45 -0
- package/templates/kotlin/gradle/README.md.ejs +138 -0
- package/templates/kotlin/gradle/build.gradle.kts.ejs +48 -0
- package/templates/kotlin/gradle/settings.gradle.kts.ejs +1 -0
- package/templates/kotlin/gradle/src/main/kotlin/com/example/mcp/McpServer.kt.ejs +141 -0
- package/templates/kotlin/gradle/src/main/resources/logback.xml +13 -0
- package/templates/kotlin/maven/.env.example +6 -0
- package/templates/kotlin/maven/.gitignore.ejs +50 -0
- package/templates/kotlin/maven/README.md.ejs +96 -0
- package/templates/kotlin/maven/pom.xml.ejs +105 -0
- package/templates/kotlin/maven/src/main/kotlin/com/example/mcp/McpServer.kt.ejs +141 -0
- package/templates/kotlin/maven/src/main/resources/logback.xml +13 -0
package/dist/cli.js
CHANGED
|
@@ -1,84 +1,850 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
import {
|
|
3
|
+
PRESETS,
|
|
3
4
|
addToolCommand,
|
|
4
5
|
createCommand,
|
|
5
|
-
|
|
6
|
-
|
|
6
|
+
createInitialCommit,
|
|
7
|
+
createSpinner,
|
|
8
|
+
ensureDir,
|
|
9
|
+
exists,
|
|
10
|
+
generateFromWizard,
|
|
11
|
+
initCommand,
|
|
12
|
+
initGitRepository,
|
|
13
|
+
isGitInstalled,
|
|
14
|
+
logger,
|
|
15
|
+
promptJavaBuildTool,
|
|
16
|
+
promptLanguage,
|
|
17
|
+
readDir,
|
|
18
|
+
readFile,
|
|
19
|
+
withSpinner,
|
|
20
|
+
writeFile
|
|
21
|
+
} from "./chunk-YISSMIHU.js";
|
|
7
22
|
|
|
8
23
|
// src/cli.ts
|
|
9
24
|
import { Command } from "commander";
|
|
25
|
+
import chalk4 from "chalk";
|
|
26
|
+
|
|
27
|
+
// src/commands/list-presets.ts
|
|
10
28
|
import chalk from "chalk";
|
|
29
|
+
async function listPresetsCommand() {
|
|
30
|
+
console.log();
|
|
31
|
+
console.log(chalk.bold.white("Available Presets"));
|
|
32
|
+
console.log(chalk.gray("\u2500".repeat(60)));
|
|
33
|
+
console.log();
|
|
34
|
+
for (const [id, preset] of Object.entries(PRESETS)) {
|
|
35
|
+
console.log(chalk.yellow.bold(` ${id}`));
|
|
36
|
+
console.log(chalk.gray(` ${preset.description}`));
|
|
37
|
+
console.log();
|
|
38
|
+
console.log(chalk.white(" Tools:"));
|
|
39
|
+
for (const tool of preset.tools) {
|
|
40
|
+
const paramCount = tool.parameters.length;
|
|
41
|
+
const paramText = paramCount === 0 ? chalk.gray("no params") : chalk.gray(`${paramCount} param${paramCount > 1 ? "s" : ""}`);
|
|
42
|
+
console.log(` ${chalk.cyan("\u2022")} ${chalk.white(tool.name)} ${paramText}`);
|
|
43
|
+
console.log(` ${chalk.gray(tool.description)}`);
|
|
44
|
+
}
|
|
45
|
+
console.log();
|
|
46
|
+
console.log(chalk.gray(" " + "\u2500".repeat(56)));
|
|
47
|
+
console.log();
|
|
48
|
+
}
|
|
49
|
+
console.log(chalk.bold.white("Usage:"));
|
|
50
|
+
console.log();
|
|
51
|
+
console.log(chalk.gray(" $"), chalk.cyan("mcp-new my-project --preset database"));
|
|
52
|
+
console.log(chalk.gray(" $"), chalk.cyan("mcp-new my-api --preset rest-api -t"));
|
|
53
|
+
console.log(chalk.gray(" $"), chalk.cyan("mcp-new my-fs --preset filesystem -p"));
|
|
54
|
+
console.log();
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
// src/commands/validate.ts
|
|
58
|
+
import path from "path";
|
|
59
|
+
import fs from "fs-extra";
|
|
60
|
+
import chalk2 from "chalk";
|
|
61
|
+
async function validateCommand() {
|
|
62
|
+
const currentDir = process.cwd();
|
|
63
|
+
logger.title("Validating MCP Server");
|
|
64
|
+
const result = await validateProject(currentDir);
|
|
65
|
+
console.log();
|
|
66
|
+
if (result.language) {
|
|
67
|
+
console.log(chalk2.blue("i"), `Detected language: ${chalk2.cyan(result.language)}`);
|
|
68
|
+
}
|
|
69
|
+
for (const info of result.info) {
|
|
70
|
+
console.log(chalk2.blue("i"), info);
|
|
71
|
+
}
|
|
72
|
+
for (const warning of result.warnings) {
|
|
73
|
+
console.log(chalk2.yellow("\u26A0"), warning);
|
|
74
|
+
}
|
|
75
|
+
for (const error of result.errors) {
|
|
76
|
+
console.log(chalk2.red("\u2717"), error);
|
|
77
|
+
}
|
|
78
|
+
console.log();
|
|
79
|
+
if (result.valid) {
|
|
80
|
+
logger.success("MCP server is valid!");
|
|
81
|
+
} else {
|
|
82
|
+
logger.error("Validation failed. Please fix the issues above.");
|
|
83
|
+
process.exit(1);
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
async function validateProject(projectDir) {
|
|
87
|
+
const result = {
|
|
88
|
+
valid: true,
|
|
89
|
+
language: null,
|
|
90
|
+
errors: [],
|
|
91
|
+
warnings: [],
|
|
92
|
+
info: []
|
|
93
|
+
};
|
|
94
|
+
const hasPackageJson = await fs.pathExists(path.join(projectDir, "package.json"));
|
|
95
|
+
const hasPyproject = await fs.pathExists(path.join(projectDir, "pyproject.toml"));
|
|
96
|
+
const hasGoMod = await fs.pathExists(path.join(projectDir, "go.mod"));
|
|
97
|
+
const hasCargoToml = await fs.pathExists(path.join(projectDir, "Cargo.toml"));
|
|
98
|
+
if (!hasPackageJson && !hasPyproject && !hasGoMod && !hasCargoToml) {
|
|
99
|
+
result.errors.push("No project configuration found (package.json, pyproject.toml, go.mod, or Cargo.toml)");
|
|
100
|
+
result.valid = false;
|
|
101
|
+
return result;
|
|
102
|
+
}
|
|
103
|
+
if (hasPackageJson) {
|
|
104
|
+
result.language = "typescript";
|
|
105
|
+
await validateTypeScriptProject(projectDir, result);
|
|
106
|
+
}
|
|
107
|
+
if (hasPyproject) {
|
|
108
|
+
result.language = "python";
|
|
109
|
+
await validatePythonProject(projectDir, result);
|
|
110
|
+
}
|
|
111
|
+
if (hasGoMod) {
|
|
112
|
+
result.language = "go";
|
|
113
|
+
await validateGoProject(projectDir, result);
|
|
114
|
+
}
|
|
115
|
+
if (hasCargoToml) {
|
|
116
|
+
result.language = "rust";
|
|
117
|
+
await validateRustProject(projectDir, result);
|
|
118
|
+
}
|
|
119
|
+
return result;
|
|
120
|
+
}
|
|
121
|
+
async function validateTypeScriptProject(projectDir, result) {
|
|
122
|
+
try {
|
|
123
|
+
const packageJsonPath = path.join(projectDir, "package.json");
|
|
124
|
+
const packageJson = await fs.readJson(packageJsonPath);
|
|
125
|
+
const deps = { ...packageJson.dependencies, ...packageJson.devDependencies };
|
|
126
|
+
if (deps["@modelcontextprotocol/sdk"]) {
|
|
127
|
+
result.info.push(`MCP SDK version: ${chalk2.green(deps["@modelcontextprotocol/sdk"])}`);
|
|
128
|
+
} else {
|
|
129
|
+
result.errors.push("Missing @modelcontextprotocol/sdk dependency");
|
|
130
|
+
result.valid = false;
|
|
131
|
+
}
|
|
132
|
+
const srcIndex = path.join(projectDir, "src", "index.ts");
|
|
133
|
+
const srcIndexJs = path.join(projectDir, "src", "index.js");
|
|
134
|
+
const distIndex = path.join(projectDir, "dist", "index.js");
|
|
135
|
+
if (await fs.pathExists(srcIndex)) {
|
|
136
|
+
result.info.push("Entry point: src/index.ts");
|
|
137
|
+
await validateTypeScriptEntryPoint(srcIndex, result);
|
|
138
|
+
} else if (await fs.pathExists(srcIndexJs)) {
|
|
139
|
+
result.info.push("Entry point: src/index.js");
|
|
140
|
+
} else if (await fs.pathExists(distIndex)) {
|
|
141
|
+
result.info.push("Entry point: dist/index.js (built)");
|
|
142
|
+
} else {
|
|
143
|
+
result.warnings.push("No entry point found (expected src/index.ts or src/index.js)");
|
|
144
|
+
}
|
|
145
|
+
if (await fs.pathExists(path.join(projectDir, "tsconfig.json"))) {
|
|
146
|
+
result.info.push("TypeScript config: tsconfig.json");
|
|
147
|
+
} else {
|
|
148
|
+
result.warnings.push("No tsconfig.json found");
|
|
149
|
+
}
|
|
150
|
+
if (packageJson.scripts?.build) {
|
|
151
|
+
result.info.push(`Build script: ${chalk2.gray(packageJson.scripts.build)}`);
|
|
152
|
+
} else {
|
|
153
|
+
result.warnings.push("No build script found in package.json");
|
|
154
|
+
}
|
|
155
|
+
} catch (error) {
|
|
156
|
+
result.errors.push("Failed to parse package.json");
|
|
157
|
+
result.valid = false;
|
|
158
|
+
}
|
|
159
|
+
}
|
|
160
|
+
async function validateTypeScriptEntryPoint(filePath, result) {
|
|
161
|
+
try {
|
|
162
|
+
const content = await fs.readFile(filePath, "utf-8");
|
|
163
|
+
if (content.includes("@modelcontextprotocol/sdk")) {
|
|
164
|
+
result.info.push("MCP SDK import found");
|
|
165
|
+
} else {
|
|
166
|
+
result.warnings.push("No MCP SDK import found in entry point");
|
|
167
|
+
}
|
|
168
|
+
if (content.includes("McpServer") || content.includes("Server")) {
|
|
169
|
+
result.info.push("MCP Server class usage found");
|
|
170
|
+
} else {
|
|
171
|
+
result.warnings.push("No MCP Server class found");
|
|
172
|
+
}
|
|
173
|
+
const toolMatches = content.match(/\.tool\s*\(/g) || content.match(/setRequestHandler.*CallToolRequest/g);
|
|
174
|
+
if (toolMatches) {
|
|
175
|
+
result.info.push(`Tools defined: ${chalk2.green(toolMatches.length)}`);
|
|
176
|
+
}
|
|
177
|
+
} catch {
|
|
178
|
+
result.warnings.push("Could not analyze entry point file");
|
|
179
|
+
}
|
|
180
|
+
}
|
|
181
|
+
async function validatePythonProject(projectDir, result) {
|
|
182
|
+
try {
|
|
183
|
+
const pyprojectPath = path.join(projectDir, "pyproject.toml");
|
|
184
|
+
const content = await fs.readFile(pyprojectPath, "utf-8");
|
|
185
|
+
if (content.includes("mcp") || content.includes("modelcontextprotocol")) {
|
|
186
|
+
result.info.push("MCP dependency found in pyproject.toml");
|
|
187
|
+
} else {
|
|
188
|
+
const requirementsPath = path.join(projectDir, "requirements.txt");
|
|
189
|
+
if (await fs.pathExists(requirementsPath)) {
|
|
190
|
+
const requirements = await fs.readFile(requirementsPath, "utf-8");
|
|
191
|
+
if (requirements.includes("mcp")) {
|
|
192
|
+
result.info.push("MCP dependency found in requirements.txt");
|
|
193
|
+
} else {
|
|
194
|
+
result.errors.push("Missing MCP dependency");
|
|
195
|
+
result.valid = false;
|
|
196
|
+
}
|
|
197
|
+
} else {
|
|
198
|
+
result.warnings.push("No requirements.txt found");
|
|
199
|
+
}
|
|
200
|
+
}
|
|
201
|
+
const serverPath = path.join(projectDir, "src", "server.py");
|
|
202
|
+
if (await fs.pathExists(serverPath)) {
|
|
203
|
+
result.info.push("Server file: src/server.py");
|
|
204
|
+
} else {
|
|
205
|
+
result.warnings.push("No server.py found in src/");
|
|
206
|
+
}
|
|
207
|
+
} catch (error) {
|
|
208
|
+
result.errors.push("Failed to parse pyproject.toml");
|
|
209
|
+
result.valid = false;
|
|
210
|
+
}
|
|
211
|
+
}
|
|
212
|
+
async function validateGoProject(projectDir, result) {
|
|
213
|
+
try {
|
|
214
|
+
const goModPath = path.join(projectDir, "go.mod");
|
|
215
|
+
const content = await fs.readFile(goModPath, "utf-8");
|
|
216
|
+
if (content.includes("mcp-go") || content.includes("modelcontextprotocol")) {
|
|
217
|
+
result.info.push("MCP Go SDK found in go.mod");
|
|
218
|
+
} else {
|
|
219
|
+
result.errors.push("Missing MCP Go SDK dependency");
|
|
220
|
+
result.valid = false;
|
|
221
|
+
}
|
|
222
|
+
const mainPath = path.join(projectDir, "cmd", "server", "main.go");
|
|
223
|
+
const altMainPath = path.join(projectDir, "main.go");
|
|
224
|
+
if (await fs.pathExists(mainPath)) {
|
|
225
|
+
result.info.push("Entry point: cmd/server/main.go");
|
|
226
|
+
} else if (await fs.pathExists(altMainPath)) {
|
|
227
|
+
result.info.push("Entry point: main.go");
|
|
228
|
+
} else {
|
|
229
|
+
result.warnings.push("No main.go found");
|
|
230
|
+
}
|
|
231
|
+
} catch (error) {
|
|
232
|
+
result.errors.push("Failed to parse go.mod");
|
|
233
|
+
result.valid = false;
|
|
234
|
+
}
|
|
235
|
+
}
|
|
236
|
+
async function validateRustProject(projectDir, result) {
|
|
237
|
+
try {
|
|
238
|
+
const cargoPath = path.join(projectDir, "Cargo.toml");
|
|
239
|
+
const content = await fs.readFile(cargoPath, "utf-8");
|
|
240
|
+
if (content.includes("rmcp") || content.includes("mcp")) {
|
|
241
|
+
result.info.push("MCP Rust SDK found in Cargo.toml");
|
|
242
|
+
} else {
|
|
243
|
+
result.errors.push("Missing MCP Rust SDK dependency");
|
|
244
|
+
result.valid = false;
|
|
245
|
+
}
|
|
246
|
+
const mainPath = path.join(projectDir, "src", "main.rs");
|
|
247
|
+
if (await fs.pathExists(mainPath)) {
|
|
248
|
+
result.info.push("Entry point: src/main.rs");
|
|
249
|
+
} else {
|
|
250
|
+
result.warnings.push("No main.rs found");
|
|
251
|
+
}
|
|
252
|
+
} catch (error) {
|
|
253
|
+
result.errors.push("Failed to parse Cargo.toml");
|
|
254
|
+
result.valid = false;
|
|
255
|
+
}
|
|
256
|
+
}
|
|
257
|
+
|
|
258
|
+
// src/commands/upgrade.ts
|
|
259
|
+
import path2 from "path";
|
|
260
|
+
import fs2 from "fs-extra";
|
|
261
|
+
import chalk3 from "chalk";
|
|
262
|
+
import { execa } from "execa";
|
|
263
|
+
async function upgradeCommand(options) {
|
|
264
|
+
const currentDir = process.cwd();
|
|
265
|
+
logger.title("MCP SDK Upgrade");
|
|
266
|
+
const hasPackageJson = await fs2.pathExists(path2.join(currentDir, "package.json"));
|
|
267
|
+
const hasPyproject = await fs2.pathExists(path2.join(currentDir, "pyproject.toml"));
|
|
268
|
+
const hasGoMod = await fs2.pathExists(path2.join(currentDir, "go.mod"));
|
|
269
|
+
const hasCargoToml = await fs2.pathExists(path2.join(currentDir, "Cargo.toml"));
|
|
270
|
+
if (!hasPackageJson && !hasPyproject && !hasGoMod && !hasCargoToml) {
|
|
271
|
+
logger.error("No project configuration found.");
|
|
272
|
+
logger.info("Run this command from the root of your MCP server project.");
|
|
273
|
+
process.exit(1);
|
|
274
|
+
}
|
|
275
|
+
let info = null;
|
|
276
|
+
if (hasPackageJson) {
|
|
277
|
+
info = await checkNodePackage(currentDir);
|
|
278
|
+
} else if (hasPyproject) {
|
|
279
|
+
info = await checkPythonPackage(currentDir);
|
|
280
|
+
} else if (hasGoMod) {
|
|
281
|
+
info = await checkGoPackage(currentDir);
|
|
282
|
+
} else if (hasCargoToml) {
|
|
283
|
+
info = await checkRustPackage(currentDir);
|
|
284
|
+
}
|
|
285
|
+
if (!info) {
|
|
286
|
+
logger.error("Could not detect MCP SDK version.");
|
|
287
|
+
process.exit(1);
|
|
288
|
+
}
|
|
289
|
+
console.log();
|
|
290
|
+
console.log(chalk3.blue("i"), `Package: ${chalk3.cyan(info.packageName)}`);
|
|
291
|
+
console.log(chalk3.blue("i"), `Current version: ${info.current ? chalk3.yellow(info.current) : chalk3.gray("not installed")}`);
|
|
292
|
+
console.log(chalk3.blue("i"), `Latest version: ${info.latest ? chalk3.green(info.latest) : chalk3.gray("unknown")}`);
|
|
293
|
+
console.log();
|
|
294
|
+
if (options.check) {
|
|
295
|
+
if (info.current === info.latest) {
|
|
296
|
+
logger.success("Already up to date!");
|
|
297
|
+
} else if (info.latest) {
|
|
298
|
+
logger.info(`Update available: ${info.current} \u2192 ${info.latest}`);
|
|
299
|
+
logger.code(`mcp-new upgrade`);
|
|
300
|
+
}
|
|
301
|
+
return;
|
|
302
|
+
}
|
|
303
|
+
if (info.current === info.latest) {
|
|
304
|
+
logger.success("Already up to date!");
|
|
305
|
+
return;
|
|
306
|
+
}
|
|
307
|
+
if (!info.latest) {
|
|
308
|
+
logger.error("Could not fetch latest version.");
|
|
309
|
+
process.exit(1);
|
|
310
|
+
}
|
|
311
|
+
const spinner = createSpinner(`Upgrading ${info.packageName}...`);
|
|
312
|
+
spinner.start();
|
|
313
|
+
try {
|
|
314
|
+
if (hasPackageJson) {
|
|
315
|
+
await upgradeNodePackage(currentDir, info);
|
|
316
|
+
} else if (hasPyproject) {
|
|
317
|
+
await upgradePythonPackage(currentDir, info);
|
|
318
|
+
} else if (hasGoMod) {
|
|
319
|
+
await upgradeGoPackage(currentDir, info);
|
|
320
|
+
} else if (hasCargoToml) {
|
|
321
|
+
await upgradeRustPackage(currentDir, info);
|
|
322
|
+
}
|
|
323
|
+
spinner.succeed(`Upgraded to ${info.packageName}@${info.latest}`);
|
|
324
|
+
logger.blank();
|
|
325
|
+
logger.success("MCP SDK upgraded successfully!");
|
|
326
|
+
} catch (error) {
|
|
327
|
+
spinner.fail("Upgrade failed");
|
|
328
|
+
if (error instanceof Error) {
|
|
329
|
+
logger.error(error.message);
|
|
330
|
+
}
|
|
331
|
+
process.exit(1);
|
|
332
|
+
}
|
|
333
|
+
}
|
|
334
|
+
async function checkNodePackage(projectDir) {
|
|
335
|
+
const packageName = "@modelcontextprotocol/sdk";
|
|
336
|
+
let current = null;
|
|
337
|
+
let latest = null;
|
|
338
|
+
try {
|
|
339
|
+
const packageJson = await fs2.readJson(path2.join(projectDir, "package.json"));
|
|
340
|
+
const deps = { ...packageJson.dependencies, ...packageJson.devDependencies };
|
|
341
|
+
current = deps[packageName]?.replace(/[\^~]/, "") || null;
|
|
342
|
+
} catch {
|
|
343
|
+
}
|
|
344
|
+
try {
|
|
345
|
+
const { stdout } = await execa("npm", ["view", packageName, "version"]);
|
|
346
|
+
latest = stdout.trim();
|
|
347
|
+
} catch {
|
|
348
|
+
}
|
|
349
|
+
return { current, latest, packageManager: "npm", packageName };
|
|
350
|
+
}
|
|
351
|
+
async function upgradeNodePackage(projectDir, info) {
|
|
352
|
+
const packageJsonPath = path2.join(projectDir, "package.json");
|
|
353
|
+
const packageJson = await fs2.readJson(packageJsonPath);
|
|
354
|
+
if (packageJson.dependencies?.[info.packageName]) {
|
|
355
|
+
packageJson.dependencies[info.packageName] = `^${info.latest}`;
|
|
356
|
+
} else if (packageJson.devDependencies?.[info.packageName]) {
|
|
357
|
+
packageJson.devDependencies[info.packageName] = `^${info.latest}`;
|
|
358
|
+
}
|
|
359
|
+
await fs2.writeJson(packageJsonPath, packageJson, { spaces: 2 });
|
|
360
|
+
await execa("npm", ["install"], { cwd: projectDir });
|
|
361
|
+
}
|
|
362
|
+
async function checkPythonPackage(_projectDir) {
|
|
363
|
+
const packageName = "mcp";
|
|
364
|
+
let current = null;
|
|
365
|
+
let latest = null;
|
|
366
|
+
try {
|
|
367
|
+
const { stdout } = await execa("pip", ["show", packageName]);
|
|
368
|
+
const versionMatch = stdout.match(/Version:\s*(\S+)/);
|
|
369
|
+
current = versionMatch?.[1] || null;
|
|
370
|
+
} catch {
|
|
371
|
+
}
|
|
372
|
+
try {
|
|
373
|
+
const { stdout } = await execa("pip", ["index", "versions", packageName]);
|
|
374
|
+
const match = stdout.match(/Available versions:\s*([^\s,]+)/);
|
|
375
|
+
latest = match?.[1] || null;
|
|
376
|
+
} catch {
|
|
377
|
+
try {
|
|
378
|
+
const { stdout } = await execa("pip", ["install", `${packageName}==`, "--dry-run"], { reject: false });
|
|
379
|
+
const match = stdout.match(/from versions:\s*([^)]+)\)/);
|
|
380
|
+
if (match) {
|
|
381
|
+
const versions = match[1].split(",").map((v) => v.trim());
|
|
382
|
+
latest = versions[versions.length - 1] || null;
|
|
383
|
+
}
|
|
384
|
+
} catch {
|
|
385
|
+
}
|
|
386
|
+
}
|
|
387
|
+
return { current, latest, packageManager: "pip", packageName };
|
|
388
|
+
}
|
|
389
|
+
async function upgradePythonPackage(_projectDir, info) {
|
|
390
|
+
await execa("pip", ["install", "--upgrade", info.packageName]);
|
|
391
|
+
}
|
|
392
|
+
async function checkGoPackage(projectDir) {
|
|
393
|
+
const packageName = "github.com/mark3labs/mcp-go";
|
|
394
|
+
let current = null;
|
|
395
|
+
let latest = null;
|
|
396
|
+
try {
|
|
397
|
+
const goModContent = await fs2.readFile(path2.join(projectDir, "go.mod"), "utf-8");
|
|
398
|
+
const match = goModContent.match(new RegExp(`${packageName.replace(/\//g, "\\/")}\\s+v([\\d.]+)`));
|
|
399
|
+
current = match?.[1] || null;
|
|
400
|
+
} catch {
|
|
401
|
+
}
|
|
402
|
+
try {
|
|
403
|
+
const { stdout } = await execa("go", ["list", "-m", "-versions", packageName]);
|
|
404
|
+
const versions = stdout.split(" ").slice(1);
|
|
405
|
+
latest = versions[versions.length - 1]?.replace("v", "") || null;
|
|
406
|
+
} catch {
|
|
407
|
+
}
|
|
408
|
+
return { current, latest, packageManager: "go", packageName };
|
|
409
|
+
}
|
|
410
|
+
async function upgradeGoPackage(projectDir, info) {
|
|
411
|
+
await execa("go", ["get", "-u", `${info.packageName}@latest`], { cwd: projectDir });
|
|
412
|
+
await execa("go", ["mod", "tidy"], { cwd: projectDir });
|
|
413
|
+
}
|
|
414
|
+
async function checkRustPackage(projectDir) {
|
|
415
|
+
const packageName = "rmcp";
|
|
416
|
+
let current = null;
|
|
417
|
+
let latest = null;
|
|
418
|
+
try {
|
|
419
|
+
const cargoContent = await fs2.readFile(path2.join(projectDir, "Cargo.toml"), "utf-8");
|
|
420
|
+
const match = cargoContent.match(/rmcp\s*=\s*["']([^"']+)["']/);
|
|
421
|
+
current = match?.[1] || null;
|
|
422
|
+
} catch {
|
|
423
|
+
}
|
|
424
|
+
try {
|
|
425
|
+
const { stdout } = await execa("cargo", ["search", packageName, "--limit", "1"]);
|
|
426
|
+
const match = stdout.match(/rmcp\s*=\s*"([^"]+)"/);
|
|
427
|
+
latest = match?.[1] || null;
|
|
428
|
+
} catch {
|
|
429
|
+
}
|
|
430
|
+
return { current, latest, packageManager: "cargo", packageName };
|
|
431
|
+
}
|
|
432
|
+
async function upgradeRustPackage(projectDir, info) {
|
|
433
|
+
await execa("cargo", ["update", "-p", info.packageName], { cwd: projectDir });
|
|
434
|
+
}
|
|
435
|
+
|
|
436
|
+
// src/commands/monorepo.ts
|
|
437
|
+
import path3 from "path";
|
|
438
|
+
import inquirer from "inquirer";
|
|
439
|
+
async function monorepoInitCommand(workspaceName, options) {
|
|
440
|
+
try {
|
|
441
|
+
let name = workspaceName;
|
|
442
|
+
if (!name) {
|
|
443
|
+
const { inputName } = await inquirer.prompt([
|
|
444
|
+
{
|
|
445
|
+
type: "input",
|
|
446
|
+
name: "inputName",
|
|
447
|
+
message: "Workspace name:",
|
|
448
|
+
default: "mcp-workspace"
|
|
449
|
+
}
|
|
450
|
+
]);
|
|
451
|
+
name = inputName;
|
|
452
|
+
}
|
|
453
|
+
const outputDir = path3.resolve(process.cwd(), name);
|
|
454
|
+
if (await exists(outputDir)) {
|
|
455
|
+
const files = await readDir(outputDir);
|
|
456
|
+
if (files.length > 0 && !options.force) {
|
|
457
|
+
logger.error(
|
|
458
|
+
`Directory "${name}" already exists and is not empty. Use --force to override.`
|
|
459
|
+
);
|
|
460
|
+
process.exit(1);
|
|
461
|
+
}
|
|
462
|
+
}
|
|
463
|
+
logger.title(`Creating MCP Monorepo: ${name}`);
|
|
464
|
+
await withSpinner(
|
|
465
|
+
"Creating workspace structure...",
|
|
466
|
+
async () => {
|
|
467
|
+
await ensureDir(outputDir);
|
|
468
|
+
await ensureDir(path3.join(outputDir, "packages"));
|
|
469
|
+
await ensureDir(path3.join(outputDir, "shared"));
|
|
470
|
+
},
|
|
471
|
+
"Workspace structure created"
|
|
472
|
+
);
|
|
473
|
+
const workspaceConfig = {
|
|
474
|
+
name,
|
|
475
|
+
packages: []
|
|
476
|
+
};
|
|
477
|
+
await withSpinner(
|
|
478
|
+
"Creating configuration files...",
|
|
479
|
+
async () => {
|
|
480
|
+
await writeFile(
|
|
481
|
+
path3.join(outputDir, "mcp.workspace.json"),
|
|
482
|
+
JSON.stringify(workspaceConfig, null, 2)
|
|
483
|
+
);
|
|
484
|
+
const packageJson = {
|
|
485
|
+
name,
|
|
486
|
+
version: "1.0.0",
|
|
487
|
+
private: true,
|
|
488
|
+
workspaces: ["packages/*", "shared/*"],
|
|
489
|
+
scripts: {
|
|
490
|
+
build: "npm run build --workspaces",
|
|
491
|
+
dev: "npm run dev --workspaces --if-present",
|
|
492
|
+
test: "npm run test --workspaces --if-present"
|
|
493
|
+
}
|
|
494
|
+
};
|
|
495
|
+
await writeFile(path3.join(outputDir, "package.json"), JSON.stringify(packageJson, null, 2));
|
|
496
|
+
const readme = `# ${name}
|
|
497
|
+
|
|
498
|
+
MCP Monorepo Workspace
|
|
499
|
+
|
|
500
|
+
## Structure
|
|
501
|
+
|
|
502
|
+
\`\`\`
|
|
503
|
+
${name}/
|
|
504
|
+
\u251C\u2500\u2500 packages/ # MCP servers
|
|
505
|
+
\u251C\u2500\u2500 shared/ # Shared utilities and types
|
|
506
|
+
\u251C\u2500\u2500 mcp.workspace.json # Workspace configuration
|
|
507
|
+
\u2514\u2500\u2500 package.json # Root package.json
|
|
508
|
+
\`\`\`
|
|
509
|
+
|
|
510
|
+
## Commands
|
|
511
|
+
|
|
512
|
+
\`\`\`bash
|
|
513
|
+
# Add a new MCP server
|
|
514
|
+
mcp-new monorepo add <server-name>
|
|
515
|
+
|
|
516
|
+
# Build all packages
|
|
517
|
+
npm run build
|
|
518
|
+
|
|
519
|
+
# Run all dev servers
|
|
520
|
+
npm run dev
|
|
521
|
+
\`\`\`
|
|
522
|
+
|
|
523
|
+
## Packages
|
|
524
|
+
|
|
525
|
+
${workspaceConfig.packages.length === 0 ? "_No packages yet. Run `mcp-new monorepo add <name>` to create one._" : workspaceConfig.packages.map((p) => `- ${p}`).join("\n")}
|
|
526
|
+
`;
|
|
527
|
+
await writeFile(path3.join(outputDir, "README.md"), readme);
|
|
528
|
+
const gitignore = `# Dependencies
|
|
529
|
+
node_modules/
|
|
530
|
+
|
|
531
|
+
# Build outputs
|
|
532
|
+
dist/
|
|
533
|
+
build/
|
|
534
|
+
*.tsbuildinfo
|
|
535
|
+
|
|
536
|
+
# Environment
|
|
537
|
+
.env
|
|
538
|
+
.env.local
|
|
539
|
+
.env.*.local
|
|
540
|
+
|
|
541
|
+
# IDE
|
|
542
|
+
.idea/
|
|
543
|
+
.vscode/
|
|
544
|
+
*.swp
|
|
545
|
+
*.swo
|
|
546
|
+
|
|
547
|
+
# OS
|
|
548
|
+
.DS_Store
|
|
549
|
+
Thumbs.db
|
|
550
|
+
|
|
551
|
+
# Logs
|
|
552
|
+
*.log
|
|
553
|
+
npm-debug.log*
|
|
554
|
+
`;
|
|
555
|
+
await writeFile(path3.join(outputDir, ".gitignore"), gitignore);
|
|
556
|
+
},
|
|
557
|
+
"Configuration files created"
|
|
558
|
+
);
|
|
559
|
+
const gitInstalled = await isGitInstalled();
|
|
560
|
+
if (gitInstalled) {
|
|
561
|
+
await withSpinner(
|
|
562
|
+
"Initializing git repository...",
|
|
563
|
+
async () => {
|
|
564
|
+
await initGitRepository(outputDir);
|
|
565
|
+
await createInitialCommit(outputDir);
|
|
566
|
+
},
|
|
567
|
+
"Git repository initialized"
|
|
568
|
+
);
|
|
569
|
+
}
|
|
570
|
+
logger.success(`Monorepo workspace "${name}" created successfully!`);
|
|
571
|
+
logger.box("Next steps:", ["", ` cd ${name}`, ` mcp-new monorepo add my-first-server`, ""]);
|
|
572
|
+
} catch (error) {
|
|
573
|
+
if (error instanceof Error) {
|
|
574
|
+
logger.error(error.message);
|
|
575
|
+
} else {
|
|
576
|
+
logger.error("An unexpected error occurred");
|
|
577
|
+
}
|
|
578
|
+
process.exit(1);
|
|
579
|
+
}
|
|
580
|
+
}
|
|
581
|
+
async function monorepoAddCommand(serverName, options) {
|
|
582
|
+
try {
|
|
583
|
+
const workspaceConfigPath = path3.resolve(process.cwd(), "mcp.workspace.json");
|
|
584
|
+
if (!await exists(workspaceConfigPath)) {
|
|
585
|
+
logger.error(
|
|
586
|
+
"Not in a monorepo workspace. Run `mcp-new monorepo init` first, or cd into an existing workspace."
|
|
587
|
+
);
|
|
588
|
+
process.exit(1);
|
|
589
|
+
}
|
|
590
|
+
let name = serverName || options.name;
|
|
591
|
+
if (!name) {
|
|
592
|
+
const { inputName } = await inquirer.prompt([
|
|
593
|
+
{
|
|
594
|
+
type: "input",
|
|
595
|
+
name: "inputName",
|
|
596
|
+
message: "Server name:",
|
|
597
|
+
default: "my-mcp-server"
|
|
598
|
+
}
|
|
599
|
+
]);
|
|
600
|
+
name = inputName;
|
|
601
|
+
}
|
|
602
|
+
let language;
|
|
603
|
+
const opts = options;
|
|
604
|
+
if (opts.typescript === true || opts.t === true) language = "typescript";
|
|
605
|
+
else if (opts.python === true || opts.p === true) language = "python";
|
|
606
|
+
else if (opts.go === true || opts.g === true) language = "go";
|
|
607
|
+
else if (opts.rust === true || opts.r === true) language = "rust";
|
|
608
|
+
else if (opts.java === true || opts.j === true) language = "java";
|
|
609
|
+
else if (opts.kotlin === true || opts.k === true) language = "kotlin";
|
|
610
|
+
else if (opts.csharp === true || opts.c === true) language = "csharp";
|
|
611
|
+
else if (opts.elixir === true || opts.e === true) language = "elixir";
|
|
612
|
+
if (!language) {
|
|
613
|
+
language = await promptLanguage();
|
|
614
|
+
}
|
|
615
|
+
let javaBuildTool;
|
|
616
|
+
if (language === "java" || language === "kotlin") {
|
|
617
|
+
javaBuildTool = options.maven ? "maven" : options.gradle ? "gradle" : await promptJavaBuildTool();
|
|
618
|
+
}
|
|
619
|
+
const outputDir = path3.join(process.cwd(), "packages", name);
|
|
620
|
+
if (await exists(outputDir)) {
|
|
621
|
+
logger.error(`Server "${name}" already exists in packages/`);
|
|
622
|
+
process.exit(1);
|
|
623
|
+
}
|
|
624
|
+
logger.title(`Adding MCP Server: ${name}`);
|
|
625
|
+
await generateFromWizard(
|
|
626
|
+
{
|
|
627
|
+
name,
|
|
628
|
+
description: "",
|
|
629
|
+
language,
|
|
630
|
+
transport: "stdio",
|
|
631
|
+
tools: [],
|
|
632
|
+
resources: [],
|
|
633
|
+
includeExampleTool: true,
|
|
634
|
+
skipInstall: options.skipInstall || false,
|
|
635
|
+
initGit: false,
|
|
636
|
+
// Don't init git for individual packages
|
|
637
|
+
javaBuildTool
|
|
638
|
+
},
|
|
639
|
+
outputDir
|
|
640
|
+
);
|
|
641
|
+
const workspaceConfigContent = await readFile(workspaceConfigPath);
|
|
642
|
+
const workspaceConfig = JSON.parse(workspaceConfigContent);
|
|
643
|
+
workspaceConfig.packages.push(name);
|
|
644
|
+
await writeFile(workspaceConfigPath, JSON.stringify(workspaceConfig, null, 2));
|
|
645
|
+
logger.success(`Server "${name}" added to packages/`);
|
|
646
|
+
logger.info(`Language: ${language}${javaBuildTool ? ` (${javaBuildTool})` : ""}`);
|
|
647
|
+
logger.box("Next steps:", [
|
|
648
|
+
"",
|
|
649
|
+
` cd packages/${name}`,
|
|
650
|
+
" # Start developing your MCP server",
|
|
651
|
+
""
|
|
652
|
+
]);
|
|
653
|
+
} catch (error) {
|
|
654
|
+
if (error instanceof Error) {
|
|
655
|
+
logger.error(error.message);
|
|
656
|
+
} else {
|
|
657
|
+
logger.error("An unexpected error occurred");
|
|
658
|
+
}
|
|
659
|
+
process.exit(1);
|
|
660
|
+
}
|
|
661
|
+
}
|
|
662
|
+
async function monorepoListCommand() {
|
|
663
|
+
try {
|
|
664
|
+
const workspaceConfigPath = path3.resolve(process.cwd(), "mcp.workspace.json");
|
|
665
|
+
if (!await exists(workspaceConfigPath)) {
|
|
666
|
+
logger.error("Not in a monorepo workspace.");
|
|
667
|
+
process.exit(1);
|
|
668
|
+
}
|
|
669
|
+
const workspaceConfigContent = await readFile(workspaceConfigPath);
|
|
670
|
+
const workspaceConfig = JSON.parse(workspaceConfigContent);
|
|
671
|
+
logger.title(`Workspace: ${workspaceConfig.name}`);
|
|
672
|
+
if (workspaceConfig.packages.length === 0) {
|
|
673
|
+
logger.info("No packages yet. Run `mcp-new monorepo add <name>` to create one.");
|
|
674
|
+
} else {
|
|
675
|
+
logger.info("Packages:");
|
|
676
|
+
workspaceConfig.packages.forEach((pkg, index) => {
|
|
677
|
+
console.log(` ${index + 1}. ${pkg}`);
|
|
678
|
+
});
|
|
679
|
+
}
|
|
680
|
+
} catch (error) {
|
|
681
|
+
if (error instanceof Error) {
|
|
682
|
+
logger.error(error.message);
|
|
683
|
+
} else {
|
|
684
|
+
logger.error("An unexpected error occurred");
|
|
685
|
+
}
|
|
686
|
+
process.exit(1);
|
|
687
|
+
}
|
|
688
|
+
}
|
|
689
|
+
|
|
690
|
+
// src/cli.ts
|
|
11
691
|
var program = new Command();
|
|
12
692
|
var logo = `
|
|
13
|
-
${
|
|
14
|
-
${
|
|
15
|
-
${
|
|
16
|
-
${
|
|
693
|
+
${chalk4.cyan("\u2554\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2557")}
|
|
694
|
+
${chalk4.cyan("\u2551")} ${chalk4.bold.white("mcp-new")} ${chalk4.cyan("\u2551")}
|
|
695
|
+
${chalk4.cyan("\u2551")} ${chalk4.gray("Generate MCP servers in seconds")} ${chalk4.cyan("\u2551")}
|
|
696
|
+
${chalk4.cyan("\u255A\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u255D")}
|
|
17
697
|
`;
|
|
18
698
|
var examples = `
|
|
19
|
-
${
|
|
699
|
+
${chalk4.bold("Examples:")}
|
|
20
700
|
|
|
21
|
-
${
|
|
22
|
-
${
|
|
701
|
+
${chalk4.gray("# Create a new MCP server with interactive wizard")}
|
|
702
|
+
${chalk4.cyan("$")} mcp-new my-server
|
|
23
703
|
|
|
24
|
-
${
|
|
25
|
-
${
|
|
704
|
+
${chalk4.gray("# Create TypeScript server with defaults")}
|
|
705
|
+
${chalk4.cyan("$")} mcp-new my-server -t -y
|
|
26
706
|
|
|
27
|
-
${
|
|
28
|
-
${
|
|
707
|
+
${chalk4.gray("# Create Python server")}
|
|
708
|
+
${chalk4.cyan("$")} mcp-new my-server -p
|
|
29
709
|
|
|
30
|
-
${
|
|
31
|
-
${
|
|
32
|
-
${
|
|
33
|
-
${
|
|
710
|
+
${chalk4.gray("# Create from preset template")}
|
|
711
|
+
${chalk4.cyan("$")} mcp-new my-db --preset database
|
|
712
|
+
${chalk4.cyan("$")} mcp-new my-api --preset rest-api
|
|
713
|
+
${chalk4.cyan("$")} mcp-new my-fs --preset filesystem
|
|
34
714
|
|
|
35
|
-
${
|
|
36
|
-
${
|
|
715
|
+
${chalk4.gray("# Create from OpenAPI specification")}
|
|
716
|
+
${chalk4.cyan("$")} mcp-new my-api --from-openapi ./openapi.yaml
|
|
37
717
|
|
|
38
|
-
${
|
|
39
|
-
${
|
|
718
|
+
${chalk4.gray("# Create using AI (requires ANTHROPIC_API_KEY)")}
|
|
719
|
+
${chalk4.cyan("$")} mcp-new my-server --from-prompt
|
|
40
720
|
|
|
41
|
-
${
|
|
721
|
+
${chalk4.bold("Available Presets:")}
|
|
42
722
|
|
|
43
|
-
${
|
|
44
|
-
${
|
|
45
|
-
${
|
|
723
|
+
${chalk4.yellow("database")} Database CRUD tools (query, insert, update, delete, list_tables)
|
|
724
|
+
${chalk4.yellow("rest-api")} REST API tools (http_get, http_post, http_put, http_delete, set_base_url)
|
|
725
|
+
${chalk4.yellow("filesystem")} File system tools (read_file, write_file, list_directory, search_files, file_info)
|
|
46
726
|
|
|
47
|
-
${
|
|
727
|
+
${chalk4.bold("Supported Languages:")}
|
|
48
728
|
|
|
49
|
-
${
|
|
50
|
-
${
|
|
51
|
-
${
|
|
52
|
-
${
|
|
729
|
+
${chalk4.green("-t, --typescript")} TypeScript with npm
|
|
730
|
+
${chalk4.green("-p, --python")} Python with pip
|
|
731
|
+
${chalk4.green("-g, --go")} Go with go modules
|
|
732
|
+
${chalk4.green("-r, --rust")} Rust with cargo
|
|
733
|
+
${chalk4.green("-j, --java")} Java with Maven/Gradle
|
|
734
|
+
${chalk4.green("-k, --kotlin")} Kotlin with Maven/Gradle
|
|
735
|
+
${chalk4.green("-c, --csharp")} C# with .NET
|
|
736
|
+
${chalk4.green("-e, --elixir")} Elixir with Mix
|
|
53
737
|
|
|
54
|
-
${
|
|
738
|
+
${chalk4.bold("Learn More:")}
|
|
55
739
|
|
|
56
|
-
Documentation: ${
|
|
57
|
-
MCP Spec: ${
|
|
740
|
+
Documentation: ${chalk4.underline("https://github.com/d1maash/mcp-new")}
|
|
741
|
+
MCP Spec: ${chalk4.underline("https://spec.modelcontextprotocol.io")}
|
|
58
742
|
`;
|
|
59
|
-
program.name("mcp-new").description("CLI tool for generating MCP (Model Context Protocol) servers").version("1.
|
|
60
|
-
program.argument("[project-name]", "Name of the project to create").option("-t, --typescript", "Use TypeScript template").option("-p, --python", "Use Python template").option("-g, --go", "Use Go template").option("-r, --rust", "Use Rust template").option("--skip-install", "Skip dependency installation").option("--from-openapi <path>", "Generate from OpenAPI/Swagger specification").option("--from-prompt", "Generate tools using AI from text description").option("--preset <name>", "Use a preset template (database, rest-api, filesystem)").option("-y, --yes", "Skip prompts and use defaults").action(createCommand);
|
|
61
|
-
program.command("init").description("Initialize MCP server in the current directory").option("-t, --typescript", "Use TypeScript template").option("-p, --python", "Use Python template").option("-g, --go", "Use Go template").option("-r, --rust", "Use Rust template").option("--skip-install", "Skip dependency installation").option("-f, --force", "Initialize even if directory contains files").addHelpText(
|
|
62
|
-
|
|
743
|
+
program.name("mcp-new").description("CLI tool for generating MCP (Model Context Protocol) servers").version("1.5.0").addHelpText("beforeAll", logo).addHelpText("after", examples);
|
|
744
|
+
program.argument("[project-name]", "Name of the project to create").option("-t, --typescript", "Use TypeScript template").option("-p, --python", "Use Python template").option("-g, --go", "Use Go template").option("-r, --rust", "Use Rust template").option("-j, --java", "Use Java template").option("-k, --kotlin", "Use Kotlin template").option("-c, --csharp", "Use C# (.NET) template").option("-e, --elixir", "Use Elixir template").option("--maven", "Use Maven build tool (for Java/Kotlin)").option("--gradle", "Use Gradle build tool (for Java/Kotlin)").option("--skip-install", "Skip dependency installation").option("--from-openapi <path>", "Generate from OpenAPI/Swagger specification").option("--from-prompt", "Generate tools using AI from text description").option("--preset <name>", "Use a preset template (database, rest-api, filesystem)").option("-y, --yes", "Skip prompts and use defaults").action(createCommand);
|
|
745
|
+
program.command("init").description("Initialize MCP server in the current directory").option("-t, --typescript", "Use TypeScript template").option("-p, --python", "Use Python template").option("-g, --go", "Use Go template").option("-r, --rust", "Use Rust template").option("-j, --java", "Use Java template").option("-k, --kotlin", "Use Kotlin template").option("-c, --csharp", "Use C# (.NET) template").option("-e, --elixir", "Use Elixir template").option("--maven", "Use Maven build tool (for Java/Kotlin)").option("--gradle", "Use Gradle build tool (for Java/Kotlin)").option("--skip-install", "Skip dependency installation").option("-f, --force", "Initialize even if directory contains files").addHelpText(
|
|
746
|
+
"after",
|
|
747
|
+
`
|
|
748
|
+
${chalk4.bold("Examples:")}
|
|
749
|
+
|
|
750
|
+
${chalk4.gray("# Initialize in current directory")}
|
|
751
|
+
${chalk4.cyan("$")} mcp-new init
|
|
752
|
+
|
|
753
|
+
${chalk4.gray("# Initialize with TypeScript")}
|
|
754
|
+
${chalk4.cyan("$")} mcp-new init -t
|
|
755
|
+
|
|
756
|
+
${chalk4.gray("# Force initialize (overwrite existing files)")}
|
|
757
|
+
${chalk4.cyan("$")} mcp-new init -f
|
|
758
|
+
`
|
|
759
|
+
).action(initCommand);
|
|
760
|
+
program.command("add-tool").description("Add a new tool to an existing MCP server").option("-n, --name <name>", "Tool name (snake_case)").addHelpText(
|
|
761
|
+
"after",
|
|
762
|
+
`
|
|
763
|
+
${chalk4.bold("Examples:")}
|
|
764
|
+
|
|
765
|
+
${chalk4.gray("# Add tool interactively")}
|
|
766
|
+
${chalk4.cyan("$")} mcp-new add-tool
|
|
767
|
+
|
|
768
|
+
${chalk4.gray("# Add tool with name")}
|
|
769
|
+
${chalk4.cyan("$")} mcp-new add-tool -n my_new_tool
|
|
770
|
+
`
|
|
771
|
+
).action(addToolCommand);
|
|
772
|
+
program.command("list-presets").description("List all available preset templates").addHelpText(
|
|
773
|
+
"after",
|
|
774
|
+
`
|
|
775
|
+
${chalk4.bold("Examples:")}
|
|
776
|
+
|
|
777
|
+
${chalk4.gray("# Show all presets with their tools")}
|
|
778
|
+
${chalk4.cyan("$")} mcp-new list-presets
|
|
779
|
+
`
|
|
780
|
+
).action(listPresetsCommand);
|
|
781
|
+
program.command("validate").description("Validate the current MCP server project").addHelpText(
|
|
782
|
+
"after",
|
|
783
|
+
`
|
|
784
|
+
${chalk4.bold("Examples:")}
|
|
785
|
+
|
|
786
|
+
${chalk4.gray("# Validate current project")}
|
|
787
|
+
${chalk4.cyan("$")} mcp-new validate
|
|
788
|
+
|
|
789
|
+
${chalk4.bold("Checks:")}
|
|
790
|
+
\u2022 Project configuration (package.json, pyproject.toml, etc.)
|
|
791
|
+
\u2022 MCP SDK dependency presence and version
|
|
792
|
+
\u2022 Entry point file existence
|
|
793
|
+
\u2022 Basic project structure
|
|
794
|
+
`
|
|
795
|
+
).action(validateCommand);
|
|
796
|
+
program.command("upgrade").description("Upgrade MCP SDK to the latest version").option("-c, --check", "Check for updates without installing").addHelpText(
|
|
797
|
+
"after",
|
|
798
|
+
`
|
|
799
|
+
${chalk4.bold("Examples:")}
|
|
800
|
+
|
|
801
|
+
${chalk4.gray("# Upgrade MCP SDK to latest version")}
|
|
802
|
+
${chalk4.cyan("$")} mcp-new upgrade
|
|
803
|
+
|
|
804
|
+
${chalk4.gray("# Check for updates without installing")}
|
|
805
|
+
${chalk4.cyan("$")} mcp-new upgrade --check
|
|
63
806
|
|
|
64
|
-
|
|
65
|
-
|
|
807
|
+
${chalk4.bold("Supported languages:")}
|
|
808
|
+
\u2022 TypeScript/JavaScript (npm)
|
|
809
|
+
\u2022 Python (pip)
|
|
810
|
+
\u2022 Go (go modules)
|
|
811
|
+
\u2022 Rust (cargo)
|
|
812
|
+
`
|
|
813
|
+
).action(upgradeCommand);
|
|
814
|
+
var monorepo = program.command("monorepo").description("Manage MCP monorepo workspaces");
|
|
815
|
+
monorepo.command("init [workspace-name]").description("Initialize a new MCP monorepo workspace").option("-f, --force", "Initialize even if directory contains files").addHelpText(
|
|
816
|
+
"after",
|
|
817
|
+
`
|
|
818
|
+
${chalk4.bold("Examples:")}
|
|
66
819
|
|
|
67
|
-
${
|
|
68
|
-
${
|
|
820
|
+
${chalk4.gray("# Create a new monorepo workspace")}
|
|
821
|
+
${chalk4.cyan("$")} mcp-new monorepo init my-workspace
|
|
69
822
|
|
|
70
|
-
${
|
|
71
|
-
${
|
|
72
|
-
`
|
|
73
|
-
|
|
74
|
-
|
|
823
|
+
${chalk4.gray("# Create in current directory name")}
|
|
824
|
+
${chalk4.cyan("$")} mcp-new monorepo init
|
|
825
|
+
`
|
|
826
|
+
).action((_workspaceName, _options, command) => {
|
|
827
|
+
const opts = command.optsWithGlobals();
|
|
828
|
+
const workspaceName = command.args[0];
|
|
829
|
+
monorepoInitCommand(workspaceName, opts);
|
|
830
|
+
});
|
|
831
|
+
monorepo.command("add [server-name]").description("Add a new MCP server to the workspace").option("-n, --name <name>", "Server name").option("-t, --typescript", "Use TypeScript template").option("-p, --python", "Use Python template").option("-g, --go", "Use Go template").option("-r, --rust", "Use Rust template").option("-j, --java", "Use Java template").option("-k, --kotlin", "Use Kotlin template").option("-c, --csharp", "Use C# (.NET) template").option("-e, --elixir", "Use Elixir template").option("--maven", "Use Maven build tool (for Java/Kotlin)").option("--gradle", "Use Gradle build tool (for Java/Kotlin)").option("--skip-install", "Skip dependency installation").addHelpText(
|
|
832
|
+
"after",
|
|
833
|
+
`
|
|
834
|
+
${chalk4.bold("Examples:")}
|
|
75
835
|
|
|
76
|
-
${
|
|
77
|
-
${
|
|
836
|
+
${chalk4.gray("# Add a TypeScript server")}
|
|
837
|
+
${chalk4.cyan("$")} mcp-new monorepo add my-server -t
|
|
78
838
|
|
|
79
|
-
${
|
|
80
|
-
${
|
|
81
|
-
`
|
|
839
|
+
${chalk4.gray("# Add a Java server with Gradle")}
|
|
840
|
+
${chalk4.cyan("$")} mcp-new monorepo add api-server -j --gradle
|
|
841
|
+
`
|
|
842
|
+
).action((_serverName, _options, command) => {
|
|
843
|
+
const opts = command.optsWithGlobals();
|
|
844
|
+
const serverName = command.args[0];
|
|
845
|
+
monorepoAddCommand(serverName, opts);
|
|
846
|
+
});
|
|
847
|
+
monorepo.command("list").description("List all packages in the workspace").action(monorepoListCommand);
|
|
82
848
|
program.parse();
|
|
83
849
|
if (process.argv.length === 2) {
|
|
84
850
|
program.help();
|