frontmcp 0.2.5 → 0.3.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/dist/cli.js DELETED
@@ -1,667 +0,0 @@
1
- #!/usr/bin/env node
2
- "use strict";
3
- /**
4
- * frontmcp - FrontMCP command line interface
5
- * Save as bin/frontmcp.ts (compile to JS with shebang preserved) or run with tsx.
6
- */
7
- var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
8
- if (k2 === undefined) k2 = k;
9
- var desc = Object.getOwnPropertyDescriptor(m, k);
10
- if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
11
- desc = { enumerable: true, get: function() { return m[k]; } };
12
- }
13
- Object.defineProperty(o, k2, desc);
14
- }) : (function(o, m, k, k2) {
15
- if (k2 === undefined) k2 = k;
16
- o[k2] = m[k];
17
- }));
18
- var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
19
- Object.defineProperty(o, "default", { enumerable: true, value: v });
20
- }) : function(o, v) {
21
- o["default"] = v;
22
- });
23
- var __importStar = (this && this.__importStar) || (function () {
24
- var ownKeys = function(o) {
25
- ownKeys = Object.getOwnPropertyNames || function (o) {
26
- var ar = [];
27
- for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
28
- return ar;
29
- };
30
- return ownKeys(o);
31
- };
32
- return function (mod) {
33
- if (mod && mod.__esModule) return mod;
34
- var result = {};
35
- if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
36
- __setModuleDefault(result, mod);
37
- return result;
38
- };
39
- })();
40
- var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
41
- function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
42
- return new (P || (P = Promise))(function (resolve, reject) {
43
- function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
44
- function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
45
- function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
46
- step((generator = generator.apply(thisArg, _arguments || [])).next());
47
- });
48
- };
49
- Object.defineProperty(exports, "__esModule", { value: true });
50
- const fs = __importStar(require("fs"));
51
- const fs_1 = require("fs");
52
- const path = __importStar(require("path"));
53
- const child_process_1 = require("child_process");
54
- const version_1 = require("./version");
55
- const COLORS = {
56
- reset: '\x1b[0m',
57
- bold: '\x1b[1m',
58
- dim: '\x1b[2m',
59
- red: '\x1b[31m',
60
- green: '\x1b[32m',
61
- yellow: '\x1b[33m',
62
- blue: '\x1b[34m',
63
- cyan: '\x1b[36m',
64
- gray: '\x1b[90m',
65
- };
66
- const c = (color, s) => COLORS[color] + s + COLORS.reset;
67
- function showHelp() {
68
- console.log(`
69
- ${c('bold', 'frontmcp')} — FrontMCP command line interface
70
-
71
- ${c('bold', 'Usage')}
72
- frontmcp <command> [options]
73
-
74
- ${c('bold', 'Commands')}
75
- dev Start in development mode (tsx --watch <entry> + async type-check)
76
- build Compile entry with TypeScript (tsc)
77
- init Create or fix a tsconfig.json suitable for FrontMCP
78
- doctor Check Node/npm versions and tsconfig requirements
79
- inspector Launch MCP Inspector (npx @modelcontextprotocol/inspector)
80
- create <name> Scaffold a new FrontMCP project in ./<name>
81
- help Show this help message
82
-
83
- ${c('bold', 'Options')}
84
- -o, --out-dir <dir> Output directory (default: ./dist)
85
- -e, --entry <path> Manually specify entry file path
86
-
87
- ${c('bold', 'Examples')}
88
- frontmcp dev
89
- frontmcp build --out-dir build
90
- frontmcp init
91
- frontmcp doctor
92
- frontmcp inspector
93
- npx frontmcp create my-mcp
94
- `);
95
- }
96
- function parseArgs(argv) {
97
- const out = { _: [] };
98
- for (let i = 0; i < argv.length; i++) {
99
- const a = argv[i];
100
- if (a === '--out-dir' || a === '-o')
101
- out.outDir = argv[++i];
102
- else if (a === '--entry' || a === '-e')
103
- out.entry = argv[++i];
104
- else if (a === '--help' || a === '-h')
105
- out.help = true;
106
- else
107
- out._.push(a);
108
- }
109
- return out;
110
- }
111
- function fileExists(p) {
112
- return __awaiter(this, void 0, void 0, function* () {
113
- try {
114
- yield fs_1.promises.access(p, fs.constants.F_OK);
115
- return true;
116
- }
117
- catch (_a) {
118
- return false;
119
- }
120
- });
121
- }
122
- function readJSON(jsonPath) {
123
- return __awaiter(this, void 0, void 0, function* () {
124
- try {
125
- const buf = yield fs_1.promises.readFile(jsonPath, 'utf8');
126
- return JSON.parse(buf);
127
- }
128
- catch (_a) {
129
- return null;
130
- }
131
- });
132
- }
133
- function writeJSON(p, obj) {
134
- return __awaiter(this, void 0, void 0, function* () {
135
- yield fs_1.promises.writeFile(p, JSON.stringify(obj, null, 2) + '\n', 'utf8');
136
- });
137
- }
138
- function tryCandidates(base) {
139
- const exts = ['', '.ts', '.tsx', '.js', '.mjs', '.cjs'];
140
- return exts.map((ext) => base + ext);
141
- }
142
- function resolveEntry(cwd, explicit) {
143
- return __awaiter(this, void 0, void 0, function* () {
144
- if (explicit) {
145
- const full = path.resolve(cwd, explicit);
146
- if (yield fileExists(full))
147
- return full;
148
- throw new Error(`Entry override not found: ${explicit}`);
149
- }
150
- const pkgPath = path.join(cwd, 'package.json');
151
- if (yield fileExists(pkgPath)) {
152
- const pkg = yield readJSON(pkgPath);
153
- if (pkg && typeof pkg.main === 'string' && pkg.main.trim()) {
154
- const mainCandidates = tryCandidates(path.resolve(cwd, pkg.main));
155
- for (const p of mainCandidates) {
156
- if (yield fileExists(p))
157
- return p;
158
- }
159
- const asDir = path.resolve(cwd, pkg.main);
160
- const idxCandidates = tryCandidates(path.join(asDir, 'index'));
161
- for (const p of idxCandidates) {
162
- if (yield fileExists(p))
163
- return p;
164
- }
165
- }
166
- }
167
- const fallback = path.join(cwd, 'src', 'main.ts');
168
- if (yield fileExists(fallback))
169
- return fallback;
170
- const msg = [
171
- c('red', 'No entry file found.'),
172
- '',
173
- 'I looked for:',
174
- ` • ${pkgPath} with a valid "main" field`,
175
- ` • ${path.relative(cwd, fallback)}`,
176
- '',
177
- 'Please create an entry file (e.g. src/main.ts) or set "main" in package.json,',
178
- 'or run with an explicit path:',
179
- ` frontmcp dev --entry src/main.ts`,
180
- ].join('\n');
181
- throw new Error(msg);
182
- });
183
- }
184
- function runCmd(cmd, args, opts = {}) {
185
- return new Promise((resolve, reject) => {
186
- const child = (0, child_process_1.spawn)(cmd, args, Object.assign({ stdio: 'inherit', shell: true }, opts));
187
- child.on('close', (code) => (code === 0 ? resolve() : reject(new Error(`${cmd} exited with code ${code}`))));
188
- child.on('error', reject);
189
- });
190
- }
191
- function ensureDir(p) {
192
- return __awaiter(this, void 0, void 0, function* () {
193
- yield fs_1.promises.mkdir(p, { recursive: true });
194
- });
195
- }
196
- function isDirEmpty(dir) {
197
- return __awaiter(this, void 0, void 0, function* () {
198
- try {
199
- const items = yield fs_1.promises.readdir(dir);
200
- return items.length === 0;
201
- }
202
- catch (e) {
203
- if ((e === null || e === void 0 ? void 0 : e.code) === 'ENOENT')
204
- return true;
205
- throw e;
206
- }
207
- });
208
- }
209
- function sanitizeForFolder(name) {
210
- const seg = name.startsWith('@') && name.includes('/') ? name.split('/')[1] : name;
211
- return seg.replace(/[^a-zA-Z0-9._-]/g, '-').replace(/-+/g, '-').replace(/^-|-$/g, '').toLowerCase() || 'frontmcp-app';
212
- }
213
- function sanitizeForNpm(name) {
214
- if (name.startsWith('@') && name.includes('/')) {
215
- const [scope, pkg] = name.split('/');
216
- const s = scope.replace(/[^a-z0-9-]/gi, '').toLowerCase();
217
- const p = pkg.replace(/[^a-z0-9._-]/gi, '-').toLowerCase();
218
- return `@${s}/${p || 'frontmcp-app'}`;
219
- }
220
- return name.replace(/[^a-z0-9._-]/gi, '-').toLowerCase() || 'frontmcp-app';
221
- }
222
- /* --------------------------------- Actions -------------------------------- */
223
- function isTsLike(p) {
224
- return /\.tsx?$/i.test(p);
225
- }
226
- function killQuiet(proc) {
227
- try {
228
- proc && proc.kill('SIGINT');
229
- }
230
- catch (_a) {
231
- }
232
- }
233
- function runDev(opts) {
234
- return __awaiter(this, void 0, void 0, function* () {
235
- const cwd = process.cwd();
236
- const entry = yield resolveEntry(cwd, opts.entry);
237
- console.log(`${c('cyan', '[dev]')} using entry: ${path.relative(cwd, entry)}`);
238
- console.log(`${c('gray', '[dev]')} starting ${c('bold', 'tsx --watch')} and ${c('bold', 'tsc --noEmit --watch')} (async type-checker)`);
239
- console.log(`${c('gray', 'hint:')} press Ctrl+C to stop`);
240
- // Start tsx watcher (app run)
241
- const app = (0, child_process_1.spawn)('npx', ['-y', 'tsx', '--watch', entry], { stdio: 'inherit', shell: true });
242
- // Start tsc in watch mode for async type-checking (non-blocking)
243
- const checker = (0, child_process_1.spawn)('npx', ['-y', 'tsc', '--noEmit', '--pretty', '--watch'], { stdio: 'inherit', shell: true });
244
- const cleanup = () => {
245
- killQuiet(checker);
246
- killQuiet(app);
247
- };
248
- process.on('SIGINT', () => {
249
- cleanup();
250
- process.exit(0);
251
- });
252
- yield new Promise((resolve, reject) => {
253
- app.on('close', (_code) => {
254
- // When app exits, stop checker too.
255
- cleanup();
256
- resolve();
257
- });
258
- app.on('error', (err) => {
259
- cleanup();
260
- reject(err);
261
- });
262
- });
263
- });
264
- }
265
- function runBuild(opts) {
266
- return __awaiter(this, void 0, void 0, function* () {
267
- const cwd = process.cwd();
268
- const entry = yield resolveEntry(cwd, opts.entry);
269
- const outDir = path.resolve(cwd, opts.outDir || 'dist');
270
- yield ensureDir(outDir);
271
- console.log(`${c('cyan', '[build]')} entry: ${path.relative(cwd, entry)}`);
272
- console.log(`${c('cyan', '[build]')} outDir: ${path.relative(cwd, outDir)}`);
273
- const args = [];
274
- args.push('--outDir', outDir);
275
- args.push('--skipLibCheck');
276
- args.push('--rootDir', path.dirname(entry));
277
- if (!isTsLike(entry)) {
278
- args.push('--allowJs');
279
- console.log(c('yellow', '[build] Entry is not TypeScript; enabling --allowJs'));
280
- }
281
- const tsconfigPath = path.join(cwd, 'tsconfig.json');
282
- if (yield fileExists(tsconfigPath)) {
283
- console.log(c('gray', `[build] tsconfig.json detected (project options will be respected where applicable)`));
284
- }
285
- yield runCmd('npx', ['-y', 'tsc', entry, ...args]);
286
- console.log(c('green', '✅ Build completed.'));
287
- console.log(c('gray', `Output placed in ${path.relative(cwd, outDir)}`));
288
- });
289
- }
290
- /* --------------------------- tsconfig management --------------------------- */
291
- const REQUIRED_DECORATOR_FIELDS = {
292
- target: 'es2021',
293
- module: 'esnext',
294
- emitDecoratorMetadata: true,
295
- experimentalDecorators: true,
296
- strictFunctionTypes: true,
297
- moduleResolution: 'node',
298
- };
299
- const RECOMMENDED_TSCONFIG = {
300
- compilerOptions: {
301
- target: REQUIRED_DECORATOR_FIELDS.target,
302
- module: REQUIRED_DECORATOR_FIELDS.module,
303
- emitDecoratorMetadata: REQUIRED_DECORATOR_FIELDS.emitDecoratorMetadata,
304
- experimentalDecorators: REQUIRED_DECORATOR_FIELDS.experimentalDecorators,
305
- strictFunctionTypes: REQUIRED_DECORATOR_FIELDS.strictFunctionTypes,
306
- moduleResolution: REQUIRED_DECORATOR_FIELDS.moduleResolution,
307
- strict: true,
308
- esModuleInterop: true,
309
- resolveJsonModule: true,
310
- skipLibCheck: true,
311
- sourceMap: true,
312
- outDir: 'dist',
313
- rootDir: 'src',
314
- types: ['node'],
315
- },
316
- include: ['src/**/*'],
317
- };
318
- function deepMerge(base, patch) {
319
- var _a;
320
- const out = Object.assign({}, base);
321
- for (const [k, v] of Object.entries(patch)) {
322
- if (v && typeof v === 'object' && !Array.isArray(v)) {
323
- out[k] = deepMerge((_a = base[k]) !== null && _a !== void 0 ? _a : {}, v);
324
- }
325
- else {
326
- out[k] = v;
327
- }
328
- }
329
- return out;
330
- }
331
- function ensureRequiredTsOptions(obj) {
332
- const next = Object.assign({}, obj);
333
- next.compilerOptions = Object.assign({}, (next.compilerOptions || {}));
334
- next.compilerOptions.target = REQUIRED_DECORATOR_FIELDS.target;
335
- next.compilerOptions.module = REQUIRED_DECORATOR_FIELDS.module;
336
- next.compilerOptions.emitDecoratorMetadata = REQUIRED_DECORATOR_FIELDS.emitDecoratorMetadata;
337
- next.compilerOptions.experimentalDecorators = REQUIRED_DECORATOR_FIELDS.experimentalDecorators;
338
- return next;
339
- }
340
- function normalizeStr(x) {
341
- return typeof x === 'string' ? x.toLowerCase() : undefined;
342
- }
343
- function checkRequiredTsOptions(compilerOptions) {
344
- const issues = [];
345
- const ok = [];
346
- const target = normalizeStr(compilerOptions === null || compilerOptions === void 0 ? void 0 : compilerOptions.target);
347
- const moduleVal = normalizeStr(compilerOptions === null || compilerOptions === void 0 ? void 0 : compilerOptions.module);
348
- const edm = compilerOptions === null || compilerOptions === void 0 ? void 0 : compilerOptions.emitDecoratorMetadata;
349
- const ed = compilerOptions === null || compilerOptions === void 0 ? void 0 : compilerOptions.experimentalDecorators;
350
- if (target === REQUIRED_DECORATOR_FIELDS.target)
351
- ok.push(`compilerOptions.target = "${REQUIRED_DECORATOR_FIELDS.target}"`);
352
- else
353
- issues.push(`compilerOptions.target should be "${REQUIRED_DECORATOR_FIELDS.target}"`);
354
- if (moduleVal === REQUIRED_DECORATOR_FIELDS.module)
355
- ok.push(`compilerOptions.module = "${REQUIRED_DECORATOR_FIELDS.module}"`);
356
- else
357
- issues.push(`compilerOptions.module should be "${REQUIRED_DECORATOR_FIELDS.module}"`);
358
- if (edm === REQUIRED_DECORATOR_FIELDS.emitDecoratorMetadata)
359
- ok.push(`compilerOptions.emitDecoratorMetadata = true`);
360
- else
361
- issues.push(`compilerOptions.emitDecoratorMetadata should be true`);
362
- if (ed === REQUIRED_DECORATOR_FIELDS.experimentalDecorators)
363
- ok.push(`compilerOptions.experimentalDecorators = true`);
364
- else
365
- issues.push(`compilerOptions.experimentalDecorators should be true`);
366
- return { ok, issues };
367
- }
368
- function runInit(baseDir) {
369
- return __awaiter(this, void 0, void 0, function* () {
370
- const cwd = baseDir !== null && baseDir !== void 0 ? baseDir : process.cwd();
371
- const tsconfigPath = path.join(cwd, 'tsconfig.json');
372
- const existing = yield readJSON(tsconfigPath);
373
- if (!existing) {
374
- console.log(c('yellow', `tsconfig.json not found — creating one in ${path.relative(process.cwd(), cwd) || '.'}.`));
375
- yield writeJSON(tsconfigPath, RECOMMENDED_TSCONFIG);
376
- console.log(c('green', '✅ Created tsconfig.json with required decorator settings.'));
377
- return;
378
- }
379
- let merged = deepMerge(RECOMMENDED_TSCONFIG, existing);
380
- merged = ensureRequiredTsOptions(merged);
381
- yield writeJSON(tsconfigPath, merged);
382
- console.log(c('green', '✅ tsconfig.json verified and updated (required decorator settings enforced).'));
383
- });
384
- }
385
- function cmpSemver(a, b) {
386
- const pa = a.split('.').map((n) => parseInt(n, 10) || 0);
387
- const pb = b.split('.').map((n) => parseInt(n, 10) || 0);
388
- for (let i = 0; i < 3; i++) {
389
- if ((pa[i] || 0) > (pb[i] || 0))
390
- return 1;
391
- if ((pa[i] || 0) < (pb[i] || 0))
392
- return -1;
393
- }
394
- return 0;
395
- }
396
- function runDoctor() {
397
- return __awaiter(this, void 0, void 0, function* () {
398
- var _a, _b, _c;
399
- const MIN_NODE = '22.0.0';
400
- const MIN_NPM = '10.0.0';
401
- const cwd = process.cwd();
402
- let ok = true;
403
- const nodeVer = process.versions.node;
404
- if (cmpSemver(nodeVer, MIN_NODE) >= 0) {
405
- console.log(`✅ Node ${nodeVer} (min ${MIN_NODE})`);
406
- }
407
- else {
408
- ok = false;
409
- console.log(`❌ Node ${nodeVer} — please upgrade to >= ${MIN_NODE}`);
410
- }
411
- let npmVer = 'unknown';
412
- try {
413
- npmVer = yield new Promise((resolve, reject) => {
414
- var _a;
415
- const child = (0, child_process_1.spawn)('npm', ['-v'], { shell: true });
416
- let out = '';
417
- (_a = child.stdout) === null || _a === void 0 ? void 0 : _a.on('data', (d) => (out += String(d)));
418
- child.on('close', () => resolve(out.trim()));
419
- child.on('error', reject);
420
- });
421
- if (cmpSemver(npmVer, MIN_NPM) >= 0) {
422
- console.log(`✅ npm ${npmVer} (min ${MIN_NPM})`);
423
- }
424
- else {
425
- ok = false;
426
- console.log(`❌ npm ${npmVer} — please upgrade to >= ${MIN_NPM}`);
427
- }
428
- }
429
- catch (_d) {
430
- ok = false;
431
- console.log('❌ npm not found in PATH');
432
- }
433
- const tsconfigPath = path.join(cwd, 'tsconfig.json');
434
- if (yield fileExists(tsconfigPath)) {
435
- console.log(`✅ tsconfig.json found`);
436
- const tsconfig = yield readJSON(tsconfigPath);
437
- const { ok: oks, issues } = checkRequiredTsOptions(tsconfig === null || tsconfig === void 0 ? void 0 : tsconfig.compilerOptions);
438
- for (const line of oks)
439
- console.log(c('green', ` ✓ ${line}`));
440
- if (issues.length) {
441
- ok = false;
442
- for (const line of issues)
443
- console.log(c('yellow', ` • ${line}`));
444
- console.log(c('cyan', ` -> Run "frontmcp init" to apply the required settings.`));
445
- }
446
- }
447
- else {
448
- ok = false;
449
- console.log(`❌ tsconfig.json not found — run ${c('cyan', 'frontmcp init')}`);
450
- }
451
- try {
452
- const entry = yield resolveEntry(cwd);
453
- console.log(`✅ entry detected: ${path.relative(cwd, entry)}`);
454
- }
455
- catch (e) {
456
- const firstLine = (_c = (_b = (_a = e === null || e === void 0 ? void 0 : e.message) === null || _a === void 0 ? void 0 : _a.split('\n')) === null || _b === void 0 ? void 0 : _b[0]) !== null && _c !== void 0 ? _c : 'entry not found';
457
- console.log(`❌ entry not detected — ${firstLine}`);
458
- }
459
- if (ok)
460
- console.log(c('green', '\nAll checks passed. You are ready to go!'));
461
- else
462
- console.log(c('yellow', '\nSome checks failed. See above for fixes.'));
463
- });
464
- }
465
- /* ------------------------------- Inspector -------------------------------- */
466
- function runInspector() {
467
- return __awaiter(this, void 0, void 0, function* () {
468
- console.log(`${c('cyan', '[inspector]')} launching MCP Inspector...`);
469
- yield runCmd('npx', ['-y', '@modelcontextprotocol/inspector']);
470
- });
471
- }
472
- /* --------------------------------- Create --------------------------------- */
473
- function pkgNameFromCwd(cwd) {
474
- return path.basename(cwd).replace(/[^a-zA-Z0-9._-]/g, '-').toLowerCase() || 'frontmcp-app';
475
- }
476
- function upsertPackageJson(cwd, nameOverride, selfVersion) {
477
- return __awaiter(this, void 0, void 0, function* () {
478
- var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k;
479
- const pkgPath = path.join(cwd, 'package.json');
480
- const existing = yield readJSON(pkgPath);
481
- const base = {
482
- name: nameOverride !== null && nameOverride !== void 0 ? nameOverride : pkgNameFromCwd(cwd),
483
- version: '0.1.0',
484
- private: true,
485
- type: 'commonjs',
486
- main: 'src/main.ts',
487
- scripts: {
488
- dev: 'frontmcp dev',
489
- build: 'frontmcp build',
490
- inspect: 'frontmcp inspector',
491
- doctor: 'frontmcp doctor',
492
- },
493
- engines: {
494
- node: '>=22',
495
- npm: '>=10',
496
- },
497
- dependencies: {
498
- '@frontmcp/sdk': '^0.2.5',
499
- '@frontmcp/core': '^0.2.5',
500
- zod: '^3.23.8',
501
- 'reflect-metadata': '^0.2.2',
502
- },
503
- devDependencies: {
504
- frontmcp: selfVersion, // exact CLI version used by npx
505
- tsx: '^4.20.6',
506
- "@types/node": "^20.11.30",
507
- typescript: '^5.5.3',
508
- },
509
- };
510
- if (!existing) {
511
- yield writeJSON(pkgPath, base);
512
- console.log(c('green', '✅ Created package.json (pinned versions + exact frontmcp)'));
513
- return;
514
- }
515
- const merged = Object.assign(Object.assign({}, base), existing);
516
- merged.name = existing.name || base.name;
517
- merged.main = existing.main || base.main;
518
- merged.type = existing.type || base.type;
519
- merged.scripts = Object.assign(Object.assign(Object.assign({}, base.scripts), (existing.scripts || {})), { dev: (_b = (_a = existing.scripts) === null || _a === void 0 ? void 0 : _a.dev) !== null && _b !== void 0 ? _b : base.scripts.dev, build: (_d = (_c = existing.scripts) === null || _c === void 0 ? void 0 : _c.build) !== null && _d !== void 0 ? _d : base.scripts.build, inspect: (_f = (_e = existing.scripts) === null || _e === void 0 ? void 0 : _e.inspect) !== null && _f !== void 0 ? _f : base.scripts.inspect, doctor: (_h = (_g = existing.scripts) === null || _g === void 0 ? void 0 : _g.doctor) !== null && _h !== void 0 ? _h : base.scripts.doctor });
520
- merged.engines = Object.assign(Object.assign({}, (existing.engines || {})), { node: ((_j = existing.engines) === null || _j === void 0 ? void 0 : _j.node) || base.engines.node, npm: ((_k = existing.engines) === null || _k === void 0 ? void 0 : _k.npm) || base.engines.npm });
521
- merged.dependencies = Object.assign(Object.assign(Object.assign({}, base.dependencies), (existing.dependencies || {})), { zod: '^3.23.8', 'reflect-metadata': '^0.2.2' });
522
- merged.devDependencies = Object.assign(Object.assign(Object.assign({}, base.devDependencies), (existing.devDependencies || {})), { frontmcp: selfVersion, tsx: '^4.20.6', typescript: '^5.5.3' });
523
- yield writeJSON(pkgPath, merged);
524
- console.log(c('green', '✅ Updated package.json (ensured exact frontmcp and pinned versions)'));
525
- });
526
- }
527
- function scaffoldFileIfMissing(baseDir, p, content) {
528
- return __awaiter(this, void 0, void 0, function* () {
529
- if (yield fileExists(p)) {
530
- console.log(c('gray', `skip: ${path.relative(baseDir, p)} already exists`));
531
- return;
532
- }
533
- yield ensureDir(path.dirname(p));
534
- yield fs_1.promises.writeFile(p, content.replace(/^\n/, ''), 'utf8');
535
- console.log(c('green', `✓ created ${path.relative(baseDir, p)}`));
536
- });
537
- }
538
- const TEMPLATE_MAIN_TS = `
539
- import 'reflect-metadata';
540
- import { FrontMcp } from '@frontmcp/sdk';
541
- import { CalcApp } from './calc.app';
542
-
543
- @FrontMcp({
544
- info: { name: 'Demo 🚀', version: '0.1.0' },
545
- apps: [CalcApp],
546
- auth: {
547
- type: 'remote',
548
- name: 'my-remote-auth',
549
- baseUrl: 'https://idp.example.com',
550
- },
551
- })
552
- export default class Server {}
553
- `;
554
- const TEMPLATE_CALC_APP_TS = `
555
- import { App } from '@frontmcp/sdk';
556
- import AddTool from './tools/add.tool';
557
-
558
- @App({
559
- id: 'calc',
560
- name: 'Calculator',
561
- tools: [AddTool],
562
- })
563
- export class CalcApp {}
564
- `;
565
- const TEMPLATE_ADD_TOOL_TS = `
566
- import { tool } from '@frontmcp/sdk';
567
- import { z } from 'zod';
568
-
569
- const AddTool = tool({
570
- name: 'add',
571
- description: 'Add two numbers',
572
- inputSchema: { a: z.number(), b: z.number() },
573
- outputSchema: { result: z.number() },
574
- })(async (input, _ctx) => {
575
- return { result: input.a + input.b };
576
- });
577
-
578
- export default AddTool;
579
- `;
580
- function runCreate(projectArg) {
581
- return __awaiter(this, void 0, void 0, function* () {
582
- if (!projectArg) {
583
- console.error(c('red', 'Error: project name is required.\n'));
584
- console.log(`Usage: ${c('bold', 'npx frontmcp create <project-name>')}`);
585
- process.exit(1);
586
- }
587
- const folder = sanitizeForFolder(projectArg);
588
- const pkgName = sanitizeForNpm(projectArg);
589
- const targetDir = path.resolve(process.cwd(), folder);
590
- if (yield fileExists(targetDir)) {
591
- if (!(yield isDirEmpty(targetDir))) {
592
- console.error(c('red', `Refusing to scaffold into non-empty directory: ${path.relative(process.cwd(), targetDir)}`));
593
- console.log(c('gray', 'Pick a different name or start with an empty folder.'));
594
- process.exit(1);
595
- }
596
- }
597
- else {
598
- yield ensureDir(targetDir);
599
- }
600
- console.log(`${c('cyan', '[create]')} Creating project in ${c('bold', './' + path.relative(process.cwd(), targetDir))}`);
601
- process.chdir(targetDir);
602
- // 1) tsconfig
603
- yield runInit(targetDir);
604
- // 2) package.json (pinned deps + exact CLI version)
605
- const selfVersion = (0, version_1.getSelfVersion)();
606
- yield upsertPackageJson(targetDir, pkgName, selfVersion);
607
- // 3) files
608
- yield scaffoldFileIfMissing(targetDir, path.join(targetDir, 'src', 'main.ts'), TEMPLATE_MAIN_TS);
609
- yield scaffoldFileIfMissing(targetDir, path.join(targetDir, 'src', 'calc.app.ts'), TEMPLATE_CALC_APP_TS);
610
- yield scaffoldFileIfMissing(targetDir, path.join(targetDir, 'src', 'tools', 'add.tool.ts'), TEMPLATE_ADD_TOOL_TS);
611
- console.log('\nNext steps:');
612
- console.log(` 1) cd ${folder}`);
613
- console.log(' 2) npm install');
614
- console.log(' 3) npm run dev ', c('gray', '# tsx watcher + async tsc type-check'));
615
- console.log(' 4) npm run inspect ', c('gray', '# launch MCP Inspector'));
616
- console.log(' 5) npm run build ', c('gray', '# compile with tsc via frontmcp build'));
617
- });
618
- }
619
- /* --------------------------------- Main ----------------------------------- */
620
- function main() {
621
- return __awaiter(this, void 0, void 0, function* () {
622
- const argv = process.argv.slice(2);
623
- const parsed = parseArgs(argv);
624
- const cmd = parsed._[0];
625
- if (parsed.help || !cmd) {
626
- showHelp();
627
- process.exit(0);
628
- }
629
- try {
630
- switch (cmd) {
631
- case 'dev':
632
- yield runDev(parsed);
633
- break;
634
- case 'build':
635
- parsed.outDir = parsed.outDir || 'dist';
636
- yield runBuild(parsed);
637
- break;
638
- case 'init':
639
- yield runInit();
640
- break;
641
- case 'doctor':
642
- yield runDoctor();
643
- break;
644
- case 'inspector':
645
- yield runInspector();
646
- break;
647
- case 'create': {
648
- const projectName = parsed._[1];
649
- yield runCreate(projectName);
650
- break;
651
- }
652
- case 'help':
653
- showHelp();
654
- break;
655
- default:
656
- console.error(c('red', `Unknown command: ${cmd}`));
657
- showHelp();
658
- process.exitCode = 1;
659
- }
660
- }
661
- catch (err) {
662
- console.error('\n' + c('red', err instanceof Error ? err.stack || err.message : String(err)));
663
- process.exit(1);
664
- }
665
- });
666
- }
667
- main();
package/dist/index.js DELETED
@@ -1,2 +0,0 @@
1
- "use strict";
2
- console.log('Happy developing ✨');
package/dist/version.js DELETED
@@ -1,7 +0,0 @@
1
- "use strict";
2
- /* ------------------------ Self-version detection -------------------------- */
3
- Object.defineProperty(exports, "__esModule", { value: true });
4
- exports.getSelfVersion = getSelfVersion;
5
- function getSelfVersion() {
6
- return '0.2.5';
7
- }