@mcp-fe/mcp-worker 0.1.11 → 0.2.2

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/index.js CHANGED
@@ -208,6 +208,197 @@ var ToolRegistry = class {
208
208
  }
209
209
  };
210
210
 
211
+ // libs/mcp-worker/src/client/web-mcp-adapter.ts
212
+ var WebMcpAdapter = class _WebMcpAdapter {
213
+ /** Tracks names of tools currently registered via WebMCP API */
214
+ registeredTools = /* @__PURE__ */ new Set();
215
+ /** Whether the adapter is enabled (enabled by default — auto-detects browser support) */
216
+ enabled = true;
217
+ // --------------------------------------------------------------------------
218
+ // Feature detection
219
+ // --------------------------------------------------------------------------
220
+ /**
221
+ * Check if the browser exposes the WebMCP API (`navigator.modelContext`).
222
+ *
223
+ * Safe to call in any environment (SSR, workers, older browsers).
224
+ *
225
+ * @see https://webmachinelearning.github.io/webmcp/#navigator-extension
226
+ */
227
+ static isSupported() {
228
+ try {
229
+ return typeof navigator !== "undefined" && "modelContext" in navigator && navigator.modelContext != null && typeof navigator.modelContext.registerTool === "function";
230
+ } catch {
231
+ return false;
232
+ }
233
+ }
234
+ /**
235
+ * Convenience: instance-level check that also respects the `enabled` flag.
236
+ */
237
+ isAvailable() {
238
+ return this.enabled && _WebMcpAdapter.isSupported();
239
+ }
240
+ // --------------------------------------------------------------------------
241
+ // Configuration
242
+ // --------------------------------------------------------------------------
243
+ /**
244
+ * Enable or disable the WebMCP adapter.
245
+ *
246
+ * When disabled, `registerTool` / `unregisterTool` become silent no-ops
247
+ * even if the browser supports the API.
248
+ */
249
+ setEnabled(value) {
250
+ this.enabled = value;
251
+ logger.log(`[WebMcpAdapter] Enabled: ${value}`);
252
+ }
253
+ // --------------------------------------------------------------------------
254
+ // Registration
255
+ // --------------------------------------------------------------------------
256
+ /**
257
+ * Register a tool with the WebMCP API (`navigator.modelContext.registerTool()`).
258
+ *
259
+ * Silently returns if the API is unavailable or the adapter is disabled.
260
+ * Per spec, `registerTool()` throws if a tool with the same name already exists,
261
+ * so we unregister first if needed (idempotent update).
262
+ *
263
+ * @param name - Tool name
264
+ * @param description - Human-readable description (required by spec)
265
+ * @param inputSchema - JSON Schema for tool inputs
266
+ * @param handler - Async handler executed in the main thread
267
+ * @param options - Additional MCP tool options (annotations, …)
268
+ */
269
+ registerTool(name, description, inputSchema, handler, options) {
270
+ if (!this.isAvailable()) {
271
+ return;
272
+ }
273
+ if (this.registeredTools.has(name)) {
274
+ this.unregisterTool(name);
275
+ }
276
+ try {
277
+ const modelContext = navigator.modelContext;
278
+ const tool = {
279
+ name,
280
+ description: description ?? name,
281
+ inputSchema,
282
+ execute: async (input) => {
283
+ return handler(input);
284
+ },
285
+ annotations: this.mapAnnotations(options?.annotations)
286
+ };
287
+ modelContext.registerTool(tool);
288
+ this.registeredTools.add(name);
289
+ logger.log(
290
+ `[WebMcpAdapter] Registered tool '${name}' via navigator.modelContext`
291
+ );
292
+ } catch (error) {
293
+ logger.warn(`[WebMcpAdapter] Failed to register '${name}':`, error);
294
+ }
295
+ }
296
+ /**
297
+ * Unregister a tool from the WebMCP API (`navigator.modelContext.unregisterTool()`).
298
+ *
299
+ * Safe to call even if the tool was never registered via WebMCP.
300
+ *
301
+ * @param name - Tool name to unregister
302
+ * @returns `true` if the tool was found and unregistered, `false` otherwise
303
+ */
304
+ unregisterTool(name) {
305
+ if (!this.registeredTools.has(name)) {
306
+ return false;
307
+ }
308
+ try {
309
+ if (_WebMcpAdapter.isSupported()) {
310
+ const modelContext = navigator.modelContext;
311
+ modelContext.unregisterTool(name);
312
+ }
313
+ this.registeredTools.delete(name);
314
+ logger.log(
315
+ `[WebMcpAdapter] Unregistered tool '${name}' from navigator.modelContext`
316
+ );
317
+ return true;
318
+ } catch (error) {
319
+ logger.warn(`[WebMcpAdapter] Failed to unregister '${name}':`, error);
320
+ this.registeredTools.delete(name);
321
+ return false;
322
+ }
323
+ }
324
+ /**
325
+ * Unregister ALL tools registered via WebMCP.
326
+ *
327
+ * Uses `navigator.modelContext.clearContext()` when available (per spec, clears
328
+ * all tools at once), otherwise falls back to individual unregisterTool calls.
329
+ */
330
+ clearAll() {
331
+ if (this.registeredTools.size === 0)
332
+ return;
333
+ logger.log(`[WebMcpAdapter] Clearing ${this.registeredTools.size} tool(s)`);
334
+ try {
335
+ if (_WebMcpAdapter.isSupported()) {
336
+ const modelContext = navigator.modelContext;
337
+ modelContext.clearContext();
338
+ }
339
+ } catch (error) {
340
+ logger.warn(
341
+ "[WebMcpAdapter] clearContext() failed, falling back to individual unregister:",
342
+ error
343
+ );
344
+ const names = Array.from(this.registeredTools);
345
+ names.forEach((name) => {
346
+ try {
347
+ if (_WebMcpAdapter.isSupported()) {
348
+ navigator.modelContext.unregisterTool(name);
349
+ }
350
+ } catch {
351
+ }
352
+ });
353
+ }
354
+ this.registeredTools.clear();
355
+ }
356
+ // --------------------------------------------------------------------------
357
+ // Query
358
+ // --------------------------------------------------------------------------
359
+ /**
360
+ * Check if a tool is registered via WebMCP.
361
+ */
362
+ isRegistered(name) {
363
+ return this.registeredTools.has(name);
364
+ }
365
+ /**
366
+ * Get names of all tools registered via WebMCP.
367
+ */
368
+ getRegisteredTools() {
369
+ return Array.from(this.registeredTools);
370
+ }
371
+ // --------------------------------------------------------------------------
372
+ // Mapping helpers
373
+ // --------------------------------------------------------------------------
374
+ /**
375
+ * Map internal ToolAnnotations to WebMCP ToolAnnotations.
376
+ * The spec currently only defines `readOnlyHint`.
377
+ */
378
+ mapAnnotations(annotations) {
379
+ if (!annotations)
380
+ return void 0;
381
+ return {
382
+ readOnlyHint: annotations.readOnlyHint
383
+ };
384
+ }
385
+ /**
386
+ * Convert internal ToolDefinition to ModelContextTool format (utility).
387
+ * Requires an execute callback to be provided separately.
388
+ */
389
+ static toModelContextTool(tool, handler) {
390
+ return {
391
+ name: tool.name,
392
+ description: tool.description ?? tool.name,
393
+ inputSchema: tool.inputSchema,
394
+ execute: async (input) => {
395
+ return handler(input);
396
+ },
397
+ annotations: tool.annotations ? { readOnlyHint: tool.annotations.readOnlyHint } : void 0
398
+ };
399
+ }
400
+ };
401
+
211
402
  // libs/mcp-worker/src/client/worker-client.ts
212
403
  var WorkerClient = class _WorkerClient {
213
404
  // Configurable worker script URLs (defaults kept for backward compatibility)
@@ -229,6 +420,8 @@ var WorkerClient = class _WorkerClient {
229
420
  initResolvers = [];
230
421
  // Tool registry for managing tool lifecycle
231
422
  toolRegistry = new ToolRegistry();
423
+ // WebMCP adapter for browser-level tool registration via navigator.modelContext
424
+ webMcpAdapter = new WebMcpAdapter();
232
425
  // Tab tracking for multi-tab support
233
426
  tabId;
234
427
  static TAB_ID_STORAGE_KEY = "mcp_fe_tab_id";
@@ -339,6 +532,7 @@ var WorkerClient = class _WorkerClient {
339
532
  logger.log(
340
533
  `[WorkerClient] Page unloading, cleaning up ${toolNames.length} tool(s)`
341
534
  );
535
+ this.webMcpAdapter.clearAll();
342
536
  toolNames.forEach((toolName) => {
343
537
  const existing = this.toolRegistry.getInfo(toolName);
344
538
  if (!existing)
@@ -383,6 +577,14 @@ var WorkerClient = class _WorkerClient {
383
577
  this.serviceWorkerUrl = opts.serviceWorkerUrl;
384
578
  if (opts.backendWsUrl)
385
579
  this.backendWsUrl = opts.backendWsUrl;
580
+ if (opts.enableWebMcp !== void 0) {
581
+ this.webMcpAdapter.setEnabled(opts.enableWebMcp);
582
+ }
583
+ }
584
+ if (this.webMcpAdapter.isAvailable()) {
585
+ logger.log(
586
+ "[WorkerClient] WebMCP: auto-enabled (navigator.modelContext detected)"
587
+ );
386
588
  }
387
589
  if (this.initPromise) {
388
590
  return this.initPromise.then(async () => {
@@ -459,6 +661,7 @@ var WorkerClient = class _WorkerClient {
459
661
  const details = this.toolRegistry.getDetails(toolName);
460
662
  if (!details)
461
663
  return;
664
+ const handler = this.toolRegistry.getHandler(toolName);
462
665
  try {
463
666
  await this.registerToolInWorker(
464
667
  details.name,
@@ -473,6 +676,22 @@ var WorkerClient = class _WorkerClient {
473
676
  title: details.title
474
677
  }
475
678
  );
679
+ if (handler) {
680
+ this.webMcpAdapter.registerTool(
681
+ details.name,
682
+ details.description,
683
+ details.inputSchema,
684
+ handler,
685
+ {
686
+ outputSchema: details.outputSchema,
687
+ annotations: details.annotations,
688
+ execution: details.execution,
689
+ _meta: details._meta,
690
+ icons: details.icons,
691
+ title: details.title
692
+ }
693
+ );
694
+ }
476
695
  } catch (error) {
477
696
  logger.error(
478
697
  `[WorkerClient] Failed to sync tool '${toolName}' to worker:`,
@@ -604,78 +823,87 @@ var WorkerClient = class _WorkerClient {
604
823
  }
605
824
  }
606
825
  async initServiceWorkerFallback() {
607
- if ("serviceWorker" in navigator) {
608
- try {
609
- const existingRegistration = await navigator.serviceWorker.getRegistration();
610
- if (existingRegistration) {
611
- this.serviceWorkerRegistration = existingRegistration;
612
- this.workerType = "service";
613
- logger.info(
614
- "[WorkerClient] Using existing ServiceWorker registration"
615
- );
616
- return;
617
- }
826
+ if (!("serviceWorker" in navigator)) {
827
+ throw new Error("Neither SharedWorker nor ServiceWorker is supported");
828
+ }
829
+ try {
830
+ const existingRegistration = await navigator.serviceWorker.getRegistration();
831
+ if (existingRegistration) {
832
+ this.serviceWorkerRegistration = existingRegistration;
833
+ this.workerType = "service";
834
+ logger.info("[WorkerClient] Using existing ServiceWorker registration");
835
+ } else {
618
836
  this.serviceWorkerRegistration = await navigator.serviceWorker.register(
619
837
  this.serviceWorkerUrl
620
838
  );
621
839
  this.workerType = "service";
622
- if ("serviceWorker" in navigator) {
623
- navigator.serviceWorker.addEventListener(
624
- "message",
625
- (ev) => {
626
- try {
627
- const data = ev.data;
628
- if (data && data.type === "CALL_TOOL") {
629
- const targetTabId = data.targetTabId;
630
- if (targetTabId && targetTabId !== this.tabId) {
631
- logger.log(
632
- `[WorkerClient] Ignoring CALL_TOOL (not for this tab): ${data.toolName}`,
633
- { targetTabId, myTabId: this.tabId }
634
- );
635
- return;
636
- }
637
- this.handleToolCall(
638
- data.toolName,
639
- data.args,
640
- data.callId
641
- ).catch((error) => {
642
- logger.error(
643
- "[WorkerClient] Failed to handle tool call:",
644
- error
645
- );
646
- });
840
+ logger.info("[WorkerClient] Using MCP ServiceWorker (fallback)");
841
+ }
842
+ navigator.serviceWorker.addEventListener(
843
+ "message",
844
+ (ev) => {
845
+ try {
846
+ const data = ev.data;
847
+ if (data && data.type === "CONNECTION_STATUS") {
848
+ const connected = !!data.connected;
849
+ this.connectionStatusCallbacks.forEach((cb) => {
850
+ try {
851
+ cb(connected);
852
+ } catch {
647
853
  }
648
- } catch (error) {
854
+ });
855
+ } else if (data && data.type === "CALL_TOOL") {
856
+ const targetTabId = data.targetTabId;
857
+ if (targetTabId && targetTabId !== this.tabId) {
858
+ logger.log(
859
+ `[WorkerClient] Ignoring CALL_TOOL (not for this tab): ${data.toolName}`,
860
+ { targetTabId, myTabId: this.tabId }
861
+ );
862
+ return;
863
+ }
864
+ this.handleToolCall(
865
+ data.toolName,
866
+ data.args,
867
+ data.callId
868
+ ).catch((error) => {
649
869
  logger.error(
650
- "[WorkerClient] Error processing ServiceWorker message:",
870
+ "[WorkerClient] Failed to handle tool call:",
651
871
  error
652
872
  );
653
- }
873
+ });
654
874
  }
655
- );
656
- }
657
- logger.info("[WorkerClient] Using MCP ServiceWorker (fallback)");
658
- try {
659
- const initMsg = {
660
- type: "INIT",
661
- backendUrl: this.backendWsUrl
662
- };
663
- if (this.pendingAuthToken)
664
- initMsg["token"] = this.pendingAuthToken;
665
- if (this.serviceWorkerRegistration.active) {
666
- this.serviceWorkerRegistration.active.postMessage(initMsg);
667
- } else if ("serviceWorker" in navigator && navigator.serviceWorker.controller) {
668
- navigator.serviceWorker.controller.postMessage(initMsg);
875
+ } catch (error) {
876
+ logger.error(
877
+ "[WorkerClient] Error processing ServiceWorker message:",
878
+ error
879
+ );
669
880
  }
881
+ }
882
+ );
883
+ try {
884
+ const initMsg = {
885
+ type: "INIT",
886
+ backendUrl: this.backendWsUrl
887
+ };
888
+ if (this.pendingAuthToken)
889
+ initMsg["token"] = this.pendingAuthToken;
890
+ const sendInit = (worker) => {
891
+ worker.postMessage(initMsg);
670
892
  this.pendingAuthToken = null;
671
- } catch {
893
+ };
894
+ if (this.serviceWorkerRegistration.active) {
895
+ sendInit(this.serviceWorkerRegistration.active);
896
+ } else {
897
+ navigator.serviceWorker.ready.then((reg) => {
898
+ if (reg.active)
899
+ sendInit(reg.active);
900
+ });
672
901
  }
673
- } catch (error) {
674
- logger.error("[WorkerClient] Failed to register ServiceWorker:", error);
675
- throw error;
902
+ } catch {
676
903
  }
677
- } else {
678
- throw new Error("Neither SharedWorker nor ServiceWorker is supported");
904
+ } catch (error) {
905
+ logger.error("[WorkerClient] Failed to register ServiceWorker:", error);
906
+ throw error;
679
907
  }
680
908
  }
681
909
  // Low-level request that expects a reply via MessageChannel
@@ -1003,6 +1231,13 @@ var WorkerClient = class _WorkerClient {
1003
1231
  }
1004
1232
  if (isNew) {
1005
1233
  await this.registerToolInWorker(name, description, inputSchema, options);
1234
+ this.webMcpAdapter.registerTool(
1235
+ name,
1236
+ description,
1237
+ inputSchema,
1238
+ handler,
1239
+ options
1240
+ );
1006
1241
  }
1007
1242
  }
1008
1243
  /**
@@ -1060,6 +1295,7 @@ var WorkerClient = class _WorkerClient {
1060
1295
  "UNREGISTER_TOOL",
1061
1296
  { name, tabId: this.tabId }
1062
1297
  );
1298
+ this.webMcpAdapter.unregisterTool(name);
1063
1299
  logger.log(`[WorkerClient] Unregistered tool '${name}'`);
1064
1300
  return workerResult?.success ?? false;
1065
1301
  }
@@ -1096,6 +1332,66 @@ var WorkerClient = class _WorkerClient {
1096
1332
  isToolRegistered(toolName) {
1097
1333
  return this.toolRegistry.isRegistered(toolName);
1098
1334
  }
1335
+ // --------------------------------------------------------------------------
1336
+ // WebMCP API
1337
+ // --------------------------------------------------------------------------
1338
+ /**
1339
+ * Check if the browser supports the WebMCP API (`navigator.modelContext`).
1340
+ */
1341
+ static isWebMcpSupported() {
1342
+ return WebMcpAdapter.isSupported();
1343
+ }
1344
+ /**
1345
+ * Check if WebMCP is both enabled AND supported.
1346
+ */
1347
+ isWebMcpAvailable() {
1348
+ return this.webMcpAdapter.isAvailable();
1349
+ }
1350
+ /**
1351
+ * Enable or disable WebMCP registration at runtime.
1352
+ * When enabled and the browser supports it, newly registered tools will also
1353
+ * be advertised via `navigator.modelContext`. Existing tools are synced immediately.
1354
+ */
1355
+ setWebMcpEnabled(enabled) {
1356
+ this.webMcpAdapter.setEnabled(enabled);
1357
+ if (enabled && WebMcpAdapter.isSupported() && this.isInitialized) {
1358
+ const toolNames = this.toolRegistry.getRegisteredTools();
1359
+ toolNames.forEach((toolName) => {
1360
+ const details = this.toolRegistry.getDetails(toolName);
1361
+ const handler = this.toolRegistry.getHandler(toolName);
1362
+ if (!details || !handler)
1363
+ return;
1364
+ this.webMcpAdapter.registerTool(
1365
+ details.name,
1366
+ details.description,
1367
+ details.inputSchema,
1368
+ handler,
1369
+ {
1370
+ outputSchema: details.outputSchema,
1371
+ annotations: details.annotations,
1372
+ execution: details.execution,
1373
+ _meta: details._meta,
1374
+ icons: details.icons,
1375
+ title: details.title
1376
+ }
1377
+ );
1378
+ });
1379
+ } else if (!enabled) {
1380
+ this.webMcpAdapter.clearAll();
1381
+ }
1382
+ }
1383
+ /**
1384
+ * Check if a specific tool is registered via the WebMCP API.
1385
+ */
1386
+ isToolRegisteredViaWebMcp(toolName) {
1387
+ return this.webMcpAdapter.isRegistered(toolName);
1388
+ }
1389
+ /**
1390
+ * Get names of tools registered via the WebMCP API.
1391
+ */
1392
+ getWebMcpRegisteredTools() {
1393
+ return this.webMcpAdapter.getRegisteredTools();
1394
+ }
1099
1395
  /**
1100
1396
  * Handle tool call from worker - execute handler in main thread and return result
1101
1397
  * @private
@@ -1235,6 +1531,7 @@ async function queryEvents(filters) {
1235
1531
  });
1236
1532
  }
1237
1533
  export {
1534
+ WebMcpAdapter,
1238
1535
  WorkerClient,
1239
1536
  logger,
1240
1537
  queryEvents,
@@ -21357,14 +21357,24 @@ var MCPController = class _MCPController {
21357
21357
  this.socket = null;
21358
21358
  }
21359
21359
  return new Promise((resolve) => {
21360
- const url2 = this.authToken ? `${this.backendUrl}?token=${this.authToken}` : this.backendUrl;
21361
- this.socket = new WebSocket(url2);
21360
+ this.socket = new WebSocket(this.backendUrl);
21362
21361
  this.socket.onopen = async () => {
21363
21362
  logger.log("[MCPController] Connected to backend MCP server");
21364
21363
  this.reconnectAttempts = 0;
21365
21364
  this.isReconnectingForToken = false;
21366
21365
  try {
21367
21366
  if (this.socket) {
21367
+ if (this.authToken) {
21368
+ try {
21369
+ await this.performAuthHandshake(this.socket, this.authToken);
21370
+ } catch (error2) {
21371
+ logger.error("[MCPController] Auth handshake failed:", error2);
21372
+ this.broadcastFn({ type: "CONNECTION_STATUS", connected: false });
21373
+ this.socket.close(4001, "Authentication failed");
21374
+ resolve();
21375
+ return;
21376
+ }
21377
+ }
21368
21378
  this.transport = new WebSocketTransport(this.socket);
21369
21379
  if (typeof this.transport.start === "function") {
21370
21380
  try {
@@ -21667,6 +21677,37 @@ var MCPController = class _MCPController {
21667
21677
  }
21668
21678
  return true;
21669
21679
  }
21680
+ /**
21681
+ * Sends AUTH message and waits for AUTH_OK before MCP transport is started.
21682
+ * Token is never sent in the URL — only in this initial payload message.
21683
+ */
21684
+ performAuthHandshake(socket, token) {
21685
+ return new Promise((resolve, reject) => {
21686
+ const timeout = setTimeout(() => {
21687
+ socket.removeEventListener("message", handleMessage);
21688
+ reject(new Error("Authentication timeout"));
21689
+ }, 1e4);
21690
+ const handleMessage = (event) => {
21691
+ let msg;
21692
+ try {
21693
+ msg = JSON.parse(event.data);
21694
+ } catch {
21695
+ return;
21696
+ }
21697
+ if (msg.type === "AUTH_OK") {
21698
+ clearTimeout(timeout);
21699
+ socket.removeEventListener("message", handleMessage);
21700
+ resolve();
21701
+ } else if (msg.type === "AUTH_ERROR") {
21702
+ clearTimeout(timeout);
21703
+ socket.removeEventListener("message", handleMessage);
21704
+ reject(new Error(msg.message || "Authentication rejected by server"));
21705
+ }
21706
+ };
21707
+ socket.addEventListener("message", handleMessage);
21708
+ socket.send(JSON.stringify({ type: "AUTH", token }));
21709
+ });
21710
+ }
21670
21711
  getConnectionStatus() {
21671
21712
  return this.socket?.readyState === WebSocket.OPEN;
21672
21713
  }
@@ -21357,14 +21357,24 @@ var MCPController = class _MCPController {
21357
21357
  this.socket = null;
21358
21358
  }
21359
21359
  return new Promise((resolve) => {
21360
- const url2 = this.authToken ? `${this.backendUrl}?token=${this.authToken}` : this.backendUrl;
21361
- this.socket = new WebSocket(url2);
21360
+ this.socket = new WebSocket(this.backendUrl);
21362
21361
  this.socket.onopen = async () => {
21363
21362
  logger.log("[MCPController] Connected to backend MCP server");
21364
21363
  this.reconnectAttempts = 0;
21365
21364
  this.isReconnectingForToken = false;
21366
21365
  try {
21367
21366
  if (this.socket) {
21367
+ if (this.authToken) {
21368
+ try {
21369
+ await this.performAuthHandshake(this.socket, this.authToken);
21370
+ } catch (error2) {
21371
+ logger.error("[MCPController] Auth handshake failed:", error2);
21372
+ this.broadcastFn({ type: "CONNECTION_STATUS", connected: false });
21373
+ this.socket.close(4001, "Authentication failed");
21374
+ resolve();
21375
+ return;
21376
+ }
21377
+ }
21368
21378
  this.transport = new WebSocketTransport(this.socket);
21369
21379
  if (typeof this.transport.start === "function") {
21370
21380
  try {
@@ -21667,6 +21677,37 @@ var MCPController = class _MCPController {
21667
21677
  }
21668
21678
  return true;
21669
21679
  }
21680
+ /**
21681
+ * Sends AUTH message and waits for AUTH_OK before MCP transport is started.
21682
+ * Token is never sent in the URL — only in this initial payload message.
21683
+ */
21684
+ performAuthHandshake(socket, token) {
21685
+ return new Promise((resolve, reject) => {
21686
+ const timeout = setTimeout(() => {
21687
+ socket.removeEventListener("message", handleMessage);
21688
+ reject(new Error("Authentication timeout"));
21689
+ }, 1e4);
21690
+ const handleMessage = (event) => {
21691
+ let msg;
21692
+ try {
21693
+ msg = JSON.parse(event.data);
21694
+ } catch {
21695
+ return;
21696
+ }
21697
+ if (msg.type === "AUTH_OK") {
21698
+ clearTimeout(timeout);
21699
+ socket.removeEventListener("message", handleMessage);
21700
+ resolve();
21701
+ } else if (msg.type === "AUTH_ERROR") {
21702
+ clearTimeout(timeout);
21703
+ socket.removeEventListener("message", handleMessage);
21704
+ reject(new Error(msg.message || "Authentication rejected by server"));
21705
+ }
21706
+ };
21707
+ socket.addEventListener("message", handleMessage);
21708
+ socket.send(JSON.stringify({ type: "AUTH", token }));
21709
+ });
21710
+ }
21670
21711
  getConnectionStatus() {
21671
21712
  return this.socket?.readyState === WebSocket.OPEN;
21672
21713
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@mcp-fe/mcp-worker",
3
- "version": "0.1.11",
3
+ "version": "0.2.2",
4
4
  "license": "Apache-2.0",
5
5
  "homepage": "https://mcp-fe.ai",
6
6
  "repository": {
@@ -3,6 +3,8 @@
3
3
  * Use this in your application code
4
4
  */
5
5
  export { WorkerClient, type WorkerClientInitOptions } from './worker-client';
6
+ export { WebMcpAdapter } from './web-mcp-adapter';
7
+ export type { ModelContext, ModelContextTool, ModelContextOptions, ModelContextClient, ToolExecuteCallback, UserInteractionCallback, WebMcpToolAnnotations, } from './web-mcp-types';
6
8
  export type { ToolHandler, ToolDefinition, Icon, ToolAnnotations, ToolExecution, UserEvent, EventFilters, TabInfo, } from '../shared/types';
7
9
  export { logger } from '../shared/logger';
8
10
  import { WorkerClient } from './worker-client';
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../../libs/mcp-worker/src/client/index.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,EAAE,YAAY,EAAE,KAAK,uBAAuB,EAAE,MAAM,iBAAiB,CAAC;AAG7E,YAAY,EACV,WAAW,EACX,cAAc,EACd,IAAI,EACJ,eAAe,EACf,aAAa,EACb,SAAS,EACT,YAAY,EACZ,OAAO,GACR,MAAM,iBAAiB,CAAC;AAGzB,OAAO,EAAE,MAAM,EAAE,MAAM,kBAAkB,CAAC;AAG1C,OAAO,EAAE,YAAY,EAAE,MAAM,iBAAiB,CAAC;AAC/C,eAAO,MAAM,YAAY,cAAqB,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../../libs/mcp-worker/src/client/index.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,EAAE,YAAY,EAAE,KAAK,uBAAuB,EAAE,MAAM,iBAAiB,CAAC;AAG7E,OAAO,EAAE,aAAa,EAAE,MAAM,mBAAmB,CAAC;AAClD,YAAY,EACV,YAAY,EACZ,gBAAgB,EAChB,mBAAmB,EACnB,kBAAkB,EAClB,mBAAmB,EACnB,uBAAuB,EACvB,qBAAqB,GACtB,MAAM,iBAAiB,CAAC;AAGzB,YAAY,EACV,WAAW,EACX,cAAc,EACd,IAAI,EACJ,eAAe,EACf,aAAa,EACb,SAAS,EACT,YAAY,EACZ,OAAO,GACR,MAAM,iBAAiB,CAAC;AAGzB,OAAO,EAAE,MAAM,EAAE,MAAM,kBAAkB,CAAC;AAG1C,OAAO,EAAE,YAAY,EAAE,MAAM,iBAAiB,CAAC;AAC/C,eAAO,MAAM,YAAY,cAAqB,CAAC"}