opensentinel 2.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.
Files changed (83) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +283 -0
  3. package/dist/bot-KJ26BG56.js +15 -0
  4. package/dist/bot-KJ26BG56.js.map +1 -0
  5. package/dist/charts-MMXM6BWW.js +241 -0
  6. package/dist/charts-MMXM6BWW.js.map +1 -0
  7. package/dist/chunk-4LVWXUNC.js +1079 -0
  8. package/dist/chunk-4LVWXUNC.js.map +1 -0
  9. package/dist/chunk-4TG2IG5K.js +5249 -0
  10. package/dist/chunk-4TG2IG5K.js.map +1 -0
  11. package/dist/chunk-6DRDKB45.js +251 -0
  12. package/dist/chunk-6DRDKB45.js.map +1 -0
  13. package/dist/chunk-6SNHU3CY.js +123 -0
  14. package/dist/chunk-6SNHU3CY.js.map +1 -0
  15. package/dist/chunk-CI6Q63MM.js +1613 -0
  16. package/dist/chunk-CI6Q63MM.js.map +1 -0
  17. package/dist/chunk-CQ4JURG7.js +57 -0
  18. package/dist/chunk-CQ4JURG7.js.map +1 -0
  19. package/dist/chunk-F6QUZQGI.js +51 -0
  20. package/dist/chunk-F6QUZQGI.js.map +1 -0
  21. package/dist/chunk-GK3E2I7A.js +216 -0
  22. package/dist/chunk-GK3E2I7A.js.map +1 -0
  23. package/dist/chunk-GUBEEYDW.js +211 -0
  24. package/dist/chunk-GUBEEYDW.js.map +1 -0
  25. package/dist/chunk-GVJVEWHI.js +29 -0
  26. package/dist/chunk-GVJVEWHI.js.map +1 -0
  27. package/dist/chunk-HH2HBTQM.js +806 -0
  28. package/dist/chunk-HH2HBTQM.js.map +1 -0
  29. package/dist/chunk-JXUP2X7V.js +129 -0
  30. package/dist/chunk-JXUP2X7V.js.map +1 -0
  31. package/dist/chunk-KHNYJY2Z.js +178 -0
  32. package/dist/chunk-KHNYJY2Z.js.map +1 -0
  33. package/dist/chunk-L3F43VPB.js +652 -0
  34. package/dist/chunk-L3F43VPB.js.map +1 -0
  35. package/dist/chunk-L3PDU3XN.js +803 -0
  36. package/dist/chunk-L3PDU3XN.js.map +1 -0
  37. package/dist/chunk-NSBPE2FW.js +17 -0
  38. package/dist/chunk-NSBPE2FW.js.map +1 -0
  39. package/dist/cli.d.ts +1 -0
  40. package/dist/cli.js +52 -0
  41. package/dist/cli.js.map +1 -0
  42. package/dist/commands/setup.d.ts +9 -0
  43. package/dist/commands/setup.js +374 -0
  44. package/dist/commands/setup.js.map +1 -0
  45. package/dist/commands/start.d.ts +8 -0
  46. package/dist/commands/start.js +27 -0
  47. package/dist/commands/start.js.map +1 -0
  48. package/dist/commands/status.d.ts +8 -0
  49. package/dist/commands/status.js +57 -0
  50. package/dist/commands/status.js.map +1 -0
  51. package/dist/commands/stop.d.ts +8 -0
  52. package/dist/commands/stop.js +37 -0
  53. package/dist/commands/stop.js.map +1 -0
  54. package/dist/commands/utils.d.ts +50 -0
  55. package/dist/commands/utils.js +36 -0
  56. package/dist/commands/utils.js.map +1 -0
  57. package/dist/discord-ZOJFTVTB.js +49 -0
  58. package/dist/discord-ZOJFTVTB.js.map +1 -0
  59. package/dist/imessage-JFRB6EJ7.js +14 -0
  60. package/dist/imessage-JFRB6EJ7.js.map +1 -0
  61. package/dist/lib.d.ts +855 -0
  62. package/dist/lib.js +274 -0
  63. package/dist/lib.js.map +1 -0
  64. package/dist/mcp-LS7Q3Z5W.js +30 -0
  65. package/dist/mcp-LS7Q3Z5W.js.map +1 -0
  66. package/dist/scheduler-EZ7CZMCS.js +42 -0
  67. package/dist/scheduler-EZ7CZMCS.js.map +1 -0
  68. package/dist/signal-T3MCSULM.js +14 -0
  69. package/dist/signal-T3MCSULM.js.map +1 -0
  70. package/dist/slack-N2M4FHAJ.js +54 -0
  71. package/dist/slack-N2M4FHAJ.js.map +1 -0
  72. package/dist/src-K7GASHRH.js +430 -0
  73. package/dist/src-K7GASHRH.js.map +1 -0
  74. package/dist/tools-24GZHYRF.js +16 -0
  75. package/dist/tools-24GZHYRF.js.map +1 -0
  76. package/dist/whatsapp-VCRUPAO5.js +14 -0
  77. package/dist/whatsapp-VCRUPAO5.js.map +1 -0
  78. package/drizzle/0000_chilly_shinobi_shaw.sql +75 -0
  79. package/drizzle/0001_freezing_shape.sql +274 -0
  80. package/drizzle/meta/0000_snapshot.json +529 -0
  81. package/drizzle/meta/0001_snapshot.json +2576 -0
  82. package/drizzle/meta/_journal.json +20 -0
  83. package/package.json +98 -0
@@ -0,0 +1,652 @@
1
+ // src/core/mcp/client.ts
2
+ import { spawn } from "child_process";
3
+ import { nanoid } from "nanoid";
4
+ var MCP_PROTOCOL_VERSION = "2024-11-05";
5
+ var MCPClient = class {
6
+ config;
7
+ state;
8
+ process = null;
9
+ pendingRequests = /* @__PURE__ */ new Map();
10
+ messageBuffer = "";
11
+ requestTimeout;
12
+ constructor(config, timeout = 3e4) {
13
+ this.config = config;
14
+ this.requestTimeout = timeout;
15
+ this.state = {
16
+ config,
17
+ status: "disconnected",
18
+ tools: []
19
+ };
20
+ }
21
+ get id() {
22
+ return this.config.id;
23
+ }
24
+ get name() {
25
+ return this.config.name;
26
+ }
27
+ get status() {
28
+ return this.state.status;
29
+ }
30
+ get tools() {
31
+ return this.state.tools;
32
+ }
33
+ get serverInfo() {
34
+ return this.state.serverInfo;
35
+ }
36
+ // ============================================
37
+ // CONNECTION MANAGEMENT
38
+ // ============================================
39
+ async connect() {
40
+ if (this.state.status === "connected") {
41
+ return;
42
+ }
43
+ this.state.status = "connecting";
44
+ try {
45
+ if (this.config.transport === "stdio") {
46
+ await this.connectStdio();
47
+ } else if (this.config.transport === "http+sse") {
48
+ await this.connectHttpSse();
49
+ } else {
50
+ throw new Error(`Unsupported transport: ${this.config.transport}`);
51
+ }
52
+ const initResult = await this.initialize();
53
+ this.state.capabilities = initResult.capabilities;
54
+ this.state.serverInfo = initResult.serverInfo;
55
+ await this.refreshTools();
56
+ this.state.status = "connected";
57
+ this.state.lastActivity = /* @__PURE__ */ new Date();
58
+ console.log(`[MCP] Connected to ${this.name} (${this.state.tools.length} tools)`);
59
+ } catch (error) {
60
+ this.state.status = "error";
61
+ this.state.lastError = error instanceof Error ? error.message : "Unknown error";
62
+ throw error;
63
+ }
64
+ }
65
+ async disconnect() {
66
+ if (this.state.status === "disconnected") {
67
+ return;
68
+ }
69
+ for (const [, pending] of this.pendingRequests) {
70
+ clearTimeout(pending.timeout);
71
+ pending.reject(new Error("Connection closed"));
72
+ }
73
+ this.pendingRequests.clear();
74
+ if (this.process) {
75
+ this.process.kill();
76
+ this.process = null;
77
+ }
78
+ this.state.status = "disconnected";
79
+ this.state.tools = [];
80
+ console.log(`[MCP] Disconnected from ${this.name}`);
81
+ }
82
+ // ============================================
83
+ // STDIO TRANSPORT
84
+ // ============================================
85
+ async connectStdio() {
86
+ if (!this.config.command) {
87
+ throw new Error("STDIO transport requires a command");
88
+ }
89
+ const env = {
90
+ ...process.env,
91
+ ...this.config.env
92
+ };
93
+ this.process = spawn(
94
+ this.config.command,
95
+ this.config.args || [],
96
+ {
97
+ cwd: this.config.cwd || process.cwd(),
98
+ env,
99
+ stdio: ["pipe", "pipe", "pipe"]
100
+ }
101
+ );
102
+ this.readStdout();
103
+ this.readStderr();
104
+ await new Promise((resolve) => setTimeout(resolve, 500));
105
+ }
106
+ readStdout() {
107
+ if (!this.process?.stdout) return;
108
+ this.process.stdout.on("data", (chunk) => {
109
+ this.messageBuffer += chunk.toString();
110
+ this.processMessageBuffer();
111
+ });
112
+ this.process.stdout.on("error", (error) => {
113
+ if (this.state.status === "connected" || this.state.status === "connecting") {
114
+ console.error(`[MCP] ${this.name} stdout error:`, error);
115
+ }
116
+ });
117
+ }
118
+ readStderr() {
119
+ if (!this.process?.stderr) return;
120
+ this.process.stderr.on("data", (chunk) => {
121
+ const text = chunk.toString();
122
+ if (text.trim()) {
123
+ console.log(`[MCP] ${this.name} stderr: ${text.trim()}`);
124
+ }
125
+ });
126
+ }
127
+ processMessageBuffer() {
128
+ const lines = this.messageBuffer.split("\n");
129
+ this.messageBuffer = lines.pop() || "";
130
+ for (const line of lines) {
131
+ if (!line.trim()) continue;
132
+ try {
133
+ const message = JSON.parse(line);
134
+ this.handleResponse(message);
135
+ } catch {
136
+ console.warn(`[MCP] ${this.name} failed to parse message: ${line.slice(0, 100)}`);
137
+ }
138
+ }
139
+ }
140
+ handleResponse(response) {
141
+ if (response.id === void 0 || response.id === null) {
142
+ return;
143
+ }
144
+ const pending = this.pendingRequests.get(response.id);
145
+ if (!pending) {
146
+ console.warn(`[MCP] ${this.name} received response for unknown request: ${response.id}`);
147
+ return;
148
+ }
149
+ clearTimeout(pending.timeout);
150
+ this.pendingRequests.delete(response.id);
151
+ if (response.error) {
152
+ pending.reject(new Error(response.error.message));
153
+ } else {
154
+ pending.resolve(response.result);
155
+ }
156
+ }
157
+ async sendRequest(method, params) {
158
+ if (!this.process?.stdin) {
159
+ throw new Error("Not connected");
160
+ }
161
+ const id = nanoid();
162
+ const request = {
163
+ jsonrpc: "2.0",
164
+ id,
165
+ method,
166
+ params
167
+ };
168
+ const promise = new Promise((resolve, reject) => {
169
+ const timeout = setTimeout(() => {
170
+ this.pendingRequests.delete(id);
171
+ reject(new Error(`Request timeout: ${method}`));
172
+ }, this.requestTimeout);
173
+ this.pendingRequests.set(id, { resolve, reject, timeout });
174
+ });
175
+ const data = JSON.stringify(request) + "\n";
176
+ this.process.stdin.write(data);
177
+ return promise;
178
+ }
179
+ // ============================================
180
+ // HTTP+SSE TRANSPORT
181
+ // ============================================
182
+ async connectHttpSse() {
183
+ if (!this.config.url) {
184
+ throw new Error("HTTP+SSE transport requires a URL");
185
+ }
186
+ try {
187
+ const response = await fetch(`${this.config.url}/health`, {
188
+ headers: this.config.headers
189
+ });
190
+ if (!response.ok) {
191
+ throw new Error(`Server health check failed: ${response.status}`);
192
+ }
193
+ } catch (error) {
194
+ const response = await fetch(this.config.url, {
195
+ method: "POST",
196
+ headers: {
197
+ "Content-Type": "application/json",
198
+ ...this.config.headers
199
+ },
200
+ body: JSON.stringify({
201
+ jsonrpc: "2.0",
202
+ id: "ping",
203
+ method: "ping"
204
+ })
205
+ });
206
+ if (!response.ok) {
207
+ throw new Error(`Server connection failed: ${response.status}`);
208
+ }
209
+ }
210
+ }
211
+ async sendHttpRequest(method, params) {
212
+ if (!this.config.url) {
213
+ throw new Error("HTTP+SSE transport requires a URL");
214
+ }
215
+ const request = {
216
+ jsonrpc: "2.0",
217
+ id: nanoid(),
218
+ method,
219
+ params
220
+ };
221
+ const response = await fetch(this.config.url, {
222
+ method: "POST",
223
+ headers: {
224
+ "Content-Type": "application/json",
225
+ ...this.config.headers
226
+ },
227
+ body: JSON.stringify(request)
228
+ });
229
+ if (!response.ok) {
230
+ throw new Error(`HTTP request failed: ${response.status}`);
231
+ }
232
+ const result = await response.json();
233
+ if (result.error) {
234
+ throw new Error(result.error.message);
235
+ }
236
+ return result.result;
237
+ }
238
+ // ============================================
239
+ // MCP PROTOCOL METHODS
240
+ // ============================================
241
+ async initialize() {
242
+ const params = {
243
+ protocolVersion: MCP_PROTOCOL_VERSION,
244
+ capabilities: {
245
+ roots: { listChanged: true }
246
+ },
247
+ clientInfo: {
248
+ name: "OpenSentinel",
249
+ version: "2.0.0"
250
+ }
251
+ };
252
+ const result = await this.request("initialize", params);
253
+ await this.notify("notifications/initialized", {});
254
+ return result;
255
+ }
256
+ async refreshTools() {
257
+ const result = await this.request("tools/list", {});
258
+ this.state.tools = result.tools || [];
259
+ return this.state.tools;
260
+ }
261
+ async callTool(name, args) {
262
+ const params = {
263
+ name,
264
+ arguments: args
265
+ };
266
+ try {
267
+ const result = await this.request("tools/call", params);
268
+ this.state.lastActivity = /* @__PURE__ */ new Date();
269
+ const textContent = result.content.filter((c) => c.type === "text" && c.text).map((c) => c.text).join("\n");
270
+ return {
271
+ success: !result.isError,
272
+ output: textContent || JSON.stringify(result.content),
273
+ isError: result.isError
274
+ };
275
+ } catch (error) {
276
+ return {
277
+ success: false,
278
+ error: error instanceof Error ? error.message : "Unknown error"
279
+ };
280
+ }
281
+ }
282
+ // ============================================
283
+ // GENERIC REQUEST/NOTIFY
284
+ // ============================================
285
+ async request(method, params) {
286
+ if (this.config.transport === "stdio") {
287
+ return this.sendRequest(method, params);
288
+ } else {
289
+ return this.sendHttpRequest(method, params);
290
+ }
291
+ }
292
+ async notify(method, params) {
293
+ if (this.config.transport === "stdio" && this.process?.stdin) {
294
+ const notification = {
295
+ jsonrpc: "2.0",
296
+ method,
297
+ params
298
+ };
299
+ this.process.stdin.write(JSON.stringify(notification) + "\n");
300
+ }
301
+ }
302
+ // ============================================
303
+ // STATE ACCESS
304
+ // ============================================
305
+ getState() {
306
+ return { ...this.state };
307
+ }
308
+ };
309
+
310
+ // src/core/mcp/registry.ts
311
+ var MCPRegistry = class {
312
+ clients = /* @__PURE__ */ new Map();
313
+ config;
314
+ defaultTimeout;
315
+ constructor(config) {
316
+ this.config = config;
317
+ this.defaultTimeout = config.settings?.timeout || 3e4;
318
+ }
319
+ // ============================================
320
+ // INITIALIZATION
321
+ // ============================================
322
+ /**
323
+ * Connect to all enabled MCP servers
324
+ */
325
+ async initialize() {
326
+ const enabledServers = this.config.servers.filter((s) => s.enabled);
327
+ console.log(`[MCP] Initializing ${enabledServers.length} server(s)...`);
328
+ const results = await Promise.allSettled(
329
+ enabledServers.map((config) => this.connectServer(config))
330
+ );
331
+ results.forEach((result, index) => {
332
+ if (result.status === "rejected") {
333
+ console.error(
334
+ `[MCP] Failed to connect to ${enabledServers[index].name}:`,
335
+ result.reason
336
+ );
337
+ }
338
+ });
339
+ const connected = results.filter((r) => r.status === "fulfilled").length;
340
+ console.log(`[MCP] Connected to ${connected}/${enabledServers.length} servers`);
341
+ }
342
+ /**
343
+ * Connect to a single MCP server
344
+ */
345
+ async connectServer(config) {
346
+ if (this.clients.has(config.id)) {
347
+ throw new Error(`Server ${config.id} already connected`);
348
+ }
349
+ const client = new MCPClient(config, this.defaultTimeout);
350
+ await client.connect();
351
+ this.clients.set(config.id, client);
352
+ }
353
+ /**
354
+ * Disconnect from a specific server
355
+ */
356
+ async disconnectServer(id) {
357
+ const client = this.clients.get(id);
358
+ if (client) {
359
+ await client.disconnect();
360
+ this.clients.delete(id);
361
+ }
362
+ }
363
+ /**
364
+ * Disconnect from all servers
365
+ */
366
+ async shutdown() {
367
+ console.log("[MCP] Shutting down all connections...");
368
+ await Promise.all(
369
+ Array.from(this.clients.values()).map((client) => client.disconnect())
370
+ );
371
+ this.clients.clear();
372
+ }
373
+ // ============================================
374
+ // TOOL MANAGEMENT
375
+ // ============================================
376
+ /**
377
+ * Get all tools from all connected servers
378
+ * Tools are prefixed with "mcp_{serverId}_" for routing
379
+ */
380
+ getAllTools() {
381
+ const tools = [];
382
+ for (const [serverId, client] of this.clients) {
383
+ if (client.status === "connected") {
384
+ for (const tool of client.tools) {
385
+ tools.push({ serverId, tool });
386
+ }
387
+ }
388
+ }
389
+ return tools;
390
+ }
391
+ /**
392
+ * Get tools from a specific server
393
+ */
394
+ getServerTools(serverId) {
395
+ const client = this.clients.get(serverId);
396
+ return client?.tools || [];
397
+ }
398
+ /**
399
+ * Call a tool on a specific server
400
+ */
401
+ async callTool(serverId, toolName, args) {
402
+ const client = this.clients.get(serverId);
403
+ if (!client) {
404
+ return {
405
+ success: false,
406
+ error: `MCP server not found: ${serverId}`
407
+ };
408
+ }
409
+ if (client.status !== "connected") {
410
+ return {
411
+ success: false,
412
+ error: `MCP server not connected: ${serverId}`
413
+ };
414
+ }
415
+ console.log(`[MCP] Calling ${serverId}:${toolName}`);
416
+ return client.callTool(toolName, args);
417
+ }
418
+ // ============================================
419
+ // SERVER MANAGEMENT
420
+ // ============================================
421
+ /**
422
+ * Get status of all servers
423
+ */
424
+ getServerStates() {
425
+ return Array.from(this.clients.values()).map((client) => client.getState());
426
+ }
427
+ /**
428
+ * Get status of a specific server
429
+ */
430
+ getServerState(serverId) {
431
+ return this.clients.get(serverId)?.getState();
432
+ }
433
+ /**
434
+ * Check if a server is connected
435
+ */
436
+ isConnected(serverId) {
437
+ const client = this.clients.get(serverId);
438
+ return client?.status === "connected";
439
+ }
440
+ /**
441
+ * Refresh tools from all connected servers
442
+ */
443
+ async refreshAllTools() {
444
+ await Promise.all(
445
+ Array.from(this.clients.values()).filter((client) => client.status === "connected").map((client) => client.refreshTools())
446
+ );
447
+ }
448
+ /**
449
+ * Add a new server configuration and optionally connect
450
+ */
451
+ async addServer(config, connect = true) {
452
+ if (this.clients.has(config.id)) {
453
+ throw new Error(`Server ${config.id} already exists`);
454
+ }
455
+ this.config.servers.push(config);
456
+ if (connect && config.enabled) {
457
+ await this.connectServer(config);
458
+ }
459
+ }
460
+ /**
461
+ * Remove a server
462
+ */
463
+ async removeServer(serverId) {
464
+ await this.disconnectServer(serverId);
465
+ this.config.servers = this.config.servers.filter((s) => s.id !== serverId);
466
+ }
467
+ /**
468
+ * Get the current configuration
469
+ */
470
+ getConfig() {
471
+ return { ...this.config };
472
+ }
473
+ /**
474
+ * Get count of connected servers
475
+ */
476
+ get connectedCount() {
477
+ return Array.from(this.clients.values()).filter(
478
+ (c) => c.status === "connected"
479
+ ).length;
480
+ }
481
+ /**
482
+ * Get total tool count across all servers
483
+ */
484
+ get totalToolCount() {
485
+ return this.getAllTools().length;
486
+ }
487
+ };
488
+ async function loadMCPConfig(path) {
489
+ try {
490
+ const { readFile, access } = await import("fs/promises");
491
+ try {
492
+ await access(path);
493
+ } catch {
494
+ console.log(`[MCP] Config file not found: ${path}, using empty config`);
495
+ return { servers: [] };
496
+ }
497
+ const content = await readFile(path, "utf-8");
498
+ const config = JSON.parse(content);
499
+ if (!Array.isArray(config.servers)) {
500
+ console.warn("[MCP] Invalid config: servers must be an array");
501
+ return { servers: [] };
502
+ }
503
+ return config;
504
+ } catch (error) {
505
+ console.error("[MCP] Failed to load config:", error);
506
+ return { servers: [] };
507
+ }
508
+ }
509
+ async function initMCPRegistry(configPath) {
510
+ const config = await loadMCPConfig(configPath);
511
+ const registry = new MCPRegistry(config);
512
+ await registry.initialize();
513
+ return registry;
514
+ }
515
+
516
+ // src/core/mcp/tool-bridge.ts
517
+ var MCP_TOOL_PREFIX = "mcp_";
518
+ function createMCPToolName(serverId, toolName) {
519
+ const safeServerId = serverId.replace(/[^a-zA-Z0-9_]/g, "_");
520
+ const safeToolName = toolName.replace(/[^a-zA-Z0-9_]/g, "_");
521
+ return `${MCP_TOOL_PREFIX}${safeServerId}__${safeToolName}`;
522
+ }
523
+ function isMCPTool(name) {
524
+ return name.startsWith(MCP_TOOL_PREFIX);
525
+ }
526
+ function parseMCPToolName(name) {
527
+ if (!isMCPTool(name)) {
528
+ return null;
529
+ }
530
+ const withoutPrefix = name.slice(MCP_TOOL_PREFIX.length);
531
+ const separatorIndex = withoutPrefix.indexOf("__");
532
+ if (separatorIndex === -1) {
533
+ return null;
534
+ }
535
+ return {
536
+ serverId: withoutPrefix.slice(0, separatorIndex),
537
+ toolName: withoutPrefix.slice(separatorIndex + 2)
538
+ };
539
+ }
540
+ function convertProperty(prop) {
541
+ const result = {
542
+ type: prop.type
543
+ };
544
+ if (prop.description) {
545
+ result.description = prop.description;
546
+ }
547
+ if (prop.enum) {
548
+ result.enum = prop.enum;
549
+ }
550
+ if (prop.items) {
551
+ result.items = convertProperty(prop.items);
552
+ }
553
+ if (prop.properties) {
554
+ result.properties = Object.fromEntries(
555
+ Object.entries(prop.properties).map(([key, value]) => [
556
+ key,
557
+ convertProperty(value)
558
+ ])
559
+ );
560
+ }
561
+ if (prop.required) {
562
+ result.required = prop.required;
563
+ }
564
+ return result;
565
+ }
566
+ function mcpToolToAnthropicTool(serverId, serverName, tool) {
567
+ const properties = {};
568
+ if (tool.inputSchema.properties) {
569
+ for (const [key, value] of Object.entries(tool.inputSchema.properties)) {
570
+ properties[key] = convertProperty(value);
571
+ }
572
+ }
573
+ const inputSchema = {
574
+ type: "object",
575
+ properties,
576
+ required: tool.inputSchema.required || []
577
+ };
578
+ const name = createMCPToolName(serverId, tool.name);
579
+ const description = tool.description ? `[${serverName}] ${tool.description}` : `[${serverName}] ${tool.name}`;
580
+ return {
581
+ name,
582
+ description,
583
+ input_schema: inputSchema
584
+ };
585
+ }
586
+ function mcpToolsToAnthropicTools(registry) {
587
+ const tools = [];
588
+ const serverStates = registry.getServerStates();
589
+ for (const state of serverStates) {
590
+ if (state.status !== "connected") continue;
591
+ const serverName = state.serverInfo?.name || state.config.name;
592
+ for (const tool of state.tools) {
593
+ tools.push(mcpToolToAnthropicTool(state.config.id, serverName, tool));
594
+ }
595
+ }
596
+ return tools;
597
+ }
598
+ async function executeMCPTool(registry, toolName, args) {
599
+ const parsed = parseMCPToolName(toolName);
600
+ if (!parsed) {
601
+ return {
602
+ success: false,
603
+ error: `Invalid MCP tool name: ${toolName}`
604
+ };
605
+ }
606
+ return registry.callTool(parsed.serverId, parsed.toolName, args);
607
+ }
608
+ function getMCPToolSummary(registry) {
609
+ const states = registry.getServerStates();
610
+ const lines = [];
611
+ for (const state of states) {
612
+ const status = state.status === "connected" ? "\u2713" : "\u2717";
613
+ const serverName = state.serverInfo?.name || state.config.name;
614
+ const toolCount = state.tools.length;
615
+ lines.push(` ${status} ${serverName}: ${toolCount} tools`);
616
+ if (state.status === "connected" && state.tools.length > 0) {
617
+ const toolNames = state.tools.map((t) => t.name).join(", ");
618
+ lines.push(` Tools: ${toolNames}`);
619
+ } else if (state.lastError) {
620
+ lines.push(` Error: ${state.lastError}`);
621
+ }
622
+ }
623
+ if (lines.length === 0) {
624
+ return " No MCP servers configured";
625
+ }
626
+ return lines.join("\n");
627
+ }
628
+ function findMCPTool(registry, toolName) {
629
+ const allTools = registry.getAllTools();
630
+ for (const { serverId, tool } of allTools) {
631
+ if (tool.name === toolName) {
632
+ return { serverId, tool };
633
+ }
634
+ }
635
+ return null;
636
+ }
637
+
638
+ export {
639
+ MCPClient,
640
+ MCPRegistry,
641
+ loadMCPConfig,
642
+ initMCPRegistry,
643
+ createMCPToolName,
644
+ isMCPTool,
645
+ parseMCPToolName,
646
+ mcpToolToAnthropicTool,
647
+ mcpToolsToAnthropicTools,
648
+ executeMCPTool,
649
+ getMCPToolSummary,
650
+ findMCPTool
651
+ };
652
+ //# sourceMappingURL=chunk-L3F43VPB.js.map