mcp-new 1.2.1 → 1.2.2
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 +15 -0
- package/dist/{chunk-BHGUGEHE.js → chunk-3JG4FVS2.js} +1 -0
- package/dist/cli.js +493 -46
- package/dist/index.js +1 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -124,6 +124,18 @@ mcp-new init
|
|
|
124
124
|
|
|
125
125
|
# Add a new tool to existing project
|
|
126
126
|
mcp-new add-tool
|
|
127
|
+
|
|
128
|
+
# List all available presets
|
|
129
|
+
mcp-new list-presets
|
|
130
|
+
|
|
131
|
+
# Validate current MCP server project
|
|
132
|
+
mcp-new validate
|
|
133
|
+
|
|
134
|
+
# Upgrade MCP SDK to latest version
|
|
135
|
+
mcp-new upgrade
|
|
136
|
+
|
|
137
|
+
# Check for updates without installing
|
|
138
|
+
mcp-new upgrade --check
|
|
127
139
|
```
|
|
128
140
|
|
|
129
141
|
---
|
|
@@ -151,6 +163,9 @@ Options:
|
|
|
151
163
|
Commands:
|
|
152
164
|
init Initialize in current directory
|
|
153
165
|
add-tool Add tool to existing project
|
|
166
|
+
list-presets List all available preset templates
|
|
167
|
+
validate Validate current MCP server project
|
|
168
|
+
upgrade Upgrade MCP SDK to latest version
|
|
154
169
|
```
|
|
155
170
|
|
|
156
171
|
### Generated Project Structure
|
package/dist/cli.js
CHANGED
|
@@ -1,84 +1,531 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
import {
|
|
3
|
+
PRESETS,
|
|
3
4
|
addToolCommand,
|
|
4
5
|
createCommand,
|
|
5
|
-
|
|
6
|
-
|
|
6
|
+
createSpinner,
|
|
7
|
+
initCommand,
|
|
8
|
+
logger
|
|
9
|
+
} from "./chunk-3JG4FVS2.js";
|
|
7
10
|
|
|
8
11
|
// src/cli.ts
|
|
9
12
|
import { Command } from "commander";
|
|
13
|
+
import chalk4 from "chalk";
|
|
14
|
+
|
|
15
|
+
// src/commands/list-presets.ts
|
|
10
16
|
import chalk from "chalk";
|
|
17
|
+
async function listPresetsCommand() {
|
|
18
|
+
console.log();
|
|
19
|
+
console.log(chalk.bold.white("Available Presets"));
|
|
20
|
+
console.log(chalk.gray("\u2500".repeat(60)));
|
|
21
|
+
console.log();
|
|
22
|
+
for (const [id, preset] of Object.entries(PRESETS)) {
|
|
23
|
+
console.log(chalk.yellow.bold(` ${id}`));
|
|
24
|
+
console.log(chalk.gray(` ${preset.description}`));
|
|
25
|
+
console.log();
|
|
26
|
+
console.log(chalk.white(" Tools:"));
|
|
27
|
+
for (const tool of preset.tools) {
|
|
28
|
+
const paramCount = tool.parameters.length;
|
|
29
|
+
const paramText = paramCount === 0 ? chalk.gray("no params") : chalk.gray(`${paramCount} param${paramCount > 1 ? "s" : ""}`);
|
|
30
|
+
console.log(` ${chalk.cyan("\u2022")} ${chalk.white(tool.name)} ${paramText}`);
|
|
31
|
+
console.log(` ${chalk.gray(tool.description)}`);
|
|
32
|
+
}
|
|
33
|
+
console.log();
|
|
34
|
+
console.log(chalk.gray(" " + "\u2500".repeat(56)));
|
|
35
|
+
console.log();
|
|
36
|
+
}
|
|
37
|
+
console.log(chalk.bold.white("Usage:"));
|
|
38
|
+
console.log();
|
|
39
|
+
console.log(chalk.gray(" $"), chalk.cyan("mcp-new my-project --preset database"));
|
|
40
|
+
console.log(chalk.gray(" $"), chalk.cyan("mcp-new my-api --preset rest-api -t"));
|
|
41
|
+
console.log(chalk.gray(" $"), chalk.cyan("mcp-new my-fs --preset filesystem -p"));
|
|
42
|
+
console.log();
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
// src/commands/validate.ts
|
|
46
|
+
import path from "path";
|
|
47
|
+
import fs from "fs-extra";
|
|
48
|
+
import chalk2 from "chalk";
|
|
49
|
+
async function validateCommand() {
|
|
50
|
+
const currentDir = process.cwd();
|
|
51
|
+
logger.title("Validating MCP Server");
|
|
52
|
+
const result = await validateProject(currentDir);
|
|
53
|
+
console.log();
|
|
54
|
+
if (result.language) {
|
|
55
|
+
console.log(chalk2.blue("i"), `Detected language: ${chalk2.cyan(result.language)}`);
|
|
56
|
+
}
|
|
57
|
+
for (const info of result.info) {
|
|
58
|
+
console.log(chalk2.blue("i"), info);
|
|
59
|
+
}
|
|
60
|
+
for (const warning of result.warnings) {
|
|
61
|
+
console.log(chalk2.yellow("\u26A0"), warning);
|
|
62
|
+
}
|
|
63
|
+
for (const error of result.errors) {
|
|
64
|
+
console.log(chalk2.red("\u2717"), error);
|
|
65
|
+
}
|
|
66
|
+
console.log();
|
|
67
|
+
if (result.valid) {
|
|
68
|
+
logger.success("MCP server is valid!");
|
|
69
|
+
} else {
|
|
70
|
+
logger.error("Validation failed. Please fix the issues above.");
|
|
71
|
+
process.exit(1);
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
async function validateProject(projectDir) {
|
|
75
|
+
const result = {
|
|
76
|
+
valid: true,
|
|
77
|
+
language: null,
|
|
78
|
+
errors: [],
|
|
79
|
+
warnings: [],
|
|
80
|
+
info: []
|
|
81
|
+
};
|
|
82
|
+
const hasPackageJson = await fs.pathExists(path.join(projectDir, "package.json"));
|
|
83
|
+
const hasPyproject = await fs.pathExists(path.join(projectDir, "pyproject.toml"));
|
|
84
|
+
const hasGoMod = await fs.pathExists(path.join(projectDir, "go.mod"));
|
|
85
|
+
const hasCargoToml = await fs.pathExists(path.join(projectDir, "Cargo.toml"));
|
|
86
|
+
if (!hasPackageJson && !hasPyproject && !hasGoMod && !hasCargoToml) {
|
|
87
|
+
result.errors.push("No project configuration found (package.json, pyproject.toml, go.mod, or Cargo.toml)");
|
|
88
|
+
result.valid = false;
|
|
89
|
+
return result;
|
|
90
|
+
}
|
|
91
|
+
if (hasPackageJson) {
|
|
92
|
+
result.language = "typescript";
|
|
93
|
+
await validateTypeScriptProject(projectDir, result);
|
|
94
|
+
}
|
|
95
|
+
if (hasPyproject) {
|
|
96
|
+
result.language = "python";
|
|
97
|
+
await validatePythonProject(projectDir, result);
|
|
98
|
+
}
|
|
99
|
+
if (hasGoMod) {
|
|
100
|
+
result.language = "go";
|
|
101
|
+
await validateGoProject(projectDir, result);
|
|
102
|
+
}
|
|
103
|
+
if (hasCargoToml) {
|
|
104
|
+
result.language = "rust";
|
|
105
|
+
await validateRustProject(projectDir, result);
|
|
106
|
+
}
|
|
107
|
+
return result;
|
|
108
|
+
}
|
|
109
|
+
async function validateTypeScriptProject(projectDir, result) {
|
|
110
|
+
try {
|
|
111
|
+
const packageJsonPath = path.join(projectDir, "package.json");
|
|
112
|
+
const packageJson = await fs.readJson(packageJsonPath);
|
|
113
|
+
const deps = { ...packageJson.dependencies, ...packageJson.devDependencies };
|
|
114
|
+
if (deps["@modelcontextprotocol/sdk"]) {
|
|
115
|
+
result.info.push(`MCP SDK version: ${chalk2.green(deps["@modelcontextprotocol/sdk"])}`);
|
|
116
|
+
} else {
|
|
117
|
+
result.errors.push("Missing @modelcontextprotocol/sdk dependency");
|
|
118
|
+
result.valid = false;
|
|
119
|
+
}
|
|
120
|
+
const srcIndex = path.join(projectDir, "src", "index.ts");
|
|
121
|
+
const srcIndexJs = path.join(projectDir, "src", "index.js");
|
|
122
|
+
const distIndex = path.join(projectDir, "dist", "index.js");
|
|
123
|
+
if (await fs.pathExists(srcIndex)) {
|
|
124
|
+
result.info.push("Entry point: src/index.ts");
|
|
125
|
+
await validateTypeScriptEntryPoint(srcIndex, result);
|
|
126
|
+
} else if (await fs.pathExists(srcIndexJs)) {
|
|
127
|
+
result.info.push("Entry point: src/index.js");
|
|
128
|
+
} else if (await fs.pathExists(distIndex)) {
|
|
129
|
+
result.info.push("Entry point: dist/index.js (built)");
|
|
130
|
+
} else {
|
|
131
|
+
result.warnings.push("No entry point found (expected src/index.ts or src/index.js)");
|
|
132
|
+
}
|
|
133
|
+
if (await fs.pathExists(path.join(projectDir, "tsconfig.json"))) {
|
|
134
|
+
result.info.push("TypeScript config: tsconfig.json");
|
|
135
|
+
} else {
|
|
136
|
+
result.warnings.push("No tsconfig.json found");
|
|
137
|
+
}
|
|
138
|
+
if (packageJson.scripts?.build) {
|
|
139
|
+
result.info.push(`Build script: ${chalk2.gray(packageJson.scripts.build)}`);
|
|
140
|
+
} else {
|
|
141
|
+
result.warnings.push("No build script found in package.json");
|
|
142
|
+
}
|
|
143
|
+
} catch (error) {
|
|
144
|
+
result.errors.push("Failed to parse package.json");
|
|
145
|
+
result.valid = false;
|
|
146
|
+
}
|
|
147
|
+
}
|
|
148
|
+
async function validateTypeScriptEntryPoint(filePath, result) {
|
|
149
|
+
try {
|
|
150
|
+
const content = await fs.readFile(filePath, "utf-8");
|
|
151
|
+
if (content.includes("@modelcontextprotocol/sdk")) {
|
|
152
|
+
result.info.push("MCP SDK import found");
|
|
153
|
+
} else {
|
|
154
|
+
result.warnings.push("No MCP SDK import found in entry point");
|
|
155
|
+
}
|
|
156
|
+
if (content.includes("McpServer") || content.includes("Server")) {
|
|
157
|
+
result.info.push("MCP Server class usage found");
|
|
158
|
+
} else {
|
|
159
|
+
result.warnings.push("No MCP Server class found");
|
|
160
|
+
}
|
|
161
|
+
const toolMatches = content.match(/\.tool\s*\(/g) || content.match(/setRequestHandler.*CallToolRequest/g);
|
|
162
|
+
if (toolMatches) {
|
|
163
|
+
result.info.push(`Tools defined: ${chalk2.green(toolMatches.length)}`);
|
|
164
|
+
}
|
|
165
|
+
} catch {
|
|
166
|
+
result.warnings.push("Could not analyze entry point file");
|
|
167
|
+
}
|
|
168
|
+
}
|
|
169
|
+
async function validatePythonProject(projectDir, result) {
|
|
170
|
+
try {
|
|
171
|
+
const pyprojectPath = path.join(projectDir, "pyproject.toml");
|
|
172
|
+
const content = await fs.readFile(pyprojectPath, "utf-8");
|
|
173
|
+
if (content.includes("mcp") || content.includes("modelcontextprotocol")) {
|
|
174
|
+
result.info.push("MCP dependency found in pyproject.toml");
|
|
175
|
+
} else {
|
|
176
|
+
const requirementsPath = path.join(projectDir, "requirements.txt");
|
|
177
|
+
if (await fs.pathExists(requirementsPath)) {
|
|
178
|
+
const requirements = await fs.readFile(requirementsPath, "utf-8");
|
|
179
|
+
if (requirements.includes("mcp")) {
|
|
180
|
+
result.info.push("MCP dependency found in requirements.txt");
|
|
181
|
+
} else {
|
|
182
|
+
result.errors.push("Missing MCP dependency");
|
|
183
|
+
result.valid = false;
|
|
184
|
+
}
|
|
185
|
+
} else {
|
|
186
|
+
result.warnings.push("No requirements.txt found");
|
|
187
|
+
}
|
|
188
|
+
}
|
|
189
|
+
const serverPath = path.join(projectDir, "src", "server.py");
|
|
190
|
+
if (await fs.pathExists(serverPath)) {
|
|
191
|
+
result.info.push("Server file: src/server.py");
|
|
192
|
+
} else {
|
|
193
|
+
result.warnings.push("No server.py found in src/");
|
|
194
|
+
}
|
|
195
|
+
} catch (error) {
|
|
196
|
+
result.errors.push("Failed to parse pyproject.toml");
|
|
197
|
+
result.valid = false;
|
|
198
|
+
}
|
|
199
|
+
}
|
|
200
|
+
async function validateGoProject(projectDir, result) {
|
|
201
|
+
try {
|
|
202
|
+
const goModPath = path.join(projectDir, "go.mod");
|
|
203
|
+
const content = await fs.readFile(goModPath, "utf-8");
|
|
204
|
+
if (content.includes("mcp-go") || content.includes("modelcontextprotocol")) {
|
|
205
|
+
result.info.push("MCP Go SDK found in go.mod");
|
|
206
|
+
} else {
|
|
207
|
+
result.errors.push("Missing MCP Go SDK dependency");
|
|
208
|
+
result.valid = false;
|
|
209
|
+
}
|
|
210
|
+
const mainPath = path.join(projectDir, "cmd", "server", "main.go");
|
|
211
|
+
const altMainPath = path.join(projectDir, "main.go");
|
|
212
|
+
if (await fs.pathExists(mainPath)) {
|
|
213
|
+
result.info.push("Entry point: cmd/server/main.go");
|
|
214
|
+
} else if (await fs.pathExists(altMainPath)) {
|
|
215
|
+
result.info.push("Entry point: main.go");
|
|
216
|
+
} else {
|
|
217
|
+
result.warnings.push("No main.go found");
|
|
218
|
+
}
|
|
219
|
+
} catch (error) {
|
|
220
|
+
result.errors.push("Failed to parse go.mod");
|
|
221
|
+
result.valid = false;
|
|
222
|
+
}
|
|
223
|
+
}
|
|
224
|
+
async function validateRustProject(projectDir, result) {
|
|
225
|
+
try {
|
|
226
|
+
const cargoPath = path.join(projectDir, "Cargo.toml");
|
|
227
|
+
const content = await fs.readFile(cargoPath, "utf-8");
|
|
228
|
+
if (content.includes("rmcp") || content.includes("mcp")) {
|
|
229
|
+
result.info.push("MCP Rust SDK found in Cargo.toml");
|
|
230
|
+
} else {
|
|
231
|
+
result.errors.push("Missing MCP Rust SDK dependency");
|
|
232
|
+
result.valid = false;
|
|
233
|
+
}
|
|
234
|
+
const mainPath = path.join(projectDir, "src", "main.rs");
|
|
235
|
+
if (await fs.pathExists(mainPath)) {
|
|
236
|
+
result.info.push("Entry point: src/main.rs");
|
|
237
|
+
} else {
|
|
238
|
+
result.warnings.push("No main.rs found");
|
|
239
|
+
}
|
|
240
|
+
} catch (error) {
|
|
241
|
+
result.errors.push("Failed to parse Cargo.toml");
|
|
242
|
+
result.valid = false;
|
|
243
|
+
}
|
|
244
|
+
}
|
|
245
|
+
|
|
246
|
+
// src/commands/upgrade.ts
|
|
247
|
+
import path2 from "path";
|
|
248
|
+
import fs2 from "fs-extra";
|
|
249
|
+
import chalk3 from "chalk";
|
|
250
|
+
import { execa } from "execa";
|
|
251
|
+
async function upgradeCommand(options) {
|
|
252
|
+
const currentDir = process.cwd();
|
|
253
|
+
logger.title("MCP SDK Upgrade");
|
|
254
|
+
const hasPackageJson = await fs2.pathExists(path2.join(currentDir, "package.json"));
|
|
255
|
+
const hasPyproject = await fs2.pathExists(path2.join(currentDir, "pyproject.toml"));
|
|
256
|
+
const hasGoMod = await fs2.pathExists(path2.join(currentDir, "go.mod"));
|
|
257
|
+
const hasCargoToml = await fs2.pathExists(path2.join(currentDir, "Cargo.toml"));
|
|
258
|
+
if (!hasPackageJson && !hasPyproject && !hasGoMod && !hasCargoToml) {
|
|
259
|
+
logger.error("No project configuration found.");
|
|
260
|
+
logger.info("Run this command from the root of your MCP server project.");
|
|
261
|
+
process.exit(1);
|
|
262
|
+
}
|
|
263
|
+
let info = null;
|
|
264
|
+
if (hasPackageJson) {
|
|
265
|
+
info = await checkNodePackage(currentDir);
|
|
266
|
+
} else if (hasPyproject) {
|
|
267
|
+
info = await checkPythonPackage(currentDir);
|
|
268
|
+
} else if (hasGoMod) {
|
|
269
|
+
info = await checkGoPackage(currentDir);
|
|
270
|
+
} else if (hasCargoToml) {
|
|
271
|
+
info = await checkRustPackage(currentDir);
|
|
272
|
+
}
|
|
273
|
+
if (!info) {
|
|
274
|
+
logger.error("Could not detect MCP SDK version.");
|
|
275
|
+
process.exit(1);
|
|
276
|
+
}
|
|
277
|
+
console.log();
|
|
278
|
+
console.log(chalk3.blue("i"), `Package: ${chalk3.cyan(info.packageName)}`);
|
|
279
|
+
console.log(chalk3.blue("i"), `Current version: ${info.current ? chalk3.yellow(info.current) : chalk3.gray("not installed")}`);
|
|
280
|
+
console.log(chalk3.blue("i"), `Latest version: ${info.latest ? chalk3.green(info.latest) : chalk3.gray("unknown")}`);
|
|
281
|
+
console.log();
|
|
282
|
+
if (options.check) {
|
|
283
|
+
if (info.current === info.latest) {
|
|
284
|
+
logger.success("Already up to date!");
|
|
285
|
+
} else if (info.latest) {
|
|
286
|
+
logger.info(`Update available: ${info.current} \u2192 ${info.latest}`);
|
|
287
|
+
logger.code(`mcp-new upgrade`);
|
|
288
|
+
}
|
|
289
|
+
return;
|
|
290
|
+
}
|
|
291
|
+
if (info.current === info.latest) {
|
|
292
|
+
logger.success("Already up to date!");
|
|
293
|
+
return;
|
|
294
|
+
}
|
|
295
|
+
if (!info.latest) {
|
|
296
|
+
logger.error("Could not fetch latest version.");
|
|
297
|
+
process.exit(1);
|
|
298
|
+
}
|
|
299
|
+
const spinner = createSpinner(`Upgrading ${info.packageName}...`);
|
|
300
|
+
spinner.start();
|
|
301
|
+
try {
|
|
302
|
+
if (hasPackageJson) {
|
|
303
|
+
await upgradeNodePackage(currentDir, info);
|
|
304
|
+
} else if (hasPyproject) {
|
|
305
|
+
await upgradePythonPackage(currentDir, info);
|
|
306
|
+
} else if (hasGoMod) {
|
|
307
|
+
await upgradeGoPackage(currentDir, info);
|
|
308
|
+
} else if (hasCargoToml) {
|
|
309
|
+
await upgradeRustPackage(currentDir, info);
|
|
310
|
+
}
|
|
311
|
+
spinner.succeed(`Upgraded to ${info.packageName}@${info.latest}`);
|
|
312
|
+
logger.blank();
|
|
313
|
+
logger.success("MCP SDK upgraded successfully!");
|
|
314
|
+
} catch (error) {
|
|
315
|
+
spinner.fail("Upgrade failed");
|
|
316
|
+
if (error instanceof Error) {
|
|
317
|
+
logger.error(error.message);
|
|
318
|
+
}
|
|
319
|
+
process.exit(1);
|
|
320
|
+
}
|
|
321
|
+
}
|
|
322
|
+
async function checkNodePackage(projectDir) {
|
|
323
|
+
const packageName = "@modelcontextprotocol/sdk";
|
|
324
|
+
let current = null;
|
|
325
|
+
let latest = null;
|
|
326
|
+
try {
|
|
327
|
+
const packageJson = await fs2.readJson(path2.join(projectDir, "package.json"));
|
|
328
|
+
const deps = { ...packageJson.dependencies, ...packageJson.devDependencies };
|
|
329
|
+
current = deps[packageName]?.replace(/[\^~]/, "") || null;
|
|
330
|
+
} catch {
|
|
331
|
+
}
|
|
332
|
+
try {
|
|
333
|
+
const { stdout } = await execa("npm", ["view", packageName, "version"]);
|
|
334
|
+
latest = stdout.trim();
|
|
335
|
+
} catch {
|
|
336
|
+
}
|
|
337
|
+
return { current, latest, packageManager: "npm", packageName };
|
|
338
|
+
}
|
|
339
|
+
async function upgradeNodePackage(projectDir, info) {
|
|
340
|
+
const packageJsonPath = path2.join(projectDir, "package.json");
|
|
341
|
+
const packageJson = await fs2.readJson(packageJsonPath);
|
|
342
|
+
if (packageJson.dependencies?.[info.packageName]) {
|
|
343
|
+
packageJson.dependencies[info.packageName] = `^${info.latest}`;
|
|
344
|
+
} else if (packageJson.devDependencies?.[info.packageName]) {
|
|
345
|
+
packageJson.devDependencies[info.packageName] = `^${info.latest}`;
|
|
346
|
+
}
|
|
347
|
+
await fs2.writeJson(packageJsonPath, packageJson, { spaces: 2 });
|
|
348
|
+
await execa("npm", ["install"], { cwd: projectDir });
|
|
349
|
+
}
|
|
350
|
+
async function checkPythonPackage(projectDir) {
|
|
351
|
+
const packageName = "mcp";
|
|
352
|
+
let current = null;
|
|
353
|
+
let latest = null;
|
|
354
|
+
try {
|
|
355
|
+
const { stdout } = await execa("pip", ["show", packageName]);
|
|
356
|
+
const versionMatch = stdout.match(/Version:\s*(\S+)/);
|
|
357
|
+
current = versionMatch?.[1] || null;
|
|
358
|
+
} catch {
|
|
359
|
+
}
|
|
360
|
+
try {
|
|
361
|
+
const { stdout } = await execa("pip", ["index", "versions", packageName]);
|
|
362
|
+
const match = stdout.match(/Available versions:\s*([^\s,]+)/);
|
|
363
|
+
latest = match?.[1] || null;
|
|
364
|
+
} catch {
|
|
365
|
+
try {
|
|
366
|
+
const { stdout } = await execa("pip", ["install", `${packageName}==`, "--dry-run"], { reject: false });
|
|
367
|
+
const match = stdout.match(/from versions:\s*([^)]+)\)/);
|
|
368
|
+
if (match) {
|
|
369
|
+
const versions = match[1].split(",").map((v) => v.trim());
|
|
370
|
+
latest = versions[versions.length - 1] || null;
|
|
371
|
+
}
|
|
372
|
+
} catch {
|
|
373
|
+
}
|
|
374
|
+
}
|
|
375
|
+
return { current, latest, packageManager: "pip", packageName };
|
|
376
|
+
}
|
|
377
|
+
async function upgradePythonPackage(_projectDir, info) {
|
|
378
|
+
await execa("pip", ["install", "--upgrade", info.packageName]);
|
|
379
|
+
}
|
|
380
|
+
async function checkGoPackage(projectDir) {
|
|
381
|
+
const packageName = "github.com/mark3labs/mcp-go";
|
|
382
|
+
let current = null;
|
|
383
|
+
let latest = null;
|
|
384
|
+
try {
|
|
385
|
+
const goModContent = await fs2.readFile(path2.join(projectDir, "go.mod"), "utf-8");
|
|
386
|
+
const match = goModContent.match(new RegExp(`${packageName.replace(/\//g, "\\/")}\\s+v([\\d.]+)`));
|
|
387
|
+
current = match?.[1] || null;
|
|
388
|
+
} catch {
|
|
389
|
+
}
|
|
390
|
+
try {
|
|
391
|
+
const { stdout } = await execa("go", ["list", "-m", "-versions", packageName]);
|
|
392
|
+
const versions = stdout.split(" ").slice(1);
|
|
393
|
+
latest = versions[versions.length - 1]?.replace("v", "") || null;
|
|
394
|
+
} catch {
|
|
395
|
+
}
|
|
396
|
+
return { current, latest, packageManager: "go", packageName };
|
|
397
|
+
}
|
|
398
|
+
async function upgradeGoPackage(projectDir, info) {
|
|
399
|
+
await execa("go", ["get", "-u", `${info.packageName}@latest`], { cwd: projectDir });
|
|
400
|
+
await execa("go", ["mod", "tidy"], { cwd: projectDir });
|
|
401
|
+
}
|
|
402
|
+
async function checkRustPackage(projectDir) {
|
|
403
|
+
const packageName = "rmcp";
|
|
404
|
+
let current = null;
|
|
405
|
+
let latest = null;
|
|
406
|
+
try {
|
|
407
|
+
const cargoContent = await fs2.readFile(path2.join(projectDir, "Cargo.toml"), "utf-8");
|
|
408
|
+
const match = cargoContent.match(/rmcp\s*=\s*["']([^"']+)["']/);
|
|
409
|
+
current = match?.[1] || null;
|
|
410
|
+
} catch {
|
|
411
|
+
}
|
|
412
|
+
try {
|
|
413
|
+
const { stdout } = await execa("cargo", ["search", packageName, "--limit", "1"]);
|
|
414
|
+
const match = stdout.match(/rmcp\s*=\s*"([^"]+)"/);
|
|
415
|
+
latest = match?.[1] || null;
|
|
416
|
+
} catch {
|
|
417
|
+
}
|
|
418
|
+
return { current, latest, packageManager: "cargo", packageName };
|
|
419
|
+
}
|
|
420
|
+
async function upgradeRustPackage(projectDir, info) {
|
|
421
|
+
await execa("cargo", ["update", "-p", info.packageName], { cwd: projectDir });
|
|
422
|
+
}
|
|
423
|
+
|
|
424
|
+
// src/cli.ts
|
|
11
425
|
var program = new Command();
|
|
12
426
|
var logo = `
|
|
13
|
-
${
|
|
14
|
-
${
|
|
15
|
-
${
|
|
16
|
-
${
|
|
427
|
+
${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")}
|
|
428
|
+
${chalk4.cyan("\u2551")} ${chalk4.bold.white("mcp-new")} ${chalk4.cyan("\u2551")}
|
|
429
|
+
${chalk4.cyan("\u2551")} ${chalk4.gray("Generate MCP servers in seconds")} ${chalk4.cyan("\u2551")}
|
|
430
|
+
${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
431
|
`;
|
|
18
432
|
var examples = `
|
|
19
|
-
${
|
|
433
|
+
${chalk4.bold("Examples:")}
|
|
20
434
|
|
|
21
|
-
${
|
|
22
|
-
${
|
|
435
|
+
${chalk4.gray("# Create a new MCP server with interactive wizard")}
|
|
436
|
+
${chalk4.cyan("$")} mcp-new my-server
|
|
23
437
|
|
|
24
|
-
${
|
|
25
|
-
${
|
|
438
|
+
${chalk4.gray("# Create TypeScript server with defaults")}
|
|
439
|
+
${chalk4.cyan("$")} mcp-new my-server -t -y
|
|
26
440
|
|
|
27
|
-
${
|
|
28
|
-
${
|
|
441
|
+
${chalk4.gray("# Create Python server")}
|
|
442
|
+
${chalk4.cyan("$")} mcp-new my-server -p
|
|
29
443
|
|
|
30
|
-
${
|
|
31
|
-
${
|
|
32
|
-
${
|
|
33
|
-
${
|
|
444
|
+
${chalk4.gray("# Create from preset template")}
|
|
445
|
+
${chalk4.cyan("$")} mcp-new my-db --preset database
|
|
446
|
+
${chalk4.cyan("$")} mcp-new my-api --preset rest-api
|
|
447
|
+
${chalk4.cyan("$")} mcp-new my-fs --preset filesystem
|
|
34
448
|
|
|
35
|
-
${
|
|
36
|
-
${
|
|
449
|
+
${chalk4.gray("# Create from OpenAPI specification")}
|
|
450
|
+
${chalk4.cyan("$")} mcp-new my-api --from-openapi ./openapi.yaml
|
|
37
451
|
|
|
38
|
-
${
|
|
39
|
-
${
|
|
452
|
+
${chalk4.gray("# Create using AI (requires ANTHROPIC_API_KEY)")}
|
|
453
|
+
${chalk4.cyan("$")} mcp-new my-server --from-prompt
|
|
40
454
|
|
|
41
|
-
${
|
|
455
|
+
${chalk4.bold("Available Presets:")}
|
|
42
456
|
|
|
43
|
-
${
|
|
44
|
-
${
|
|
45
|
-
${
|
|
457
|
+
${chalk4.yellow("database")} Database CRUD tools (query, insert, update, delete, list_tables)
|
|
458
|
+
${chalk4.yellow("rest-api")} REST API tools (http_get, http_post, http_put, http_delete, set_base_url)
|
|
459
|
+
${chalk4.yellow("filesystem")} File system tools (read_file, write_file, list_directory, search_files, file_info)
|
|
46
460
|
|
|
47
|
-
${
|
|
461
|
+
${chalk4.bold("Supported Languages:")}
|
|
48
462
|
|
|
49
|
-
${
|
|
50
|
-
${
|
|
51
|
-
${
|
|
52
|
-
${
|
|
463
|
+
${chalk4.green("-t, --typescript")} TypeScript with npm
|
|
464
|
+
${chalk4.green("-p, --python")} Python with pip
|
|
465
|
+
${chalk4.green("-g, --go")} Go with go modules
|
|
466
|
+
${chalk4.green("-r, --rust")} Rust with cargo
|
|
53
467
|
|
|
54
|
-
${
|
|
468
|
+
${chalk4.bold("Learn More:")}
|
|
55
469
|
|
|
56
|
-
Documentation: ${
|
|
57
|
-
MCP Spec: ${
|
|
470
|
+
Documentation: ${chalk4.underline("https://github.com/d1maash/mcp-new")}
|
|
471
|
+
MCP Spec: ${chalk4.underline("https://spec.modelcontextprotocol.io")}
|
|
58
472
|
`;
|
|
59
|
-
program.name("mcp-new").description("CLI tool for generating MCP (Model Context Protocol) servers").version("1.2.
|
|
473
|
+
program.name("mcp-new").description("CLI tool for generating MCP (Model Context Protocol) servers").version("1.2.2").addHelpText("beforeAll", logo).addHelpText("after", examples);
|
|
60
474
|
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
475
|
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("after", `
|
|
62
|
-
${
|
|
476
|
+
${chalk4.bold("Examples:")}
|
|
63
477
|
|
|
64
|
-
${
|
|
65
|
-
${
|
|
478
|
+
${chalk4.gray("# Initialize in current directory")}
|
|
479
|
+
${chalk4.cyan("$")} mcp-new init
|
|
66
480
|
|
|
67
|
-
${
|
|
68
|
-
${
|
|
481
|
+
${chalk4.gray("# Initialize with TypeScript")}
|
|
482
|
+
${chalk4.cyan("$")} mcp-new init -t
|
|
69
483
|
|
|
70
|
-
${
|
|
71
|
-
${
|
|
484
|
+
${chalk4.gray("# Force initialize (overwrite existing files)")}
|
|
485
|
+
${chalk4.cyan("$")} mcp-new init -f
|
|
72
486
|
`).action(initCommand);
|
|
73
487
|
program.command("add-tool").description("Add a new tool to an existing MCP server").option("-n, --name <name>", "Tool name (snake_case)").addHelpText("after", `
|
|
74
|
-
${
|
|
488
|
+
${chalk4.bold("Examples:")}
|
|
75
489
|
|
|
76
|
-
${
|
|
77
|
-
${
|
|
490
|
+
${chalk4.gray("# Add tool interactively")}
|
|
491
|
+
${chalk4.cyan("$")} mcp-new add-tool
|
|
78
492
|
|
|
79
|
-
${
|
|
80
|
-
${
|
|
493
|
+
${chalk4.gray("# Add tool with name")}
|
|
494
|
+
${chalk4.cyan("$")} mcp-new add-tool -n my_new_tool
|
|
81
495
|
`).action(addToolCommand);
|
|
496
|
+
program.command("list-presets").description("List all available preset templates").addHelpText("after", `
|
|
497
|
+
${chalk4.bold("Examples:")}
|
|
498
|
+
|
|
499
|
+
${chalk4.gray("# Show all presets with their tools")}
|
|
500
|
+
${chalk4.cyan("$")} mcp-new list-presets
|
|
501
|
+
`).action(listPresetsCommand);
|
|
502
|
+
program.command("validate").description("Validate the current MCP server project").addHelpText("after", `
|
|
503
|
+
${chalk4.bold("Examples:")}
|
|
504
|
+
|
|
505
|
+
${chalk4.gray("# Validate current project")}
|
|
506
|
+
${chalk4.cyan("$")} mcp-new validate
|
|
507
|
+
|
|
508
|
+
${chalk4.bold("Checks:")}
|
|
509
|
+
\u2022 Project configuration (package.json, pyproject.toml, etc.)
|
|
510
|
+
\u2022 MCP SDK dependency presence and version
|
|
511
|
+
\u2022 Entry point file existence
|
|
512
|
+
\u2022 Basic project structure
|
|
513
|
+
`).action(validateCommand);
|
|
514
|
+
program.command("upgrade").description("Upgrade MCP SDK to the latest version").option("-c, --check", "Check for updates without installing").addHelpText("after", `
|
|
515
|
+
${chalk4.bold("Examples:")}
|
|
516
|
+
|
|
517
|
+
${chalk4.gray("# Upgrade MCP SDK to latest version")}
|
|
518
|
+
${chalk4.cyan("$")} mcp-new upgrade
|
|
519
|
+
|
|
520
|
+
${chalk4.gray("# Check for updates without installing")}
|
|
521
|
+
${chalk4.cyan("$")} mcp-new upgrade --check
|
|
522
|
+
|
|
523
|
+
${chalk4.bold("Supported languages:")}
|
|
524
|
+
\u2022 TypeScript/JavaScript (npm)
|
|
525
|
+
\u2022 Python (pip)
|
|
526
|
+
\u2022 Go (go modules)
|
|
527
|
+
\u2022 Rust (cargo)
|
|
528
|
+
`).action(upgradeCommand);
|
|
82
529
|
program.parse();
|
|
83
530
|
if (process.argv.length === 2) {
|
|
84
531
|
program.help();
|
package/dist/index.js
CHANGED