@mcpcloud/cli 0.29.0 → 0.30.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +1 -1
- package/dist/index.js +294 -195
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -7972,6 +7972,8 @@ function registerServerGetCommand(servers) {
|
|
|
7972
7972
|
"upstream keys": s.upstreamApiKeyMode ?? "shared",
|
|
7973
7973
|
"client identity": s.forwardClientIdentity ? "forwarded" : "off",
|
|
7974
7974
|
"connections hub offer": s.offerConnectionsHub === false ? "off" : "shown",
|
|
7975
|
+
world: s.closedWorld ? "closed (openWorldHint: false)" : "open",
|
|
7976
|
+
"client refresh": s.refreshClientsOnToolChange ? "on tool change" : "off",
|
|
7975
7977
|
upstream: "mcp deployments get latest --server <server>",
|
|
7976
7978
|
"end-user access": s.endUserAccess ?? "disabled",
|
|
7977
7979
|
...s.endUserAccess === "enabled" && s.connectPageUrl ? { "connect page": s.connectPageUrl } : {},
|
|
@@ -9126,7 +9128,7 @@ function driftLine(change) {
|
|
|
9126
9128
|
|
|
9127
9129
|
// src/commands/servers-update.ts
|
|
9128
9130
|
function registerServerUpdateCommand(servers) {
|
|
9129
|
-
servers.command("update <server>").description("Update a server (name, description, tool surface, upstream key mode, runtime token TTL, client identity forwarding, connections hub offer, spec source URL)").option("--org <organizationId>", "Organization ID").option("--name <name>", "New display name").option("--description <text>", "New description").option("--discovery-mode <all|wrapper>", 'Tool surface: "all" registers every operation; "wrapper" registers searchTools/getToolDefinition/useTool INSTEAD (operations are called through useTool).').option("--code-mode <off|opt-in|default>", "Code Mode: expose codemode_execute so an agent can script several calls in one sandboxed run. Served by the edge, so it takes effect on the next deploy.").option("--upstream-api-key-mode <shared|perMember>", "Whose upstream credential the server uses: one shared key, or each member their own (Pro and above). perMember needs a protected access mode (privateOrg or unlisted) — refused while the active deployment is public.").option("--runtime-token-ttl <seconds|default>", 'Runtime token lifetime in seconds (60-86400; the default AND cap for minted tokens). Pass "default" to restore the 300s platform default.').option("--forward-client-identity <on|off>", 'Tell your upstream API which agent is calling: "on" adds X-MCP-Client-Name (e.g. "Claude Code") and the MCP client info headers to every upstream request, so your app can show the agent by name. The values are the client’s own claims — for display, never for authentication. Takes effect on the next deploy.').option("--connections-hub-offer <on|off>", "Whether your connect page shows one quiet line after a successful connect, pointing customers who use several MCPCloud apps to the connections hub (see and disconnect them all with a verified email). On by default; applies right away, no redeploy. It never asks customers to create an account.").option("--source-url <url>", "Read this server’s spec from a different URL from now on. The URL is fetched and parsed as the server’s source type first, and the report shows what a regenerate from it would change. Tools are not touched until you regenerate.").option("--dry-run", "With --source-url: fetch, parse and report without storing anything").addHelpText("after", [
|
|
9131
|
+
servers.command("update <server>").description("Update a server (name, description, tool surface, upstream key mode, runtime token TTL, client identity forwarding, connections hub offer, spec source URL)").option("--org <organizationId>", "Organization ID").option("--name <name>", "New display name").option("--description <text>", "New description").option("--discovery-mode <all|wrapper>", 'Tool surface: "all" registers every operation; "wrapper" registers searchTools/getToolDefinition/useTool INSTEAD (operations are called through useTool).').option("--code-mode <off|opt-in|default>", "Code Mode: expose codemode_execute so an agent can script several calls in one sandboxed run. Served by the edge, so it takes effect on the next deploy.").option("--upstream-api-key-mode <shared|perMember>", "Whose upstream credential the server uses: one shared key, or each member their own (Pro and above). perMember needs a protected access mode (privateOrg or unlisted) — refused while the active deployment is public.").option("--runtime-token-ttl <seconds|default>", 'Runtime token lifetime in seconds (60-86400; the default AND cap for minted tokens). Pass "default" to restore the 300s platform default.').option("--forward-client-identity <on|off>", 'Tell your upstream API which agent is calling: "on" adds X-MCP-Client-Name (e.g. "Claude Code") and the MCP client info headers to every upstream request, so your app can show the agent by name. The values are the client’s own claims — for display, never for authentication. Takes effect on the next deploy.').option("--connections-hub-offer <on|off>", "Whether your connect page shows one quiet line after a successful connect, pointing customers who use several MCPCloud apps to the connections hub (see and disconnect them all with a verified email). On by default; applies right away, no redeploy. It never asks customers to create an account.").option("--closed-world <on|off>", 'Whether your tools act only inside the signed-in user’s own account. "on" tells clients openWorldHint: false, so they can skip the "this reaches the outside world" caution; leave it off for tools that email, post or otherwise reach people or systems outside the account. A tool’s own setting (`mcp tools edit`, or x-mcp-annotations in the spec) still wins. Takes effect on the next regenerate + deploy.').option("--refresh-clients <on|off>", "After a deploy that changes your tools, make agents already connected load the new list: each connection gets a session tied to the current tools, and the old one ends when they change. Some agents report the ended session as one failed call instead of reconnecting by themselves. Off by default; takes effect on the next deploy.").option("--source-url <url>", "Read this server’s spec from a different URL from now on. The URL is fetched and parsed as the server’s source type first, and the report shows what a regenerate from it would change. Tools are not touched until you regenerate.").option("--dry-run", "With --source-url: fetch, parse and report without storing anything").addHelpText("after", [
|
|
9130
9132
|
"",
|
|
9131
9133
|
"Notes:",
|
|
9132
9134
|
" The OAuth provider is `mcp servers oauth set`; how customers sign in is",
|
|
@@ -9161,7 +9163,7 @@ async function runUpdate(serverRef, opts) {
|
|
|
9161
9163
|
throw new Error("--dry-run only previews --source-url. Run the other changes without --dry-run.");
|
|
9162
9164
|
}
|
|
9163
9165
|
if (!hasSettings && opts.sourceUrl === undefined) {
|
|
9164
|
-
throw new Error("Provide at least one of --name, --description, --discovery-mode, --code-mode, --upstream-api-key-mode, --runtime-token-ttl, --forward-client-identity, --connections-hub-offer, or --source-url.");
|
|
9166
|
+
throw new Error("Provide at least one of --name, --description, --discovery-mode, --code-mode, --upstream-api-key-mode, --runtime-token-ttl, --forward-client-identity, --connections-hub-offer, --closed-world, --refresh-clients, or --source-url.");
|
|
9165
9167
|
}
|
|
9166
9168
|
const orgId = await resolveOrgId(opts.org);
|
|
9167
9169
|
const serverId = await resolveServerId(serverRef, orgId);
|
|
@@ -9246,6 +9248,12 @@ function buildSettingsPatch(opts) {
|
|
|
9246
9248
|
"off"
|
|
9247
9249
|
]) === "on";
|
|
9248
9250
|
}
|
|
9251
|
+
if (opts.refreshClients !== undefined) {
|
|
9252
|
+
body["refreshClientsOnToolChange"] = validateChoice("refresh-clients", opts.refreshClients, ["on", "off"]) === "on";
|
|
9253
|
+
}
|
|
9254
|
+
if (opts.closedWorld !== undefined) {
|
|
9255
|
+
body["closedWorld"] = validateChoice("closed-world", opts.closedWorld, ["on", "off"]) === "on";
|
|
9256
|
+
}
|
|
9249
9257
|
if (opts.forwardClientIdentity !== undefined) {
|
|
9250
9258
|
body["forwardClientIdentity"] = validateChoice("forward-client-identity", opts.forwardClientIdentity, [
|
|
9251
9259
|
"on",
|
|
@@ -11270,8 +11278,8 @@ function renderBool(value) {
|
|
|
11270
11278
|
}
|
|
11271
11279
|
|
|
11272
11280
|
// src/commands/tools-edit.ts
|
|
11273
|
-
import { existsSync as
|
|
11274
|
-
import { join as
|
|
11281
|
+
import { existsSync as existsSync15 } from "node:fs";
|
|
11282
|
+
import { join as join12, relative as relative3 } from "node:path";
|
|
11275
11283
|
|
|
11276
11284
|
// src/lib/editor-shell.ts
|
|
11277
11285
|
import { spawn as spawn2 } from "node:child_process";
|
|
@@ -11365,15 +11373,106 @@ async function runEditor(args) {
|
|
|
11365
11373
|
return { ok: true, contents, command };
|
|
11366
11374
|
}
|
|
11367
11375
|
|
|
11376
|
+
// src/commands/tools-edit-declared.ts
|
|
11377
|
+
import { existsSync as existsSync14 } from "node:fs";
|
|
11378
|
+
import { join as join11 } from "node:path";
|
|
11379
|
+
var HINT_FLAGS = [
|
|
11380
|
+
{ flag: "destructive", option: "--destructive", key: "destructiveHint" },
|
|
11381
|
+
{ flag: "openWorld", option: "--open-world", key: "openWorldHint" },
|
|
11382
|
+
{ flag: "idempotent", option: "--idempotent", key: "idempotentHint" }
|
|
11383
|
+
];
|
|
11384
|
+
function hasDeclaredEditFlags(flags) {
|
|
11385
|
+
return flags.title !== undefined || HINT_FLAGS.some(({ flag }) => flags[flag] !== undefined);
|
|
11386
|
+
}
|
|
11387
|
+
function parseHintChoice(option, raw) {
|
|
11388
|
+
const value = raw.trim().toLowerCase();
|
|
11389
|
+
if (value === "on" || value === "true")
|
|
11390
|
+
return true;
|
|
11391
|
+
if (value === "off" || value === "false")
|
|
11392
|
+
return false;
|
|
11393
|
+
if (value === "default")
|
|
11394
|
+
return null;
|
|
11395
|
+
throw new Error(`${option} must be on, off, or default (got "${raw}").`);
|
|
11396
|
+
}
|
|
11397
|
+
function buildDeclaredPatch(flags) {
|
|
11398
|
+
const body = {};
|
|
11399
|
+
if (flags.title !== undefined) {
|
|
11400
|
+
const title = flags.title.replace(/\s+/g, " ").trim();
|
|
11401
|
+
body.title = title === "" || title.toLowerCase() === "default" ? null : title;
|
|
11402
|
+
}
|
|
11403
|
+
for (const { flag, option, key } of HINT_FLAGS) {
|
|
11404
|
+
const raw = flags[flag];
|
|
11405
|
+
if (raw === undefined)
|
|
11406
|
+
continue;
|
|
11407
|
+
body.annotationOverrides = {
|
|
11408
|
+
...body.annotationOverrides,
|
|
11409
|
+
[key]: parseHintChoice(option, raw)
|
|
11410
|
+
};
|
|
11411
|
+
}
|
|
11412
|
+
return body;
|
|
11413
|
+
}
|
|
11414
|
+
async function runDeclaredToolEdit(args) {
|
|
11415
|
+
const patch = buildDeclaredPatch(args.flags);
|
|
11416
|
+
const tools = await fetchAllPages("/api/v1/project/tools", { organizationId: args.ctx.organizationId, projectId: args.ctx.projectId }, "tools");
|
|
11417
|
+
const tool = tools.find((candidate) => candidate.serverId === args.ctx.serverId && candidate.name === args.toolName);
|
|
11418
|
+
if (!tool) {
|
|
11419
|
+
printError(`No tool named ${args.toolName} on this server.`);
|
|
11420
|
+
throw new CliExitError(1);
|
|
11421
|
+
}
|
|
11422
|
+
const result = await api.patch("/api/v1/server/tool", {
|
|
11423
|
+
organizationId: args.ctx.organizationId,
|
|
11424
|
+
projectId: args.ctx.projectId,
|
|
11425
|
+
serverId: args.ctx.serverId,
|
|
11426
|
+
toolId: tool.id,
|
|
11427
|
+
expectedUpdatedAt: tool.updatedAt,
|
|
11428
|
+
...patch
|
|
11429
|
+
});
|
|
11430
|
+
if (isJsonMode()) {
|
|
11431
|
+
printJson({
|
|
11432
|
+
ok: true,
|
|
11433
|
+
updatedAt: result.tool.updatedAt,
|
|
11434
|
+
changedFields: result.patchedFields,
|
|
11435
|
+
title: result.tool.title ?? null,
|
|
11436
|
+
annotationOverrides: result.tool.annotationOverrides ?? null
|
|
11437
|
+
});
|
|
11438
|
+
return;
|
|
11439
|
+
}
|
|
11440
|
+
printSuccess(`Saved ${c.bold(args.toolName)} ${c.dim(`(${result.patchedFields.join(", ")})`)}`);
|
|
11441
|
+
printInfo(c.dim(" → titles and hints are baked into the tool definitions: run `mcp servers regenerate` and deploy for clients to see them."));
|
|
11442
|
+
if (patch.annotationOverrides?.destructiveHint === true) {
|
|
11443
|
+
printInfo(c.dim(" → a destructive tool is called directly; Code Mode will not run it inside a script."));
|
|
11444
|
+
}
|
|
11445
|
+
const localFile = join11(serverToolsDir(devRoot(process.cwd()), args.ctx.serverId), `${args.toolName}.md`);
|
|
11446
|
+
if (existsSync14(localFile)) {
|
|
11447
|
+
printInfo(c.dim(` → run \`mcp tools pull ${args.toolName}\` before editing its .md again, so the next push is not refused as a conflict.`));
|
|
11448
|
+
}
|
|
11449
|
+
}
|
|
11450
|
+
|
|
11368
11451
|
// src/commands/tools-edit.ts
|
|
11369
11452
|
function registerToolsEditCommand(tools) {
|
|
11370
|
-
tools.command("edit <name>").description("Open a tool's local .md in $EDITOR; pushes your changes to the cloud on save. Requires `mcp dev` to have materialized tools (run `mcp tools pull` first if needed).").option("--org <organizationId>", "Organization ID (defaults to .mcpcloud/state.json)").option("--server <server>", "Server (id, name, or slug; defaults to .mcpcloud/state.json)").option("--editor <command>", "Editor binary to use (defaults to $VISUAL, then $EDITOR, then vi)").addHelpText("after", [
|
|
11453
|
+
tools.command("edit <name>").description("Open a tool's local .md in $EDITOR; pushes your changes to the cloud on save. Requires `mcp dev` to have materialized tools (run `mcp tools pull` first if needed). With --title / --destructive / --open-world / --idempotent, sets those directly instead — no editor, no local file needed.").option("--org <organizationId>", "Organization ID (defaults to .mcpcloud/state.json)").option("--server <server>", "Server (id, name, or slug; defaults to .mcpcloud/state.json)").option("--editor <command>", "Editor binary to use (defaults to $VISUAL, then $EDITOR, then vi)").option("--title <title|default>", `Human title clients show for the tool (max 80 characters), e.g. "Create a page". "default" hands it back to the spec's x-mcp-title, else the operation summary.`).option("--destructive <on|off|default>", 'Declare the tool destructive (destructiveHint) — for an overwrite or move the method alone under-describes. "on" makes clients confirm it and keeps it out of Code Mode scripts; "off" never relabels a DELETE as safe.').option("--open-world <on|off|default>", "Whether the tool reaches people or systems outside the user's own account (openWorldHint). Overrides the server's --closed-world setting for this tool.").option("--idempotent <on|off|default>", "Whether repeating the call with the same arguments has no further effect (idempotentHint).").addHelpText("after", [
|
|
11371
11454
|
"",
|
|
11372
11455
|
"Examples:",
|
|
11373
11456
|
" $ mcp tools edit get_user # opens .mcpcloud/tools/<server>/get_user.md",
|
|
11374
|
-
" $ mcp tools edit get_user --editor nano"
|
|
11457
|
+
" $ mcp tools edit get_user --editor nano",
|
|
11458
|
+
' $ mcp tools edit createpage --title "Create a page"',
|
|
11459
|
+
" $ mcp tools edit replacepagemarkdown --destructive on --open-world off",
|
|
11460
|
+
"",
|
|
11461
|
+
"Titles and hints are baked into the generated tool definitions: regenerate",
|
|
11462
|
+
"and deploy for clients to see them. A spec can declare the same per",
|
|
11463
|
+
"operation with x-mcp-title and x-mcp-annotations; values set here win."
|
|
11375
11464
|
].join(`
|
|
11376
11465
|
`)).action(runAction(async (name, opts) => {
|
|
11466
|
+
if (hasDeclaredEditFlags(opts)) {
|
|
11467
|
+
const ctx = await resolveToolsContext({
|
|
11468
|
+
orgOverride: opts.org,
|
|
11469
|
+
serverOverride: opts.server
|
|
11470
|
+
});
|
|
11471
|
+
if (!ctx)
|
|
11472
|
+
return;
|
|
11473
|
+
await runDeclaredToolEdit({ ctx, toolName: name, flags: opts });
|
|
11474
|
+
return;
|
|
11475
|
+
}
|
|
11377
11476
|
await runToolsEdit({
|
|
11378
11477
|
toolName: name,
|
|
11379
11478
|
orgOverride: opts.org,
|
|
@@ -11394,8 +11493,8 @@ async function runToolsEdit(args) {
|
|
|
11394
11493
|
if (!ctx)
|
|
11395
11494
|
return;
|
|
11396
11495
|
const cwd = process.cwd();
|
|
11397
|
-
const filePath =
|
|
11398
|
-
if (!
|
|
11496
|
+
const filePath = join12(serverToolsDir(devRoot(cwd), ctx.serverId), `${args.toolName}.md`);
|
|
11497
|
+
if (!existsSync15(filePath)) {
|
|
11399
11498
|
printError(`Tool file not found: ${relative3(cwd, filePath)}`);
|
|
11400
11499
|
printInfo(` ${c.dim("Run")} ${c.bold(`mcp tools pull ${args.toolName}`)} ${c.dim("first to materialize it, or check the name is spelled correctly.")}`);
|
|
11401
11500
|
throw new CliExitError(1);
|
|
@@ -12161,11 +12260,11 @@ async function runPullHandler(args) {
|
|
|
12161
12260
|
}
|
|
12162
12261
|
|
|
12163
12262
|
// src/commands/tools-rename.ts
|
|
12164
|
-
import { existsSync as
|
|
12263
|
+
import { existsSync as existsSync17 } from "node:fs";
|
|
12165
12264
|
import { relative as relative6 } from "node:path";
|
|
12166
12265
|
|
|
12167
12266
|
// src/commands/tools-rename-input.ts
|
|
12168
|
-
import { existsSync as
|
|
12267
|
+
import { existsSync as existsSync16, readFileSync as readFileSync18 } from "node:fs";
|
|
12169
12268
|
import { isAbsolute as isAbsolute3, resolve as resolve7 } from "node:path";
|
|
12170
12269
|
var MODES_HINT = "Pass exactly one of: <old> <new>, --from-operation-ids, or --map @renames.json.";
|
|
12171
12270
|
function resolveRenameSelection(args) {
|
|
@@ -12196,7 +12295,7 @@ function readRenameMap(ref, cwd) {
|
|
|
12196
12295
|
if (!raw)
|
|
12197
12296
|
throw new CliExitError(1, "--map needs a file path, e.g. --map @renames.json.");
|
|
12198
12297
|
const path = isAbsolute3(raw) ? raw : resolve7(cwd, raw);
|
|
12199
|
-
if (!
|
|
12298
|
+
if (!existsSync16(path))
|
|
12200
12299
|
throw new CliExitError(1, `--map file not found: ${path}`);
|
|
12201
12300
|
let parsed;
|
|
12202
12301
|
try {
|
|
@@ -12392,7 +12491,7 @@ async function runToolsRename(oldName, newName, opts) {
|
|
|
12392
12491
|
printRenameReport(res, {
|
|
12393
12492
|
serverId: ctx.serverId,
|
|
12394
12493
|
fromOperationIds: "fromOperationIds" in selection,
|
|
12395
|
-
localToolsDir:
|
|
12494
|
+
localToolsDir: existsSync17(localDir) ? relative6(cwd, localDir) || "." : null
|
|
12396
12495
|
});
|
|
12397
12496
|
}
|
|
12398
12497
|
function selectionBody(selection) {
|
|
@@ -12548,7 +12647,7 @@ async function runResetHandler(args) {
|
|
|
12548
12647
|
}
|
|
12549
12648
|
|
|
12550
12649
|
// src/commands/tools-show.ts
|
|
12551
|
-
import { existsSync as
|
|
12650
|
+
import { existsSync as existsSync18 } from "node:fs";
|
|
12552
12651
|
function registerToolsShowCommand(tools) {
|
|
12553
12652
|
tools.command("show <name>").description("Show a tool's full applied metadata (and any pending AI suggestion).").option("--org <organizationId>", "Organization ID (defaults to .mcpcloud/state.json)").option("--server <server>", "Server (id, name, or slug; defaults to .mcpcloud/state.json)").action(runAction(async (name, opts) => {
|
|
12554
12653
|
await runToolsShow({
|
|
@@ -12576,7 +12675,7 @@ async function runToolsShow(args) {
|
|
|
12576
12675
|
throw new CliExitError(1);
|
|
12577
12676
|
}
|
|
12578
12677
|
const devRootDir = devRoot(process.cwd());
|
|
12579
|
-
const inDevTree =
|
|
12678
|
+
const inDevTree = existsSync18(devRootDir);
|
|
12580
12679
|
const [detailed, handlerResult] = await Promise.all([
|
|
12581
12680
|
fetchEnrichedToolDetail({
|
|
12582
12681
|
organizationId: ctx.organizationId,
|
|
@@ -13812,7 +13911,7 @@ function registerSkillInstallCommand(skills) {
|
|
|
13812
13911
|
|
|
13813
13912
|
// src/commands/skills-pull.ts
|
|
13814
13913
|
import { mkdirSync as mkdirSync8, writeFileSync as writeFileSync7 } from "node:fs";
|
|
13815
|
-
import { dirname as dirname6, isAbsolute as isAbsolute4, join as
|
|
13914
|
+
import { dirname as dirname6, isAbsolute as isAbsolute4, join as join13, resolve as resolve8 } from "node:path";
|
|
13816
13915
|
function formatBytes2(bytes) {
|
|
13817
13916
|
if (bytes < 1024)
|
|
13818
13917
|
return `${bytes} B`;
|
|
@@ -13843,7 +13942,7 @@ function registerSkillPullCommand(skills) {
|
|
|
13843
13942
|
const dir = resolve8(opts.output ?? `./${result.skill.slug}`);
|
|
13844
13943
|
for (const file of result.files) {
|
|
13845
13944
|
assertSafeRelativePath2(file.path);
|
|
13846
|
-
const full =
|
|
13945
|
+
const full = join13(dir, file.path);
|
|
13847
13946
|
mkdirSync8(dirname6(full), { recursive: true });
|
|
13848
13947
|
writeFileSync7(full, file.content);
|
|
13849
13948
|
}
|
|
@@ -13861,12 +13960,12 @@ function registerSkillPullCommand(skills) {
|
|
|
13861
13960
|
const missing = result.dependencies.filter((entry) => !entry.installed);
|
|
13862
13961
|
if (result.dependencies.length === 0) {
|
|
13863
13962
|
printKeyValue({
|
|
13864
|
-
Next: `Copy ${
|
|
13963
|
+
Next: `Copy ${join13(dir, "SKILL.md")} into the skills directory your agent reads.`
|
|
13865
13964
|
});
|
|
13866
13965
|
return;
|
|
13867
13966
|
}
|
|
13868
13967
|
printKeyValue({
|
|
13869
|
-
Next: `Copy ${
|
|
13968
|
+
Next: `Copy ${join13(dir, "SKILL.md")} into the skills directory your agent reads.`,
|
|
13870
13969
|
Servers: result.dependencies.map((entry) => `${entry.name}${entry.installed ? "" : " (not installed)"}`).join(", ")
|
|
13871
13970
|
});
|
|
13872
13971
|
if (missing.length > 0) {
|
|
@@ -14298,18 +14397,18 @@ function registerSkillCommands(program) {
|
|
|
14298
14397
|
}
|
|
14299
14398
|
|
|
14300
14399
|
// src/lib/dev/prepare.ts
|
|
14301
|
-
import { existsSync as
|
|
14302
|
-
import { join as
|
|
14400
|
+
import { existsSync as existsSync25, readFileSync as readFileSync24, writeFileSync as writeFileSync12 } from "node:fs";
|
|
14401
|
+
import { join as join20, relative as relative8, resolve as resolve9 } from "node:path";
|
|
14303
14402
|
|
|
14304
14403
|
// src/lib/dev/bundle-sync.ts
|
|
14305
14404
|
import {
|
|
14306
|
-
existsSync as
|
|
14405
|
+
existsSync as existsSync19,
|
|
14307
14406
|
mkdirSync as mkdirSync9,
|
|
14308
14407
|
readFileSync as readFileSync21,
|
|
14309
14408
|
rmSync as rmSync2,
|
|
14310
14409
|
writeFileSync as writeFileSync8
|
|
14311
14410
|
} from "node:fs";
|
|
14312
|
-
import { dirname as dirname7, join as
|
|
14411
|
+
import { dirname as dirname7, join as join14 } from "node:path";
|
|
14313
14412
|
async function resolveServerProject(args) {
|
|
14314
14413
|
const data = await api.get("/api/v1/server", {
|
|
14315
14414
|
organizationId: args.organizationId,
|
|
@@ -14370,7 +14469,7 @@ async function fetchBundle(args) {
|
|
|
14370
14469
|
return parsed;
|
|
14371
14470
|
}
|
|
14372
14471
|
function materializeBundle(destDir, bundle, options = {}) {
|
|
14373
|
-
if (!
|
|
14472
|
+
if (!existsSync19(destDir)) {
|
|
14374
14473
|
mkdirSync9(destDir, { recursive: true });
|
|
14375
14474
|
}
|
|
14376
14475
|
const preserve = options.preservePaths;
|
|
@@ -14386,7 +14485,7 @@ function materializeBundle(destDir, bundle, options = {}) {
|
|
|
14386
14485
|
preservedCount += 1;
|
|
14387
14486
|
continue;
|
|
14388
14487
|
}
|
|
14389
|
-
const target =
|
|
14488
|
+
const target = join14(destDir, safePath);
|
|
14390
14489
|
mkdirSync9(dirname7(target), { recursive: true });
|
|
14391
14490
|
writeFileSync8(target, file.content, "utf-8");
|
|
14392
14491
|
writtenCount += 1;
|
|
@@ -14416,7 +14515,7 @@ function pruneStaleFiles(rootDir, currentDir, kept) {
|
|
|
14416
14515
|
const { relative } = __require("node:path");
|
|
14417
14516
|
let removed = 0;
|
|
14418
14517
|
for (const entry of readdirSync(currentDir)) {
|
|
14419
|
-
const abs =
|
|
14518
|
+
const abs = join14(currentDir, entry);
|
|
14420
14519
|
const stat = statSync(abs);
|
|
14421
14520
|
if (stat.isDirectory()) {
|
|
14422
14521
|
removed += pruneStaleFiles(rootDir, abs, kept);
|
|
@@ -14440,12 +14539,12 @@ function pruneStaleFiles(rootDir, currentDir, kept) {
|
|
|
14440
14539
|
// src/lib/dev/git-clone.ts
|
|
14441
14540
|
import { spawnSync } from "node:child_process";
|
|
14442
14541
|
import {
|
|
14443
|
-
existsSync as
|
|
14542
|
+
existsSync as existsSync20,
|
|
14444
14543
|
mkdirSync as mkdirSync10,
|
|
14445
14544
|
readFileSync as readFileSync22,
|
|
14446
14545
|
writeFileSync as writeFileSync9
|
|
14447
14546
|
} from "node:fs";
|
|
14448
|
-
import { dirname as dirname8, join as
|
|
14547
|
+
import { dirname as dirname8, join as join15 } from "node:path";
|
|
14449
14548
|
|
|
14450
14549
|
class GitNotAvailableError extends Error {
|
|
14451
14550
|
constructor() {
|
|
@@ -14536,12 +14635,12 @@ function isGitAvailable() {
|
|
|
14536
14635
|
}
|
|
14537
14636
|
}
|
|
14538
14637
|
function applyLocalExcludes(repoDir) {
|
|
14539
|
-
const excludePath =
|
|
14540
|
-
const existing =
|
|
14638
|
+
const excludePath = join15(repoDir, ".git", "info", "exclude");
|
|
14639
|
+
const existing = existsSync20(excludePath) ? readFileSync22(excludePath, "utf-8") : "";
|
|
14541
14640
|
const next = mergeLocalExcludes(existing);
|
|
14542
14641
|
if (next === null)
|
|
14543
14642
|
return;
|
|
14544
|
-
if (!
|
|
14643
|
+
if (!existsSync20(dirname8(excludePath))) {
|
|
14545
14644
|
mkdirSync10(dirname8(excludePath), { recursive: true });
|
|
14546
14645
|
}
|
|
14547
14646
|
writeFileSync9(excludePath, next, "utf-8");
|
|
@@ -14550,7 +14649,7 @@ function ensureClone(opts) {
|
|
|
14550
14649
|
if (!isGitAvailable()) {
|
|
14551
14650
|
throw new GitNotAvailableError;
|
|
14552
14651
|
}
|
|
14553
|
-
if (
|
|
14652
|
+
if (existsSync20(join15(opts.repoDir, ".git"))) {
|
|
14554
14653
|
opts.onStep?.("Refreshing existing clone (git fetch)…");
|
|
14555
14654
|
runGit(gitFetchArgs(opts.branch), opts.repoDir);
|
|
14556
14655
|
applyLocalExcludes(opts.repoDir);
|
|
@@ -14566,12 +14665,12 @@ function ensureClone(opts) {
|
|
|
14566
14665
|
}
|
|
14567
14666
|
|
|
14568
14667
|
// src/lib/dev/host-runtime.ts
|
|
14569
|
-
import { existsSync as
|
|
14570
|
-
import { dirname as dirname9, join as
|
|
14668
|
+
import { existsSync as existsSync22, mkdirSync as mkdirSync12, writeFileSync as writeFileSync11 } from "node:fs";
|
|
14669
|
+
import { dirname as dirname9, join as join17 } from "node:path";
|
|
14571
14670
|
|
|
14572
14671
|
// src/lib/dev/inspector-module.ts
|
|
14573
|
-
import { existsSync as
|
|
14574
|
-
import { join as
|
|
14672
|
+
import { existsSync as existsSync21, mkdirSync as mkdirSync11, writeFileSync as writeFileSync10 } from "node:fs";
|
|
14673
|
+
import { join as join16 } from "node:path";
|
|
14575
14674
|
|
|
14576
14675
|
// src/lib/dev/inspector-assets.ts
|
|
14577
14676
|
var INSPECTOR_HTML = `<!doctype html>
|
|
@@ -29719,9 +29818,9 @@ function buildInspectorModule() {
|
|
|
29719
29818
|
`);
|
|
29720
29819
|
}
|
|
29721
29820
|
function writeInspectorModule(serverDir) {
|
|
29722
|
-
if (!
|
|
29821
|
+
if (!existsSync21(serverDir))
|
|
29723
29822
|
mkdirSync11(serverDir, { recursive: true });
|
|
29724
|
-
const target =
|
|
29823
|
+
const target = join16(serverDir, INSPECTOR_FILE_NAME);
|
|
29725
29824
|
writeFileSync10(target, buildInspectorModule(), "utf-8");
|
|
29726
29825
|
return target;
|
|
29727
29826
|
}
|
|
@@ -29907,9 +30006,9 @@ function buildHostScript(options) {
|
|
|
29907
30006
|
`);
|
|
29908
30007
|
}
|
|
29909
30008
|
function writeHostScript(serverDir, options) {
|
|
29910
|
-
if (!
|
|
30009
|
+
if (!existsSync22(serverDir))
|
|
29911
30010
|
mkdirSync12(serverDir, { recursive: true });
|
|
29912
|
-
const target =
|
|
30011
|
+
const target = join17(serverDir, HOST_FILE_NAME);
|
|
29913
30012
|
mkdirSync12(dirname9(target), { recursive: true });
|
|
29914
30013
|
writeFileSync11(target, buildHostScript(options), "utf-8");
|
|
29915
30014
|
if (options.inspector) {
|
|
@@ -29921,38 +30020,38 @@ function writeHostScript(serverDir, options) {
|
|
|
29921
30020
|
// src/lib/dev/inspector-store.ts
|
|
29922
30021
|
import {
|
|
29923
30022
|
appendFileSync as appendFileSync2,
|
|
29924
|
-
existsSync as
|
|
30023
|
+
existsSync as existsSync23,
|
|
29925
30024
|
mkdirSync as mkdirSync13,
|
|
29926
30025
|
readFileSync as readFileSync23,
|
|
29927
30026
|
readdirSync as readdirSync2,
|
|
29928
30027
|
renameSync,
|
|
29929
30028
|
statSync as statSync2
|
|
29930
30029
|
} from "node:fs";
|
|
29931
|
-
import { join as
|
|
30030
|
+
import { join as join18 } from "node:path";
|
|
29932
30031
|
var INSPECTOR_DIRNAME = "inspector";
|
|
29933
30032
|
var ACTIVE_FILE = "calls.ndjson";
|
|
29934
30033
|
var ROTATED_PREFIX = "calls.";
|
|
29935
30034
|
var ROTATED_SUFFIX = ".ndjson";
|
|
29936
30035
|
var ROTATION_LIMIT_BYTES = 50 * 1024 * 1024;
|
|
29937
30036
|
function inspectorDir(cwd) {
|
|
29938
|
-
return
|
|
30037
|
+
return join18(devRoot(cwd), INSPECTOR_DIRNAME);
|
|
29939
30038
|
}
|
|
29940
30039
|
function ensureInspectorDir(dir) {
|
|
29941
|
-
if (!
|
|
30040
|
+
if (!existsSync23(dir))
|
|
29942
30041
|
mkdirSync13(dir, { recursive: true });
|
|
29943
30042
|
}
|
|
29944
30043
|
function activeFilePath(dir) {
|
|
29945
|
-
return
|
|
30044
|
+
return join18(dir, ACTIVE_FILE);
|
|
29946
30045
|
}
|
|
29947
30046
|
function isRotatedName(name) {
|
|
29948
30047
|
return name !== ACTIVE_FILE && name.startsWith(ROTATED_PREFIX) && name.endsWith(ROTATED_SUFFIX);
|
|
29949
30048
|
}
|
|
29950
30049
|
function listRotatedFiles(dir) {
|
|
29951
|
-
if (!
|
|
30050
|
+
if (!existsSync23(dir))
|
|
29952
30051
|
return [];
|
|
29953
30052
|
const rotated = readdirSync2(dir).filter(isRotatedName);
|
|
29954
30053
|
rotated.sort();
|
|
29955
|
-
return rotated.map((n) =>
|
|
30054
|
+
return rotated.map((n) => join18(dir, n));
|
|
29956
30055
|
}
|
|
29957
30056
|
function parseLines(text) {
|
|
29958
30057
|
if (!text)
|
|
@@ -29969,11 +30068,11 @@ function parseLines(text) {
|
|
|
29969
30068
|
return out;
|
|
29970
30069
|
}
|
|
29971
30070
|
function readAll(dir) {
|
|
29972
|
-
if (!
|
|
30071
|
+
if (!existsSync23(dir))
|
|
29973
30072
|
return [];
|
|
29974
30073
|
const out = [];
|
|
29975
30074
|
for (const path of [...listRotatedFiles(dir), activeFilePath(dir)]) {
|
|
29976
|
-
if (!
|
|
30075
|
+
if (!existsSync23(path))
|
|
29977
30076
|
continue;
|
|
29978
30077
|
out.push(...parseLines(readFileSync23(path, "utf-8")));
|
|
29979
30078
|
}
|
|
@@ -30025,8 +30124,8 @@ function parseDuration(input) {
|
|
|
30025
30124
|
|
|
30026
30125
|
// src/lib/dev/local-runtime.ts
|
|
30027
30126
|
import { spawn as spawn4 } from "node:child_process";
|
|
30028
|
-
import { existsSync as
|
|
30029
|
-
import { join as
|
|
30127
|
+
import { existsSync as existsSync24 } from "node:fs";
|
|
30128
|
+
import { join as join19 } from "node:path";
|
|
30030
30129
|
function detectRuntime(preferred = "auto") {
|
|
30031
30130
|
if (preferred === "bun" || preferred === "node")
|
|
30032
30131
|
return preferred;
|
|
@@ -30037,7 +30136,7 @@ function detectRuntime(preferred = "auto") {
|
|
|
30037
30136
|
return "node";
|
|
30038
30137
|
}
|
|
30039
30138
|
function startRuntime(options) {
|
|
30040
|
-
if (!
|
|
30139
|
+
if (!existsSync24(options.hostScriptPath)) {
|
|
30041
30140
|
throw new Error(`Host script not found: ${options.hostScriptPath}`);
|
|
30042
30141
|
}
|
|
30043
30142
|
const runtime = detectRuntime(options.runtime);
|
|
@@ -30078,11 +30177,11 @@ function startRuntime(options) {
|
|
|
30078
30177
|
};
|
|
30079
30178
|
}
|
|
30080
30179
|
async function installDependencies(options) {
|
|
30081
|
-
const pkgPath =
|
|
30082
|
-
if (!
|
|
30180
|
+
const pkgPath = join19(options.serverDir, "package.json");
|
|
30181
|
+
if (!existsSync24(pkgPath))
|
|
30083
30182
|
return { ran: false, exitCode: null };
|
|
30084
|
-
const nodeModules =
|
|
30085
|
-
if (options.skipIfPresent !== false &&
|
|
30183
|
+
const nodeModules = join19(options.serverDir, "node_modules");
|
|
30184
|
+
if (options.skipIfPresent !== false && existsSync24(nodeModules)) {
|
|
30086
30185
|
return { ran: false, exitCode: 0 };
|
|
30087
30186
|
}
|
|
30088
30187
|
options.onStep?.("Installing dependencies (bun install)…");
|
|
@@ -30121,14 +30220,14 @@ function missingEnvBindingNames(envExample, envJson) {
|
|
|
30121
30220
|
return names;
|
|
30122
30221
|
}
|
|
30123
30222
|
function printEnvBindingHint(dest, envPath, cwd) {
|
|
30124
|
-
const examplePath =
|
|
30125
|
-
if (!
|
|
30223
|
+
const examplePath = join20(dest, ".env.example");
|
|
30224
|
+
if (!existsSync25(examplePath))
|
|
30126
30225
|
return;
|
|
30127
30226
|
let example = "";
|
|
30128
30227
|
let envJson = "{}";
|
|
30129
30228
|
try {
|
|
30130
30229
|
example = readFileSync24(examplePath, "utf-8");
|
|
30131
|
-
if (
|
|
30230
|
+
if (existsSync25(envPath))
|
|
30132
30231
|
envJson = readFileSync24(envPath, "utf-8");
|
|
30133
30232
|
} catch {
|
|
30134
30233
|
return;
|
|
@@ -30165,7 +30264,7 @@ async function prepareDev(opts) {
|
|
|
30165
30264
|
const registered = readConfig().gitRepoDirs?.[opts.serverId];
|
|
30166
30265
|
const chosen = opts.repoDirOverride ? resolve9(cwd, opts.repoDirOverride) : registered;
|
|
30167
30266
|
repoDir = chosen ?? gitCloneDir(cwd, gitLink.owner, gitLink.name);
|
|
30168
|
-
if (chosen &&
|
|
30267
|
+
if (chosen && existsSync25(join20(repoDir, ".git"))) {
|
|
30169
30268
|
const origin = getOriginUrl(repoDir);
|
|
30170
30269
|
if (!origin || !originMatchesRepo(origin, gitLink.owner, gitLink.name)) {
|
|
30171
30270
|
printError(`${repoDir} is a checkout of ${origin ?? "an unknown remote"}, not ${gitLink.owner}/${gitLink.name}. Pass a checkout of the linked repo, or drop --repo to use the default clone.`);
|
|
@@ -30175,7 +30274,7 @@ async function prepareDev(opts) {
|
|
|
30175
30274
|
if (registered && !opts.repoDirOverride) {
|
|
30176
30275
|
printInfo(` → using registered checkout ${repoDir}`);
|
|
30177
30276
|
}
|
|
30178
|
-
dest = gitLink.pathPrefix ?
|
|
30277
|
+
dest = gitLink.pathPrefix ? join20(repoDir, gitLink.pathPrefix) : repoDir;
|
|
30179
30278
|
printStep(`Git-linked server — cloning ${gitLink.owner}/${gitLink.name}@${gitLink.branch}…`);
|
|
30180
30279
|
try {
|
|
30181
30280
|
const result = ensureClone({
|
|
@@ -30200,7 +30299,7 @@ async function prepareDev(opts) {
|
|
|
30200
30299
|
}
|
|
30201
30300
|
process.exit(1);
|
|
30202
30301
|
}
|
|
30203
|
-
if (!
|
|
30302
|
+
if (!existsSync25(env)) {
|
|
30204
30303
|
writeFileSync12(env, `{}
|
|
30205
30304
|
`, "utf-8");
|
|
30206
30305
|
printInfo(` → seeded ${relative8(cwd, env)} (empty; fill secrets here)`);
|
|
@@ -30226,7 +30325,7 @@ async function prepareDev(opts) {
|
|
|
30226
30325
|
});
|
|
30227
30326
|
const result = materializeBundle(dest, bundle, { prune: true });
|
|
30228
30327
|
printInfo(` → wrote ${result.filesWritten} files (pruned ${result.filesRemoved})`);
|
|
30229
|
-
if (!
|
|
30328
|
+
if (!existsSync25(env)) {
|
|
30230
30329
|
writeFileSync12(env, `{}
|
|
30231
30330
|
`, "utf-8");
|
|
30232
30331
|
printInfo(` → seeded ${relative8(cwd, env)} (empty; fill secrets here)`);
|
|
@@ -30245,7 +30344,7 @@ async function prepareDev(opts) {
|
|
|
30245
30344
|
});
|
|
30246
30345
|
printInfo(` → wrote ${toolsResult.filesWritten} editable tool file${toolsResult.filesWritten === 1 ? "" : "s"}${toolsResult.filesRemoved > 0 ? ` (pruned ${toolsResult.filesRemoved})` : ""}`);
|
|
30247
30346
|
} else {
|
|
30248
|
-
if (!
|
|
30347
|
+
if (!existsSync25(dest)) {
|
|
30249
30348
|
printError("No cached bundle found. Run once without --offline first.");
|
|
30250
30349
|
process.exit(1);
|
|
30251
30350
|
}
|
|
@@ -30254,7 +30353,7 @@ async function prepareDev(opts) {
|
|
|
30254
30353
|
process.exit(1);
|
|
30255
30354
|
}
|
|
30256
30355
|
}
|
|
30257
|
-
const entryRel = ENTRY_CANDIDATES.find((c2) =>
|
|
30356
|
+
const entryRel = ENTRY_CANDIDATES.find((c2) => existsSync25(join20(dest, c2)));
|
|
30258
30357
|
if (!entryRel) {
|
|
30259
30358
|
printError("Could not locate an entry file (expected src/worker.ts).");
|
|
30260
30359
|
process.exit(1);
|
|
@@ -30302,8 +30401,8 @@ async function prepareDev(opts) {
|
|
|
30302
30401
|
|
|
30303
30402
|
// src/lib/dev/tree-sync.ts
|
|
30304
30403
|
import { createHash as createHash4 } from "node:crypto";
|
|
30305
|
-
import { existsSync as
|
|
30306
|
-
import { join as
|
|
30404
|
+
import { existsSync as existsSync26, mkdirSync as mkdirSync14, readdirSync as readdirSync3, readFileSync as readFileSync25, writeFileSync as writeFileSync13 } from "node:fs";
|
|
30405
|
+
import { join as join21 } from "node:path";
|
|
30307
30406
|
var AUTHORING_GUIDE_FILE = "AGENTS.md";
|
|
30308
30407
|
var STRUCTURAL_FRONTMATTER_KEYS = [
|
|
30309
30408
|
"inputSchema",
|
|
@@ -30318,12 +30417,12 @@ function isEmptyPlan(plan) {
|
|
|
30318
30417
|
}
|
|
30319
30418
|
function listToolFiles(devRootDir, serverId) {
|
|
30320
30419
|
const dir = serverToolsDir(devRootDir, serverId);
|
|
30321
|
-
if (!
|
|
30420
|
+
if (!existsSync26(dir))
|
|
30322
30421
|
return [];
|
|
30323
30422
|
return readdirSync3(dir).filter((entry) => entry.endsWith(".md")).filter((entry) => entry !== AUTHORING_GUIDE_FILE).map((entry) => entry.slice(0, -3)).sort();
|
|
30324
30423
|
}
|
|
30325
30424
|
function readToolFile(devRootDir, serverId, toolName) {
|
|
30326
|
-
const file =
|
|
30425
|
+
const file = join21(serverToolsDir(devRootDir, serverId), `${toolName}.md`);
|
|
30327
30426
|
const raw = readFileSync25(file, "utf-8");
|
|
30328
30427
|
try {
|
|
30329
30428
|
return { raw, view: parseToolMarkdown(raw) };
|
|
@@ -30350,7 +30449,7 @@ async function writeAuthoringGuide(args) {
|
|
|
30350
30449
|
return null;
|
|
30351
30450
|
const dir = serverToolsDir(args.devRootDir, args.serverId);
|
|
30352
30451
|
mkdirSync14(dir, { recursive: true });
|
|
30353
|
-
const guidePath =
|
|
30452
|
+
const guidePath = join21(dir, AUTHORING_GUIDE_FILE);
|
|
30354
30453
|
writeFileSync13(guidePath, markdown, "utf8");
|
|
30355
30454
|
return guidePath;
|
|
30356
30455
|
} catch {
|
|
@@ -30441,18 +30540,18 @@ function changedFieldNames(view, storedHash) {
|
|
|
30441
30540
|
}
|
|
30442
30541
|
var HANDLER_MANIFEST_FILE = ".handlers-state.json";
|
|
30443
30542
|
function handlerManifestPath(devRootDir, serverId) {
|
|
30444
|
-
return
|
|
30543
|
+
return join21(serverToolsDir(devRootDir, serverId), HANDLER_MANIFEST_FILE);
|
|
30445
30544
|
}
|
|
30446
30545
|
function hashSource2(source) {
|
|
30447
30546
|
return createHash4("sha256").update(source).digest("hex");
|
|
30448
30547
|
}
|
|
30449
30548
|
function listHandlerFiles(devRootDir) {
|
|
30450
30549
|
const dir = serverBundleHandlersDir(devRootDir);
|
|
30451
|
-
if (!
|
|
30550
|
+
if (!existsSync26(dir))
|
|
30452
30551
|
return [];
|
|
30453
30552
|
return readdirSync3(dir).filter((entry) => entry.endsWith(".ts") && !entry.endsWith(".definition.ts")).sort().map((entry) => ({
|
|
30454
30553
|
slug: entry.slice(0, -3),
|
|
30455
|
-
source: readFileSync25(
|
|
30554
|
+
source: readFileSync25(join21(dir, entry), "utf-8")
|
|
30456
30555
|
}));
|
|
30457
30556
|
}
|
|
30458
30557
|
function writeHandlerManifest(args) {
|
|
@@ -30461,7 +30560,7 @@ function writeHandlerManifest(args) {
|
|
|
30461
30560
|
handlers[file.slug] = hashSource2(file.source);
|
|
30462
30561
|
}
|
|
30463
30562
|
const dir = serverToolsDir(args.devRootDir, args.serverId);
|
|
30464
|
-
if (!
|
|
30563
|
+
if (!existsSync26(dir))
|
|
30465
30564
|
mkdirSync14(dir, { recursive: true });
|
|
30466
30565
|
const manifest = {
|
|
30467
30566
|
handlers,
|
|
@@ -30472,8 +30571,8 @@ function writeHandlerManifest(args) {
|
|
|
30472
30571
|
return Object.keys(handlers).length;
|
|
30473
30572
|
}
|
|
30474
30573
|
function recordHandlerPushed(args) {
|
|
30475
|
-
const file =
|
|
30476
|
-
if (!
|
|
30574
|
+
const file = join21(serverBundleHandlersDir(args.devRootDir), `${args.slug}.ts`);
|
|
30575
|
+
if (!existsSync26(file))
|
|
30477
30576
|
return;
|
|
30478
30577
|
const manifest = readHandlerManifest(args.devRootDir, args.serverId) ?? {
|
|
30479
30578
|
handlers: {},
|
|
@@ -30485,7 +30584,7 @@ function recordHandlerPushed(args) {
|
|
|
30485
30584
|
}
|
|
30486
30585
|
function readHandlerManifest(devRootDir, serverId) {
|
|
30487
30586
|
const file = handlerManifestPath(devRootDir, serverId);
|
|
30488
|
-
if (!
|
|
30587
|
+
if (!existsSync26(file))
|
|
30489
30588
|
return null;
|
|
30490
30589
|
try {
|
|
30491
30590
|
const parsed = JSON.parse(readFileSync25(file, "utf-8"));
|
|
@@ -31258,9 +31357,9 @@ function registerDomainCommands(program) {
|
|
|
31258
31357
|
|
|
31259
31358
|
// src/commands/config.ts
|
|
31260
31359
|
import { homedir as homedir2 } from "node:os";
|
|
31261
|
-
import { join as
|
|
31360
|
+
import { join as join22 } from "node:path";
|
|
31262
31361
|
function configFilePath() {
|
|
31263
|
-
return
|
|
31362
|
+
return join22(homedir2(), ".mcpcloud", "config.json");
|
|
31264
31363
|
}
|
|
31265
31364
|
function previewKey2(key) {
|
|
31266
31365
|
if (!key)
|
|
@@ -31505,12 +31604,12 @@ function registerConfigCommands(program) {
|
|
|
31505
31604
|
}
|
|
31506
31605
|
|
|
31507
31606
|
// src/commands/dev.ts
|
|
31508
|
-
import { existsSync as
|
|
31607
|
+
import { existsSync as existsSync39 } from "node:fs";
|
|
31509
31608
|
import { isAbsolute as isAbsolute5, relative as relative9, resolve as resolve11 } from "node:path";
|
|
31510
31609
|
|
|
31511
31610
|
// src/lib/dev/sessions.ts
|
|
31512
31611
|
import {
|
|
31513
|
-
existsSync as
|
|
31612
|
+
existsSync as existsSync27,
|
|
31514
31613
|
mkdirSync as mkdirSync15,
|
|
31515
31614
|
readFileSync as readFileSync26,
|
|
31516
31615
|
readdirSync as readdirSync4,
|
|
@@ -31518,17 +31617,17 @@ import {
|
|
|
31518
31617
|
writeFileSync as writeFileSync14
|
|
31519
31618
|
} from "node:fs";
|
|
31520
31619
|
import { homedir as homedir3 } from "node:os";
|
|
31521
|
-
import { join as
|
|
31620
|
+
import { join as join23 } from "node:path";
|
|
31522
31621
|
var SESSIONS_DIR_NAME = "dev-sessions";
|
|
31523
31622
|
function sessionsDir() {
|
|
31524
|
-
return
|
|
31623
|
+
return join23(homedir3(), ".mcpcloud", SESSIONS_DIR_NAME);
|
|
31525
31624
|
}
|
|
31526
31625
|
function sessionFile(pid) {
|
|
31527
|
-
return
|
|
31626
|
+
return join23(sessionsDir(), `${pid}.json`);
|
|
31528
31627
|
}
|
|
31529
31628
|
function ensureDir() {
|
|
31530
31629
|
const dir = sessionsDir();
|
|
31531
|
-
if (!
|
|
31630
|
+
if (!existsSync27(dir))
|
|
31532
31631
|
mkdirSync15(dir, { recursive: true, mode: 448 });
|
|
31533
31632
|
}
|
|
31534
31633
|
function recordSession(record) {
|
|
@@ -31540,7 +31639,7 @@ function recordSession(record) {
|
|
|
31540
31639
|
}
|
|
31541
31640
|
function removeSession(pid) {
|
|
31542
31641
|
const path = sessionFile(pid);
|
|
31543
|
-
if (
|
|
31642
|
+
if (existsSync27(path)) {
|
|
31544
31643
|
try {
|
|
31545
31644
|
unlinkSync(path);
|
|
31546
31645
|
} catch {}
|
|
@@ -31548,13 +31647,13 @@ function removeSession(pid) {
|
|
|
31548
31647
|
}
|
|
31549
31648
|
function listSessions() {
|
|
31550
31649
|
const dir = sessionsDir();
|
|
31551
|
-
if (!
|
|
31650
|
+
if (!existsSync27(dir))
|
|
31552
31651
|
return [];
|
|
31553
31652
|
const live = [];
|
|
31554
31653
|
for (const entry of readdirSync4(dir)) {
|
|
31555
31654
|
if (!entry.endsWith(".json"))
|
|
31556
31655
|
continue;
|
|
31557
|
-
const path =
|
|
31656
|
+
const path = join23(dir, entry);
|
|
31558
31657
|
try {
|
|
31559
31658
|
const parsed = JSON.parse(readFileSync26(path, "utf-8"));
|
|
31560
31659
|
if (typeof parsed.pid !== "number") {
|
|
@@ -31893,13 +31992,13 @@ function formatSummary(record) {
|
|
|
31893
31992
|
|
|
31894
31993
|
// src/commands/dev-tail.ts
|
|
31895
31994
|
import {
|
|
31896
|
-
existsSync as
|
|
31995
|
+
existsSync as existsSync28,
|
|
31897
31996
|
openSync,
|
|
31898
31997
|
readSync,
|
|
31899
31998
|
closeSync,
|
|
31900
31999
|
statSync as statSync3
|
|
31901
32000
|
} from "node:fs";
|
|
31902
|
-
import { join as
|
|
32001
|
+
import { join as join24 } from "node:path";
|
|
31903
32002
|
var DEFAULT_INTERVAL_MS = 250;
|
|
31904
32003
|
var MAX_READ_CHUNK = 64 * 1024;
|
|
31905
32004
|
function registerDevTailCommand(dev) {
|
|
@@ -31908,14 +32007,14 @@ function registerDevTailCommand(dev) {
|
|
|
31908
32007
|
async function runDevTail(opts) {
|
|
31909
32008
|
const cwd = process.cwd();
|
|
31910
32009
|
const dir = inspectorDir(cwd);
|
|
31911
|
-
const activePath =
|
|
32010
|
+
const activePath = join24(dir, ACTIVE_FILE);
|
|
31912
32011
|
const intervalMs = parseInterval(opts.intervalMs);
|
|
31913
|
-
if (!
|
|
32012
|
+
if (!existsSync28(dir)) {
|
|
31914
32013
|
printInfo(`No inspector history yet at ${dir}. Run \`mcp dev\` to start capturing.`);
|
|
31915
32014
|
throw new CliExitError(0);
|
|
31916
32015
|
}
|
|
31917
32016
|
let cursor = 0;
|
|
31918
|
-
if (
|
|
32017
|
+
if (existsSync28(activePath)) {
|
|
31919
32018
|
try {
|
|
31920
32019
|
cursor = opts.fromStart ? 0 : statSync3(activePath).size;
|
|
31921
32020
|
} catch {
|
|
@@ -31931,7 +32030,7 @@ async function runDevTail(opts) {
|
|
|
31931
32030
|
process.on("SIGTERM", stop);
|
|
31932
32031
|
while (!stopped) {
|
|
31933
32032
|
let size = 0;
|
|
31934
|
-
if (
|
|
32033
|
+
if (existsSync28(activePath)) {
|
|
31935
32034
|
try {
|
|
31936
32035
|
size = statSync3(activePath).size;
|
|
31937
32036
|
} catch {
|
|
@@ -32176,8 +32275,8 @@ function startGitPullPoll(args) {
|
|
|
32176
32275
|
|
|
32177
32276
|
// src/lib/dev/editor.ts
|
|
32178
32277
|
import { spawn as spawn5 } from "node:child_process";
|
|
32179
|
-
import { existsSync as
|
|
32180
|
-
import { delimiter as delimiter2, join as
|
|
32278
|
+
import { existsSync as existsSync29, statSync as statSync4 } from "node:fs";
|
|
32279
|
+
import { delimiter as delimiter2, join as join25 } from "node:path";
|
|
32181
32280
|
import { platform as platform3 } from "node:os";
|
|
32182
32281
|
var TARGET_LABEL = {
|
|
32183
32282
|
tools: "tool metadata",
|
|
@@ -32213,8 +32312,8 @@ function findOnPath2(command) {
|
|
|
32213
32312
|
if (!dir)
|
|
32214
32313
|
continue;
|
|
32215
32314
|
for (const ext of exts) {
|
|
32216
|
-
const candidate =
|
|
32217
|
-
if (
|
|
32315
|
+
const candidate = join25(dir, command + ext);
|
|
32316
|
+
if (existsSync29(candidate) && isExecutable(candidate))
|
|
32218
32317
|
return candidate;
|
|
32219
32318
|
}
|
|
32220
32319
|
}
|
|
@@ -32503,11 +32602,11 @@ function parseOpenChoice(raw) {
|
|
|
32503
32602
|
}
|
|
32504
32603
|
|
|
32505
32604
|
// src/lib/dev/file-watcher.ts
|
|
32506
|
-
import { existsSync as
|
|
32507
|
-
import { join as
|
|
32605
|
+
import { existsSync as existsSync30, statSync as statSync5, watch as fsWatch2 } from "node:fs";
|
|
32606
|
+
import { join as join26 } from "node:path";
|
|
32508
32607
|
var DEFAULT_IGNORE = ["node_modules", ".git", "_mcpsh_host.mjs"];
|
|
32509
32608
|
function watchDir(options) {
|
|
32510
|
-
if (!
|
|
32609
|
+
if (!existsSync30(options.rootDir)) {
|
|
32511
32610
|
throw new Error(`watchDir: directory does not exist: ${options.rootDir}`);
|
|
32512
32611
|
}
|
|
32513
32612
|
const ignore = new Set([...DEFAULT_IGNORE, ...options.ignore ?? []]);
|
|
@@ -32543,7 +32642,7 @@ function watchDir(options) {
|
|
|
32543
32642
|
for (const entry of readdirSync(options.rootDir)) {
|
|
32544
32643
|
if (ignore.has(entry))
|
|
32545
32644
|
continue;
|
|
32546
|
-
const sub =
|
|
32645
|
+
const sub = join26(options.rootDir, entry);
|
|
32547
32646
|
try {
|
|
32548
32647
|
const stat = statSync5(sub);
|
|
32549
32648
|
if (!stat.isDirectory())
|
|
@@ -32591,10 +32690,10 @@ function isToolHandlerPath(rel) {
|
|
|
32591
32690
|
}
|
|
32592
32691
|
|
|
32593
32692
|
// src/lib/dev/tools-watcher.ts
|
|
32594
|
-
import { existsSync as
|
|
32693
|
+
import { existsSync as existsSync31 } from "node:fs";
|
|
32595
32694
|
function startToolsWatcher(args) {
|
|
32596
32695
|
const rootDir = serverToolsDir(devRoot(args.cwd), args.serverId);
|
|
32597
|
-
if (!
|
|
32696
|
+
if (!existsSync31(rootDir))
|
|
32598
32697
|
return null;
|
|
32599
32698
|
let inflight = false;
|
|
32600
32699
|
let pendingNames = new Set;
|
|
@@ -32713,10 +32812,10 @@ async function maybeHotReload(args) {
|
|
|
32713
32812
|
}
|
|
32714
32813
|
|
|
32715
32814
|
// src/lib/dev/handlers-watcher.ts
|
|
32716
|
-
import { existsSync as
|
|
32815
|
+
import { existsSync as existsSync32 } from "node:fs";
|
|
32717
32816
|
function startHandlersWatcher(args) {
|
|
32718
32817
|
const rootDir = serverBundleHandlersDir(devRoot(args.cwd));
|
|
32719
|
-
if (!
|
|
32818
|
+
if (!existsSync32(rootDir))
|
|
32720
32819
|
return null;
|
|
32721
32820
|
let inflight = false;
|
|
32722
32821
|
let pendingSlugs = new Set;
|
|
@@ -32923,15 +33022,15 @@ function createBurstGuard() {
|
|
|
32923
33022
|
}
|
|
32924
33023
|
|
|
32925
33024
|
// src/lib/dev/agent-connectors/claude-code.ts
|
|
32926
|
-
import { existsSync as
|
|
33025
|
+
import { existsSync as existsSync34, unlinkSync as unlinkSync2, writeFileSync as writeFileSync16 } from "node:fs";
|
|
32927
33026
|
import { homedir as homedir4 } from "node:os";
|
|
32928
|
-
import { join as
|
|
33027
|
+
import { join as join28 } from "node:path";
|
|
32929
33028
|
|
|
32930
33029
|
// src/lib/dev/agent-connectors/json-config-utils.ts
|
|
32931
|
-
import { existsSync as
|
|
32932
|
-
import { dirname as dirname10, join as
|
|
33030
|
+
import { existsSync as existsSync33, mkdirSync as mkdirSync16, readFileSync as readFileSync27, writeFileSync as writeFileSync15 } from "node:fs";
|
|
33031
|
+
import { dirname as dirname10, join as join27, basename } from "node:path";
|
|
32933
33032
|
function readJsonFile(path) {
|
|
32934
|
-
if (!
|
|
33033
|
+
if (!existsSync33(path))
|
|
32935
33034
|
return { ok: true, value: {} };
|
|
32936
33035
|
try {
|
|
32937
33036
|
const raw = readFileSync27(path, "utf-8");
|
|
@@ -32955,13 +33054,13 @@ function atomicWriteJson(path, value) {
|
|
|
32955
33054
|
renameSync(tmp, path);
|
|
32956
33055
|
}
|
|
32957
33056
|
function backupConfig(args) {
|
|
32958
|
-
if (!
|
|
33057
|
+
if (!existsSync33(args.configPath)) {
|
|
32959
33058
|
return { backupPath: null, existed: false };
|
|
32960
33059
|
}
|
|
32961
33060
|
mkdirSync16(args.backupsDir, { recursive: true });
|
|
32962
33061
|
const filename = `${args.agentId}__${basename(args.configPath)}.bak`;
|
|
32963
|
-
const backupPath =
|
|
32964
|
-
if (!
|
|
33062
|
+
const backupPath = join27(args.backupsDir, filename);
|
|
33063
|
+
if (!existsSync33(backupPath)) {
|
|
32965
33064
|
const raw = readFileSync27(args.configPath, "utf-8");
|
|
32966
33065
|
writeFileSync15(backupPath, raw, "utf-8");
|
|
32967
33066
|
}
|
|
@@ -32969,8 +33068,8 @@ function backupConfig(args) {
|
|
|
32969
33068
|
}
|
|
32970
33069
|
function restoreFromBackup(args) {
|
|
32971
33070
|
const filename = `${args.agentId}__${basename(args.configPath)}.bak`;
|
|
32972
|
-
const backupPath =
|
|
32973
|
-
if (!
|
|
33071
|
+
const backupPath = join27(args.backupsDir, filename);
|
|
33072
|
+
if (!existsSync33(backupPath)) {
|
|
32974
33073
|
return { restored: false };
|
|
32975
33074
|
}
|
|
32976
33075
|
const raw = readFileSync27(backupPath, "utf-8");
|
|
@@ -32981,15 +33080,15 @@ function restoreFromBackup(args) {
|
|
|
32981
33080
|
|
|
32982
33081
|
// src/lib/dev/agent-connectors/claude-code.ts
|
|
32983
33082
|
function configPath() {
|
|
32984
|
-
return
|
|
33083
|
+
return join28(homedir4(), ".claude.json");
|
|
32985
33084
|
}
|
|
32986
33085
|
function legacyConfigPath() {
|
|
32987
|
-
return
|
|
33086
|
+
return join28(homedir4(), ".claude", "mcp.json");
|
|
32988
33087
|
}
|
|
32989
33088
|
function resolveConfigPath() {
|
|
32990
|
-
if (
|
|
33089
|
+
if (existsSync34(configPath()))
|
|
32991
33090
|
return configPath();
|
|
32992
|
-
if (
|
|
33091
|
+
if (existsSync34(legacyConfigPath()))
|
|
32993
33092
|
return legacyConfigPath();
|
|
32994
33093
|
return configPath();
|
|
32995
33094
|
}
|
|
@@ -32999,8 +33098,8 @@ var claudeCodeConnector = {
|
|
|
32999
33098
|
hotkey: "c",
|
|
33000
33099
|
describeLocation: () => resolveConfigPath(),
|
|
33001
33100
|
async detect() {
|
|
33002
|
-
const claudeDir =
|
|
33003
|
-
if (
|
|
33101
|
+
const claudeDir = join28(homedir4(), ".claude");
|
|
33102
|
+
if (existsSync34(configPath()) || existsSync34(legacyConfigPath()) || existsSync34(claudeDir)) {
|
|
33004
33103
|
return { installed: true, note: "Found Claude Code config" };
|
|
33005
33104
|
}
|
|
33006
33105
|
return { installed: false };
|
|
@@ -33038,7 +33137,7 @@ var claudeCodeConnector = {
|
|
|
33038
33137
|
backupsDir: args.backupsDir,
|
|
33039
33138
|
agentId: this.id
|
|
33040
33139
|
});
|
|
33041
|
-
if (!restored.restored &&
|
|
33140
|
+
if (!restored.restored && existsSync34(path)) {
|
|
33042
33141
|
const after = readJsonFile(path);
|
|
33043
33142
|
if (after.ok && after.value && typeof after.value === "object") {
|
|
33044
33143
|
const root = after.value;
|
|
@@ -33060,16 +33159,16 @@ var claudeCodeConnector = {
|
|
|
33060
33159
|
|
|
33061
33160
|
// src/lib/dev/agent-connectors/codex.ts
|
|
33062
33161
|
import {
|
|
33063
|
-
existsSync as
|
|
33162
|
+
existsSync as existsSync35,
|
|
33064
33163
|
mkdirSync as mkdirSync17,
|
|
33065
33164
|
readFileSync as readFileSync28,
|
|
33066
33165
|
unlinkSync as unlinkSync3,
|
|
33067
33166
|
writeFileSync as writeFileSync17
|
|
33068
33167
|
} from "node:fs";
|
|
33069
33168
|
import { homedir as homedir5 } from "node:os";
|
|
33070
|
-
import { dirname as dirname11, join as
|
|
33169
|
+
import { dirname as dirname11, join as join29 } from "node:path";
|
|
33071
33170
|
function configPath2() {
|
|
33072
|
-
return
|
|
33171
|
+
return join29(homedir5(), ".codex", "config.toml");
|
|
33073
33172
|
}
|
|
33074
33173
|
var SECTION_PREFIX = "mcp_servers.";
|
|
33075
33174
|
function buildSection(name, url) {
|
|
@@ -33107,7 +33206,7 @@ var codexConnector = {
|
|
|
33107
33206
|
hotkey: "x",
|
|
33108
33207
|
describeLocation: () => configPath2(),
|
|
33109
33208
|
async detect() {
|
|
33110
|
-
if (
|
|
33209
|
+
if (existsSync35(join29(homedir5(), ".codex")) || existsSync35(configPath2())) {
|
|
33111
33210
|
return { installed: true, note: "Found ~/.codex/" };
|
|
33112
33211
|
}
|
|
33113
33212
|
return { installed: false };
|
|
@@ -33120,7 +33219,7 @@ var codexConnector = {
|
|
|
33120
33219
|
agentId: this.id
|
|
33121
33220
|
});
|
|
33122
33221
|
let existing = "";
|
|
33123
|
-
if (
|
|
33222
|
+
if (existsSync35(path)) {
|
|
33124
33223
|
existing = readFileSync28(path, "utf-8");
|
|
33125
33224
|
}
|
|
33126
33225
|
const conflict = findSectionRange(existing, args.name) !== null;
|
|
@@ -33142,7 +33241,7 @@ var codexConnector = {
|
|
|
33142
33241
|
},
|
|
33143
33242
|
async remove(args) {
|
|
33144
33243
|
const path = configPath2();
|
|
33145
|
-
if (
|
|
33244
|
+
if (existsSync35(path)) {
|
|
33146
33245
|
const existing = readFileSync28(path, "utf-8");
|
|
33147
33246
|
const range = findSectionRange(existing, args.name);
|
|
33148
33247
|
if (range) {
|
|
@@ -33155,7 +33254,7 @@ var codexConnector = {
|
|
|
33155
33254
|
backupsDir: args.backupsDir,
|
|
33156
33255
|
agentId: this.id
|
|
33157
33256
|
});
|
|
33158
|
-
if (!restored.restored &&
|
|
33257
|
+
if (!restored.restored && existsSync35(path)) {
|
|
33159
33258
|
const after = readFileSync28(path, "utf-8");
|
|
33160
33259
|
if (!after.trim()) {
|
|
33161
33260
|
try {
|
|
@@ -33168,11 +33267,11 @@ var codexConnector = {
|
|
|
33168
33267
|
};
|
|
33169
33268
|
|
|
33170
33269
|
// src/lib/dev/agent-connectors/continue.ts
|
|
33171
|
-
import { existsSync as
|
|
33270
|
+
import { existsSync as existsSync36, unlinkSync as unlinkSync4, writeFileSync as writeFileSync18 } from "node:fs";
|
|
33172
33271
|
import { homedir as homedir6 } from "node:os";
|
|
33173
|
-
import { join as
|
|
33272
|
+
import { join as join30 } from "node:path";
|
|
33174
33273
|
function configPath3() {
|
|
33175
|
-
return
|
|
33274
|
+
return join30(homedir6(), ".continue", "config.json");
|
|
33176
33275
|
}
|
|
33177
33276
|
function isContinueServerEntry(value) {
|
|
33178
33277
|
return Boolean(value && typeof value === "object" && typeof value.name === "string");
|
|
@@ -33183,8 +33282,8 @@ var continueConnector = {
|
|
|
33183
33282
|
hotkey: "n",
|
|
33184
33283
|
describeLocation: () => configPath3(),
|
|
33185
33284
|
async detect() {
|
|
33186
|
-
const dir =
|
|
33187
|
-
if (
|
|
33285
|
+
const dir = join30(homedir6(), ".continue");
|
|
33286
|
+
if (existsSync36(dir) || existsSync36(configPath3())) {
|
|
33188
33287
|
return { installed: true, note: "Found ~/.continue/" };
|
|
33189
33288
|
}
|
|
33190
33289
|
return { installed: false };
|
|
@@ -33222,7 +33321,7 @@ var continueConnector = {
|
|
|
33222
33321
|
backupsDir: args.backupsDir,
|
|
33223
33322
|
agentId: this.id
|
|
33224
33323
|
});
|
|
33225
|
-
if (!restored.restored &&
|
|
33324
|
+
if (!restored.restored && existsSync36(path)) {
|
|
33226
33325
|
const after = readJsonFile(path);
|
|
33227
33326
|
if (after.ok && after.value && typeof after.value === "object") {
|
|
33228
33327
|
const root = after.value;
|
|
@@ -33243,11 +33342,11 @@ var continueConnector = {
|
|
|
33243
33342
|
};
|
|
33244
33343
|
|
|
33245
33344
|
// src/lib/dev/agent-connectors/cursor.ts
|
|
33246
|
-
import { existsSync as
|
|
33345
|
+
import { existsSync as existsSync37, unlinkSync as unlinkSync5, writeFileSync as writeFileSync19 } from "node:fs";
|
|
33247
33346
|
import { homedir as homedir7 } from "node:os";
|
|
33248
|
-
import { join as
|
|
33347
|
+
import { join as join31 } from "node:path";
|
|
33249
33348
|
function globalConfigPath() {
|
|
33250
|
-
return
|
|
33349
|
+
return join31(homedir7(), ".cursor", "mcp.json");
|
|
33251
33350
|
}
|
|
33252
33351
|
var cursorConnector = {
|
|
33253
33352
|
id: "cursor",
|
|
@@ -33255,9 +33354,9 @@ var cursorConnector = {
|
|
|
33255
33354
|
hotkey: "u",
|
|
33256
33355
|
describeLocation: () => globalConfigPath(),
|
|
33257
33356
|
async detect() {
|
|
33258
|
-
const cursorDir =
|
|
33259
|
-
const macAppSupport =
|
|
33260
|
-
if (
|
|
33357
|
+
const cursorDir = join31(homedir7(), ".cursor");
|
|
33358
|
+
const macAppSupport = join31(homedir7(), "Library", "Application Support", "Cursor");
|
|
33359
|
+
if (existsSync37(cursorDir) || existsSync37(macAppSupport)) {
|
|
33261
33360
|
return { installed: true, note: "Found Cursor config dir" };
|
|
33262
33361
|
}
|
|
33263
33362
|
return { installed: false };
|
|
@@ -33295,7 +33394,7 @@ var cursorConnector = {
|
|
|
33295
33394
|
backupsDir: args.backupsDir,
|
|
33296
33395
|
agentId: this.id
|
|
33297
33396
|
});
|
|
33298
|
-
if (!restored.restored &&
|
|
33397
|
+
if (!restored.restored && existsSync37(path)) {
|
|
33299
33398
|
const after = readJsonFile(path);
|
|
33300
33399
|
if (after.ok && after.value && typeof after.value === "object") {
|
|
33301
33400
|
const root = after.value;
|
|
@@ -33316,30 +33415,30 @@ var cursorConnector = {
|
|
|
33316
33415
|
};
|
|
33317
33416
|
|
|
33318
33417
|
// src/lib/dev/agent-connectors/vscode-copilot.ts
|
|
33319
|
-
import { existsSync as
|
|
33418
|
+
import { existsSync as existsSync38, unlinkSync as unlinkSync6, writeFileSync as writeFileSync20 } from "node:fs";
|
|
33320
33419
|
import { homedir as homedir8, platform as platform4 } from "node:os";
|
|
33321
|
-
import { join as
|
|
33420
|
+
import { join as join32, resolve as resolve10 } from "node:path";
|
|
33322
33421
|
function userLevelConfigPath() {
|
|
33323
33422
|
const home = homedir8();
|
|
33324
33423
|
const p = platform4();
|
|
33325
33424
|
if (p === "darwin")
|
|
33326
|
-
return
|
|
33425
|
+
return join32(home, "Library", "Application Support", "Code", "User", "mcp.json");
|
|
33327
33426
|
if (p === "win32") {
|
|
33328
|
-
const appData = process.env["APPDATA"] ??
|
|
33329
|
-
return
|
|
33427
|
+
const appData = process.env["APPDATA"] ?? join32(home, "AppData", "Roaming");
|
|
33428
|
+
return join32(appData, "Code", "User", "mcp.json");
|
|
33330
33429
|
}
|
|
33331
|
-
const xdg = process.env["XDG_CONFIG_HOME"] ??
|
|
33332
|
-
return
|
|
33430
|
+
const xdg = process.env["XDG_CONFIG_HOME"] ?? join32(home, ".config");
|
|
33431
|
+
return join32(xdg, "Code", "User", "mcp.json");
|
|
33333
33432
|
}
|
|
33334
33433
|
function isHomeDir(cwd) {
|
|
33335
33434
|
return resolve10(cwd) === resolve10(homedir8());
|
|
33336
33435
|
}
|
|
33337
33436
|
function hasWorkspaceVscode(cwd) {
|
|
33338
|
-
return
|
|
33437
|
+
return existsSync38(join32(cwd, ".vscode"));
|
|
33339
33438
|
}
|
|
33340
33439
|
function configPath4(cwd) {
|
|
33341
33440
|
if (!isHomeDir(cwd) && hasWorkspaceVscode(cwd)) {
|
|
33342
|
-
return
|
|
33441
|
+
return join32(cwd, ".vscode", "mcp.json");
|
|
33343
33442
|
}
|
|
33344
33443
|
return userLevelConfigPath();
|
|
33345
33444
|
}
|
|
@@ -33353,7 +33452,7 @@ var vscodeCopilotConnector = {
|
|
|
33353
33452
|
if (!isHomeDir(here) && hasWorkspaceVscode(here)) {
|
|
33354
33453
|
return { installed: true, note: "Found .vscode/ in current dir" };
|
|
33355
33454
|
}
|
|
33356
|
-
if (
|
|
33455
|
+
if (existsSync38(userLevelConfigPath().replace(/mcp\.json$/, ""))) {
|
|
33357
33456
|
return { installed: true, note: "Found VS Code user profile" };
|
|
33358
33457
|
}
|
|
33359
33458
|
return { installed: false };
|
|
@@ -33391,7 +33490,7 @@ var vscodeCopilotConnector = {
|
|
|
33391
33490
|
backupsDir: args.backupsDir,
|
|
33392
33491
|
agentId: this.id
|
|
33393
33492
|
});
|
|
33394
|
-
if (!restored.restored &&
|
|
33493
|
+
if (!restored.restored && existsSync38(path)) {
|
|
33395
33494
|
const after = readJsonFile(path);
|
|
33396
33495
|
if (after.ok && after.value && typeof after.value === "object") {
|
|
33397
33496
|
const root = after.value;
|
|
@@ -33709,7 +33808,7 @@ async function runDev(opts) {
|
|
|
33709
33808
|
let specPath = null;
|
|
33710
33809
|
if (opts.spec) {
|
|
33711
33810
|
const resolved = resolveSpecPath(cwd, opts.spec);
|
|
33712
|
-
if (!
|
|
33811
|
+
if (!existsSync39(resolved)) {
|
|
33713
33812
|
printError(`Spec file not found: ${resolved}`);
|
|
33714
33813
|
process.exit(1);
|
|
33715
33814
|
}
|
|
@@ -34639,13 +34738,13 @@ async function confirmRollback(deploymentId) {
|
|
|
34639
34738
|
}
|
|
34640
34739
|
|
|
34641
34740
|
// src/commands/doctor.ts
|
|
34642
|
-
import { existsSync as
|
|
34741
|
+
import { existsSync as existsSync41, statSync as statSync6, readFileSync as readFileSync30 } from "node:fs";
|
|
34643
34742
|
import { homedir as homedir9, platform as platform6 } from "node:os";
|
|
34644
|
-
import { join as
|
|
34743
|
+
import { join as join34, delimiter as delimiter3 } from "node:path";
|
|
34645
34744
|
|
|
34646
34745
|
// src/lib/version-check.ts
|
|
34647
|
-
import { existsSync as
|
|
34648
|
-
import { join as
|
|
34746
|
+
import { existsSync as existsSync40, mkdirSync as mkdirSync18, readFileSync as readFileSync29, writeFileSync as writeFileSync21 } from "node:fs";
|
|
34747
|
+
import { join as join33 } from "node:path";
|
|
34649
34748
|
var CACHE_TTL_MS = 24 * 60 * 60 * 1000;
|
|
34650
34749
|
var FETCH_TIMEOUT_MS2 = 2000;
|
|
34651
34750
|
var REGISTRY_URL = "https://registry.npmjs.org/@mcpcloud/cli/latest";
|
|
@@ -34653,10 +34752,10 @@ function cacheDir() {
|
|
|
34653
34752
|
return configDir();
|
|
34654
34753
|
}
|
|
34655
34754
|
function cacheFile() {
|
|
34656
|
-
return
|
|
34755
|
+
return join33(cacheDir(), "version-check.json");
|
|
34657
34756
|
}
|
|
34658
34757
|
function readCache() {
|
|
34659
|
-
if (!
|
|
34758
|
+
if (!existsSync40(cacheFile()))
|
|
34660
34759
|
return null;
|
|
34661
34760
|
try {
|
|
34662
34761
|
const raw = JSON.parse(readFileSync29(cacheFile(), "utf-8"));
|
|
@@ -34669,7 +34768,7 @@ function readCache() {
|
|
|
34669
34768
|
}
|
|
34670
34769
|
function writeCache(entry) {
|
|
34671
34770
|
try {
|
|
34672
|
-
if (!
|
|
34771
|
+
if (!existsSync40(cacheDir()))
|
|
34673
34772
|
mkdirSync18(cacheDir(), { recursive: true, mode: 448 });
|
|
34674
34773
|
writeFileSync21(cacheFile(), JSON.stringify(entry, null, 2), { mode: 384 });
|
|
34675
34774
|
} catch {}
|
|
@@ -34782,8 +34881,8 @@ function checkNode() {
|
|
|
34782
34881
|
}
|
|
34783
34882
|
function checkConfigFile() {
|
|
34784
34883
|
const t0 = Date.now();
|
|
34785
|
-
const path =
|
|
34786
|
-
if (!
|
|
34884
|
+
const path = join34(homedir9(), ".mcpcloud", "config.json");
|
|
34885
|
+
if (!existsSync41(path)) {
|
|
34787
34886
|
return {
|
|
34788
34887
|
name: "Config file",
|
|
34789
34888
|
status: "warn",
|
|
@@ -34936,8 +35035,8 @@ function checkClaudeCli() {
|
|
|
34936
35035
|
for (const dir of PATH.split(delimiter3)) {
|
|
34937
35036
|
if (!dir)
|
|
34938
35037
|
continue;
|
|
34939
|
-
const candidate =
|
|
34940
|
-
if (
|
|
35038
|
+
const candidate = join34(dir, exe);
|
|
35039
|
+
if (existsSync41(candidate)) {
|
|
34941
35040
|
return {
|
|
34942
35041
|
name: "claude CLI",
|
|
34943
35042
|
status: "pass",
|
|
@@ -35688,8 +35787,8 @@ function registerInstallationCommands(program) {
|
|
|
35688
35787
|
}
|
|
35689
35788
|
|
|
35690
35789
|
// src/commands/invoke.ts
|
|
35691
|
-
import { existsSync as
|
|
35692
|
-
import { join as
|
|
35790
|
+
import { existsSync as existsSync42, readFileSync as readFileSync31 } from "node:fs";
|
|
35791
|
+
import { join as join35 } from "node:path";
|
|
35693
35792
|
|
|
35694
35793
|
// src/lib/dev/local-invoke.ts
|
|
35695
35794
|
var READY_TIMEOUT_MS = 30000;
|
|
@@ -36072,7 +36171,7 @@ async function runLocalInvoke(args) {
|
|
|
36072
36171
|
const prepared = await prepareDev({
|
|
36073
36172
|
cwd,
|
|
36074
36173
|
inspector: false,
|
|
36075
|
-
offline:
|
|
36174
|
+
offline: existsSync42(join35(devRoot(cwd), "server")),
|
|
36076
36175
|
organizationId: target.organizationId,
|
|
36077
36176
|
port,
|
|
36078
36177
|
serverId: target.serverId,
|
|
@@ -37054,26 +37153,26 @@ function registerConnectionsCommands(program) {
|
|
|
37054
37153
|
// src/lib/plugins.ts
|
|
37055
37154
|
import { spawn as spawn7 } from "node:child_process";
|
|
37056
37155
|
import {
|
|
37057
|
-
existsSync as
|
|
37156
|
+
existsSync as existsSync43,
|
|
37058
37157
|
mkdirSync as mkdirSync19,
|
|
37059
37158
|
readdirSync as readdirSync5,
|
|
37060
37159
|
readFileSync as readFileSync32,
|
|
37061
37160
|
rmSync as rmSync3,
|
|
37062
37161
|
statSync as statSync7
|
|
37063
37162
|
} from "node:fs";
|
|
37064
|
-
import { join as
|
|
37163
|
+
import { join as join36 } from "node:path";
|
|
37065
37164
|
import { pathToFileURL } from "node:url";
|
|
37066
37165
|
function pluginsDir() {
|
|
37067
|
-
return
|
|
37166
|
+
return join36(configDir(), "plugins");
|
|
37068
37167
|
}
|
|
37069
37168
|
function ensureDir2() {
|
|
37070
37169
|
const dir = pluginsDir();
|
|
37071
|
-
if (!
|
|
37170
|
+
if (!existsSync43(dir))
|
|
37072
37171
|
mkdirSync19(dir, { recursive: true, mode: 448 });
|
|
37073
37172
|
}
|
|
37074
37173
|
function readManifestFromPackageDir(packageDir) {
|
|
37075
|
-
const pkgPath =
|
|
37076
|
-
if (!
|
|
37174
|
+
const pkgPath = join36(packageDir, "package.json");
|
|
37175
|
+
if (!existsSync43(pkgPath))
|
|
37077
37176
|
return null;
|
|
37078
37177
|
let pkg;
|
|
37079
37178
|
try {
|
|
@@ -37084,8 +37183,8 @@ function readManifestFromPackageDir(packageDir) {
|
|
|
37084
37183
|
if (!pkg.name)
|
|
37085
37184
|
return null;
|
|
37086
37185
|
const relEntry = pkg.mcpsh?.register ?? pkg.mcp?.register ?? pkg.main ?? "index.js";
|
|
37087
|
-
const entry =
|
|
37088
|
-
if (!
|
|
37186
|
+
const entry = join36(packageDir, relEntry);
|
|
37187
|
+
if (!existsSync43(entry))
|
|
37089
37188
|
return null;
|
|
37090
37189
|
return {
|
|
37091
37190
|
name: pkg.name,
|
|
@@ -37096,11 +37195,11 @@ function readManifestFromPackageDir(packageDir) {
|
|
|
37096
37195
|
}
|
|
37097
37196
|
function listInstalledPlugins() {
|
|
37098
37197
|
const dir = pluginsDir();
|
|
37099
|
-
if (!
|
|
37198
|
+
if (!existsSync43(dir))
|
|
37100
37199
|
return [];
|
|
37101
37200
|
const out = [];
|
|
37102
37201
|
for (const entry of readdirSync5(dir)) {
|
|
37103
|
-
const full =
|
|
37202
|
+
const full = join36(dir, entry);
|
|
37104
37203
|
let s;
|
|
37105
37204
|
try {
|
|
37106
37205
|
s = statSync7(full);
|
|
@@ -37111,7 +37210,7 @@ function listInstalledPlugins() {
|
|
|
37111
37210
|
continue;
|
|
37112
37211
|
if (entry.startsWith("@")) {
|
|
37113
37212
|
for (const child of readdirSync5(full)) {
|
|
37114
|
-
const m = readManifestFromPackageDir(
|
|
37213
|
+
const m = readManifestFromPackageDir(join36(full, child));
|
|
37115
37214
|
if (m)
|
|
37116
37215
|
out.push(m);
|
|
37117
37216
|
}
|
|
@@ -37175,12 +37274,12 @@ async function installPlugin(packageSpec) {
|
|
|
37175
37274
|
if (code !== 0) {
|
|
37176
37275
|
throw new Error(`npm install ${packageSpec} exited with code ${code}.`);
|
|
37177
37276
|
}
|
|
37178
|
-
const nm =
|
|
37179
|
-
if (!
|
|
37277
|
+
const nm = join36(dir, "node_modules");
|
|
37278
|
+
if (!existsSync43(nm)) {
|
|
37180
37279
|
throw new Error(`npm install ran but produced no node_modules under ${dir}.`);
|
|
37181
37280
|
}
|
|
37182
37281
|
const baseName = packageSpec.replace(/@[^@/]+$/, "");
|
|
37183
|
-
const candidatePath = baseName.startsWith("@") ?
|
|
37282
|
+
const candidatePath = baseName.startsWith("@") ? join36(nm, baseName.split("/")[0], baseName.split("/")[1] ?? "") : join36(nm, baseName);
|
|
37184
37283
|
const manifest = readManifestFromPackageDir(candidatePath);
|
|
37185
37284
|
if (!manifest) {
|
|
37186
37285
|
throw new Error(`Installed but could not read plugin manifest at ${candidatePath}.`);
|
|
@@ -37188,26 +37287,26 @@ async function installPlugin(packageSpec) {
|
|
|
37188
37287
|
return { name: manifest.name, entry: manifest.entry };
|
|
37189
37288
|
}
|
|
37190
37289
|
function removePlugin(name) {
|
|
37191
|
-
const nm =
|
|
37192
|
-
if (!
|
|
37290
|
+
const nm = join36(pluginsDir(), "node_modules");
|
|
37291
|
+
if (!existsSync43(nm))
|
|
37193
37292
|
return false;
|
|
37194
|
-
const target = name.startsWith("@") ?
|
|
37195
|
-
if (!
|
|
37293
|
+
const target = name.startsWith("@") ? join36(nm, name.split("/")[0], name.split("/")[1] ?? "") : join36(nm, name);
|
|
37294
|
+
if (!existsSync43(target))
|
|
37196
37295
|
return false;
|
|
37197
37296
|
rmSync3(target, { recursive: true, force: true });
|
|
37198
37297
|
return true;
|
|
37199
37298
|
}
|
|
37200
37299
|
function listInstalledPluginsCombined() {
|
|
37201
37300
|
const direct = listInstalledPlugins();
|
|
37202
|
-
const nm =
|
|
37203
|
-
if (!
|
|
37301
|
+
const nm = join36(pluginsDir(), "node_modules");
|
|
37302
|
+
if (!existsSync43(nm))
|
|
37204
37303
|
return direct;
|
|
37205
37304
|
const seen = new Set(direct.map((p) => p.name));
|
|
37206
37305
|
const out = [...direct];
|
|
37207
37306
|
for (const entry of readdirSync5(nm)) {
|
|
37208
37307
|
if (entry === ".bin" || entry === ".package-lock.json")
|
|
37209
37308
|
continue;
|
|
37210
|
-
const full =
|
|
37309
|
+
const full = join36(nm, entry);
|
|
37211
37310
|
let s;
|
|
37212
37311
|
try {
|
|
37213
37312
|
s = statSync7(full);
|
|
@@ -37218,7 +37317,7 @@ function listInstalledPluginsCombined() {
|
|
|
37218
37317
|
continue;
|
|
37219
37318
|
if (entry.startsWith("@")) {
|
|
37220
37319
|
for (const child of readdirSync5(full)) {
|
|
37221
|
-
const m = readManifestFromPackageDir(
|
|
37320
|
+
const m = readManifestFromPackageDir(join36(full, child));
|
|
37222
37321
|
if (m && !seen.has(m.name)) {
|
|
37223
37322
|
seen.add(m.name);
|
|
37224
37323
|
out.push(m);
|
|
@@ -38828,12 +38927,12 @@ function displayValueFor(field, value) {
|
|
|
38828
38927
|
|
|
38829
38928
|
// src/lib/tui/state-store.ts
|
|
38830
38929
|
import {
|
|
38831
|
-
existsSync as
|
|
38930
|
+
existsSync as existsSync44,
|
|
38832
38931
|
mkdirSync as mkdirSync20,
|
|
38833
38932
|
readFileSync as readFileSync33,
|
|
38834
38933
|
writeFileSync as writeFileSync22
|
|
38835
38934
|
} from "node:fs";
|
|
38836
|
-
import { join as
|
|
38935
|
+
import { join as join37 } from "node:path";
|
|
38837
38936
|
var ALL_TABS = [
|
|
38838
38937
|
"servers",
|
|
38839
38938
|
"projects",
|
|
@@ -38843,7 +38942,7 @@ var ALL_TABS = [
|
|
|
38843
38942
|
"devSessions"
|
|
38844
38943
|
];
|
|
38845
38944
|
function tuiStateFile() {
|
|
38846
|
-
return
|
|
38945
|
+
return join37(configDir(), "tui-state.json");
|
|
38847
38946
|
}
|
|
38848
38947
|
function isTab(v) {
|
|
38849
38948
|
return typeof v === "string" && ALL_TABS.includes(v);
|
|
@@ -38908,7 +39007,7 @@ function sanitizeTuiState(input) {
|
|
|
38908
39007
|
}
|
|
38909
39008
|
function readTuiState() {
|
|
38910
39009
|
const path = tuiStateFile();
|
|
38911
|
-
if (!
|
|
39010
|
+
if (!existsSync44(path))
|
|
38912
39011
|
return {};
|
|
38913
39012
|
let parsed;
|
|
38914
39013
|
try {
|
|
@@ -38920,7 +39019,7 @@ function readTuiState() {
|
|
|
38920
39019
|
}
|
|
38921
39020
|
function writeTuiState(state) {
|
|
38922
39021
|
try {
|
|
38923
|
-
if (!
|
|
39022
|
+
if (!existsSync44(configDir())) {
|
|
38924
39023
|
mkdirSync20(configDir(), { recursive: true, mode: 448 });
|
|
38925
39024
|
}
|
|
38926
39025
|
writeFileSync22(tuiStateFile(), JSON.stringify(state, null, 2), {
|