@mcp-b/webmcp-local-relay 5.1.0 → 6.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,3 +1,4 @@
1
+ import { z } from "zod/v4";
1
2
  import { randomUUID } from "node:crypto";
2
3
  import { EventEmitter } from "node:events";
3
4
  import WebSocket, { WebSocketServer } from "ws";
@@ -5,16 +6,23 @@ import { mkdir, readFile, writeFile } from "node:fs/promises";
5
6
  import { homedir } from "node:os";
6
7
  import { dirname, join } from "node:path";
7
8
  import { CallToolRequestParamsSchema, CallToolResultSchema, ToolAnnotationsSchema, ToolSchema } from "@modelcontextprotocol/core";
8
- import { z } from "zod/v4";
9
9
  import { parseArgs } from "node:util";
10
10
  import { execFile } from "node:child_process";
11
11
  import { McpServer, fromJsonSchema } from "@modelcontextprotocol/server";
12
12
  import { StdioServerTransport } from "@modelcontextprotocol/server/stdio";
13
13
 
14
14
  //#region src/portStrategy.ts
15
+ function isTcpAddress(address) {
16
+ return address !== null && typeof address !== "string";
17
+ }
15
18
  const DEFAULT_RELAY_PORT = 9333;
16
19
  const DEFAULT_RELAY_PORT_RANGE_END = 9348;
17
20
  const RELAY_PORT_CACHE_MAX_AGE_MS = 1440 * 60 * 1e3;
21
+ const PersistedRelayPortSchema = z.object({
22
+ port: z.number().int().min(1).max(65535),
23
+ host: z.string().min(1),
24
+ updatedAt: z.string()
25
+ });
18
26
  function defaultRelayPortPersistPath() {
19
27
  return join(homedir(), ".webmcp", "relay-port.json");
20
28
  }
@@ -27,17 +35,13 @@ async function persistPort(port, path = defaultRelayPortPersistPath(), host = "1
27
35
  await mkdir(dirname(path), { recursive: true });
28
36
  await writeFile(path, `${JSON.stringify(payload, null, 2)}\n`, "utf8");
29
37
  }
30
- async function readPersistedPort(path = defaultRelayPortPersistPath(), options = {}) {
38
+ async function readPersistedPort(path, expectedHost) {
31
39
  try {
32
40
  const raw = await readFile(path, "utf8");
33
- const parsed = JSON.parse(raw);
34
- if (typeof parsed.port !== "number" || !Number.isInteger(parsed.port) || parsed.port < 1 || parsed.port > 65535) return null;
35
- if (typeof parsed.host !== "string" || parsed.host.length === 0) return null;
36
- if (options.expectedHost && parsed.host !== options.expectedHost) return null;
37
- const maxAgeMs = options.maxAgeMs ?? RELAY_PORT_CACHE_MAX_AGE_MS;
38
- const now = options.now ?? Date.now();
39
- const updatedAtMs = typeof parsed.updatedAt === "string" ? Date.parse(parsed.updatedAt) : NaN;
40
- if (!Number.isFinite(updatedAtMs) || now - updatedAtMs > maxAgeMs) return null;
41
+ const parsed = PersistedRelayPortSchema.parse(JSON.parse(raw));
42
+ if (expectedHost && parsed.host !== expectedHost) return null;
43
+ const updatedAtMs = Date.parse(parsed.updatedAt);
44
+ if (!Number.isFinite(updatedAtMs) || Date.now() - updatedAtMs > RELAY_PORT_CACHE_MAX_AGE_MS) return null;
41
45
  return parsed.port;
42
46
  } catch {
43
47
  return null;
@@ -50,7 +54,7 @@ async function buildPortCandidates(options) {
50
54
  wasFixed: true,
51
55
  fromCache: false
52
56
  }];
53
- const cachedPort = await readPersistedPort(persistPath, { expectedHost: host });
57
+ const cachedPort = await readPersistedPort(persistPath, host);
54
58
  const seen = /* @__PURE__ */ new Set();
55
59
  const candidates = [];
56
60
  const pushCandidate = (port, fromCache) => {
@@ -404,11 +408,10 @@ const RelayDescriptorSchema = z.object({
404
408
  /**
405
409
  * Schema for server hello messages sent immediately after WebSocket connect.
406
410
  */
407
- const ServerHelloMessageSchema = z.object({
411
+ const ServerHelloMessageSchema = RelayDescriptorSchema.extend({
408
412
  type: z.literal("server-hello"),
409
413
  service: z.literal("webmcp-local-relay"),
410
- version: z.literal(1),
411
- ...RelayDescriptorSchema.shape
414
+ version: z.literal(1)
412
415
  });
413
416
  /**
414
417
  * Schema for acceptance of a browser source hello message.
@@ -507,6 +510,8 @@ const RELAY_INTERNAL_PROTOCOL = "webmcp-relay.v1";
507
510
  const RELAY_SERVER_MESSAGE_TIMEOUT_MS = 750;
508
511
  const HEARTBEAT_INTERVAL_MS = 15e3;
509
512
  const HEARTBEAT_DEAD_THRESHOLD_MS = 25e3;
513
+ const RawMessageTypeSchema = z.object({ type: z.unknown().optional() });
514
+ const RelayProtocolTypeSchema = z.string().startsWith("relay/");
510
515
  const SUPPORTED_SUBPROTOCOLS = new Set([
511
516
  RELAY_BROWSER_PROTOCOL,
512
517
  RELAY_DISCOVERY_PROTOCOL,
@@ -644,13 +649,14 @@ var RelayBridgeServer = class extends EventEmitter {
644
649
  await this.startAsServer(0);
645
650
  return;
646
651
  }
647
- const candidates = await buildPortCandidates({
652
+ const strategyOptions = {
648
653
  defaultPort: this.preferredPort,
649
- ...this.portExplicitlySet ? { fixedPort: this.preferredPort } : {},
650
654
  host: this.host,
651
655
  persistPath: this.persistPath,
652
656
  rangeEnd: this.portRangeEnd
653
- });
657
+ };
658
+ if (this.portExplicitlySet) strategyOptions.fixedPort = this.preferredPort;
659
+ const candidates = await buildPortCandidates(strategyOptions);
654
660
  for (const candidate of candidates) try {
655
661
  await this.startAsServer(candidate.port);
656
662
  await this.persistSelectedPort();
@@ -666,8 +672,8 @@ var RelayBridgeServer = class extends EventEmitter {
666
672
  }
667
673
  throw new Error(`No compatible relay port was available in the range ${this.preferredPort}-${this.portRangeEnd}.`);
668
674
  }
669
- isAddressInUseError(error) {
670
- return error instanceof Error && ("code" in error ? error.code === "EADDRINUSE" : error.message.includes("EADDRINUSE"));
675
+ isAddressInUseError(cause) {
676
+ return cause instanceof Error && ("code" in cause ? cause.code === "EADDRINUSE" : cause.message.includes("EADDRINUSE"));
671
677
  }
672
678
  async persistSelectedPort() {
673
679
  try {
@@ -825,7 +831,7 @@ var RelayBridgeServer = class extends EventEmitter {
825
831
  this.wss = wss;
826
832
  this._mode = "server";
827
833
  const address = wss.address();
828
- if (address && typeof address !== "string") this.desiredPort = address.port;
834
+ if (isTcpAddress(address)) this.desiredPort = address.port;
829
835
  this.on("stateChanged", this.onStateChangedPushRelay);
830
836
  }
831
837
  buildServerHello() {
@@ -848,11 +854,10 @@ var RelayBridgeServer = class extends EventEmitter {
848
854
  * for a `relay/result` that never arrives.
849
855
  */
850
856
  async invokeToolLocally(toolName, args, options) {
851
- const resolved = this.registry.resolveInvocation({
852
- toolName,
853
- ...options.sourceId === void 0 ? {} : { sourceId: options.sourceId },
854
- ...options.requestTabId === void 0 ? {} : { requestTabId: options.requestTabId }
855
- });
857
+ const invocation = { toolName };
858
+ if (options.sourceId !== void 0) invocation.sourceId = options.sourceId;
859
+ if (options.requestTabId !== void 0) invocation.requestTabId = options.requestTabId;
860
+ const resolved = this.registry.resolveInvocation(invocation);
856
861
  if (!resolved) throw new Error(`No active browser source provides tool "${toolName}"`);
857
862
  const socket = this.socketByConnectionId.get(resolved.connectionId);
858
863
  if (!socket || socket.readyState !== WebSocket.OPEN) throw new Error(`Tool source ${resolved.connectionId} disconnected before invocation of "${toolName}"`);
@@ -894,7 +899,7 @@ var RelayBridgeServer = class extends EventEmitter {
894
899
  process.stderr.write(`[webmcp-local-relay] warn: invalid JSON from connection ${connectionId} (${err instanceof Error ? err.message : "parse error"}): ${preview}\n`);
895
900
  return;
896
901
  }
897
- const typeField = typeof parsedJson === "object" && parsedJson !== null && "type" in parsedJson ? parsedJson.type : void 0;
902
+ const typeField = RawMessageTypeSchema.safeParse(parsedJson).data?.type;
898
903
  const socket = this.socketByConnectionId.get(connectionId);
899
904
  if (!socket) return;
900
905
  if (socket.protocol === RELAY_INTERNAL_PROTOCOL) {
@@ -903,7 +908,7 @@ var RelayBridgeServer = class extends EventEmitter {
903
908
  else process.stderr.write(`[webmcp-local-relay] warn: invalid relay message from ${connectionId}: ${relayMsg.error.message}\n`);
904
909
  return;
905
910
  }
906
- if (typeof typeField === "string" && typeField.startsWith("relay/")) {
911
+ if (RelayProtocolTypeSchema.safeParse(typeField).success) {
907
912
  process.stderr.write(`[webmcp-local-relay] warn: connection ${connectionId} used the relay protocol without negotiating it\n`);
908
913
  socket.close(1008, "Relay protocol was not negotiated");
909
914
  return;
@@ -914,9 +919,9 @@ var RelayBridgeServer = class extends EventEmitter {
914
919
  return;
915
920
  }
916
921
  this.registry.touchConnection(connectionId);
917
- this.onBrowserClientMessage(connectionId, parsedMessage.data);
922
+ this.onBrowserClientMessage(connectionId, socket, parsedMessage.data);
918
923
  }
919
- onBrowserClientMessage(connectionId, message) {
924
+ onBrowserClientMessage(connectionId, socket, message) {
920
925
  if (message.type !== "hello" && !this.browserClientConnectionIds.has(connectionId)) {
921
926
  process.stderr.write(`[webmcp-local-relay] warn: connection ${connectionId} sent ${message.type} before hello, ignoring\n`);
922
927
  return;
@@ -924,11 +929,10 @@ var RelayBridgeServer = class extends EventEmitter {
924
929
  switch (message.type) {
925
930
  case "hello":
926
931
  try {
927
- const socket = this.socketByConnectionId.get(connectionId);
928
932
  const origin = this.requestOriginByConnectionId.get(connectionId) ?? message.origin;
929
933
  if (!this.isHostOriginAllowed(origin)) {
930
934
  process.stderr.write(`[webmcp-local-relay] warn: rejecting source ${connectionId} with disallowed host origin: ${origin ?? "missing"}\n`);
931
- if (socket) this.sendHelloRejected(socket, {
935
+ this.sendHelloRejected(socket, {
932
936
  type: "hello/rejected",
933
937
  reason: "host-origin-not-allowed",
934
938
  message: "Host page origin is not allowed by this relay."
@@ -940,7 +944,7 @@ var RelayBridgeServer = class extends EventEmitter {
940
944
  origin
941
945
  });
942
946
  this.browserClientConnectionIds.add(connectionId);
943
- if (socket) this.sendHelloAccepted(socket, { type: "hello/accepted" });
947
+ this.sendHelloAccepted(socket, { type: "hello/accepted" });
944
948
  this.emit("stateChanged");
945
949
  } catch (err) {
946
950
  process.stderr.write(`[webmcp-local-relay] error: failed to process hello from connection ${connectionId}: ${err instanceof Error ? err.stack ?? err.message : String(err)}\n`);
@@ -953,7 +957,7 @@ var RelayBridgeServer = class extends EventEmitter {
953
957
  this.emit("stateChanged");
954
958
  } catch (err) {
955
959
  process.stderr.write(`[webmcp-local-relay] error: failed to register tools for connection ${connectionId}: ${err instanceof Error ? err.stack ?? err.message : String(err)}\n`);
956
- this.socketByConnectionId.get(connectionId)?.close(1008, "Invalid tool list");
960
+ socket.close(1008, "Invalid tool list");
957
961
  }
958
962
  break;
959
963
  case "result": {
@@ -1221,7 +1225,7 @@ var RelayBridgeServer = class extends EventEmitter {
1221
1225
  }
1222
1226
  const message = RelayServerToClientMessageSchema.safeParse(parsed);
1223
1227
  if (!message.success) {
1224
- const typeField = typeof parsed === "object" && parsed !== null && "type" in parsed ? parsed.type : "unknown";
1228
+ const typeField = RawMessageTypeSchema.safeParse(parsed).data?.type ?? "unknown";
1225
1229
  process.stderr.write(`[webmcp-local-relay] warn: invalid relay server message (type=${typeField}): ${message.error.message}\n`);
1226
1230
  return null;
1227
1231
  }
@@ -1424,18 +1428,19 @@ function parseCliOptions(argv) {
1424
1428
  const maxPayloadBytes = parsePositiveInteger("max-payload", values["max-payload"]);
1425
1429
  const allowedOrigins = (values["widget-origin"] ?? values["allowed-origin"] ?? values["ws-origin"])?.split(",").map((origin) => origin.trim()).filter(Boolean) ?? ["*"];
1426
1430
  if (allowedOrigins.length === 0) throw new Error("--widget-origin must include at least one origin.");
1427
- return {
1431
+ const options = {
1428
1432
  allowedOrigins,
1429
1433
  help: values.help ?? false,
1430
1434
  host: values.host ?? "127.0.0.1",
1431
1435
  port,
1432
- portExplicitlySet: values.port !== void 0,
1433
- ...values.label === void 0 ? {} : { label: values.label },
1434
- ...invokeTimeoutMs === void 0 ? {} : { invokeTimeoutMs },
1435
- ...maxPayloadBytes === void 0 ? {} : { maxPayloadBytes },
1436
- ...values["relay-id"] === void 0 ? {} : { relayId: values["relay-id"] },
1437
- ...values.workspace === void 0 ? {} : { workspace: values.workspace }
1436
+ portExplicitlySet: values.port !== void 0
1438
1437
  };
1438
+ if (values.label !== void 0) options.label = values.label;
1439
+ if (invokeTimeoutMs !== void 0) options.invokeTimeoutMs = invokeTimeoutMs;
1440
+ if (maxPayloadBytes !== void 0) options.maxPayloadBytes = maxPayloadBytes;
1441
+ if (values["relay-id"] !== void 0) options.relayId = values["relay-id"];
1442
+ if (values.workspace !== void 0) options.workspace = values.workspace;
1443
+ return options;
1439
1444
  }
1440
1445
  /**
1441
1446
  * Prints CLI usage to stderr.
@@ -1465,6 +1470,22 @@ function printHelp() {
1465
1470
 
1466
1471
  //#endregion
1467
1472
  //#region src/mcpRelayServer.ts
1473
+ const JsonSchemaObjectSchema = z.record(z.string(), z.unknown());
1474
+ function textResult(text) {
1475
+ return { content: [{
1476
+ type: "text",
1477
+ text
1478
+ }] };
1479
+ }
1480
+ function errorResult(text) {
1481
+ return {
1482
+ content: [{
1483
+ type: "text",
1484
+ text
1485
+ }],
1486
+ isError: true
1487
+ };
1488
+ }
1468
1489
  /**
1469
1490
  * MCP server facade that exposes browser-relayed tools over MCP transport.
1470
1491
  */
@@ -1474,6 +1495,7 @@ var LocalRelayMcpServer = class {
1474
1495
  */
1475
1496
  bridge;
1476
1497
  mcpServer;
1498
+ launchBrowser;
1477
1499
  dynamicTools = /* @__PURE__ */ new Map();
1478
1500
  syncDebounceTimer = null;
1479
1501
  connected = false;
@@ -1482,6 +1504,7 @@ var LocalRelayMcpServer = class {
1482
1504
  */
1483
1505
  constructor(options = {}) {
1484
1506
  this.bridge = options.bridge ?? new RelayBridgeServer(options.bridgeOptions);
1507
+ this.launchBrowser = options.launchBrowser ?? execFile;
1485
1508
  this.mcpServer = new McpServer({
1486
1509
  name: options.serverName ?? "webmcp-local-relay",
1487
1510
  version: options.serverVersion ?? "0.0.0"
@@ -1557,10 +1580,10 @@ var LocalRelayMcpServer = class {
1557
1580
  const clientMode = this.bridge.mode === "client";
1558
1581
  const sources = clientMode ? this.bridge.listSourcesFromRelay() : this.bridge.registry.listSources();
1559
1582
  const info = {
1560
- ...clientMode ? { mode: "client" } : {},
1561
1583
  count: sources.length,
1562
1584
  sources
1563
1585
  };
1586
+ if (clientMode) info.mode = "client";
1564
1587
  return {
1565
1588
  content: [{
1566
1589
  type: "text",
@@ -1598,76 +1621,26 @@ var LocalRelayMcpServer = class {
1598
1621
  }),
1599
1622
  annotations: { readOnlyHint: false }
1600
1623
  }, async ({ url, refresh }) => {
1601
- let parsed;
1602
- try {
1603
- parsed = new URL(url);
1604
- } catch {
1605
- return {
1606
- content: [{
1607
- type: "text",
1608
- text: `Invalid URL: ${url}`
1609
- }],
1610
- isError: true
1611
- };
1612
- }
1613
- if (parsed.protocol !== "http:" && parsed.protocol !== "https:") return {
1614
- content: [{
1615
- type: "text",
1616
- text: `Only http: and https: URLs are allowed. Got: ${parsed.protocol}`
1617
- }],
1618
- isError: true
1619
- };
1624
+ const parsed = URL.parse(url);
1625
+ if (!parsed) return errorResult(`Invalid URL: ${url}`);
1626
+ if (parsed.protocol !== "http:" && parsed.protocol !== "https:") return errorResult(`Only http: and https: URLs are allowed. Got: ${parsed.protocol}`);
1620
1627
  const existing = this.bridge.mode === "server" ? this.bridge.registry.listSources().find((source) => source.url && URL.parse(source.url)?.origin === parsed.origin) : void 0;
1621
1628
  if (refresh) {
1622
- if (this.bridge.mode === "client") return {
1623
- content: [{
1624
- type: "text",
1625
- text: "Refresh is not supported in client mode. Only the server relay can reload sources."
1626
- }],
1627
- isError: true
1628
- };
1629
- if (!existing) return {
1630
- content: [{
1631
- type: "text",
1632
- text: `No connected source matches origin ${parsed.origin}. The page may not be open or connected.`
1633
- }],
1634
- isError: true
1635
- };
1629
+ if (this.bridge.mode === "client") return errorResult("Refresh is not supported in client mode. Only the server relay can reload sources.");
1630
+ if (!existing) return errorResult(`No connected source matches origin ${parsed.origin}. The page may not be open or connected.`);
1636
1631
  try {
1637
1632
  this.bridge.reloadSource(existing.sourceId);
1638
- return { content: [{
1639
- type: "text",
1640
- text: `Reload sent to source ${existing.sourceId} (${existing.url ?? existing.origin}).`
1641
- }] };
1642
1633
  } catch (err) {
1643
- return {
1644
- content: [{
1645
- type: "text",
1646
- text: `Failed to reload source: ${err instanceof Error ? err.message : String(err)}`
1647
- }],
1648
- isError: true
1649
- };
1634
+ return errorResult(`Failed to reload source: ${err instanceof Error ? err.message : String(err)}`);
1650
1635
  }
1636
+ return textResult(`Reload sent to source ${existing.sourceId} (${existing.url ?? existing.origin}).`);
1651
1637
  }
1652
1638
  try {
1653
1639
  await this.openInBrowser(url);
1654
1640
  } catch (err) {
1655
- return {
1656
- content: [{
1657
- type: "text",
1658
- text: `Failed to open browser: ${err instanceof Error ? err.message : String(err)}`
1659
- }],
1660
- isError: true
1661
- };
1641
+ return errorResult(`Failed to open browser: ${err instanceof Error ? err.message : String(err)}`);
1662
1642
  }
1663
- if (existing) return { content: [{
1664
- type: "text",
1665
- text: `Opened ${url} in the default browser. Note: a source from ${existing.url ?? existing.origin} is already connected.`
1666
- }] };
1667
- return { content: [{
1668
- type: "text",
1669
- text: `Opened ${url} in the default browser.`
1670
- }] };
1643
+ return textResult(existing ? `Opened ${url} in the default browser. Note: a source from ${existing.url ?? existing.origin} is already connected.` : `Opened ${url} in the default browser.`);
1671
1644
  });
1672
1645
  }
1673
1646
  /**
@@ -1680,7 +1653,7 @@ var LocalRelayMcpServer = class {
1680
1653
  const safeUrl = new URL(url).href;
1681
1654
  const command = process.platform === "darwin" ? "open" : process.platform === "win32" ? "explorer.exe" : "xdg-open";
1682
1655
  return new Promise((resolve, reject) => {
1683
- execFile(command, [safeUrl], (err) => {
1656
+ this.launchBrowser(command, [safeUrl], (err) => {
1684
1657
  if (err) reject(err);
1685
1658
  else resolve();
1686
1659
  });
@@ -1770,30 +1743,25 @@ var LocalRelayMcpServer = class {
1770
1743
  * Registers a single dynamic tool and returns a removal handle.
1771
1744
  */
1772
1745
  registerDynamicTool(tool) {
1773
- const inputSchema = fromJsonSchema(tool.inputSchema);
1774
- const outputSchema = tool.outputSchema ? fromJsonSchema(tool.outputSchema) : void 0;
1775
- return this.mcpServer.registerTool(tool.name, {
1776
- ...tool.title !== void 0 ? { title: tool.title } : {},
1746
+ const inputSchema = fromJsonSchema(JsonSchemaObjectSchema.parse(tool.inputSchema));
1747
+ const outputSchema = tool.outputSchema !== void 0 ? fromJsonSchema(JsonSchemaObjectSchema.parse(tool.outputSchema)) : void 0;
1748
+ const registration = {
1777
1749
  description: this.dynamicToolDescription(tool),
1778
- inputSchema,
1779
- ...outputSchema ? { outputSchema } : {},
1780
- ...tool.annotations ? { annotations: tool.annotations } : {},
1781
- ...tool.icons ? { icons: tool.icons } : {},
1782
- ...tool._meta ? { _meta: tool._meta } : {}
1783
- }, async (args) => {
1750
+ inputSchema
1751
+ };
1752
+ if (tool.title !== void 0) registration.title = tool.title;
1753
+ if (outputSchema) registration.outputSchema = outputSchema;
1754
+ if (tool.annotations) registration.annotations = tool.annotations;
1755
+ if (tool.icons) registration.icons = tool.icons;
1756
+ if (tool._meta) registration._meta = tool._meta;
1757
+ return this.mcpServer.registerTool(tool.name, registration, async (args) => {
1784
1758
  try {
1785
1759
  return await this.bridge.invokeTool(tool.name, args);
1786
1760
  } catch (err) {
1787
1761
  const message = err instanceof Error ? err.message : String(err);
1788
1762
  const details = err instanceof Error ? err.stack ?? err.message : String(err);
1789
1763
  process.stderr.write(`[webmcp-local-relay] error: dynamic tool "${tool.name}" invocation failed: ${details}\n`);
1790
- return {
1791
- content: [{
1792
- type: "text",
1793
- text: `Failed to invoke relayed tool "${tool.name}": ${message}`
1794
- }],
1795
- isError: true
1796
- };
1764
+ return errorResult(`Failed to invoke relayed tool "${tool.name}": ${message}`);
1797
1765
  }
1798
1766
  });
1799
1767
  }
@@ -1832,4 +1800,4 @@ var LocalRelayMcpServer = class {
1832
1800
 
1833
1801
  //#endregion
1834
1802
  export { NormalizedToolSchema as C, normalizeInboundTool as D, ToolSchema as E, InboundToolSchema as S, ToolAnnotationsSchema as T, extractSanitizedDomain as _, BrowserToRelayMessageSchema as a, CallToolResultSchema as b, RelayHelloAcceptedMessageSchema as c, RelaySourceInfoSchema as d, RelayToBrowserMessageSchema as f, buildPublicToolName as g, RelayRegistry as h, RelayBridgeServer as i, RelayHelloRejectedMessageSchema as l, HelloRequiredError as m, parseCliOptions as n, RelayClientToServerMessageSchema as o, ServerHelloMessageSchema as p, printHelp as r, RelayDescriptorSchema as s, LocalRelayMcpServer as t, RelayServerToClientMessageSchema as u, sanitizeName as v, RelayInvokeArgsSchema as w, DEFAULT_TOOL_INPUT_SCHEMA as x, CallToolRequestParamsSchema as y };
1835
- //# sourceMappingURL=mcpRelayServer-DfGkigG5.mjs.map
1803
+ //# sourceMappingURL=mcpRelayServer-DEgebuO2.mjs.map