okengine 0.23.1 → 0.23.2
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/package.json +1 -1
- package/site/content/docs/ai/mcp.mdx +3 -3
- package/site/content/docs/elements/signal/broadcast.mdx +4 -2
- package/site/content/docs/reference/configuration.mdx +16 -0
- package/site/content/docs/reference/errors.mdx +31 -19
- package/src/compiler/aot.test.ts +3 -2
- package/src/compiler/aot.ts +45 -1
- package/src/compiler/dynamic.ts +1 -1
- package/src/compiler/http-parse.test.ts +101 -0
- package/src/compiler/http-parse.ts +188 -9
- package/src/compiler/interpret.ts +25 -2
- package/src/console/ui-next/dist/assets/{access-page-C_N4qvai.js → access-page-zBMhZnFm.js} +1 -1
- package/src/console/ui-next/dist/assets/{agent-disclosure-Cq1TxniW.js → agent-disclosure-CBj9f7Ju.js} +1 -1
- package/src/console/ui-next/dist/assets/{cache-glyph-BaI4uxZz.js → cache-glyph-D3MY49h3.js} +1 -1
- package/src/console/ui-next/dist/assets/{call-pii-button-DNyK7IIY.js → call-pii-button-L9JxdBhp.js} +1 -1
- package/src/console/ui-next/dist/assets/{collapsible-CRhBJMZR.js → collapsible-BvFaX-Zt.js} +1 -1
- package/src/console/ui-next/dist/assets/{decisions-page-D9twj8Xy.js → decisions-page-DgB76m-X.js} +1 -1
- package/src/console/ui-next/dist/assets/{duration-tone-CsHWlVPU.js → duration-tone-l1DSJ2Vz.js} +1 -1
- package/src/console/ui-next/dist/assets/{flows-page-ZaTJAhR9.js → flows-page-Bb9t1lu6.js} +1 -1
- package/src/console/ui-next/dist/assets/{highlighted-json-DQ-EMAfz.js → highlighted-json-DMvsi3Ti.js} +1 -1
- package/src/console/ui-next/dist/assets/{http-method-Cn_Fl79s.js → http-method-BwhJBTcQ.js} +1 -1
- package/src/console/ui-next/dist/assets/{index-CmRFeWdT.js → index-RhV2jT_7.js} +3 -3
- package/src/console/ui-next/dist/assets/{observability-page-Cn6R_dXz.js → observability-page-BRfUILBq.js} +1 -1
- package/src/console/ui-next/dist/assets/{replica-lag-Bx6EZhSe.js → replica-lag-BsceAzIG.js} +1 -1
- package/src/console/ui-next/dist/assets/{request-meta-DmdiUrfh.js → request-meta-C6lTyCXp.js} +1 -1
- package/src/console/ui-next/dist/assets/{store-page-8P6vGXnn.js → store-page-YmE806bJ.js} +1 -1
- package/src/console/ui-next/dist/assets/{trace-detail-sheet-BfGvpFSv.js → trace-detail-sheet-Di4irS49.js} +1 -1
- package/src/console/ui-next/dist/assets/{tree-expand-toggle-CWdUHbc0.js → tree-expand-toggle-DYeL6Rye.js} +1 -1
- package/src/console/ui-next/dist/assets/{units-page-CZOFZzay.js → units-page-07agasRA.js} +1 -1
- package/src/console/ui-next/dist/assets/{vault-page-ki_ishmX.js → vault-page-CHBck4n_.js} +1 -1
- package/src/console/ui-next/dist/index.html +1 -1
- package/src/console/ui-next/seed-parked-approval.ts +5 -1
- package/src/drivers/journal-postgres.test.ts +84 -1
- package/src/drivers/journal-postgres.ts +282 -32
- package/src/drivers/postgres.test.ts +60 -0
- package/src/drivers/postgres.ts +79 -5
- package/src/drivers/signal-compete.test.ts +6 -2
- package/src/drivers/signal-postgres.test.ts +170 -0
- package/src/drivers/signal-postgres.ts +449 -196
- package/src/drivers/signal-redis.test.ts +224 -0
- package/src/drivers/signal-redis.ts +835 -150
- package/src/elements/ai/approval.test.ts +15 -3
- package/src/elements/ai/approval.ts +15 -9
- package/src/elements/channel/runtime.ts +31 -4
- package/src/elements/channel/sql-ledger.test.ts +404 -0
- package/src/elements/channel/sql-ledger.ts +177 -33
- package/src/elements/clock/chaos-child.ts +12 -2
- package/src/elements/clock/durable.ts +11 -0
- package/src/elements/store/cache-bus.test.ts +121 -0
- package/src/elements/store/cache-bus.ts +278 -0
- package/src/elements/store/cache.test.ts +59 -0
- package/src/elements/store/cache.ts +157 -12
- package/src/elements/store/runtime.ts +44 -2
- package/src/elements/store/sql-errors.test.ts +131 -0
- package/src/elements/store/sql-errors.ts +39 -16
- package/src/elements/store/sql-nested-tx.test.ts +344 -0
- package/src/elements/store/sql-session.ts +183 -3
- package/src/kernel/app.ts +176 -28
- package/src/kernel/auto-registry.test.ts +5 -1
- package/src/kernel/boot-bind/signal.ts +13 -2
- package/src/kernel/boot-bind/store.ts +16 -1
- package/src/kernel/boot.test.ts +2 -2
- package/src/kernel/boot.ts +41 -11
- package/src/kernel/boundary-contract.ts +7 -0
- package/src/kernel/builtin-errors.ts +2 -0
- package/src/kernel/call.test.ts +1 -0
- package/src/kernel/fx-sql-handle.ts +7 -1
- package/src/kernel/horizontal-child.ts +54 -1
- package/src/kernel/horizontal.integration.test.ts +131 -7
- package/src/kernel/idempotency.test.ts +5 -6
- package/src/kernel/journal-boot.test.ts +83 -6
- package/src/kernel/journal.test.ts +44 -0
- package/src/kernel/journal.ts +171 -26
- package/src/mcp/authorization.ts +5 -11
- package/src/mcp/confirmation.ts +203 -38
- package/src/mcp/docs-server.ts +7 -2
- package/src/mcp/index.ts +4 -0
- package/src/mcp/mcp.test.ts +321 -33
- package/src/mcp/server.ts +8 -3
- package/src/mcp/session.ts +7 -0
- package/src/mcp/tools.ts +68 -19
- package/src/runtime/bun.ts +5 -0
- package/src/runtime/types.ts +5 -0
package/src/mcp/confirmation.ts
CHANGED
|
@@ -5,27 +5,82 @@
|
|
|
5
5
|
* re-validating is how tool poisoning and rug pulls persist. Every write
|
|
6
6
|
* (or otherwise sensitive) tool invocation must carry a fresh confirmation
|
|
7
7
|
* token that was issued for that exact tool + arguments digest.
|
|
8
|
+
*
|
|
9
|
+
* The requester and the issuer are different auth sessions (`claims.sid`),
|
|
10
|
+
* even when they are the same principal. A write without a token returns an
|
|
11
|
+
* opaque confirmation id bound to the requester. `oke.action.confirm` mints
|
|
12
|
+
* the token only from another session. Only the requester session can
|
|
13
|
+
* consume it, and the issuer session cannot.
|
|
14
|
+
*
|
|
15
|
+
* Pending rows live in this process only. A token issued on another process
|
|
16
|
+
* is absent here and fails closed with `"unknown"`. Do not add shared storage.
|
|
8
17
|
*/
|
|
9
18
|
|
|
10
19
|
/** Typed confirmation phrase for irreversible MCP writes. */
|
|
11
20
|
export const MCP_CONFIRM_PHRASE = "CONFIRM" as const;
|
|
12
21
|
|
|
13
|
-
/**
|
|
22
|
+
/**
|
|
23
|
+
* Auth session a confirmation is bound to.
|
|
24
|
+
*
|
|
25
|
+
* `sid` is `McpRequester.sessionId` (`claims.sid`), not the MCP transport
|
|
26
|
+
* session id from `initialize`.
|
|
27
|
+
*/
|
|
28
|
+
export interface ConfirmationTarget {
|
|
29
|
+
/** Operator principal id (`claims.sub`). */
|
|
30
|
+
readonly principalId: string;
|
|
31
|
+
/** Auth session id (`claims.sid`). */
|
|
32
|
+
readonly sid: string;
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
/**
|
|
36
|
+
* Confirmation after a different session has issued its token.
|
|
37
|
+
*
|
|
38
|
+
* The write rejection that opens a confirmation never carries `token`.
|
|
39
|
+
*/
|
|
14
40
|
export interface PendingConfirmation {
|
|
15
|
-
/**
|
|
41
|
+
/** Opaque id returned to the requester. Not a token. */
|
|
42
|
+
readonly confirmationId: string;
|
|
43
|
+
/** Cryptographically random token. Present only after issue. */
|
|
16
44
|
readonly token: string;
|
|
17
45
|
/** Tool name the token authorises. */
|
|
18
46
|
readonly tool: string;
|
|
19
47
|
/** SHA-256 of canonical JSON arguments. */
|
|
20
48
|
readonly argsDigest: string;
|
|
21
|
-
/**
|
|
22
|
-
readonly
|
|
49
|
+
/** Requester the write is bound to. */
|
|
50
|
+
readonly target: ConfirmationTarget;
|
|
51
|
+
/** Auth session that issued the token. Distinct from {@link ConfirmationTarget.sid}. */
|
|
52
|
+
readonly issuerSid: string;
|
|
23
53
|
/** Expiry epoch-ms. */
|
|
24
54
|
readonly expiresAt: number;
|
|
25
|
-
/** Human reason recorded
|
|
55
|
+
/** Human reason recorded when the token was issued. */
|
|
26
56
|
readonly reason: string;
|
|
27
57
|
}
|
|
28
58
|
|
|
59
|
+
/**
|
|
60
|
+
* Opaque handle for a write that still needs another session to confirm.
|
|
61
|
+
*
|
|
62
|
+
* This is not a token and must not be accepted by {@link ConfirmationGate.consume}.
|
|
63
|
+
*/
|
|
64
|
+
export interface OpenConfirmation {
|
|
65
|
+
/** Id to pass to `oke.action.confirm`. */
|
|
66
|
+
readonly confirmationId: string;
|
|
67
|
+
/** Expiry epoch-ms of the pending row. */
|
|
68
|
+
readonly expiresAt: number;
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
/** Result of issuing a confirmation token from a second session. */
|
|
72
|
+
export type ConfirmIssueResult =
|
|
73
|
+
| {
|
|
74
|
+
readonly ok: true;
|
|
75
|
+
readonly token: string;
|
|
76
|
+
readonly tool: string;
|
|
77
|
+
readonly expiresAt: number;
|
|
78
|
+
}
|
|
79
|
+
| {
|
|
80
|
+
readonly ok: false;
|
|
81
|
+
readonly reason: "unknown" | "expired" | "same-session" | "reason-short" | "already-issued";
|
|
82
|
+
};
|
|
83
|
+
|
|
29
84
|
/** Result of consuming a confirmation. */
|
|
30
85
|
export type ConfirmConsumeResult =
|
|
31
86
|
| { readonly ok: true; readonly pending: PendingConfirmation }
|
|
@@ -37,7 +92,8 @@ export type ConfirmConsumeResult =
|
|
|
37
92
|
| "expired"
|
|
38
93
|
| "tool-mismatch"
|
|
39
94
|
| "args-mismatch"
|
|
40
|
-
| "
|
|
95
|
+
| "session-mismatch"
|
|
96
|
+
| "issuer-mismatch"
|
|
41
97
|
| "phrase-mismatch"
|
|
42
98
|
| "reason-short";
|
|
43
99
|
};
|
|
@@ -50,51 +106,128 @@ export interface ConfirmationGateOptions {
|
|
|
50
106
|
}
|
|
51
107
|
|
|
52
108
|
/**
|
|
53
|
-
*
|
|
54
|
-
*
|
|
109
|
+
* In-process confirmation gate with **no session-level cache**.
|
|
110
|
+
*
|
|
111
|
+
* Tokens are single-use and bound to tool + args digest + target session.
|
|
112
|
+
* The map is per process: an id or token issued elsewhere fails closed
|
|
113
|
+
* with `"unknown"`. Do not add shared storage.
|
|
55
114
|
*/
|
|
56
|
-
export
|
|
57
|
-
|
|
115
|
+
export interface ConfirmationGate {
|
|
116
|
+
/**
|
|
117
|
+
* Bind a write attempt to the requester.
|
|
118
|
+
*
|
|
119
|
+
* Returns an opaque confirmation id and never a token.
|
|
120
|
+
*
|
|
121
|
+
* @param input - Tool, arguments, and requester session
|
|
122
|
+
*/
|
|
123
|
+
readonly open: (input: {
|
|
58
124
|
readonly tool: string;
|
|
59
125
|
readonly args: unknown;
|
|
60
|
-
readonly
|
|
126
|
+
readonly target: ConfirmationTarget;
|
|
127
|
+
}) => OpenConfirmation;
|
|
128
|
+
/**
|
|
129
|
+
* Issue a single-use token for an open confirmation.
|
|
130
|
+
*
|
|
131
|
+
* Succeeds only when `callerSid` is not the target session.
|
|
132
|
+
*
|
|
133
|
+
* @param input - Confirmation id, reason, and issuer session
|
|
134
|
+
*/
|
|
135
|
+
readonly issue: (input: {
|
|
136
|
+
readonly confirmationId: string;
|
|
61
137
|
readonly reason: string;
|
|
62
|
-
|
|
138
|
+
readonly callerSid: string;
|
|
139
|
+
}) => ConfirmIssueResult;
|
|
140
|
+
/**
|
|
141
|
+
* Consume a token for one write.
|
|
142
|
+
*
|
|
143
|
+
* Requires `consumerSid === target.sid` and `issuerSid !== consumerSid`,
|
|
144
|
+
* plus single-use, tool, args digest, expiry, and phrase checks.
|
|
145
|
+
*
|
|
146
|
+
* @param input - Write attempt presenting the token
|
|
147
|
+
*/
|
|
63
148
|
readonly consume: (input: {
|
|
64
149
|
readonly tool: string;
|
|
65
150
|
readonly args: unknown;
|
|
66
|
-
readonly
|
|
151
|
+
readonly consumerSid: string;
|
|
67
152
|
readonly token: string;
|
|
68
153
|
readonly phrase: string;
|
|
69
154
|
readonly reason: string;
|
|
70
155
|
}) => ConfirmConsumeResult;
|
|
71
156
|
/** Test helper — pending count (never used for consent caching). */
|
|
72
157
|
readonly size: () => number;
|
|
73
|
-
}
|
|
158
|
+
}
|
|
159
|
+
|
|
160
|
+
/** Mutable row stored in the per-process maps. */
|
|
161
|
+
interface ConfirmationRecord {
|
|
162
|
+
confirmationId: string;
|
|
163
|
+
token: string | null;
|
|
164
|
+
tool: string;
|
|
165
|
+
argsDigest: string;
|
|
166
|
+
target: ConfirmationTarget;
|
|
167
|
+
issuerSid: string | null;
|
|
168
|
+
expiresAt: number;
|
|
169
|
+
reason: string;
|
|
170
|
+
}
|
|
171
|
+
|
|
172
|
+
/**
|
|
173
|
+
* Create a confirmation gate with **no session-level cache**.
|
|
174
|
+
*
|
|
175
|
+
* @param options - Clock and TTL
|
|
176
|
+
*/
|
|
177
|
+
export function createConfirmationGate(options: ConfirmationGateOptions = {}): ConfirmationGate {
|
|
74
178
|
const now = options.now ?? (() => Date.now());
|
|
75
179
|
const ttlMs = options.ttlMs ?? 2 * 60 * 1000;
|
|
76
|
-
|
|
180
|
+
// Per-process only. A token issued on another process is not in these maps
|
|
181
|
+
// and fails closed with "unknown". Do not add shared storage.
|
|
182
|
+
const byId = new Map<string, ConfirmationRecord>();
|
|
183
|
+
const byToken = new Map<string, ConfirmationRecord>();
|
|
77
184
|
|
|
78
185
|
return {
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
const entry: PendingConfirmation = {
|
|
86
|
-
token,
|
|
186
|
+
open(input) {
|
|
187
|
+
prune(byId, byToken, now());
|
|
188
|
+
const confirmationId = `mcp_id_${cryptoRandomHex(24)}`;
|
|
189
|
+
const entry: ConfirmationRecord = {
|
|
190
|
+
confirmationId,
|
|
191
|
+
token: null,
|
|
87
192
|
tool: input.tool,
|
|
88
193
|
argsDigest: digestArgs(input.args),
|
|
89
|
-
|
|
194
|
+
target: input.target,
|
|
195
|
+
issuerSid: null,
|
|
90
196
|
expiresAt: now() + ttlMs,
|
|
91
|
-
reason:
|
|
197
|
+
reason: "",
|
|
92
198
|
};
|
|
93
|
-
|
|
94
|
-
return entry;
|
|
199
|
+
byId.set(confirmationId, entry);
|
|
200
|
+
return { confirmationId, expiresAt: entry.expiresAt };
|
|
201
|
+
},
|
|
202
|
+
issue(input) {
|
|
203
|
+
if (input.reason.trim().length < 3) {
|
|
204
|
+
return { ok: false, reason: "reason-short" };
|
|
205
|
+
}
|
|
206
|
+
prune(byId, byToken, now());
|
|
207
|
+
const entry = byId.get(input.confirmationId);
|
|
208
|
+
if (!entry) {
|
|
209
|
+
return { ok: false, reason: "unknown" };
|
|
210
|
+
}
|
|
211
|
+
if (entry.expiresAt <= now()) {
|
|
212
|
+
drop(byId, byToken, entry);
|
|
213
|
+
return { ok: false, reason: "expired" };
|
|
214
|
+
}
|
|
215
|
+
// Same auth session cannot request, confirm, and invoke.
|
|
216
|
+
if (input.callerSid === entry.target.sid) {
|
|
217
|
+
return { ok: false, reason: "same-session" };
|
|
218
|
+
}
|
|
219
|
+
if (entry.token !== null) {
|
|
220
|
+
return { ok: false, reason: "already-issued" };
|
|
221
|
+
}
|
|
222
|
+
const token = `mcp_c_${cryptoRandomHex(24)}`;
|
|
223
|
+
entry.token = token;
|
|
224
|
+
entry.issuerSid = input.callerSid;
|
|
225
|
+
entry.reason = input.reason.trim();
|
|
226
|
+
byToken.set(token, entry);
|
|
227
|
+
return { ok: true, token, tool: entry.tool, expiresAt: entry.expiresAt };
|
|
95
228
|
},
|
|
96
229
|
consume(input) {
|
|
97
|
-
prune(
|
|
230
|
+
prune(byId, byToken, now());
|
|
98
231
|
if (!input.token) {
|
|
99
232
|
return { ok: false, reason: "missing" };
|
|
100
233
|
}
|
|
@@ -104,12 +237,13 @@ export function createConfirmationGate(options: ConfirmationGateOptions = {}): {
|
|
|
104
237
|
if (input.reason.trim().length < 3) {
|
|
105
238
|
return { ok: false, reason: "reason-short" };
|
|
106
239
|
}
|
|
107
|
-
const entry =
|
|
240
|
+
const entry = byToken.get(input.token);
|
|
108
241
|
if (!entry) {
|
|
242
|
+
// Missing locally — including a token issued on another process.
|
|
109
243
|
return { ok: false, reason: "unknown" };
|
|
110
244
|
}
|
|
111
245
|
// Single-use: remove before further checks so replay fails.
|
|
112
|
-
|
|
246
|
+
drop(byId, byToken, entry);
|
|
113
247
|
if (entry.expiresAt <= now()) {
|
|
114
248
|
return { ok: false, reason: "expired" };
|
|
115
249
|
}
|
|
@@ -119,14 +253,32 @@ export function createConfirmationGate(options: ConfirmationGateOptions = {}): {
|
|
|
119
253
|
if (entry.argsDigest !== digestArgs(input.args)) {
|
|
120
254
|
return { ok: false, reason: "args-mismatch" };
|
|
121
255
|
}
|
|
122
|
-
if (entry.
|
|
123
|
-
return { ok: false, reason: "
|
|
256
|
+
if (entry.target.sid !== input.consumerSid) {
|
|
257
|
+
return { ok: false, reason: "session-mismatch" };
|
|
124
258
|
}
|
|
125
|
-
|
|
259
|
+
if (entry.issuerSid === null || entry.issuerSid === input.consumerSid) {
|
|
260
|
+
return { ok: false, reason: "issuer-mismatch" };
|
|
261
|
+
}
|
|
262
|
+
if (entry.token === null) {
|
|
263
|
+
return { ok: false, reason: "unknown" };
|
|
264
|
+
}
|
|
265
|
+
return {
|
|
266
|
+
ok: true,
|
|
267
|
+
pending: {
|
|
268
|
+
confirmationId: entry.confirmationId,
|
|
269
|
+
token: entry.token,
|
|
270
|
+
tool: entry.tool,
|
|
271
|
+
argsDigest: entry.argsDigest,
|
|
272
|
+
target: entry.target,
|
|
273
|
+
issuerSid: entry.issuerSid,
|
|
274
|
+
expiresAt: entry.expiresAt,
|
|
275
|
+
reason: entry.reason,
|
|
276
|
+
},
|
|
277
|
+
};
|
|
126
278
|
},
|
|
127
279
|
size() {
|
|
128
|
-
prune(
|
|
129
|
-
return
|
|
280
|
+
prune(byId, byToken, now());
|
|
281
|
+
return byId.size;
|
|
130
282
|
},
|
|
131
283
|
};
|
|
132
284
|
}
|
|
@@ -142,6 +294,15 @@ export function digestArgs(args: unknown): string {
|
|
|
142
294
|
return hasher.digest("hex");
|
|
143
295
|
}
|
|
144
296
|
|
|
297
|
+
function drop(
|
|
298
|
+
byId: Map<string, ConfirmationRecord>,
|
|
299
|
+
byToken: Map<string, ConfirmationRecord>,
|
|
300
|
+
entry: ConfirmationRecord,
|
|
301
|
+
): void {
|
|
302
|
+
byId.delete(entry.confirmationId);
|
|
303
|
+
if (entry.token !== null) byToken.delete(entry.token);
|
|
304
|
+
}
|
|
305
|
+
|
|
145
306
|
function cryptoRandomHex(byteLength: number): string {
|
|
146
307
|
const bytes = new Uint8Array(byteLength);
|
|
147
308
|
crypto.getRandomValues(bytes);
|
|
@@ -160,8 +321,12 @@ function canonicalJson(value: unknown): string {
|
|
|
160
321
|
return `{${keys.map((k) => `${JSON.stringify(k)}:${canonicalJson(obj[k])}`).join(",")}}`;
|
|
161
322
|
}
|
|
162
323
|
|
|
163
|
-
function prune(
|
|
164
|
-
|
|
165
|
-
|
|
324
|
+
function prune(
|
|
325
|
+
byId: Map<string, ConfirmationRecord>,
|
|
326
|
+
byToken: Map<string, ConfirmationRecord>,
|
|
327
|
+
t: number,
|
|
328
|
+
): void {
|
|
329
|
+
for (const entry of byId.values()) {
|
|
330
|
+
if (entry.expiresAt <= t) drop(byId, byToken, entry);
|
|
166
331
|
}
|
|
167
332
|
}
|
package/src/mcp/docs-server.ts
CHANGED
|
@@ -11,6 +11,7 @@ import {
|
|
|
11
11
|
forbiddenResponse,
|
|
12
12
|
resolveAllowedHosts,
|
|
13
13
|
} from "../runtime/security.ts";
|
|
14
|
+
import { HttpBodyRejected, parseBody } from "../compiler/http-parse.ts";
|
|
14
15
|
import { DOCS_MCP_PORT, type ServerHandle } from "../runtime/types.ts";
|
|
15
16
|
import { asData } from "./data.ts";
|
|
16
17
|
import { defaultDocsContentDir, loadDocsIndex, type DocsIndex } from "./docs-index.ts";
|
|
@@ -81,8 +82,11 @@ export async function createDocsMcpServer(
|
|
|
81
82
|
|
|
82
83
|
let body: unknown;
|
|
83
84
|
try {
|
|
84
|
-
body = await request
|
|
85
|
-
} catch {
|
|
85
|
+
body = await parseBody(request);
|
|
86
|
+
} catch (err) {
|
|
87
|
+
if (err instanceof HttpBodyRejected && err.code === "PayloadTooLarge") {
|
|
88
|
+
return new Response("Payload Too Large", { status: 413 });
|
|
89
|
+
}
|
|
86
90
|
return jsonRpcHttp(rpcError(null, RpcErrorCode.parse, "invalid JSON body"), 400);
|
|
87
91
|
}
|
|
88
92
|
|
|
@@ -202,6 +206,7 @@ export async function serveDocsMcp(
|
|
|
202
206
|
const server = Bun.serve({
|
|
203
207
|
hostname,
|
|
204
208
|
port,
|
|
209
|
+
maxRequestBodySize: 1_048_576,
|
|
205
210
|
fetch: mcp.fetch,
|
|
206
211
|
});
|
|
207
212
|
const boundPort = server.port ?? port;
|
package/src/mcp/index.ts
CHANGED
|
@@ -32,8 +32,12 @@ export {
|
|
|
32
32
|
createConfirmationGate,
|
|
33
33
|
digestArgs,
|
|
34
34
|
MCP_CONFIRM_PHRASE,
|
|
35
|
+
type ConfirmationGate,
|
|
36
|
+
type ConfirmationTarget,
|
|
35
37
|
type ConfirmConsumeResult,
|
|
38
|
+
type ConfirmIssueResult,
|
|
36
39
|
type ConfirmationGateOptions,
|
|
40
|
+
type OpenConfirmation,
|
|
37
41
|
type PendingConfirmation,
|
|
38
42
|
} from "./confirmation.ts";
|
|
39
43
|
|