@prefecthq/fastmcp-ts 0.0.5 → 0.1.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/entrypoint-runtime.cjs +87 -0
- package/dist/cli/entrypoint-runtime.cjs.map +1 -0
- package/dist/cli/index.cjs +85 -37
- package/dist/cli/index.cjs.map +1 -1
- package/dist/server.d.ts +7 -0
- package/dist/server.js +18 -7
- package/dist/server.js.map +1 -1
- package/package.json +1 -1
|
@@ -0,0 +1,87 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
"use strict";
|
|
3
|
+
|
|
4
|
+
// src/cli/entrypoint-runtime.ts
|
|
5
|
+
var import_node_url = require("url");
|
|
6
|
+
var AUTO_DETECT_NAMES = ["default", "mcp", "server", "app"];
|
|
7
|
+
function isFastMCPInstance(value) {
|
|
8
|
+
if (!value || typeof value !== "object") return false;
|
|
9
|
+
const obj = value;
|
|
10
|
+
return typeof obj["run"] === "function" && typeof obj["tool"] === "function" && typeof obj["resource"] === "function" && typeof obj["prompt"] === "function" && typeof obj["connect"] === "function";
|
|
11
|
+
}
|
|
12
|
+
function describe(value) {
|
|
13
|
+
if (value === null) return "null";
|
|
14
|
+
if (Array.isArray(value)) return "an array";
|
|
15
|
+
return `a ${typeof value}`;
|
|
16
|
+
}
|
|
17
|
+
function fail(message) {
|
|
18
|
+
console.error(`fastmcp: ${message}`);
|
|
19
|
+
process.exit(1);
|
|
20
|
+
}
|
|
21
|
+
async function resolveFactory(value, exportName, filePath) {
|
|
22
|
+
if (typeof value !== "function") return value;
|
|
23
|
+
try {
|
|
24
|
+
return await value();
|
|
25
|
+
} catch (err) {
|
|
26
|
+
fail(
|
|
27
|
+
`Failed to call entrypoint factory "${exportName}" in ${filePath}: ` + (err instanceof Error ? err.message : String(err))
|
|
28
|
+
);
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
async function main() {
|
|
32
|
+
const filePath = process.env["FASTMCP_ENTRYPOINT_FILE"];
|
|
33
|
+
if (!filePath) {
|
|
34
|
+
fail("internal error: FASTMCP_ENTRYPOINT_FILE was not set for the entrypoint bootstrap");
|
|
35
|
+
}
|
|
36
|
+
const explicitExport = process.env["FASTMCP_ENTRYPOINT_EXPORT"];
|
|
37
|
+
let mod;
|
|
38
|
+
try {
|
|
39
|
+
mod = await import((0, import_node_url.pathToFileURL)(filePath).href);
|
|
40
|
+
} catch (err) {
|
|
41
|
+
fail(
|
|
42
|
+
`Failed to load entrypoint file "${filePath}": ` + (err instanceof Error ? err.stack ?? err.message : String(err))
|
|
43
|
+
);
|
|
44
|
+
}
|
|
45
|
+
let resolved;
|
|
46
|
+
if (explicitExport) {
|
|
47
|
+
if (!(explicitExport in mod)) {
|
|
48
|
+
const available = Object.keys(mod).filter((k) => k !== "__esModule");
|
|
49
|
+
fail(
|
|
50
|
+
`Entrypoint export "${explicitExport}" not found in ${filePath}.` + (available.length > 0 ? ` Available exports: ${available.join(", ")}.` : " The file has no exports.")
|
|
51
|
+
);
|
|
52
|
+
}
|
|
53
|
+
const target = await resolveFactory(mod[explicitExport], explicitExport, filePath);
|
|
54
|
+
if (!isFastMCPInstance(target)) {
|
|
55
|
+
fail(
|
|
56
|
+
`Entrypoint export "${explicitExport}" in ${filePath} is not a FastMCP server (or a function that returns one). Got ${describe(target)}.`
|
|
57
|
+
);
|
|
58
|
+
}
|
|
59
|
+
resolved = target;
|
|
60
|
+
} else {
|
|
61
|
+
for (const name of AUTO_DETECT_NAMES) {
|
|
62
|
+
if (!(name in mod)) continue;
|
|
63
|
+
const candidate = mod[name];
|
|
64
|
+
if (isFastMCPInstance(candidate)) {
|
|
65
|
+
resolved = candidate;
|
|
66
|
+
break;
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
if (resolved === void 0) {
|
|
70
|
+
return;
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
if (resolved.isRunning) {
|
|
74
|
+
return;
|
|
75
|
+
}
|
|
76
|
+
await resolved.run();
|
|
77
|
+
if (resolved.address) {
|
|
78
|
+
const { host, port, path } = resolved.address;
|
|
79
|
+
process.stderr.write(`listening on http://${host}:${port}${path}
|
|
80
|
+
`);
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
main().catch((err) => {
|
|
84
|
+
console.error(err);
|
|
85
|
+
process.exit(1);
|
|
86
|
+
});
|
|
87
|
+
//# sourceMappingURL=entrypoint-runtime.cjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../src/cli/entrypoint-runtime.ts"],"sourcesContent":["/**\n * Entrypoint bootstrap — spawned by the CLI (`run`, `inspect`, `list`, `call`,\n * `dev inspector`) instead of the user's server file directly.\n *\n * This mirrors Python FastMCP's `FileSystemSource` entrypoint resolution\n * (`fastmcp/utilities/mcp_server_config/v1/sources/filesystem.py`): import the\n * user's file, resolve a named export (or a factory function that returns a\n * server), and start it. Keeping this in a spawned subprocess (rather than\n * importing the user's file in the CLI's own process) preserves two things the\n * existing CLI already relies on: `tsx` transpilation for TypeScript files, and\n * process isolation so a crashing user server doesn't take down the CLI.\n *\n * Contract (set by the parent CLI process via environment variables):\n * - FASTMCP_ENTRYPOINT_FILE: absolute path to the user's server file (required)\n * - FASTMCP_ENTRYPOINT_EXPORT: export name to resolve. Omitted when the user\n * didn't specify one, in which case a conventional name is auto-detected.\n *\n * Resolution order when FASTMCP_ENTRYPOINT_EXPORT is not set:\n * `default`, `mcp`, `server`, `app` — the first of these that is already a\n * FastMCP instance wins. Auto-detection deliberately does NOT call factory\n * functions (mirroring Python FastMCP's `_find_server_object`, which only\n * resolves factories for an explicit entrypoint) — invoking an arbitrary\n * exported function as a side effect of guessing a name would be surprising,\n * and a name match that isn't a FastMCP instance is skipped in favor of the\n * next candidate rather than committing to it. Factory functions are only\n * resolved when the export name is given explicitly (`file:export` or\n * `--export`).\n *\n * Backwards compatibility: if no explicit export was requested and none of the\n * conventional names resolve to a valid entrypoint, this script assumes the\n * file already started its own server via top-level side effects (the\n * historical fastmcp-ts contract, e.g. `server.run()` at module scope) and\n * exits without error. An explicit export request that can't be resolved is\n * always a hard error.\n */\n\nimport { pathToFileURL } from 'node:url'\n\nconst AUTO_DETECT_NAMES = ['default', 'mcp', 'server', 'app']\n\ninterface RunnableFastMCP {\n run(): Promise<void>\n isRunning: boolean\n address: { host: string; port: number; path: string } | null\n}\n\nfunction isFastMCPInstance(value: unknown): value is RunnableFastMCP {\n if (!value || typeof value !== 'object') return false\n const obj = value as Record<string, unknown>\n return (\n typeof obj['run'] === 'function' &&\n typeof obj['tool'] === 'function' &&\n typeof obj['resource'] === 'function' &&\n typeof obj['prompt'] === 'function' &&\n typeof obj['connect'] === 'function'\n )\n}\n\nfunction describe(value: unknown): string {\n if (value === null) return 'null'\n if (Array.isArray(value)) return 'an array'\n return `a ${typeof value}`\n}\n\nfunction fail(message: string): never {\n console.error(`fastmcp: ${message}`)\n process.exit(1)\n}\n\nasync function resolveFactory(\n value: unknown,\n exportName: string,\n filePath: string,\n): Promise<unknown> {\n if (typeof value !== 'function') return value\n try {\n return await (value as () => unknown)()\n } catch (err) {\n fail(\n `Failed to call entrypoint factory \"${exportName}\" in ${filePath}: ` +\n (err instanceof Error ? err.message : String(err)),\n )\n }\n}\n\nasync function main(): Promise<void> {\n const filePath = process.env['FASTMCP_ENTRYPOINT_FILE']\n if (!filePath) {\n fail('internal error: FASTMCP_ENTRYPOINT_FILE was not set for the entrypoint bootstrap')\n }\n\n const explicitExport = process.env['FASTMCP_ENTRYPOINT_EXPORT']\n\n let mod: Record<string, unknown>\n try {\n mod = (await import(pathToFileURL(filePath).href)) as Record<string, unknown>\n } catch (err) {\n fail(\n `Failed to load entrypoint file \"${filePath}\": ` +\n (err instanceof Error ? (err.stack ?? err.message) : String(err)),\n )\n }\n\n let resolved: RunnableFastMCP | undefined\n\n if (explicitExport) {\n if (!(explicitExport in mod)) {\n const available = Object.keys(mod).filter((k) => k !== '__esModule')\n fail(\n `Entrypoint export \"${explicitExport}\" not found in ${filePath}.` +\n (available.length > 0\n ? ` Available exports: ${available.join(', ')}.`\n : ' The file has no exports.'),\n )\n }\n const target = await resolveFactory(mod[explicitExport], explicitExport, filePath)\n if (!isFastMCPInstance(target)) {\n fail(\n `Entrypoint export \"${explicitExport}\" in ${filePath} is not a FastMCP server ` +\n `(or a function that returns one). Got ${describe(target)}.`,\n )\n }\n resolved = target\n } else {\n for (const name of AUTO_DETECT_NAMES) {\n if (!(name in mod)) continue\n const candidate = mod[name]\n // Only a direct FastMCP instance is auto-detected — a name match that\n // isn't one (including a function, which would require calling it) is\n // skipped in favor of the next conventional name rather than erroring\n // or invoking it speculatively.\n if (isFastMCPInstance(candidate)) {\n resolved = candidate\n break\n }\n }\n if (resolved === undefined) {\n // No conventional export resolved to a FastMCP instance. Assume this is\n // a legacy self-running file (it started its own server via top-level\n // side effects when imported above) and exit quietly.\n return\n }\n }\n\n if (resolved.isRunning) {\n // The file already started this server itself (e.g. a top-level\n // `server.run()` call) before we got a chance to. Don't start it twice.\n return\n }\n\n await resolved.run()\n\n // Mirrors the \"listening on <url>\" line the raw-SDK CLI test fixtures print\n // themselves — FastMCP's own run() doesn't emit a startup banner, but the\n // CLI's `run` command watches stderr for this text to detect a successful\n // HTTP start (see spawnServer()'s \"started\" detection in commands/run.ts).\n if (resolved.address) {\n const { host, port, path } = resolved.address\n process.stderr.write(`listening on http://${host}:${port}${path}\\n`)\n }\n}\n\nmain().catch((err) => {\n console.error(err)\n process.exit(1)\n})\n"],"mappings":";;;;AAoCA,sBAA8B;AAE9B,IAAM,oBAAoB,CAAC,WAAW,OAAO,UAAU,KAAK;AAQ5D,SAAS,kBAAkB,OAA0C;AACnE,MAAI,CAAC,SAAS,OAAO,UAAU,SAAU,QAAO;AAChD,QAAM,MAAM;AACZ,SACE,OAAO,IAAI,KAAK,MAAM,cACtB,OAAO,IAAI,MAAM,MAAM,cACvB,OAAO,IAAI,UAAU,MAAM,cAC3B,OAAO,IAAI,QAAQ,MAAM,cACzB,OAAO,IAAI,SAAS,MAAM;AAE9B;AAEA,SAAS,SAAS,OAAwB;AACxC,MAAI,UAAU,KAAM,QAAO;AAC3B,MAAI,MAAM,QAAQ,KAAK,EAAG,QAAO;AACjC,SAAO,KAAK,OAAO,KAAK;AAC1B;AAEA,SAAS,KAAK,SAAwB;AACpC,UAAQ,MAAM,YAAY,OAAO,EAAE;AACnC,UAAQ,KAAK,CAAC;AAChB;AAEA,eAAe,eACb,OACA,YACA,UACkB;AAClB,MAAI,OAAO,UAAU,WAAY,QAAO;AACxC,MAAI;AACF,WAAO,MAAO,MAAwB;AAAA,EACxC,SAAS,KAAK;AACZ;AAAA,MACE,sCAAsC,UAAU,QAAQ,QAAQ,QAC7D,eAAe,QAAQ,IAAI,UAAU,OAAO,GAAG;AAAA,IACpD;AAAA,EACF;AACF;AAEA,eAAe,OAAsB;AACnC,QAAM,WAAW,QAAQ,IAAI,yBAAyB;AACtD,MAAI,CAAC,UAAU;AACb,SAAK,kFAAkF;AAAA,EACzF;AAEA,QAAM,iBAAiB,QAAQ,IAAI,2BAA2B;AAE9D,MAAI;AACJ,MAAI;AACF,UAAO,MAAM,WAAO,+BAAc,QAAQ,EAAE;AAAA,EAC9C,SAAS,KAAK;AACZ;AAAA,MACE,mCAAmC,QAAQ,SACxC,eAAe,QAAS,IAAI,SAAS,IAAI,UAAW,OAAO,GAAG;AAAA,IACnE;AAAA,EACF;AAEA,MAAI;AAEJ,MAAI,gBAAgB;AAClB,QAAI,EAAE,kBAAkB,MAAM;AAC5B,YAAM,YAAY,OAAO,KAAK,GAAG,EAAE,OAAO,CAAC,MAAM,MAAM,YAAY;AACnE;AAAA,QACE,sBAAsB,cAAc,kBAAkB,QAAQ,OAC3D,UAAU,SAAS,IAChB,uBAAuB,UAAU,KAAK,IAAI,CAAC,MAC3C;AAAA,MACR;AAAA,IACF;AACA,UAAM,SAAS,MAAM,eAAe,IAAI,cAAc,GAAG,gBAAgB,QAAQ;AACjF,QAAI,CAAC,kBAAkB,MAAM,GAAG;AAC9B;AAAA,QACE,sBAAsB,cAAc,QAAQ,QAAQ,kEACT,SAAS,MAAM,CAAC;AAAA,MAC7D;AAAA,IACF;AACA,eAAW;AAAA,EACb,OAAO;AACL,eAAW,QAAQ,mBAAmB;AACpC,UAAI,EAAE,QAAQ,KAAM;AACpB,YAAM,YAAY,IAAI,IAAI;AAK1B,UAAI,kBAAkB,SAAS,GAAG;AAChC,mBAAW;AACX;AAAA,MACF;AAAA,IACF;AACA,QAAI,aAAa,QAAW;AAI1B;AAAA,IACF;AAAA,EACF;AAEA,MAAI,SAAS,WAAW;AAGtB;AAAA,EACF;AAEA,QAAM,SAAS,IAAI;AAMnB,MAAI,SAAS,SAAS;AACpB,UAAM,EAAE,MAAM,MAAM,KAAK,IAAI,SAAS;AACtC,YAAQ,OAAO,MAAM,uBAAuB,IAAI,IAAI,IAAI,GAAG,IAAI;AAAA,CAAI;AAAA,EACrE;AACF;AAEA,KAAK,EAAE,MAAM,CAAC,QAAQ;AACpB,UAAQ,MAAM,GAAG;AACjB,UAAQ,KAAK,CAAC;AAChB,CAAC;","names":[]}
|
package/dist/cli/index.cjs
CHANGED
|
@@ -1172,7 +1172,7 @@ var init_version = __esm({
|
|
|
1172
1172
|
async run({ args }) {
|
|
1173
1173
|
if (args.json) setJsonMode(true);
|
|
1174
1174
|
const data = {
|
|
1175
|
-
fastmcp: "0.0
|
|
1175
|
+
fastmcp: "0.1.0",
|
|
1176
1176
|
"mcp-sdk": "^1.29.0",
|
|
1177
1177
|
node: process.version,
|
|
1178
1178
|
platform: `${process.platform} ${process.arch}`
|
|
@@ -1188,16 +1188,24 @@ var init_version = __esm({
|
|
|
1188
1188
|
});
|
|
1189
1189
|
|
|
1190
1190
|
// src/cli/utils/file-spec.ts
|
|
1191
|
-
function parseFileSpec(spec) {
|
|
1191
|
+
function parseFileSpec(spec, exportOverride) {
|
|
1192
1192
|
const colonIdx = spec.lastIndexOf(":");
|
|
1193
1193
|
let filePart;
|
|
1194
1194
|
let exportName;
|
|
1195
|
+
let explicitExport;
|
|
1195
1196
|
if (colonIdx > 1) {
|
|
1196
1197
|
filePart = spec.slice(0, colonIdx);
|
|
1197
|
-
exportName = spec.slice(colonIdx + 1)
|
|
1198
|
+
exportName = spec.slice(colonIdx + 1);
|
|
1199
|
+
explicitExport = exportName.length > 0;
|
|
1200
|
+
if (!explicitExport) exportName = "default";
|
|
1198
1201
|
} else {
|
|
1199
1202
|
filePart = spec;
|
|
1200
1203
|
exportName = "default";
|
|
1204
|
+
explicitExport = false;
|
|
1205
|
+
}
|
|
1206
|
+
if (exportOverride) {
|
|
1207
|
+
exportName = exportOverride;
|
|
1208
|
+
explicitExport = true;
|
|
1201
1209
|
}
|
|
1202
1210
|
const filePath = (0, import_node_path.resolve)(process.cwd(), filePart);
|
|
1203
1211
|
if (!(0, import_node_fs.existsSync)(filePath)) {
|
|
@@ -1205,7 +1213,7 @@ function parseFileSpec(spec) {
|
|
|
1205
1213
|
}
|
|
1206
1214
|
const ext = (0, import_node_path.extname)(filePath).toLowerCase();
|
|
1207
1215
|
const isTypeScript = ext === ".ts" || ext === ".tsx" || ext === ".mts";
|
|
1208
|
-
return { filePath, exportName, isTypeScript };
|
|
1216
|
+
return { filePath, exportName, explicitExport, isTypeScript };
|
|
1209
1217
|
}
|
|
1210
1218
|
var import_node_fs, import_node_path;
|
|
1211
1219
|
var init_file_spec = __esm({
|
|
@@ -1216,6 +1224,27 @@ var init_file_spec = __esm({
|
|
|
1216
1224
|
}
|
|
1217
1225
|
});
|
|
1218
1226
|
|
|
1227
|
+
// src/cli/utils/entrypoint-bootstrap.ts
|
|
1228
|
+
function resolveEntrypointBootstrapPath() {
|
|
1229
|
+
return (0, import_node_path2.join)(__dirname, "entrypoint-runtime.cjs");
|
|
1230
|
+
}
|
|
1231
|
+
function buildEntrypointEnv(spec) {
|
|
1232
|
+
const env2 = {
|
|
1233
|
+
FASTMCP_ENTRYPOINT_FILE: spec.filePath
|
|
1234
|
+
};
|
|
1235
|
+
if (spec.explicitExport) {
|
|
1236
|
+
env2["FASTMCP_ENTRYPOINT_EXPORT"] = spec.exportName;
|
|
1237
|
+
}
|
|
1238
|
+
return env2;
|
|
1239
|
+
}
|
|
1240
|
+
var import_node_path2;
|
|
1241
|
+
var init_entrypoint_bootstrap = __esm({
|
|
1242
|
+
"src/cli/utils/entrypoint-bootstrap.ts"() {
|
|
1243
|
+
"use strict";
|
|
1244
|
+
import_node_path2 = require("path");
|
|
1245
|
+
}
|
|
1246
|
+
});
|
|
1247
|
+
|
|
1219
1248
|
// src/cli/utils/error.ts
|
|
1220
1249
|
function cliError(message, opts = {}) {
|
|
1221
1250
|
process.stderr.write(`${theme.error(symbols.failure)} ${theme.error(message)}
|
|
@@ -1274,12 +1303,12 @@ function readdirp(root, options = {}) {
|
|
|
1274
1303
|
options.root = root;
|
|
1275
1304
|
return new ReaddirpStream(options);
|
|
1276
1305
|
}
|
|
1277
|
-
var import_promises,
|
|
1306
|
+
var import_promises, import_node_path3, import_node_stream, EntryTypes, defaultOptions, RECURSIVE_ERROR_CODE, NORMAL_FLOW_ERRORS, ALL_TYPES, DIR_TYPES, FILE_TYPES, isNormalFlowError, wantBigintFsStats, emptyFn, normalizeFilter, ReaddirpStream;
|
|
1278
1307
|
var init_readdirp = __esm({
|
|
1279
1308
|
"node_modules/readdirp/index.js"() {
|
|
1280
1309
|
"use strict";
|
|
1281
1310
|
import_promises = require("fs/promises");
|
|
1282
|
-
|
|
1311
|
+
import_node_path3 = require("path");
|
|
1283
1312
|
import_node_stream = require("stream");
|
|
1284
1313
|
EntryTypes = {
|
|
1285
1314
|
FILE_TYPE: "files",
|
|
@@ -1369,7 +1398,7 @@ var init_readdirp = __esm({
|
|
|
1369
1398
|
this._wantsDir = type ? DIR_TYPES.has(type) : false;
|
|
1370
1399
|
this._wantsFile = type ? FILE_TYPES.has(type) : false;
|
|
1371
1400
|
this._wantsEverything = type === EntryTypes.EVERYTHING_TYPE;
|
|
1372
|
-
this._root = (0,
|
|
1401
|
+
this._root = (0, import_node_path3.resolve)(root);
|
|
1373
1402
|
this._isDirent = !opts.alwaysStat;
|
|
1374
1403
|
this._statsProp = this._isDirent ? "dirent" : "stats";
|
|
1375
1404
|
this._rdOptions = { encoding: "utf8", withFileTypes: this._isDirent };
|
|
@@ -1440,8 +1469,8 @@ var init_readdirp = __esm({
|
|
|
1440
1469
|
let entry;
|
|
1441
1470
|
const basename3 = this._isDirent ? dirent.name : dirent;
|
|
1442
1471
|
try {
|
|
1443
|
-
const fullPath = (0,
|
|
1444
|
-
entry = { path: (0,
|
|
1472
|
+
const fullPath = (0, import_node_path3.resolve)((0, import_node_path3.join)(path, basename3));
|
|
1473
|
+
entry = { path: (0, import_node_path3.relative)(this._root, fullPath), fullPath, basename: basename3 };
|
|
1445
1474
|
entry[this._statsProp] = this._isDirent ? dirent : await this._stat(fullPath);
|
|
1446
1475
|
} catch (err) {
|
|
1447
1476
|
this._onError(err);
|
|
@@ -1475,7 +1504,7 @@ var init_readdirp = __esm({
|
|
|
1475
1504
|
}
|
|
1476
1505
|
if (entryRealPathStats.isDirectory()) {
|
|
1477
1506
|
const len = entryRealPath.length;
|
|
1478
|
-
if (full.startsWith(entryRealPath) && full.substr(len, 1) ===
|
|
1507
|
+
if (full.startsWith(entryRealPath) && full.substr(len, 1) === import_node_path3.sep) {
|
|
1479
1508
|
const recursiveError = new Error(`Circular symlink detected: "${full}" points to "${entryRealPath}"`);
|
|
1480
1509
|
recursiveError.code = RECURSIVE_ERROR_CODE;
|
|
1481
1510
|
return this._onError(recursiveError);
|
|
@@ -3019,10 +3048,11 @@ var run_exports = {};
|
|
|
3019
3048
|
__export(run_exports, {
|
|
3020
3049
|
default: () => run_default
|
|
3021
3050
|
});
|
|
3022
|
-
function spawnServer(
|
|
3023
|
-
const
|
|
3051
|
+
function spawnServer(spec, env2) {
|
|
3052
|
+
const bootstrapPath = resolveEntrypointBootstrapPath();
|
|
3053
|
+
const [cmd, args] = spec.isTypeScript ? ["npx", ["tsx", bootstrapPath]] : ["node", [bootstrapPath]];
|
|
3024
3054
|
return (0, import_node_child_process.spawn)(cmd, args, {
|
|
3025
|
-
env: { ...process.env, ...env2 },
|
|
3055
|
+
env: { ...process.env, ...buildEntrypointEnv(spec), ...env2 },
|
|
3026
3056
|
stdio: ["inherit", "pipe", "pipe"]
|
|
3027
3057
|
});
|
|
3028
3058
|
}
|
|
@@ -3033,6 +3063,7 @@ var init_run = __esm({
|
|
|
3033
3063
|
init_dist();
|
|
3034
3064
|
import_node_child_process = require("child_process");
|
|
3035
3065
|
init_file_spec();
|
|
3066
|
+
init_entrypoint_bootstrap();
|
|
3036
3067
|
init_error();
|
|
3037
3068
|
init_theme();
|
|
3038
3069
|
init_symbols();
|
|
@@ -3041,7 +3072,9 @@ var init_run = __esm({
|
|
|
3041
3072
|
args: {
|
|
3042
3073
|
spec: { type: "positional", description: "File spec (e.g. server.ts or server.ts:app)", required: true },
|
|
3043
3074
|
transport: { type: "string", description: "Transport type (stdio|http|sse)", default: "stdio" },
|
|
3075
|
+
host: { type: "string", description: "HTTP host to bind to (for http transport)" },
|
|
3044
3076
|
port: { type: "string", description: "HTTP port (for http/sse transports)" },
|
|
3077
|
+
path: { type: "string", description: "HTTP path to serve on (for http transport)" },
|
|
3045
3078
|
reload: { type: "boolean", description: "Restart on file change", default: false }
|
|
3046
3079
|
},
|
|
3047
3080
|
async run({ args }) {
|
|
@@ -3054,8 +3087,10 @@ var init_run = __esm({
|
|
|
3054
3087
|
const transportEnv = {
|
|
3055
3088
|
MCP_TRANSPORT: args.transport
|
|
3056
3089
|
};
|
|
3090
|
+
if (args.host) transportEnv["MCP_HOST"] = args.host;
|
|
3057
3091
|
if (args.port) transportEnv["MCP_PORT"] = args.port;
|
|
3058
|
-
|
|
3092
|
+
if (args.path) transportEnv["MCP_PATH"] = args.path;
|
|
3093
|
+
let child = spawnServer(fileSpec, transportEnv);
|
|
3059
3094
|
let started = false;
|
|
3060
3095
|
function attachHandlers(proc) {
|
|
3061
3096
|
proc.stdout?.on("data", (chunk) => {
|
|
@@ -3091,7 +3126,7 @@ var init_run = __esm({
|
|
|
3091
3126
|
`);
|
|
3092
3127
|
child.kill();
|
|
3093
3128
|
started = false;
|
|
3094
|
-
child = spawnServer(fileSpec
|
|
3129
|
+
child = spawnServer(fileSpec, transportEnv);
|
|
3095
3130
|
attachHandlers(child);
|
|
3096
3131
|
});
|
|
3097
3132
|
}
|
|
@@ -29381,8 +29416,11 @@ async function connectClient(mode, auth2) {
|
|
|
29381
29416
|
return client2;
|
|
29382
29417
|
}
|
|
29383
29418
|
const { spec } = mode;
|
|
29384
|
-
const
|
|
29385
|
-
const
|
|
29419
|
+
const bootstrapPath = resolveEntrypointBootstrapPath();
|
|
29420
|
+
const [command, cmdArgs] = spec.isTypeScript ? ["npx", ["tsx", bootstrapPath]] : ["node", [bootstrapPath]];
|
|
29421
|
+
const transport = new StdioTransport(command, cmdArgs, {
|
|
29422
|
+
env: { ...stdioEnv, ...buildEntrypointEnv(spec) }
|
|
29423
|
+
});
|
|
29386
29424
|
const client = new Client2(transport, { auth: auth2 });
|
|
29387
29425
|
await client.connect();
|
|
29388
29426
|
return client;
|
|
@@ -29401,6 +29439,7 @@ var init_connect = __esm({
|
|
|
29401
29439
|
"use strict";
|
|
29402
29440
|
init_client3();
|
|
29403
29441
|
init_transports();
|
|
29442
|
+
init_entrypoint_bootstrap();
|
|
29404
29443
|
}
|
|
29405
29444
|
});
|
|
29406
29445
|
|
|
@@ -30087,7 +30126,7 @@ var init_dist6 = __esm({
|
|
|
30087
30126
|
function Ze() {
|
|
30088
30127
|
return import_node_process4.default.platform !== "win32" ? import_node_process4.default.env.TERM !== "linux" : !!import_node_process4.default.env.CI || !!import_node_process4.default.env.WT_SESSION || !!import_node_process4.default.env.TERMINUS_SUBLIME || import_node_process4.default.env.ConEmuTask === "{cmd::Cmder}" || import_node_process4.default.env.TERM_PROGRAM === "Terminus-Sublime" || import_node_process4.default.env.TERM_PROGRAM === "vscode" || import_node_process4.default.env.TERM === "xterm-256color" || import_node_process4.default.env.TERM === "alacritty" || import_node_process4.default.env.TERMINAL_EMULATOR === "JetBrains-JediTerm";
|
|
30089
30128
|
}
|
|
30090
|
-
var import_node_util3, import_node_process4, import_node_fs4,
|
|
30129
|
+
var import_node_util3, import_node_process4, import_node_fs4, import_node_path4, import_sisteransi2, ee, ae, w2, _e, oe, ue, F, le, d, E2, Ie, Ee, z3, H2, te, U, J, xe, se, ce, Ge, $e, de, Oe, he, pe, me, ge, V2, ot2, Ct, fe, Ve, je;
|
|
30091
30130
|
var init_dist7 = __esm({
|
|
30092
30131
|
"node_modules/@clack/prompts/dist/index.mjs"() {
|
|
30093
30132
|
"use strict";
|
|
@@ -30098,7 +30137,7 @@ var init_dist7 = __esm({
|
|
|
30098
30137
|
init_main();
|
|
30099
30138
|
init_dist5();
|
|
30100
30139
|
import_node_fs4 = require("fs");
|
|
30101
|
-
|
|
30140
|
+
import_node_path4 = require("path");
|
|
30102
30141
|
import_sisteransi2 = __toESM(require_src(), 1);
|
|
30103
30142
|
ee = Ze();
|
|
30104
30143
|
ae = () => process.env.CI === "true";
|
|
@@ -32121,6 +32160,7 @@ var init_inspect = __esm({
|
|
|
32121
32160
|
url: { type: "string", description: "Server URL" },
|
|
32122
32161
|
command: { type: "string", description: "stdio server command" },
|
|
32123
32162
|
file: { type: "string", description: "Server file (e.g. server.ts)" },
|
|
32163
|
+
export: { type: "string", description: "Named export to resolve (e.g. server); overrides file:export syntax" },
|
|
32124
32164
|
auth: { type: "string", description: "Bearer token" },
|
|
32125
32165
|
json: { type: "boolean", description: "Output JSON", default: false }
|
|
32126
32166
|
},
|
|
@@ -32133,7 +32173,7 @@ var init_inspect = __esm({
|
|
|
32133
32173
|
let fileSpec;
|
|
32134
32174
|
if (args.file) {
|
|
32135
32175
|
try {
|
|
32136
|
-
fileSpec = parseFileSpec(args.file);
|
|
32176
|
+
fileSpec = parseFileSpec(args.file, args.export);
|
|
32137
32177
|
} catch (err) {
|
|
32138
32178
|
cliError(formatError(err));
|
|
32139
32179
|
}
|
|
@@ -32234,6 +32274,7 @@ var init_list = __esm({
|
|
|
32234
32274
|
url: { type: "string", description: "Server URL" },
|
|
32235
32275
|
command: { type: "string", description: "stdio server command" },
|
|
32236
32276
|
file: { type: "string", description: "Server file (e.g. server.ts)" },
|
|
32277
|
+
export: { type: "string", description: "Named export to resolve (e.g. server); overrides file:export syntax" },
|
|
32237
32278
|
auth: { type: "string", description: "Bearer token" },
|
|
32238
32279
|
resources: { type: "boolean", description: "Also list resources", default: false },
|
|
32239
32280
|
prompts: { type: "boolean", description: "Also list prompts", default: false },
|
|
@@ -32249,7 +32290,7 @@ var init_list = __esm({
|
|
|
32249
32290
|
let fileSpec;
|
|
32250
32291
|
if (args.file) {
|
|
32251
32292
|
try {
|
|
32252
|
-
fileSpec = parseFileSpec(args.file);
|
|
32293
|
+
fileSpec = parseFileSpec(args.file, args.export);
|
|
32253
32294
|
} catch (err) {
|
|
32254
32295
|
cliError(formatError(err));
|
|
32255
32296
|
}
|
|
@@ -32524,6 +32565,7 @@ var init_call = __esm({
|
|
|
32524
32565
|
url: { type: "string", description: "Server URL" },
|
|
32525
32566
|
command: { type: "string", description: "stdio server command" },
|
|
32526
32567
|
file: { type: "string", description: "Server file (e.g. server.ts)" },
|
|
32568
|
+
export: { type: "string", description: "Named export to resolve (e.g. server); overrides file:export syntax" },
|
|
32527
32569
|
auth: { type: "string", description: "Bearer token" },
|
|
32528
32570
|
"input-json": { type: "string", description: "Raw JSON input instead of key=value args" },
|
|
32529
32571
|
json: { type: "boolean", description: "Output JSON", default: false }
|
|
@@ -32537,7 +32579,7 @@ var init_call = __esm({
|
|
|
32537
32579
|
let fileSpec;
|
|
32538
32580
|
if (args.file) {
|
|
32539
32581
|
try {
|
|
32540
|
-
fileSpec = parseFileSpec(args.file);
|
|
32582
|
+
fileSpec = parseFileSpec(args.file, args.export);
|
|
32541
32583
|
} catch (err) {
|
|
32542
32584
|
cliError(formatError(err));
|
|
32543
32585
|
}
|
|
@@ -32573,7 +32615,7 @@ var init_call = __esm({
|
|
|
32573
32615
|
{ hint: suggestion ? `Did you mean "${suggestion}"?` : void 0 }
|
|
32574
32616
|
);
|
|
32575
32617
|
}
|
|
32576
|
-
const flagValues = new Set([target, args.url, args.command, args.file, args.auth, args["input-json"]].filter(Boolean));
|
|
32618
|
+
const flagValues = new Set([target, args.url, args.command, args.file, args.export, args.auth, args["input-json"]].filter(Boolean));
|
|
32577
32619
|
const kvRaw = rawArgs.filter((a) => !a.startsWith("-") && !flagValues.has(a));
|
|
32578
32620
|
let input = args["input-json"] ? JSON.parse(args["input-json"]) : parseKvArgs(kvRaw);
|
|
32579
32621
|
if (matchedTool?.inputSchema) {
|
|
@@ -39939,11 +39981,11 @@ var require_dist2 = __commonJS({
|
|
|
39939
39981
|
function getConfigPaths() {
|
|
39940
39982
|
const home = (0, import_node_os3.homedir)();
|
|
39941
39983
|
const platform2 = process.platform;
|
|
39942
|
-
const claudeDesktop = platform2 === "darwin" ? (0,
|
|
39984
|
+
const claudeDesktop = platform2 === "darwin" ? (0, import_node_path5.join)(home, "Library", "Application Support", "Claude", "claude_desktop_config.json") : platform2 === "win32" ? (0, import_node_path5.join)(process.env["APPDATA"] ?? (0, import_node_path5.join)(home, "AppData", "Roaming"), "Claude", "claude_desktop_config.json") : (0, import_node_path5.join)(home, ".config", "Claude", "claude_desktop_config.json");
|
|
39943
39985
|
return {
|
|
39944
39986
|
"claude-code": {
|
|
39945
39987
|
name: "claude-code",
|
|
39946
|
-
path: (0,
|
|
39988
|
+
path: (0, import_node_path5.join)(home, ".claude.json"),
|
|
39947
39989
|
format: "json"
|
|
39948
39990
|
},
|
|
39949
39991
|
"claude-desktop": {
|
|
@@ -39953,22 +39995,22 @@ function getConfigPaths() {
|
|
|
39953
39995
|
},
|
|
39954
39996
|
cursor: {
|
|
39955
39997
|
name: "cursor",
|
|
39956
|
-
path: (0,
|
|
39998
|
+
path: (0, import_node_path5.join)(home, ".cursor", "mcp.json"),
|
|
39957
39999
|
format: "json"
|
|
39958
40000
|
},
|
|
39959
40001
|
gemini: {
|
|
39960
40002
|
name: "gemini",
|
|
39961
|
-
path: (0,
|
|
40003
|
+
path: (0, import_node_path5.join)(home, ".gemini", "settings.json"),
|
|
39962
40004
|
format: "json"
|
|
39963
40005
|
},
|
|
39964
40006
|
goose: {
|
|
39965
40007
|
name: "goose",
|
|
39966
|
-
path: (0,
|
|
40008
|
+
path: (0, import_node_path5.join)(home, ".config", "goose", "config.yaml"),
|
|
39967
40009
|
format: "yaml"
|
|
39968
40010
|
},
|
|
39969
40011
|
"mcp-json": {
|
|
39970
40012
|
name: "mcp-json",
|
|
39971
|
-
path: (0,
|
|
40013
|
+
path: (0, import_node_path5.resolve)(process.cwd(), "mcp.json"),
|
|
39972
40014
|
format: "json"
|
|
39973
40015
|
}
|
|
39974
40016
|
};
|
|
@@ -39982,12 +40024,12 @@ function writeConfig(path, data, format2) {
|
|
|
39982
40024
|
const content = format2 === "yaml" ? import_yaml.default.stringify(data) : JSON.stringify(data, null, 2) + "\n";
|
|
39983
40025
|
(0, import_node_fs5.writeFileSync)(path, content, "utf8");
|
|
39984
40026
|
}
|
|
39985
|
-
var import_node_os3,
|
|
40027
|
+
var import_node_os3, import_node_path5, import_node_fs5, import_yaml;
|
|
39986
40028
|
var init_config_paths = __esm({
|
|
39987
40029
|
"src/cli/utils/config-paths.ts"() {
|
|
39988
40030
|
"use strict";
|
|
39989
40031
|
import_node_os3 = require("os");
|
|
39990
|
-
|
|
40032
|
+
import_node_path5 = require("path");
|
|
39991
40033
|
import_node_fs5 = require("fs");
|
|
39992
40034
|
import_yaml = __toESM(require_dist2(), 1);
|
|
39993
40035
|
}
|
|
@@ -45169,7 +45211,7 @@ function parseEnvMap(raw) {
|
|
|
45169
45211
|
);
|
|
45170
45212
|
}
|
|
45171
45213
|
function ensureDir(path) {
|
|
45172
|
-
const dir = (0,
|
|
45214
|
+
const dir = (0, import_node_path6.dirname)(path);
|
|
45173
45215
|
if (!(0, import_node_fs6.existsSync)(dir)) {
|
|
45174
45216
|
(0, import_node_fs6.mkdirSync)(dir, { recursive: true });
|
|
45175
45217
|
}
|
|
@@ -45256,12 +45298,12 @@ async function installServer(opts) {
|
|
|
45256
45298
|
cliError(err instanceof Error ? err.message : String(err));
|
|
45257
45299
|
}
|
|
45258
45300
|
}
|
|
45259
|
-
var import_node_fs6,
|
|
45301
|
+
var import_node_fs6, import_node_path6;
|
|
45260
45302
|
var init_shared = __esm({
|
|
45261
45303
|
"src/cli/commands/install/shared.ts"() {
|
|
45262
45304
|
"use strict";
|
|
45263
45305
|
import_node_fs6 = require("fs");
|
|
45264
|
-
|
|
45306
|
+
import_node_path6 = require("path");
|
|
45265
45307
|
init_dist8();
|
|
45266
45308
|
init_dist7();
|
|
45267
45309
|
init_config_paths();
|
|
@@ -45550,6 +45592,7 @@ var init_inspector = __esm({
|
|
|
45550
45592
|
init_dist();
|
|
45551
45593
|
import_node_child_process2 = require("child_process");
|
|
45552
45594
|
init_file_spec();
|
|
45595
|
+
init_entrypoint_bootstrap();
|
|
45553
45596
|
init_error();
|
|
45554
45597
|
init_output();
|
|
45555
45598
|
init_theme();
|
|
@@ -45568,7 +45611,8 @@ var init_inspector = __esm({
|
|
|
45568
45611
|
} catch (err) {
|
|
45569
45612
|
cliError(formatError(err));
|
|
45570
45613
|
}
|
|
45571
|
-
const
|
|
45614
|
+
const bootstrapPath = resolveEntrypointBootstrapPath();
|
|
45615
|
+
const serverCmd = fileSpec.isTypeScript ? `npx tsx ${bootstrapPath}` : `node ${bootstrapPath}`;
|
|
45572
45616
|
await withSpinner(
|
|
45573
45617
|
"Starting inspector\u2026",
|
|
45574
45618
|
() => new Promise((resolve5) => setTimeout(resolve5, 300))
|
|
@@ -45576,7 +45620,11 @@ var init_inspector = __esm({
|
|
|
45576
45620
|
const inspectorProcess = (0, import_node_child_process2.spawn)(
|
|
45577
45621
|
"npx",
|
|
45578
45622
|
["@modelcontextprotocol/inspector", "--server", serverCmd],
|
|
45579
|
-
{
|
|
45623
|
+
{
|
|
45624
|
+
stdio: "inherit",
|
|
45625
|
+
shell: true,
|
|
45626
|
+
env: { ...process.env, MCP_TRANSPORT: "stdio", ...buildEntrypointEnv(fileSpec) }
|
|
45627
|
+
}
|
|
45580
45628
|
);
|
|
45581
45629
|
log.info(`Inspector running \u2014 ${theme.url(`http://localhost:${args.port}`)}`);
|
|
45582
45630
|
const { watch: watch2 } = await Promise.resolve().then(() => (init_chokidar(), chokidar_exports));
|
|
@@ -45623,7 +45671,7 @@ init_format();
|
|
|
45623
45671
|
var main = defineCommand({
|
|
45624
45672
|
meta: {
|
|
45625
45673
|
name: "fastmcp",
|
|
45626
|
-
version: "0.0
|
|
45674
|
+
version: "0.1.0",
|
|
45627
45675
|
description: "FastMCP CLI \u2014 build, run, and manage MCP servers"
|
|
45628
45676
|
},
|
|
45629
45677
|
args: {
|