@mcp-b/webmcp-local-relay 0.0.0-beta-20260225101008

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/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2025 mcp-b contributors
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md ADDED
@@ -0,0 +1,193 @@
1
+ # @mcp-b/webmcp-local-relay
2
+
3
+ Local MCP relay for browser WebMCP tools.
4
+
5
+ This package lets an MCP client (Claude Code, Cursor, etc.) call tools from websites you currently have open, via a localhost bridge.
6
+
7
+ ## Requirement: WebMCP Runtime On The Page
8
+
9
+ Relay only forwards tools that are registered on `navigator.modelContext`.
10
+
11
+ A connected page must install one of:
12
+
13
+ 1. `@mcp-b/global` (recommended).
14
+ 2. `@mcp-b/webmcp-polyfill` (strict core), with `navigator.modelContextTesting` available (default in the polyfill).
15
+
16
+ Runtime dispatch behavior:
17
+
18
+ - If `navigator.modelContext.listTools` + `navigator.modelContext.callTool` exist, relay uses that extension path.
19
+ - Otherwise, relay uses `navigator.modelContextTesting.listTools` + `executeTool`.
20
+
21
+ ## Users First: Install In Claude Code (Plugin)
22
+
23
+ Recommended path: install the plugin in Claude Code, then use the relayed tools directly.
24
+
25
+ 1. Clone this repository locally.
26
+ 2. In Claude Code, run:
27
+
28
+ ```text
29
+ /plugin add /absolute/path/to/npm-packages/packages/webmcp-local-relay/.claude-plugin
30
+ ```
31
+
32
+ Optional scope flag:
33
+
34
+ ```text
35
+ /plugin add /absolute/path/to/npm-packages/packages/webmcp-local-relay/.claude-plugin --scope user
36
+ ```
37
+
38
+ 3. Confirm installation:
39
+
40
+ ```text
41
+ /plugin list
42
+ ```
43
+
44
+ 4. Start using the relay:
45
+ - Ask Claude to run `webmcp_list_sources`.
46
+ - Ask Claude to run `webmcp_list_tools`.
47
+ - Call the returned `webmcp_*` tools.
48
+
49
+ Plugin manifest:
50
+ - [`./.claude-plugin/plugin.json`](./.claude-plugin/plugin.json)
51
+
52
+ Skill included in the plugin:
53
+ - [`./.claude-plugin/skills/webmcp-local-relay/SKILL.md`](./.claude-plugin/skills/webmcp-local-relay/SKILL.md)
54
+
55
+ ## Claude Code Section: Plugin + Skill Behavior
56
+
57
+ The plugin wires two things:
58
+
59
+ 1. MCP server registration:
60
+ - Starts `@mcp-b/webmcp-local-relay` via `npx`.
61
+ 2. Skill registration:
62
+ - Provides a focused skill that tells the agent how to discover sources/tools and route calls safely.
63
+
64
+ The skill guidance is intentionally operational:
65
+ - list sources first
66
+ - list tools second
67
+ - pick the right domain/tab
68
+ - re-list tools if the browser session changes
69
+
70
+ ## Reference Docs (Deep Dive Sources)
71
+
72
+ - Claude Code plugin creation:
73
+ - https://docs.anthropic.com/en/docs/claude-code/plugins/create-plugins
74
+ - Claude Code plugin schema and plugin marketplace reference:
75
+ - https://docs.anthropic.com/en/docs/claude-code/plugins/plugins-reference
76
+ - Claude Code plugin discovery and install commands:
77
+ - https://docs.anthropic.com/en/docs/claude-code/plugins/discover-plugins
78
+ - Claude Code skill system:
79
+ - https://docs.anthropic.com/en/docs/claude-code/skills
80
+ - Agent Skills ecosystem project:
81
+ - https://github.com/agentskills/agent-skills
82
+
83
+ ## Website Owner Setup
84
+
85
+ Your page should load an embed script that injects a hidden widget iframe.
86
+
87
+ ```html
88
+ <script src="https://yourdomain.example/embed.js"></script>
89
+ ```
90
+
91
+ Minimal `embed.js` pattern:
92
+
93
+ ```js
94
+ (() => {
95
+ const iframe = document.createElement('iframe');
96
+ iframe.src = 'https://yourdomain.example/widget';
97
+ iframe.style.display = 'none';
98
+ iframe.setAttribute('aria-hidden', 'true');
99
+ document.body.appendChild(iframe);
100
+ })();
101
+ ```
102
+
103
+ Your page must also register tools using one of the supported WebMCP runtimes.
104
+
105
+ Example (recommended) with `@mcp-b/global`:
106
+
107
+ ```html
108
+ <script src="https://cdn.jsdelivr.net/npm/@mcp-b/global@latest/dist/index.iife.js"></script>
109
+ <script>
110
+ navigator.modelContext.registerTool({
111
+ name: 'get_page_title',
112
+ description: 'Get page title',
113
+ inputSchema: { type: 'object', properties: {} },
114
+ execute: async () => ({ content: [{ type: 'text', text: document.title }] }),
115
+ });
116
+ </script>
117
+ ```
118
+
119
+ Example with strict `@mcp-b/webmcp-polyfill`:
120
+
121
+ ```html
122
+ <script src="https://cdn.jsdelivr.net/npm/@mcp-b/webmcp-polyfill@latest/dist/index.iife.js"></script>
123
+ <script>
124
+ navigator.modelContext.registerTool({
125
+ name: 'get_page_title',
126
+ description: 'Get page title',
127
+ inputSchema: { type: 'object', properties: {} },
128
+ execute: async () => ({ content: [{ type: 'text', text: document.title }] }),
129
+ });
130
+ </script>
131
+ ```
132
+
133
+ Widget responsibilities:
134
+ - Connect to `ws://127.0.0.1:9333` (or your configured relay port).
135
+ - Send source metadata (`hello`) and current tool list (`tools/list`).
136
+ - Handle `invoke` messages and return `result`.
137
+ - Reconnect automatically when the local relay starts later.
138
+
139
+ Security baseline:
140
+ - Run relay on loopback only (`127.0.0.1`).
141
+ - Restrict `--widget-origin` to your widget origin in production.
142
+
143
+ ## User Setup Without Plugin (Fallback)
144
+
145
+ If you do not want plugin install, add the MCP server directly:
146
+
147
+ ```json
148
+ {
149
+ "mcpServers": {
150
+ "webmcp-local-relay": {
151
+ "command": "npx",
152
+ "args": ["-y", "@mcp-b/webmcp-local-relay@latest"]
153
+ }
154
+ }
155
+ }
156
+ ```
157
+
158
+ Then restart Claude Code and call:
159
+ - `webmcp_list_sources`
160
+ - `webmcp_list_tools`
161
+
162
+ ## Developer Setup
163
+
164
+ From repository root:
165
+
166
+ ```bash
167
+ pnpm install
168
+ pnpm --filter @mcp-b/webmcp-local-relay build
169
+ pnpm --filter @mcp-b/webmcp-local-relay test
170
+ pnpm --filter @mcp-b/webmcp-local-relay test:e2e
171
+ ```
172
+
173
+ Run relay locally:
174
+
175
+ ```bash
176
+ node packages/webmcp-local-relay/dist/cli.js --host 127.0.0.1 --port 9333
177
+ ```
178
+
179
+ Lock widget origin while developing:
180
+
181
+ ```bash
182
+ node packages/webmcp-local-relay/dist/cli.js --host 127.0.0.1 --port 9333 --widget-origin https://your-widget-domain.example
183
+ ```
184
+
185
+ ## Tooling Model
186
+
187
+ Static tools:
188
+ - `webmcp_list_sources`
189
+ - `webmcp_list_tools`
190
+
191
+ Dynamic tools:
192
+ - registered from browser sources
193
+ - deterministic namespaced IDs for de-duping across tabs and domains
package/dist/cli.d.ts ADDED
@@ -0,0 +1 @@
1
+ export { };
package/dist/cli.js ADDED
@@ -0,0 +1,74 @@
1
+ #!/usr/bin/env node
2
+ import { t as LocalRelayMcpServer } from "./mcpRelayServer-BwF1i7Se.js";
3
+
4
+ //#region src/cli.ts
5
+ function parseCliOptions(argv) {
6
+ const options$1 = {
7
+ host: "127.0.0.1",
8
+ port: 9333,
9
+ allowedOrigins: ["*"]
10
+ };
11
+ for (let i = 0; i < argv.length; i++) {
12
+ const token = argv[i];
13
+ if (!token) continue;
14
+ if ((token === "--host" || token === "-h") && argv[i + 1]) {
15
+ options$1.host = argv[++i];
16
+ continue;
17
+ }
18
+ if ((token === "--port" || token === "-p") && argv[i + 1]) {
19
+ const value = Number.parseInt(argv[++i], 10);
20
+ if (Number.isFinite(value) && value > 0 && value <= 65535) options$1.port = value;
21
+ continue;
22
+ }
23
+ if ((token === "--widget-origin" || token === "--allowed-origin") && argv[i + 1]) {
24
+ const split = argv[++i].split(",").map((part) => part.trim()).filter(Boolean);
25
+ if (split.length > 0) options$1.allowedOrigins = split;
26
+ continue;
27
+ }
28
+ if (token === "--help" || token === "-?") {
29
+ printHelp();
30
+ process.exit(0);
31
+ }
32
+ }
33
+ return options$1;
34
+ }
35
+ function printHelp() {
36
+ process.stderr.write([
37
+ "webmcp-local-relay",
38
+ "",
39
+ "Usage:",
40
+ " webmcp-local-relay [--host 127.0.0.1] [--port 9333] [--widget-origin https://yourdomain.com]",
41
+ "",
42
+ "Options:",
43
+ " --host, -h Bind host for local websocket relay (default: 127.0.0.1)",
44
+ " --port, -p Bind port for local websocket relay (default: 9333)",
45
+ " --widget-origin Allowed browser origin(s), comma-separated (default: *)",
46
+ " --allowed-origin Alias for --widget-origin",
47
+ " --help, -? Show help",
48
+ ""
49
+ ].join("\n"));
50
+ }
51
+ const options = parseCliOptions(process.argv.slice(2));
52
+ const relay = new LocalRelayMcpServer({ bridgeOptions: {
53
+ host: options.host,
54
+ port: options.port,
55
+ allowedOrigins: options.allowedOrigins
56
+ } });
57
+ await relay.start();
58
+ await relay.startStdio();
59
+ process.stderr.write(`[webmcp-local-relay] listening on ws://${options.host}:${relay.bridge.port} (allowed origins: ${options.allowedOrigins.join(", ")})\n`);
60
+ const shutdown = async (signal) => {
61
+ process.stderr.write(`[webmcp-local-relay] received ${signal}, shutting down\n`);
62
+ await relay.stop();
63
+ process.exit(0);
64
+ };
65
+ process.on("SIGINT", () => {
66
+ shutdown("SIGINT");
67
+ });
68
+ process.on("SIGTERM", () => {
69
+ shutdown("SIGTERM");
70
+ });
71
+
72
+ //#endregion
73
+ export { };
74
+ //# sourceMappingURL=cli.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"cli.js","names":["options: CliOptions","options"],"sources":["../src/cli.ts"],"sourcesContent":["#!/usr/bin/env node\n\nimport { LocalRelayMcpServer } from './mcpRelayServer.js';\n\ninterface CliOptions {\n host: string;\n port: number;\n allowedOrigins: string[];\n}\n\nfunction parseCliOptions(argv: string[]): CliOptions {\n const options: CliOptions = {\n host: '127.0.0.1',\n port: 9333,\n allowedOrigins: ['*'],\n };\n\n for (let i = 0; i < argv.length; i++) {\n const token = argv[i];\n if (!token) continue;\n\n if ((token === '--host' || token === '-h') && argv[i + 1]) {\n options.host = argv[++i] as string;\n continue;\n }\n\n if ((token === '--port' || token === '-p') && argv[i + 1]) {\n const value = Number.parseInt(argv[++i] as string, 10);\n if (Number.isFinite(value) && value > 0 && value <= 65535) {\n options.port = value;\n }\n continue;\n }\n\n if ((token === '--widget-origin' || token === '--allowed-origin') && argv[i + 1]) {\n const raw = argv[++i] as string;\n const split = raw\n .split(',')\n .map((part) => part.trim())\n .filter(Boolean);\n\n if (split.length > 0) {\n options.allowedOrigins = split;\n }\n continue;\n }\n\n if (token === '--help' || token === '-?') {\n printHelp();\n process.exit(0);\n }\n }\n\n return options;\n}\n\nfunction printHelp(): void {\n process.stderr.write(\n [\n 'webmcp-local-relay',\n '',\n 'Usage:',\n ' webmcp-local-relay [--host 127.0.0.1] [--port 9333] [--widget-origin https://yourdomain.com]',\n '',\n 'Options:',\n ' --host, -h Bind host for local websocket relay (default: 127.0.0.1)',\n ' --port, -p Bind port for local websocket relay (default: 9333)',\n ' --widget-origin Allowed browser origin(s), comma-separated (default: *)',\n ' --allowed-origin Alias for --widget-origin',\n ' --help, -? Show help',\n '',\n ].join('\\n')\n );\n}\n\nconst options = parseCliOptions(process.argv.slice(2));\n\nconst relay = new LocalRelayMcpServer({\n bridgeOptions: {\n host: options.host,\n port: options.port,\n allowedOrigins: options.allowedOrigins,\n },\n});\n\nawait relay.start();\nawait relay.startStdio();\n\nprocess.stderr.write(\n `[webmcp-local-relay] listening on ws://${options.host}:${relay.bridge.port} (allowed origins: ${options.allowedOrigins.join(', ')})\\n`\n);\n\nconst shutdown = async (signal: string) => {\n process.stderr.write(`[webmcp-local-relay] received ${signal}, shutting down\\n`);\n await relay.stop();\n process.exit(0);\n};\n\nprocess.on('SIGINT', () => {\n void shutdown('SIGINT');\n});\nprocess.on('SIGTERM', () => {\n void shutdown('SIGTERM');\n});\n"],"mappings":";;;;AAUA,SAAS,gBAAgB,MAA4B;CACnD,MAAMA,YAAsB;EAC1B,MAAM;EACN,MAAM;EACN,gBAAgB,CAAC,IAAI;EACtB;AAED,MAAK,IAAI,IAAI,GAAG,IAAI,KAAK,QAAQ,KAAK;EACpC,MAAM,QAAQ,KAAK;AACnB,MAAI,CAAC,MAAO;AAEZ,OAAK,UAAU,YAAY,UAAU,SAAS,KAAK,IAAI,IAAI;AACzD,aAAQ,OAAO,KAAK,EAAE;AACtB;;AAGF,OAAK,UAAU,YAAY,UAAU,SAAS,KAAK,IAAI,IAAI;GACzD,MAAM,QAAQ,OAAO,SAAS,KAAK,EAAE,IAAc,GAAG;AACtD,OAAI,OAAO,SAAS,MAAM,IAAI,QAAQ,KAAK,SAAS,MAClD,WAAQ,OAAO;AAEjB;;AAGF,OAAK,UAAU,qBAAqB,UAAU,uBAAuB,KAAK,IAAI,IAAI;GAEhF,MAAM,QADM,KAAK,EAAE,GAEhB,MAAM,IAAI,CACV,KAAK,SAAS,KAAK,MAAM,CAAC,CAC1B,OAAO,QAAQ;AAElB,OAAI,MAAM,SAAS,EACjB,WAAQ,iBAAiB;AAE3B;;AAGF,MAAI,UAAU,YAAY,UAAU,MAAM;AACxC,cAAW;AACX,WAAQ,KAAK,EAAE;;;AAInB,QAAOC;;AAGT,SAAS,YAAkB;AACzB,SAAQ,OAAO,MACb;EACE;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACD,CAAC,KAAK,KAAK,CACb;;AAGH,MAAM,UAAU,gBAAgB,QAAQ,KAAK,MAAM,EAAE,CAAC;AAEtD,MAAM,QAAQ,IAAI,oBAAoB,EACpC,eAAe;CACb,MAAM,QAAQ;CACd,MAAM,QAAQ;CACd,gBAAgB,QAAQ;CACzB,EACF,CAAC;AAEF,MAAM,MAAM,OAAO;AACnB,MAAM,MAAM,YAAY;AAExB,QAAQ,OAAO,MACb,0CAA0C,QAAQ,KAAK,GAAG,MAAM,OAAO,KAAK,qBAAqB,QAAQ,eAAe,KAAK,KAAK,CAAC,KACpI;AAED,MAAM,WAAW,OAAO,WAAmB;AACzC,SAAQ,OAAO,MAAM,iCAAiC,OAAO,mBAAmB;AAChF,OAAM,MAAM,MAAM;AAClB,SAAQ,KAAK,EAAE;;AAGjB,QAAQ,GAAG,gBAAgB;AACzB,CAAK,SAAS,SAAS;EACvB;AACF,QAAQ,GAAG,iBAAiB;AAC1B,CAAK,SAAS,UAAU;EACxB"}
@@ -0,0 +1,314 @@
1
+ import { z } from "zod";
2
+ import { EventEmitter } from "node:events";
3
+ import { CallToolResult } from "@modelcontextprotocol/sdk/types.js";
4
+ import { Transport } from "@modelcontextprotocol/sdk/shared/transport.js";
5
+
6
+ //#region src/schemas.d.ts
7
+ declare const BrowserToolSchema: z.ZodObject<{
8
+ name: z.ZodString;
9
+ description: z.ZodOptional<z.ZodString>;
10
+ inputSchema: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodUnknown>>;
11
+ outputSchema: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodUnknown>>;
12
+ annotations: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodUnknown>>;
13
+ }, "strip", z.ZodTypeAny, {
14
+ name: string;
15
+ description?: string | undefined;
16
+ inputSchema?: Record<string, unknown> | undefined;
17
+ outputSchema?: Record<string, unknown> | undefined;
18
+ annotations?: Record<string, unknown> | undefined;
19
+ }, {
20
+ name: string;
21
+ description?: string | undefined;
22
+ inputSchema?: Record<string, unknown> | undefined;
23
+ outputSchema?: Record<string, unknown> | undefined;
24
+ annotations?: Record<string, unknown> | undefined;
25
+ }>;
26
+ declare const BrowserHelloMessageSchema: z.ZodObject<{
27
+ type: z.ZodLiteral<"hello">;
28
+ tabId: z.ZodString;
29
+ origin: z.ZodOptional<z.ZodString>;
30
+ url: z.ZodOptional<z.ZodString>;
31
+ title: z.ZodOptional<z.ZodString>;
32
+ iconUrl: z.ZodOptional<z.ZodString>;
33
+ }, "strip", z.ZodTypeAny, {
34
+ type: "hello";
35
+ tabId: string;
36
+ origin?: string | undefined;
37
+ url?: string | undefined;
38
+ title?: string | undefined;
39
+ iconUrl?: string | undefined;
40
+ }, {
41
+ type: "hello";
42
+ tabId: string;
43
+ origin?: string | undefined;
44
+ url?: string | undefined;
45
+ title?: string | undefined;
46
+ iconUrl?: string | undefined;
47
+ }>;
48
+ declare const BrowserToRelayMessageSchema: z.ZodDiscriminatedUnion<"type", [z.ZodObject<{
49
+ type: z.ZodLiteral<"hello">;
50
+ tabId: z.ZodString;
51
+ origin: z.ZodOptional<z.ZodString>;
52
+ url: z.ZodOptional<z.ZodString>;
53
+ title: z.ZodOptional<z.ZodString>;
54
+ iconUrl: z.ZodOptional<z.ZodString>;
55
+ }, "strip", z.ZodTypeAny, {
56
+ type: "hello";
57
+ tabId: string;
58
+ origin?: string | undefined;
59
+ url?: string | undefined;
60
+ title?: string | undefined;
61
+ iconUrl?: string | undefined;
62
+ }, {
63
+ type: "hello";
64
+ tabId: string;
65
+ origin?: string | undefined;
66
+ url?: string | undefined;
67
+ title?: string | undefined;
68
+ iconUrl?: string | undefined;
69
+ }>, z.ZodObject<{
70
+ type: z.ZodLiteral<"tools/list">;
71
+ tools: z.ZodArray<z.ZodObject<{
72
+ name: z.ZodString;
73
+ description: z.ZodOptional<z.ZodString>;
74
+ inputSchema: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodUnknown>>;
75
+ outputSchema: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodUnknown>>;
76
+ annotations: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodUnknown>>;
77
+ }, "strip", z.ZodTypeAny, {
78
+ name: string;
79
+ description?: string | undefined;
80
+ inputSchema?: Record<string, unknown> | undefined;
81
+ outputSchema?: Record<string, unknown> | undefined;
82
+ annotations?: Record<string, unknown> | undefined;
83
+ }, {
84
+ name: string;
85
+ description?: string | undefined;
86
+ inputSchema?: Record<string, unknown> | undefined;
87
+ outputSchema?: Record<string, unknown> | undefined;
88
+ annotations?: Record<string, unknown> | undefined;
89
+ }>, "many">;
90
+ }, "strip", z.ZodTypeAny, {
91
+ type: "tools/list";
92
+ tools: {
93
+ name: string;
94
+ description?: string | undefined;
95
+ inputSchema?: Record<string, unknown> | undefined;
96
+ outputSchema?: Record<string, unknown> | undefined;
97
+ annotations?: Record<string, unknown> | undefined;
98
+ }[];
99
+ }, {
100
+ type: "tools/list";
101
+ tools: {
102
+ name: string;
103
+ description?: string | undefined;
104
+ inputSchema?: Record<string, unknown> | undefined;
105
+ outputSchema?: Record<string, unknown> | undefined;
106
+ annotations?: Record<string, unknown> | undefined;
107
+ }[];
108
+ }>, z.ZodObject<{
109
+ type: z.ZodLiteral<"tools/changed">;
110
+ tools: z.ZodArray<z.ZodObject<{
111
+ name: z.ZodString;
112
+ description: z.ZodOptional<z.ZodString>;
113
+ inputSchema: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodUnknown>>;
114
+ outputSchema: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodUnknown>>;
115
+ annotations: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodUnknown>>;
116
+ }, "strip", z.ZodTypeAny, {
117
+ name: string;
118
+ description?: string | undefined;
119
+ inputSchema?: Record<string, unknown> | undefined;
120
+ outputSchema?: Record<string, unknown> | undefined;
121
+ annotations?: Record<string, unknown> | undefined;
122
+ }, {
123
+ name: string;
124
+ description?: string | undefined;
125
+ inputSchema?: Record<string, unknown> | undefined;
126
+ outputSchema?: Record<string, unknown> | undefined;
127
+ annotations?: Record<string, unknown> | undefined;
128
+ }>, "many">;
129
+ }, "strip", z.ZodTypeAny, {
130
+ type: "tools/changed";
131
+ tools: {
132
+ name: string;
133
+ description?: string | undefined;
134
+ inputSchema?: Record<string, unknown> | undefined;
135
+ outputSchema?: Record<string, unknown> | undefined;
136
+ annotations?: Record<string, unknown> | undefined;
137
+ }[];
138
+ }, {
139
+ type: "tools/changed";
140
+ tools: {
141
+ name: string;
142
+ description?: string | undefined;
143
+ inputSchema?: Record<string, unknown> | undefined;
144
+ outputSchema?: Record<string, unknown> | undefined;
145
+ annotations?: Record<string, unknown> | undefined;
146
+ }[];
147
+ }>, z.ZodObject<{
148
+ type: z.ZodLiteral<"result">;
149
+ callId: z.ZodString;
150
+ result: z.ZodUnknown;
151
+ }, "strip", z.ZodTypeAny, {
152
+ type: "result";
153
+ callId: string;
154
+ result?: unknown;
155
+ }, {
156
+ type: "result";
157
+ callId: string;
158
+ result?: unknown;
159
+ }>, z.ZodObject<{
160
+ type: z.ZodLiteral<"pong">;
161
+ }, "strip", z.ZodTypeAny, {
162
+ type: "pong";
163
+ }, {
164
+ type: "pong";
165
+ }>]>;
166
+ type BrowserToRelayMessage = z.infer<typeof BrowserToRelayMessageSchema>;
167
+ type BrowserTool = z.infer<typeof BrowserToolSchema>;
168
+ type BrowserHelloMessage = z.infer<typeof BrowserHelloMessageSchema>;
169
+ declare const RelayToBrowserMessageSchema: z.ZodDiscriminatedUnion<"type", [z.ZodObject<{
170
+ type: z.ZodLiteral<"invoke">;
171
+ callId: z.ZodString;
172
+ toolName: z.ZodString;
173
+ args: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodUnknown>>;
174
+ }, "strip", z.ZodTypeAny, {
175
+ type: "invoke";
176
+ callId: string;
177
+ toolName: string;
178
+ args?: Record<string, unknown> | undefined;
179
+ }, {
180
+ type: "invoke";
181
+ callId: string;
182
+ toolName: string;
183
+ args?: Record<string, unknown> | undefined;
184
+ }>, z.ZodObject<{
185
+ type: z.ZodLiteral<"ping">;
186
+ }, "strip", z.ZodTypeAny, {
187
+ type: "ping";
188
+ }, {
189
+ type: "ping";
190
+ }>]>;
191
+ type RelayToBrowserMessage = z.infer<typeof RelayToBrowserMessageSchema>;
192
+ //#endregion
193
+ //#region src/registry.d.ts
194
+ interface SourceInfo {
195
+ sourceId: string;
196
+ tabId: string;
197
+ origin: string | undefined;
198
+ url: string | undefined;
199
+ title: string | undefined;
200
+ iconUrl: string | undefined;
201
+ connectedAt: number;
202
+ lastSeenAt: number;
203
+ toolCount: number;
204
+ }
205
+ interface AggregatedTool {
206
+ name: string;
207
+ originalName: string;
208
+ description: string | undefined;
209
+ inputSchema: Record<string, unknown> | undefined;
210
+ outputSchema: Record<string, unknown> | undefined;
211
+ annotations: Record<string, unknown> | undefined;
212
+ sources: SourceInfo[];
213
+ }
214
+ interface ResolvedInvocation {
215
+ connectionId: string;
216
+ tool: BrowserTool;
217
+ publicToolName: string;
218
+ }
219
+ declare class RelayRegistry {
220
+ private readonly now;
221
+ private readonly sourceByConnectionId;
222
+ private readonly toolsByConnectionId;
223
+ private readonly providersByPublicToolName;
224
+ constructor(now?: () => number);
225
+ upsertSource(connectionId: string, hello: BrowserHelloMessage): void;
226
+ registerTools(connectionId: string, tools: BrowserTool[]): void;
227
+ removeConnection(connectionId: string): void;
228
+ touchConnection(connectionId: string): void;
229
+ listSources(): SourceInfo[];
230
+ listTools(): AggregatedTool[];
231
+ resolveInvocation(options: {
232
+ toolName: string;
233
+ sourceId?: string;
234
+ requestTabId?: string;
235
+ }): ResolvedInvocation | null;
236
+ private removeConnectionTools;
237
+ private sortProvidersByRecency;
238
+ private compareRecency;
239
+ }
240
+ //#endregion
241
+ //#region src/bridgeServer.d.ts
242
+ interface RelayBridgeServerOptions {
243
+ host?: string;
244
+ port?: number;
245
+ allowedOrigins?: string[];
246
+ maxPayloadBytes?: number;
247
+ invokeTimeoutMs?: number;
248
+ }
249
+ declare class RelayBridgeServer extends EventEmitter {
250
+ readonly registry: RelayRegistry;
251
+ private readonly host;
252
+ private desiredPort;
253
+ private readonly allowedOrigins;
254
+ private readonly maxPayloadBytes;
255
+ private readonly invokeTimeoutMs;
256
+ private wss;
257
+ private readonly socketByConnectionId;
258
+ private readonly connectionIdBySocket;
259
+ private readonly pendingInvocations;
260
+ constructor(options?: RelayBridgeServerOptions, registry?: RelayRegistry);
261
+ get port(): number;
262
+ start(): Promise<void>;
263
+ stop(): Promise<void>;
264
+ invokeTool(toolName: string, args: Record<string, unknown>, options?: {
265
+ sourceId?: string;
266
+ requestTabId?: string;
267
+ }): Promise<CallToolResult>;
268
+ private onSocketMessage;
269
+ private onSocketClose;
270
+ private isOriginAllowed;
271
+ private normalizeCallToolResult;
272
+ }
273
+ //#endregion
274
+ //#region src/mcpRelayServer.d.ts
275
+ interface LocalRelayMcpServerOptions {
276
+ bridge?: RelayBridgeServer;
277
+ bridgeOptions?: RelayBridgeServerOptions;
278
+ serverName?: string;
279
+ serverVersion?: string;
280
+ }
281
+ declare class LocalRelayMcpServer {
282
+ readonly bridge: RelayBridgeServer;
283
+ private readonly mcpServer;
284
+ private readonly dynamicToolHandles;
285
+ private readonly dynamicToolSignature;
286
+ private syncing;
287
+ private syncRequested;
288
+ private connected;
289
+ constructor(options?: LocalRelayMcpServerOptions);
290
+ start(): Promise<void>;
291
+ connect(transport: Transport): Promise<void>;
292
+ startStdio(): Promise<void>;
293
+ stop(): Promise<void>;
294
+ listDynamicToolNames(): string[];
295
+ private registerStaticTools;
296
+ private syncDynamicTools;
297
+ private applyDynamicTools;
298
+ private registerDynamicTool;
299
+ private dynamicToolDescription;
300
+ private normalizeAnnotations;
301
+ private toolSignature;
302
+ }
303
+ //#endregion
304
+ //#region src/naming.d.ts
305
+ declare function sanitizeName(value: string): string;
306
+ declare function extractSanitizedDomain(originOrUrl?: string): string;
307
+ declare function buildPublicToolName(options: {
308
+ domain: string;
309
+ tabId: string;
310
+ originalToolName: string;
311
+ }): string;
312
+ //#endregion
313
+ export { type AggregatedTool, type BrowserToRelayMessage, BrowserToRelayMessageSchema, type BrowserTool, LocalRelayMcpServer, type LocalRelayMcpServerOptions, RelayBridgeServer, type RelayBridgeServerOptions, RelayRegistry, type RelayToBrowserMessage, RelayToBrowserMessageSchema, type ResolvedInvocation, type SourceInfo, buildPublicToolName, extractSanitizedDomain, sanitizeName };
314
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","names":[],"sources":["../src/schemas.ts","../src/registry.ts","../src/bridgeServer.ts","../src/mcpRelayServer.ts","../src/naming.ts"],"sourcesContent":[],"mappings":"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"}
package/dist/index.js ADDED
@@ -0,0 +1,3 @@
1
+ import { a as RelayRegistry, c as sanitizeName, i as RelayToBrowserMessageSchema, n as RelayBridgeServer, o as buildPublicToolName, r as BrowserToRelayMessageSchema, s as extractSanitizedDomain, t as LocalRelayMcpServer } from "./mcpRelayServer-BwF1i7Se.js";
2
+
3
+ export { BrowserToRelayMessageSchema, LocalRelayMcpServer, RelayBridgeServer, RelayRegistry, RelayToBrowserMessageSchema, buildPublicToolName, extractSanitizedDomain, sanitizeName };