@blen/fedreg-mcp-server 2.2.1 → 2.2.3

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.
@@ -1,4 +1,5 @@
1
1
  import { preflight } from './policy.js';
2
+ import { DEFAULT_LIMITS, LOG_LINE_OVERHEAD, LOG_TRUNCATED, LogSink, MAX_ERROR_MESSAGE, boundMessage, finishValue, policyMessage, resultTooLarge } from './limits.js';
2
3
  async function loadIvm() {
3
4
  const mod = await import('isolated-vm');
4
5
  const candidate = (typeof mod.Isolate === 'function' ? mod : mod.default ?? {});
@@ -6,12 +7,22 @@ async function loadIvm() {
6
7
  throw new Error('isolated-vm native binding unavailable');
7
8
  return candidate;
8
9
  }
10
+ /**
11
+ * isolated-vm sandbox: a fresh V8 isolate per execution with a heap cap. The host owns a
12
+ * wall-clock deadline that starts before setup: when it fires the isolate
13
+ * is disposed, which stops running code and rejects anything it awaits, and the execution settles
14
+ * once. V8's own `timeout` stays as a second guard for synchronous loops. This runs in the server
15
+ * process, so for hosted multi-user execution prefer the Deno runner (separate process).
16
+ */
9
17
  export class IsolateRunner {
18
+ limits;
10
19
  kind = 'isolate';
20
+ constructor(limits = DEFAULT_LIMITS) {
21
+ this.limits = limits;
22
+ }
11
23
  async available() {
12
24
  try {
13
25
  const ivm = await loadIvm();
14
- // Confirm the native binding actually loaded by exercising it.
15
26
  const iso = new ivm.Isolate({ memoryLimit: 16 });
16
27
  iso.dispose();
17
28
  return true;
@@ -22,78 +33,154 @@ export class IsolateRunner {
22
33
  }
23
34
  async execute(opts, rpc) {
24
35
  const started = Date.now();
36
+ const limits = { ...this.limits, ...(opts.limits ?? {}) };
37
+ const timeoutMs = opts.timeoutMs ?? 15_000;
38
+ const logs = new LogSink(limits.maxLogBytes, limits.maxLogLines);
39
+ const done = (r) => ({ ...r, logs: logs.lines(), durationMs: Date.now() - started });
25
40
  const policy = preflight(opts.code);
26
- if (!policy.ok) {
27
- return {
28
- ok: false,
29
- logs: [],
30
- error: { name: 'PolicyError', message: policy.errors.join('; ') },
31
- durationMs: Date.now() - started,
32
- };
41
+ if (!policy.ok)
42
+ return done({ ok: false, error: { name: 'PolicyError', message: policyMessage(policy.errors) } });
43
+ if (Buffer.byteLength(opts.code, 'utf8') > limits.maxCodeBytes) {
44
+ return done({ ok: false, error: { name: 'CodeTooLarge', message: `Code exceeds ${limits.maxCodeBytes} bytes.` } });
33
45
  }
34
- // dynamic import — keeps the optional dep optional at runtime.
35
46
  const ivm = await loadIvm();
36
- const isolate = new ivm.Isolate({ memoryLimit: opts.memoryMb ?? 64 });
37
- const context = await isolate.createContext();
38
- const jail = context.global;
39
- await jail.set('global', jail.derefInto());
40
- const logs = [];
41
- // host-side log sink
42
- await context.evalClosure(`globalThis.console = { log: (...a) => $0.applyIgnored(undefined, [a.map(String).join(' ')]),
43
- error: (...a) => $0.applyIgnored(undefined, [a.map(String).join(' ')]),
44
- warn: (...a) => $0.applyIgnored(undefined, [a.map(String).join(' ')]),
45
- info: (...a) => $0.applyIgnored(undefined, [a.map(String).join(' ')]) };`, [(line) => logs.push(String(line))], { arguments: { reference: true } });
46
- // RPC bridge — pass the host function directly; `arguments: { reference: true }`
47
- // auto-wraps each argument as a Reference inside the isolate.
48
- const hostRpc = async (binding, path, args) => {
49
- const result = await rpc.dispatch({ binding, path, args });
50
- return new ivm.ExternalCopy(result).copyInto();
51
- };
52
- // Safe to interpolate: binding names are pre-validated as JS identifiers by
53
- // getSources() (src/sdk/sources/index.ts). Do NOT interpolate unvalidated strings here.
54
- const namesLiteral = JSON.stringify(opts.bindings ?? []);
55
- await context.evalClosure(`function makeProxy(binding, rpc) {
56
- const handler = (path) => new Proxy(function(){}, {
57
- get(_, key) { return handler([...path, String(key)]); },
58
- apply(_, __, args) {
59
- return rpc.apply(
60
- undefined,
61
- [binding, path, args],
62
- { arguments: { copy: true }, result: { promise: true, copy: true } },
63
- ).then(r => {
64
- if (!r.ok) { const e = new Error(r.error.message); e.name = r.error.name; throw e; }
65
- return r.value;
66
- });
67
- },
68
- });
69
- return handler([]);
70
- }
71
- for (const name of ${namesLiteral}) { globalThis[name] = makeProxy(name, $0); }`, [hostRpc], { arguments: { reference: true } });
72
- try {
73
- const wrapped = `(async () => { ${opts.code}\n })()`;
74
- const script = await isolate.compileScript(wrapped);
75
- const result = await script.run(context, {
76
- timeout: opts.timeoutMs ?? 15_000,
77
- promise: true,
78
- copy: true,
79
- });
80
- return { ok: true, value: result, logs, durationMs: Date.now() - started };
81
- }
82
- catch (err) {
83
- const e = err;
84
- return {
85
- ok: false,
86
- logs,
87
- error: { name: e.name ?? 'Error', message: e.message ?? String(err), stack: e.stack },
88
- durationMs: Date.now() - started,
89
- };
90
- }
91
- finally {
47
+ const isolate = new ivm.Isolate({ memoryLimit: Math.max(16, opts.memoryMb ?? 64) });
48
+ let disposed = false;
49
+ const dispose = () => { if (!disposed) {
50
+ disposed = true;
92
51
  try {
93
- context.release();
94
52
  isolate.dispose();
95
53
  }
96
54
  catch { /* ignore */ }
55
+ } };
56
+ let stop;
57
+ const stopped = new Promise(resolve => { stop = resolve; });
58
+ const deadline = setTimeout(() => stop({ ok: false, error: { name: 'TimeoutError', message: `Execution exceeded ${timeoutMs}ms` } }), timeoutMs);
59
+ const run = async () => {
60
+ const context = await isolate.createContext();
61
+ const jail = context.global;
62
+ await jail.set('global', jail.derefInto());
63
+ // Trusted primitives are captured here, before any user code runs, and every budget (logs,
64
+ // SDK arguments, result, error) is enforced with them inside the isolate, in UTF-8 bytes, so
65
+ // replacing JSON.stringify, String.prototype methods or Promise.prototype.then cannot push an
66
+ // oversized value into the host copy path. The host re-checks everything it receives.
67
+ const L = {
68
+ maxLogBytes: limits.maxLogBytes, maxLogLines: limits.maxLogLines, overhead: LOG_LINE_OVERHEAD, marker: LOG_TRUNCATED,
69
+ maxRpcArgBytes: limits.maxRpcArgBytes, maxResultBytes: limits.maxResultBytes, maxError: MAX_ERROR_MESSAGE,
70
+ };
71
+ await context.evalClosure(`const L = ${JSON.stringify(L)};
72
+ const S = JSON.stringify, Str = String, apply = Reflect.apply, then = Promise.prototype.then;
73
+ const cca = String.prototype.charCodeAt, sl = String.prototype.slice, join = Array.prototype.join, map = Array.prototype.map;
74
+ const freeze = Object.freeze, define = Object.defineProperty, isArray = Array.isArray, create = Object.create;
75
+ const bytes = (s) => { let n = 0; const len = s.length; for (let i = 0; i < len; i++) { const c = apply(cca, s, [i]);
76
+ n += c < 0x80 ? 1 : c < 0x800 ? 2 : (c >= 0xD800 && c <= 0xDBFF) ? (i++, 4) : 3; } return n; };
77
+ const cut = (s, n) => s.length > n ? apply(sl, s, [0, n]) : s;
78
+ const show = (v) => { if (typeof v === 'string') return v; try { const j = S(v); return j === undefined ? Str(v) : j; } catch { return Str(v); } };
79
+ let used = 0, lines = 0, done = false;
80
+ const log = (...a) => {
81
+ if (done) return;
82
+ let text = cut(apply(join, apply(map, a, [show]), [' ']), L.maxLogBytes);
83
+ used += bytes(text) + L.overhead; lines++;
84
+ if (used > L.maxLogBytes - L.marker.length - L.overhead || lines >= L.maxLogLines) { done = true; text = L.marker; }
85
+ $0.applyIgnored(undefined, [text]);
86
+ };
87
+ define(globalThis, 'console', { value: freeze({ log, error: log, warn: log, info: log, debug: log }), writable: false, configurable: false });
88
+ const argsJson = (args) => { const j = S(isArray(args) ? args : []); if (bytes(j) > L.maxRpcArgBytes) return undefined; return j; };
89
+ const ok = (v) => { let j; try { j = S(v === undefined ? null : v); } catch (e) { return err({ name: 'TypeError', message: 'The returned value is not JSON-serializable' }); }
90
+ if (typeof j !== 'string') j = 'null';
91
+ const b = bytes(j); return b > L.maxResultBytes ? 'R' + b : 'V' + j; };
92
+ const err = (e) => { let name = 'Error', message = '', status;
93
+ try { name = cut(Str(e && e.name || 'Error'), 100); message = cut(Str(e && e.message !== undefined ? e.message : e), L.maxError); status = e && typeof e.status === 'number' ? e.status : undefined; } catch {}
94
+ // Null-prototype record of primitives: no inherited toJSON or getters can reshape it.
95
+ const rec = create(null); rec.name = name; rec.message = message; if (typeof status === 'number') rec.status = status;
96
+ // name/message were cut before serializing, so the JSON is bounded (escaping at most 6x);
97
+ // it is never sliced, which could break it and lose the name and status.
98
+ let out; try { out = S(rec); } catch {
99
+ const fb = create(null); fb.name = 'Error'; fb.message = 'The error could not be serialized.'; if (typeof status === 'number') fb.status = status;
100
+ out = S(fb); }
101
+ return 'E' + out; };
102
+ define(globalThis, '__fedregInternal', { value: freeze({ argsJson,
103
+ run: (fn) => apply(then, fn(), [ok, err]) }), writable: false, configurable: false, enumerable: false });`, [(line) => logs.push(String(line))], { arguments: { reference: true } });
104
+ let pending = 0;
105
+ const hostRpc = async (binding, path, argsJson) => {
106
+ const fail = (name, message) => new ivm.ExternalCopy({ ok: false, error: { name, message } }).copyInto();
107
+ if (disposed)
108
+ return fail('AbortError', 'Execution has ended.');
109
+ if (pending >= limits.maxPendingRpc)
110
+ return fail('TooManyPendingCalls', `At most ${limits.maxPendingRpc} SDK calls may be pending at once.`);
111
+ if (typeof argsJson !== 'string' || Buffer.byteLength(argsJson, 'utf8') > limits.maxRpcArgBytes)
112
+ return fail('ArgumentsTooLarge', `SDK call arguments exceed ${limits.maxRpcArgBytes} bytes.`);
113
+ let args;
114
+ try {
115
+ args = JSON.parse(argsJson);
116
+ }
117
+ catch {
118
+ return fail('TypeError', 'SDK arguments must be JSON-serializable.');
119
+ }
120
+ pending++;
121
+ try {
122
+ const result = await rpc.dispatch({ binding, path, args });
123
+ return new ivm.ExternalCopy(result).copyInto();
124
+ }
125
+ finally {
126
+ pending--;
127
+ }
128
+ };
129
+ // Binding names are pre-validated JS identifiers (getSources); safe to embed as JSON.
130
+ await context.evalClosure(`const internal = globalThis.__fedregInternal;
131
+ function makeProxy(binding, rpc) {
132
+ const handler = (path) => new Proxy(function(){}, {
133
+ get(_, key) { return typeof key === 'symbol' ? undefined : handler([...path, String(key)]); },
134
+ apply(_, __, args) {
135
+ let json;
136
+ try { json = internal.argsJson(args); } catch { return Promise.reject(new TypeError('SDK arguments must be JSON-serializable')); }
137
+ if (json === undefined) { const e = new Error('SDK call arguments exceed ${limits.maxRpcArgBytes} bytes.'); e.name = 'ArgumentsTooLarge'; return Promise.reject(e); }
138
+ return rpc.apply(undefined, [binding, path, json], { arguments: { copy: true }, result: { promise: true, copy: true } })
139
+ .then(r => {
140
+ if (!r.ok) { const e = new Error(r.error.message); e.name = r.error.name; if (typeof r.error.status === 'number') e.status = r.error.status; throw e; }
141
+ return r.value;
142
+ });
143
+ },
144
+ });
145
+ return handler([]);
146
+ }
147
+ for (const name of ${JSON.stringify(opts.bindings ?? [])}) {
148
+ Object.defineProperty(globalThis, name, { value: makeProxy(name, $0), writable: false, configurable: false });
149
+ }`, [hostRpc], { arguments: { reference: true } });
150
+ // 'V' + JSON (value), 'R' + bytes (result over budget, never transferred), 'E' + JSON (bounded
151
+ // error, so an SDK error's status survives the copy).
152
+ const script = await isolate.compileScript(`__fedregInternal.run(async () => { ${opts.code}\n })`);
153
+ const tagged = await script.run(context, { timeout: timeoutMs, promise: true, copy: true });
154
+ if (typeof tagged === 'string' && tagged.startsWith('V'))
155
+ return finishValue(tagged.slice(1), limits);
156
+ if (typeof tagged === 'string' && tagged.startsWith('R'))
157
+ return { ok: false, error: resultTooLarge(Number(tagged.slice(1)), limits) };
158
+ if (typeof tagged !== 'string' || !tagged.startsWith('E'))
159
+ return { ok: false, error: { name: 'SandboxProtocolError', message: 'The sandbox returned an invalid result.' } };
160
+ let e;
161
+ try {
162
+ e = JSON.parse(tagged.slice(1));
163
+ }
164
+ catch {
165
+ e = { name: 'Error', message: 'The sandbox returned an unreadable error.' };
166
+ }
167
+ return { ok: false, error: { name: String(e.name ?? 'Error').slice(0, 100), message: boundMessage(String(e.message ?? '')), ...(typeof e.status === 'number' ? { status: e.status } : {}) } };
168
+ };
169
+ try {
170
+ const outcome = await Promise.race([
171
+ run().catch((err) => {
172
+ const e = err;
173
+ if (disposed)
174
+ return { ok: false, error: { name: 'TimeoutError', message: `Execution exceeded ${timeoutMs}ms` } };
175
+ return { ok: false, error: { name: String(e?.name ?? 'Error').slice(0, 100), message: boundMessage(String(e?.message ?? err)), ...(typeof e?.status === 'number' ? { status: e.status } : {}) } };
176
+ }),
177
+ stopped,
178
+ ]);
179
+ return done(outcome);
180
+ }
181
+ finally {
182
+ clearTimeout(deadline);
183
+ dispose();
97
184
  }
98
185
  }
99
186
  }
@@ -1 +1 @@
1
- {"version":3,"file":"isolate.js","sourceRoot":"","sources":["../../src/sandbox/isolate.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"isolate.js","sourceRoot":"","sources":["../../src/sandbox/isolate.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,62 @@
1
+ /**
2
+ * Byte budgets for one execution. They bound what the host buffers and what reaches the model,
3
+ * independently of the V8 heap limit inside the sandbox. The defaults are deliberately generous:
4
+ * they exist to stop runaway or hostile output, not to constrain ordinary queries (a filtered
5
+ * `ecfr.full` part or a page of Federal Register documents fits comfortably).
6
+ */
7
+ export interface SandboxLimits {
8
+ /** Largest accepted user code. */
9
+ maxCodeBytes: number;
10
+ /** Total log size kept (text plus per-line overhead); later lines are dropped with a marker. */
11
+ maxLogBytes: number;
12
+ /** Most log lines kept, however short. */
13
+ maxLogLines: number;
14
+ /** Largest JSON-serialized return value; bigger results fail with ResultTooLarge. */
15
+ maxResultBytes: number;
16
+ /** Largest JSON-serialized argument list for one SDK call. */
17
+ maxRpcArgBytes: number;
18
+ /** SDK calls that may be awaiting a response at once. */
19
+ maxPendingRpc: number;
20
+ /** Deno only: total bytes the child may write to stdout over the execution. */
21
+ maxStdoutBytes: number;
22
+ /** Deno only: largest single frame (line) on stdout. */
23
+ maxFrameBytes: number;
24
+ }
25
+ export declare const DEFAULT_LIMITS: Readonly<SandboxLimits>;
26
+ /** Bytes charged per log line on top of its text, so empty-line floods are bounded too. */
27
+ export declare const LOG_LINE_OVERHEAD = 16;
28
+ export declare const LOG_TRUNCATED = "[logs truncated]";
29
+ /** Host-side log budget. The sandboxes enforce the same budget before sending (defense in depth). */
30
+ export declare class LogSink {
31
+ private readonly max;
32
+ private readonly maxLines;
33
+ private readonly out;
34
+ private bytes;
35
+ private dropped;
36
+ constructor(max: number, maxLines?: number);
37
+ push(line: string): void;
38
+ lines(): string[];
39
+ }
40
+ export declare function checkRpcArgs(args: unknown[], limits: SandboxLimits): {
41
+ name: string;
42
+ message: string;
43
+ } | undefined;
44
+ /** Turn the sandbox's JSON result into the execute envelope, enforcing maxResultBytes. */
45
+ export declare function finishValue(json: string, limits: SandboxLimits): {
46
+ ok: boolean;
47
+ value?: unknown;
48
+ error?: {
49
+ name: string;
50
+ message: string;
51
+ };
52
+ };
53
+ export declare function resultTooLarge(size: number, limits: SandboxLimits): {
54
+ name: string;
55
+ message: string;
56
+ };
57
+ /** Longest error message any execution reports. */
58
+ export declare const MAX_ERROR_MESSAGE = 4000;
59
+ export declare function boundMessage(message: string): string;
60
+ /** Preflight diagnostics: distinct messages only, at most 10, bounded in total. */
61
+ export declare function policyMessage(errors: string[]): string;
62
+ //# sourceMappingURL=limits.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"limits.d.ts","sourceRoot":"","sources":["../../src/sandbox/limits.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AACH,MAAM,WAAW,aAAa;IAC5B,kCAAkC;IAClC,YAAY,EAAE,MAAM,CAAC;IACrB,gGAAgG;IAChG,WAAW,EAAE,MAAM,CAAC;IACpB,0CAA0C;IAC1C,WAAW,EAAE,MAAM,CAAC;IACpB,qFAAqF;IACrF,cAAc,EAAE,MAAM,CAAC;IACvB,8DAA8D;IAC9D,cAAc,EAAE,MAAM,CAAC;IACvB,yDAAyD;IACzD,aAAa,EAAE,MAAM,CAAC;IACtB,+EAA+E;IAC/E,cAAc,EAAE,MAAM,CAAC;IACvB,wDAAwD;IACxD,aAAa,EAAE,MAAM,CAAC;CACvB;AAED,eAAO,MAAM,cAAc,EAAE,QAAQ,CAAC,aAAa,CAWjD,CAAC;AAEH,2FAA2F;AAC3F,eAAO,MAAM,iBAAiB,KAAK,CAAC;AACpC,eAAO,MAAM,aAAa,qBAAqB,CAAC;AAEhD,qGAAqG;AACrG,qBAAa,OAAO;IAIN,OAAO,CAAC,QAAQ,CAAC,GAAG;IAAU,OAAO,CAAC,QAAQ,CAAC,QAAQ;IAHnE,OAAO,CAAC,QAAQ,CAAC,GAAG,CAAgB;IACpC,OAAO,CAAC,KAAK,CAAK;IAClB,OAAO,CAAC,OAAO,CAAS;gBACK,GAAG,EAAE,MAAM,EAAmB,QAAQ,SAA6B;IAChG,IAAI,CAAC,IAAI,EAAE,MAAM,GAAG,IAAI;IAcxB,KAAK,IAAI,MAAM,EAAE;CAClB;AAED,wBAAgB,YAAY,CAAC,IAAI,EAAE,OAAO,EAAE,EAAE,MAAM,EAAE,aAAa,GAAG;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,OAAO,EAAE,MAAM,CAAA;CAAE,GAAG,SAAS,CAOlH;AAED,0FAA0F;AAC1F,wBAAgB,WAAW,CAAC,IAAI,EAAE,MAAM,EAAE,MAAM,EAAE,aAAa,GAAG;IAAE,EAAE,EAAE,OAAO,CAAC;IAAC,KAAK,CAAC,EAAE,OAAO,CAAC;IAAC,KAAK,CAAC,EAAE;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,OAAO,EAAE,MAAM,CAAA;KAAE,CAAA;CAAE,CAK5I;AAED,wBAAgB,cAAc,CAAC,IAAI,EAAE,MAAM,EAAE,MAAM,EAAE,aAAa,GAAG;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,OAAO,EAAE,MAAM,CAAA;CAAE,CAMrG;AAED,mDAAmD;AACnD,eAAO,MAAM,iBAAiB,OAAO,CAAC;AAEtC,wBAAgB,YAAY,CAAC,OAAO,EAAE,MAAM,GAAG,MAAM,CAEpD;AAED,mFAAmF;AACnF,wBAAgB,aAAa,CAAC,MAAM,EAAE,MAAM,EAAE,GAAG,MAAM,CAItD"}
@@ -0,0 +1,87 @@
1
+ export const DEFAULT_LIMITS = Object.freeze({
2
+ maxCodeBytes: 256 * 1024,
3
+ maxLogBytes: 1024 * 1024,
4
+ maxLogLines: 10_000,
5
+ maxResultBytes: 8 * 1024 * 1024,
6
+ maxRpcArgBytes: 1024 * 1024,
7
+ // Matches the per-execute public call budget, so `Promise.all` over a full budget still works.
8
+ maxPendingRpc: 100,
9
+ maxStdoutBytes: 128 * 1024 * 1024,
10
+ // A result travels as an escaped JSON string inside a frame, so allow for escaping overhead.
11
+ maxFrameBytes: 48 * 1024 * 1024,
12
+ });
13
+ /** Bytes charged per log line on top of its text, so empty-line floods are bounded too. */
14
+ export const LOG_LINE_OVERHEAD = 16;
15
+ export const LOG_TRUNCATED = '[logs truncated]';
16
+ /** Host-side log budget. The sandboxes enforce the same budget before sending (defense in depth). */
17
+ export class LogSink {
18
+ max;
19
+ maxLines;
20
+ out = [];
21
+ bytes = 0;
22
+ dropped = false;
23
+ constructor(max, maxLines = DEFAULT_LIMITS.maxLogLines) {
24
+ this.max = max;
25
+ this.maxLines = maxLines;
26
+ }
27
+ push(line) {
28
+ if (this.dropped)
29
+ return;
30
+ const text = line.length > this.max ? line.slice(0, this.max) : line;
31
+ const cost = Buffer.byteLength(text, 'utf8') + LOG_LINE_OVERHEAD;
32
+ // Room for the marker is reserved up front, so the total never exceeds the budget.
33
+ const reserve = Buffer.byteLength(LOG_TRUNCATED, 'utf8') + LOG_LINE_OVERHEAD;
34
+ if (text === LOG_TRUNCATED || this.out.length >= this.maxLines - 1 || this.bytes + cost > this.max - reserve) {
35
+ this.dropped = true;
36
+ if (reserve <= this.max)
37
+ this.out.push(LOG_TRUNCATED);
38
+ return;
39
+ }
40
+ this.bytes += cost;
41
+ this.out.push(text);
42
+ }
43
+ lines() { return [...this.out]; }
44
+ }
45
+ export function checkRpcArgs(args, limits) {
46
+ let size;
47
+ try {
48
+ size = Buffer.byteLength(JSON.stringify(args) ?? '', 'utf8');
49
+ }
50
+ catch {
51
+ return { name: 'TypeError', message: 'SDK arguments must be JSON-serializable.' };
52
+ }
53
+ return size > limits.maxRpcArgBytes
54
+ ? { name: 'ArgumentsTooLarge', message: `SDK call arguments exceed ${limits.maxRpcArgBytes} bytes.` }
55
+ : undefined;
56
+ }
57
+ /** Turn the sandbox's JSON result into the execute envelope, enforcing maxResultBytes. */
58
+ export function finishValue(json, limits) {
59
+ const size = Buffer.byteLength(json, 'utf8');
60
+ if (size > limits.maxResultBytes)
61
+ return { ok: false, error: resultTooLarge(size, limits) };
62
+ try {
63
+ return { ok: true, value: JSON.parse(json) };
64
+ }
65
+ catch {
66
+ return { ok: false, error: { name: 'SandboxProtocolError', message: 'The sandbox returned an invalid result.' } };
67
+ }
68
+ }
69
+ export function resultTooLarge(size, limits) {
70
+ return {
71
+ name: 'ResultTooLarge',
72
+ message: `The returned value is ${size} bytes; the limit is ${limits.maxResultBytes}. Return only what you need: `
73
+ + 'request fewer records (per_page), select fields, filter ecfr.full by part or section, map records to the attributes you need, or slice long text.',
74
+ };
75
+ }
76
+ /** Longest error message any execution reports. */
77
+ export const MAX_ERROR_MESSAGE = 4000;
78
+ export function boundMessage(message) {
79
+ return message.length > MAX_ERROR_MESSAGE ? `${message.slice(0, MAX_ERROR_MESSAGE)}… [truncated]` : message;
80
+ }
81
+ /** Preflight diagnostics: distinct messages only, at most 10, bounded in total. */
82
+ export function policyMessage(errors) {
83
+ const unique = [...new Set(errors)];
84
+ const shown = unique.slice(0, 10).join('; ');
85
+ return boundMessage(unique.length > 10 ? `${shown}; and ${unique.length - 10} more` : shown);
86
+ }
87
+ //# sourceMappingURL=limits.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"limits.js","sourceRoot":"","sources":["../../src/sandbox/limits.ts"],"names":[],"mappings":"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"}
@@ -1,8 +1,11 @@
1
+ import type { SandboxLimits } from './limits.js';
1
2
  export interface ExecuteOptions {
2
3
  code: string;
3
4
  timeoutMs?: number;
4
5
  memoryMb?: number;
5
6
  bindings?: string[];
7
+ /** Overrides for the runner's byte budgets. */
8
+ limits?: Partial<SandboxLimits>;
6
9
  }
7
10
  export interface ExecuteResult {
8
11
  ok: boolean;
@@ -1 +1 @@
1
- {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/sandbox/types.ts"],"names":[],"mappings":"AAAA,MAAM,WAAW,cAAc;IAC7B,IAAI,EAAE,MAAM,CAAC;IACb,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,QAAQ,CAAC,EAAE,MAAM,EAAE,CAAC;CACrB;AAED,MAAM,WAAW,aAAa;IAC5B,EAAE,EAAE,OAAO,CAAC;IACZ,KAAK,CAAC,EAAE,OAAO,CAAC;IAChB,IAAI,EAAE,MAAM,EAAE,CAAC;IACf,KAAK,CAAC,EAAE;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,OAAO,EAAE,MAAM,CAAC;QAAC,KAAK,CAAC,EAAE,MAAM,CAAC;QAAC,MAAM,CAAC,EAAE,MAAM,CAAA;KAAE,CAAC;IAC3E,UAAU,EAAE,MAAM,CAAC;CACpB;AAED,MAAM,MAAM,WAAW,GAAG,SAAS,GAAG,MAAM,GAAG,MAAM,CAAC;AAEtD,MAAM,WAAW,aAAa;IAC5B,IAAI,EAAE,SAAS,GAAG,MAAM,GAAG,aAAa,CAAC;IACzC,SAAS,IAAI,OAAO,CAAC,OAAO,CAAC,CAAC;IAC9B,OAAO,CAAC,IAAI,EAAE,cAAc,EAAE,GAAG,EAAE,SAAS,GAAG,OAAO,CAAC,aAAa,CAAC,CAAC;CACvE;AAED,MAAM,WAAW,OAAO;IACtB,OAAO,EAAE,MAAM,CAAC;IAChB,IAAI,EAAE,MAAM,EAAE,CAAC;IACf,IAAI,EAAE,OAAO,EAAE,CAAC;CACjB;AAED,MAAM,WAAW,SAAS;IACxB,QAAQ,CAAC,IAAI,EAAE,OAAO,GAAG,OAAO,CAAC;QAAE,EAAE,EAAE,OAAO,CAAC;QAAC,KAAK,CAAC,EAAE,OAAO,CAAC;QAAC,KAAK,CAAC,EAAE;YAAE,IAAI,EAAE,MAAM,CAAC;YAAC,OAAO,EAAE,MAAM,CAAC;YAAC,MAAM,CAAC,EAAE,MAAM,CAAA;SAAE,CAAA;KAAE,CAAC,CAAC;CAChI"}
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/sandbox/types.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,aAAa,CAAC;AAEjD,MAAM,WAAW,cAAc;IAC7B,IAAI,EAAE,MAAM,CAAC;IACb,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,QAAQ,CAAC,EAAE,MAAM,EAAE,CAAC;IACpB,+CAA+C;IAC/C,MAAM,CAAC,EAAE,OAAO,CAAC,aAAa,CAAC,CAAC;CACjC;AAED,MAAM,WAAW,aAAa;IAC5B,EAAE,EAAE,OAAO,CAAC;IACZ,KAAK,CAAC,EAAE,OAAO,CAAC;IAChB,IAAI,EAAE,MAAM,EAAE,CAAC;IACf,KAAK,CAAC,EAAE;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,OAAO,EAAE,MAAM,CAAC;QAAC,KAAK,CAAC,EAAE,MAAM,CAAC;QAAC,MAAM,CAAC,EAAE,MAAM,CAAA;KAAE,CAAC;IAC3E,UAAU,EAAE,MAAM,CAAC;CACpB;AAED,MAAM,MAAM,WAAW,GAAG,SAAS,GAAG,MAAM,GAAG,MAAM,CAAC;AAEtD,MAAM,WAAW,aAAa;IAC5B,IAAI,EAAE,SAAS,GAAG,MAAM,GAAG,aAAa,CAAC;IACzC,SAAS,IAAI,OAAO,CAAC,OAAO,CAAC,CAAC;IAC9B,OAAO,CAAC,IAAI,EAAE,cAAc,EAAE,GAAG,EAAE,SAAS,GAAG,OAAO,CAAC,aAAa,CAAC,CAAC;CACvE;AAED,MAAM,WAAW,OAAO;IACtB,OAAO,EAAE,MAAM,CAAC;IAChB,IAAI,EAAE,MAAM,EAAE,CAAC;IACf,IAAI,EAAE,OAAO,EAAE,CAAC;CACjB;AAED,MAAM,WAAW,SAAS;IACxB,QAAQ,CAAC,IAAI,EAAE,OAAO,GAAG,OAAO,CAAC;QAAE,EAAE,EAAE,OAAO,CAAC;QAAC,KAAK,CAAC,EAAE,OAAO,CAAC;QAAC,KAAK,CAAC,EAAE;YAAE,IAAI,EAAE,MAAM,CAAC;YAAC,OAAO,EAAE,MAAM,CAAC;YAAC,MAAM,CAAC,EAAE,MAAM,CAAA;SAAE,CAAA;KAAE,CAAC,CAAC;CAChI"}
@@ -13,7 +13,7 @@ export function buildSdk(cfg) {
13
13
  methods: Object.freeze(methods),
14
14
  meta: sources.map(({ name, label, enabled, disabledReason }) => ({ name, label, enabled, disabledReason })),
15
15
  registeredNames: sources.map(s => s.name),
16
- version: () => '2.2.1', // x-release-version
16
+ version: () => '2.2.3', // x-release-version
17
17
  };
18
18
  }
19
19
  //# sourceMappingURL=bindings.js.map
@@ -34,7 +34,7 @@ function cachedInputSchema(name, jsonSchema) {
34
34
  return converted;
35
35
  }
36
36
  export function buildMcpServer(deps, requestCtx) {
37
- const server = new McpServer({ name: 'fedreg-mcp-server', version: '2.2.1' }, // x-release-version
37
+ const server = new McpServer({ name: 'fedreg-mcp-server', version: '2.2.3' }, // x-release-version
38
38
  {
39
39
  capabilities: { tools: {} },
40
40
  cacheHints: { 'tools/list': LIST_CACHE_HINT, 'server/discover': LIST_CACHE_HINT },
@@ -11,7 +11,7 @@ export function oauthProtectedResource(cfg, resourceUrl) {
11
11
  bearer_methods_supported: ['header'],
12
12
  scopes_supported: cfg.scopes ?? [],
13
13
  resource_documentation: 'https://github.com/blen-labs/fedreg-mcp-server#self-hosting-remote-http',
14
- resource_name: 'Federal Register, eCFR & regulations.gov MCP Server',
14
+ resource_name: 'Federal Regulations MCP Server',
15
15
  };
16
16
  }
17
17
  //# sourceMappingURL=wellKnown.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"wellKnown.js","sourceRoot":"","sources":["../../src/server/wellKnown.ts"],"names":[],"mappings":"AAEA;;;;;GAKG;AACH,MAAM,UAAU,sBAAsB,CAAC,GAAe,EAAE,WAAmB;IACzE,OAAO;QACL,QAAQ,EAAE,WAAW;QACrB,qBAAqB,EAAE,GAAG,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,EAAE;QACrD,wBAAwB,EAAE,CAAC,QAAQ,CAAC;QACpC,gBAAgB,EAAE,GAAG,CAAC,MAAM,IAAI,EAAE;QAClC,sBAAsB,EAAE,yEAAyE;QACjG,aAAa,EAAE,qDAAqD;KACrE,CAAC;AACJ,CAAC"}
1
+ {"version":3,"file":"wellKnown.js","sourceRoot":"","sources":["../../src/server/wellKnown.ts"],"names":[],"mappings":"AAEA;;;;;GAKG;AACH,MAAM,UAAU,sBAAsB,CAAC,GAAe,EAAE,WAAmB;IACzE,OAAO;QACL,QAAQ,EAAE,WAAW;QACrB,qBAAqB,EAAE,GAAG,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,EAAE;QACrD,wBAAwB,EAAE,CAAC,QAAQ,CAAC;QACpC,gBAAgB,EAAE,GAAG,CAAC,MAAM,IAAI,EAAE;QAClC,sBAAsB,EAAE,yEAAyE;QACjG,aAAa,EAAE,gCAAgC;KAChD,CAAC;AACJ,CAAC"}