@adia-ai/agent 0.8.29 → 0.8.31

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.
Files changed (58) hide show
  1. package/CHANGELOG.md +45 -0
  2. package/README.md +384 -11
  3. package/agent.d.ts +44 -3
  4. package/agent.d.ts.map +1 -1
  5. package/agent.js +172 -8
  6. package/agent.js.map +1 -1
  7. package/events.d.ts +46 -2
  8. package/events.d.ts.map +1 -1
  9. package/events.js +30 -1
  10. package/events.js.map +1 -1
  11. package/guardrail.d.ts +68 -0
  12. package/guardrail.d.ts.map +1 -0
  13. package/guardrail.js +79 -0
  14. package/guardrail.js.map +1 -0
  15. package/index.d.ts +15 -7
  16. package/index.d.ts.map +1 -1
  17. package/index.js +7 -3
  18. package/index.js.map +1 -1
  19. package/integrations.d.ts +19 -2
  20. package/integrations.d.ts.map +1 -1
  21. package/integrations.js +6 -1
  22. package/integrations.js.map +1 -1
  23. package/loop.d.ts +19 -8
  24. package/loop.d.ts.map +1 -1
  25. package/loop.js +176 -9
  26. package/loop.js.map +1 -1
  27. package/mcp-transport.d.ts +128 -0
  28. package/mcp-transport.d.ts.map +1 -0
  29. package/mcp-transport.js +361 -0
  30. package/mcp-transport.js.map +1 -0
  31. package/mcp.d.ts +120 -0
  32. package/mcp.d.ts.map +1 -0
  33. package/mcp.js +264 -0
  34. package/mcp.js.map +1 -0
  35. package/package.json +1 -1
  36. package/resource.d.ts +28 -3
  37. package/resource.d.ts.map +1 -1
  38. package/resource.js +43 -5
  39. package/resource.js.map +1 -1
  40. package/session.d.ts +18 -0
  41. package/session.d.ts.map +1 -1
  42. package/session.js +40 -0
  43. package/session.js.map +1 -1
  44. package/stub.d.ts +8 -0
  45. package/stub.d.ts.map +1 -1
  46. package/stub.js +13 -0
  47. package/stub.js.map +1 -1
  48. package/tools.d.ts +6 -0
  49. package/tools.d.ts.map +1 -1
  50. package/tools.js.map +1 -1
  51. package/trace.d.ts +50 -0
  52. package/trace.d.ts.map +1 -0
  53. package/trace.js +60 -0
  54. package/trace.js.map +1 -0
  55. package/workflow.d.ts +113 -11
  56. package/workflow.d.ts.map +1 -1
  57. package/workflow.js +93 -15
  58. package/workflow.js.map +1 -1
@@ -0,0 +1,361 @@
1
+ /**
2
+ * MCP streamable-HTTP client transport — the smallest thing that speaks the
3
+ * protocol.
4
+ *
5
+ * Deliberately NOT `@modelcontextprotocol/sdk`. The subset a client needs to
6
+ * consume a server as a tool/resource source is five methods over one POST
7
+ * endpoint (initialize · notifications/initialized · tools/list · tools/call ·
8
+ * resources/list · resources/read); the SDK brings a server framework, stdio
9
+ * and websocket transports, an auth stack, and zod along with it. This
10
+ * package's whole posture is zero runtime dependencies beyond `@adia-ai/llm`
11
+ * and a browser-first build, so the subset is hand-rolled here and the SDK
12
+ * stays where it belongs — `packages/a2ui/mcp`, which SERVES.
13
+ *
14
+ * Wire rules the spec fixes and this module obeys:
15
+ * - Every request is a POST carrying one JSON-RPC message, with
16
+ * `accept: application/json, text/event-stream` — the server picks.
17
+ * - A `mcp-session-id` response header on the initialize response is echoed
18
+ * on every subsequent request (and on the DELETE that closes the session).
19
+ * - The negotiated `MCP-Protocol-Version` rides every post-initialize
20
+ * request.
21
+ * - An SSE response body is read until the event whose `data:` payload is
22
+ * the JSON-RPC response for THIS request id; server-initiated
23
+ * notifications interleaved on that stream are ignored (this client
24
+ * subscribes to nothing, so there is nothing it can act on).
25
+ * - The protocol headers are the LAST spread in every request, so a caller
26
+ * header cannot quietly replace `accept` or the session id and turn a
27
+ * working connection into an inexplicable one.
28
+ *
29
+ * Nothing here waits forever. Every round trip carries a deadline covering
30
+ * BOTH the fetch and the wait for the answer to arrive on an SSE body — a
31
+ * server that accepts a POST and then says nothing is a real failure mode,
32
+ * and it is indistinguishable from a hang unless someone is holding a clock.
33
+ * The deadline and the caller's `signal` share one abort path, so a timeout
34
+ * and a user cancellation both actually cancel the request rather than
35
+ * abandoning it.
36
+ *
37
+ * Everything is `fetch`-only, so it runs unchanged in a browser — with the
38
+ * CORS caveat the README records. `fetchImpl` exists so a test can hand the
39
+ * transport an in-process server instead of a network.
40
+ */
41
+ const CLIENT_PROTOCOL_VERSION = '2025-06-18';
42
+ /** Versions this client can talk. A server answering initialize with
43
+ * anything else is a hard stop: guessing at an unknown dialect is how you
44
+ * get a half-working tool list. A version NEWER than the one requested is
45
+ * refused too — the server would be answering a question we did not ask,
46
+ * and the dialect it picked is by definition one this client was not
47
+ * written against. */
48
+ const SUPPORTED_PROTOCOL_VERSIONS = new Set([
49
+ '2025-06-18', '2025-03-26', '2024-11-05',
50
+ ]);
51
+ /**
52
+ * Default per-request deadline: 60 seconds.
53
+ *
54
+ * It has to clear the slowest legitimate answer, and for MCP that is a tool
55
+ * that thinks — the in-repo a2ui server's `generate_ui` runs an LLM inside
56
+ * `tools/call`. A handshake-sized number (5–10s) would make MCP-client mode
57
+ * useless for exactly the servers this repo has. One knob rather than
58
+ * separate connect/call budgets: two numbers to tune is worse than one
59
+ * generous one, and `timeoutMs` is per-request, so a caller with a slower
60
+ * tool raises it in the one place that matters.
61
+ */
62
+ export const DEFAULT_MCP_TIMEOUT_MS = 60_000;
63
+ /** Every MCP failure this package raises carries this name, so a consumer
64
+ * can tell an MCP fault from a tool's own bad day without string-matching. */
65
+ export class McpError extends Error {
66
+ name = 'McpError';
67
+ /** The server the fault belongs to. Empty for a fault raised while
68
+ * assembling several sources, where no single server owns it. */
69
+ url;
70
+ constructor(message, url = '', options) {
71
+ super(url ? `${message} [${url}]` : message, options);
72
+ this.url = url;
73
+ }
74
+ }
75
+ /** Connect-time faults: unreachable server, non-2xx, protocol mismatch, a
76
+ * timeout, a JSON-RPC error on initialize/list, or a listed tool this
77
+ * harness cannot register. Thrown, never swallowed — an agent that
78
+ * silently ran with an empty tool list would look like a model that forgot
79
+ * how to use its tools. */
80
+ export class McpConnectionError extends McpError {
81
+ name = 'McpConnectionError';
82
+ }
83
+ /** A `tools/call` or `resources/read` that failed after the connection was
84
+ * established. Thrown inside a ToolDef's `execute`, which `executeTool`
85
+ * turns into an `isError` tool_result — the model sees it and can react. */
86
+ export class McpCallError extends McpError {
87
+ name = 'McpCallError';
88
+ }
89
+ function isResponseFor(message, id) {
90
+ return !!message && typeof message === 'object' && message.id === id;
91
+ }
92
+ /** One abort path for the deadline and every caller signal. Returns the
93
+ * controller (so the caller can abort the underlying request on timeout)
94
+ * plus a `settle` to release the timer and the listeners — a per-request
95
+ * listener left on a long-lived connection signal IS a leak. */
96
+ function abortPath(signals, timeoutMs) {
97
+ const controller = new AbortController();
98
+ let expired = false;
99
+ const live = signals.filter((s) => !!s);
100
+ const onAbort = () => controller.abort();
101
+ for (const signal of live) {
102
+ if (signal.aborted)
103
+ controller.abort();
104
+ else
105
+ signal.addEventListener('abort', onAbort, { once: true });
106
+ }
107
+ const timer = timeoutMs > 0
108
+ ? setTimeout(() => { expired = true; controller.abort(); }, timeoutMs)
109
+ : null;
110
+ return {
111
+ signal: controller.signal,
112
+ timedOut: () => expired,
113
+ settle: () => {
114
+ if (timer)
115
+ clearTimeout(timer);
116
+ for (const signal of live)
117
+ signal.removeEventListener('abort', onAbort);
118
+ },
119
+ };
120
+ }
121
+ /** Reject as soon as the shared abort path fires, whatever `promise` is
122
+ * doing. `fetch` honors the signal; an in-memory Response's reader does
123
+ * not, and a hung server is exactly the case where nobody else is holding
124
+ * a clock — so the race is explicit rather than delegated. */
125
+ function untilAborted(promise, path) {
126
+ if (path.signal.aborted)
127
+ return Promise.reject(abortReason(path));
128
+ return new Promise((resolve, reject) => {
129
+ const onAbort = () => reject(abortReason(path));
130
+ path.signal.addEventListener('abort', onAbort, { once: true });
131
+ promise.then(resolve, reject).finally(() => {
132
+ path.signal.removeEventListener('abort', onAbort);
133
+ });
134
+ });
135
+ }
136
+ function abortReason(path) {
137
+ return path.timedOut()
138
+ ? new Error('__mcp_timeout__')
139
+ : new Error('__mcp_aborted__');
140
+ }
141
+ /** Turn the internal marker (or a fetch's own AbortError) into the right
142
+ * named MCP error, so a caller reads "timed out" / "aborted" instead of
143
+ * the DOM's vocabulary. */
144
+ function describeFailure(err, timeoutMs) {
145
+ const message = err?.message ?? String(err);
146
+ if (message === '__mcp_timeout__')
147
+ return `timed out after ${timeoutMs}ms`;
148
+ if (message === '__mcp_aborted__')
149
+ return 'aborted by caller';
150
+ if (err?.name === 'AbortError')
151
+ return 'aborted';
152
+ return message;
153
+ }
154
+ /** Pull the JSON-RPC response for `id` out of an SSE body.
155
+ *
156
+ * Event-block granularity, per the SSE spec rather than per line: an event
157
+ * ends at a blank line and its `data:` lines are joined with newlines, so a
158
+ * server that pretty-prints its JSON across several `data:` lines is read
159
+ * correctly instead of silently discarded as unparseable. */
160
+ async function readSseResponse(res, id, url, path, ErrorClass) {
161
+ const body = res.body;
162
+ if (!body)
163
+ throw new ErrorClass('server sent an SSE response with no body', url);
164
+ const reader = body.getReader();
165
+ const decoder = new TextDecoder();
166
+ let buffer = '';
167
+ let data = [];
168
+ const flush = () => {
169
+ if (!data.length)
170
+ return null;
171
+ const payload = data.join('\n');
172
+ data = [];
173
+ let message;
174
+ try {
175
+ message = JSON.parse(payload);
176
+ }
177
+ catch {
178
+ return null; // A malformed event is not this request's answer.
179
+ }
180
+ return isResponseFor(message, id) ? message : null;
181
+ };
182
+ try {
183
+ for (;;) {
184
+ const { done, value } = await untilAborted(reader.read(), path);
185
+ if (done)
186
+ break;
187
+ buffer += decoder.decode(value, { stream: true });
188
+ let cut;
189
+ while ((cut = buffer.indexOf('\n')) !== -1) {
190
+ const line = buffer.slice(0, cut).replace(/\r$/, '');
191
+ buffer = buffer.slice(cut + 1);
192
+ if (!line) {
193
+ const message = flush();
194
+ if (message)
195
+ return message;
196
+ continue;
197
+ }
198
+ if (line.startsWith('data:')) {
199
+ // One optional space after the colon is part of the framing.
200
+ data.push(line.slice(5).replace(/^ /, ''));
201
+ }
202
+ }
203
+ }
204
+ const trailing = flush();
205
+ if (trailing)
206
+ return trailing;
207
+ }
208
+ finally {
209
+ await reader.cancel().catch(() => { });
210
+ }
211
+ throw new ErrorClass(`SSE stream ended before a response to request ${id} arrived`, url);
212
+ }
213
+ /** `connectOptions.signal` covers the HANDSHAKE only. It is deliberately not
214
+ * `options.signal`: that one is connection-level and would keep aborting
215
+ * every later call, so a turn that cancelled the connect would poison every
216
+ * turn after it. */
217
+ export async function connectStreamableHttp(options, connectOptions = {}) {
218
+ const { url } = options;
219
+ const doFetch = options.fetchImpl ?? globalThis.fetch;
220
+ if (typeof doFetch !== 'function') {
221
+ throw new McpConnectionError('no global fetch available — pass fetchImpl', url);
222
+ }
223
+ const clientInfo = options.clientInfo ?? { name: '@adia-ai/agent', version: '1' };
224
+ const defaultTimeout = options.timeoutMs ?? DEFAULT_MCP_TIMEOUT_MS;
225
+ let sessionId;
226
+ let negotiated = CLIENT_PROTOCOL_VERSION;
227
+ let nextId = 1;
228
+ /** Caller headers first: the protocol's own headers are not negotiable,
229
+ * and a caller who sets `accept` or `mcp-session-id` by accident should
230
+ * not be able to break the transport from the outside. */
231
+ function headers(extra) {
232
+ return {
233
+ ...options.headers,
234
+ 'content-type': 'application/json',
235
+ accept: 'application/json, text/event-stream',
236
+ ...(sessionId ? { 'mcp-session-id': sessionId } : {}),
237
+ ...extra,
238
+ };
239
+ }
240
+ async function post(body, ErrorClass, path, timeoutMs, extraHeaders) {
241
+ let res;
242
+ try {
243
+ res = await untilAborted(doFetch(url, {
244
+ method: 'POST',
245
+ headers: headers(extraHeaders),
246
+ body: JSON.stringify(body),
247
+ signal: path.signal,
248
+ }), path);
249
+ }
250
+ catch (err) {
251
+ throw new ErrorClass(`cannot reach MCP server: ${describeFailure(err, timeoutMs)}`, url, { cause: err });
252
+ }
253
+ if (!res.ok) {
254
+ const text = await res.text().catch(() => '');
255
+ throw new ErrorClass(`MCP server returned ${res.status}${text ? `: ${text.slice(0, 300)}` : ''}`, url);
256
+ }
257
+ return res;
258
+ }
259
+ async function rpc(method, params, ErrorClass, requestOptions) {
260
+ const id = nextId++;
261
+ const timeoutMs = requestOptions?.timeoutMs ?? defaultTimeout;
262
+ const path = abortPath([options.signal, requestOptions?.signal], timeoutMs);
263
+ try {
264
+ const res = await post({ jsonrpc: '2.0', id, method, ...(params ? { params } : {}) }, ErrorClass, path, timeoutMs, method === 'initialize' ? {} : { 'mcp-protocol-version': negotiated });
265
+ if (method === 'initialize') {
266
+ const assigned = res.headers.get('mcp-session-id');
267
+ if (assigned)
268
+ sessionId = assigned;
269
+ }
270
+ const contentType = res.headers.get('content-type') ?? '';
271
+ let message;
272
+ if (contentType.includes('text/event-stream')) {
273
+ try {
274
+ message = await readSseResponse(res, id, url, path, ErrorClass);
275
+ }
276
+ catch (err) {
277
+ if (err instanceof McpError)
278
+ throw err;
279
+ throw new ErrorClass(`${method} failed: ${describeFailure(err, timeoutMs)}`, url, { cause: err });
280
+ }
281
+ }
282
+ else {
283
+ const text = await untilAborted(res.text(), path).catch((err) => {
284
+ throw new ErrorClass(`${method} failed: ${describeFailure(err, timeoutMs)}`, url, { cause: err });
285
+ });
286
+ try {
287
+ message = JSON.parse(text);
288
+ }
289
+ catch {
290
+ throw new ErrorClass(`MCP server sent a non-JSON response to ${method}: ${text.slice(0, 200)}`, url);
291
+ }
292
+ }
293
+ if (message.error) {
294
+ throw new ErrorClass(`${method} failed (${message.error.code}): ${message.error.message}`, url);
295
+ }
296
+ return message.result;
297
+ }
298
+ finally {
299
+ path.settle();
300
+ }
301
+ }
302
+ const initResult = await rpc('initialize', {
303
+ protocolVersion: CLIENT_PROTOCOL_VERSION,
304
+ capabilities: {},
305
+ clientInfo,
306
+ }, McpConnectionError, connectOptions.signal ? { signal: connectOptions.signal } : undefined);
307
+ const serverVersion = initResult?.protocolVersion ?? CLIENT_PROTOCOL_VERSION;
308
+ // Dates sort lexicographically, so "newer than we asked for" is a string
309
+ // comparison — and it is refused as firmly as an unknown one.
310
+ if (!SUPPORTED_PROTOCOL_VERSIONS.has(serverVersion) || serverVersion > CLIENT_PROTOCOL_VERSION) {
311
+ throw new McpConnectionError(`server speaks MCP protocol "${serverVersion}", this client asked for ` +
312
+ `${CLIENT_PROTOCOL_VERSION} and accepts ${[...SUPPORTED_PROTOCOL_VERSIONS].join(', ')}`, url);
313
+ }
314
+ negotiated = serverVersion;
315
+ // The spec's post-initialize notification. It carries no id and gets no
316
+ // response body worth reading — but a server that rejects it has told us
317
+ // the handshake did not take, so the failure is fatal like any other
318
+ // connect-time fault.
319
+ {
320
+ const path = abortPath([options.signal, connectOptions.signal], defaultTimeout);
321
+ try {
322
+ const res = await post({ jsonrpc: '2.0', method: 'notifications/initialized' }, McpConnectionError, path, defaultTimeout, { 'mcp-protocol-version': negotiated });
323
+ await res.body?.cancel().catch(() => { });
324
+ }
325
+ finally {
326
+ path.settle();
327
+ }
328
+ }
329
+ return {
330
+ url,
331
+ serverInfo: {
332
+ name: initResult?.serverInfo?.name ?? 'unknown',
333
+ version: initResult?.serverInfo?.version ?? '0',
334
+ },
335
+ protocolVersion: negotiated,
336
+ capabilities: initResult?.capabilities ?? {},
337
+ request(method, params, requestOptions) {
338
+ return rpc(method, params, McpCallError, requestOptions);
339
+ },
340
+ async close() {
341
+ if (!sessionId)
342
+ return;
343
+ const path = abortPath([], defaultTimeout);
344
+ try {
345
+ await untilAborted(doFetch(url, {
346
+ method: 'DELETE',
347
+ headers: headers({ 'mcp-protocol-version': negotiated }),
348
+ signal: path.signal,
349
+ }), path);
350
+ }
351
+ catch {
352
+ // A session the server will time out on its own is not worth a throw.
353
+ }
354
+ finally {
355
+ path.settle();
356
+ }
357
+ sessionId = undefined;
358
+ },
359
+ };
360
+ }
361
+ //# sourceMappingURL=mcp-transport.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"mcp-transport.js","sourceRoot":"","sources":["src/mcp-transport.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAuCG;AAEH,MAAM,uBAAuB,GAAG,YAAY,CAAC;AAE7C;;;;;uBAKuB;AACvB,MAAM,2BAA2B,GAAG,IAAI,GAAG,CAAC;IAC1C,YAAY,EAAE,YAAY,EAAE,YAAY;CACzC,CAAC,CAAC;AAEH;;;;;;;;;;GAUG;AACH,MAAM,CAAC,MAAM,sBAAsB,GAAG,MAAM,CAAC;AAE7C;+EAC+E;AAC/E,MAAM,OAAO,QAAS,SAAQ,KAAK;IACf,IAAI,GAAW,UAAU,CAAC;IAC5C;sEACkE;IACzD,GAAG,CAAS;IACrB,YAAY,OAAe,EAAE,GAAG,GAAG,EAAE,EAAE,OAA6B;QAClE,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,GAAG,OAAO,KAAK,GAAG,GAAG,CAAC,CAAC,CAAC,OAAO,EAAE,OAAO,CAAC,CAAC;QACtD,IAAI,CAAC,GAAG,GAAG,GAAG,CAAC;IACjB,CAAC;CACF;AAED;;;;4BAI4B;AAC5B,MAAM,OAAO,kBAAmB,SAAQ,QAAQ;IAC5B,IAAI,GAAG,oBAAoB,CAAC;CAC/C;AAED;;6EAE6E;AAC7E,MAAM,OAAO,YAAa,SAAQ,QAAQ;IACtB,IAAI,GAAG,cAAc,CAAC;CACzC;AAqDD,SAAS,aAAa,CAAC,OAAgB,EAAE,EAAU;IACjD,OAAO,CAAC,CAAC,OAAO,IAAI,OAAO,OAAO,KAAK,QAAQ,IAAK,OAA2B,CAAC,EAAE,KAAK,EAAE,CAAC;AAC5F,CAAC;AAED;;;iEAGiE;AACjE,SAAS,SAAS,CAAC,OAAuC,EAAE,SAAiB;IAM3E,MAAM,UAAU,GAAG,IAAI,eAAe,EAAE,CAAC;IACzC,IAAI,OAAO,GAAG,KAAK,CAAC;IACpB,MAAM,IAAI,GAAG,OAAO,CAAC,MAAM,CAAC,CAAC,CAAC,EAAoB,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;IAE1D,MAAM,OAAO,GAAG,GAAG,EAAE,CAAC,UAAU,CAAC,KAAK,EAAE,CAAC;IACzC,KAAK,MAAM,MAAM,IAAI,IAAI,EAAE,CAAC;QAC1B,IAAI,MAAM,CAAC,OAAO;YAAE,UAAU,CAAC,KAAK,EAAE,CAAC;;YAClC,MAAM,CAAC,gBAAgB,CAAC,OAAO,EAAE,OAAO,EAAE,EAAE,IAAI,EAAE,IAAI,EAAE,CAAC,CAAC;IACjE,CAAC;IAED,MAAM,KAAK,GAAG,SAAS,GAAG,CAAC;QACzB,CAAC,CAAC,UAAU,CAAC,GAAG,EAAE,GAAG,OAAO,GAAG,IAAI,CAAC,CAAC,UAAU,CAAC,KAAK,EAAE,CAAC,CAAC,CAAC,EAAE,SAAS,CAAC;QACtE,CAAC,CAAC,IAAI,CAAC;IAET,OAAO;QACL,MAAM,EAAE,UAAU,CAAC,MAAM;QACzB,QAAQ,EAAE,GAAG,EAAE,CAAC,OAAO;QACvB,MAAM,EAAE,GAAG,EAAE;YACX,IAAI,KAAK;gBAAE,YAAY,CAAC,KAAK,CAAC,CAAC;YAC/B,KAAK,MAAM,MAAM,IAAI,IAAI;gBAAE,MAAM,CAAC,mBAAmB,CAAC,OAAO,EAAE,OAAO,CAAC,CAAC;QAC1E,CAAC;KACF,CAAC;AACJ,CAAC;AAED;;;+DAG+D;AAC/D,SAAS,YAAY,CAAI,OAAmB,EAAE,IAAkC;IAC9E,IAAI,IAAI,CAAC,MAAM,CAAC,OAAO;QAAE,OAAO,OAAO,CAAC,MAAM,CAAC,WAAW,CAAC,IAAI,CAAC,CAAC,CAAC;IAClE,OAAO,IAAI,OAAO,CAAI,CAAC,OAAO,EAAE,MAAM,EAAE,EAAE;QACxC,MAAM,OAAO,GAAG,GAAG,EAAE,CAAC,MAAM,CAAC,WAAW,CAAC,IAAI,CAAC,CAAC,CAAC;QAChD,IAAI,CAAC,MAAM,CAAC,gBAAgB,CAAC,OAAO,EAAE,OAAO,EAAE,EAAE,IAAI,EAAE,IAAI,EAAE,CAAC,CAAC;QAC/D,OAAO,CAAC,IAAI,CAAC,OAAO,EAAE,MAAM,CAAC,CAAC,OAAO,CAAC,GAAG,EAAE;YACzC,IAAI,CAAC,MAAM,CAAC,mBAAmB,CAAC,OAAO,EAAE,OAAO,CAAC,CAAC;QACpD,CAAC,CAAC,CAAC;IACL,CAAC,CAAC,CAAC;AACL,CAAC;AAED,SAAS,WAAW,CAAC,IAAkC;IACrD,OAAO,IAAI,CAAC,QAAQ,EAAE;QACpB,CAAC,CAAC,IAAI,KAAK,CAAC,iBAAiB,CAAC;QAC9B,CAAC,CAAC,IAAI,KAAK,CAAC,iBAAiB,CAAC,CAAC;AACnC,CAAC;AAED;;4BAE4B;AAC5B,SAAS,eAAe,CAAC,GAAY,EAAE,SAAiB;IACtD,MAAM,OAAO,GAAI,GAAa,EAAE,OAAO,IAAI,MAAM,CAAC,GAAG,CAAC,CAAC;IACvD,IAAI,OAAO,KAAK,iBAAiB;QAAE,OAAO,mBAAmB,SAAS,IAAI,CAAC;IAC3E,IAAI,OAAO,KAAK,iBAAiB;QAAE,OAAO,mBAAmB,CAAC;IAC9D,IAAK,GAAa,EAAE,IAAI,KAAK,YAAY;QAAE,OAAO,SAAS,CAAC;IAC5D,OAAO,OAAO,CAAC;AACjB,CAAC;AAED;;;;;8DAK8D;AAC9D,KAAK,UAAU,eAAe,CAC5B,GAAa,EACb,EAAU,EACV,GAAW,EACX,IAAkC,EAClC,UAA2B;IAE3B,MAAM,IAAI,GAAG,GAAG,CAAC,IAAI,CAAC;IACtB,IAAI,CAAC,IAAI;QAAE,MAAM,IAAI,UAAU,CAAC,0CAA0C,EAAE,GAAG,CAAC,CAAC;IACjF,MAAM,MAAM,GAAG,IAAI,CAAC,SAAS,EAAE,CAAC;IAChC,MAAM,OAAO,GAAG,IAAI,WAAW,EAAE,CAAC;IAClC,IAAI,MAAM,GAAG,EAAE,CAAC;IAChB,IAAI,IAAI,GAAa,EAAE,CAAC;IAExB,MAAM,KAAK,GAAG,GAA2B,EAAE;QACzC,IAAI,CAAC,IAAI,CAAC,MAAM;YAAE,OAAO,IAAI,CAAC;QAC9B,MAAM,OAAO,GAAG,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;QAChC,IAAI,GAAG,EAAE,CAAC;QACV,IAAI,OAAgB,CAAC;QACrB,IAAI,CAAC;YACH,OAAO,GAAG,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC;QAChC,CAAC;QAAC,MAAM,CAAC;YACP,OAAO,IAAI,CAAC,CAAC,kDAAkD;QACjE,CAAC;QACD,OAAO,aAAa,CAAC,OAAO,EAAE,EAAE,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,IAAI,CAAC;IACrD,CAAC,CAAC;IAEF,IAAI,CAAC;QACH,SAAS,CAAC;YACR,MAAM,EAAE,IAAI,EAAE,KAAK,EAAE,GAAG,MAAM,YAAY,CAAC,MAAM,CAAC,IAAI,EAAE,EAAE,IAAI,CAAC,CAAC;YAChE,IAAI,IAAI;gBAAE,MAAM;YAChB,MAAM,IAAI,OAAO,CAAC,MAAM,CAAC,KAAK,EAAE,EAAE,MAAM,EAAE,IAAI,EAAE,CAAC,CAAC;YAClD,IAAI,GAAW,CAAC;YAChB,OAAO,CAAC,GAAG,GAAG,MAAM,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC;gBAC3C,MAAM,IAAI,GAAG,MAAM,CAAC,KAAK,CAAC,CAAC,EAAE,GAAG,CAAC,CAAC,OAAO,CAAC,KAAK,EAAE,EAAE,CAAC,CAAC;gBACrD,MAAM,GAAG,MAAM,CAAC,KAAK,CAAC,GAAG,GAAG,CAAC,CAAC,CAAC;gBAC/B,IAAI,CAAC,IAAI,EAAE,CAAC;oBACV,MAAM,OAAO,GAAG,KAAK,EAAE,CAAC;oBACxB,IAAI,OAAO;wBAAE,OAAO,OAAO,CAAC;oBAC5B,SAAS;gBACX,CAAC;gBACD,IAAI,IAAI,CAAC,UAAU,CAAC,OAAO,CAAC,EAAE,CAAC;oBAC7B,6DAA6D;oBAC7D,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,IAAI,EAAE,EAAE,CAAC,CAAC,CAAC;gBAC7C,CAAC;YACH,CAAC;QACH,CAAC;QACD,MAAM,QAAQ,GAAG,KAAK,EAAE,CAAC;QACzB,IAAI,QAAQ;YAAE,OAAO,QAAQ,CAAC;IAChC,CAAC;YAAS,CAAC;QACT,MAAM,MAAM,CAAC,MAAM,EAAE,CAAC,KAAK,CAAC,GAAG,EAAE,GAAE,CAAC,CAAC,CAAC;IACxC,CAAC;IACD,MAAM,IAAI,UAAU,CAAC,iDAAiD,EAAE,UAAU,EAAE,GAAG,CAAC,CAAC;AAC3F,CAAC;AAED;;;qBAGqB;AACrB,MAAM,CAAC,KAAK,UAAU,qBAAqB,CACzC,OAA4B,EAC5B,iBAA2C,EAAE;IAE7C,MAAM,EAAE,GAAG,EAAE,GAAG,OAAO,CAAC;IACxB,MAAM,OAAO,GAAG,OAAO,CAAC,SAAS,IAAI,UAAU,CAAC,KAAK,CAAC;IACtD,IAAI,OAAO,OAAO,KAAK,UAAU,EAAE,CAAC;QAClC,MAAM,IAAI,kBAAkB,CAAC,4CAA4C,EAAE,GAAG,CAAC,CAAC;IAClF,CAAC;IACD,MAAM,UAAU,GAAG,OAAO,CAAC,UAAU,IAAI,EAAE,IAAI,EAAE,gBAAgB,EAAE,OAAO,EAAE,GAAG,EAAE,CAAC;IAClF,MAAM,cAAc,GAAG,OAAO,CAAC,SAAS,IAAI,sBAAsB,CAAC;IAEnE,IAAI,SAA6B,CAAC;IAClC,IAAI,UAAU,GAAG,uBAAuB,CAAC;IACzC,IAAI,MAAM,GAAG,CAAC,CAAC;IAEf;;+DAE2D;IAC3D,SAAS,OAAO,CAAC,KAA8B;QAC7C,OAAO;YACL,GAAG,OAAO,CAAC,OAAO;YAClB,cAAc,EAAE,kBAAkB;YAClC,MAAM,EAAE,qCAAqC;YAC7C,GAAG,CAAC,SAAS,CAAC,CAAC,CAAC,EAAE,gBAAgB,EAAE,SAAS,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;YACrD,GAAG,KAAK;SACT,CAAC;IACJ,CAAC;IAED,KAAK,UAAU,IAAI,CACjB,IAA6B,EAC7B,UAA2B,EAC3B,IAAkC,EAClC,SAAiB,EACjB,YAAqC;QAErC,IAAI,GAAa,CAAC;QAClB,IAAI,CAAC;YACH,GAAG,GAAG,MAAM,YAAY,CAAC,OAAO,CAAC,GAAG,EAAE;gBACpC,MAAM,EAAE,MAAM;gBACd,OAAO,EAAE,OAAO,CAAC,YAAY,CAAC;gBAC9B,IAAI,EAAE,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC;gBAC1B,MAAM,EAAE,IAAI,CAAC,MAAM;aACpB,CAAC,EAAE,IAAI,CAAC,CAAC;QACZ,CAAC;QAAC,OAAO,GAAG,EAAE,CAAC;YACb,MAAM,IAAI,UAAU,CAAC,4BAA4B,eAAe,CAAC,GAAG,EAAE,SAAS,CAAC,EAAE,EAAE,GAAG,EAAE,EAAE,KAAK,EAAE,GAAG,EAAE,CAAC,CAAC;QAC3G,CAAC;QACD,IAAI,CAAC,GAAG,CAAC,EAAE,EAAE,CAAC;YACZ,MAAM,IAAI,GAAG,MAAM,GAAG,CAAC,IAAI,EAAE,CAAC,KAAK,CAAC,GAAG,EAAE,CAAC,EAAE,CAAC,CAAC;YAC9C,MAAM,IAAI,UAAU,CAAC,uBAAuB,GAAG,CAAC,MAAM,GAAG,IAAI,CAAC,CAAC,CAAC,KAAK,IAAI,CAAC,KAAK,CAAC,CAAC,EAAE,GAAG,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,EAAE,EAAE,GAAG,CAAC,CAAC;QACzG,CAAC;QACD,OAAO,GAAG,CAAC;IACb,CAAC;IAED,KAAK,UAAU,GAAG,CAChB,MAAc,EACd,MAA2C,EAC3C,UAA2B,EAC3B,cAAkC;QAElC,MAAM,EAAE,GAAG,MAAM,EAAE,CAAC;QACpB,MAAM,SAAS,GAAG,cAAc,EAAE,SAAS,IAAI,cAAc,CAAC;QAC9D,MAAM,IAAI,GAAG,SAAS,CAAC,CAAC,OAAO,CAAC,MAAM,EAAE,cAAc,EAAE,MAAM,CAAC,EAAE,SAAS,CAAC,CAAC;QAC5E,IAAI,CAAC;YACH,MAAM,GAAG,GAAG,MAAM,IAAI,CACpB,EAAE,OAAO,EAAE,KAAK,EAAE,EAAE,EAAE,MAAM,EAAE,GAAG,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,MAAM,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAC7D,UAAU,EACV,IAAI,EACJ,SAAS,EACT,MAAM,KAAK,YAAY,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,sBAAsB,EAAE,UAAU,EAAE,CACtE,CAAC;YACF,IAAI,MAAM,KAAK,YAAY,EAAE,CAAC;gBAC5B,MAAM,QAAQ,GAAG,GAAG,CAAC,OAAO,CAAC,GAAG,CAAC,gBAAgB,CAAC,CAAC;gBACnD,IAAI,QAAQ;oBAAE,SAAS,GAAG,QAAQ,CAAC;YACrC,CAAC;YACD,MAAM,WAAW,GAAG,GAAG,CAAC,OAAO,CAAC,GAAG,CAAC,cAAc,CAAC,IAAI,EAAE,CAAC;YAC1D,IAAI,OAAwB,CAAC;YAC7B,IAAI,WAAW,CAAC,QAAQ,CAAC,mBAAmB,CAAC,EAAE,CAAC;gBAC9C,IAAI,CAAC;oBACH,OAAO,GAAG,MAAM,eAAe,CAAC,GAAG,EAAE,EAAE,EAAE,GAAG,EAAE,IAAI,EAAE,UAAU,CAAC,CAAC;gBAClE,CAAC;gBAAC,OAAO,GAAG,EAAE,CAAC;oBACb,IAAI,GAAG,YAAY,QAAQ;wBAAE,MAAM,GAAG,CAAC;oBACvC,MAAM,IAAI,UAAU,CAAC,GAAG,MAAM,YAAY,eAAe,CAAC,GAAG,EAAE,SAAS,CAAC,EAAE,EAAE,GAAG,EAAE,EAAE,KAAK,EAAE,GAAG,EAAE,CAAC,CAAC;gBACpG,CAAC;YACH,CAAC;iBAAM,CAAC;gBACN,MAAM,IAAI,GAAG,MAAM,YAAY,CAAC,GAAG,CAAC,IAAI,EAAE,EAAE,IAAI,CAAC,CAAC,KAAK,CAAC,CAAC,GAAY,EAAE,EAAE;oBACvE,MAAM,IAAI,UAAU,CAAC,GAAG,MAAM,YAAY,eAAe,CAAC,GAAG,EAAE,SAAS,CAAC,EAAE,EAAE,GAAG,EAAE,EAAE,KAAK,EAAE,GAAG,EAAE,CAAC,CAAC;gBACpG,CAAC,CAAC,CAAC;gBACH,IAAI,CAAC;oBACH,OAAO,GAAG,IAAI,CAAC,KAAK,CAAC,IAAI,CAAoB,CAAC;gBAChD,CAAC;gBAAC,MAAM,CAAC;oBACP,MAAM,IAAI,UAAU,CAAC,0CAA0C,MAAM,KAAK,IAAI,CAAC,KAAK,CAAC,CAAC,EAAE,GAAG,CAAC,EAAE,EAAE,GAAG,CAAC,CAAC;gBACvG,CAAC;YACH,CAAC;YACD,IAAI,OAAO,CAAC,KAAK,EAAE,CAAC;gBAClB,MAAM,IAAI,UAAU,CAAC,GAAG,MAAM,YAAY,OAAO,CAAC,KAAK,CAAC,IAAI,MAAM,OAAO,CAAC,KAAK,CAAC,OAAO,EAAE,EAAE,GAAG,CAAC,CAAC;YAClG,CAAC;YACD,OAAO,OAAO,CAAC,MAAW,CAAC;QAC7B,CAAC;gBAAS,CAAC;YACT,IAAI,CAAC,MAAM,EAAE,CAAC;QAChB,CAAC;IACH,CAAC;IAED,MAAM,UAAU,GAAG,MAAM,GAAG,CAIzB,YAAY,EAAE;QACf,eAAe,EAAE,uBAAuB;QACxC,YAAY,EAAE,EAAE;QAChB,UAAU;KACX,EAAE,kBAAkB,EAAE,cAAc,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,MAAM,EAAE,cAAc,CAAC,MAAM,EAAE,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC;IAE9F,MAAM,aAAa,GAAG,UAAU,EAAE,eAAe,IAAI,uBAAuB,CAAC;IAC7E,yEAAyE;IACzE,8DAA8D;IAC9D,IAAI,CAAC,2BAA2B,CAAC,GAAG,CAAC,aAAa,CAAC,IAAI,aAAa,GAAG,uBAAuB,EAAE,CAAC;QAC/F,MAAM,IAAI,kBAAkB,CAC1B,+BAA+B,aAAa,2BAA2B;YACvE,GAAG,uBAAuB,gBAAgB,CAAC,GAAG,2BAA2B,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,EACvF,GAAG,CACJ,CAAC;IACJ,CAAC;IACD,UAAU,GAAG,aAAa,CAAC;IAE3B,wEAAwE;IACxE,yEAAyE;IACzE,qEAAqE;IACrE,sBAAsB;IACtB,CAAC;QACC,MAAM,IAAI,GAAG,SAAS,CAAC,CAAC,OAAO,CAAC,MAAM,EAAE,cAAc,CAAC,MAAM,CAAC,EAAE,cAAc,CAAC,CAAC;QAChF,IAAI,CAAC;YACH,MAAM,GAAG,GAAG,MAAM,IAAI,CACpB,EAAE,OAAO,EAAE,KAAK,EAAE,MAAM,EAAE,2BAA2B,EAAE,EACvD,kBAAkB,EAClB,IAAI,EACJ,cAAc,EACd,EAAE,sBAAsB,EAAE,UAAU,EAAE,CACvC,CAAC;YACF,MAAM,GAAG,CAAC,IAAI,EAAE,MAAM,EAAE,CAAC,KAAK,CAAC,GAAG,EAAE,GAAE,CAAC,CAAC,CAAC;QAC3C,CAAC;gBAAS,CAAC;YACT,IAAI,CAAC,MAAM,EAAE,CAAC;QAChB,CAAC;IACH,CAAC;IAED,OAAO;QACL,GAAG;QACH,UAAU,EAAE;YACV,IAAI,EAAE,UAAU,EAAE,UAAU,EAAE,IAAI,IAAI,SAAS;YAC/C,OAAO,EAAE,UAAU,EAAE,UAAU,EAAE,OAAO,IAAI,GAAG;SAChD;QACD,eAAe,EAAE,UAAU;QAC3B,YAAY,EAAE,UAAU,EAAE,YAAY,IAAI,EAAE;QAC5C,OAAO,CACL,MAAc,EACd,MAAgC,EAChC,cAAkC;YAElC,OAAO,GAAG,CAAI,MAAM,EAAE,MAAM,EAAE,YAAY,EAAE,cAAc,CAAC,CAAC;QAC9D,CAAC;QACD,KAAK,CAAC,KAAK;YACT,IAAI,CAAC,SAAS;gBAAE,OAAO;YACvB,MAAM,IAAI,GAAG,SAAS,CAAC,EAAE,EAAE,cAAc,CAAC,CAAC;YAC3C,IAAI,CAAC;gBACH,MAAM,YAAY,CAAC,OAAO,CAAC,GAAG,EAAE;oBAC9B,MAAM,EAAE,QAAQ;oBAChB,OAAO,EAAE,OAAO,CAAC,EAAE,sBAAsB,EAAE,UAAU,EAAE,CAAC;oBACxD,MAAM,EAAE,IAAI,CAAC,MAAM;iBACpB,CAAC,EAAE,IAAI,CAAC,CAAC;YACZ,CAAC;YAAC,MAAM,CAAC;gBACP,sEAAsE;YACxE,CAAC;oBAAS,CAAC;gBACT,IAAI,CAAC,MAAM,EAAE,CAAC;YAChB,CAAC;YACD,SAAS,GAAG,SAAS,CAAC;QACxB,CAAC;KACF,CAAC;AACJ,CAAC"}
package/mcp.d.ts ADDED
@@ -0,0 +1,120 @@
1
+ /**
2
+ * MCP-client mode — a server becomes a tool/resource source.
3
+ *
4
+ * `mcpServer({ url })` declares a source; the agent connects it and every
5
+ * tool the server lists arrives as a normal `ToolDef` in the loop. Nothing
6
+ * downstream knows the difference: guardrails see the calls, the tracer
7
+ * records the executions, `checkInput` runs at the boundary, a failure comes
8
+ * back as an `isError` tool_result. That sameness is the point — MCP is a
9
+ * SOURCE of tools, not a second kind of tool.
10
+ *
11
+ * How it composes with the tier-2 registry (integrations.ts):
12
+ * - `register` — used, and it is the fail-fast the lead cares about: two
13
+ * servers exposing `search`, or a server tool colliding with a declared
14
+ * one, throws at connect instead of silently shadowing.
15
+ * - `buildToolDispatch` — used: the ONE place a manifest becomes a ToolDef
16
+ * (law 8's shared executor seam) stays the only place.
17
+ * - `resolveIntegrations` — deliberately NOT used. Its two jobs are
18
+ * persona-enablement intersection and dropping manifests whose env key is
19
+ * unprovisioned; an MCP server has neither a persona list nor an env key,
20
+ * and its `MAX_INTEGRATIONS` cap SILENTLY drops the overflow. A server
21
+ * exposing more tools than the cap is a real thing (the in-repo a2ui
22
+ * server has ~20), and quietly serving two thirds of them is the failure
23
+ * mode this whole feature is supposed to prevent. So the cap here is
24
+ * explicit and LOUD: `maxTools` (default `MAX_INTEGRATIONS`) throws when
25
+ * exceeded, and `tools` narrows the list on purpose.
26
+ *
27
+ * Schemas arrive as JSON Schema and are passed to the model VERBATIM. They
28
+ * are not trimmed to `checkInput`'s allowlist: the MCP server is the
29
+ * authoritative validator (its rejection comes back as an error result the
30
+ * model can read), so a faithful copy of a contract someone else owns beats
31
+ * a locally-enforceable subset that describes the tool less accurately. The
32
+ * manifest says so with `validation: 'remote'` rather than leaving it
33
+ * implied.
34
+ *
35
+ * RESOURCES map onto the two existing modes and no new one. `tool` is the
36
+ * default — the harness cannot know which of a remote server's resources an
37
+ * app wants in every prompt, and attaching all of them would grow the system
38
+ * prompt without bound — and `attach: [name|uri]` promotes the ones the APP
39
+ * decides belong there every turn. That is the whole application-controlled
40
+ * vs. model-controlled distinction MCP itself draws, expressed with the
41
+ * modes the harness already has. gh#671's third mode is NOT needed here; see
42
+ * the README's ruling.
43
+ *
44
+ * Everything a server returns — tool descriptions, resource text, error
45
+ * strings — is DATA. A description that reads like an instruction is still a
46
+ * description; it lands inside the tool spec or a `<resource>` envelope and
47
+ * decides nothing about what the harness does.
48
+ */
49
+ import { type ResourceDef } from './resource.js';
50
+ import type { ToolDef } from './tools.js';
51
+ import { type McpConnection, type McpTransportOptions } from './mcp-transport.js';
52
+ export interface McpServerOptions extends McpTransportOptions {
53
+ /** Prefix for every tool name this server contributes — the way to run
54
+ * two servers that both expose `search`. Applied before the
55
+ * `[a-zA-Z0-9_-]` sanitize, so `weather_` + `get-forecast` is
56
+ * `weather_get-forecast`. */
57
+ prefix?: string;
58
+ /** Allowlist of server-side tool names to register. Absent = all of them
59
+ * (subject to `maxTools`). */
60
+ tools?: string[];
61
+ /** Loud cap: more listed tools than this throws at connect rather than
62
+ * registering a silent subset. Default `MAX_INTEGRATIONS`. */
63
+ maxTools?: number;
64
+ /** `false` skips `resources/list` entirely — a server whose resources are
65
+ * irrelevant to this agent shouldn't pay for the round trip. */
66
+ resources?: boolean;
67
+ /** Resource names or URIs to expose as `attach` mode (fetched every turn
68
+ * and inlined in the system prompt). Everything else is `tool` mode. */
69
+ attach?: string[];
70
+ }
71
+ /** What `createAgent({ integrations })` accepts. One arm today; the union
72
+ * is the extension point a future source (an OpenAPI spec, a worker) adds
73
+ * an arm to without changing the config surface. */
74
+ export interface McpSource {
75
+ kind: 'mcp';
76
+ url: string;
77
+ options: McpServerOptions;
78
+ }
79
+ export interface McpServerReport {
80
+ url: string;
81
+ serverInfo: {
82
+ name: string;
83
+ version: string;
84
+ };
85
+ protocolVersion: string;
86
+ tools: string[];
87
+ resources: Array<{
88
+ name: string;
89
+ uri: string;
90
+ mode: 'attach' | 'tool';
91
+ }>;
92
+ }
93
+ export interface ConnectedMcpServer extends McpServerReport {
94
+ connection: McpConnection;
95
+ toolDefs: ToolDef[];
96
+ resourceDefs: ResourceDef[];
97
+ }
98
+ /** Declare an MCP server as a source. Pure — no connection happens here, so
99
+ * this is safe to call at module scope; the agent connects on first use (or
100
+ * eagerly via `agent.connect()`). */
101
+ export declare function mcpServer(options: McpServerOptions): McpSource;
102
+ /** Connect one declared source: handshake, list, register, build. Any
103
+ * failure along the way throws `McpConnectionError` — including a failure
104
+ * the REGISTRY raises, which is a plain Error about a manifest and would
105
+ * otherwise escape as a different error class than the one the failure
106
+ * table promises. The caller never receives a half-built source or an empty
107
+ * tool list that looks like a server with nothing to offer.
108
+ *
109
+ * `signal` cancels the connect in flight (the turn that triggered it was
110
+ * aborted); it does NOT stay attached to the resulting connection, whose
111
+ * later calls carry their own turn's signal. */
112
+ export declare function connectMcpSource(source: McpSource, opts?: {
113
+ signal?: AbortSignal;
114
+ }): Promise<ConnectedMcpServer>;
115
+ /** The whole assembled tool set must have unique names — the loop dispatches
116
+ * by name, so a duplicate is a tool that silently never runs. Per-server
117
+ * registration cannot see across sources or into the declared tools, so the
118
+ * check lands here, once, over everything. */
119
+ export declare function assertUniqueToolNames(tools: ToolDef[]): void;
120
+ //# sourceMappingURL=mcp.d.ts.map
package/mcp.d.ts.map ADDED
@@ -0,0 +1 @@
1
+ {"version":3,"file":"mcp.d.ts","sourceRoot":"","sources":["src/mcp.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA+CG;AAMH,OAAO,EAAkB,KAAK,WAAW,EAAwB,MAAM,eAAe,CAAC;AACvF,OAAO,KAAK,EAAe,OAAO,EAAE,MAAM,YAAY,CAAC;AACvD,OAAO,EAEL,KAAK,aAAa,EAAE,KAAK,mBAAmB,EAC7C,MAAM,oBAAoB,CAAC;AAE5B,MAAM,WAAW,gBAAiB,SAAQ,mBAAmB;IAC3D;;;kCAG8B;IAC9B,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB;mCAC+B;IAC/B,KAAK,CAAC,EAAE,MAAM,EAAE,CAAC;IACjB;mEAC+D;IAC/D,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB;qEACiE;IACjE,SAAS,CAAC,EAAE,OAAO,CAAC;IACpB;6EACyE;IACzE,MAAM,CAAC,EAAE,MAAM,EAAE,CAAC;CACnB;AAED;;qDAEqD;AACrD,MAAM,WAAW,SAAS;IACxB,IAAI,EAAE,KAAK,CAAC;IACZ,GAAG,EAAE,MAAM,CAAC;IACZ,OAAO,EAAE,gBAAgB,CAAC;CAC3B;AAED,MAAM,WAAW,eAAe;IAC9B,GAAG,EAAE,MAAM,CAAC;IACZ,UAAU,EAAE;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,OAAO,EAAE,MAAM,CAAA;KAAE,CAAC;IAC9C,eAAe,EAAE,MAAM,CAAC;IACxB,KAAK,EAAE,MAAM,EAAE,CAAC;IAChB,SAAS,EAAE,KAAK,CAAC;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,GAAG,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,QAAQ,GAAG,MAAM,CAAA;KAAE,CAAC,CAAC;CAC1E;AAED,MAAM,WAAW,kBAAmB,SAAQ,eAAe;IACzD,UAAU,EAAE,aAAa,CAAC;IAC1B,QAAQ,EAAE,OAAO,EAAE,CAAC;IACpB,YAAY,EAAE,WAAW,EAAE,CAAC;CAC7B;AAyBD;;sCAEsC;AACtC,wBAAgB,SAAS,CAAC,OAAO,EAAE,gBAAgB,GAAG,SAAS,CAG9D;AA2GD;;;;;;;;;iDASiD;AACjD,wBAAsB,gBAAgB,CACpC,MAAM,EAAE,SAAS,EACjB,IAAI,GAAE;IAAE,MAAM,CAAC,EAAE,WAAW,CAAA;CAAO,GAClC,OAAO,CAAC,kBAAkB,CAAC,CAa7B;AA+GD;;;+CAG+C;AAC/C,wBAAgB,qBAAqB,CAAC,KAAK,EAAE,OAAO,EAAE,GAAG,IAAI,CAW5D"}