@wrongstack/mcp 0.317.2 → 0.319.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.js +42 -5
- package/package.json +2 -2
package/dist/index.js
CHANGED
|
@@ -817,10 +817,11 @@ function boundedServerName(value) {
|
|
|
817
817
|
|
|
818
818
|
// src/client.ts
|
|
819
819
|
import { spawn as spawn2 } from "node:child_process";
|
|
820
|
-
import { buildChildEnv, buildWin32CmdShimInvocation, toErrorMessage } from "@wrongstack/core/utils";
|
|
820
|
+
import { buildChildEnv as buildChildEnv2, buildWin32CmdShimInvocation, toErrorMessage } from "@wrongstack/core/utils";
|
|
821
821
|
|
|
822
822
|
// src/client-process.ts
|
|
823
823
|
import { spawn } from "node:child_process";
|
|
824
|
+
import { buildChildEnv } from "@wrongstack/core/utils";
|
|
824
825
|
function forceKillTree(child) {
|
|
825
826
|
if (child.pid === void 0) {
|
|
826
827
|
try {
|
|
@@ -832,6 +833,9 @@ function forceKillTree(child) {
|
|
|
832
833
|
if (process.platform === "win32") {
|
|
833
834
|
const killer = spawn("taskkill", ["/pid", String(child.pid), "/T", "/F"], {
|
|
834
835
|
stdio: "ignore",
|
|
836
|
+
// H-8 convention (spawn-convention test): taskkill needs PATH only —
|
|
837
|
+
// do not hand it the credential-bearing parent environment.
|
|
838
|
+
env: buildChildEnv(),
|
|
835
839
|
windowsHide: true
|
|
836
840
|
});
|
|
837
841
|
killer.once("error", () => {
|
|
@@ -2284,7 +2288,7 @@ var MCPClient = class _MCPClient {
|
|
|
2284
2288
|
}
|
|
2285
2289
|
const isWin = process.platform === "win32";
|
|
2286
2290
|
const rawArgs = this.opts.args ?? [];
|
|
2287
|
-
const spawnEnv =
|
|
2291
|
+
const spawnEnv = buildChildEnv2({ extra: extraEnv });
|
|
2288
2292
|
const stdio = ["pipe", "pipe", "pipe"];
|
|
2289
2293
|
const child = isWin ? (() => {
|
|
2290
2294
|
const shim = buildWin32CmdShimInvocation(this.opts.command, rawArgs);
|
|
@@ -3036,6 +3040,15 @@ async function persist(configPath, full, servers) {
|
|
|
3036
3040
|
full.mcpServers = servers;
|
|
3037
3041
|
await writeConfig(configPath, full);
|
|
3038
3042
|
}
|
|
3043
|
+
var UNSAFE_SERVER_NAMES = /* @__PURE__ */ new Set([
|
|
3044
|
+
"__proto__",
|
|
3045
|
+
"constructor",
|
|
3046
|
+
"prototype"
|
|
3047
|
+
]);
|
|
3048
|
+
function unsafeServerNameResult(name) {
|
|
3049
|
+
if (!UNSAFE_SERVER_NAMES.has(name)) return void 0;
|
|
3050
|
+
return { ok: false, message: `Invalid server name "${name}"` };
|
|
3051
|
+
}
|
|
3039
3052
|
function normalizeTransport(t) {
|
|
3040
3053
|
if (t === "sse") return "sse";
|
|
3041
3054
|
if (t === "http" || t === "streamable-http") return "streamable-http";
|
|
@@ -3124,11 +3137,13 @@ async function listMcp(deps) {
|
|
|
3124
3137
|
}
|
|
3125
3138
|
async function addMcp(input, deps) {
|
|
3126
3139
|
if (!input.name) return { ok: false, message: "Server name is required" };
|
|
3140
|
+
const unsafe = unsafeServerNameResult(input.name);
|
|
3141
|
+
if (unsafe) return unsafe;
|
|
3127
3142
|
const { full, servers } = await readServers(deps.configPath);
|
|
3128
|
-
if (servers
|
|
3143
|
+
if (Object.hasOwn(servers, input.name)) {
|
|
3129
3144
|
return { ok: false, message: `Server "${input.name}" already exists` };
|
|
3130
3145
|
}
|
|
3131
|
-
const preset = deps.presets
|
|
3146
|
+
const preset = deps.presets && Object.hasOwn(deps.presets, input.name) ? deps.presets[input.name] : void 0;
|
|
3132
3147
|
const hasExplicitConfig = !!(input.transport || input.command || input.url);
|
|
3133
3148
|
const cfg = hasExplicitConfig ? buildConfig(input, preset) : preset ? buildConfig({ ...input, name: input.name }, preset) : buildConfig(input);
|
|
3134
3149
|
if (!hasExplicitConfig && !preset) {
|
|
@@ -3153,7 +3168,12 @@ async function addMcp(input, deps) {
|
|
|
3153
3168
|
}
|
|
3154
3169
|
async function updateMcp(input, deps) {
|
|
3155
3170
|
if (!input.name) return { ok: false, message: "Server name is required" };
|
|
3171
|
+
const unsafe = unsafeServerNameResult(input.name);
|
|
3172
|
+
if (unsafe) return unsafe;
|
|
3156
3173
|
const { full, servers } = await readServers(deps.configPath);
|
|
3174
|
+
if (!Object.hasOwn(servers, input.name)) {
|
|
3175
|
+
return { ok: false, message: `Server "${input.name}" not found` };
|
|
3176
|
+
}
|
|
3157
3177
|
const existing = servers[input.name];
|
|
3158
3178
|
if (!existing) return { ok: false, message: `Server "${input.name}" not found` };
|
|
3159
3179
|
const cfg = buildConfig(input, { ...existing, name: input.name });
|
|
@@ -3172,8 +3192,10 @@ async function updateMcp(input, deps) {
|
|
|
3172
3192
|
}
|
|
3173
3193
|
async function removeMcp(name, deps) {
|
|
3174
3194
|
if (!name) return { ok: false, message: "Server name is required" };
|
|
3195
|
+
const unsafe = unsafeServerNameResult(name);
|
|
3196
|
+
if (unsafe) return unsafe;
|
|
3175
3197
|
const { full, servers } = await readServers(deps.configPath);
|
|
3176
|
-
if (!servers
|
|
3198
|
+
if (!Object.hasOwn(servers, name)) return { ok: false, message: `Server "${name}" not found` };
|
|
3177
3199
|
await safeStop(name, deps);
|
|
3178
3200
|
forgetRegistryState(deps.registry, name);
|
|
3179
3201
|
delete servers[name];
|
|
@@ -3182,7 +3204,12 @@ async function removeMcp(name, deps) {
|
|
|
3182
3204
|
}
|
|
3183
3205
|
async function enableMcp(name, deps) {
|
|
3184
3206
|
if (!name) return { ok: false, message: "Server name is required" };
|
|
3207
|
+
const unsafe = unsafeServerNameResult(name);
|
|
3208
|
+
if (unsafe) return unsafe;
|
|
3185
3209
|
const { full, servers } = await readServers(deps.configPath);
|
|
3210
|
+
if (!Object.hasOwn(servers, name)) {
|
|
3211
|
+
return { ok: false, message: `Server "${name}" is not in config. Add it first.` };
|
|
3212
|
+
}
|
|
3186
3213
|
const cfg = servers[name];
|
|
3187
3214
|
if (!cfg) {
|
|
3188
3215
|
return { ok: false, message: `Server "${name}" is not in config. Add it first.` };
|
|
@@ -3194,7 +3221,12 @@ async function enableMcp(name, deps) {
|
|
|
3194
3221
|
}
|
|
3195
3222
|
async function disableMcp(name, deps) {
|
|
3196
3223
|
if (!name) return { ok: false, message: "Server name is required" };
|
|
3224
|
+
const unsafe = unsafeServerNameResult(name);
|
|
3225
|
+
if (unsafe) return unsafe;
|
|
3197
3226
|
const { full, servers } = await readServers(deps.configPath);
|
|
3227
|
+
if (!Object.hasOwn(servers, name)) {
|
|
3228
|
+
return { ok: false, message: `Server "${name}" is not in config.` };
|
|
3229
|
+
}
|
|
3198
3230
|
const cfg = servers[name];
|
|
3199
3231
|
if (!cfg) return { ok: false, message: `Server "${name}" is not in config.` };
|
|
3200
3232
|
await safeStop(name, deps);
|
|
@@ -3210,6 +3242,8 @@ async function disableMcp(name, deps) {
|
|
|
3210
3242
|
}
|
|
3211
3243
|
async function restartMcp(name, deps) {
|
|
3212
3244
|
if (!name) return { ok: false, message: "Server name is required" };
|
|
3245
|
+
const unsafe = unsafeServerNameResult(name);
|
|
3246
|
+
if (unsafe) return unsafe;
|
|
3213
3247
|
const registered = deps.registry.list().some((s) => s.name === name);
|
|
3214
3248
|
if (registered) {
|
|
3215
3249
|
try {
|
|
@@ -3221,6 +3255,9 @@ async function restartMcp(name, deps) {
|
|
|
3221
3255
|
}
|
|
3222
3256
|
}
|
|
3223
3257
|
const { servers } = await readServers(deps.configPath);
|
|
3258
|
+
if (!Object.hasOwn(servers, name)) {
|
|
3259
|
+
return { ok: false, message: `Server "${name}" is not in config.` };
|
|
3260
|
+
}
|
|
3224
3261
|
const cfg = servers[name];
|
|
3225
3262
|
if (!cfg) return { ok: false, message: `Server "${name}" is not in config.` };
|
|
3226
3263
|
return startServer(name, { ...cfg, name }, deps, `Server "${name}" started`, { restart: true });
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@wrongstack/mcp",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.319.0",
|
|
4
4
|
"license": "MIT",
|
|
5
5
|
"description": "WrongStack Model Context Protocol client and registry: stdio, SSE, and streamable HTTP transports.",
|
|
6
6
|
"repository": {
|
|
@@ -26,7 +26,7 @@
|
|
|
26
26
|
"!dist/**/*.map"
|
|
27
27
|
],
|
|
28
28
|
"dependencies": {
|
|
29
|
-
"@wrongstack/core": "0.
|
|
29
|
+
"@wrongstack/core": "0.319.0"
|
|
30
30
|
},
|
|
31
31
|
"devDependencies": {
|
|
32
32
|
"@types/node": "^26.2.0",
|