@mcpcloud/cli 0.14.0 → 0.15.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 -0
- package/dist/index.js +315 -180
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -377,6 +377,7 @@ _Generated from the live command tree by `bun run docs:readme` — do not edit b
|
|
|
377
377
|
| `mcp skills installations <skill>` | List the installation footprint of a skill (which orgs / users installed it) |
|
|
378
378
|
| `mcp skills invoke <skill>` | Run a deployed skill from the terminal. Resolves the skill’s MCP endpoint, auto-discovers its single tool, and calls it. |
|
|
379
379
|
| `mcp skills list` | List skills in an organization |
|
|
380
|
+
| `mcp skills pull <registryArtifactId>` | Download an installed skill as SKILL.md + mcpcloud.json for your coding agent |
|
|
380
381
|
| `mcp skills test-runs` | Inspect and trigger skill sandbox test runs |
|
|
381
382
|
| `mcp skills test-runs get <testRunId>` | Show one skill test run with assertions, trace, and output |
|
|
382
383
|
| `mcp skills test-runs list <skill>` | List sandbox test runs for a skill |
|
package/dist/index.js
CHANGED
|
@@ -4030,7 +4030,7 @@ function configFile() {
|
|
|
4030
4030
|
return join(configDir(), "config.json");
|
|
4031
4031
|
}
|
|
4032
4032
|
var DEFAULT_PROFILE_NAME = "default";
|
|
4033
|
-
var DEFAULT_BASE_URL = "https://
|
|
4033
|
+
var DEFAULT_BASE_URL = "https://api.mcpcloud.sh";
|
|
4034
4034
|
var PRODUCTION_BASE_URL = DEFAULT_BASE_URL;
|
|
4035
4035
|
var DEFAULT_APP_URL = "https://mcpcloud.sh";
|
|
4036
4036
|
|
|
@@ -10981,7 +10981,7 @@ function parseTimeoutMs(value, fallbackMs) {
|
|
|
10981
10981
|
return Math.round(n * 1000);
|
|
10982
10982
|
}
|
|
10983
10983
|
function registerSkillInvokeCommand(skills) {
|
|
10984
|
-
skills.command("invoke <skill>").description("Run a deployed skill from the terminal. Resolves the skill’s MCP endpoint, auto-discovers its single tool, and calls it.").option("--org <organizationId>", "Organization ID (overrides default)").option("--input <json>", "Skill input as inline JSON, `@path/to/input.json`, or `@-` for stdin. Defaults to `{}`.").option("--tool <name>", "Override the auto-discovered tool name (a deployed skill normally exposes exactly one)").option("--timeout <seconds>", "Request timeout in seconds (default 60, max 600)").option("--raw", "Print the raw JSON-RPC `result` envelope").addHelpText("after", [
|
|
10984
|
+
skills.command("invoke <skill>").description("Run a deployed skill from the terminal. Resolves the skill’s MCP endpoint, auto-discovers its single tool, and calls it.").option("--org <organizationId>", "Organization ID (overrides default)").option("--input <json>", "Skill input as inline JSON, `@path/to/input.json`, or `@-` for stdin. Defaults to `{}`.").option("--tool <name>", "Override the auto-discovered tool name (a deployed skill normally exposes exactly one)").option("--timeout <seconds>", "Request timeout in seconds (default 60, max 600)").option("--raw", "Print the raw JSON-RPC `result` envelope").option("--token <token>", "Skill runtime token (skr_…). Prefer --token-stdin.").option("--token-stdin", "Read the skill runtime token from stdin (recommended — keeps it out of argv)").addHelpText("after", [
|
|
10985
10985
|
"",
|
|
10986
10986
|
"Examples:",
|
|
10987
10987
|
` $ mcp skills invoke skill_123 --input '{"topic":"weather"}'`,
|
|
@@ -11017,13 +11017,29 @@ async function runSkillInvoke(skillRef, opts) {
|
|
|
11017
11017
|
if (active.status !== "active") {
|
|
11018
11018
|
printWarn(`Skill deployment is ${active.status}, not active — the call may be refused.`);
|
|
11019
11019
|
}
|
|
11020
|
+
const runtimeToken = opts.tokenStdin ? await readStdin2() : opts.token?.trim() ?? "";
|
|
11021
|
+
if (!runtimeToken) {
|
|
11022
|
+
if (isJsonMode()) {
|
|
11023
|
+
printJson({
|
|
11024
|
+
ok: false,
|
|
11025
|
+
error: "runtime_token_required",
|
|
11026
|
+
hint: "Pass --token-stdin (or --token). Reveal the token on the skill's deployment card."
|
|
11027
|
+
});
|
|
11028
|
+
} else {
|
|
11029
|
+
printError("A skill endpoint requires an Authorization: Bearer token — none was provided.");
|
|
11030
|
+
printWarn(`Reveal it on the skill's deployment card, then: echo "$SKILL_TOKEN" | mcp skills invoke <skill> --token-stdin`);
|
|
11031
|
+
}
|
|
11032
|
+
throw new CliExitError(1);
|
|
11033
|
+
}
|
|
11034
|
+
const headers = { Authorization: `Bearer ${runtimeToken}` };
|
|
11020
11035
|
const timeoutMs = parseTimeoutMs(opts.timeout, 60000);
|
|
11021
|
-
const toolName = opts.tool ?? await discoverSkillTool(active.mcpUrl, timeoutMs);
|
|
11036
|
+
const toolName = opts.tool ?? await discoverSkillTool(active.mcpUrl, timeoutMs, headers);
|
|
11022
11037
|
const result = await invokeMcpTool({
|
|
11023
11038
|
url: active.mcpUrl,
|
|
11024
11039
|
toolName,
|
|
11025
11040
|
toolArguments: parsedInput.ok ? parsedInput.value : {},
|
|
11026
|
-
timeoutMs
|
|
11041
|
+
timeoutMs,
|
|
11042
|
+
headers
|
|
11027
11043
|
});
|
|
11028
11044
|
if (isJsonMode()) {
|
|
11029
11045
|
printJson({
|
|
@@ -11057,8 +11073,15 @@ async function runSkillInvoke(skillRef, opts) {
|
|
|
11057
11073
|
printWarn(`Skill reported isError=true. Inspect ${c.bold("--json")} or ${c.bold("--raw")} for the full envelope.`);
|
|
11058
11074
|
}
|
|
11059
11075
|
}
|
|
11060
|
-
async function
|
|
11061
|
-
const
|
|
11076
|
+
async function readStdin2() {
|
|
11077
|
+
const chunks = [];
|
|
11078
|
+
for await (const chunk of process.stdin) {
|
|
11079
|
+
chunks.push(Buffer.from(chunk));
|
|
11080
|
+
}
|
|
11081
|
+
return Buffer.concat(chunks).toString("utf8").trim();
|
|
11082
|
+
}
|
|
11083
|
+
async function discoverSkillTool(mcpUrl, timeoutMs, headers) {
|
|
11084
|
+
const listed = await listMcpTools({ url: mcpUrl, timeoutMs, headers });
|
|
11062
11085
|
if (!listed.ok) {
|
|
11063
11086
|
const detail = listed.reason === "rpc-error" ? listed.error.message : `${listed.status > 0 ? `HTTP ${listed.status}` : "network error"}: ${listed.message}`;
|
|
11064
11087
|
printError(`Could not list the skill's tools to auto-discover the entry point (${detail}). Pass --tool <name> to call it directly.`);
|
|
@@ -11104,15 +11127,98 @@ function invokeResultToJson(result) {
|
|
|
11104
11127
|
};
|
|
11105
11128
|
}
|
|
11106
11129
|
|
|
11130
|
+
// src/commands/skills-pull.ts
|
|
11131
|
+
import { mkdirSync as mkdirSync8, writeFileSync as writeFileSync7 } from "node:fs";
|
|
11132
|
+
import { dirname as dirname6, isAbsolute as isAbsolute3, join as join11, resolve as resolve7 } from "node:path";
|
|
11133
|
+
function formatBytes2(bytes) {
|
|
11134
|
+
if (bytes < 1024)
|
|
11135
|
+
return `${bytes} B`;
|
|
11136
|
+
return `${(bytes / 1024).toFixed(1)} KB`;
|
|
11137
|
+
}
|
|
11138
|
+
function assertSafeRelativePath2(path) {
|
|
11139
|
+
if (isAbsolute3(path) || path.split(/[\\/]/).includes("..")) {
|
|
11140
|
+
throw new Error(`Refusing to write unsafe package path: ${path}`);
|
|
11141
|
+
}
|
|
11142
|
+
}
|
|
11143
|
+
function registerSkillPullCommand(skills) {
|
|
11144
|
+
skills.command("pull <registryArtifactId>").description("Download an installed skill as SKILL.md + mcpcloud.json for your coding agent").option("--org <organizationId>", "Organization ID").option("--output <dir>", "Write the package files to a directory (default: ./<slug>)").option("--skill-version <semver>", "Published version (defaults to the latest)").addHelpText("after", [
|
|
11145
|
+
"",
|
|
11146
|
+
"Examples:",
|
|
11147
|
+
" # Pull a skill you installed from the marketplace:",
|
|
11148
|
+
" $ mcp skills pull p179hst... --output ./skills/ship-an-mcp-server",
|
|
11149
|
+
"",
|
|
11150
|
+
" # Then point your agent at the servers it needs:",
|
|
11151
|
+
" $ cat ./skills/ship-an-mcp-server/mcpcloud.json"
|
|
11152
|
+
].join(`
|
|
11153
|
+
`)).action(runAction(async (registryArtifactId, opts) => {
|
|
11154
|
+
const organizationId = await resolveOrgId(opts.org);
|
|
11155
|
+
const result = await api.post("/api/v1/skill/package", {
|
|
11156
|
+
organizationId,
|
|
11157
|
+
registryArtifactId,
|
|
11158
|
+
...opts.skillVersion ? { version: opts.skillVersion } : {}
|
|
11159
|
+
});
|
|
11160
|
+
const dir = resolve7(opts.output ?? `./${result.skill.slug}`);
|
|
11161
|
+
for (const file of result.files) {
|
|
11162
|
+
assertSafeRelativePath2(file.path);
|
|
11163
|
+
const full = join11(dir, file.path);
|
|
11164
|
+
mkdirSync8(dirname6(full), { recursive: true });
|
|
11165
|
+
writeFileSync7(full, file.content);
|
|
11166
|
+
}
|
|
11167
|
+
if (isJsonMode()) {
|
|
11168
|
+
printJson({
|
|
11169
|
+
skill: result.skill,
|
|
11170
|
+
fileCount: result.fileCount,
|
|
11171
|
+
byteSize: result.byteSize,
|
|
11172
|
+
dependencies: result.dependencies,
|
|
11173
|
+
output: dir
|
|
11174
|
+
});
|
|
11175
|
+
return;
|
|
11176
|
+
}
|
|
11177
|
+
printSuccess(`Pulled ${result.skill.name} v${result.skill.version} (${result.fileCount} files, ${formatBytes2(result.byteSize)}) to ${dir}.`);
|
|
11178
|
+
const missing = result.dependencies.filter((entry) => !entry.installed);
|
|
11179
|
+
if (result.dependencies.length === 0) {
|
|
11180
|
+
printKeyValue({
|
|
11181
|
+
Next: `Copy ${join11(dir, "SKILL.md")} into the skills directory your agent reads.`
|
|
11182
|
+
});
|
|
11183
|
+
return;
|
|
11184
|
+
}
|
|
11185
|
+
printKeyValue({
|
|
11186
|
+
Next: `Copy ${join11(dir, "SKILL.md")} into the skills directory your agent reads.`,
|
|
11187
|
+
Servers: result.dependencies.map((entry) => `${entry.name}${entry.installed ? "" : " (not installed)"}`).join(", ")
|
|
11188
|
+
});
|
|
11189
|
+
if (missing.length > 0) {
|
|
11190
|
+
printKeyValue({
|
|
11191
|
+
"Heads up": `Install ${missing.map((entry) => entry.name).join(", ")} before running this skill.`
|
|
11192
|
+
});
|
|
11193
|
+
}
|
|
11194
|
+
}));
|
|
11195
|
+
}
|
|
11196
|
+
|
|
11107
11197
|
// src/commands/skills.ts
|
|
11108
|
-
async function
|
|
11109
|
-
|
|
11110
|
-
|
|
11198
|
+
async function readStdin3() {
|
|
11199
|
+
const chunks = [];
|
|
11200
|
+
for await (const chunk of process.stdin) {
|
|
11201
|
+
chunks.push(Buffer.from(chunk));
|
|
11202
|
+
}
|
|
11203
|
+
return Buffer.concat(chunks).toString("utf8").trim();
|
|
11204
|
+
}
|
|
11205
|
+
async function runClaudeMcpAdd(connectionName, mcpUrl, bearerToken) {
|
|
11206
|
+
return new Promise((resolve8) => {
|
|
11207
|
+
const child = spawn3("claude", [
|
|
11208
|
+
"mcp",
|
|
11209
|
+
"add",
|
|
11210
|
+
"--transport",
|
|
11211
|
+
"http",
|
|
11212
|
+
connectionName,
|
|
11213
|
+
mcpUrl,
|
|
11214
|
+
"--header",
|
|
11215
|
+
`Authorization: Bearer ${bearerToken}`
|
|
11216
|
+
], {
|
|
11111
11217
|
stdio: "inherit",
|
|
11112
11218
|
shell: false
|
|
11113
11219
|
});
|
|
11114
|
-
child.on("error", () =>
|
|
11115
|
-
child.on("exit", (code) =>
|
|
11220
|
+
child.on("error", () => resolve8(127));
|
|
11221
|
+
child.on("exit", (code) => resolve8(code ?? 1));
|
|
11116
11222
|
});
|
|
11117
11223
|
}
|
|
11118
11224
|
function registerSkillCommands(program2) {
|
|
@@ -11120,6 +11226,7 @@ function registerSkillCommands(program2) {
|
|
|
11120
11226
|
registerSkillMutationCommands(skills);
|
|
11121
11227
|
registerSkillTestCommands(skills);
|
|
11122
11228
|
registerSkillInvokeCommand(skills);
|
|
11229
|
+
registerSkillPullCommand(skills);
|
|
11123
11230
|
skills.command("list").description("List skills in an organization").option("--org <organizationId>", "Organization ID").option("--project <project>", "Filter by project (id or name)").option("--limit <n>", "Maximum results (default 25)", parsePositiveIntOption("limit"), "25").addHelpText("after", [
|
|
11124
11231
|
"",
|
|
11125
11232
|
"Examples:",
|
|
@@ -11181,7 +11288,8 @@ function registerSkillCommands(program2) {
|
|
|
11181
11288
|
"mcp endpoint": s.activeDeployment?.mcpUrl ?? "—"
|
|
11182
11289
|
});
|
|
11183
11290
|
}));
|
|
11184
|
-
skills.command("connect <skill>").description("Print (or apply) the MCP configuration that connects this skill to your coding agent").option("--org <organizationId>", "Organization ID").option("--agent <agent>", `Agent preset: ${AGENT_KEYS.join(", ")}`, "claude-code").option("--name <name>", "Override the connection name shown in the agent (defaults to the skill slug)").option("--apply", 'For claude-code: invoke "claude mcp add" automatically. Other agents print only.').action(runAction(async (skillRef, opts) => {
|
|
11291
|
+
skills.command("connect <skill>").description("Print (or apply) the MCP configuration that connects this skill to your coding agent").option("--org <organizationId>", "Organization ID").option("--agent <agent>", `Agent preset: ${AGENT_KEYS.join(", ")}`, "claude-code").option("--name <name>", "Override the connection name shown in the agent (defaults to the skill slug)").option("--apply", 'For claude-code: invoke "claude mcp add" automatically. Other agents print only.').option("--token <token>", "Skill runtime token (skr_…) to inline into --apply. Prefer --token-stdin.").option("--token-stdin", "Read the skill runtime token from stdin (recommended — keeps it out of argv)").action(runAction(async (skillRef, opts) => {
|
|
11292
|
+
const runtimeToken = opts.tokenStdin ? await readStdin3() : opts.token?.trim() ?? "";
|
|
11185
11293
|
if (!isAgentKey(opts.agent)) {
|
|
11186
11294
|
printError(`Unknown --agent '${opts.agent}'. Valid values: ${AGENT_KEYS.join(", ")}.`);
|
|
11187
11295
|
throw new CliExitError(1);
|
|
@@ -11227,10 +11335,23 @@ function registerSkillCommands(program2) {
|
|
|
11227
11335
|
}
|
|
11228
11336
|
throw new CliExitError(1);
|
|
11229
11337
|
}
|
|
11338
|
+
if (!runtimeToken) {
|
|
11339
|
+
if (isJsonMode()) {
|
|
11340
|
+
printJson({
|
|
11341
|
+
ok: false,
|
|
11342
|
+
error: "runtime_token_required",
|
|
11343
|
+
hint: "Pass --token-stdin (or --token). Reveal the token on the skill's deployment card."
|
|
11344
|
+
});
|
|
11345
|
+
} else {
|
|
11346
|
+
printError("A skill endpoint requires an Authorization: Bearer token, so --apply needs one too.");
|
|
11347
|
+
printInfo(`Reveal it on the skill's deployment card, then: echo "$SKILL_TOKEN" | mcp skills connect <skill> --apply --token-stdin`);
|
|
11348
|
+
}
|
|
11349
|
+
throw new CliExitError(1);
|
|
11350
|
+
}
|
|
11230
11351
|
if (!isJsonMode()) {
|
|
11231
|
-
printInfo(`Applying via "claude mcp add --transport http ${connectionName} ${deployment.mcpUrl}"…`);
|
|
11352
|
+
printInfo(`Applying via "claude mcp add --transport http ${connectionName} ${deployment.mcpUrl} --header …"…`);
|
|
11232
11353
|
}
|
|
11233
|
-
const code = await runClaudeMcpAdd(connectionName, deployment.mcpUrl);
|
|
11354
|
+
const code = await runClaudeMcpAdd(connectionName, deployment.mcpUrl, runtimeToken);
|
|
11234
11355
|
if (code === 127) {
|
|
11235
11356
|
if (isJsonMode()) {
|
|
11236
11357
|
printJson({
|
|
@@ -11286,7 +11407,10 @@ function registerSkillCommands(program2) {
|
|
|
11286
11407
|
agent: preset.key,
|
|
11287
11408
|
connectionName,
|
|
11288
11409
|
location: preset.location,
|
|
11289
|
-
snippet: preset.snippet
|
|
11410
|
+
snippet: preset.snippet,
|
|
11411
|
+
requiresAuthHeader: true,
|
|
11412
|
+
authHeader: "Authorization",
|
|
11413
|
+
authScheme: "Bearer"
|
|
11290
11414
|
});
|
|
11291
11415
|
return;
|
|
11292
11416
|
}
|
|
@@ -11298,6 +11422,12 @@ function registerSkillCommands(program2) {
|
|
|
11298
11422
|
printInfo(`Add this to ${preset.location}`);
|
|
11299
11423
|
printInfo("");
|
|
11300
11424
|
printInfo(preset.snippet);
|
|
11425
|
+
printInfo("");
|
|
11426
|
+
printWarn("This endpoint requires an Authorization: Bearer <skill runtime token> header — the snippet above does not include one.");
|
|
11427
|
+
printInfo("Reveal the token on the skill's deployment card, then add it to your client's header config.");
|
|
11428
|
+
if (agent === "claude-code") {
|
|
11429
|
+
printInfo(` claude mcp add --transport http ${connectionName} ${deployment.mcpUrl} --header "Authorization: Bearer <token>"`);
|
|
11430
|
+
}
|
|
11301
11431
|
if (preset.applyHint) {
|
|
11302
11432
|
printInfo("");
|
|
11303
11433
|
printInfo(preset.applyHint);
|
|
@@ -11780,9 +11910,9 @@ function registerDomainCommands(program2) {
|
|
|
11780
11910
|
|
|
11781
11911
|
// src/commands/config.ts
|
|
11782
11912
|
import { homedir as homedir2 } from "node:os";
|
|
11783
|
-
import { join as
|
|
11913
|
+
import { join as join12 } from "node:path";
|
|
11784
11914
|
function configFilePath() {
|
|
11785
|
-
return
|
|
11915
|
+
return join12(homedir2(), ".mcpcloud", "config.json");
|
|
11786
11916
|
}
|
|
11787
11917
|
function previewKey2(key) {
|
|
11788
11918
|
if (!key)
|
|
@@ -12028,34 +12158,34 @@ function registerConfigCommands(program2) {
|
|
|
12028
12158
|
|
|
12029
12159
|
// src/commands/dev.ts
|
|
12030
12160
|
import { existsSync as existsSync33 } from "node:fs";
|
|
12031
|
-
import { isAbsolute as
|
|
12161
|
+
import { isAbsolute as isAbsolute4, relative as relative7, resolve as resolve9 } from "node:path";
|
|
12032
12162
|
|
|
12033
12163
|
// src/lib/dev/sessions.ts
|
|
12034
12164
|
import {
|
|
12035
12165
|
existsSync as existsSync14,
|
|
12036
|
-
mkdirSync as
|
|
12166
|
+
mkdirSync as mkdirSync9,
|
|
12037
12167
|
readFileSync as readFileSync12,
|
|
12038
12168
|
readdirSync as readdirSync2,
|
|
12039
12169
|
unlinkSync,
|
|
12040
|
-
writeFileSync as
|
|
12170
|
+
writeFileSync as writeFileSync8
|
|
12041
12171
|
} from "node:fs";
|
|
12042
12172
|
import { homedir as homedir3 } from "node:os";
|
|
12043
|
-
import { join as
|
|
12173
|
+
import { join as join13 } from "node:path";
|
|
12044
12174
|
var SESSIONS_DIR_NAME = "dev-sessions";
|
|
12045
12175
|
function sessionsDir() {
|
|
12046
|
-
return
|
|
12176
|
+
return join13(homedir3(), ".mcpcloud", SESSIONS_DIR_NAME);
|
|
12047
12177
|
}
|
|
12048
12178
|
function sessionFile(pid) {
|
|
12049
|
-
return
|
|
12179
|
+
return join13(sessionsDir(), `${pid}.json`);
|
|
12050
12180
|
}
|
|
12051
12181
|
function ensureDir() {
|
|
12052
12182
|
const dir = sessionsDir();
|
|
12053
12183
|
if (!existsSync14(dir))
|
|
12054
|
-
|
|
12184
|
+
mkdirSync9(dir, { recursive: true, mode: 448 });
|
|
12055
12185
|
}
|
|
12056
12186
|
function recordSession(record) {
|
|
12057
12187
|
ensureDir();
|
|
12058
|
-
|
|
12188
|
+
writeFileSync8(sessionFile(record.pid), JSON.stringify(record, null, 2), {
|
|
12059
12189
|
encoding: "utf-8",
|
|
12060
12190
|
mode: 384
|
|
12061
12191
|
});
|
|
@@ -12076,7 +12206,7 @@ function listSessions() {
|
|
|
12076
12206
|
for (const entry of readdirSync2(dir)) {
|
|
12077
12207
|
if (!entry.endsWith(".json"))
|
|
12078
12208
|
continue;
|
|
12079
|
-
const path =
|
|
12209
|
+
const path = join13(dir, entry);
|
|
12080
12210
|
try {
|
|
12081
12211
|
const parsed = JSON.parse(readFileSync12(path, "utf-8"));
|
|
12082
12212
|
if (typeof parsed.pid !== "number") {
|
|
@@ -12271,27 +12401,27 @@ function invokeResultToJson2(result) {
|
|
|
12271
12401
|
import {
|
|
12272
12402
|
appendFileSync as appendFileSync2,
|
|
12273
12403
|
existsSync as existsSync15,
|
|
12274
|
-
mkdirSync as
|
|
12404
|
+
mkdirSync as mkdirSync10,
|
|
12275
12405
|
readFileSync as readFileSync13,
|
|
12276
12406
|
readdirSync as readdirSync3,
|
|
12277
12407
|
renameSync,
|
|
12278
12408
|
statSync as statSync2
|
|
12279
12409
|
} from "node:fs";
|
|
12280
|
-
import { join as
|
|
12410
|
+
import { join as join14 } from "node:path";
|
|
12281
12411
|
var INSPECTOR_DIRNAME = "inspector";
|
|
12282
12412
|
var ACTIVE_FILE = "calls.ndjson";
|
|
12283
12413
|
var ROTATED_PREFIX = "calls.";
|
|
12284
12414
|
var ROTATED_SUFFIX = ".ndjson";
|
|
12285
12415
|
var ROTATION_LIMIT_BYTES = 50 * 1024 * 1024;
|
|
12286
12416
|
function inspectorDir(cwd) {
|
|
12287
|
-
return
|
|
12417
|
+
return join14(devRoot(cwd), INSPECTOR_DIRNAME);
|
|
12288
12418
|
}
|
|
12289
12419
|
function ensureInspectorDir(dir) {
|
|
12290
12420
|
if (!existsSync15(dir))
|
|
12291
|
-
|
|
12421
|
+
mkdirSync10(dir, { recursive: true });
|
|
12292
12422
|
}
|
|
12293
12423
|
function activeFilePath(dir) {
|
|
12294
|
-
return
|
|
12424
|
+
return join14(dir, ACTIVE_FILE);
|
|
12295
12425
|
}
|
|
12296
12426
|
function isRotatedName(name) {
|
|
12297
12427
|
return name !== ACTIVE_FILE && name.startsWith(ROTATED_PREFIX) && name.endsWith(ROTATED_SUFFIX);
|
|
@@ -12301,7 +12431,7 @@ function listRotatedFiles(dir) {
|
|
|
12301
12431
|
return [];
|
|
12302
12432
|
const rotated = readdirSync3(dir).filter(isRotatedName);
|
|
12303
12433
|
rotated.sort();
|
|
12304
|
-
return rotated.map((n) =>
|
|
12434
|
+
return rotated.map((n) => join14(dir, n));
|
|
12305
12435
|
}
|
|
12306
12436
|
function parseLines(text) {
|
|
12307
12437
|
if (!text)
|
|
@@ -12526,7 +12656,7 @@ import {
|
|
|
12526
12656
|
closeSync,
|
|
12527
12657
|
statSync as statSync3
|
|
12528
12658
|
} from "node:fs";
|
|
12529
|
-
import { join as
|
|
12659
|
+
import { join as join15 } from "node:path";
|
|
12530
12660
|
var DEFAULT_INTERVAL_MS = 250;
|
|
12531
12661
|
var MAX_READ_CHUNK = 64 * 1024;
|
|
12532
12662
|
function registerDevTailCommand(dev) {
|
|
@@ -12535,7 +12665,7 @@ function registerDevTailCommand(dev) {
|
|
|
12535
12665
|
async function runDevTail(opts) {
|
|
12536
12666
|
const cwd = process.cwd();
|
|
12537
12667
|
const dir = inspectorDir(cwd);
|
|
12538
|
-
const activePath =
|
|
12668
|
+
const activePath = join15(dir, ACTIVE_FILE);
|
|
12539
12669
|
const intervalMs = parseInterval(opts.intervalMs);
|
|
12540
12670
|
if (!existsSync16(dir)) {
|
|
12541
12671
|
printInfo(`No inspector history yet at ${dir}. Run \`mcp dev\` to start capturing.`);
|
|
@@ -12643,7 +12773,7 @@ function emitLines(text, filter) {
|
|
|
12643
12773
|
}
|
|
12644
12774
|
}
|
|
12645
12775
|
function sleep(ms) {
|
|
12646
|
-
return new Promise((
|
|
12776
|
+
return new Promise((resolve8) => setTimeout(resolve8, ms));
|
|
12647
12777
|
}
|
|
12648
12778
|
|
|
12649
12779
|
// src/lib/dev/bootstrap.ts
|
|
@@ -12761,12 +12891,12 @@ async function runInteractiveBootstrap() {
|
|
|
12761
12891
|
// src/lib/dev/bundle-sync.ts
|
|
12762
12892
|
import {
|
|
12763
12893
|
existsSync as existsSync17,
|
|
12764
|
-
mkdirSync as
|
|
12894
|
+
mkdirSync as mkdirSync11,
|
|
12765
12895
|
readFileSync as readFileSync14,
|
|
12766
12896
|
rmSync as rmSync2,
|
|
12767
|
-
writeFileSync as
|
|
12897
|
+
writeFileSync as writeFileSync9
|
|
12768
12898
|
} from "node:fs";
|
|
12769
|
-
import { dirname as
|
|
12899
|
+
import { dirname as dirname7, join as join16 } from "node:path";
|
|
12770
12900
|
async function resolveServerProject(args) {
|
|
12771
12901
|
const data = await api.get("/api/v1/server", {
|
|
12772
12902
|
organizationId: args.organizationId,
|
|
@@ -12828,7 +12958,7 @@ async function fetchBundle(args) {
|
|
|
12828
12958
|
}
|
|
12829
12959
|
function materializeBundle(destDir, bundle, options = {}) {
|
|
12830
12960
|
if (!existsSync17(destDir)) {
|
|
12831
|
-
|
|
12961
|
+
mkdirSync11(destDir, { recursive: true });
|
|
12832
12962
|
}
|
|
12833
12963
|
const preserve = options.preservePaths;
|
|
12834
12964
|
const kept = new Set;
|
|
@@ -12843,9 +12973,9 @@ function materializeBundle(destDir, bundle, options = {}) {
|
|
|
12843
12973
|
preservedCount += 1;
|
|
12844
12974
|
continue;
|
|
12845
12975
|
}
|
|
12846
|
-
const target =
|
|
12847
|
-
|
|
12848
|
-
|
|
12976
|
+
const target = join16(destDir, safePath);
|
|
12977
|
+
mkdirSync11(dirname7(target), { recursive: true });
|
|
12978
|
+
writeFileSync9(target, file.content, "utf-8");
|
|
12849
12979
|
writtenCount += 1;
|
|
12850
12980
|
}
|
|
12851
12981
|
let removed = 0;
|
|
@@ -12873,7 +13003,7 @@ function pruneStaleFiles(rootDir, currentDir, kept) {
|
|
|
12873
13003
|
const { relative: relative6 } = __require("node:path");
|
|
12874
13004
|
let removed = 0;
|
|
12875
13005
|
for (const entry of readdirSync4(currentDir)) {
|
|
12876
|
-
const abs =
|
|
13006
|
+
const abs = join16(currentDir, entry);
|
|
12877
13007
|
const stat = statSync4(abs);
|
|
12878
13008
|
if (stat.isDirectory()) {
|
|
12879
13009
|
removed += pruneStaleFiles(rootDir, abs, kept);
|
|
@@ -12940,7 +13070,7 @@ function startGitPullPoll(args) {
|
|
|
12940
13070
|
// src/lib/dev/editor.ts
|
|
12941
13071
|
import { spawn as spawn4 } from "node:child_process";
|
|
12942
13072
|
import { existsSync as existsSync18, statSync as statSync4 } from "node:fs";
|
|
12943
|
-
import { delimiter as delimiter2, join as
|
|
13073
|
+
import { delimiter as delimiter2, join as join17 } from "node:path";
|
|
12944
13074
|
import { platform as platform3 } from "node:os";
|
|
12945
13075
|
var TARGET_LABEL = {
|
|
12946
13076
|
tools: "tool metadata",
|
|
@@ -12976,7 +13106,7 @@ function findOnPath2(command) {
|
|
|
12976
13106
|
if (!dir)
|
|
12977
13107
|
continue;
|
|
12978
13108
|
for (const ext of exts) {
|
|
12979
|
-
const candidate =
|
|
13109
|
+
const candidate = join17(dir, command + ext);
|
|
12980
13110
|
if (existsSync18(candidate) && isExecutable(candidate))
|
|
12981
13111
|
return candidate;
|
|
12982
13112
|
}
|
|
@@ -13258,7 +13388,7 @@ function parseOpenChoice(raw) {
|
|
|
13258
13388
|
|
|
13259
13389
|
// src/lib/dev/file-watcher.ts
|
|
13260
13390
|
import { existsSync as existsSync19, statSync as statSync5, watch as fsWatch2 } from "node:fs";
|
|
13261
|
-
import { join as
|
|
13391
|
+
import { join as join18 } from "node:path";
|
|
13262
13392
|
var DEFAULT_IGNORE = ["node_modules", ".git", "_mcpsh_host.mjs"];
|
|
13263
13393
|
function watchDir(options) {
|
|
13264
13394
|
if (!existsSync19(options.rootDir)) {
|
|
@@ -13297,7 +13427,7 @@ function watchDir(options) {
|
|
|
13297
13427
|
for (const entry of readdirSync4(options.rootDir)) {
|
|
13298
13428
|
if (ignore.has(entry))
|
|
13299
13429
|
continue;
|
|
13300
|
-
const sub =
|
|
13430
|
+
const sub = join18(options.rootDir, entry);
|
|
13301
13431
|
try {
|
|
13302
13432
|
const stat = statSync5(sub);
|
|
13303
13433
|
if (!stat.isDirectory())
|
|
@@ -13564,7 +13694,7 @@ async function handleOne2(args) {
|
|
|
13564
13694
|
// src/lib/dev/local-runtime.ts
|
|
13565
13695
|
import { spawn as spawn5 } from "node:child_process";
|
|
13566
13696
|
import { existsSync as existsSync22 } from "node:fs";
|
|
13567
|
-
import { join as
|
|
13697
|
+
import { join as join19 } from "node:path";
|
|
13568
13698
|
function detectRuntime(preferred = "auto") {
|
|
13569
13699
|
if (preferred === "bun" || preferred === "node")
|
|
13570
13700
|
return preferred;
|
|
@@ -13601,52 +13731,52 @@ function startRuntime(options) {
|
|
|
13601
13731
|
if (child.exitCode !== null)
|
|
13602
13732
|
return;
|
|
13603
13733
|
child.kill("SIGTERM");
|
|
13604
|
-
await new Promise((
|
|
13734
|
+
await new Promise((resolve8) => {
|
|
13605
13735
|
const timer = setTimeout(() => {
|
|
13606
13736
|
if (child.exitCode === null)
|
|
13607
13737
|
child.kill("SIGKILL");
|
|
13608
|
-
|
|
13738
|
+
resolve8();
|
|
13609
13739
|
}, 3000);
|
|
13610
13740
|
child.once("exit", () => {
|
|
13611
13741
|
clearTimeout(timer);
|
|
13612
|
-
|
|
13742
|
+
resolve8();
|
|
13613
13743
|
});
|
|
13614
13744
|
});
|
|
13615
13745
|
}
|
|
13616
13746
|
};
|
|
13617
13747
|
}
|
|
13618
13748
|
async function installDependencies(options) {
|
|
13619
|
-
const pkgPath =
|
|
13749
|
+
const pkgPath = join19(options.serverDir, "package.json");
|
|
13620
13750
|
if (!existsSync22(pkgPath))
|
|
13621
13751
|
return { ran: false, exitCode: null };
|
|
13622
|
-
const nodeModules =
|
|
13752
|
+
const nodeModules = join19(options.serverDir, "node_modules");
|
|
13623
13753
|
if (options.skipIfPresent !== false && existsSync22(nodeModules)) {
|
|
13624
13754
|
return { ran: false, exitCode: 0 };
|
|
13625
13755
|
}
|
|
13626
13756
|
options.onStep?.("Installing dependencies (bun install)…");
|
|
13627
|
-
return await new Promise((
|
|
13757
|
+
return await new Promise((resolve8) => {
|
|
13628
13758
|
const child = spawn5("bun", ["install", "--silent"], {
|
|
13629
13759
|
cwd: options.serverDir,
|
|
13630
13760
|
stdio: "inherit"
|
|
13631
13761
|
});
|
|
13632
|
-
child.on("error", () =>
|
|
13633
|
-
child.on("exit", (code) =>
|
|
13762
|
+
child.on("error", () => resolve8({ ran: true, exitCode: 127 }));
|
|
13763
|
+
child.on("exit", (code) => resolve8({ ran: true, exitCode: code }));
|
|
13634
13764
|
});
|
|
13635
13765
|
}
|
|
13636
13766
|
|
|
13637
13767
|
// src/lib/dev/prepare.ts
|
|
13638
|
-
import { existsSync as existsSync26, writeFileSync as
|
|
13639
|
-
import { join as
|
|
13768
|
+
import { existsSync as existsSync26, writeFileSync as writeFileSync13 } from "node:fs";
|
|
13769
|
+
import { join as join23, relative as relative6 } from "node:path";
|
|
13640
13770
|
|
|
13641
13771
|
// src/lib/dev/git-clone.ts
|
|
13642
13772
|
import { spawnSync } from "node:child_process";
|
|
13643
13773
|
import {
|
|
13644
13774
|
existsSync as existsSync23,
|
|
13645
|
-
mkdirSync as
|
|
13775
|
+
mkdirSync as mkdirSync12,
|
|
13646
13776
|
readFileSync as readFileSync15,
|
|
13647
|
-
writeFileSync as
|
|
13777
|
+
writeFileSync as writeFileSync10
|
|
13648
13778
|
} from "node:fs";
|
|
13649
|
-
import { dirname as
|
|
13779
|
+
import { dirname as dirname8, join as join20 } from "node:path";
|
|
13650
13780
|
|
|
13651
13781
|
class GitNotAvailableError extends Error {
|
|
13652
13782
|
constructor() {
|
|
@@ -13719,21 +13849,21 @@ function isGitAvailable() {
|
|
|
13719
13849
|
}
|
|
13720
13850
|
}
|
|
13721
13851
|
function applyLocalExcludes(repoDir) {
|
|
13722
|
-
const excludePath =
|
|
13852
|
+
const excludePath = join20(repoDir, ".git", "info", "exclude");
|
|
13723
13853
|
const existing = existsSync23(excludePath) ? readFileSync15(excludePath, "utf-8") : "";
|
|
13724
13854
|
const next = mergeLocalExcludes(existing);
|
|
13725
13855
|
if (next === null)
|
|
13726
13856
|
return;
|
|
13727
|
-
if (!existsSync23(
|
|
13728
|
-
|
|
13857
|
+
if (!existsSync23(dirname8(excludePath))) {
|
|
13858
|
+
mkdirSync12(dirname8(excludePath), { recursive: true });
|
|
13729
13859
|
}
|
|
13730
|
-
|
|
13860
|
+
writeFileSync10(excludePath, next, "utf-8");
|
|
13731
13861
|
}
|
|
13732
13862
|
function ensureClone(opts) {
|
|
13733
13863
|
if (!isGitAvailable()) {
|
|
13734
13864
|
throw new GitNotAvailableError;
|
|
13735
13865
|
}
|
|
13736
|
-
if (existsSync23(
|
|
13866
|
+
if (existsSync23(join20(opts.repoDir, ".git"))) {
|
|
13737
13867
|
opts.onStep?.("Refreshing existing clone (git fetch)…");
|
|
13738
13868
|
runGit(gitFetchArgs(opts.branch), opts.repoDir);
|
|
13739
13869
|
applyLocalExcludes(opts.repoDir);
|
|
@@ -13749,12 +13879,12 @@ function ensureClone(opts) {
|
|
|
13749
13879
|
}
|
|
13750
13880
|
|
|
13751
13881
|
// src/lib/dev/host-runtime.ts
|
|
13752
|
-
import { existsSync as existsSync25, mkdirSync as
|
|
13753
|
-
import { dirname as
|
|
13882
|
+
import { existsSync as existsSync25, mkdirSync as mkdirSync14, writeFileSync as writeFileSync12 } from "node:fs";
|
|
13883
|
+
import { dirname as dirname9, join as join22 } from "node:path";
|
|
13754
13884
|
|
|
13755
13885
|
// src/lib/dev/inspector-module.ts
|
|
13756
|
-
import { existsSync as existsSync24, mkdirSync as
|
|
13757
|
-
import { join as
|
|
13886
|
+
import { existsSync as existsSync24, mkdirSync as mkdirSync13, writeFileSync as writeFileSync11 } from "node:fs";
|
|
13887
|
+
import { join as join21 } from "node:path";
|
|
13758
13888
|
|
|
13759
13889
|
// src/lib/dev/inspector-assets.ts
|
|
13760
13890
|
var INSPECTOR_HTML = `<!doctype html>
|
|
@@ -28890,9 +29020,9 @@ function buildInspectorModule() {
|
|
|
28890
29020
|
}
|
|
28891
29021
|
function writeInspectorModule(serverDir2) {
|
|
28892
29022
|
if (!existsSync24(serverDir2))
|
|
28893
|
-
|
|
28894
|
-
const target =
|
|
28895
|
-
|
|
29023
|
+
mkdirSync13(serverDir2, { recursive: true });
|
|
29024
|
+
const target = join21(serverDir2, INSPECTOR_FILE_NAME);
|
|
29025
|
+
writeFileSync11(target, buildInspectorModule(), "utf-8");
|
|
28896
29026
|
return target;
|
|
28897
29027
|
}
|
|
28898
29028
|
|
|
@@ -29072,10 +29202,10 @@ function buildHostScript(options) {
|
|
|
29072
29202
|
}
|
|
29073
29203
|
function writeHostScript(serverDir2, options) {
|
|
29074
29204
|
if (!existsSync25(serverDir2))
|
|
29075
|
-
|
|
29076
|
-
const target =
|
|
29077
|
-
|
|
29078
|
-
|
|
29205
|
+
mkdirSync14(serverDir2, { recursive: true });
|
|
29206
|
+
const target = join22(serverDir2, HOST_FILE_NAME);
|
|
29207
|
+
mkdirSync14(dirname9(target), { recursive: true });
|
|
29208
|
+
writeFileSync12(target, buildHostScript(options), "utf-8");
|
|
29079
29209
|
if (options.inspector) {
|
|
29080
29210
|
writeInspectorModule(serverDir2);
|
|
29081
29211
|
}
|
|
@@ -29108,7 +29238,7 @@ async function prepareDev(opts) {
|
|
|
29108
29238
|
projectId = projectId ?? gitLink.projectId;
|
|
29109
29239
|
serverName = `${gitLink.owner}/${gitLink.name}`;
|
|
29110
29240
|
repoDir = gitCloneDir(cwd, gitLink.owner, gitLink.name);
|
|
29111
|
-
dest = gitLink.pathPrefix ?
|
|
29241
|
+
dest = gitLink.pathPrefix ? join23(repoDir, gitLink.pathPrefix) : repoDir;
|
|
29112
29242
|
printStep(`Git-linked server — cloning ${gitLink.owner}/${gitLink.name}@${gitLink.branch}…`);
|
|
29113
29243
|
try {
|
|
29114
29244
|
const result = ensureClone({
|
|
@@ -29129,7 +29259,7 @@ async function prepareDev(opts) {
|
|
|
29129
29259
|
process.exit(1);
|
|
29130
29260
|
}
|
|
29131
29261
|
if (!existsSync26(env)) {
|
|
29132
|
-
|
|
29262
|
+
writeFileSync13(env, `{}
|
|
29133
29263
|
`, "utf-8");
|
|
29134
29264
|
printInfo(` → seeded ${relative6(cwd, env)} (empty; fill secrets here)`);
|
|
29135
29265
|
}
|
|
@@ -29154,7 +29284,7 @@ async function prepareDev(opts) {
|
|
|
29154
29284
|
const result = materializeBundle(dest, bundle, { prune: true });
|
|
29155
29285
|
printInfo(` → wrote ${result.filesWritten} files (pruned ${result.filesRemoved})`);
|
|
29156
29286
|
if (!existsSync26(env)) {
|
|
29157
|
-
|
|
29287
|
+
writeFileSync13(env, `{}
|
|
29158
29288
|
`, "utf-8");
|
|
29159
29289
|
printInfo(` → seeded ${relative6(cwd, env)} (empty; fill secrets here)`);
|
|
29160
29290
|
}
|
|
@@ -29180,7 +29310,7 @@ async function prepareDev(opts) {
|
|
|
29180
29310
|
process.exit(1);
|
|
29181
29311
|
}
|
|
29182
29312
|
}
|
|
29183
|
-
const entryRel = ENTRY_CANDIDATES.find((c2) => existsSync26(
|
|
29313
|
+
const entryRel = ENTRY_CANDIDATES.find((c2) => existsSync26(join23(dest, c2)));
|
|
29184
29314
|
if (!entryRel) {
|
|
29185
29315
|
printError("Could not locate an entry file (expected src/worker.ts).");
|
|
29186
29316
|
process.exit(1);
|
|
@@ -29338,13 +29468,13 @@ function createBurstGuard() {
|
|
|
29338
29468
|
}
|
|
29339
29469
|
|
|
29340
29470
|
// src/lib/dev/agent-connectors/claude-code.ts
|
|
29341
|
-
import { existsSync as existsSync28, unlinkSync as unlinkSync2, writeFileSync as
|
|
29471
|
+
import { existsSync as existsSync28, unlinkSync as unlinkSync2, writeFileSync as writeFileSync15 } from "node:fs";
|
|
29342
29472
|
import { homedir as homedir4 } from "node:os";
|
|
29343
|
-
import { join as
|
|
29473
|
+
import { join as join25 } from "node:path";
|
|
29344
29474
|
|
|
29345
29475
|
// src/lib/dev/agent-connectors/json-config-utils.ts
|
|
29346
|
-
import { existsSync as existsSync27, mkdirSync as
|
|
29347
|
-
import { dirname as
|
|
29476
|
+
import { existsSync as existsSync27, mkdirSync as mkdirSync15, readFileSync as readFileSync16, writeFileSync as writeFileSync14 } from "node:fs";
|
|
29477
|
+
import { dirname as dirname10, join as join24, basename } from "node:path";
|
|
29348
29478
|
function readJsonFile(path) {
|
|
29349
29479
|
if (!existsSync27(path))
|
|
29350
29480
|
return { ok: true, value: {} };
|
|
@@ -29362,9 +29492,9 @@ function readJsonFile(path) {
|
|
|
29362
29492
|
}
|
|
29363
29493
|
}
|
|
29364
29494
|
function atomicWriteJson(path, value) {
|
|
29365
|
-
|
|
29495
|
+
mkdirSync15(dirname10(path), { recursive: true });
|
|
29366
29496
|
const tmp = `${path}.mcpsh-${process.pid}-${Date.now()}.tmp`;
|
|
29367
|
-
|
|
29497
|
+
writeFileSync14(tmp, JSON.stringify(value, null, 2) + `
|
|
29368
29498
|
`, "utf-8");
|
|
29369
29499
|
const { renameSync: renameSync2 } = __require("node:fs");
|
|
29370
29500
|
renameSync2(tmp, path);
|
|
@@ -29373,33 +29503,33 @@ function backupConfig(args) {
|
|
|
29373
29503
|
if (!existsSync27(args.configPath)) {
|
|
29374
29504
|
return { backupPath: null, existed: false };
|
|
29375
29505
|
}
|
|
29376
|
-
|
|
29506
|
+
mkdirSync15(args.backupsDir, { recursive: true });
|
|
29377
29507
|
const filename = `${args.agentId}__${basename(args.configPath)}.bak`;
|
|
29378
|
-
const backupPath =
|
|
29508
|
+
const backupPath = join24(args.backupsDir, filename);
|
|
29379
29509
|
if (!existsSync27(backupPath)) {
|
|
29380
29510
|
const raw = readFileSync16(args.configPath, "utf-8");
|
|
29381
|
-
|
|
29511
|
+
writeFileSync14(backupPath, raw, "utf-8");
|
|
29382
29512
|
}
|
|
29383
29513
|
return { backupPath, existed: true };
|
|
29384
29514
|
}
|
|
29385
29515
|
function restoreFromBackup(args) {
|
|
29386
29516
|
const filename = `${args.agentId}__${basename(args.configPath)}.bak`;
|
|
29387
|
-
const backupPath =
|
|
29517
|
+
const backupPath = join24(args.backupsDir, filename);
|
|
29388
29518
|
if (!existsSync27(backupPath)) {
|
|
29389
29519
|
return { restored: false };
|
|
29390
29520
|
}
|
|
29391
29521
|
const raw = readFileSync16(backupPath, "utf-8");
|
|
29392
|
-
|
|
29393
|
-
|
|
29522
|
+
mkdirSync15(dirname10(args.configPath), { recursive: true });
|
|
29523
|
+
writeFileSync14(args.configPath, raw, "utf-8");
|
|
29394
29524
|
return { restored: true };
|
|
29395
29525
|
}
|
|
29396
29526
|
|
|
29397
29527
|
// src/lib/dev/agent-connectors/claude-code.ts
|
|
29398
29528
|
function configPath() {
|
|
29399
|
-
return
|
|
29529
|
+
return join25(homedir4(), ".claude.json");
|
|
29400
29530
|
}
|
|
29401
29531
|
function legacyConfigPath() {
|
|
29402
|
-
return
|
|
29532
|
+
return join25(homedir4(), ".claude", "mcp.json");
|
|
29403
29533
|
}
|
|
29404
29534
|
function resolveConfigPath() {
|
|
29405
29535
|
if (existsSync28(configPath()))
|
|
@@ -29414,7 +29544,7 @@ var claudeCodeConnector = {
|
|
|
29414
29544
|
hotkey: "c",
|
|
29415
29545
|
describeLocation: () => resolveConfigPath(),
|
|
29416
29546
|
async detect() {
|
|
29417
|
-
const claudeDir =
|
|
29547
|
+
const claudeDir = join25(homedir4(), ".claude");
|
|
29418
29548
|
if (existsSync28(configPath()) || existsSync28(legacyConfigPath()) || existsSync28(claudeDir)) {
|
|
29419
29549
|
return { installed: true, note: "Found Claude Code config" };
|
|
29420
29550
|
}
|
|
@@ -29463,7 +29593,7 @@ var claudeCodeConnector = {
|
|
|
29463
29593
|
try {
|
|
29464
29594
|
unlinkSync2(path);
|
|
29465
29595
|
} catch {
|
|
29466
|
-
|
|
29596
|
+
writeFileSync15(path, `{}
|
|
29467
29597
|
`, "utf-8");
|
|
29468
29598
|
}
|
|
29469
29599
|
}
|
|
@@ -29476,15 +29606,15 @@ var claudeCodeConnector = {
|
|
|
29476
29606
|
// src/lib/dev/agent-connectors/codex.ts
|
|
29477
29607
|
import {
|
|
29478
29608
|
existsSync as existsSync29,
|
|
29479
|
-
mkdirSync as
|
|
29609
|
+
mkdirSync as mkdirSync16,
|
|
29480
29610
|
readFileSync as readFileSync17,
|
|
29481
29611
|
unlinkSync as unlinkSync3,
|
|
29482
|
-
writeFileSync as
|
|
29612
|
+
writeFileSync as writeFileSync16
|
|
29483
29613
|
} from "node:fs";
|
|
29484
29614
|
import { homedir as homedir5 } from "node:os";
|
|
29485
|
-
import { dirname as
|
|
29615
|
+
import { dirname as dirname11, join as join26 } from "node:path";
|
|
29486
29616
|
function configPath2() {
|
|
29487
|
-
return
|
|
29617
|
+
return join26(homedir5(), ".codex", "config.toml");
|
|
29488
29618
|
}
|
|
29489
29619
|
var SECTION_PREFIX = "mcp_servers.";
|
|
29490
29620
|
function buildSection(name, url) {
|
|
@@ -29522,7 +29652,7 @@ var codexConnector = {
|
|
|
29522
29652
|
hotkey: "x",
|
|
29523
29653
|
describeLocation: () => configPath2(),
|
|
29524
29654
|
async detect() {
|
|
29525
|
-
if (existsSync29(
|
|
29655
|
+
if (existsSync29(join26(homedir5(), ".codex")) || existsSync29(configPath2())) {
|
|
29526
29656
|
return { installed: true, note: "Found ~/.codex/" };
|
|
29527
29657
|
}
|
|
29528
29658
|
return { installed: false };
|
|
@@ -29551,8 +29681,8 @@ var codexConnector = {
|
|
|
29551
29681
|
next += `
|
|
29552
29682
|
`;
|
|
29553
29683
|
next += buildSection(args.name, args.url);
|
|
29554
|
-
|
|
29555
|
-
|
|
29684
|
+
mkdirSync16(dirname11(path), { recursive: true });
|
|
29685
|
+
writeFileSync16(path, next, "utf-8");
|
|
29556
29686
|
return { added: !conflict, conflict };
|
|
29557
29687
|
},
|
|
29558
29688
|
async remove(args) {
|
|
@@ -29562,7 +29692,7 @@ var codexConnector = {
|
|
|
29562
29692
|
const range = findSectionRange(existing, args.name);
|
|
29563
29693
|
if (range) {
|
|
29564
29694
|
const next = existing.slice(0, range.start) + existing.slice(range.end);
|
|
29565
|
-
|
|
29695
|
+
writeFileSync16(path, next, "utf-8");
|
|
29566
29696
|
}
|
|
29567
29697
|
}
|
|
29568
29698
|
const restored = restoreFromBackup({
|
|
@@ -29583,11 +29713,11 @@ var codexConnector = {
|
|
|
29583
29713
|
};
|
|
29584
29714
|
|
|
29585
29715
|
// src/lib/dev/agent-connectors/continue.ts
|
|
29586
|
-
import { existsSync as existsSync30, unlinkSync as unlinkSync4, writeFileSync as
|
|
29716
|
+
import { existsSync as existsSync30, unlinkSync as unlinkSync4, writeFileSync as writeFileSync17 } from "node:fs";
|
|
29587
29717
|
import { homedir as homedir6 } from "node:os";
|
|
29588
|
-
import { join as
|
|
29718
|
+
import { join as join27 } from "node:path";
|
|
29589
29719
|
function configPath3() {
|
|
29590
|
-
return
|
|
29720
|
+
return join27(homedir6(), ".continue", "config.json");
|
|
29591
29721
|
}
|
|
29592
29722
|
function isContinueServerEntry(value) {
|
|
29593
29723
|
return Boolean(value && typeof value === "object" && typeof value.name === "string");
|
|
@@ -29598,7 +29728,7 @@ var continueConnector = {
|
|
|
29598
29728
|
hotkey: "n",
|
|
29599
29729
|
describeLocation: () => configPath3(),
|
|
29600
29730
|
async detect() {
|
|
29601
|
-
const dir =
|
|
29731
|
+
const dir = join27(homedir6(), ".continue");
|
|
29602
29732
|
if (existsSync30(dir) || existsSync30(configPath3())) {
|
|
29603
29733
|
return { installed: true, note: "Found ~/.continue/" };
|
|
29604
29734
|
}
|
|
@@ -29647,7 +29777,7 @@ var continueConnector = {
|
|
|
29647
29777
|
try {
|
|
29648
29778
|
unlinkSync4(path);
|
|
29649
29779
|
} catch {
|
|
29650
|
-
|
|
29780
|
+
writeFileSync17(path, `{}
|
|
29651
29781
|
`, "utf-8");
|
|
29652
29782
|
}
|
|
29653
29783
|
}
|
|
@@ -29658,11 +29788,11 @@ var continueConnector = {
|
|
|
29658
29788
|
};
|
|
29659
29789
|
|
|
29660
29790
|
// src/lib/dev/agent-connectors/cursor.ts
|
|
29661
|
-
import { existsSync as existsSync31, unlinkSync as unlinkSync5, writeFileSync as
|
|
29791
|
+
import { existsSync as existsSync31, unlinkSync as unlinkSync5, writeFileSync as writeFileSync18 } from "node:fs";
|
|
29662
29792
|
import { homedir as homedir7 } from "node:os";
|
|
29663
|
-
import { join as
|
|
29793
|
+
import { join as join28 } from "node:path";
|
|
29664
29794
|
function globalConfigPath() {
|
|
29665
|
-
return
|
|
29795
|
+
return join28(homedir7(), ".cursor", "mcp.json");
|
|
29666
29796
|
}
|
|
29667
29797
|
var cursorConnector = {
|
|
29668
29798
|
id: "cursor",
|
|
@@ -29670,8 +29800,8 @@ var cursorConnector = {
|
|
|
29670
29800
|
hotkey: "u",
|
|
29671
29801
|
describeLocation: () => globalConfigPath(),
|
|
29672
29802
|
async detect() {
|
|
29673
|
-
const cursorDir =
|
|
29674
|
-
const macAppSupport =
|
|
29803
|
+
const cursorDir = join28(homedir7(), ".cursor");
|
|
29804
|
+
const macAppSupport = join28(homedir7(), "Library", "Application Support", "Cursor");
|
|
29675
29805
|
if (existsSync31(cursorDir) || existsSync31(macAppSupport)) {
|
|
29676
29806
|
return { installed: true, note: "Found Cursor config dir" };
|
|
29677
29807
|
}
|
|
@@ -29720,7 +29850,7 @@ var cursorConnector = {
|
|
|
29720
29850
|
try {
|
|
29721
29851
|
unlinkSync5(path);
|
|
29722
29852
|
} catch {
|
|
29723
|
-
|
|
29853
|
+
writeFileSync18(path, `{}
|
|
29724
29854
|
`, "utf-8");
|
|
29725
29855
|
}
|
|
29726
29856
|
}
|
|
@@ -29731,30 +29861,30 @@ var cursorConnector = {
|
|
|
29731
29861
|
};
|
|
29732
29862
|
|
|
29733
29863
|
// src/lib/dev/agent-connectors/vscode-copilot.ts
|
|
29734
|
-
import { existsSync as existsSync32, unlinkSync as unlinkSync6, writeFileSync as
|
|
29864
|
+
import { existsSync as existsSync32, unlinkSync as unlinkSync6, writeFileSync as writeFileSync19 } from "node:fs";
|
|
29735
29865
|
import { homedir as homedir8, platform as platform4 } from "node:os";
|
|
29736
|
-
import { join as
|
|
29866
|
+
import { join as join29, resolve as resolve8 } from "node:path";
|
|
29737
29867
|
function userLevelConfigPath() {
|
|
29738
29868
|
const home = homedir8();
|
|
29739
29869
|
const p2 = platform4();
|
|
29740
29870
|
if (p2 === "darwin")
|
|
29741
|
-
return
|
|
29871
|
+
return join29(home, "Library", "Application Support", "Code", "User", "mcp.json");
|
|
29742
29872
|
if (p2 === "win32") {
|
|
29743
|
-
const appData = process.env["APPDATA"] ??
|
|
29744
|
-
return
|
|
29873
|
+
const appData = process.env["APPDATA"] ?? join29(home, "AppData", "Roaming");
|
|
29874
|
+
return join29(appData, "Code", "User", "mcp.json");
|
|
29745
29875
|
}
|
|
29746
|
-
const xdg = process.env["XDG_CONFIG_HOME"] ??
|
|
29747
|
-
return
|
|
29876
|
+
const xdg = process.env["XDG_CONFIG_HOME"] ?? join29(home, ".config");
|
|
29877
|
+
return join29(xdg, "Code", "User", "mcp.json");
|
|
29748
29878
|
}
|
|
29749
29879
|
function isHomeDir(cwd) {
|
|
29750
|
-
return
|
|
29880
|
+
return resolve8(cwd) === resolve8(homedir8());
|
|
29751
29881
|
}
|
|
29752
29882
|
function hasWorkspaceVscode(cwd) {
|
|
29753
|
-
return existsSync32(
|
|
29883
|
+
return existsSync32(join29(cwd, ".vscode"));
|
|
29754
29884
|
}
|
|
29755
29885
|
function configPath4(cwd) {
|
|
29756
29886
|
if (!isHomeDir(cwd) && hasWorkspaceVscode(cwd)) {
|
|
29757
|
-
return
|
|
29887
|
+
return join29(cwd, ".vscode", "mcp.json");
|
|
29758
29888
|
}
|
|
29759
29889
|
return userLevelConfigPath();
|
|
29760
29890
|
}
|
|
@@ -29816,7 +29946,7 @@ var vscodeCopilotConnector = {
|
|
|
29816
29946
|
try {
|
|
29817
29947
|
unlinkSync6(path);
|
|
29818
29948
|
} catch {
|
|
29819
|
-
|
|
29949
|
+
writeFileSync19(path, `{}
|
|
29820
29950
|
`, "utf-8");
|
|
29821
29951
|
}
|
|
29822
29952
|
}
|
|
@@ -29960,7 +30090,7 @@ function parseGraceMs(value, fallbackMs) {
|
|
|
29960
30090
|
return Math.round(n * 1000);
|
|
29961
30091
|
}
|
|
29962
30092
|
function resolveSpecPath(cwd, raw) {
|
|
29963
|
-
return
|
|
30093
|
+
return isAbsolute4(raw) ? raw : resolve9(cwd, raw);
|
|
29964
30094
|
}
|
|
29965
30095
|
function buildConnectionName(serverId) {
|
|
29966
30096
|
const slug = serverId.toLowerCase().replace(/[^a-z0-9]+/g, "-").slice(0, 24) || "mcp-server";
|
|
@@ -31062,11 +31192,11 @@ async function confirmRollback(deploymentId) {
|
|
|
31062
31192
|
// src/commands/doctor.ts
|
|
31063
31193
|
import { existsSync as existsSync35, statSync as statSync6, readFileSync as readFileSync19 } from "node:fs";
|
|
31064
31194
|
import { homedir as homedir9, platform as platform6 } from "node:os";
|
|
31065
|
-
import { join as
|
|
31195
|
+
import { join as join31, delimiter as delimiter3 } from "node:path";
|
|
31066
31196
|
|
|
31067
31197
|
// src/lib/version-check.ts
|
|
31068
|
-
import { existsSync as existsSync34, mkdirSync as
|
|
31069
|
-
import { join as
|
|
31198
|
+
import { existsSync as existsSync34, mkdirSync as mkdirSync17, readFileSync as readFileSync18, writeFileSync as writeFileSync20 } from "node:fs";
|
|
31199
|
+
import { join as join30 } from "node:path";
|
|
31070
31200
|
var CACHE_TTL_MS = 24 * 60 * 60 * 1000;
|
|
31071
31201
|
var FETCH_TIMEOUT_MS2 = 2000;
|
|
31072
31202
|
var REGISTRY_URL = "https://registry.npmjs.org/@mcpcloud/cli/latest";
|
|
@@ -31074,7 +31204,7 @@ function cacheDir() {
|
|
|
31074
31204
|
return configDir();
|
|
31075
31205
|
}
|
|
31076
31206
|
function cacheFile() {
|
|
31077
|
-
return
|
|
31207
|
+
return join30(cacheDir(), "version-check.json");
|
|
31078
31208
|
}
|
|
31079
31209
|
function readCache() {
|
|
31080
31210
|
if (!existsSync34(cacheFile()))
|
|
@@ -31091,8 +31221,8 @@ function readCache() {
|
|
|
31091
31221
|
function writeCache(entry) {
|
|
31092
31222
|
try {
|
|
31093
31223
|
if (!existsSync34(cacheDir()))
|
|
31094
|
-
|
|
31095
|
-
|
|
31224
|
+
mkdirSync17(cacheDir(), { recursive: true, mode: 448 });
|
|
31225
|
+
writeFileSync20(cacheFile(), JSON.stringify(entry, null, 2), { mode: 384 });
|
|
31096
31226
|
} catch {}
|
|
31097
31227
|
}
|
|
31098
31228
|
function compareVersions(a, b2) {
|
|
@@ -31203,7 +31333,7 @@ function checkNode() {
|
|
|
31203
31333
|
}
|
|
31204
31334
|
function checkConfigFile() {
|
|
31205
31335
|
const t0 = Date.now();
|
|
31206
|
-
const path =
|
|
31336
|
+
const path = join31(homedir9(), ".mcpcloud", "config.json");
|
|
31207
31337
|
if (!existsSync35(path)) {
|
|
31208
31338
|
return {
|
|
31209
31339
|
name: "Config file",
|
|
@@ -31357,7 +31487,7 @@ function checkClaudeCli() {
|
|
|
31357
31487
|
for (const dir of PATH.split(delimiter3)) {
|
|
31358
31488
|
if (!dir)
|
|
31359
31489
|
continue;
|
|
31360
|
-
const candidate =
|
|
31490
|
+
const candidate = join31(dir, exe);
|
|
31361
31491
|
if (existsSync35(candidate)) {
|
|
31362
31492
|
return {
|
|
31363
31493
|
name: "claude CLI",
|
|
@@ -31697,10 +31827,10 @@ function prompt2(question) {
|
|
|
31697
31827
|
throw new Error("Interactive prompts are disabled in CI mode. Pass --org / --project / --name explicitly or run `mcp init` outside CI.");
|
|
31698
31828
|
}
|
|
31699
31829
|
const rl = createInterface3({ input: process.stdin, output: process.stderr });
|
|
31700
|
-
return new Promise((
|
|
31830
|
+
return new Promise((resolve10) => {
|
|
31701
31831
|
rl.question(question, (answer) => {
|
|
31702
31832
|
rl.close();
|
|
31703
|
-
|
|
31833
|
+
resolve10(answer.trim());
|
|
31704
31834
|
});
|
|
31705
31835
|
});
|
|
31706
31836
|
}
|
|
@@ -32312,6 +32442,9 @@ function invokeResultToJson3(result) {
|
|
|
32312
32442
|
};
|
|
32313
32443
|
}
|
|
32314
32444
|
|
|
32445
|
+
// src/commands/marketplace.ts
|
|
32446
|
+
import { readFile } from "node:fs/promises";
|
|
32447
|
+
|
|
32315
32448
|
// src/lib/resolve-marketplace.ts
|
|
32316
32449
|
var ARTIFACT_KIND = {
|
|
32317
32450
|
label: "artifact",
|
|
@@ -32563,14 +32696,14 @@ function registerMarketplaceCommands(program2) {
|
|
|
32563
32696
|
printSuccess(`Forked ${c.bold(data.fork.artifactType)} → ${data.fork.forkedId} (draft).`);
|
|
32564
32697
|
printStep(data.fork.artifactType === "server" ? `Iterate: \`mcp dev\` then \`mcp servers deploy ${data.fork.forkedId} --wait\`.` : `Iterate on skill ${data.fork.forkedId} then \`mcp skills deploy\`.`);
|
|
32565
32698
|
}));
|
|
32566
|
-
marketplace.command("publish <server|skill>").description("Publish a deployed server or a versioned skill to the registry (requires org admin)").requiredOption("--type <type>", "Artifact type: server | skill").requiredOption("--project <project>", "The artifact's project (id or name)").option("--semver <semver>", "Version to publish (required for servers; skills use their current version)").option("--visibility <visibility>", "public (marketplace) | private (your org only). Default public.", "public").option("--changelog <text>", "
|
|
32699
|
+
marketplace.command("publish <server|skill>").description("Publish a deployed server or a versioned skill to the registry (requires org admin)").requiredOption("--type <type>", "Artifact type: server | skill").requiredOption("--project <project>", "The artifact's project (id or name)").option("--semver <semver>", "Version to publish (required for servers; skills use their current version)").option("--visibility <visibility>", "public (marketplace) | private (your org only). Default public.", "public").option("--changelog <text>", "Changelog for this version. Required for every version after the first.").option("--readme <path>", "Path to a markdown README for the listing. Required on first publish; omit later to keep the published one.").option("--org <organizationId>", "Organization ID").addHelpText("after", [
|
|
32567
32700
|
"",
|
|
32568
32701
|
"Notes:",
|
|
32569
32702
|
" Servers must be successfully deployed before publishing. Publishing to",
|
|
32570
32703
|
" the public marketplace or a private-org registry requires the Pro plan.",
|
|
32571
32704
|
"",
|
|
32572
32705
|
"Examples:",
|
|
32573
|
-
" $ mcp marketplace publish srv_123 --type server --project proj_1 --semver 1.0.0",
|
|
32706
|
+
" $ mcp marketplace publish srv_123 --type server --project proj_1 --semver 1.0.0 --readme ./README.md",
|
|
32574
32707
|
" $ mcp marketplace publish skill_9 --type skill --project proj_1 --visibility private"
|
|
32575
32708
|
].join(`
|
|
32576
32709
|
`)).action(runAction(async (id, opts) => {
|
|
@@ -32585,12 +32718,14 @@ function registerMarketplaceCommands(program2) {
|
|
|
32585
32718
|
}
|
|
32586
32719
|
const access = visibility === "private" ? "privateOrg" : "public";
|
|
32587
32720
|
const projectId = await resolveProjectId(opts.project, orgId);
|
|
32721
|
+
const readmeContent = opts.readme ? await readFile(opts.readme, "utf8") : null;
|
|
32588
32722
|
const body = {
|
|
32589
32723
|
organizationId: orgId,
|
|
32590
32724
|
artifactType: type,
|
|
32591
32725
|
projectId,
|
|
32592
32726
|
access,
|
|
32593
|
-
...opts.changelog ? { changelog: opts.changelog } : {}
|
|
32727
|
+
...opts.changelog ? { changelog: opts.changelog } : {},
|
|
32728
|
+
...readmeContent ? { readmeContent } : {}
|
|
32594
32729
|
};
|
|
32595
32730
|
if (type === "server") {
|
|
32596
32731
|
if (!opts.semver) {
|
|
@@ -33200,24 +33335,24 @@ function registerConnectionsCommands(program2) {
|
|
|
33200
33335
|
import { spawn as spawn7 } from "node:child_process";
|
|
33201
33336
|
import {
|
|
33202
33337
|
existsSync as existsSync36,
|
|
33203
|
-
mkdirSync as
|
|
33338
|
+
mkdirSync as mkdirSync18,
|
|
33204
33339
|
readdirSync as readdirSync4,
|
|
33205
33340
|
readFileSync as readFileSync20,
|
|
33206
33341
|
rmSync as rmSync3,
|
|
33207
33342
|
statSync as statSync7
|
|
33208
33343
|
} from "node:fs";
|
|
33209
|
-
import { join as
|
|
33344
|
+
import { join as join32 } from "node:path";
|
|
33210
33345
|
import { pathToFileURL } from "node:url";
|
|
33211
33346
|
function pluginsDir() {
|
|
33212
|
-
return
|
|
33347
|
+
return join32(configDir(), "plugins");
|
|
33213
33348
|
}
|
|
33214
33349
|
function ensureDir2() {
|
|
33215
33350
|
const dir = pluginsDir();
|
|
33216
33351
|
if (!existsSync36(dir))
|
|
33217
|
-
|
|
33352
|
+
mkdirSync18(dir, { recursive: true, mode: 448 });
|
|
33218
33353
|
}
|
|
33219
33354
|
function readManifestFromPackageDir(packageDir) {
|
|
33220
|
-
const pkgPath =
|
|
33355
|
+
const pkgPath = join32(packageDir, "package.json");
|
|
33221
33356
|
if (!existsSync36(pkgPath))
|
|
33222
33357
|
return null;
|
|
33223
33358
|
let pkg;
|
|
@@ -33229,7 +33364,7 @@ function readManifestFromPackageDir(packageDir) {
|
|
|
33229
33364
|
if (!pkg.name)
|
|
33230
33365
|
return null;
|
|
33231
33366
|
const relEntry = pkg.mcpsh?.register ?? pkg.mcp?.register ?? pkg.main ?? "index.js";
|
|
33232
|
-
const entry =
|
|
33367
|
+
const entry = join32(packageDir, relEntry);
|
|
33233
33368
|
if (!existsSync36(entry))
|
|
33234
33369
|
return null;
|
|
33235
33370
|
return {
|
|
@@ -33245,7 +33380,7 @@ function listInstalledPlugins() {
|
|
|
33245
33380
|
return [];
|
|
33246
33381
|
const out = [];
|
|
33247
33382
|
for (const entry of readdirSync4(dir)) {
|
|
33248
|
-
const full =
|
|
33383
|
+
const full = join32(dir, entry);
|
|
33249
33384
|
let s;
|
|
33250
33385
|
try {
|
|
33251
33386
|
s = statSync7(full);
|
|
@@ -33256,7 +33391,7 @@ function listInstalledPlugins() {
|
|
|
33256
33391
|
continue;
|
|
33257
33392
|
if (entry.startsWith("@")) {
|
|
33258
33393
|
for (const child of readdirSync4(full)) {
|
|
33259
|
-
const m2 = readManifestFromPackageDir(
|
|
33394
|
+
const m2 = readManifestFromPackageDir(join32(full, child));
|
|
33260
33395
|
if (m2)
|
|
33261
33396
|
out.push(m2);
|
|
33262
33397
|
}
|
|
@@ -33291,15 +33426,15 @@ async function loadPlugins(program2) {
|
|
|
33291
33426
|
}
|
|
33292
33427
|
var PACKAGE_SPEC_PATTERN = /^(@[a-z0-9~-][\w.~-]*\/)?[a-z0-9~-][\w.~-]*(@[-\w.^~><=*+|]+)?$/i;
|
|
33293
33428
|
function runNpm(args, cwd) {
|
|
33294
|
-
return new Promise((
|
|
33429
|
+
return new Promise((resolve10) => {
|
|
33295
33430
|
const isWindows = process.platform === "win32";
|
|
33296
33431
|
const child = spawn7(isWindows ? "npm.cmd" : "npm", args, {
|
|
33297
33432
|
shell: isWindows,
|
|
33298
33433
|
cwd,
|
|
33299
33434
|
stdio: "inherit"
|
|
33300
33435
|
});
|
|
33301
|
-
child.on("close", (code) =>
|
|
33302
|
-
child.on("error", () =>
|
|
33436
|
+
child.on("close", (code) => resolve10(code ?? 1));
|
|
33437
|
+
child.on("error", () => resolve10(1));
|
|
33303
33438
|
});
|
|
33304
33439
|
}
|
|
33305
33440
|
async function installPlugin(packageSpec) {
|
|
@@ -33320,12 +33455,12 @@ async function installPlugin(packageSpec) {
|
|
|
33320
33455
|
if (code !== 0) {
|
|
33321
33456
|
throw new Error(`npm install ${packageSpec} exited with code ${code}.`);
|
|
33322
33457
|
}
|
|
33323
|
-
const nm =
|
|
33458
|
+
const nm = join32(dir, "node_modules");
|
|
33324
33459
|
if (!existsSync36(nm)) {
|
|
33325
33460
|
throw new Error(`npm install ran but produced no node_modules under ${dir}.`);
|
|
33326
33461
|
}
|
|
33327
33462
|
const baseName = packageSpec.replace(/@[^@/]+$/, "");
|
|
33328
|
-
const candidatePath = baseName.startsWith("@") ?
|
|
33463
|
+
const candidatePath = baseName.startsWith("@") ? join32(nm, baseName.split("/")[0], baseName.split("/")[1] ?? "") : join32(nm, baseName);
|
|
33329
33464
|
const manifest = readManifestFromPackageDir(candidatePath);
|
|
33330
33465
|
if (!manifest) {
|
|
33331
33466
|
throw new Error(`Installed but could not read plugin manifest at ${candidatePath}.`);
|
|
@@ -33333,10 +33468,10 @@ async function installPlugin(packageSpec) {
|
|
|
33333
33468
|
return { name: manifest.name, entry: manifest.entry };
|
|
33334
33469
|
}
|
|
33335
33470
|
function removePlugin(name) {
|
|
33336
|
-
const nm =
|
|
33471
|
+
const nm = join32(pluginsDir(), "node_modules");
|
|
33337
33472
|
if (!existsSync36(nm))
|
|
33338
33473
|
return false;
|
|
33339
|
-
const target = name.startsWith("@") ?
|
|
33474
|
+
const target = name.startsWith("@") ? join32(nm, name.split("/")[0], name.split("/")[1] ?? "") : join32(nm, name);
|
|
33340
33475
|
if (!existsSync36(target))
|
|
33341
33476
|
return false;
|
|
33342
33477
|
rmSync3(target, { recursive: true, force: true });
|
|
@@ -33344,7 +33479,7 @@ function removePlugin(name) {
|
|
|
33344
33479
|
}
|
|
33345
33480
|
function listInstalledPluginsCombined() {
|
|
33346
33481
|
const direct = listInstalledPlugins();
|
|
33347
|
-
const nm =
|
|
33482
|
+
const nm = join32(pluginsDir(), "node_modules");
|
|
33348
33483
|
if (!existsSync36(nm))
|
|
33349
33484
|
return direct;
|
|
33350
33485
|
const seen = new Set(direct.map((p2) => p2.name));
|
|
@@ -33352,7 +33487,7 @@ function listInstalledPluginsCombined() {
|
|
|
33352
33487
|
for (const entry of readdirSync4(nm)) {
|
|
33353
33488
|
if (entry === ".bin" || entry === ".package-lock.json")
|
|
33354
33489
|
continue;
|
|
33355
|
-
const full =
|
|
33490
|
+
const full = join32(nm, entry);
|
|
33356
33491
|
let s;
|
|
33357
33492
|
try {
|
|
33358
33493
|
s = statSync7(full);
|
|
@@ -33363,7 +33498,7 @@ function listInstalledPluginsCombined() {
|
|
|
33363
33498
|
continue;
|
|
33364
33499
|
if (entry.startsWith("@")) {
|
|
33365
33500
|
for (const child of readdirSync4(full)) {
|
|
33366
|
-
const m2 = readManifestFromPackageDir(
|
|
33501
|
+
const m2 = readManifestFromPackageDir(join32(full, child));
|
|
33367
33502
|
if (m2 && !seen.has(m2.name)) {
|
|
33368
33503
|
seen.add(m2.name);
|
|
33369
33504
|
out.push(m2);
|
|
@@ -33823,7 +33958,7 @@ function clipboardCandidatesFor(platform7, waylandDisplay) {
|
|
|
33823
33958
|
return linux;
|
|
33824
33959
|
}
|
|
33825
33960
|
async function defaultIsExecutable(binary) {
|
|
33826
|
-
return await new Promise((
|
|
33961
|
+
return await new Promise((resolve10) => {
|
|
33827
33962
|
const isWin = process.platform === "win32";
|
|
33828
33963
|
const cmd = isWin ? "where" : "command";
|
|
33829
33964
|
const args = isWin ? [binary] : ["-v", binary];
|
|
@@ -33831,8 +33966,8 @@ async function defaultIsExecutable(binary) {
|
|
|
33831
33966
|
shell: !isWin,
|
|
33832
33967
|
stdio: "ignore"
|
|
33833
33968
|
});
|
|
33834
|
-
child.on("error", () =>
|
|
33835
|
-
child.on("exit", (code) =>
|
|
33969
|
+
child.on("error", () => resolve10(false));
|
|
33970
|
+
child.on("exit", (code) => resolve10(code === 0));
|
|
33836
33971
|
});
|
|
33837
33972
|
}
|
|
33838
33973
|
async function detectClipboard(probe) {
|
|
@@ -33854,7 +33989,7 @@ async function copyToClipboard(text, probe) {
|
|
|
33854
33989
|
};
|
|
33855
33990
|
}
|
|
33856
33991
|
const spawnImpl = probe?.spawnImpl ?? spawn8;
|
|
33857
|
-
return await new Promise((
|
|
33992
|
+
return await new Promise((resolve10) => {
|
|
33858
33993
|
const child = spawnImpl(candidate.binary, candidate.args, {
|
|
33859
33994
|
stdio: ["pipe", "ignore", "pipe"]
|
|
33860
33995
|
});
|
|
@@ -33863,7 +33998,7 @@ async function copyToClipboard(text, probe) {
|
|
|
33863
33998
|
stderr += chunk.toString("utf-8");
|
|
33864
33999
|
});
|
|
33865
34000
|
child.on("error", (err) => {
|
|
33866
|
-
|
|
34001
|
+
resolve10({
|
|
33867
34002
|
kind: "failed",
|
|
33868
34003
|
binary: candidate.binary,
|
|
33869
34004
|
message: err instanceof Error ? err.message : String(err)
|
|
@@ -33871,9 +34006,9 @@ async function copyToClipboard(text, probe) {
|
|
|
33871
34006
|
});
|
|
33872
34007
|
child.on("exit", (code) => {
|
|
33873
34008
|
if (code === 0) {
|
|
33874
|
-
|
|
34009
|
+
resolve10({ kind: "ok", binary: candidate.binary });
|
|
33875
34010
|
} else {
|
|
33876
|
-
|
|
34011
|
+
resolve10({
|
|
33877
34012
|
kind: "failed",
|
|
33878
34013
|
binary: candidate.binary,
|
|
33879
34014
|
message: stderr.trim() || `${candidate.binary} exited with status ${code ?? "?"}`
|
|
@@ -33883,7 +34018,7 @@ async function copyToClipboard(text, probe) {
|
|
|
33883
34018
|
try {
|
|
33884
34019
|
child.stdin?.end(text);
|
|
33885
34020
|
} catch (err) {
|
|
33886
|
-
|
|
34021
|
+
resolve10({
|
|
33887
34022
|
kind: "failed",
|
|
33888
34023
|
binary: candidate.binary,
|
|
33889
34024
|
message: err instanceof Error ? err.message : String(err)
|
|
@@ -34954,11 +35089,11 @@ function displayValueFor(field, value) {
|
|
|
34954
35089
|
// src/lib/tui/state-store.ts
|
|
34955
35090
|
import {
|
|
34956
35091
|
existsSync as existsSync37,
|
|
34957
|
-
mkdirSync as
|
|
35092
|
+
mkdirSync as mkdirSync19,
|
|
34958
35093
|
readFileSync as readFileSync21,
|
|
34959
|
-
writeFileSync as
|
|
35094
|
+
writeFileSync as writeFileSync21
|
|
34960
35095
|
} from "node:fs";
|
|
34961
|
-
import { join as
|
|
35096
|
+
import { join as join33 } from "node:path";
|
|
34962
35097
|
var ALL_TABS = [
|
|
34963
35098
|
"servers",
|
|
34964
35099
|
"projects",
|
|
@@ -34968,7 +35103,7 @@ var ALL_TABS = [
|
|
|
34968
35103
|
"devSessions"
|
|
34969
35104
|
];
|
|
34970
35105
|
function tuiStateFile() {
|
|
34971
|
-
return
|
|
35106
|
+
return join33(configDir(), "tui-state.json");
|
|
34972
35107
|
}
|
|
34973
35108
|
function isTab(v2) {
|
|
34974
35109
|
return typeof v2 === "string" && ALL_TABS.includes(v2);
|
|
@@ -35046,9 +35181,9 @@ function readTuiState() {
|
|
|
35046
35181
|
function writeTuiState(state) {
|
|
35047
35182
|
try {
|
|
35048
35183
|
if (!existsSync37(configDir())) {
|
|
35049
|
-
|
|
35184
|
+
mkdirSync19(configDir(), { recursive: true, mode: 448 });
|
|
35050
35185
|
}
|
|
35051
|
-
|
|
35186
|
+
writeFileSync21(tuiStateFile(), JSON.stringify(state, null, 2), {
|
|
35052
35187
|
encoding: "utf-8",
|
|
35053
35188
|
mode: 384
|
|
35054
35189
|
});
|
|
@@ -37053,7 +37188,7 @@ function registerUiCommand(program2) {
|
|
|
37053
37188
|
}
|
|
37054
37189
|
return false;
|
|
37055
37190
|
};
|
|
37056
|
-
await new Promise((
|
|
37191
|
+
await new Promise((resolve10) => {
|
|
37057
37192
|
const flushAndExit = () => {
|
|
37058
37193
|
try {
|
|
37059
37194
|
if (persistTimer) {
|
|
@@ -37063,7 +37198,7 @@ function registerUiCommand(program2) {
|
|
|
37063
37198
|
writeTuiState(snapshotForPersist());
|
|
37064
37199
|
} catch {}
|
|
37065
37200
|
shutdown(handles);
|
|
37066
|
-
|
|
37201
|
+
resolve10();
|
|
37067
37202
|
};
|
|
37068
37203
|
const executePaletteCommand = (id) => {
|
|
37069
37204
|
if (id.startsWith("tab:")) {
|
|
@@ -37672,7 +37807,7 @@ function registerUiCommand(program2) {
|
|
|
37672
37807
|
|
|
37673
37808
|
// src/commands/update.ts
|
|
37674
37809
|
import { spawn as spawn9 } from "node:child_process";
|
|
37675
|
-
import { dirname as
|
|
37810
|
+
import { dirname as dirname12 } from "node:path";
|
|
37676
37811
|
import { fileURLToPath as fileURLToPath2 } from "node:url";
|
|
37677
37812
|
function detectInstallContext() {
|
|
37678
37813
|
const override = process.env["MCPSH_PACKAGE_MANAGER"]?.trim().toLowerCase();
|
|
@@ -37685,7 +37820,7 @@ function detectInstallContext() {
|
|
|
37685
37820
|
}
|
|
37686
37821
|
const here = (() => {
|
|
37687
37822
|
try {
|
|
37688
|
-
return
|
|
37823
|
+
return dirname12(fileURLToPath2(import.meta.url));
|
|
37689
37824
|
} catch {
|
|
37690
37825
|
return process.argv[1] ?? "";
|
|
37691
37826
|
}
|
|
@@ -37733,10 +37868,10 @@ function buildCommand(manager) {
|
|
|
37733
37868
|
}
|
|
37734
37869
|
}
|
|
37735
37870
|
function runShell(command) {
|
|
37736
|
-
return new Promise((
|
|
37871
|
+
return new Promise((resolve10) => {
|
|
37737
37872
|
const child = spawn9(command, { shell: true, stdio: "inherit" });
|
|
37738
|
-
child.on("close", (code) =>
|
|
37739
|
-
child.on("error", () =>
|
|
37873
|
+
child.on("close", (code) => resolve10(code ?? 1));
|
|
37874
|
+
child.on("error", () => resolve10(1));
|
|
37740
37875
|
});
|
|
37741
37876
|
}
|
|
37742
37877
|
function registerUpdateCommand(program2) {
|