toolcraft 0.0.415 → 0.0.417

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/composition.json CHANGED
@@ -98,7 +98,7 @@
98
98
  },
99
99
  {
100
100
  "name": "tiny-http-mcp-server",
101
- "version": "0.1.89",
101
+ "version": "0.1.90",
102
102
  "license": "MIT"
103
103
  },
104
104
  {
@@ -113,7 +113,7 @@
113
113
  },
114
114
  {
115
115
  "name": "toolcraft",
116
- "version": "0.0.415",
116
+ "version": "0.0.417",
117
117
  "license": "MIT"
118
118
  },
119
119
  {
@@ -123,7 +123,7 @@
123
123
  },
124
124
  {
125
125
  "name": "toolcraft-schema",
126
- "version": "0.0.415",
126
+ "version": "0.0.417",
127
127
  "license": "MIT"
128
128
  },
129
129
  {
@@ -98,7 +98,7 @@
98
98
  },
99
99
  {
100
100
  "name": "tiny-http-mcp-server",
101
- "version": "0.1.89",
101
+ "version": "0.1.90",
102
102
  "license": "MIT"
103
103
  },
104
104
  {
@@ -113,7 +113,7 @@
113
113
  },
114
114
  {
115
115
  "name": "toolcraft",
116
- "version": "0.0.415",
116
+ "version": "0.0.417",
117
117
  "license": "MIT"
118
118
  },
119
119
  {
@@ -123,7 +123,7 @@
123
123
  },
124
124
  {
125
125
  "name": "toolcraft-schema",
126
- "version": "0.0.415",
126
+ "version": "0.0.417",
127
127
  "license": "MIT"
128
128
  },
129
129
  {
@@ -18,7 +18,7 @@
18
18
  },
19
19
  {
20
20
  "name": "tiny-http-mcp-server",
21
- "version": "0.1.89",
21
+ "version": "0.1.90",
22
22
  "license": "MIT"
23
23
  },
24
24
  {
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "tiny-http-mcp-server",
3
- "version": "0.1.89",
3
+ "version": "0.1.90",
4
4
  "description": "Minimal MCP server over HTTP built on tiny-stdio-mcp-server",
5
5
  "type": "module",
6
6
  "main": "dist/index.js",
@@ -73,6 +73,12 @@ before OAuth callbacks run. Invalid headers fail without reflecting their values
73
73
  Use `snapshotHttpTransportHeaders(headers)` to apply the same ownership and safe
74
74
  validation when preparing a registry before constructing transports.
75
75
  `maxResponseBytes` bounds a complete JSON body or each SSE event (default 16 MiB).
76
+ Before deserialization, HTTP JSON-RPC messages also have fixed per-message limits:
77
+ 100,000 nodes (including keys), 64 container levels, 4 MiB of decoded UTF-16
78
+ strings, and an 8 MiB allocation estimate (128 bytes per node plus string storage).
79
+ The first limit reached rejects the reply. These conservative admission limits
80
+ protect Worker hosts from compact object amplification; they are not exact heap
81
+ measurements. Increasing the byte limit does not increase the structural limits.
76
82
  Receive streams may carry many bounded events and keepalive comments; the limit
77
83
  does not cap their lifetime bytes. Use request deadlines and cancellation to
78
84
  bound pending operations.
@@ -65,6 +65,65 @@ var init_inMemory = __esm({
65
65
  }
66
66
  });
67
67
 
68
+ // src/http-json-budget.ts
69
+ function assertHttpJsonBudget(text) {
70
+ let nodes = 0;
71
+ let allocation = 0;
72
+ let decodedBytes = 0;
73
+ const stack = [];
74
+ const whitespace = (c) => c === " " || c === " " || c === "\r" || c === "\n";
75
+ const check = () => {
76
+ if (nodes > 1e5 || stack.length > 64 || allocation > 8 * 1024 * 1024 || decodedBytes > 4 * 1024 * 1024)
77
+ throw new Error("MCP HTTP JSON structural budget exceeded");
78
+ };
79
+ for (let i = 0; i < text.length; ) {
80
+ const c = text[i++];
81
+ if (whitespace(c) || c === "," || c === ":") continue;
82
+ if (c === "}" || c === "]") {
83
+ if (stack.pop() !== c) throw new SyntaxError("Malformed MCP HTTP JSON nesting");
84
+ continue;
85
+ }
86
+ nodes++;
87
+ allocation += 128;
88
+ if (c === "{" || c === "[") {
89
+ stack.push(c === "{" ? "}" : "]");
90
+ check();
91
+ continue;
92
+ }
93
+ check();
94
+ if (c === '"') {
95
+ let closed = false;
96
+ while (i < text.length) {
97
+ const character = text[i++];
98
+ if (character === '"') {
99
+ closed = true;
100
+ break;
101
+ }
102
+ if (character.charCodeAt(0) < 32) throw new SyntaxError("Malformed MCP HTTP JSON string");
103
+ if (character === "\\") {
104
+ const escape = text[i++];
105
+ if (escape === "u") {
106
+ for (let digit = 0; digit < 4; digit++) {
107
+ const hex = text[i++];
108
+ if (hex === void 0 || !"0123456789abcdefABCDEF".includes(hex))
109
+ throw new SyntaxError("Malformed MCP HTTP JSON escape");
110
+ }
111
+ } else if (escape === void 0 || !'"\\/bfnrt'.includes(escape)) {
112
+ throw new SyntaxError("Malformed MCP HTTP JSON escape");
113
+ }
114
+ }
115
+ decodedBytes += 2;
116
+ allocation += 2;
117
+ check();
118
+ }
119
+ if (!closed) throw new SyntaxError("Unterminated MCP HTTP JSON string");
120
+ } else {
121
+ while (i < text.length && !whitespace(text[i]) && !'{}[],:"'.includes(text[i])) i++;
122
+ }
123
+ }
124
+ if (stack.length !== 0) throw new SyntaxError("Unterminated MCP HTTP JSON container");
125
+ }
126
+
68
127
  // src/internal.ts
69
128
  import { spawn as spawn2 } from "node:child_process";
70
129
  import { PassThrough } from "node:stream";
@@ -8208,6 +8267,7 @@ var HttpTransport = class {
8208
8267
  signal
8209
8268
  )).trim();
8210
8269
  if (request !== void 0 && responseBody.length > 0) {
8270
+ assertHttpJsonBudget(responseBody);
8211
8271
  let parsed = parseJsonRpcMessage(responseBody);
8212
8272
  if (parsed.type === "invalid") {
8213
8273
  try {
@@ -8361,6 +8421,7 @@ var HttpTransport = class {
8361
8421
  if (context !== void 0) throw new Error("MCP HTTP response body is empty");
8362
8422
  return;
8363
8423
  }
8424
+ assertHttpJsonBudget(payload);
8364
8425
  if (context !== void 0) {
8365
8426
  this.writeReadableLine(context.validate(payload, false));
8366
8427
  return;
@@ -8383,6 +8444,7 @@ var HttpTransport = class {
8383
8444
  this.rejectLegacyEndpoint = void 0;
8384
8445
  continue;
8385
8446
  }
8447
+ assertHttpJsonBudget(message.data);
8386
8448
  this.writeReadableLine(context?.validate(message.data, true) ?? message.data);
8387
8449
  if (context?.completed) return;
8388
8450
  }
@@ -8,7 +8,7 @@
8
8
  },
9
9
  {
10
10
  "name": "toolcraft-schema",
11
- "version": "0.0.415",
11
+ "version": "0.0.417",
12
12
  "license": "MIT"
13
13
  }
14
14
  ]
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "toolcraft-schema",
3
- "version": "0.0.415",
3
+ "version": "0.0.417",
4
4
  "license": "MIT",
5
5
  "type": "module",
6
6
  "main": "dist/index.js",
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "toolcraft",
3
- "version": "0.0.415",
3
+ "version": "0.0.417",
4
4
  "license": "MIT",
5
5
  "type": "module",
6
6
  "main": "dist/index.js",
@@ -162,7 +162,7 @@
162
162
  "yaml"
163
163
  ],
164
164
  "optionalDependencies": {
165
- "toolcraft-schema": "0.0.415",
165
+ "toolcraft-schema": "0.0.417",
166
166
  "toolcraft-design": "*",
167
167
  "@poe-code/frontmatter": "*",
168
168
  "@poe-code/agent-mcp-config": "*",