@anvia/mcp 1.0.0-rc.10

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/README.md ADDED
@@ -0,0 +1,86 @@
1
+ # @anvia/mcp
2
+
3
+ Model Context Protocol client integration for Anvia agents.
4
+
5
+ This package owns MCP connections, transports, tool discovery, and cleanup. `@anvia/core` keeps only
6
+ the lightweight MCP registration contracts consumed by `Agent`.
7
+
8
+ Requires Node.js 20 or newer and uses the official MCP TypeScript SDK v2 client.
9
+
10
+ ## Installation
11
+
12
+ ```sh
13
+ pnpm add @anvia/mcp @anvia/core
14
+ ```
15
+
16
+ ## Usage
17
+
18
+ ```ts
19
+ import { Agent } from "@anvia/core/agent";
20
+ import { McpClient, McpClientGroup } from "@anvia/mcp";
21
+
22
+ const filesystem = new McpClient({
23
+ name: "filesystem",
24
+ transport: {
25
+ type: "stdio",
26
+ command: "npx",
27
+ args: ["-y", "@modelcontextprotocol/server-filesystem", "./workspace"],
28
+ },
29
+ });
30
+ const github = new McpClient({
31
+ name: "github",
32
+ transport: {
33
+ type: "streamableHttp",
34
+ url: "https://mcp.example.com/mcp",
35
+ headers: { authorization: `Bearer ${process.env.MCP_TOKEN}` },
36
+ },
37
+ tools: { prefix: "github_" },
38
+ });
39
+
40
+ const mcp = await McpClientGroup.connect({ clients: [filesystem, github] });
41
+ const agent = new Agent({ id: "assistant", model, mcpServers: mcp.servers });
42
+
43
+ try {
44
+ await agent.generate({ prompt: "Find the issue and update it." });
45
+ } finally {
46
+ await mcp.close();
47
+ }
48
+ ```
49
+
50
+ Construction performs no I/O. `connect()` discovers every tool page once and returns a frozen
51
+ registration snapshot. Reconnect and rebuild the Agent to adopt changed remote tools.
52
+
53
+ `@anvia/mcp` requires the modern MCP `2026-07-28` protocol. Connections fail clearly when a server
54
+ does not support that revision; the package never attempts or falls back to the legacy MCP
55
+ handshake.
56
+
57
+ Built-in Streamable HTTP connections enforce Anvia URL safety by default and do not accept a custom
58
+ `fetch`. Static request headers are explicit transport configuration; arbitrary Fetch `RequestInit`
59
+ fields are not exposed because the MCP transport owns its HTTP method, body, abort signal, session,
60
+ and protocol headers. Configured headers are sent only to the exact MCP endpoint, are not attached to
61
+ OAuth requests, and cause endpoint redirects to fail instead of forwarding credentials. A static
62
+ `authorization` header cannot be combined with `authProvider`.
63
+
64
+ For an intentionally local or private-network server, set `ssrfProtection: "disabled"` on that
65
+ transport. This disables hostname and DNS restrictions for the complete transport, including
66
+ redirects and OAuth discovery, while still requiring HTTP(S). Use it only when the application owns
67
+ and trusts that network boundary. MCP server instructions remain inspectable metadata and are not
68
+ added to Agent instructions.
69
+
70
+ ## Exports
71
+
72
+ - `McpClient`
73
+ - `McpClientGroup`
74
+ - `McpClientOptions`
75
+ - `McpClientTransport`
76
+ - `McpServer`
77
+ - `McpTool`
78
+ - `isMcpTool`
79
+
80
+ ## Development
81
+
82
+ ```sh
83
+ pnpm --filter @anvia/mcp typecheck
84
+ pnpm --filter @anvia/mcp test
85
+ pnpm --filter @anvia/mcp build
86
+ ```
@@ -0,0 +1,65 @@
1
+ import { McpServer } from '@anvia/core/mcp';
2
+ export { McpServer, McpServerInfo, McpTool, isMcpTool } from '@anvia/core/mcp';
3
+ import { IOType } from 'node:child_process';
4
+ import { Stream } from 'node:stream';
5
+ import { OAuthClientProvider, StreamableHTTPReconnectionOptions, Transport } from '@modelcontextprotocol/client';
6
+
7
+ type McpStdioTransport = {
8
+ readonly type: "stdio";
9
+ readonly command: string;
10
+ readonly args?: string[] | undefined;
11
+ readonly env?: Record<string, string> | undefined;
12
+ readonly cwd?: string | undefined;
13
+ readonly stderr?: IOType | Stream | number | undefined;
14
+ readonly maxBufferSize?: number | undefined;
15
+ };
16
+ type McpStreamableHttpTransport = {
17
+ readonly type: "streamableHttp";
18
+ readonly url: string | URL;
19
+ readonly ssrfProtection?: "strict" | "disabled" | undefined;
20
+ readonly headers?: Readonly<Record<string, string>> | undefined;
21
+ readonly authProvider?: OAuthClientProvider | undefined;
22
+ readonly reconnectionOptions?: StreamableHTTPReconnectionOptions | undefined;
23
+ readonly sessionId?: string | undefined;
24
+ };
25
+ type McpTransport = Transport;
26
+ type McpCustomTransport = {
27
+ readonly type: "custom";
28
+ readonly create: (options: {
29
+ abortSignal?: AbortSignal | undefined;
30
+ }) => McpTransport | Promise<McpTransport>;
31
+ };
32
+ type McpClientTransport = McpStdioTransport | McpStreamableHttpTransport | McpCustomTransport;
33
+ type McpClientOptions = {
34
+ readonly name: string;
35
+ readonly transport: McpClientTransport;
36
+ readonly tools?: {
37
+ readonly prefix?: string | undefined;
38
+ };
39
+ };
40
+ type McpConnectOptions = {
41
+ readonly abortSignal?: AbortSignal | undefined;
42
+ };
43
+ type McpClientGroupConnectOptions = {
44
+ readonly clients: readonly McpClient[];
45
+ readonly abortSignal?: AbortSignal | undefined;
46
+ };
47
+
48
+ declare class McpClient {
49
+ #private;
50
+ readonly name: string;
51
+ constructor(options: McpClientOptions);
52
+ connect(options?: McpConnectOptions): Promise<McpServer>;
53
+ close(): Promise<void>;
54
+ }
55
+
56
+ declare class McpClientGroup {
57
+ #private;
58
+ readonly clients: readonly McpClient[];
59
+ readonly servers: readonly McpServer[];
60
+ private constructor();
61
+ static connect(options: McpClientGroupConnectOptions): Promise<McpClientGroup>;
62
+ close(): Promise<void>;
63
+ }
64
+
65
+ export { McpClient, McpClientGroup, type McpClientGroupConnectOptions, type McpClientOptions, type McpClientTransport, type McpConnectOptions, type McpCustomTransport, type McpStdioTransport, type McpStreamableHttpTransport, type McpTransport };
package/dist/index.js ADDED
@@ -0,0 +1,717 @@
1
+ // src/index.ts
2
+ import { isMcpTool } from "@anvia/core/mcp";
3
+
4
+ // src/client.ts
5
+ import { readFileSync } from "fs";
6
+ import { Client, StreamableHTTPClientTransport } from "@modelcontextprotocol/client";
7
+ import { StdioClientTransport } from "@modelcontextprotocol/client/stdio";
8
+
9
+ // src/abort.ts
10
+ function linkAbortSignal(source, target) {
11
+ if (source === void 0) {
12
+ return () => void 0;
13
+ }
14
+ if (source.aborted) {
15
+ target.abort(source.reason);
16
+ return () => void 0;
17
+ }
18
+ const onAbort = () => target.abort(source.reason);
19
+ source.addEventListener("abort", onAbort, { once: true });
20
+ return () => source.removeEventListener("abort", onAbort);
21
+ }
22
+ function throwIfAborted(signal) {
23
+ if (signal?.aborted === true) {
24
+ throw abortError(signal.reason);
25
+ }
26
+ }
27
+ function abortError(reason) {
28
+ if (isAbortError(reason)) {
29
+ return reason;
30
+ }
31
+ const error = new Error(
32
+ "The operation was aborted.",
33
+ reason === void 0 ? void 0 : { cause: reason }
34
+ );
35
+ error.name = "AbortError";
36
+ return error;
37
+ }
38
+ function isAbortError(error) {
39
+ const seen = /* @__PURE__ */ new Set();
40
+ let current = error;
41
+ while (typeof current === "object" && current !== null && !seen.has(current)) {
42
+ seen.add(current);
43
+ if ("name" in current && current.name === "AbortError") {
44
+ return true;
45
+ }
46
+ current = "cause" in current ? current.cause : void 0;
47
+ }
48
+ return false;
49
+ }
50
+
51
+ // src/tool.ts
52
+ import { ToolOutput } from "@anvia/core/tool";
53
+
54
+ // src/result.ts
55
+ import { isJsonValue } from "@anvia/core/completion";
56
+ function createCallToolParams(name, args) {
57
+ if (args === void 0) {
58
+ return { name };
59
+ }
60
+ return { name, arguments: parseMcpToolArguments(args) };
61
+ }
62
+ function parseMcpToolArguments(args) {
63
+ if (!isMcpJsonObject(args)) {
64
+ throw new TypeError("MCP tool arguments must be a strict JSON object");
65
+ }
66
+ return args;
67
+ }
68
+ function isMcpJsonObject(value) {
69
+ return typeof value === "object" && value !== null && !Array.isArray(value) && isJsonValue(value);
70
+ }
71
+ function mapMcpToolResult(result) {
72
+ if ("toolResult" in result) {
73
+ return [{ type: "text", text: serializeMcpValue(result.toolResult) }];
74
+ }
75
+ if (result.isError === true) {
76
+ throw new Error(mcpErrorMessage(result.content));
77
+ }
78
+ const content = result.content.map(mapMcpContent);
79
+ if (content.length === 0 && result.structuredContent !== void 0) {
80
+ content.push({ type: "text", text: serializeMcpValue(result.structuredContent) });
81
+ }
82
+ return content;
83
+ }
84
+ function mcpErrorMessage(content) {
85
+ const text = content.map((item) => item.type === "text" ? item.text : void 0).filter((item) => item !== void 0).join("\n");
86
+ return text === "" ? "MCP tool returned an error" : text;
87
+ }
88
+ function mapMcpContent(content) {
89
+ if (content.type === "text") {
90
+ return { type: "text", text: content.text };
91
+ }
92
+ if (content.type === "image") {
93
+ return {
94
+ type: "file",
95
+ data: { type: "data", data: content.data },
96
+ mediaType: content.mimeType
97
+ };
98
+ }
99
+ if (content.type === "resource") {
100
+ return { type: "text", text: serializeResource(content.resource) };
101
+ }
102
+ if (content.type === "audio") {
103
+ throw new Error(`Unsupported MCP tool result content type: audio (${content.mimeType})`);
104
+ }
105
+ throw new Error(`Unsupported MCP tool result content type: resource_link (${content.uri})`);
106
+ }
107
+ function serializeResource(resource) {
108
+ const mediaType = resource.mimeType ?? ("text" in resource ? "text/plain" : "application/octet-stream");
109
+ const encoding = "text" in resource ? "text" : "base64";
110
+ const data = "text" in resource ? resource.text : resource.blob;
111
+ return `MCP resource (${resource.uri}; ${mediaType}; ${encoding})
112
+ ${data}`;
113
+ }
114
+ function serializeMcpValue(value) {
115
+ if (typeof value === "string") {
116
+ return value;
117
+ }
118
+ if (!isJsonValue(value)) {
119
+ throw new TypeError("MCP tool results must be strict JSON values.");
120
+ }
121
+ let serialized;
122
+ try {
123
+ serialized = JSON.stringify(value);
124
+ } catch (error) {
125
+ throw new TypeError("MCP tool results must be strict JSON values.", { cause: error });
126
+ }
127
+ if (serialized === void 0) {
128
+ throw new TypeError("MCP tool results must be strict JSON values.");
129
+ }
130
+ return serialized;
131
+ }
132
+
133
+ // src/tool.ts
134
+ function createMcpTool(options) {
135
+ const { definition, client, serverName, prefix = "" } = options;
136
+ const exposedName = `${prefix}${definition.name}`;
137
+ const provenance = Object.freeze({
138
+ serverName,
139
+ remoteName: definition.name
140
+ });
141
+ const toolDefinition = Object.freeze({
142
+ name: exposedName,
143
+ description: definition.description ?? "",
144
+ parameters: deepFreeze(structuredClone(definition.inputSchema))
145
+ });
146
+ const tool = {
147
+ name: exposedName,
148
+ mcp: provenance,
149
+ definition() {
150
+ return toolDefinition;
151
+ },
152
+ parseInput(args) {
153
+ return parseMcpToolArguments(args);
154
+ },
155
+ async call(args, context) {
156
+ const result = await client.callTool(
157
+ createCallToolParams(definition.name, args),
158
+ context?.abortSignal === void 0 ? {} : { signal: context.abortSignal }
159
+ );
160
+ return ToolOutput.content(mapMcpToolResult(result));
161
+ }
162
+ };
163
+ return Object.freeze(tool);
164
+ }
165
+ function deepFreeze(value) {
166
+ if (typeof value !== "object" || value === null || Object.isFrozen(value)) {
167
+ return value;
168
+ }
169
+ for (const child of Object.values(value)) {
170
+ deepFreeze(child);
171
+ }
172
+ return Object.freeze(value);
173
+ }
174
+
175
+ // src/url-safety.ts
176
+ import { lookup } from "dns/promises";
177
+ import { BlockList, isIP } from "net";
178
+ import { Agent, Pool, fetch as undiciFetch } from "undici";
179
+ var blockedIpv4Addresses = new BlockList();
180
+ var blockedIpv6Addresses = new BlockList();
181
+ for (const [network, prefix] of [
182
+ ["0.0.0.0", 8],
183
+ ["10.0.0.0", 8],
184
+ ["100.64.0.0", 10],
185
+ ["127.0.0.0", 8],
186
+ ["169.254.0.0", 16],
187
+ ["172.16.0.0", 12],
188
+ ["192.0.0.0", 24],
189
+ ["192.0.2.0", 24],
190
+ ["192.88.99.0", 24],
191
+ ["192.168.0.0", 16],
192
+ ["198.18.0.0", 15],
193
+ ["198.51.100.0", 24],
194
+ ["203.0.113.0", 24],
195
+ ["224.0.0.0", 4],
196
+ ["240.0.0.0", 4]
197
+ ]) {
198
+ blockedIpv4Addresses.addSubnet(network, prefix, "ipv4");
199
+ }
200
+ for (const [network, prefix] of [
201
+ ["::", 96],
202
+ ["::ffff:0:0", 96],
203
+ ["64:ff9b::", 96],
204
+ ["64:ff9b:1::", 48],
205
+ ["100::", 64],
206
+ ["2001::", 32],
207
+ ["2001:2::", 48],
208
+ ["2001:10::", 28],
209
+ ["2001:20::", 28],
210
+ ["2001:db8::", 32],
211
+ ["2002::", 16],
212
+ ["fc00::", 7],
213
+ ["fe80::", 10],
214
+ ["fec0::", 10],
215
+ ["ff00::", 8]
216
+ ]) {
217
+ blockedIpv6Addresses.addSubnet(network, prefix, "ipv6");
218
+ }
219
+ var defaultAddressResolver = (hostname) => lookup(hostname, { all: true, verbatim: true });
220
+ function parseAndValidateMcpUrl(url) {
221
+ const parsed = parseMcpHttpUrl(url);
222
+ validateMcpHostname(parsed.hostname);
223
+ return parsed;
224
+ }
225
+ function parseMcpHttpUrl(url) {
226
+ let parsed;
227
+ try {
228
+ parsed = new URL(url);
229
+ } catch {
230
+ throw new Error(`Invalid MCP URL: ${url}`);
231
+ }
232
+ if (parsed.protocol !== "http:" && parsed.protocol !== "https:") {
233
+ throw new Error(`MCP URL blocked: only HTTP(S) URLs are allowed (${parsed.protocol})`);
234
+ }
235
+ return parsed;
236
+ }
237
+ async function resolveAndValidateMcpHostname(hostname, resolveAddresses = defaultAddressResolver) {
238
+ const normalizedHostname = normalizeHostname(hostname);
239
+ validateMcpHostname(normalizedHostname);
240
+ const family = isIP(normalizedHostname);
241
+ if (family !== 0) {
242
+ return [{ address: normalizedHostname, family }];
243
+ }
244
+ let addresses;
245
+ try {
246
+ addresses = await resolveAddresses(normalizedHostname);
247
+ } catch (cause) {
248
+ throw new Error(`Unable to resolve MCP URL hostname (${normalizedHostname})`, { cause });
249
+ }
250
+ if (addresses.length === 0) {
251
+ throw new Error(`Unable to resolve MCP URL hostname (${normalizedHostname})`);
252
+ }
253
+ for (const { address } of addresses) {
254
+ validateMcpHostname(address);
255
+ }
256
+ return addresses;
257
+ }
258
+ function createSafeMcpLookup(resolveAddresses = defaultAddressResolver) {
259
+ return (hostname, options, callback) => {
260
+ void resolveAndValidateMcpHostname(hostname, resolveAddresses).then(
261
+ (addresses) => {
262
+ const requestedFamily = normalizeRequestedFamily(options.family);
263
+ const matchingAddresses = requestedFamily === 0 ? addresses : addresses.filter(({ family }) => family === requestedFamily);
264
+ if (matchingAddresses.length === 0) {
265
+ const error = new Error(`No matching address family for MCP URL (${hostname})`);
266
+ Object.assign(error, { code: "EAI_ADDRFAMILY" });
267
+ callback(error, []);
268
+ return;
269
+ }
270
+ if (options.all) {
271
+ callback(null, matchingAddresses);
272
+ return;
273
+ }
274
+ const address = matchingAddresses[0];
275
+ if (!address) {
276
+ callback(new Error(`Unable to resolve MCP URL hostname (${hostname})`), []);
277
+ return;
278
+ }
279
+ callback(null, address.address, address.family);
280
+ },
281
+ (cause) => {
282
+ callback(asError(cause), []);
283
+ }
284
+ );
285
+ };
286
+ }
287
+ function createSafeMcpFetch() {
288
+ return (url, init) => {
289
+ parseAndValidateMcpUrl(url);
290
+ return undiciFetch(url, {
291
+ ...init,
292
+ dispatcher: safeMcpDispatcher
293
+ });
294
+ };
295
+ }
296
+ function validateMcpHostname(hostname) {
297
+ const normalizedHostname = normalizeHostname(hostname);
298
+ if (normalizedHostname === "localhost" || normalizedHostname.endsWith(".localhost")) {
299
+ throw new Error(`MCP URL blocked: localhost not allowed (${normalizedHostname})`);
300
+ }
301
+ const family = isIP(normalizedHostname);
302
+ if (family === 0) {
303
+ return;
304
+ }
305
+ if (family === 4 && normalizedHostname.startsWith("127.") || family === 6 && normalizedHostname === "::1") {
306
+ throw new Error(`MCP URL blocked: localhost not allowed (${normalizedHostname})`);
307
+ }
308
+ if (normalizedHostname === "169.254.169.254" || normalizedHostname === "fd00:ec2::254") {
309
+ throw new Error(`MCP URL blocked: cloud metadata endpoint not allowed (${normalizedHostname})`);
310
+ }
311
+ if (family === 4 && blockedIpv4Addresses.check(normalizedHostname, "ipv4") || family === 6 && blockedIpv6Addresses.check(normalizedHostname, "ipv6")) {
312
+ const range = family === 4 ? "IP" : "IPv6";
313
+ throw new Error(`MCP URL blocked: private ${range} range not allowed (${normalizedHostname})`);
314
+ }
315
+ }
316
+ function normalizeHostname(hostname) {
317
+ const withoutBrackets = hostname.startsWith("[") && hostname.endsWith("]") ? hostname.slice(1, -1) : hostname;
318
+ return withoutBrackets.toLowerCase().replace(/\.+$/, "");
319
+ }
320
+ function normalizeRequestedFamily(family) {
321
+ if (family === 4 || family === "IPv4") {
322
+ return 4;
323
+ }
324
+ if (family === 6 || family === "IPv6") {
325
+ return 6;
326
+ }
327
+ return 0;
328
+ }
329
+ function asError(cause) {
330
+ return cause instanceof Error ? cause : new Error(String(cause));
331
+ }
332
+ var safeMcpDispatcher = new Agent({
333
+ autoSelectFamily: true,
334
+ connect: {
335
+ lookup: createSafeMcpLookup()
336
+ },
337
+ factory(origin, options) {
338
+ parseAndValidateMcpUrl(origin);
339
+ return new Pool(origin, options);
340
+ }
341
+ });
342
+
343
+ // src/client.ts
344
+ var mcpClientVersion;
345
+ var modernMcpProtocolVersion = "2026-07-28";
346
+ var transportOwnedHttpHeaders = /* @__PURE__ */ new Set([
347
+ "accept",
348
+ "content-type",
349
+ "last-event-id",
350
+ "mcp-method",
351
+ "mcp-name",
352
+ "mcp-protocol-version",
353
+ "mcp-session-id"
354
+ ]);
355
+ var McpClient = class {
356
+ name;
357
+ #options;
358
+ #closed = false;
359
+ #connectAbortController;
360
+ #connecting;
361
+ #resource;
362
+ #server;
363
+ constructor(options) {
364
+ if (options.name.trim() === "") {
365
+ throw new TypeError("MCP client name must not be empty");
366
+ }
367
+ this.name = options.name;
368
+ this.#options = options;
369
+ }
370
+ connect(options = {}) {
371
+ if (this.#closed) {
372
+ return Promise.reject(new Error(`MCP client "${this.name}" is closed`));
373
+ }
374
+ if (this.#server !== void 0) {
375
+ return Promise.resolve(this.#server);
376
+ }
377
+ if (this.#connecting !== void 0) {
378
+ return this.#connecting;
379
+ }
380
+ if (options.abortSignal?.aborted === true) {
381
+ return Promise.reject(abortError(options.abortSignal.reason));
382
+ }
383
+ const abortController = new AbortController();
384
+ const unlinkAbortSignal = linkAbortSignal(options.abortSignal, abortController);
385
+ this.#connectAbortController = abortController;
386
+ const connecting = this.#initialize(abortController.signal);
387
+ this.#connecting = connecting;
388
+ const clearConnecting = () => {
389
+ unlinkAbortSignal();
390
+ if (this.#connecting === connecting) {
391
+ this.#connecting = void 0;
392
+ }
393
+ if (this.#connectAbortController === abortController) {
394
+ this.#connectAbortController = void 0;
395
+ }
396
+ };
397
+ void connecting.then(clearConnecting, clearConnecting);
398
+ return connecting;
399
+ }
400
+ async close() {
401
+ this.#closed = true;
402
+ this.#connectAbortController?.abort(
403
+ abortError(new Error(`MCP client "${this.name}" was closed during connection`))
404
+ );
405
+ const resource = this.#resource;
406
+ if (resource !== void 0) {
407
+ await closeResource(resource);
408
+ }
409
+ }
410
+ async #initialize(abortSignal) {
411
+ const client = createSdkClient();
412
+ const resource = { client };
413
+ this.#resource = resource;
414
+ try {
415
+ throwIfAborted(abortSignal);
416
+ const transport = await createTransport(this.#options, { abortSignal });
417
+ throwIfAborted(abortSignal);
418
+ await client.connect(transport, requestOptions(abortSignal));
419
+ throwIfAborted(abortSignal);
420
+ const definitions = await listAllTools(client, abortSignal);
421
+ throwIfAborted(abortSignal);
422
+ const tools = definitions.map(
423
+ (definition) => createMcpTool({
424
+ definition,
425
+ client,
426
+ serverName: this.name,
427
+ prefix: this.#options.tools?.prefix
428
+ })
429
+ );
430
+ assertUniqueToolNames(tools, this.name);
431
+ if (this.#closed) {
432
+ throw new Error(`MCP client "${this.name}" was closed during connection`);
433
+ }
434
+ const serverInfo = copyServerInfo(client.getServerVersion());
435
+ const capabilities = copyJsonObject(client.getServerCapabilities());
436
+ const instructions = client.getInstructions();
437
+ let registration = {
438
+ name: this.name,
439
+ tools
440
+ };
441
+ if (serverInfo !== void 0) registration = { ...registration, serverInfo };
442
+ if (capabilities !== void 0) registration = { ...registration, capabilities };
443
+ if (instructions !== void 0) registration = { ...registration, instructions };
444
+ const server = freezeServer(registration);
445
+ this.#server = server;
446
+ return server;
447
+ } catch (error) {
448
+ try {
449
+ await closeResource(resource);
450
+ } catch {
451
+ }
452
+ if (this.#resource === resource) {
453
+ this.#resource = void 0;
454
+ }
455
+ this.#server = void 0;
456
+ throw error;
457
+ }
458
+ }
459
+ };
460
+ async function createTransport(options, connectOptions) {
461
+ const transport = options.transport;
462
+ if (transport.type === "custom") {
463
+ return transport.create({ abortSignal: connectOptions.abortSignal });
464
+ }
465
+ if (transport.type === "stdio") {
466
+ let parameters2 = {
467
+ command: transport.command
468
+ };
469
+ if (transport.args !== void 0) parameters2 = { ...parameters2, args: transport.args };
470
+ if (transport.env !== void 0) parameters2 = { ...parameters2, env: transport.env };
471
+ if (transport.cwd !== void 0) parameters2 = { ...parameters2, cwd: transport.cwd };
472
+ if (transport.stderr !== void 0) parameters2 = { ...parameters2, stderr: transport.stderr };
473
+ if (transport.maxBufferSize !== void 0) {
474
+ parameters2 = { ...parameters2, maxBufferSize: transport.maxBufferSize };
475
+ }
476
+ return new StdioClientTransport(parameters2);
477
+ }
478
+ const ssrfProtection = transport.ssrfProtection ?? "strict";
479
+ if (ssrfProtection !== "strict" && ssrfProtection !== "disabled") {
480
+ throw new TypeError("MCP Streamable HTTP ssrfProtection must be strict or disabled");
481
+ }
482
+ let parameters = {};
483
+ let url;
484
+ let transportFetch;
485
+ if (ssrfProtection === "strict") {
486
+ transportFetch = createSafeMcpFetch();
487
+ url = parseAndValidateMcpUrl(transport.url);
488
+ } else {
489
+ url = parseMcpHttpUrl(transport.url);
490
+ }
491
+ if (transport.headers !== void 0) {
492
+ const headers = copyMcpHeaders(transport.headers, transport.authProvider !== void 0);
493
+ const fetchRequest = transportFetch ?? defaultMcpFetch;
494
+ transportFetch = createMcpEndpointFetch(url, headers, fetchRequest);
495
+ }
496
+ if (transportFetch !== void 0) parameters = { ...parameters, fetch: transportFetch };
497
+ if (transport.authProvider !== void 0) {
498
+ parameters = { ...parameters, authProvider: transport.authProvider };
499
+ }
500
+ if (transport.reconnectionOptions !== void 0) {
501
+ parameters = { ...parameters, reconnectionOptions: transport.reconnectionOptions };
502
+ }
503
+ if (transport.sessionId !== void 0) {
504
+ parameters = { ...parameters, sessionId: transport.sessionId };
505
+ }
506
+ return new StreamableHTTPClientTransport(url, parameters);
507
+ }
508
+ function copyMcpHeaders(value, hasAuthProvider) {
509
+ if (typeof value !== "object" || value === null || Array.isArray(value)) {
510
+ throw new TypeError("MCP Streamable HTTP headers must be a plain object");
511
+ }
512
+ const prototype = Object.getPrototypeOf(value);
513
+ if (prototype !== Object.prototype && prototype !== null) {
514
+ throw new TypeError("MCP Streamable HTTP headers must be a plain object");
515
+ }
516
+ const headers = new Headers();
517
+ for (const [name, headerValue] of Object.entries(value)) {
518
+ if (typeof headerValue !== "string") {
519
+ throw new TypeError(`MCP Streamable HTTP header ${name} must be a string`);
520
+ }
521
+ const normalizedName = name.toLowerCase();
522
+ if (transportOwnedHttpHeaders.has(normalizedName) || normalizedName.startsWith("mcp-param-")) {
523
+ throw new TypeError(`MCP Streamable HTTP header ${name} is owned by the transport`);
524
+ }
525
+ if (hasAuthProvider && normalizedName === "authorization") {
526
+ throw new TypeError(
527
+ "MCP Streamable HTTP authorization header cannot be combined with authProvider"
528
+ );
529
+ }
530
+ headers.set(name, headerValue);
531
+ }
532
+ return headers;
533
+ }
534
+ function createMcpEndpointFetch(endpoint, configuredHeaders, fetchRequest) {
535
+ return (input, init) => {
536
+ const requestUrl = input instanceof Request ? new URL(input.url) : new URL(input);
537
+ if (requestUrl.href !== endpoint.href) return fetchRequest(input, init);
538
+ const requestHeaders = new Headers(
539
+ init?.headers ?? (input instanceof Request ? input.headers : void 0)
540
+ );
541
+ configuredHeaders.forEach((value, name) => {
542
+ requestHeaders.set(name, value);
543
+ });
544
+ return fetchRequest(input, { ...init, headers: requestHeaders, redirect: "error" });
545
+ };
546
+ }
547
+ var defaultMcpFetch = (input, init) => globalThis.fetch(input, init);
548
+ async function listAllTools(client, abortSignal) {
549
+ const result = await client.listTools(void 0, requestOptions(abortSignal));
550
+ return result.tools;
551
+ }
552
+ function assertUniqueToolNames(tools, serverName) {
553
+ const names = /* @__PURE__ */ new Set();
554
+ for (const tool of tools) {
555
+ if (names.has(tool.name)) {
556
+ throw new Error(`Duplicate MCP tool name "${tool.name}" from server "${serverName}"`);
557
+ }
558
+ names.add(tool.name);
559
+ }
560
+ }
561
+ function createSdkClient() {
562
+ const implementation = {
563
+ name: "@anvia/mcp",
564
+ version: getMcpClientVersion()
565
+ };
566
+ return new Client(implementation, {
567
+ versionNegotiation: { mode: { pin: modernMcpProtocolVersion } }
568
+ });
569
+ }
570
+ function getMcpClientVersion() {
571
+ if (mcpClientVersion === void 0) {
572
+ mcpClientVersion = readMcpPackageVersion();
573
+ }
574
+ return mcpClientVersion;
575
+ }
576
+ function requestOptions(signal) {
577
+ return signal === void 0 ? {} : { signal };
578
+ }
579
+ function closeResource(resource) {
580
+ resource.closePromise ??= resource.client.close();
581
+ return resource.closePromise;
582
+ }
583
+ function readMcpPackageVersion() {
584
+ try {
585
+ const packageJson = JSON.parse(
586
+ readFileSync(new URL("../package.json", import.meta.url), "utf8")
587
+ );
588
+ return typeof packageJson.version === "string" ? packageJson.version : "0.0.0";
589
+ } catch {
590
+ return "0.0.0";
591
+ }
592
+ }
593
+ function copyServerInfo(value) {
594
+ if (value === void 0) {
595
+ return void 0;
596
+ }
597
+ return deepFreeze2(structuredClone(value));
598
+ }
599
+ function copyJsonObject(value) {
600
+ if (value === void 0) {
601
+ return void 0;
602
+ }
603
+ return deepFreeze2(structuredClone(value));
604
+ }
605
+ function freezeServer(server) {
606
+ Object.freeze(server.tools);
607
+ return Object.freeze(server);
608
+ }
609
+ function deepFreeze2(value) {
610
+ if (typeof value !== "object" || value === null || Object.isFrozen(value)) {
611
+ return value;
612
+ }
613
+ for (const child of Object.values(value)) {
614
+ deepFreeze2(child);
615
+ }
616
+ return Object.freeze(value);
617
+ }
618
+
619
+ // src/client-group.ts
620
+ var McpClientGroup = class _McpClientGroup {
621
+ clients;
622
+ servers;
623
+ #closePromise;
624
+ constructor(clients, servers) {
625
+ this.clients = Object.freeze([...clients]);
626
+ this.servers = Object.freeze([...servers]);
627
+ }
628
+ static async connect(options) {
629
+ const clients = [...options.clients];
630
+ assertUniqueClientNames(clients);
631
+ const abortController = new AbortController();
632
+ const unlinkAbortSignal = linkAbortSignal(options.abortSignal, abortController);
633
+ let firstConnectionFailure;
634
+ let connectionFailed = false;
635
+ const connections = clients.map(
636
+ (client) => client.connect({ abortSignal: abortController.signal }).catch((error) => {
637
+ if (!connectionFailed) {
638
+ connectionFailed = true;
639
+ firstConnectionFailure = error;
640
+ abortController.abort(error);
641
+ }
642
+ throw error;
643
+ })
644
+ );
645
+ const settled = await Promise.allSettled(connections).finally(unlinkAbortSignal);
646
+ const firstFailure = settled.find(
647
+ (result) => result.status === "rejected"
648
+ );
649
+ if (firstFailure !== void 0) {
650
+ await rollbackSuccessfulClients(clients, settled);
651
+ throw connectionFailed ? firstConnectionFailure : firstFailure.reason;
652
+ }
653
+ const servers = settled.map((result) => result.value);
654
+ try {
655
+ assertUniqueServerAndToolNames(servers);
656
+ } catch (error) {
657
+ try {
658
+ await closeAll(clients);
659
+ } catch {
660
+ }
661
+ throw error;
662
+ }
663
+ return new _McpClientGroup(clients, servers);
664
+ }
665
+ close() {
666
+ this.#closePromise ??= closeAll(this.clients);
667
+ return this.#closePromise;
668
+ }
669
+ };
670
+ function assertUniqueClientNames(clients) {
671
+ const names = /* @__PURE__ */ new Set();
672
+ for (const client of clients) {
673
+ if (names.has(client.name)) {
674
+ throw new Error(`Duplicate MCP client name "${client.name}"`);
675
+ }
676
+ names.add(client.name);
677
+ }
678
+ }
679
+ function assertUniqueServerAndToolNames(servers) {
680
+ const serverNames = /* @__PURE__ */ new Set();
681
+ const toolNames = /* @__PURE__ */ new Map();
682
+ for (const server of servers) {
683
+ if (serverNames.has(server.name)) {
684
+ throw new Error(`Duplicate MCP server name "${server.name}"`);
685
+ }
686
+ serverNames.add(server.name);
687
+ for (const tool of server.tools) {
688
+ const existing = toolNames.get(tool.name);
689
+ if (existing !== void 0) {
690
+ throw new Error(
691
+ `Duplicate MCP tool name "${tool.name}" from servers "${existing}" and "${server.name}"`
692
+ );
693
+ }
694
+ toolNames.set(tool.name, server.name);
695
+ }
696
+ }
697
+ }
698
+ async function rollbackSuccessfulClients(clients, settled) {
699
+ const successful = clients.filter((_, index) => settled[index]?.status === "fulfilled");
700
+ try {
701
+ await closeAll(successful);
702
+ } catch {
703
+ }
704
+ }
705
+ async function closeAll(clients) {
706
+ const settled = await Promise.allSettled(clients.map((client) => client.close()));
707
+ const errors = settled.flatMap((result) => result.status === "rejected" ? [result.reason] : []);
708
+ if (errors.length > 0) {
709
+ throw new AggregateError(errors, "Failed to close one or more MCP clients");
710
+ }
711
+ }
712
+ export {
713
+ McpClient,
714
+ McpClientGroup,
715
+ isMcpTool
716
+ };
717
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/index.ts","../src/client.ts","../src/abort.ts","../src/tool.ts","../src/result.ts","../src/url-safety.ts","../src/client-group.ts"],"sourcesContent":["export { isMcpTool } from \"@anvia/core/mcp\";\nexport * from \"./client\";\nexport * from \"./client-group\";\nexport * from \"./types\";\n","import { readFileSync } from \"node:fs\";\nimport type { JsonObject } from \"@anvia/core/completion\";\nimport type { Transport } from \"@modelcontextprotocol/client\";\nimport { Client, StreamableHTTPClientTransport } from \"@modelcontextprotocol/client\";\nimport { StdioClientTransport } from \"@modelcontextprotocol/client/stdio\";\nimport { abortError, linkAbortSignal, throwIfAborted } from \"./abort\";\nimport { createMcpTool } from \"./tool\";\nimport type { McpClientOptions, McpConnectOptions, McpServer, McpServerInfo } from \"./types\";\nimport { createSafeMcpFetch, parseAndValidateMcpUrl, parseMcpHttpUrl } from \"./url-safety\";\n\nlet mcpClientVersion: string | undefined;\nconst modernMcpProtocolVersion = \"2026-07-28\";\n\ntype ClientResource = {\n readonly client: Client;\n closePromise?: Promise<void> | undefined;\n};\n\ntype McpFetch = NonNullable<\n NonNullable<ConstructorParameters<typeof StreamableHTTPClientTransport>[1]>[\"fetch\"]\n>;\n\nconst transportOwnedHttpHeaders = new Set([\n \"accept\",\n \"content-type\",\n \"last-event-id\",\n \"mcp-method\",\n \"mcp-name\",\n \"mcp-protocol-version\",\n \"mcp-session-id\",\n]);\n\nexport class McpClient {\n readonly name: string;\n\n readonly #options: McpClientOptions;\n #closed = false;\n #connectAbortController?: AbortController | undefined;\n #connecting?: Promise<McpServer> | undefined;\n #resource?: ClientResource | undefined;\n #server?: McpServer | undefined;\n\n constructor(options: McpClientOptions) {\n if (options.name.trim() === \"\") {\n throw new TypeError(\"MCP client name must not be empty\");\n }\n this.name = options.name;\n this.#options = options;\n }\n\n connect(options: McpConnectOptions = {}): Promise<McpServer> {\n if (this.#closed) {\n return Promise.reject(new Error(`MCP client \"${this.name}\" is closed`));\n }\n if (this.#server !== undefined) {\n return Promise.resolve(this.#server);\n }\n if (this.#connecting !== undefined) {\n return this.#connecting;\n }\n\n if (options.abortSignal?.aborted === true) {\n return Promise.reject(abortError(options.abortSignal.reason));\n }\n\n const abortController = new AbortController();\n const unlinkAbortSignal = linkAbortSignal(options.abortSignal, abortController);\n this.#connectAbortController = abortController;\n const connecting = this.#initialize(abortController.signal);\n this.#connecting = connecting;\n const clearConnecting = () => {\n unlinkAbortSignal();\n if (this.#connecting === connecting) {\n this.#connecting = undefined;\n }\n if (this.#connectAbortController === abortController) {\n this.#connectAbortController = undefined;\n }\n };\n void connecting.then(clearConnecting, clearConnecting);\n return connecting;\n }\n\n async close(): Promise<void> {\n this.#closed = true;\n this.#connectAbortController?.abort(\n abortError(new Error(`MCP client \"${this.name}\" was closed during connection`)),\n );\n\n const resource = this.#resource;\n if (resource !== undefined) {\n await closeResource(resource);\n }\n }\n\n async #initialize(abortSignal: AbortSignal): Promise<McpServer> {\n const client = createSdkClient();\n const resource: ClientResource = { client };\n this.#resource = resource;\n\n try {\n throwIfAborted(abortSignal);\n const transport = await createTransport(this.#options, { abortSignal });\n throwIfAborted(abortSignal);\n await client.connect(transport, requestOptions(abortSignal));\n throwIfAborted(abortSignal);\n const definitions = await listAllTools(client, abortSignal);\n throwIfAborted(abortSignal);\n const tools = definitions.map((definition) =>\n createMcpTool({\n definition,\n client,\n serverName: this.name,\n prefix: this.#options.tools?.prefix,\n }),\n );\n assertUniqueToolNames(tools, this.name);\n\n if (this.#closed) {\n throw new Error(`MCP client \"${this.name}\" was closed during connection`);\n }\n\n const serverInfo = copyServerInfo(client.getServerVersion());\n const capabilities = copyJsonObject(client.getServerCapabilities());\n const instructions = client.getInstructions();\n let registration: McpServer = {\n name: this.name,\n tools,\n };\n if (serverInfo !== undefined) registration = { ...registration, serverInfo };\n if (capabilities !== undefined) registration = { ...registration, capabilities };\n if (instructions !== undefined) registration = { ...registration, instructions };\n const server = freezeServer(registration);\n this.#server = server;\n return server;\n } catch (error) {\n try {\n await closeResource(resource);\n } catch {\n // Preserve the actionable connection or discovery failure.\n }\n if (this.#resource === resource) {\n this.#resource = undefined;\n }\n this.#server = undefined;\n throw error;\n }\n }\n}\n\nasync function createTransport(\n options: McpClientOptions,\n connectOptions: McpConnectOptions,\n): Promise<Transport> {\n const transport = options.transport;\n if (transport.type === \"custom\") {\n return transport.create({ abortSignal: connectOptions.abortSignal });\n }\n if (transport.type === \"stdio\") {\n let parameters: ConstructorParameters<typeof StdioClientTransport>[0] = {\n command: transport.command,\n };\n if (transport.args !== undefined) parameters = { ...parameters, args: transport.args };\n if (transport.env !== undefined) parameters = { ...parameters, env: transport.env };\n if (transport.cwd !== undefined) parameters = { ...parameters, cwd: transport.cwd };\n if (transport.stderr !== undefined) parameters = { ...parameters, stderr: transport.stderr };\n if (transport.maxBufferSize !== undefined) {\n parameters = { ...parameters, maxBufferSize: transport.maxBufferSize };\n }\n return new StdioClientTransport(parameters);\n }\n\n const ssrfProtection = transport.ssrfProtection ?? \"strict\";\n if (ssrfProtection !== \"strict\" && ssrfProtection !== \"disabled\") {\n throw new TypeError(\"MCP Streamable HTTP ssrfProtection must be strict or disabled\");\n }\n let parameters: ConstructorParameters<typeof StreamableHTTPClientTransport>[1] = {};\n let url: URL;\n let transportFetch: McpFetch | undefined;\n if (ssrfProtection === \"strict\") {\n transportFetch = createSafeMcpFetch();\n url = parseAndValidateMcpUrl(transport.url);\n } else {\n url = parseMcpHttpUrl(transport.url);\n }\n if (transport.headers !== undefined) {\n const headers = copyMcpHeaders(transport.headers, transport.authProvider !== undefined);\n const fetchRequest = transportFetch ?? defaultMcpFetch;\n transportFetch = createMcpEndpointFetch(url, headers, fetchRequest);\n }\n if (transportFetch !== undefined) parameters = { ...parameters, fetch: transportFetch };\n if (transport.authProvider !== undefined) {\n parameters = { ...parameters, authProvider: transport.authProvider };\n }\n if (transport.reconnectionOptions !== undefined) {\n parameters = { ...parameters, reconnectionOptions: transport.reconnectionOptions };\n }\n if (transport.sessionId !== undefined) {\n parameters = { ...parameters, sessionId: transport.sessionId };\n }\n return new StreamableHTTPClientTransport(url, parameters);\n}\n\nfunction copyMcpHeaders(\n value: Readonly<Record<string, string>>,\n hasAuthProvider: boolean,\n): Headers {\n if (typeof value !== \"object\" || value === null || Array.isArray(value)) {\n throw new TypeError(\"MCP Streamable HTTP headers must be a plain object\");\n }\n const prototype = Object.getPrototypeOf(value);\n if (prototype !== Object.prototype && prototype !== null) {\n throw new TypeError(\"MCP Streamable HTTP headers must be a plain object\");\n }\n const headers = new Headers();\n for (const [name, headerValue] of Object.entries(value)) {\n if (typeof headerValue !== \"string\") {\n throw new TypeError(`MCP Streamable HTTP header ${name} must be a string`);\n }\n const normalizedName = name.toLowerCase();\n if (transportOwnedHttpHeaders.has(normalizedName) || normalizedName.startsWith(\"mcp-param-\")) {\n throw new TypeError(`MCP Streamable HTTP header ${name} is owned by the transport`);\n }\n if (hasAuthProvider && normalizedName === \"authorization\") {\n throw new TypeError(\n \"MCP Streamable HTTP authorization header cannot be combined with authProvider\",\n );\n }\n headers.set(name, headerValue);\n }\n return headers;\n}\n\nfunction createMcpEndpointFetch(\n endpoint: URL,\n configuredHeaders: Headers,\n fetchRequest: McpFetch,\n): McpFetch {\n return (input, init) => {\n const requestUrl = input instanceof Request ? new URL(input.url) : new URL(input);\n if (requestUrl.href !== endpoint.href) return fetchRequest(input, init);\n\n const requestHeaders = new Headers(\n init?.headers ?? (input instanceof Request ? input.headers : undefined),\n );\n configuredHeaders.forEach((value, name) => {\n requestHeaders.set(name, value);\n });\n return fetchRequest(input, { ...init, headers: requestHeaders, redirect: \"error\" });\n };\n}\n\nconst defaultMcpFetch: McpFetch = (input, init) => globalThis.fetch(input, init);\n\nasync function listAllTools(\n client: Client,\n abortSignal?: AbortSignal | undefined,\n): Promise<Awaited<ReturnType<Client[\"listTools\"]>>[\"tools\"]> {\n const result = await client.listTools(undefined, requestOptions(abortSignal));\n return result.tools;\n}\n\nfunction assertUniqueToolNames(tools: readonly { name: string }[], serverName: string): void {\n const names = new Set<string>();\n for (const tool of tools) {\n if (names.has(tool.name)) {\n throw new Error(`Duplicate MCP tool name \"${tool.name}\" from server \"${serverName}\"`);\n }\n names.add(tool.name);\n }\n}\n\nfunction createSdkClient(): Client {\n const implementation = {\n name: \"@anvia/mcp\",\n version: getMcpClientVersion(),\n };\n return new Client(implementation, {\n versionNegotiation: { mode: { pin: modernMcpProtocolVersion } },\n });\n}\n\nfunction getMcpClientVersion(): string {\n if (mcpClientVersion === undefined) {\n mcpClientVersion = readMcpPackageVersion();\n }\n return mcpClientVersion;\n}\n\nfunction requestOptions(signal?: AbortSignal | undefined): { signal?: AbortSignal } {\n return signal === undefined ? {} : { signal };\n}\n\nfunction closeResource(resource: ClientResource): Promise<void> {\n resource.closePromise ??= resource.client.close();\n return resource.closePromise;\n}\n\nfunction readMcpPackageVersion(): string {\n try {\n const packageJson = JSON.parse(\n readFileSync(new URL(\"../package.json\", import.meta.url), \"utf8\"),\n ) as { version?: unknown };\n return typeof packageJson.version === \"string\" ? packageJson.version : \"0.0.0\";\n } catch {\n return \"0.0.0\";\n }\n}\n\nfunction copyServerInfo(value: ReturnType<Client[\"getServerVersion\"]>): McpServerInfo | undefined {\n if (value === undefined) {\n return undefined;\n }\n return deepFreeze(structuredClone(value)) as McpServerInfo;\n}\n\nfunction copyJsonObject(value: unknown): JsonObject | undefined {\n if (value === undefined) {\n return undefined;\n }\n return deepFreeze(structuredClone(value)) as JsonObject;\n}\n\nfunction freezeServer(server: McpServer): McpServer {\n Object.freeze(server.tools);\n return Object.freeze(server);\n}\n\nfunction deepFreeze<T>(value: T): T {\n if (typeof value !== \"object\" || value === null || Object.isFrozen(value)) {\n return value;\n }\n for (const child of Object.values(value)) {\n deepFreeze(child);\n }\n return Object.freeze(value);\n}\n","export function linkAbortSignal(\n source: AbortSignal | undefined,\n target: AbortController,\n): () => void {\n if (source === undefined) {\n return () => undefined;\n }\n if (source.aborted) {\n target.abort(source.reason);\n return () => undefined;\n }\n\n const onAbort = () => target.abort(source.reason);\n source.addEventListener(\"abort\", onAbort, { once: true });\n return () => source.removeEventListener(\"abort\", onAbort);\n}\n\nexport function throwIfAborted(signal: AbortSignal | undefined): void {\n if (signal?.aborted === true) {\n throw abortError(signal.reason);\n }\n}\n\nexport function abortError(reason?: unknown): Error {\n if (isAbortError(reason)) {\n return reason;\n }\n\n const error = new Error(\n \"The operation was aborted.\",\n reason === undefined ? undefined : { cause: reason },\n );\n error.name = \"AbortError\";\n return error;\n}\n\nfunction isAbortError(error: unknown): error is Error {\n const seen = new Set<object>();\n let current = error;\n while (typeof current === \"object\" && current !== null && !seen.has(current)) {\n seen.add(current);\n if (\"name\" in current && current.name === \"AbortError\") {\n return true;\n }\n current = \"cause\" in current ? current.cause : undefined;\n }\n return false;\n}\n","import type { JsonObject, ToolDefinition } from \"@anvia/core/completion\";\nimport type { McpTool } from \"@anvia/core/mcp\";\nimport { ToolOutput } from \"@anvia/core/tool\";\nimport type { Client } from \"@modelcontextprotocol/client\";\nimport { createCallToolParams, mapMcpToolResult, parseMcpToolArguments } from \"./result\";\n\ntype SdkMcpToolDefinition = Awaited<ReturnType<Client[\"listTools\"]>>[\"tools\"][number];\n\nexport function createMcpTool(options: {\n definition: SdkMcpToolDefinition;\n client: Client;\n serverName: string;\n prefix?: string | undefined;\n}): McpTool {\n const { definition, client, serverName, prefix = \"\" } = options;\n const exposedName = `${prefix}${definition.name}`;\n const provenance = Object.freeze({\n serverName,\n remoteName: definition.name,\n });\n const toolDefinition = Object.freeze<ToolDefinition>({\n name: exposedName,\n description: definition.description ?? \"\",\n parameters: deepFreeze(structuredClone(definition.inputSchema)) as unknown as JsonObject,\n });\n const tool: McpTool = {\n name: exposedName,\n mcp: provenance,\n definition(): ToolDefinition {\n return toolDefinition;\n },\n parseInput(args) {\n return parseMcpToolArguments(args);\n },\n async call(args, context) {\n const result = await client.callTool(\n createCallToolParams(definition.name, args),\n context?.abortSignal === undefined ? {} : { signal: context.abortSignal },\n );\n return ToolOutput.content(mapMcpToolResult(result));\n },\n };\n return Object.freeze(tool);\n}\n\nfunction deepFreeze<T>(value: T): T {\n if (typeof value !== \"object\" || value === null || Object.isFrozen(value)) {\n return value;\n }\n for (const child of Object.values(value)) {\n deepFreeze(child);\n }\n return Object.freeze(value);\n}\n","import { isJsonValue, type JsonObject, type ToolResultContentPart } from \"@anvia/core/completion\";\n\ntype McpResultContent =\n | { type: \"text\"; text: string }\n | { type: \"image\"; data: string; mimeType: string }\n | { type: \"audio\"; data: string; mimeType: string }\n | {\n type: \"resource\";\n resource:\n | { uri: string; text: string; mimeType?: string | undefined }\n | { uri: string; blob: string; mimeType?: string | undefined };\n }\n | {\n type: \"resource_link\";\n uri: string;\n name: string;\n mimeType?: string | undefined;\n };\n\nexport type McpToolCallResult =\n | {\n content: McpResultContent[];\n structuredContent?: unknown;\n isError?: boolean | undefined;\n }\n | {\n toolResult: unknown;\n };\n\nexport function createCallToolParams(\n name: string,\n args: unknown,\n): { name: string; arguments?: Record<string, unknown> } {\n if (args === undefined) {\n return { name };\n }\n\n return { name, arguments: parseMcpToolArguments(args) };\n}\n\nexport function parseMcpToolArguments(args: unknown): JsonObject {\n if (!isMcpJsonObject(args)) {\n throw new TypeError(\"MCP tool arguments must be a strict JSON object\");\n }\n return args;\n}\n\nfunction isMcpJsonObject(value: unknown): value is JsonObject {\n return typeof value === \"object\" && value !== null && !Array.isArray(value) && isJsonValue(value);\n}\n\nexport function mapMcpToolResult(result: McpToolCallResult): readonly ToolResultContentPart[] {\n if (\"toolResult\" in result) {\n return [{ type: \"text\", text: serializeMcpValue(result.toolResult) }];\n }\n\n if (result.isError === true) {\n throw new Error(mcpErrorMessage(result.content));\n }\n\n const content = result.content.map(mapMcpContent);\n if (content.length === 0 && result.structuredContent !== undefined) {\n content.push({ type: \"text\", text: serializeMcpValue(result.structuredContent) });\n }\n return content;\n}\n\nfunction mcpErrorMessage(content: McpResultContent[]): string {\n const text = content\n .map((item) => (item.type === \"text\" ? item.text : undefined))\n .filter((item): item is string => item !== undefined)\n .join(\"\\n\");\n\n return text === \"\" ? \"MCP tool returned an error\" : text;\n}\n\nfunction mapMcpContent(content: McpResultContent): ToolResultContentPart {\n if (content.type === \"text\") {\n return { type: \"text\", text: content.text };\n }\n\n if (content.type === \"image\") {\n return {\n type: \"file\",\n data: { type: \"data\", data: content.data },\n mediaType: content.mimeType,\n };\n }\n\n if (content.type === \"resource\") {\n return { type: \"text\", text: serializeResource(content.resource) };\n }\n\n if (content.type === \"audio\") {\n throw new Error(`Unsupported MCP tool result content type: audio (${content.mimeType})`);\n }\n\n throw new Error(`Unsupported MCP tool result content type: resource_link (${content.uri})`);\n}\n\nfunction serializeResource(\n resource:\n | { uri: string; text: string; mimeType?: string | undefined }\n | { uri: string; blob: string; mimeType?: string | undefined },\n): string {\n const mediaType =\n resource.mimeType ?? (\"text\" in resource ? \"text/plain\" : \"application/octet-stream\");\n const encoding = \"text\" in resource ? \"text\" : \"base64\";\n const data = \"text\" in resource ? resource.text : resource.blob;\n return `MCP resource (${resource.uri}; ${mediaType}; ${encoding})\\n${data}`;\n}\n\nfunction serializeMcpValue(value: unknown): string {\n if (typeof value === \"string\") {\n return value;\n }\n\n if (!isJsonValue(value)) {\n throw new TypeError(\"MCP tool results must be strict JSON values.\");\n }\n\n let serialized: string | undefined;\n try {\n serialized = JSON.stringify(value);\n } catch (error) {\n throw new TypeError(\"MCP tool results must be strict JSON values.\", { cause: error });\n }\n if (serialized === undefined) {\n throw new TypeError(\"MCP tool results must be strict JSON values.\");\n }\n return serialized;\n}\n","import type { LookupAddress } from \"node:dns\";\nimport { lookup } from \"node:dns/promises\";\nimport type { LookupFunction } from \"node:net\";\nimport { BlockList, isIP } from \"node:net\";\nimport type { StreamableHTTPClientTransportOptions } from \"@modelcontextprotocol/client\";\nimport { Agent, Pool, fetch as undiciFetch } from \"undici\";\n\ntype FetchLike = NonNullable<StreamableHTTPClientTransportOptions[\"fetch\"]>;\n\nexport type McpAddressResolver = (hostname: string) => Promise<LookupAddress[]>;\n\nconst blockedIpv4Addresses = new BlockList();\nconst blockedIpv6Addresses = new BlockList();\n\nfor (const [network, prefix] of [\n [\"0.0.0.0\", 8],\n [\"10.0.0.0\", 8],\n [\"100.64.0.0\", 10],\n [\"127.0.0.0\", 8],\n [\"169.254.0.0\", 16],\n [\"172.16.0.0\", 12],\n [\"192.0.0.0\", 24],\n [\"192.0.2.0\", 24],\n [\"192.88.99.0\", 24],\n [\"192.168.0.0\", 16],\n [\"198.18.0.0\", 15],\n [\"198.51.100.0\", 24],\n [\"203.0.113.0\", 24],\n [\"224.0.0.0\", 4],\n [\"240.0.0.0\", 4],\n] as const) {\n blockedIpv4Addresses.addSubnet(network, prefix, \"ipv4\");\n}\n\nfor (const [network, prefix] of [\n [\"::\", 96],\n [\"::ffff:0:0\", 96],\n [\"64:ff9b::\", 96],\n [\"64:ff9b:1::\", 48],\n [\"100::\", 64],\n [\"2001::\", 32],\n [\"2001:2::\", 48],\n [\"2001:10::\", 28],\n [\"2001:20::\", 28],\n [\"2001:db8::\", 32],\n [\"2002::\", 16],\n [\"fc00::\", 7],\n [\"fe80::\", 10],\n [\"fec0::\", 10],\n [\"ff00::\", 8],\n] as const) {\n blockedIpv6Addresses.addSubnet(network, prefix, \"ipv6\");\n}\n\nconst defaultAddressResolver: McpAddressResolver = (hostname) =>\n lookup(hostname, { all: true, verbatim: true });\n\nexport function parseAndValidateMcpUrl(url: string | URL): URL {\n const parsed = parseMcpHttpUrl(url);\n validateMcpHostname(parsed.hostname);\n return parsed;\n}\n\nexport function parseMcpHttpUrl(url: string | URL): URL {\n let parsed: URL;\n try {\n parsed = new URL(url);\n } catch {\n throw new Error(`Invalid MCP URL: ${url}`);\n }\n\n if (parsed.protocol !== \"http:\" && parsed.protocol !== \"https:\") {\n throw new Error(`MCP URL blocked: only HTTP(S) URLs are allowed (${parsed.protocol})`);\n }\n\n return parsed;\n}\n\nexport async function resolveAndValidateMcpHostname(\n hostname: string,\n resolveAddresses: McpAddressResolver = defaultAddressResolver,\n): Promise<LookupAddress[]> {\n const normalizedHostname = normalizeHostname(hostname);\n validateMcpHostname(normalizedHostname);\n\n const family = isIP(normalizedHostname);\n if (family !== 0) {\n return [{ address: normalizedHostname, family }];\n }\n\n let addresses: LookupAddress[];\n try {\n addresses = await resolveAddresses(normalizedHostname);\n } catch (cause) {\n throw new Error(`Unable to resolve MCP URL hostname (${normalizedHostname})`, { cause });\n }\n\n if (addresses.length === 0) {\n throw new Error(`Unable to resolve MCP URL hostname (${normalizedHostname})`);\n }\n\n for (const { address } of addresses) {\n validateMcpHostname(address);\n }\n\n return addresses;\n}\n\nexport function createSafeMcpLookup(\n resolveAddresses: McpAddressResolver = defaultAddressResolver,\n): LookupFunction {\n return (hostname, options, callback) => {\n void resolveAndValidateMcpHostname(hostname, resolveAddresses).then(\n (addresses) => {\n const requestedFamily = normalizeRequestedFamily(options.family);\n const matchingAddresses =\n requestedFamily === 0\n ? addresses\n : addresses.filter(({ family }) => family === requestedFamily);\n\n if (matchingAddresses.length === 0) {\n const error = new Error(`No matching address family for MCP URL (${hostname})`);\n Object.assign(error, { code: \"EAI_ADDRFAMILY\" });\n callback(error, []);\n return;\n }\n\n if (options.all) {\n callback(null, matchingAddresses);\n return;\n }\n\n const address = matchingAddresses[0];\n if (!address) {\n callback(new Error(`Unable to resolve MCP URL hostname (${hostname})`), []);\n return;\n }\n callback(null, address.address, address.family);\n },\n (cause: unknown) => {\n callback(asError(cause), []);\n },\n );\n };\n}\n\nexport function createSafeMcpFetch(): FetchLike {\n return (url, init) => {\n parseAndValidateMcpUrl(url);\n return undiciFetch(url as Parameters<typeof undiciFetch>[0], {\n ...(init as Parameters<typeof undiciFetch>[1]),\n dispatcher: safeMcpDispatcher,\n }) as unknown as ReturnType<FetchLike>;\n };\n}\n\nfunction validateMcpHostname(hostname: string): void {\n const normalizedHostname = normalizeHostname(hostname);\n\n if (normalizedHostname === \"localhost\" || normalizedHostname.endsWith(\".localhost\")) {\n throw new Error(`MCP URL blocked: localhost not allowed (${normalizedHostname})`);\n }\n\n const family = isIP(normalizedHostname);\n if (family === 0) {\n return;\n }\n\n if (\n (family === 4 && normalizedHostname.startsWith(\"127.\")) ||\n (family === 6 && normalizedHostname === \"::1\")\n ) {\n throw new Error(`MCP URL blocked: localhost not allowed (${normalizedHostname})`);\n }\n\n if (normalizedHostname === \"169.254.169.254\" || normalizedHostname === \"fd00:ec2::254\") {\n throw new Error(`MCP URL blocked: cloud metadata endpoint not allowed (${normalizedHostname})`);\n }\n\n if (\n (family === 4 && blockedIpv4Addresses.check(normalizedHostname, \"ipv4\")) ||\n (family === 6 && blockedIpv6Addresses.check(normalizedHostname, \"ipv6\"))\n ) {\n const range = family === 4 ? \"IP\" : \"IPv6\";\n throw new Error(`MCP URL blocked: private ${range} range not allowed (${normalizedHostname})`);\n }\n}\n\nfunction normalizeHostname(hostname: string): string {\n const withoutBrackets =\n hostname.startsWith(\"[\") && hostname.endsWith(\"]\") ? hostname.slice(1, -1) : hostname;\n return withoutBrackets.toLowerCase().replace(/\\.+$/, \"\");\n}\n\nfunction normalizeRequestedFamily(family: number | string | undefined): 0 | 4 | 6 {\n if (family === 4 || family === \"IPv4\") {\n return 4;\n }\n if (family === 6 || family === \"IPv6\") {\n return 6;\n }\n return 0;\n}\n\nfunction asError(cause: unknown): Error {\n return cause instanceof Error ? cause : new Error(String(cause));\n}\n\nconst safeMcpDispatcher = new Agent({\n autoSelectFamily: true,\n connect: {\n lookup: createSafeMcpLookup(),\n },\n factory(origin, options) {\n parseAndValidateMcpUrl(origin);\n return new Pool(origin, options as Pool.Options);\n },\n});\n","import { linkAbortSignal } from \"./abort\";\nimport type { McpClient } from \"./client\";\nimport type { McpClientGroupConnectOptions, McpServer } from \"./types\";\n\nexport class McpClientGroup {\n readonly clients: readonly McpClient[];\n readonly servers: readonly McpServer[];\n\n #closePromise?: Promise<void> | undefined;\n\n private constructor(clients: readonly McpClient[], servers: readonly McpServer[]) {\n this.clients = Object.freeze([...clients]);\n this.servers = Object.freeze([...servers]);\n }\n\n static async connect(options: McpClientGroupConnectOptions): Promise<McpClientGroup> {\n const clients = [...options.clients];\n assertUniqueClientNames(clients);\n\n const abortController = new AbortController();\n const unlinkAbortSignal = linkAbortSignal(options.abortSignal, abortController);\n let firstConnectionFailure: unknown;\n let connectionFailed = false;\n const connections = clients.map((client) =>\n client.connect({ abortSignal: abortController.signal }).catch((error: unknown) => {\n if (!connectionFailed) {\n connectionFailed = true;\n firstConnectionFailure = error;\n abortController.abort(error);\n }\n throw error;\n }),\n );\n const settled = await Promise.allSettled(connections).finally(unlinkAbortSignal);\n const firstFailure = settled.find(\n (result): result is PromiseRejectedResult => result.status === \"rejected\",\n );\n if (firstFailure !== undefined) {\n await rollbackSuccessfulClients(clients, settled);\n throw connectionFailed ? firstConnectionFailure : firstFailure.reason;\n }\n\n const servers = settled.map((result) => (result as PromiseFulfilledResult<McpServer>).value);\n try {\n assertUniqueServerAndToolNames(servers);\n } catch (error) {\n try {\n await closeAll(clients);\n } catch {\n // Preserve the registration validation failure that caused rollback.\n }\n throw error;\n }\n\n return new McpClientGroup(clients, servers);\n }\n\n close(): Promise<void> {\n this.#closePromise ??= closeAll(this.clients);\n return this.#closePromise;\n }\n}\n\nfunction assertUniqueClientNames(clients: readonly McpClient[]): void {\n const names = new Set<string>();\n for (const client of clients) {\n if (names.has(client.name)) {\n throw new Error(`Duplicate MCP client name \"${client.name}\"`);\n }\n names.add(client.name);\n }\n}\n\nfunction assertUniqueServerAndToolNames(servers: readonly McpServer[]): void {\n const serverNames = new Set<string>();\n const toolNames = new Map<string, string>();\n for (const server of servers) {\n if (serverNames.has(server.name)) {\n throw new Error(`Duplicate MCP server name \"${server.name}\"`);\n }\n serverNames.add(server.name);\n\n for (const tool of server.tools) {\n const existing = toolNames.get(tool.name);\n if (existing !== undefined) {\n throw new Error(\n `Duplicate MCP tool name \"${tool.name}\" from servers \"${existing}\" and \"${server.name}\"`,\n );\n }\n toolNames.set(tool.name, server.name);\n }\n }\n}\n\nasync function rollbackSuccessfulClients(\n clients: readonly McpClient[],\n settled: readonly PromiseSettledResult<McpServer>[],\n): Promise<void> {\n const successful = clients.filter((_, index) => settled[index]?.status === \"fulfilled\");\n try {\n await closeAll(successful);\n } catch {\n // Preserve the connection failure that caused rollback.\n }\n}\n\nasync function closeAll(clients: readonly McpClient[]): Promise<void> {\n const settled = await Promise.allSettled(clients.map((client) => client.close()));\n const errors = settled.flatMap((result) => (result.status === \"rejected\" ? [result.reason] : []));\n if (errors.length > 0) {\n throw new AggregateError(errors, \"Failed to close one or more MCP clients\");\n }\n}\n"],"mappings":"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","names":["parameters","deepFreeze"]}
package/package.json ADDED
@@ -0,0 +1,52 @@
1
+ {
2
+ "name": "@anvia/mcp",
3
+ "version": "1.0.0-rc.10",
4
+ "description": "Model Context Protocol client integration for Anvia.",
5
+ "author": "anvia",
6
+ "maintainer": "Indra Zulfi",
7
+ "license": "MIT",
8
+ "repository": {
9
+ "type": "git",
10
+ "url": "https://github.com/anvia-hq/anvia",
11
+ "directory": "packages/mcp"
12
+ },
13
+ "files": [
14
+ "dist"
15
+ ],
16
+ "publishConfig": {
17
+ "access": "public"
18
+ },
19
+ "type": "module",
20
+ "main": "./dist/index.js",
21
+ "types": "./dist/index.d.ts",
22
+ "exports": {
23
+ ".": {
24
+ "types": "./dist/index.d.ts",
25
+ "import": "./dist/index.js"
26
+ }
27
+ },
28
+ "scripts": {
29
+ "prebuild": "test -f ../core/dist/index.d.ts || pnpm --filter @anvia/core build",
30
+ "build": "tsup src/index.ts --format esm --dts --sourcemap --clean",
31
+ "test": "vitest run",
32
+ "pretypecheck": "test -f ../core/dist/index.d.ts || pnpm --filter @anvia/core build",
33
+ "typecheck": "tsc --noEmit"
34
+ },
35
+ "dependencies": {
36
+ "@modelcontextprotocol/client": "^2.0.0",
37
+ "undici": "^8.10.0"
38
+ },
39
+ "devDependencies": {
40
+ "@anvia/core": "workspace:*",
41
+ "@types/node": "^24.9.1",
42
+ "tsup": "^8.5.0",
43
+ "typescript": "^5.9.3",
44
+ "vitest": "^4.0.8"
45
+ },
46
+ "peerDependencies": {
47
+ "@anvia/core": "workspace:*"
48
+ },
49
+ "engines": {
50
+ "node": ">=20"
51
+ }
52
+ }