@mcp-fe/mcp-worker 0.0.17 → 0.1.1
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 +184 -349
- package/docs/api.md +418 -0
- package/docs/architecture.md +195 -0
- package/docs/guide.md +454 -0
- package/docs/index.md +109 -0
- package/docs/initialization.md +188 -0
- package/docs/worker-details.md +435 -0
- package/index.js +365 -5
- package/mcp-service-worker.js +505 -204
- package/mcp-shared-worker.js +487 -173
- package/package.json +1 -1
- package/src/index.d.ts +2 -1
- package/src/index.d.ts.map +1 -1
- package/src/lib/built-in-tools.d.ts +9 -0
- package/src/lib/built-in-tools.d.ts.map +1 -0
- package/src/lib/mcp-controller.d.ts +18 -0
- package/src/lib/mcp-controller.d.ts.map +1 -1
- package/src/lib/mcp-server.d.ts +11 -0
- package/src/lib/mcp-server.d.ts.map +1 -1
- package/src/lib/tool-registry.d.ts +28 -0
- package/src/lib/tool-registry.d.ts.map +1 -0
- package/src/lib/worker-client.d.ts +123 -0
- package/src/lib/worker-client.d.ts.map +1 -1
package/mcp-service-worker.js
CHANGED
|
@@ -27614,185 +27614,241 @@ var Server = class extends Protocol {
|
|
|
27614
27614
|
}
|
|
27615
27615
|
};
|
|
27616
27616
|
|
|
27617
|
-
// libs/mcp-worker/src/lib/
|
|
27618
|
-
var
|
|
27617
|
+
// libs/mcp-worker/src/lib/tool-registry.ts
|
|
27618
|
+
var ToolRegistry = class {
|
|
27619
|
+
tools = /* @__PURE__ */ new Map();
|
|
27620
|
+
handlers = /* @__PURE__ */ new Map();
|
|
27621
|
+
register(definition, handler) {
|
|
27622
|
+
this.tools.set(definition.name, definition);
|
|
27623
|
+
this.handlers.set(definition.name, handler);
|
|
27624
|
+
}
|
|
27625
|
+
unregister(name) {
|
|
27626
|
+
const deleted = this.tools.delete(name);
|
|
27627
|
+
this.handlers.delete(name);
|
|
27628
|
+
return deleted;
|
|
27629
|
+
}
|
|
27630
|
+
getTools() {
|
|
27631
|
+
return Array.from(this.tools.values());
|
|
27632
|
+
}
|
|
27633
|
+
getHandler(name) {
|
|
27634
|
+
return this.handlers.get(name);
|
|
27635
|
+
}
|
|
27636
|
+
clear() {
|
|
27637
|
+
this.tools.clear();
|
|
27638
|
+
this.handlers.clear();
|
|
27639
|
+
}
|
|
27640
|
+
};
|
|
27641
|
+
var toolRegistry = new ToolRegistry();
|
|
27642
|
+
|
|
27643
|
+
// libs/mcp-worker/src/lib/built-in-tools.ts
|
|
27644
|
+
var builtInTools = [
|
|
27645
|
+
// get_user_events tool
|
|
27619
27646
|
{
|
|
27620
|
-
|
|
27621
|
-
|
|
27647
|
+
definition: {
|
|
27648
|
+
name: "get_user_events",
|
|
27649
|
+
description: "Get user activity events (navigation, clicks, etc.)",
|
|
27650
|
+
inputSchema: {
|
|
27651
|
+
type: "object",
|
|
27652
|
+
properties: {
|
|
27653
|
+
type: {
|
|
27654
|
+
type: "string",
|
|
27655
|
+
enum: ["navigation", "click", "input", "custom"],
|
|
27656
|
+
description: "Filter by event type"
|
|
27657
|
+
},
|
|
27658
|
+
startTime: {
|
|
27659
|
+
type: "number",
|
|
27660
|
+
description: "Start timestamp (Unix timestamp in milliseconds)"
|
|
27661
|
+
},
|
|
27662
|
+
endTime: {
|
|
27663
|
+
type: "number",
|
|
27664
|
+
description: "End timestamp (Unix timestamp in milliseconds)"
|
|
27665
|
+
},
|
|
27666
|
+
path: {
|
|
27667
|
+
type: "string",
|
|
27668
|
+
description: "Filter by path/URL"
|
|
27669
|
+
},
|
|
27670
|
+
limit: {
|
|
27671
|
+
type: "number",
|
|
27672
|
+
description: "Maximum number of events to return",
|
|
27673
|
+
default: 100
|
|
27674
|
+
}
|
|
27675
|
+
}
|
|
27676
|
+
}
|
|
27677
|
+
},
|
|
27678
|
+
handler: async (args) => {
|
|
27679
|
+
const schema = external_exports3.object({
|
|
27680
|
+
type: external_exports3.enum(["navigation", "click", "input", "custom"]).optional(),
|
|
27681
|
+
startTime: external_exports3.number().optional(),
|
|
27682
|
+
endTime: external_exports3.number().optional(),
|
|
27683
|
+
path: external_exports3.string().optional(),
|
|
27684
|
+
limit: external_exports3.number().optional().default(100)
|
|
27685
|
+
});
|
|
27686
|
+
const validatedArgs = schema.parse(args || {});
|
|
27687
|
+
const events = await queryEvents(validatedArgs);
|
|
27688
|
+
return {
|
|
27689
|
+
content: [
|
|
27690
|
+
{
|
|
27691
|
+
type: "text",
|
|
27692
|
+
text: JSON.stringify({ events }, null, 2)
|
|
27693
|
+
}
|
|
27694
|
+
]
|
|
27695
|
+
};
|
|
27696
|
+
}
|
|
27622
27697
|
},
|
|
27698
|
+
// get_navigation_history tool
|
|
27623
27699
|
{
|
|
27624
|
-
|
|
27625
|
-
|
|
27626
|
-
|
|
27627
|
-
|
|
27628
|
-
|
|
27629
|
-
|
|
27630
|
-
|
|
27631
|
-
|
|
27632
|
-
|
|
27633
|
-
|
|
27634
|
-
description: "Get user activity events (navigation, clicks, etc.)",
|
|
27635
|
-
inputSchema: {
|
|
27636
|
-
type: "object",
|
|
27637
|
-
properties: {
|
|
27638
|
-
type: {
|
|
27639
|
-
type: "string",
|
|
27640
|
-
enum: ["navigation", "click", "input", "custom"],
|
|
27641
|
-
description: "Filter by event type"
|
|
27642
|
-
},
|
|
27643
|
-
startTime: {
|
|
27644
|
-
type: "number",
|
|
27645
|
-
description: "Start timestamp (Unix timestamp in milliseconds)"
|
|
27646
|
-
},
|
|
27647
|
-
endTime: {
|
|
27648
|
-
type: "number",
|
|
27649
|
-
description: "End timestamp (Unix timestamp in milliseconds)"
|
|
27650
|
-
},
|
|
27651
|
-
path: {
|
|
27652
|
-
type: "string",
|
|
27653
|
-
description: "Filter by path/URL"
|
|
27654
|
-
},
|
|
27655
|
-
limit: {
|
|
27656
|
-
type: "number",
|
|
27657
|
-
description: "Maximum number of events to return",
|
|
27658
|
-
default: 100
|
|
27659
|
-
}
|
|
27700
|
+
definition: {
|
|
27701
|
+
name: "get_navigation_history",
|
|
27702
|
+
description: "Get user navigation history",
|
|
27703
|
+
inputSchema: {
|
|
27704
|
+
type: "object",
|
|
27705
|
+
properties: {
|
|
27706
|
+
limit: {
|
|
27707
|
+
type: "number",
|
|
27708
|
+
description: "Maximum number of navigation events to return",
|
|
27709
|
+
default: 50
|
|
27660
27710
|
}
|
|
27661
27711
|
}
|
|
27662
|
-
}
|
|
27663
|
-
|
|
27664
|
-
|
|
27665
|
-
|
|
27666
|
-
|
|
27667
|
-
|
|
27668
|
-
|
|
27669
|
-
|
|
27670
|
-
|
|
27671
|
-
|
|
27672
|
-
|
|
27673
|
-
|
|
27712
|
+
}
|
|
27713
|
+
},
|
|
27714
|
+
handler: async (args) => {
|
|
27715
|
+
const schema = external_exports3.object({
|
|
27716
|
+
limit: external_exports3.number().optional().default(50)
|
|
27717
|
+
});
|
|
27718
|
+
const validatedArgs = schema.parse(args || {});
|
|
27719
|
+
const events = await queryEvents({
|
|
27720
|
+
type: "navigation",
|
|
27721
|
+
limit: validatedArgs.limit
|
|
27722
|
+
});
|
|
27723
|
+
return {
|
|
27724
|
+
content: [
|
|
27725
|
+
{
|
|
27726
|
+
type: "text",
|
|
27727
|
+
text: JSON.stringify(
|
|
27728
|
+
{
|
|
27729
|
+
navigationHistory: events.map((e) => ({
|
|
27730
|
+
from: e.from,
|
|
27731
|
+
to: e.to,
|
|
27732
|
+
path: e.path,
|
|
27733
|
+
timestamp: e.timestamp
|
|
27734
|
+
}))
|
|
27735
|
+
},
|
|
27736
|
+
null,
|
|
27737
|
+
2
|
|
27738
|
+
)
|
|
27674
27739
|
}
|
|
27675
|
-
|
|
27676
|
-
}
|
|
27677
|
-
|
|
27678
|
-
|
|
27679
|
-
|
|
27680
|
-
|
|
27681
|
-
|
|
27682
|
-
|
|
27683
|
-
|
|
27684
|
-
|
|
27685
|
-
|
|
27686
|
-
|
|
27687
|
-
|
|
27688
|
-
|
|
27689
|
-
|
|
27690
|
-
|
|
27691
|
-
|
|
27740
|
+
]
|
|
27741
|
+
};
|
|
27742
|
+
}
|
|
27743
|
+
},
|
|
27744
|
+
// get_click_events tool
|
|
27745
|
+
{
|
|
27746
|
+
definition: {
|
|
27747
|
+
name: "get_click_events",
|
|
27748
|
+
description: "Get user click events",
|
|
27749
|
+
inputSchema: {
|
|
27750
|
+
type: "object",
|
|
27751
|
+
properties: {
|
|
27752
|
+
element: {
|
|
27753
|
+
type: "string",
|
|
27754
|
+
description: "Filter by element selector or text"
|
|
27755
|
+
},
|
|
27756
|
+
limit: {
|
|
27757
|
+
type: "number",
|
|
27758
|
+
description: "Maximum number of click events to return",
|
|
27759
|
+
default: 100
|
|
27692
27760
|
}
|
|
27693
27761
|
}
|
|
27694
27762
|
}
|
|
27695
|
-
|
|
27696
|
-
|
|
27697
|
-
|
|
27698
|
-
|
|
27699
|
-
|
|
27700
|
-
|
|
27701
|
-
|
|
27702
|
-
|
|
27703
|
-
|
|
27704
|
-
|
|
27705
|
-
|
|
27706
|
-
|
|
27707
|
-
|
|
27708
|
-
|
|
27709
|
-
|
|
27710
|
-
|
|
27711
|
-
|
|
27712
|
-
const events = await queryEvents(validatedArgs);
|
|
27713
|
-
return {
|
|
27714
|
-
content: [
|
|
27715
|
-
{
|
|
27716
|
-
type: "text",
|
|
27717
|
-
text: JSON.stringify({ events }, null, 2)
|
|
27718
|
-
}
|
|
27719
|
-
]
|
|
27720
|
-
};
|
|
27763
|
+
},
|
|
27764
|
+
handler: async (args) => {
|
|
27765
|
+
const schema = external_exports3.object({
|
|
27766
|
+
element: external_exports3.string().optional(),
|
|
27767
|
+
limit: external_exports3.number().optional().default(100)
|
|
27768
|
+
});
|
|
27769
|
+
const validatedArgs = schema.parse(args || {});
|
|
27770
|
+
const events = await queryEvents({
|
|
27771
|
+
type: "click",
|
|
27772
|
+
limit: validatedArgs.limit
|
|
27773
|
+
});
|
|
27774
|
+
let filteredEvents = events;
|
|
27775
|
+
if (validatedArgs.element) {
|
|
27776
|
+
const elementFilter = validatedArgs.element.toLowerCase();
|
|
27777
|
+
filteredEvents = events.filter(
|
|
27778
|
+
(e) => e.element?.toLowerCase().includes(elementFilter) || e.elementText?.toLowerCase().includes(elementFilter) || e.elementId?.toLowerCase().includes(elementFilter) || e.elementClass?.toLowerCase().includes(elementFilter)
|
|
27779
|
+
);
|
|
27721
27780
|
}
|
|
27722
|
-
|
|
27723
|
-
|
|
27724
|
-
|
|
27725
|
-
|
|
27726
|
-
|
|
27727
|
-
|
|
27728
|
-
|
|
27729
|
-
|
|
27730
|
-
|
|
27731
|
-
|
|
27732
|
-
|
|
27733
|
-
|
|
27734
|
-
|
|
27735
|
-
|
|
27736
|
-
|
|
27737
|
-
|
|
27738
|
-
|
|
27739
|
-
|
|
27740
|
-
|
|
27741
|
-
|
|
27742
|
-
|
|
27743
|
-
|
|
27744
|
-
|
|
27745
|
-
|
|
27746
|
-
|
|
27747
|
-
|
|
27748
|
-
|
|
27749
|
-
|
|
27781
|
+
return {
|
|
27782
|
+
content: [
|
|
27783
|
+
{
|
|
27784
|
+
type: "text",
|
|
27785
|
+
text: JSON.stringify(
|
|
27786
|
+
{
|
|
27787
|
+
clickEvents: filteredEvents.map((e) => ({
|
|
27788
|
+
element: e.element,
|
|
27789
|
+
elementId: e.elementId,
|
|
27790
|
+
elementClass: e.elementClass,
|
|
27791
|
+
elementText: e.elementText,
|
|
27792
|
+
path: e.path,
|
|
27793
|
+
timestamp: e.timestamp,
|
|
27794
|
+
metadata: e.metadata
|
|
27795
|
+
}))
|
|
27796
|
+
},
|
|
27797
|
+
null,
|
|
27798
|
+
2
|
|
27799
|
+
)
|
|
27800
|
+
}
|
|
27801
|
+
]
|
|
27802
|
+
};
|
|
27803
|
+
}
|
|
27804
|
+
}
|
|
27805
|
+
];
|
|
27806
|
+
function registerBuiltInTools() {
|
|
27807
|
+
builtInTools.forEach(({ definition, handler }) => {
|
|
27808
|
+
toolRegistry.register(definition, handler);
|
|
27809
|
+
});
|
|
27810
|
+
}
|
|
27811
|
+
|
|
27812
|
+
// libs/mcp-worker/src/lib/mcp-server.ts
|
|
27813
|
+
function createMCPServer(options = {}) {
|
|
27814
|
+
const {
|
|
27815
|
+
name = "mcp-worker-server",
|
|
27816
|
+
version: version2 = "1.0.0",
|
|
27817
|
+
autoRegisterBuiltInTools = true
|
|
27818
|
+
} = options;
|
|
27819
|
+
if (autoRegisterBuiltInTools) {
|
|
27820
|
+
registerBuiltInTools();
|
|
27821
|
+
}
|
|
27822
|
+
const server = new Server(
|
|
27823
|
+
{
|
|
27824
|
+
name,
|
|
27825
|
+
version: version2
|
|
27826
|
+
},
|
|
27827
|
+
{
|
|
27828
|
+
capabilities: {
|
|
27829
|
+
tools: {}
|
|
27750
27830
|
}
|
|
27751
|
-
|
|
27752
|
-
|
|
27753
|
-
|
|
27754
|
-
|
|
27755
|
-
|
|
27756
|
-
|
|
27757
|
-
|
|
27758
|
-
|
|
27759
|
-
|
|
27760
|
-
|
|
27761
|
-
|
|
27762
|
-
|
|
27763
|
-
|
|
27764
|
-
|
|
27765
|
-
(e) => e.element?.toLowerCase().includes(elementFilter) || e.elementText?.toLowerCase().includes(elementFilter) || e.elementId?.toLowerCase().includes(elementFilter) || e.elementClass?.toLowerCase().includes(elementFilter)
|
|
27766
|
-
);
|
|
27767
|
-
}
|
|
27768
|
-
return {
|
|
27769
|
-
content: [
|
|
27770
|
-
{
|
|
27771
|
-
type: "text",
|
|
27772
|
-
text: JSON.stringify(
|
|
27773
|
-
{
|
|
27774
|
-
clickEvents: filteredEvents.map((e) => ({
|
|
27775
|
-
element: e.element,
|
|
27776
|
-
elementId: e.elementId,
|
|
27777
|
-
elementClass: e.elementClass,
|
|
27778
|
-
elementText: e.elementText,
|
|
27779
|
-
path: e.path,
|
|
27780
|
-
timestamp: e.timestamp,
|
|
27781
|
-
metadata: e.metadata
|
|
27782
|
-
}))
|
|
27783
|
-
},
|
|
27784
|
-
null,
|
|
27785
|
-
2
|
|
27786
|
-
)
|
|
27787
|
-
}
|
|
27788
|
-
]
|
|
27789
|
-
};
|
|
27831
|
+
}
|
|
27832
|
+
);
|
|
27833
|
+
server.setRequestHandler(ListToolsRequestSchema, async () => {
|
|
27834
|
+
return {
|
|
27835
|
+
tools: toolRegistry.getTools()
|
|
27836
|
+
};
|
|
27837
|
+
});
|
|
27838
|
+
server.setRequestHandler(
|
|
27839
|
+
CallToolRequestSchema,
|
|
27840
|
+
async (request) => {
|
|
27841
|
+
const { name: name2, arguments: args } = request.params;
|
|
27842
|
+
const handler = toolRegistry.getHandler(name2);
|
|
27843
|
+
if (!handler) {
|
|
27844
|
+
throw new Error(`Unknown tool: ${name2}`);
|
|
27790
27845
|
}
|
|
27791
|
-
|
|
27792
|
-
throw new Error(`Unknown tool: ${name}`);
|
|
27846
|
+
return await handler(args);
|
|
27793
27847
|
}
|
|
27794
|
-
|
|
27795
|
-
|
|
27848
|
+
);
|
|
27849
|
+
return server;
|
|
27850
|
+
}
|
|
27851
|
+
var mcpServer = createMCPServer();
|
|
27796
27852
|
|
|
27797
27853
|
// libs/mcp-worker/src/lib/websocket-transport.ts
|
|
27798
27854
|
var WebSocketTransport = class {
|
|
@@ -27872,6 +27928,9 @@ var MCPController = class _MCPController {
|
|
|
27872
27928
|
keepAliveInterval = null;
|
|
27873
27929
|
requireAuth;
|
|
27874
27930
|
isReconnectingForToken = false;
|
|
27931
|
+
// Queue for tool registrations that arrive before MCP server is ready
|
|
27932
|
+
pendingToolRegistrations = [];
|
|
27933
|
+
isMCPServerReady = false;
|
|
27875
27934
|
startKeepAlive() {
|
|
27876
27935
|
if (this.keepAliveInterval) {
|
|
27877
27936
|
clearInterval(this.keepAliveInterval);
|
|
@@ -27938,6 +27997,8 @@ var MCPController = class _MCPController {
|
|
|
27938
27997
|
logger.log(
|
|
27939
27998
|
"[MCPController] MCP Server connected to WebSocket transport"
|
|
27940
27999
|
);
|
|
28000
|
+
this.isMCPServerReady = true;
|
|
28001
|
+
this.processPendingToolRegistrations();
|
|
27941
28002
|
this.startKeepAlive();
|
|
27942
28003
|
this.broadcastFn({ type: "CONNECTION_STATUS", connected: true });
|
|
27943
28004
|
resolve();
|
|
@@ -28016,6 +28077,129 @@ var MCPController = class _MCPController {
|
|
|
28016
28077
|
async handleGetEvents() {
|
|
28017
28078
|
return queryEvents({ limit: 50 });
|
|
28018
28079
|
}
|
|
28080
|
+
/**
|
|
28081
|
+
* Process pending tool registrations after MCP server is ready
|
|
28082
|
+
* @private
|
|
28083
|
+
*/
|
|
28084
|
+
processPendingToolRegistrations() {
|
|
28085
|
+
if (this.pendingToolRegistrations.length === 0)
|
|
28086
|
+
return;
|
|
28087
|
+
logger.log(
|
|
28088
|
+
`[MCPController] Processing ${this.pendingToolRegistrations.length} pending tool registrations`
|
|
28089
|
+
);
|
|
28090
|
+
const pending = [...this.pendingToolRegistrations];
|
|
28091
|
+
this.pendingToolRegistrations = [];
|
|
28092
|
+
pending.forEach(async ({ toolData, resolve, reject }) => {
|
|
28093
|
+
try {
|
|
28094
|
+
await this.handleRegisterToolInternal(toolData);
|
|
28095
|
+
resolve();
|
|
28096
|
+
} catch (error48) {
|
|
28097
|
+
reject(error48 instanceof Error ? error48 : new Error(String(error48)));
|
|
28098
|
+
}
|
|
28099
|
+
});
|
|
28100
|
+
}
|
|
28101
|
+
async handleRegisterTool(toolData) {
|
|
28102
|
+
if (!this.isMCPServerReady) {
|
|
28103
|
+
logger.log(
|
|
28104
|
+
`[MCPController] Queueing tool registration '${toolData["name"]}' (MCP server not ready yet)`
|
|
28105
|
+
);
|
|
28106
|
+
return new Promise((resolve, reject) => {
|
|
28107
|
+
this.pendingToolRegistrations.push({
|
|
28108
|
+
toolData,
|
|
28109
|
+
resolve,
|
|
28110
|
+
reject
|
|
28111
|
+
});
|
|
28112
|
+
});
|
|
28113
|
+
}
|
|
28114
|
+
return this.handleRegisterToolInternal(toolData);
|
|
28115
|
+
}
|
|
28116
|
+
/**
|
|
28117
|
+
* Internal method to register tool (assumes MCP server is ready)
|
|
28118
|
+
* @private
|
|
28119
|
+
*/
|
|
28120
|
+
async handleRegisterToolInternal(toolData) {
|
|
28121
|
+
const name = toolData["name"];
|
|
28122
|
+
const description = toolData["description"];
|
|
28123
|
+
const inputSchema = toolData["inputSchema"];
|
|
28124
|
+
const handlerType = toolData["handlerType"];
|
|
28125
|
+
if (!name || !description || !inputSchema) {
|
|
28126
|
+
throw new Error(
|
|
28127
|
+
"Missing required tool fields: name, description, inputSchema"
|
|
28128
|
+
);
|
|
28129
|
+
}
|
|
28130
|
+
if (handlerType !== "proxy") {
|
|
28131
|
+
throw new Error(
|
|
28132
|
+
`Unsupported handler type: ${handlerType}. Only 'proxy' handlers are supported.`
|
|
28133
|
+
);
|
|
28134
|
+
}
|
|
28135
|
+
const handler = async (args) => {
|
|
28136
|
+
const callId = `call_${Date.now()}_${Math.random().toString(36).substring(2, 9)}`;
|
|
28137
|
+
logger.log(`[MCPController] Proxying tool call to main thread: ${name}`, {
|
|
28138
|
+
callId,
|
|
28139
|
+
args
|
|
28140
|
+
});
|
|
28141
|
+
return new Promise((resolve, reject) => {
|
|
28142
|
+
const pendingCall = {
|
|
28143
|
+
resolve,
|
|
28144
|
+
reject,
|
|
28145
|
+
timeout: setTimeout(() => {
|
|
28146
|
+
reject(new Error(`Tool call timeout: ${name}`));
|
|
28147
|
+
}, 3e4)
|
|
28148
|
+
// 30 second timeout
|
|
28149
|
+
};
|
|
28150
|
+
if (!this.pendingToolCalls) {
|
|
28151
|
+
this.pendingToolCalls = /* @__PURE__ */ new Map();
|
|
28152
|
+
}
|
|
28153
|
+
this.pendingToolCalls.set(callId, pendingCall);
|
|
28154
|
+
this.broadcastFn({
|
|
28155
|
+
type: "CALL_TOOL",
|
|
28156
|
+
toolName: name,
|
|
28157
|
+
args,
|
|
28158
|
+
callId
|
|
28159
|
+
});
|
|
28160
|
+
});
|
|
28161
|
+
};
|
|
28162
|
+
toolRegistry.register(
|
|
28163
|
+
{
|
|
28164
|
+
name,
|
|
28165
|
+
description,
|
|
28166
|
+
inputSchema
|
|
28167
|
+
},
|
|
28168
|
+
handler
|
|
28169
|
+
);
|
|
28170
|
+
logger.log(
|
|
28171
|
+
`[MCPController] Registered proxy tool: ${name} (forwards to main thread)`
|
|
28172
|
+
);
|
|
28173
|
+
}
|
|
28174
|
+
pendingToolCalls;
|
|
28175
|
+
handleToolCallResult(callId, result) {
|
|
28176
|
+
if (!this.pendingToolCalls)
|
|
28177
|
+
return;
|
|
28178
|
+
const pendingCall = this.pendingToolCalls.get(callId);
|
|
28179
|
+
if (!pendingCall) {
|
|
28180
|
+
logger.warn(
|
|
28181
|
+
`[MCPController] Received result for unknown call: ${callId}`
|
|
28182
|
+
);
|
|
28183
|
+
return;
|
|
28184
|
+
}
|
|
28185
|
+
clearTimeout(pendingCall.timeout);
|
|
28186
|
+
this.pendingToolCalls.delete(callId);
|
|
28187
|
+
const resultData = result;
|
|
28188
|
+
if (resultData.success && resultData.result) {
|
|
28189
|
+
pendingCall.resolve(resultData.result);
|
|
28190
|
+
} else {
|
|
28191
|
+
pendingCall.reject(new Error(resultData.error || "Tool call failed"));
|
|
28192
|
+
}
|
|
28193
|
+
}
|
|
28194
|
+
async handleUnregisterTool(toolName) {
|
|
28195
|
+
const success2 = toolRegistry.unregister(toolName);
|
|
28196
|
+
if (success2) {
|
|
28197
|
+
logger.log(`[MCPController] Unregistered tool: ${toolName}`);
|
|
28198
|
+
} else {
|
|
28199
|
+
logger.log(`[MCPController] Tool not found: ${toolName}`);
|
|
28200
|
+
}
|
|
28201
|
+
return success2;
|
|
28202
|
+
}
|
|
28019
28203
|
getConnectionStatus() {
|
|
28020
28204
|
return this.socket?.readyState === WebSocket.OPEN;
|
|
28021
28205
|
}
|
|
@@ -28056,11 +28240,17 @@ var setBackendUrl = (url2) => {
|
|
|
28056
28240
|
try {
|
|
28057
28241
|
client.postMessage(message);
|
|
28058
28242
|
} catch (e) {
|
|
28059
|
-
logger.error(
|
|
28243
|
+
logger.error(
|
|
28244
|
+
"[ServiceWorker] Failed to post message to client:",
|
|
28245
|
+
e
|
|
28246
|
+
);
|
|
28060
28247
|
}
|
|
28061
28248
|
});
|
|
28062
28249
|
}).catch((err) => {
|
|
28063
|
-
logger.error(
|
|
28250
|
+
logger.error(
|
|
28251
|
+
"[ServiceWorker] Failed to match clients for broadcast:",
|
|
28252
|
+
err
|
|
28253
|
+
);
|
|
28064
28254
|
});
|
|
28065
28255
|
});
|
|
28066
28256
|
return controller;
|
|
@@ -28105,64 +28295,175 @@ self.addEventListener("message", async (event) => {
|
|
|
28105
28295
|
return;
|
|
28106
28296
|
}
|
|
28107
28297
|
if (msg["type"] === "STORE_EVENT") {
|
|
28108
|
-
event.waitUntil(
|
|
28109
|
-
|
|
28110
|
-
|
|
28298
|
+
event.waitUntil(
|
|
28299
|
+
(async () => {
|
|
28300
|
+
try {
|
|
28301
|
+
if (!backendUrl || !controller) {
|
|
28302
|
+
if (event.ports && event.ports[0]) {
|
|
28303
|
+
event.ports[0].postMessage({
|
|
28304
|
+
success: false,
|
|
28305
|
+
error: "Worker not initialized"
|
|
28306
|
+
});
|
|
28307
|
+
} else {
|
|
28308
|
+
logger.warn("[ServiceWorker] STORE_EVENT before INIT, ignoring");
|
|
28309
|
+
}
|
|
28310
|
+
return;
|
|
28311
|
+
}
|
|
28312
|
+
const userEvent = event.data.event;
|
|
28313
|
+
await getController().handleStoreEvent(userEvent);
|
|
28111
28314
|
if (event.ports && event.ports[0]) {
|
|
28112
|
-
event.ports[0].postMessage({ success:
|
|
28315
|
+
event.ports[0].postMessage({ success: true });
|
|
28316
|
+
}
|
|
28317
|
+
} catch (error48) {
|
|
28318
|
+
logger.error("[ServiceWorker] Failed to store event:", error48);
|
|
28319
|
+
if (event.ports && event.ports[0]) {
|
|
28320
|
+
event.ports[0].postMessage({
|
|
28321
|
+
success: false,
|
|
28322
|
+
error: error48 instanceof Error ? error48.message : "Failed to store event"
|
|
28323
|
+
});
|
|
28113
28324
|
}
|
|
28114
|
-
return;
|
|
28115
|
-
}
|
|
28116
|
-
const userEvent = event.data.event;
|
|
28117
|
-
await getController().handleStoreEvent(userEvent);
|
|
28118
|
-
if (event.ports && event.ports[0]) {
|
|
28119
|
-
event.ports[0].postMessage({ success: true });
|
|
28120
|
-
}
|
|
28121
|
-
} catch (error48) {
|
|
28122
|
-
if (event.ports && event.ports[0]) {
|
|
28123
|
-
event.ports[0].postMessage({ success: false, error: error48 instanceof Error ? error48.message : "Worker not initialized" });
|
|
28124
28325
|
}
|
|
28125
|
-
}
|
|
28126
|
-
|
|
28326
|
+
})()
|
|
28327
|
+
);
|
|
28127
28328
|
return;
|
|
28128
28329
|
}
|
|
28129
28330
|
if (msg["type"] === "GET_EVENTS") {
|
|
28130
|
-
event.waitUntil(
|
|
28131
|
-
|
|
28132
|
-
|
|
28331
|
+
event.waitUntil(
|
|
28332
|
+
(async () => {
|
|
28333
|
+
try {
|
|
28334
|
+
if (!backendUrl || !controller) {
|
|
28335
|
+
if (event.ports && event.ports[0]) {
|
|
28336
|
+
event.ports[0].postMessage({
|
|
28337
|
+
success: false,
|
|
28338
|
+
error: "Worker not initialized"
|
|
28339
|
+
});
|
|
28340
|
+
}
|
|
28341
|
+
return;
|
|
28342
|
+
}
|
|
28343
|
+
const events = await getController().handleGetEvents();
|
|
28133
28344
|
if (event.ports && event.ports[0]) {
|
|
28134
|
-
event.ports[0].postMessage({ success:
|
|
28345
|
+
event.ports[0].postMessage({ success: true, events });
|
|
28346
|
+
}
|
|
28347
|
+
} catch (error48) {
|
|
28348
|
+
if (event.ports && event.ports[0]) {
|
|
28349
|
+
event.ports[0].postMessage({
|
|
28350
|
+
success: false,
|
|
28351
|
+
error: error48 instanceof Error ? error48.message : "Worker not initialized"
|
|
28352
|
+
});
|
|
28135
28353
|
}
|
|
28136
|
-
return;
|
|
28137
|
-
}
|
|
28138
|
-
const events = await getController().handleGetEvents();
|
|
28139
|
-
if (event.ports && event.ports[0]) {
|
|
28140
|
-
event.ports[0].postMessage({ success: true, events });
|
|
28141
|
-
}
|
|
28142
|
-
} catch (error48) {
|
|
28143
|
-
if (event.ports && event.ports[0]) {
|
|
28144
|
-
event.ports[0].postMessage({ success: false, error: error48 instanceof Error ? error48.message : "Worker not initialized" });
|
|
28145
28354
|
}
|
|
28146
|
-
}
|
|
28147
|
-
|
|
28355
|
+
})()
|
|
28356
|
+
);
|
|
28148
28357
|
return;
|
|
28149
28358
|
}
|
|
28150
28359
|
if (msg["type"] === "GET_CONNECTION_STATUS") {
|
|
28151
28360
|
if (event.ports && event.ports[0]) {
|
|
28152
28361
|
if (!backendUrl || !controller) {
|
|
28153
|
-
event.ports[0].postMessage({
|
|
28362
|
+
event.ports[0].postMessage({
|
|
28363
|
+
success: false,
|
|
28364
|
+
error: "Worker not initialized"
|
|
28365
|
+
});
|
|
28154
28366
|
} else {
|
|
28155
|
-
event.ports[0].postMessage({
|
|
28367
|
+
event.ports[0].postMessage({
|
|
28368
|
+
success: true,
|
|
28369
|
+
connected: getController().getConnectionStatus()
|
|
28370
|
+
});
|
|
28156
28371
|
}
|
|
28157
28372
|
}
|
|
28158
28373
|
return;
|
|
28159
28374
|
}
|
|
28375
|
+
if (msg["type"] === "REGISTER_TOOL") {
|
|
28376
|
+
event.waitUntil(
|
|
28377
|
+
(async () => {
|
|
28378
|
+
try {
|
|
28379
|
+
if (!backendUrl || !controller) {
|
|
28380
|
+
if (event.ports && event.ports[0]) {
|
|
28381
|
+
event.ports[0].postMessage({
|
|
28382
|
+
success: false,
|
|
28383
|
+
error: "Worker not initialized"
|
|
28384
|
+
});
|
|
28385
|
+
}
|
|
28386
|
+
return;
|
|
28387
|
+
}
|
|
28388
|
+
const toolData = msg;
|
|
28389
|
+
await getController().handleRegisterTool(toolData);
|
|
28390
|
+
if (event.ports && event.ports[0]) {
|
|
28391
|
+
event.ports[0].postMessage({ success: true });
|
|
28392
|
+
}
|
|
28393
|
+
} catch (error48) {
|
|
28394
|
+
if (event.ports && event.ports[0]) {
|
|
28395
|
+
event.ports[0].postMessage({
|
|
28396
|
+
success: false,
|
|
28397
|
+
error: error48 instanceof Error ? error48.message : "Failed to register tool"
|
|
28398
|
+
});
|
|
28399
|
+
}
|
|
28400
|
+
}
|
|
28401
|
+
})()
|
|
28402
|
+
);
|
|
28403
|
+
return;
|
|
28404
|
+
}
|
|
28405
|
+
if (msg["type"] === "UNREGISTER_TOOL") {
|
|
28406
|
+
event.waitUntil(
|
|
28407
|
+
(async () => {
|
|
28408
|
+
try {
|
|
28409
|
+
if (!backendUrl || !controller) {
|
|
28410
|
+
if (event.ports && event.ports[0]) {
|
|
28411
|
+
event.ports[0].postMessage({
|
|
28412
|
+
success: false,
|
|
28413
|
+
error: "Worker not initialized"
|
|
28414
|
+
});
|
|
28415
|
+
}
|
|
28416
|
+
return;
|
|
28417
|
+
}
|
|
28418
|
+
const toolName = msg["name"];
|
|
28419
|
+
if (!toolName) {
|
|
28420
|
+
if (event.ports && event.ports[0]) {
|
|
28421
|
+
event.ports[0].postMessage({
|
|
28422
|
+
success: false,
|
|
28423
|
+
error: "Tool name is required"
|
|
28424
|
+
});
|
|
28425
|
+
}
|
|
28426
|
+
return;
|
|
28427
|
+
}
|
|
28428
|
+
const success2 = await getController().handleUnregisterTool(toolName);
|
|
28429
|
+
if (event.ports && event.ports[0]) {
|
|
28430
|
+
event.ports[0].postMessage({ success: success2 });
|
|
28431
|
+
}
|
|
28432
|
+
} catch (error48) {
|
|
28433
|
+
if (event.ports && event.ports[0]) {
|
|
28434
|
+
event.ports[0].postMessage({
|
|
28435
|
+
success: false,
|
|
28436
|
+
error: error48 instanceof Error ? error48.message : "Failed to unregister tool"
|
|
28437
|
+
});
|
|
28438
|
+
}
|
|
28439
|
+
}
|
|
28440
|
+
})()
|
|
28441
|
+
);
|
|
28442
|
+
return;
|
|
28443
|
+
}
|
|
28444
|
+
if (msg["type"] === "TOOL_CALL_RESULT") {
|
|
28445
|
+
try {
|
|
28446
|
+
if (!controller) {
|
|
28447
|
+
logger.warn(
|
|
28448
|
+
"[ServiceWorker] Received TOOL_CALL_RESULT but no controller"
|
|
28449
|
+
);
|
|
28450
|
+
return;
|
|
28451
|
+
}
|
|
28452
|
+
const callId = msg["callId"];
|
|
28453
|
+
if (!callId) {
|
|
28454
|
+
logger.warn("[ServiceWorker] TOOL_CALL_RESULT missing callId");
|
|
28455
|
+
return;
|
|
28456
|
+
}
|
|
28457
|
+
getController().handleToolCallResult(callId, msg);
|
|
28458
|
+
} catch (error48) {
|
|
28459
|
+
logger.error("[ServiceWorker] Failed to handle TOOL_CALL_RESULT:", error48);
|
|
28460
|
+
}
|
|
28461
|
+
return;
|
|
28462
|
+
}
|
|
28160
28463
|
});
|
|
28161
28464
|
self.addEventListener("install", (event) => {
|
|
28162
28465
|
event.waitUntil(self.skipWaiting());
|
|
28163
28466
|
});
|
|
28164
28467
|
self.addEventListener("activate", (event) => {
|
|
28165
|
-
event.waitUntil(
|
|
28166
|
-
Promise.resolve(self.clients.claim())
|
|
28167
|
-
);
|
|
28468
|
+
event.waitUntil(Promise.resolve(self.clients.claim()));
|
|
28168
28469
|
});
|