@wrongstack/mcp 1.0.27 → 1.0.28

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.
Files changed (2) hide show
  1. package/dist/index.js +47 -20
  2. package/package.json +2 -2
package/dist/index.js CHANGED
@@ -45,7 +45,9 @@ function parseMcpBearerChallenge(header, resource) {
45
45
  const resourceMetadata = challengeParameter(parameters, "resource_metadata");
46
46
  if (resourceMetadata) {
47
47
  const metadataUrl = validateMetadataUrl(resourceMetadata);
48
- if (metadataUrl) challenge.resourceMetadataUrl = metadataUrl;
48
+ if (metadataUrl && isSameHost(metadataUrl, resource)) {
49
+ challenge.resourceMetadataUrl = metadataUrl;
50
+ }
49
51
  }
50
52
  const scope = challengeParameter(parameters, "scope");
51
53
  if (scope) {
@@ -194,6 +196,13 @@ function validateMetadataUrl(value) {
194
196
  return void 0;
195
197
  }
196
198
  }
199
+ function isSameHost(candidate, resource) {
200
+ try {
201
+ return unbracket(new URL(candidate).hostname).toLowerCase() === unbracket(new URL(resource).hostname).toLowerCase();
202
+ } catch {
203
+ return false;
204
+ }
205
+ }
197
206
  function record(value, label2) {
198
207
  if (!value || typeof value !== "object" || Array.isArray(value)) {
199
208
  throw new Error(`MCP ${label2} must be an object`);
@@ -1892,7 +1901,7 @@ function validateElicitationContent(fields, content) {
1892
1901
  out[field.name] = [];
1893
1902
  continue;
1894
1903
  }
1895
- if (raw === void 0 || raw === null || raw === "" || Array.isArray(raw) && raw.length === 0) {
1904
+ if (raw === void 0 || raw === null || Array.isArray(raw) && raw.length === 0) {
1896
1905
  if (field.required) return { ok: false, error: `${label(field)} is required` };
1897
1906
  continue;
1898
1907
  }
@@ -4607,8 +4616,12 @@ function toUserInputRequest(request3, problem) {
4607
4616
  function answerValue(field, answer) {
4608
4617
  if (!answer || answer.delegated) return void 0;
4609
4618
  switch (field.kind) {
4610
- case "string":
4611
- return answer.text?.trim() ? answer.text : void 0;
4619
+ case "string": {
4620
+ const text = answer.text;
4621
+ if (text === void 0) return void 0;
4622
+ if (!text.trim() && !field.required) return void 0;
4623
+ return text;
4624
+ }
4612
4625
  case "number":
4613
4626
  case "integer":
4614
4627
  return answer.text?.trim() || void 0;
@@ -4695,8 +4708,14 @@ async function readConfig(path2) {
4695
4708
  async function writeConfig(path2, cfg) {
4696
4709
  const raw = JSON.stringify(cfg, null, 2);
4697
4710
  const tmp = `${path2}.${process.pid}.${randomBytes3(6).toString("hex")}.tmp`;
4698
- await fs.writeFile(tmp, raw, "utf8");
4711
+ let mode = 384;
4712
+ try {
4713
+ mode = (await fs.stat(path2)).mode & 511;
4714
+ } catch {
4715
+ }
4699
4716
  try {
4717
+ await fs.writeFile(tmp, raw, { encoding: "utf8", mode });
4718
+ await fs.chmod(tmp, mode);
4700
4719
  await fs.rename(tmp, path2);
4701
4720
  } catch (err) {
4702
4721
  await fs.rm(tmp, { force: true });
@@ -5130,52 +5149,59 @@ function healthStateFor(connectionState, operations, enabled = true) {
5130
5149
  function evaluateHealthThresholds(operations, thresholds) {
5131
5150
  if (!thresholds) return [];
5132
5151
  const checks = [];
5133
- if (thresholds.connectionLatencyP95Ms !== void 0 && operations.connectionSamples.length > 0) {
5152
+ const connectionP95 = thresholds.connectionLatencyP95Ms;
5153
+ if (isUsableThreshold(connectionP95) && operations.connectionSamples.length > 0) {
5134
5154
  const value = percentile(
5135
5155
  [...operations.connectionSamples].sort((a, b) => a - b),
5136
5156
  0.95
5137
5157
  );
5138
5158
  checks.push({
5139
5159
  name: "connection-latency-p95",
5140
- passed: value <= thresholds.connectionLatencyP95Ms,
5160
+ passed: value <= connectionP95,
5141
5161
  value,
5142
- threshold: thresholds.connectionLatencyP95Ms
5162
+ threshold: connectionP95
5143
5163
  });
5144
5164
  }
5145
- if (thresholds.discoveryLatencyP95Ms !== void 0 && operations.discoverySamples.length > 0) {
5165
+ const discoveryP95 = thresholds.discoveryLatencyP95Ms;
5166
+ if (isUsableThreshold(discoveryP95) && operations.discoverySamples.length > 0) {
5146
5167
  const value = percentile(
5147
5168
  [...operations.discoverySamples].sort((a, b) => a - b),
5148
5169
  0.95
5149
5170
  );
5150
5171
  checks.push({
5151
5172
  name: "discovery-latency-p95",
5152
- passed: value <= thresholds.discoveryLatencyP95Ms,
5173
+ passed: value <= discoveryP95,
5153
5174
  value,
5154
- threshold: thresholds.discoveryLatencyP95Ms
5175
+ threshold: discoveryP95
5155
5176
  });
5156
5177
  }
5157
- if (thresholds.callLatencyP95Ms !== void 0 && operations.callSamples.length > 0) {
5178
+ const callP95 = thresholds.callLatencyP95Ms;
5179
+ if (isUsableThreshold(callP95) && operations.callSamples.length > 0) {
5158
5180
  const value = percentile(
5159
5181
  [...operations.callSamples].sort((a, b) => a - b),
5160
5182
  0.95
5161
5183
  );
5162
5184
  checks.push({
5163
5185
  name: "call-latency-p95",
5164
- passed: value <= thresholds.callLatencyP95Ms,
5186
+ passed: value <= callP95,
5165
5187
  value,
5166
- threshold: thresholds.callLatencyP95Ms
5188
+ threshold: callP95
5167
5189
  });
5168
5190
  }
5169
- if (thresholds.inFlightCalls !== void 0) {
5191
+ const inFlight = thresholds.inFlightCalls;
5192
+ if (isUsableThreshold(inFlight)) {
5170
5193
  checks.push({
5171
5194
  name: "in-flight-calls",
5172
- passed: operations.peakInFlightCalls <= thresholds.inFlightCalls,
5195
+ passed: operations.peakInFlightCalls <= inFlight,
5173
5196
  value: operations.peakInFlightCalls,
5174
- threshold: thresholds.inFlightCalls
5197
+ threshold: inFlight
5175
5198
  });
5176
5199
  }
5177
5200
  return checks;
5178
5201
  }
5202
+ function isUsableThreshold(value) {
5203
+ return typeof value === "number" && Number.isFinite(value);
5204
+ }
5179
5205
  function applyHealthThresholds(state, checks) {
5180
5206
  if (state !== "healthy") return state;
5181
5207
  return checks.some((c) => !c.passed) ? "degraded" : "healthy";
@@ -6902,6 +6928,7 @@ function serveStdio(server, opts = {}) {
6902
6928
  let bufferBytes = 0;
6903
6929
  let closed = false;
6904
6930
  let bufferTooLarge = false;
6931
+ const decoder = new TextDecoder();
6905
6932
  let writeChain = Promise.resolve();
6906
6933
  const inFlightHandlers = /* @__PURE__ */ new Set();
6907
6934
  const writeLine = (s) => {
@@ -6924,7 +6951,7 @@ function serveStdio(server, opts = {}) {
6924
6951
  };
6925
6952
  const onData = (chunk) => {
6926
6953
  if (bufferTooLarge) return;
6927
- const text = typeof chunk === "string" ? chunk : chunk.toString("utf8");
6954
+ const text = typeof chunk === "string" ? chunk : decoder.decode(chunk, { stream: true });
6928
6955
  buffer += text;
6929
6956
  bufferBytes += Buffer.byteLength(text, "utf8");
6930
6957
  if (bufferBytes > HTTP_BODY_CAP) {
@@ -7215,8 +7242,8 @@ var MCPVaultTokenStore = class {
7215
7242
  async readFile() {
7216
7243
  let raw;
7217
7244
  try {
7218
- const stat2 = await fs3.stat(this.filePath);
7219
- if (stat2.size > MAX_STORE_BYTES) throw new Error("MCP token store exceeds size limit");
7245
+ const stat3 = await fs3.stat(this.filePath);
7246
+ if (stat3.size > MAX_STORE_BYTES) throw new Error("MCP token store exceeds size limit");
7220
7247
  raw = await fs3.readFile(this.filePath, "utf8");
7221
7248
  } catch (error) {
7222
7249
  if (error.code === "ENOENT") return emptyFile();
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@wrongstack/mcp",
3
- "version": "1.0.27",
3
+ "version": "1.0.28",
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": "1.0.27",
29
+ "@wrongstack/core": "1.0.28",
30
30
  "undici": "^8.10.2"
31
31
  },
32
32
  "devDependencies": {