frontmcp 0.1.4 → 0.1.6
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 +49 -24
- package/package.json +5 -5
- package/src/cli.ts +55 -21
package/dist/cli.js
CHANGED
|
@@ -71,7 +71,7 @@ ${c('bold', 'Usage')}
|
|
|
71
71
|
frontmcp <command> [options]
|
|
72
72
|
|
|
73
73
|
${c('bold', 'Commands')}
|
|
74
|
-
dev Start in development mode (tsx --watch <entry>)
|
|
74
|
+
dev Start in development mode (tsx --watch <entry> + async type-check)
|
|
75
75
|
build Compile entry with TypeScript (tsc)
|
|
76
76
|
init Create or fix a tsconfig.json suitable for FrontMCP
|
|
77
77
|
doctor Check Node/npm versions and tsconfig requirements
|
|
@@ -151,14 +151,16 @@ function resolveEntry(cwd, explicit) {
|
|
|
151
151
|
const pkg = yield readJSON(pkgPath);
|
|
152
152
|
if (pkg && typeof pkg.main === 'string' && pkg.main.trim()) {
|
|
153
153
|
const mainCandidates = tryCandidates(path.resolve(cwd, pkg.main));
|
|
154
|
-
for (const p of mainCandidates)
|
|
154
|
+
for (const p of mainCandidates) {
|
|
155
155
|
if (yield fileExists(p))
|
|
156
156
|
return p;
|
|
157
|
+
}
|
|
157
158
|
const asDir = path.resolve(cwd, pkg.main);
|
|
158
159
|
const idxCandidates = tryCandidates(path.join(asDir, 'index'));
|
|
159
|
-
for (const p of idxCandidates)
|
|
160
|
+
for (const p of idxCandidates) {
|
|
160
161
|
if (yield fileExists(p))
|
|
161
162
|
return p;
|
|
163
|
+
}
|
|
162
164
|
}
|
|
163
165
|
}
|
|
164
166
|
const fallback = path.join(cwd, 'src', 'main.ts');
|
|
@@ -219,7 +221,6 @@ function sanitizeForNpm(name) {
|
|
|
219
221
|
/* ------------------------ Self-version detection -------------------------- */
|
|
220
222
|
function getSelfVersion() {
|
|
221
223
|
return __awaiter(this, void 0, void 0, function* () {
|
|
222
|
-
// Best-effort: find our own package.json near the executed bin.
|
|
223
224
|
const binPath = process.argv[1] || __filename;
|
|
224
225
|
const candidates = [
|
|
225
226
|
path.resolve(path.dirname(binPath), '../package.json'),
|
|
@@ -230,23 +231,51 @@ function getSelfVersion() {
|
|
|
230
231
|
if (j === null || j === void 0 ? void 0 : j.version)
|
|
231
232
|
return j.version;
|
|
232
233
|
}
|
|
233
|
-
// Fallback if not found; still satisfies the "has field" requirement.
|
|
234
234
|
return '0.0.0';
|
|
235
235
|
});
|
|
236
236
|
}
|
|
237
237
|
/* --------------------------------- Actions -------------------------------- */
|
|
238
|
+
function isTsLike(p) {
|
|
239
|
+
return /\.tsx?$/i.test(p);
|
|
240
|
+
}
|
|
241
|
+
function killQuiet(proc) {
|
|
242
|
+
try {
|
|
243
|
+
proc && proc.kill('SIGINT');
|
|
244
|
+
}
|
|
245
|
+
catch (_a) { }
|
|
246
|
+
}
|
|
238
247
|
function runDev(opts) {
|
|
239
248
|
return __awaiter(this, void 0, void 0, function* () {
|
|
240
249
|
const cwd = process.cwd();
|
|
241
250
|
const entry = yield resolveEntry(cwd, opts.entry);
|
|
242
251
|
console.log(`${c('cyan', '[dev]')} using entry: ${path.relative(cwd, entry)}`);
|
|
252
|
+
console.log(`${c('gray', '[dev]')} starting ${c('bold', 'tsx --watch')} and ${c('bold', 'tsc --noEmit --watch')} (async type-checker)`);
|
|
243
253
|
console.log(`${c('gray', 'hint:')} press Ctrl+C to stop`);
|
|
244
|
-
|
|
254
|
+
// Start tsx watcher (app run)
|
|
255
|
+
const app = (0, child_process_1.spawn)('npx', ['-y', 'tsx', '--watch', entry], { stdio: 'inherit', shell: true });
|
|
256
|
+
// Start tsc in watch mode for async type-checking (non-blocking)
|
|
257
|
+
const checker = (0, child_process_1.spawn)('npx', ['-y', 'tsc', '--noEmit', '--pretty', '--watch'], { stdio: 'inherit', shell: true });
|
|
258
|
+
const cleanup = () => {
|
|
259
|
+
killQuiet(checker);
|
|
260
|
+
killQuiet(app);
|
|
261
|
+
};
|
|
262
|
+
process.on('SIGINT', () => {
|
|
263
|
+
cleanup();
|
|
264
|
+
process.exit(0);
|
|
265
|
+
});
|
|
266
|
+
yield new Promise((resolve, reject) => {
|
|
267
|
+
app.on('close', (_code) => {
|
|
268
|
+
// When app exits, stop checker too.
|
|
269
|
+
cleanup();
|
|
270
|
+
resolve();
|
|
271
|
+
});
|
|
272
|
+
app.on('error', (err) => {
|
|
273
|
+
cleanup();
|
|
274
|
+
reject(err);
|
|
275
|
+
});
|
|
276
|
+
});
|
|
245
277
|
});
|
|
246
278
|
}
|
|
247
|
-
function isTsLike(p) {
|
|
248
|
-
return /\.tsx?$/i.test(p);
|
|
249
|
-
}
|
|
250
279
|
function runBuild(opts) {
|
|
251
280
|
return __awaiter(this, void 0, void 0, function* () {
|
|
252
281
|
const cwd = process.cwd();
|
|
@@ -477,19 +506,19 @@ function upsertPackageJson(cwd, nameOverride, selfVersion) {
|
|
|
477
506
|
npm: '>=10',
|
|
478
507
|
},
|
|
479
508
|
dependencies: {
|
|
480
|
-
'@frontmcp/sdk': '
|
|
509
|
+
'@frontmcp/sdk': '^0.1.3',
|
|
481
510
|
zod: '^3.23.8',
|
|
482
511
|
'reflect-metadata': '^0.2.2',
|
|
483
512
|
},
|
|
484
513
|
devDependencies: {
|
|
485
|
-
frontmcp: selfVersion, // exact version used by npx
|
|
514
|
+
frontmcp: selfVersion, // exact CLI version used by npx
|
|
486
515
|
tsx: '^4.20.6',
|
|
487
516
|
typescript: '^5.5.3',
|
|
488
517
|
},
|
|
489
518
|
};
|
|
490
519
|
if (!existing) {
|
|
491
520
|
yield writeJSON(pkgPath, base);
|
|
492
|
-
console.log(c('green', '✅ Created package.json (pinned
|
|
521
|
+
console.log(c('green', '✅ Created package.json (pinned versions + exact frontmcp)'));
|
|
493
522
|
return;
|
|
494
523
|
}
|
|
495
524
|
const merged = Object.assign(Object.assign({}, base), existing);
|
|
@@ -498,12 +527,8 @@ function upsertPackageJson(cwd, nameOverride, selfVersion) {
|
|
|
498
527
|
merged.type = existing.type || base.type;
|
|
499
528
|
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 });
|
|
500
529
|
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 });
|
|
501
|
-
merged.dependencies = Object.assign(Object.assign(Object.assign({}, base.dependencies), (existing.dependencies || {})), {
|
|
502
|
-
|
|
503
|
-
zod: '^3.23.8', 'reflect-metadata': '^0.2.2' });
|
|
504
|
-
merged.devDependencies = Object.assign(Object.assign(Object.assign({}, base.devDependencies), (existing.devDependencies || {})), {
|
|
505
|
-
// ensure pins
|
|
506
|
-
frontmcp: selfVersion, tsx: '^4.20.6', typescript: '^5.5.3' });
|
|
530
|
+
merged.dependencies = Object.assign(Object.assign(Object.assign({}, base.dependencies), (existing.dependencies || {})), { zod: '^3.23.8', 'reflect-metadata': '^0.2.2' });
|
|
531
|
+
merged.devDependencies = Object.assign(Object.assign(Object.assign({}, base.devDependencies), (existing.devDependencies || {})), { frontmcp: selfVersion, tsx: '^4.20.6', typescript: '^5.5.3' });
|
|
507
532
|
yield writeJSON(pkgPath, merged);
|
|
508
533
|
console.log(c('green', '✅ Updated package.json (ensured exact frontmcp and pinned versions)'));
|
|
509
534
|
});
|
|
@@ -553,9 +578,9 @@ import { z } from 'zod';
|
|
|
553
578
|
const AddTool = tool({
|
|
554
579
|
name: 'add',
|
|
555
580
|
description: 'Add two numbers',
|
|
556
|
-
inputSchema:
|
|
557
|
-
outputSchema:
|
|
558
|
-
})((input, _ctx) => {
|
|
581
|
+
inputSchema: { a: z.number(), b: z.number() },
|
|
582
|
+
outputSchema: { result: z.number() },
|
|
583
|
+
})(async (input, _ctx) => {
|
|
559
584
|
return { result: input.a + input.b };
|
|
560
585
|
});
|
|
561
586
|
|
|
@@ -585,7 +610,7 @@ function runCreate(projectArg) {
|
|
|
585
610
|
process.chdir(targetDir);
|
|
586
611
|
// 1) tsconfig
|
|
587
612
|
yield runInit(targetDir);
|
|
588
|
-
// 2) package.json (
|
|
613
|
+
// 2) package.json (pinned deps + exact CLI version)
|
|
589
614
|
const selfVersion = yield getSelfVersion();
|
|
590
615
|
yield upsertPackageJson(targetDir, pkgName, selfVersion);
|
|
591
616
|
// 3) files
|
|
@@ -595,7 +620,7 @@ function runCreate(projectArg) {
|
|
|
595
620
|
console.log('\nNext steps:');
|
|
596
621
|
console.log(` 1) cd ${folder}`);
|
|
597
622
|
console.log(' 2) npm install');
|
|
598
|
-
console.log(' 3) npm run dev ', c('gray', '#
|
|
623
|
+
console.log(' 3) npm run dev ', c('gray', '# tsx watcher + async tsc type-check'));
|
|
599
624
|
console.log(' 4) npm run inspect ', c('gray', '# launch MCP Inspector'));
|
|
600
625
|
console.log(' 5) npm run build ', c('gray', '# compile with tsc via frontmcp build'));
|
|
601
626
|
});
|
|
@@ -629,7 +654,7 @@ function main() {
|
|
|
629
654
|
yield runInspector();
|
|
630
655
|
break;
|
|
631
656
|
case 'create': {
|
|
632
|
-
const projectName = parsed._[1];
|
|
657
|
+
const projectName = parsed._[1];
|
|
633
658
|
yield runCreate(projectName);
|
|
634
659
|
break;
|
|
635
660
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "frontmcp",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.6",
|
|
4
4
|
"description": "FrontMCP command line interface",
|
|
5
5
|
"main": "dist/index.js",
|
|
6
6
|
"bin": {
|
|
@@ -12,10 +12,10 @@
|
|
|
12
12
|
"prepare": "npm run build"
|
|
13
13
|
},
|
|
14
14
|
"dependencies": {
|
|
15
|
-
"@frontmcp/sdk": "0.1.3",
|
|
16
|
-
"@frontmcp/core": "0.1.3",
|
|
17
|
-
"@frontmcp/plugins": "0.1.3",
|
|
18
|
-
"@frontmcp/adapters": "0.1.3",
|
|
15
|
+
"@frontmcp/sdk": "^0.1.3",
|
|
16
|
+
"@frontmcp/core": "^0.1.3",
|
|
17
|
+
"@frontmcp/plugins": "^0.1.3",
|
|
18
|
+
"@frontmcp/adapters": "^0.1.3",
|
|
19
19
|
"tsx": "^4.20.6",
|
|
20
20
|
"typescript": "^5.5.3"
|
|
21
21
|
},
|
package/src/cli.ts
CHANGED
|
@@ -7,7 +7,7 @@
|
|
|
7
7
|
import * as fs from 'fs';
|
|
8
8
|
import {promises as fsp} from 'fs';
|
|
9
9
|
import * as path from 'path';
|
|
10
|
-
import {spawn} from 'child_process';
|
|
10
|
+
import {spawn, ChildProcess} from 'child_process';
|
|
11
11
|
|
|
12
12
|
/* ----------------------------- Types & Helpers ---------------------------- */
|
|
13
13
|
|
|
@@ -42,7 +42,7 @@ ${c('bold', 'Usage')}
|
|
|
42
42
|
frontmcp <command> [options]
|
|
43
43
|
|
|
44
44
|
${c('bold', 'Commands')}
|
|
45
|
-
dev Start in development mode (tsx --watch <entry>)
|
|
45
|
+
dev Start in development mode (tsx --watch <entry> + async type-check)
|
|
46
46
|
build Compile entry with TypeScript (tsc)
|
|
47
47
|
init Create or fix a tsconfig.json suitable for FrontMCP
|
|
48
48
|
doctor Check Node/npm versions and tsconfig requirements
|
|
@@ -109,17 +109,23 @@ async function resolveEntry(cwd: string, explicit?: string): Promise<string> {
|
|
|
109
109
|
if (await fileExists(full)) return full;
|
|
110
110
|
throw new Error(`Entry override not found: ${explicit}`);
|
|
111
111
|
}
|
|
112
|
+
|
|
112
113
|
const pkgPath = path.join(cwd, 'package.json');
|
|
113
114
|
if (await fileExists(pkgPath)) {
|
|
114
115
|
const pkg = await readJSON<any>(pkgPath);
|
|
115
116
|
if (pkg && typeof pkg.main === 'string' && pkg.main.trim()) {
|
|
116
117
|
const mainCandidates = tryCandidates(path.resolve(cwd, pkg.main));
|
|
117
|
-
for (const p of mainCandidates)
|
|
118
|
+
for (const p of mainCandidates) {
|
|
119
|
+
if (await fileExists(p)) return p;
|
|
120
|
+
}
|
|
118
121
|
const asDir = path.resolve(cwd, pkg.main);
|
|
119
122
|
const idxCandidates = tryCandidates(path.join(asDir, 'index'));
|
|
120
|
-
for (const p of idxCandidates)
|
|
123
|
+
for (const p of idxCandidates) {
|
|
124
|
+
if (await fileExists(p)) return p;
|
|
125
|
+
}
|
|
121
126
|
}
|
|
122
127
|
}
|
|
128
|
+
|
|
123
129
|
const fallback = path.join(cwd, 'src', 'main.ts');
|
|
124
130
|
if (await fileExists(fallback)) return fallback;
|
|
125
131
|
|
|
@@ -177,7 +183,6 @@ function sanitizeForNpm(name: string): string {
|
|
|
177
183
|
/* ------------------------ Self-version detection -------------------------- */
|
|
178
184
|
|
|
179
185
|
async function getSelfVersion(): Promise<string> {
|
|
180
|
-
// Best-effort: find our own package.json near the executed bin.
|
|
181
186
|
const binPath = process.argv[1] || __filename;
|
|
182
187
|
const candidates = [
|
|
183
188
|
path.resolve(path.dirname(binPath), '../package.json'),
|
|
@@ -187,22 +192,53 @@ async function getSelfVersion(): Promise<string> {
|
|
|
187
192
|
const j = await readJSON<any>(p);
|
|
188
193
|
if (j?.version) return j.version;
|
|
189
194
|
}
|
|
190
|
-
// Fallback if not found; still satisfies the "has field" requirement.
|
|
191
195
|
return '0.0.0';
|
|
192
196
|
}
|
|
193
197
|
|
|
194
198
|
/* --------------------------------- Actions -------------------------------- */
|
|
195
199
|
|
|
200
|
+
function isTsLike(p: string): boolean {
|
|
201
|
+
return /\.tsx?$/i.test(p);
|
|
202
|
+
}
|
|
203
|
+
|
|
204
|
+
function killQuiet(proc?: ChildProcess) {
|
|
205
|
+
try { proc && proc.kill('SIGINT'); } catch {}
|
|
206
|
+
}
|
|
207
|
+
|
|
196
208
|
async function runDev(opts: ParsedArgs): Promise<void> {
|
|
197
209
|
const cwd = process.cwd();
|
|
198
210
|
const entry = await resolveEntry(cwd, opts.entry);
|
|
211
|
+
|
|
199
212
|
console.log(`${c('cyan', '[dev]')} using entry: ${path.relative(cwd, entry)}`);
|
|
213
|
+
console.log(`${c('gray', '[dev]')} starting ${c('bold', 'tsx --watch')} and ${c('bold', 'tsc --noEmit --watch')} (async type-checker)`);
|
|
200
214
|
console.log(`${c('gray', 'hint:')} press Ctrl+C to stop`);
|
|
201
|
-
await runCmd('npx', ['-y', 'tsx', '--watch', entry]);
|
|
202
|
-
}
|
|
203
215
|
|
|
204
|
-
|
|
205
|
-
|
|
216
|
+
// Start tsx watcher (app run)
|
|
217
|
+
const app = spawn('npx', ['-y', 'tsx', '--watch', entry], {stdio: 'inherit', shell: true});
|
|
218
|
+
// Start tsc in watch mode for async type-checking (non-blocking)
|
|
219
|
+
const checker = spawn('npx', ['-y', 'tsc', '--noEmit', '--pretty', '--watch'], {stdio: 'inherit', shell: true});
|
|
220
|
+
|
|
221
|
+
const cleanup = () => {
|
|
222
|
+
killQuiet(checker);
|
|
223
|
+
killQuiet(app);
|
|
224
|
+
};
|
|
225
|
+
|
|
226
|
+
process.on('SIGINT', () => {
|
|
227
|
+
cleanup();
|
|
228
|
+
process.exit(0);
|
|
229
|
+
});
|
|
230
|
+
|
|
231
|
+
await new Promise<void>((resolve, reject) => {
|
|
232
|
+
app.on('close', (_code) => {
|
|
233
|
+
// When app exits, stop checker too.
|
|
234
|
+
cleanup();
|
|
235
|
+
resolve();
|
|
236
|
+
});
|
|
237
|
+
app.on('error', (err) => {
|
|
238
|
+
cleanup();
|
|
239
|
+
reject(err);
|
|
240
|
+
});
|
|
241
|
+
});
|
|
206
242
|
}
|
|
207
243
|
|
|
208
244
|
async function runBuild(opts: ParsedArgs): Promise<void> {
|
|
@@ -439,12 +475,12 @@ async function upsertPackageJson(cwd: string, nameOverride: string | undefined,
|
|
|
439
475
|
npm: '>=10',
|
|
440
476
|
},
|
|
441
477
|
dependencies: {
|
|
442
|
-
'@frontmcp/sdk': '
|
|
478
|
+
'@frontmcp/sdk': '^0.1.3',
|
|
443
479
|
zod: '^3.23.8',
|
|
444
480
|
'reflect-metadata': '^0.2.2',
|
|
445
481
|
},
|
|
446
482
|
devDependencies: {
|
|
447
|
-
frontmcp: selfVersion, // exact version used by npx
|
|
483
|
+
frontmcp: selfVersion, // exact CLI version used by npx
|
|
448
484
|
tsx: '^4.20.6',
|
|
449
485
|
typescript: '^5.5.3',
|
|
450
486
|
},
|
|
@@ -452,7 +488,7 @@ async function upsertPackageJson(cwd: string, nameOverride: string | undefined,
|
|
|
452
488
|
|
|
453
489
|
if (!existing) {
|
|
454
490
|
await writeJSON(pkgPath, base);
|
|
455
|
-
console.log(c('green', '✅ Created package.json (pinned
|
|
491
|
+
console.log(c('green', '✅ Created package.json (pinned versions + exact frontmcp)'));
|
|
456
492
|
return;
|
|
457
493
|
}
|
|
458
494
|
|
|
@@ -480,7 +516,6 @@ async function upsertPackageJson(cwd: string, nameOverride: string | undefined,
|
|
|
480
516
|
merged.dependencies = {
|
|
481
517
|
...base.dependencies,
|
|
482
518
|
...(existing.dependencies || {}),
|
|
483
|
-
// ensure pins
|
|
484
519
|
zod: '^3.23.8',
|
|
485
520
|
'reflect-metadata': '^0.2.2',
|
|
486
521
|
};
|
|
@@ -488,7 +523,6 @@ async function upsertPackageJson(cwd: string, nameOverride: string | undefined,
|
|
|
488
523
|
merged.devDependencies = {
|
|
489
524
|
...base.devDependencies,
|
|
490
525
|
...(existing.devDependencies || {}),
|
|
491
|
-
// ensure pins
|
|
492
526
|
frontmcp: selfVersion,
|
|
493
527
|
tsx: '^4.20.6',
|
|
494
528
|
typescript: '^5.5.3',
|
|
@@ -544,9 +578,9 @@ import { z } from 'zod';
|
|
|
544
578
|
const AddTool = tool({
|
|
545
579
|
name: 'add',
|
|
546
580
|
description: 'Add two numbers',
|
|
547
|
-
inputSchema:
|
|
548
|
-
outputSchema:
|
|
549
|
-
})((input, _ctx) => {
|
|
581
|
+
inputSchema: { a: z.number(), b: z.number() },
|
|
582
|
+
outputSchema: { result: z.number() },
|
|
583
|
+
})(async (input, _ctx) => {
|
|
550
584
|
return { result: input.a + input.b };
|
|
551
585
|
});
|
|
552
586
|
|
|
@@ -580,7 +614,7 @@ async function runCreate(projectArg?: string): Promise<void> {
|
|
|
580
614
|
// 1) tsconfig
|
|
581
615
|
await runInit(targetDir);
|
|
582
616
|
|
|
583
|
-
// 2) package.json (
|
|
617
|
+
// 2) package.json (pinned deps + exact CLI version)
|
|
584
618
|
const selfVersion = await getSelfVersion();
|
|
585
619
|
await upsertPackageJson(targetDir, pkgName, selfVersion);
|
|
586
620
|
|
|
@@ -592,7 +626,7 @@ async function runCreate(projectArg?: string): Promise<void> {
|
|
|
592
626
|
console.log('\nNext steps:');
|
|
593
627
|
console.log(` 1) cd ${folder}`);
|
|
594
628
|
console.log(' 2) npm install');
|
|
595
|
-
console.log(' 3) npm run dev ', c('gray', '#
|
|
629
|
+
console.log(' 3) npm run dev ', c('gray', '# tsx watcher + async tsc type-check'));
|
|
596
630
|
console.log(' 4) npm run inspect ', c('gray', '# launch MCP Inspector'));
|
|
597
631
|
console.log(' 5) npm run build ', c('gray', '# compile with tsc via frontmcp build'));
|
|
598
632
|
}
|
|
@@ -628,7 +662,7 @@ async function main(): Promise<void> {
|
|
|
628
662
|
await runInspector();
|
|
629
663
|
break;
|
|
630
664
|
case 'create': {
|
|
631
|
-
const projectName = parsed._[1];
|
|
665
|
+
const projectName = parsed._[1];
|
|
632
666
|
await runCreate(projectName);
|
|
633
667
|
break;
|
|
634
668
|
}
|