@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 +31 -20
- package/dist/server.d.ts +6 -0
- package/package.json +2 -2
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 >
|
|
2025
|
+
if (total > safeCap) {
|
|
2025
2026
|
await reader.cancel().catch(() => void 0);
|
|
2026
2027
|
throw new ToolError2({
|
|
2027
|
-
message: `MCP response body exceeded ${
|
|
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,
|
|
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 ${
|
|
2243
|
+
ctrl.abort(new Error(`MCP HTTP request timed out after ${safeTimeout}ms`));
|
|
2242
2244
|
};
|
|
2243
|
-
let timer = setTimeout(onTimeout,
|
|
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
|
|
2287
|
-
this.requestTimeout = opts.requestTimeoutMs
|
|
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
|
|
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
|
|
3927
|
-
|
|
3928
|
-
|
|
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,
|
|
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(
|
|
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,
|
|
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
|
|
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.
|
|
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.
|
|
29
|
+
"@wrongstack/core": "1.0.29",
|
|
30
30
|
"undici": "^8.10.2"
|
|
31
31
|
},
|
|
32
32
|
"devDependencies": {
|