@wrongstack/mcp 1.0.28 → 1.0.29

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 CHANGED
@@ -2008,6 +2008,7 @@ var ServerRequestResponder = class {
2008
2008
  import { ToolError as ToolError2 } from "@wrongstack/core/types";
2009
2009
  var MAX_MCP_HTTP_BODY_BYTES = 16 * 1024 * 1024;
2010
2010
  async function readBodyCapped(res, maxBytes = MAX_MCP_HTTP_BODY_BYTES) {
2011
+ const safeCap = typeof maxBytes === "number" && Number.isFinite(maxBytes) && maxBytes >= 0 ? maxBytes : MAX_MCP_HTTP_BODY_BYTES;
2011
2012
  const body = res.body;
2012
2013
  if (!body || typeof body.getReader !== "function") {
2013
2014
  return await res.text();
@@ -2021,13 +2022,13 @@ async function readBodyCapped(res, maxBytes = MAX_MCP_HTTP_BODY_BYTES) {
2021
2022
  if (done) break;
2022
2023
  if (!value) continue;
2023
2024
  total += value.byteLength;
2024
- if (total > maxBytes) {
2025
+ if (total > safeCap) {
2025
2026
  await reader.cancel().catch(() => void 0);
2026
2027
  throw new ToolError2({
2027
- message: `MCP response body exceeded ${maxBytes} bytes \u2014 refusing to buffer`,
2028
+ message: `MCP response body exceeded ${safeCap} bytes \u2014 refusing to buffer`,
2028
2029
  code: "TOOL_EXECUTION_FAILED",
2029
2030
  toolName: "mcp_transport",
2030
- context: { maxBytes, received: total }
2031
+ context: { maxBytes: safeCap, received: total }
2031
2032
  });
2032
2033
  }
2033
2034
  chunks.push(value);
@@ -2232,15 +2233,16 @@ function createTimeoutSignal(parent, timeoutMs, hold) {
2232
2233
  } else {
2233
2234
  parent?.addEventListener("abort", onAbort, { once: true });
2234
2235
  }
2236
+ const safeTimeout = typeof timeoutMs === "number" && Number.isFinite(timeoutMs) && timeoutMs > 0 ? timeoutMs : 6e4;
2235
2237
  const onTimeout = () => {
2236
2238
  if (hold?.()) {
2237
- timer = setTimeout(onTimeout, timeoutMs);
2239
+ timer = setTimeout(onTimeout, safeTimeout);
2238
2240
  timer.unref?.();
2239
2241
  return;
2240
2242
  }
2241
- ctrl.abort(new Error(`MCP HTTP request timed out after ${timeoutMs}ms`));
2243
+ ctrl.abort(new Error(`MCP HTTP request timed out after ${safeTimeout}ms`));
2242
2244
  };
2243
- let timer = setTimeout(onTimeout, timeoutMs);
2245
+ let timer = setTimeout(onTimeout, safeTimeout);
2244
2246
  timer.unref?.();
2245
2247
  return {
2246
2248
  signal: ctrl.signal,
@@ -2283,8 +2285,8 @@ var BaseHTTPTransport = class {
2283
2285
  this.headers = { ...opts.headers };
2284
2286
  this.authorizationProvider = opts.authorizationProvider;
2285
2287
  this.authorizationResource = canonicalMcpResource(opts.url);
2286
- this.timeout = opts.startupTimeoutMs ?? 1e4;
2287
- this.requestTimeout = opts.requestTimeoutMs ?? 6e4;
2288
+ this.timeout = typeof opts.startupTimeoutMs === "number" && Number.isFinite(opts.startupTimeoutMs) && opts.startupTimeoutMs > 0 ? opts.startupTimeoutMs : 1e4;
2289
+ this.requestTimeout = typeof opts.requestTimeoutMs === "number" && Number.isFinite(opts.requestTimeoutMs) && opts.requestTimeoutMs > 0 ? opts.requestTimeoutMs : 6e4;
2288
2290
  if (opts.tls) {
2289
2291
  if (opts.tls.rejectUnauthorized === false) {
2290
2292
  const where = urlOriginForLog(this.url);
@@ -3798,7 +3800,7 @@ var MCPClient = class _MCPClient {
3798
3800
  capabilities: this.serverRequests.capabilities(),
3799
3801
  clientInfo: MCP_CONSTANTS.CLIENT_INFO
3800
3802
  },
3801
- this.opts.startupTimeoutMs ?? 1e4
3803
+ typeof this.opts.startupTimeoutMs === "number" && Number.isFinite(this.opts.startupTimeoutMs) && this.opts.startupTimeoutMs > 0 ? this.opts.startupTimeoutMs : 1e4
3802
3804
  );
3803
3805
  if (initialize.error) {
3804
3806
  this.state = "failed";
@@ -3923,9 +3925,13 @@ var MCPClient = class _MCPClient {
3923
3925
  await Promise.allSettled([this.sseTransport?.close(), this.httpTransport?.close()]);
3924
3926
  this.state = "disconnected";
3925
3927
  }
3926
- request(method, params, timeoutMs = this.opts.requestTimeoutMs ?? 6e4, opts) {
3927
- if (this.sseTransport) return this.sseTransport.request(method, params, timeoutMs, opts);
3928
- if (this.httpTransport) return this.httpTransport.request(method, params, timeoutMs, opts);
3928
+ request(method, params, timeoutMs, opts) {
3929
+ const defaultTimeoutMs = typeof this.opts.requestTimeoutMs === "number" && Number.isFinite(this.opts.requestTimeoutMs) && this.opts.requestTimeoutMs > 0 ? this.opts.requestTimeoutMs : 6e4;
3930
+ const effectiveTimeoutMs = typeof timeoutMs === "number" && Number.isFinite(timeoutMs) && timeoutMs > 0 ? timeoutMs : defaultTimeoutMs;
3931
+ if (this.sseTransport)
3932
+ return this.sseTransport.request(method, params, effectiveTimeoutMs, opts);
3933
+ if (this.httpTransport)
3934
+ return this.httpTransport.request(method, params, effectiveTimeoutMs, opts);
3929
3935
  const signal = opts?.signal;
3930
3936
  if (signal?.aborted) {
3931
3937
  const err = new Error(`MCP "${this.opts.name}" request "${method}" aborted before send`);
@@ -3955,13 +3961,15 @@ var MCPClient = class _MCPClient {
3955
3961
  };
3956
3962
  const onTimeout = () => {
3957
3963
  if (this.serverRequests.awaitingUser) {
3958
- entry.timer = setTimeout(onTimeout, timeoutMs);
3964
+ entry.timer = setTimeout(onTimeout, effectiveTimeoutMs);
3959
3965
  return;
3960
3966
  }
3961
3967
  this.pending.delete(id);
3962
3968
  detach();
3963
3969
  reject(
3964
- new Error(`MCP "${this.opts.name}" request "${method}" timed out after ${timeoutMs}ms`)
3970
+ new Error(
3971
+ `MCP "${this.opts.name}" request "${method}" timed out after ${effectiveTimeoutMs}ms`
3972
+ )
3965
3973
  );
3966
3974
  };
3967
3975
  const entry = {
@@ -3975,7 +3983,7 @@ var MCPClient = class _MCPClient {
3975
3983
  detach();
3976
3984
  reject(err);
3977
3985
  },
3978
- timer: setTimeout(onTimeout, timeoutMs)
3986
+ timer: setTimeout(onTimeout, effectiveTimeoutMs)
3979
3987
  };
3980
3988
  this.pending.set(id, entry);
3981
3989
  const stdin = this.child?.stdin;
@@ -6649,6 +6657,7 @@ var MCPServer = class {
6649
6657
  logger;
6650
6658
  resources;
6651
6659
  prompts;
6660
+ instructions;
6652
6661
  inFlightRequests = /* @__PURE__ */ new Map();
6653
6662
  constructor(opts) {
6654
6663
  this.host = opts.host;
@@ -6657,6 +6666,7 @@ var MCPServer = class {
6657
6666
  version: MCP_CONSTANTS.CLIENT_INFO.version
6658
6667
  };
6659
6668
  this.logger = opts.logger;
6669
+ this.instructions = opts.instructions?.trim() || void 0;
6660
6670
  this.resources = structuredClone(opts.resources ?? []);
6661
6671
  this.prompts = structuredClone(opts.prompts ?? []);
6662
6672
  }
@@ -6723,7 +6733,8 @@ var MCPServer = class {
6723
6733
  ...this.resources.length > 0 ? { resources: { subscribe: false, listChanged: false } } : {},
6724
6734
  ...this.prompts.length > 0 ? { prompts: { listChanged: false } } : {}
6725
6735
  },
6726
- serverInfo: this.serverInfo
6736
+ serverInfo: this.serverInfo,
6737
+ ...this.instructions ? { instructions: this.instructions } : {}
6727
6738
  };
6728
6739
  case "ping":
6729
6740
  return {};
@@ -6777,7 +6788,7 @@ var MCPServer = class {
6777
6788
  const input = paramsRecord(params);
6778
6789
  const args = stringRecord(input["arguments"], "prompts/get arguments");
6779
6790
  for (const argument of prompt.arguments ?? []) {
6780
- if (argument.required && args[argument.name] === void 0) {
6791
+ if (argument.required && !Object.hasOwn(args, argument.name)) {
6781
6792
  throw new Error(`Prompt "${name}" requires argument "${argument.name}"`);
6782
6793
  }
6783
6794
  }
@@ -6876,11 +6887,11 @@ function requiredParamString(params, field, method) {
6876
6887
  return value;
6877
6888
  }
6878
6889
  function stringRecord(value, label2) {
6879
- if (value === void 0) return {};
6890
+ if (value === void 0) return /* @__PURE__ */ Object.create(null);
6880
6891
  if (!value || typeof value !== "object" || Array.isArray(value)) {
6881
6892
  throw new Error(`${label2} must be an object`);
6882
6893
  }
6883
- const result = {};
6894
+ const result = /* @__PURE__ */ Object.create(null);
6884
6895
  for (const [key, item] of Object.entries(value)) {
6885
6896
  if (typeof item !== "string") throw new Error(`${label2}.${key} must be a string`);
6886
6897
  result[key] = item;
@@ -6889,7 +6900,7 @@ function stringRecord(value, label2) {
6889
6900
  }
6890
6901
  function renderPromptTemplate(template, args) {
6891
6902
  return template.replace(/\{\{([A-Za-z_][A-Za-z0-9_.-]*)\}\}/g, (_match, name) => {
6892
- const value = args[name];
6903
+ const value = Object.hasOwn(args, name) ? args[name] : void 0;
6893
6904
  if (value === void 0) throw new Error(`Missing prompt template argument "${name}"`);
6894
6905
  return value;
6895
6906
  });
package/dist/server.d.ts CHANGED
@@ -67,6 +67,11 @@ export interface MCPServerOptions {
67
67
  resources?: MCPServerResource[] | undefined;
68
68
  /** Explicit allowlist only; omitted means this server exposes no prompts. */
69
69
  prompts?: MCPServerPrompt[] | undefined;
70
+ /**
71
+ * `InitializeResult.instructions`: how and when to use this server. Clients
72
+ * that honour it (Claude Code does) put it in front of the model.
73
+ */
74
+ instructions?: string | undefined;
70
75
  }
71
76
  export declare class MCPServer {
72
77
  private readonly host;
@@ -74,6 +79,7 @@ export declare class MCPServer {
74
79
  private readonly logger?;
75
80
  private readonly resources;
76
81
  private readonly prompts;
82
+ private readonly instructions;
77
83
  private readonly inFlightRequests;
78
84
  constructor(opts: MCPServerOptions);
79
85
  /**
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@wrongstack/mcp",
3
- "version": "1.0.28",
3
+ "version": "1.0.29",
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.28",
29
+ "@wrongstack/core": "1.0.29",
30
30
  "undici": "^8.10.2"
31
31
  },
32
32
  "devDependencies": {