@mcpjam/inspector 1.0.1 → 1.0.3

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.
@@ -286,7 +286,9 @@ tools.post("/execute", async (c) => {
286
286
  return c.json({ error: `Server '${serverId}' is not connected` }, 400);
287
287
  }
288
288
  const executionId = `exec_${Date.now()}_${Math.random().toString(36).slice(2, 8)}`;
289
- const execPromise = Promise.resolve().then(() => mcp2.executeToolDirect(toolName, parameters || {})).catch((error) => {
289
+ const execPromise = Promise.resolve().then(
290
+ () => mcp2.executeToolDirect(`${serverId}:${toolName}`, parameters || {})
291
+ ).catch((error) => {
290
292
  if (state) state.error = error;
291
293
  throw error;
292
294
  });
@@ -345,10 +347,7 @@ tools.post("/execute", async (c) => {
345
347
  state.result = race.res;
346
348
  activeExecution = null;
347
349
  mcp2.clearElicitationCallback();
348
- return c.json(
349
- { status: "completed", toolName, result: race.res.result },
350
- 200
351
- );
350
+ return c.json({ status: "completed", toolName, result: race.res }, 200);
352
351
  }
353
352
  return c.json(
354
353
  {
@@ -400,7 +399,7 @@ tools.post("/respond", async (c) => {
400
399
  {
401
400
  status: "completed",
402
401
  toolName: state.toolName,
403
- result: race.res.result
402
+ result: race.res
404
403
  },
405
404
  200
406
405
  );
@@ -502,6 +501,270 @@ resources.post("/read", async (c) => {
502
501
  );
503
502
  }
504
503
  });
504
+ resources.get("/widget/:sessionId", async (c) => {
505
+ const sessionId = c.req.param("sessionId");
506
+ const widgetData = c.req.query("data");
507
+ if (!widgetData) {
508
+ return c.html("<html><body>Error: Missing widget data</body></html>", 400);
509
+ }
510
+ return c.html(`
511
+ <!DOCTYPE html>
512
+ <html>
513
+ <head>
514
+ <meta charset="utf-8">
515
+ <title>Loading Widget...</title>
516
+ </head>
517
+ <body>
518
+ <script>
519
+ (async function() {
520
+ // Change URL to "/" BEFORE loading widget (for React Router)
521
+ history.replaceState(null, '', '/');
522
+
523
+ // Fetch the actual widget HTML
524
+ const response = await fetch('/api/mcp/resources/widget-content?data=${encodeURIComponent(widgetData)}');
525
+ const html = await response.text();
526
+
527
+ // Replace entire document with widget HTML
528
+ document.open();
529
+ document.write(html);
530
+ document.close();
531
+ })();
532
+ </script>
533
+ </body>
534
+ </html>
535
+ `);
536
+ });
537
+ resources.get("/widget-content", async (c) => {
538
+ try {
539
+ const widgetData = c.req.query("data");
540
+ if (!widgetData) {
541
+ return c.html(
542
+ "<html><body>Error: Missing widget data</body></html>",
543
+ 400
544
+ );
545
+ }
546
+ const base64Decoded = Buffer.from(widgetData, "base64").toString("binary");
547
+ const percentEncoded = base64Decoded.split("").map((c2) => "%" + ("00" + c2.charCodeAt(0).toString(16)).slice(-2)).join("");
548
+ const jsonString = decodeURIComponent(percentEncoded);
549
+ const { serverId, uri, toolInput, toolOutput, toolId } = JSON.parse(jsonString);
550
+ const mcpClientManager = c.mcpJamClientManager;
551
+ const connectedServers = mcpClientManager.getConnectedServers();
552
+ let actualServerId = serverId;
553
+ if (!connectedServers[serverId]) {
554
+ const serverNames = Object.keys(connectedServers);
555
+ const match = serverNames.find(
556
+ (name) => name.toLowerCase() === serverId.toLowerCase()
557
+ );
558
+ if (match) {
559
+ actualServerId = match;
560
+ } else {
561
+ return c.html(
562
+ `<html><body>
563
+ <h3>Error: Server not connected</h3>
564
+ <p>Requested server: ${serverId}</p>
565
+ <p>Available servers: ${serverNames.join(", ")}</p>
566
+ </body></html>`,
567
+ 404
568
+ );
569
+ }
570
+ }
571
+ const content = await mcpClientManager.getResource(uri, actualServerId);
572
+ let htmlContent = "";
573
+ if (Array.isArray(content)) {
574
+ htmlContent = content[0]?.text || content[0]?.blob || "";
575
+ } else if (content && typeof content === "object") {
576
+ htmlContent = content.text || content.blob || "";
577
+ if (!htmlContent && Array.isArray(content.contents)) {
578
+ htmlContent = content.contents[0]?.text || content.contents[0]?.blob || "";
579
+ }
580
+ }
581
+ if (!htmlContent) {
582
+ return c.html(
583
+ "<html><body>Error: No HTML content found</body></html>",
584
+ 404
585
+ );
586
+ }
587
+ const widgetStateKey = `openai-widget-state:${toolId}`;
588
+ const apiScript = `
589
+ <script>
590
+ (function() {
591
+ 'use strict';
592
+
593
+ const openaiAPI = {
594
+ toolInput: ${JSON.stringify(toolInput)},
595
+ toolOutput: ${JSON.stringify(toolOutput)},
596
+ displayMode: 'inline',
597
+ maxHeight: 600,
598
+ theme: 'dark',
599
+ locale: 'en-US',
600
+ safeArea: { insets: { top: 0, bottom: 0, left: 0, right: 0 } },
601
+ userAgent: {},
602
+ widgetState: null,
603
+
604
+ async setWidgetState(state) {
605
+ this.widgetState = state;
606
+ try {
607
+ localStorage.setItem(${JSON.stringify(widgetStateKey)}, JSON.stringify(state));
608
+ } catch (err) {
609
+ console.error('[OpenAI Widget] Failed to save widget state:', err);
610
+ }
611
+ window.parent.postMessage({
612
+ type: 'openai:setWidgetState',
613
+ toolId: ${JSON.stringify(toolId)},
614
+ state
615
+ }, '*');
616
+ },
617
+
618
+ async callTool(toolName, params = {}) {
619
+ return new Promise((resolve, reject) => {
620
+ const requestId = \`tool_\${Date.now()}_\${Math.random()}\`;
621
+ const handler = (event) => {
622
+ if (event.data.type === 'openai:callTool:response' &&
623
+ event.data.requestId === requestId) {
624
+ window.removeEventListener('message', handler);
625
+ if (event.data.error) {
626
+ reject(new Error(event.data.error));
627
+ } else {
628
+ resolve(event.data.result);
629
+ }
630
+ }
631
+ };
632
+ window.addEventListener('message', handler);
633
+ window.parent.postMessage({
634
+ type: 'openai:callTool',
635
+ requestId,
636
+ toolName,
637
+ params
638
+ }, '*');
639
+ setTimeout(() => {
640
+ window.removeEventListener('message', handler);
641
+ reject(new Error('Tool call timeout'));
642
+ }, 30000);
643
+ });
644
+ },
645
+
646
+ async sendFollowupTurn(message) {
647
+ const payload = typeof message === 'string'
648
+ ? { prompt: message }
649
+ : message;
650
+ window.parent.postMessage({
651
+ type: 'openai:sendFollowup',
652
+ message: payload.prompt || payload
653
+ }, '*');
654
+ },
655
+
656
+ async requestDisplayMode(options = {}) {
657
+ const mode = options.mode || 'inline';
658
+ this.displayMode = mode;
659
+ window.parent.postMessage({
660
+ type: 'openai:requestDisplayMode',
661
+ mode
662
+ }, '*');
663
+ return { mode };
664
+ },
665
+
666
+ async sendFollowUpMessage(args) {
667
+ const prompt = typeof args === 'string' ? args : (args?.prompt || '');
668
+ return this.sendFollowupTurn(prompt);
669
+ }
670
+ };
671
+
672
+ Object.defineProperty(window, 'openai', {
673
+ value: openaiAPI,
674
+ writable: false,
675
+ configurable: false,
676
+ enumerable: true
677
+ });
678
+
679
+ Object.defineProperty(window, 'webplus', {
680
+ value: openaiAPI,
681
+ writable: false,
682
+ configurable: false,
683
+ enumerable: true
684
+ });
685
+
686
+ setTimeout(() => {
687
+ try {
688
+ const globalsEvent = new CustomEvent('webplus:set_globals', {
689
+ detail: {
690
+ globals: {
691
+ displayMode: openaiAPI.displayMode,
692
+ maxHeight: openaiAPI.maxHeight,
693
+ theme: openaiAPI.theme,
694
+ locale: openaiAPI.locale,
695
+ safeArea: openaiAPI.safeArea,
696
+ userAgent: openaiAPI.userAgent
697
+ }
698
+ }
699
+ });
700
+ window.dispatchEvent(globalsEvent);
701
+ } catch (err) {}
702
+ }, 0);
703
+
704
+ setTimeout(() => {
705
+ try {
706
+ const stored = localStorage.getItem(${JSON.stringify(widgetStateKey)});
707
+ if (stored && window.openai) {
708
+ window.openai.widgetState = JSON.parse(stored);
709
+ }
710
+ } catch (err) {}
711
+ }, 0);
712
+ })();
713
+ </script>
714
+ `;
715
+ let modifiedHtml;
716
+ if (htmlContent.includes("<html>") && htmlContent.includes("<head>")) {
717
+ modifiedHtml = htmlContent.replace(
718
+ "<head>",
719
+ `<head><base href="/">${apiScript}`
720
+ );
721
+ } else {
722
+ modifiedHtml = `<!DOCTYPE html>
723
+ <html>
724
+ <head>
725
+ <base href="/">
726
+ <meta charset="UTF-8">
727
+ <meta name="viewport" content="width=device-width, initial-scale=1.0">
728
+ ${apiScript}
729
+ </head>
730
+ <body>
731
+ ${htmlContent}
732
+ </body>
733
+ </html>`;
734
+ }
735
+ const trustedCdns = [
736
+ "https://persistent.oaistatic.com",
737
+ "https://*.oaistatic.com",
738
+ "https://unpkg.com",
739
+ "https://cdn.jsdelivr.net",
740
+ "https://cdnjs.cloudflare.com",
741
+ "https://cdn.skypack.dev"
742
+ ].join(" ");
743
+ c.header(
744
+ "Content-Security-Policy",
745
+ [
746
+ "default-src 'self'",
747
+ `script-src 'self' 'unsafe-inline' 'unsafe-eval' ${trustedCdns}`,
748
+ "worker-src 'self' blob:",
749
+ "child-src 'self' blob:",
750
+ `style-src 'self' 'unsafe-inline' ${trustedCdns}`,
751
+ "img-src 'self' data: https: blob:",
752
+ "media-src 'self' data: https: blob:",
753
+ `font-src 'self' data: ${trustedCdns}`,
754
+ "connect-src 'self' https: wss: ws:",
755
+ "frame-ancestors 'self'"
756
+ ].join("; ")
757
+ );
758
+ c.header("X-Frame-Options", "SAMEORIGIN");
759
+ c.header("X-Content-Type-Options", "nosniff");
760
+ return c.html(modifiedHtml);
761
+ } catch (error) {
762
+ return c.html(
763
+ `<html><body>Error: ${error instanceof Error ? error.message : "Unknown error"}</body></html>`,
764
+ 500
765
+ );
766
+ }
767
+ });
505
768
  var resources_default = resources;
506
769
 
507
770
  // routes/mcp/prompts.ts
@@ -776,11 +1039,16 @@ function convertMastraToolsToVercelTools(mastraTools) {
776
1039
  }
777
1040
 
778
1041
  // ../shared/http-tool-calls.ts
779
- function flattenToolsets(toolsets) {
1042
+ function flattenToolsetsWithServerId(toolsets) {
780
1043
  const flattened = {};
781
- for (const serverTools of Object.values(toolsets || {})) {
1044
+ for (const [serverId, serverTools] of Object.entries(toolsets || {})) {
782
1045
  if (serverTools && typeof serverTools === "object") {
783
- Object.assign(flattened, serverTools);
1046
+ for (const [toolName, tool2] of Object.entries(serverTools)) {
1047
+ flattened[toolName] = {
1048
+ ...tool2,
1049
+ _serverId: serverId
1050
+ };
1051
+ }
784
1052
  }
785
1053
  }
786
1054
  return flattened;
@@ -818,13 +1086,18 @@ async function executeToolCallsFromMessages(messages, options) {
818
1086
  let tools2 = {};
819
1087
  if (options.client) {
820
1088
  const toolsets = await options.client.getToolsets();
821
- tools2 = flattenToolsets(toolsets);
1089
+ tools2 = flattenToolsetsWithServerId(toolsets);
822
1090
  } else if (options.toolsets) {
823
- tools2 = flattenToolsets(options.toolsets);
1091
+ const toolsets = options.toolsets;
1092
+ tools2 = flattenToolsetsWithServerId(toolsets);
824
1093
  } else {
825
1094
  tools2 = options.tools;
826
1095
  }
827
1096
  const index = buildIndexWithAliases(tools2);
1097
+ const extractServerId = (toolName) => {
1098
+ const tool2 = index[toolName];
1099
+ return tool2?._serverId;
1100
+ };
828
1101
  const existingToolResultIds = /* @__PURE__ */ new Set();
829
1102
  for (const msg of messages) {
830
1103
  if (!msg || msg.role !== "tool" || !Array.isArray(msg.content))
@@ -861,6 +1134,7 @@ async function executeToolCallsFromMessages(messages, options) {
861
1134
  } else {
862
1135
  output = { type: "text", value: String(result) };
863
1136
  }
1137
+ const serverId = extractServerId(toolName);
864
1138
  const toolResultMessage = {
865
1139
  role: "tool",
866
1140
  content: [
@@ -868,7 +1142,11 @@ async function executeToolCallsFromMessages(messages, options) {
868
1142
  type: "tool-result",
869
1143
  toolCallId: content.toolCallId,
870
1144
  toolName,
871
- output
1145
+ output,
1146
+ // Preserve full result including _meta for OpenAI Apps SDK
1147
+ result,
1148
+ // Add serverId for OpenAI component resolution
1149
+ serverId
872
1150
  }
873
1151
  ]
874
1152
  };
@@ -951,11 +1229,15 @@ var runBackendConversation = async (options) => {
951
1229
  if (msg.role === "tool" && Array.isArray(content)) {
952
1230
  for (const item of content) {
953
1231
  if (item?.type === "tool-result") {
1232
+ const fullResult = item.result;
954
1233
  const rawOutput = item.output ?? item.result ?? item.value ?? item.data ?? item.content;
955
1234
  const resultEvent = {
956
1235
  toolName: item.toolName ?? item.name,
957
- result: extractToolResultValue(rawOutput),
958
- error: item.error
1236
+ // Use full result if available, otherwise extract value from output
1237
+ result: fullResult ?? extractToolResultValue(rawOutput),
1238
+ error: item.error,
1239
+ // Preserve serverId if present
1240
+ serverId: item.serverId
959
1241
  };
960
1242
  iterationToolResults.push(resultEvent);
961
1243
  handlers?.onToolResult?.(resultEvent);
@@ -1036,6 +1318,8 @@ var handleAgentStepFinish = (streamingContext, text, toolCalls, toolResults, emi
1036
1318
  for (const call of toolCalls) {
1037
1319
  const currentToolCallId = ++streamingContext.toolCallId;
1038
1320
  streamingContext.lastEmittedToolCallId = currentToolCallId;
1321
+ const toolName = call.name || call.toolName;
1322
+ streamingContext.toolCallIdToName.set(currentToolCallId, toolName);
1039
1323
  if (streamingContext.controller && streamingContext.encoder) {
1040
1324
  sendSseEvent(
1041
1325
  streamingContext.controller,
@@ -1044,7 +1328,7 @@ var handleAgentStepFinish = (streamingContext, text, toolCalls, toolResults, emi
1044
1328
  type: "tool_call",
1045
1329
  toolCall: {
1046
1330
  id: currentToolCallId,
1047
- name: call.name || call.toolName,
1331
+ name: toolName,
1048
1332
  parameters: call.params || call.args || {},
1049
1333
  timestamp: (/* @__PURE__ */ new Date()).toISOString(),
1050
1334
  status: "executing"
@@ -1066,7 +1350,8 @@ var handleAgentStepFinish = (streamingContext, text, toolCalls, toolResults, emi
1066
1350
  toolResult: {
1067
1351
  id: currentToolCallId,
1068
1352
  toolCallId: currentToolCallId,
1069
- result: result.result,
1353
+ // Preserve full result which may include _meta for OpenAI Apps SDK
1354
+ result: result.result || result,
1070
1355
  error: result.error,
1071
1356
  timestamp: (/* @__PURE__ */ new Date()).toISOString()
1072
1357
  }
@@ -1096,7 +1381,11 @@ var handleAgentStepFinish = (streamingContext, text, toolCalls, toolResults, emi
1096
1381
  } catch {
1097
1382
  }
1098
1383
  };
1099
- var createStreamingResponse = async (model, aiSdkTools, messages, streamingContext, provider, temperature, systemPrompt) => {
1384
+ var createStreamingResponse = async (model, aiSdkTools, messages, streamingContext, provider, toolsWithServerId, temperature, systemPrompt) => {
1385
+ const extractServerId = (toolName) => {
1386
+ const tool2 = toolsWithServerId[toolName];
1387
+ return tool2?._serverId;
1388
+ };
1100
1389
  const messageHistory = (messages || []).map((m) => {
1101
1390
  switch (m.role) {
1102
1391
  case "system":
@@ -1146,6 +1435,7 @@ var createStreamingResponse = async (model, aiSdkTools, messages, streamingConte
1146
1435
  streamingContext.lastEmittedToolCallId = currentToolCallId;
1147
1436
  const name = chunk.chunk.toolName || chunk.chunk.name;
1148
1437
  const parameters = chunk.chunk.input ?? chunk.chunk.parameters ?? chunk.chunk.args ?? {};
1438
+ streamingContext.toolCallIdToName.set(currentToolCallId, name);
1149
1439
  iterationToolCalls.push({ name, params: parameters });
1150
1440
  sendSseEvent(
1151
1441
  streamingContext.controller,
@@ -1165,7 +1455,9 @@ var createStreamingResponse = async (model, aiSdkTools, messages, streamingConte
1165
1455
  }
1166
1456
  case "tool-result": {
1167
1457
  const result = chunk.chunk.output ?? chunk.chunk.result ?? chunk.chunk.value;
1168
- const currentToolCallId = streamingContext.lastEmittedToolCallId != null ? streamingContext.lastEmittedToolCallId : streamingContext.toolCallId;
1458
+ const currentToolCallId = streamingContext.lastEmittedToolCallId ?? ++streamingContext.toolCallId;
1459
+ const toolName = streamingContext.toolCallIdToName.get(currentToolCallId);
1460
+ const serverId = toolName ? extractServerId(toolName) : void 0;
1169
1461
  iterationToolResults.push({ result });
1170
1462
  sendSseEvent(
1171
1463
  streamingContext.controller,
@@ -1176,7 +1468,8 @@ var createStreamingResponse = async (model, aiSdkTools, messages, streamingConte
1176
1468
  id: currentToolCallId,
1177
1469
  toolCallId: currentToolCallId,
1178
1470
  result,
1179
- timestamp: (/* @__PURE__ */ new Date()).toISOString()
1471
+ timestamp: (/* @__PURE__ */ new Date()).toISOString(),
1472
+ serverId
1180
1473
  }
1181
1474
  }
1182
1475
  );
@@ -1203,6 +1496,8 @@ var createStreamingResponse = async (model, aiSdkTools, messages, streamingConte
1203
1496
  if (m.role === "tool") {
1204
1497
  const currentToolCallId = streamingContext.lastEmittedToolCallId != null ? streamingContext.lastEmittedToolCallId : ++streamingContext.toolCallId;
1205
1498
  const value = m.content;
1499
+ const toolName = streamingContext.toolCallIdToName.get(currentToolCallId);
1500
+ const serverId = toolName ? extractServerId(toolName) : void 0;
1206
1501
  iterationToolResults.push({ result: value });
1207
1502
  sendSseEvent(streamingContext.controller, streamingContext.encoder, {
1208
1503
  type: "tool_result",
@@ -1210,7 +1505,8 @@ var createStreamingResponse = async (model, aiSdkTools, messages, streamingConte
1210
1505
  id: currentToolCallId,
1211
1506
  toolCallId: currentToolCallId,
1212
1507
  result: value,
1213
- timestamp: (/* @__PURE__ */ new Date()).toISOString()
1508
+ timestamp: (/* @__PURE__ */ new Date()).toISOString(),
1509
+ serverId
1214
1510
  }
1215
1511
  });
1216
1512
  }
@@ -1243,20 +1539,24 @@ var sendMessagesToBackend = async (messages, streamingContext, mcpClientManager,
1243
1539
  return { role: "user", content: m.content };
1244
1540
  }
1245
1541
  });
1246
- const flatTools = await mcpClientManager.getFlattenedToolsetsForEnabledServers(
1247
- selectedServers
1248
- );
1249
- const toolDefs = Object.entries(flatTools).map(([name, tool2]) => ({
1250
- name,
1251
- description: tool2?.description,
1252
- inputSchema: zodToJsonSchema3(tool2?.inputSchema)
1253
- }));
1542
+ const toolsets = await mcpClientManager.getToolsetsWithServerIds(selectedServers);
1543
+ const toolDefs = [];
1544
+ for (const serverTools of Object.values(toolsets)) {
1545
+ for (const [name, tool2] of Object.entries(serverTools)) {
1546
+ toolDefs.push({
1547
+ name,
1548
+ description: tool2?.description,
1549
+ inputSchema: zodToJsonSchema3(tool2?.inputSchema)
1550
+ });
1551
+ }
1552
+ }
1254
1553
  if (!baseUrl) {
1255
1554
  throw new Error("CONVEX_HTTP_URL is not set");
1256
1555
  }
1257
1556
  const emitToolCall = (call) => {
1258
1557
  const currentToolCallId = ++streamingContext.toolCallId;
1259
1558
  streamingContext.lastEmittedToolCallId = currentToolCallId;
1559
+ streamingContext.toolCallIdToName.set(currentToolCallId, call.name);
1260
1560
  sendSseEvent(streamingContext.controller, streamingContext.encoder, {
1261
1561
  type: "tool_call",
1262
1562
  toolCall: {
@@ -1277,7 +1577,9 @@ var sendMessagesToBackend = async (messages, streamingContext, mcpClientManager,
1277
1577
  toolCallId: currentToolCallId,
1278
1578
  result: result.result,
1279
1579
  error: result.error,
1280
- timestamp: (/* @__PURE__ */ new Date()).toISOString()
1580
+ timestamp: (/* @__PURE__ */ new Date()).toISOString(),
1581
+ serverId: result.serverId
1582
+ // Propagate serverId
1281
1583
  }
1282
1584
  });
1283
1585
  };
@@ -1301,7 +1603,7 @@ var sendMessagesToBackend = async (messages, streamingContext, mcpClientManager,
1301
1603
  },
1302
1604
  executeToolCalls: async (messages2) => {
1303
1605
  await executeToolCallsFromMessages(messages2, {
1304
- tools: flatTools
1606
+ toolsets
1305
1607
  });
1306
1608
  },
1307
1609
  handlers: {
@@ -1323,7 +1625,7 @@ var sendMessagesToBackend = async (messages, streamingContext, mcpClientManager,
1323
1625
  text,
1324
1626
  toolCalls,
1325
1627
  toolResults.map((result) => ({
1326
- result: result.result,
1628
+ result: result.result || result,
1327
1629
  error: result.error
1328
1630
  })),
1329
1631
  false
@@ -1418,7 +1720,8 @@ chat.post("/", async (c) => {
1418
1720
  encoder,
1419
1721
  toolCallId: 0,
1420
1722
  lastEmittedToolCallId: null,
1421
- stepIndex: 0
1723
+ stepIndex: 0,
1724
+ toolCallIdToName: /* @__PURE__ */ new Map()
1422
1725
  };
1423
1726
  mcpClientManager.setElicitationCallback(async (request) => {
1424
1727
  const elicitationRequest = {
@@ -1466,10 +1769,23 @@ chat.post("/", async (c) => {
1466
1769
  requestData.selectedServers
1467
1770
  );
1468
1771
  } else {
1469
- const flatTools = await mcpClientManager.getFlattenedToolsetsForEnabledServers(
1772
+ const toolsets = await mcpClientManager.getToolsetsWithServerIds(
1470
1773
  requestData.selectedServers
1471
1774
  );
1472
- const aiSdkTools = convertMastraToolsToVercelTools(flatTools);
1775
+ const flatToolsWithServerId = {};
1776
+ for (const [serverId, serverTools] of Object.entries(
1777
+ toolsets || {}
1778
+ )) {
1779
+ if (serverTools && typeof serverTools === "object") {
1780
+ for (const [toolName, tool2] of Object.entries(serverTools)) {
1781
+ flatToolsWithServerId[toolName] = {
1782
+ ...tool2,
1783
+ _serverId: serverId
1784
+ };
1785
+ }
1786
+ }
1787
+ }
1788
+ const aiSdkTools = convertMastraToolsToVercelTools(flatToolsWithServerId);
1473
1789
  const llmModel = createLlmModel(
1474
1790
  model,
1475
1791
  apiKey || "",
@@ -1481,6 +1797,7 @@ chat.post("/", async (c) => {
1481
1797
  messages,
1482
1798
  streamingContext,
1483
1799
  provider,
1800
+ flatToolsWithServerId,
1484
1801
  temperature,
1485
1802
  systemPrompt
1486
1803
  );
@@ -9445,6 +9762,15 @@ var MCPJamClientManager = class {
9445
9762
  getServerIdForName(serverName) {
9446
9763
  return this.serverIdMapping.get(serverName);
9447
9764
  }
9765
+ // Reverse lookup: get server name from internal server ID
9766
+ getServerNameForId(serverId) {
9767
+ for (const [name, id] of this.serverIdMapping.entries()) {
9768
+ if (id === serverId) {
9769
+ return name;
9770
+ }
9771
+ }
9772
+ return void 0;
9773
+ }
9448
9774
  flattenToolsets(toolsets) {
9449
9775
  const flattenedTools = {};
9450
9776
  Object.values(toolsets).forEach((serverTools) => {
@@ -9452,6 +9778,26 @@ var MCPJamClientManager = class {
9452
9778
  });
9453
9779
  return flattenedTools;
9454
9780
  }
9781
+ async getToolsetsWithServerIds(serverNameFilter) {
9782
+ const toolsetsByServer = {};
9783
+ const allServerIdsFromFilter = serverNameFilter?.map(
9784
+ (serverName) => this.getServerIdForName(serverName)
9785
+ );
9786
+ for (const [serverId, client] of this.mcpClients.entries()) {
9787
+ if (serverNameFilter && !allServerIdsFromFilter?.includes(serverId))
9788
+ continue;
9789
+ if (this.getConnectionStatus(serverId) !== "connected") continue;
9790
+ try {
9791
+ const toolsets = await client.getToolsets();
9792
+ const flattenedTools = this.flattenToolsets(toolsets);
9793
+ const serverName = this.getServerNameForId(serverId) || serverId;
9794
+ toolsetsByServer[serverName] = flattenedTools;
9795
+ } catch (error) {
9796
+ console.warn(`Failed to get tools from server ${serverId}:`, error);
9797
+ }
9798
+ }
9799
+ return toolsetsByServer;
9800
+ }
9455
9801
  async getFlattenedToolsetsForEnabledServers(serverNameFilter) {
9456
9802
  const allFlattenedTools = {};
9457
9803
  const allServerIdsFromFilter = serverNameFilter?.map(
@@ -9687,30 +10033,12 @@ var MCPJamClientManager = class {
9687
10033
  const tool2 = flattenedTools[name];
9688
10034
  if (!tool2)
9689
10035
  throw new Error(`Tool '${name}' not found in server '${serverId}'`);
9690
- const schema = tool2.inputSchema;
9691
- const hasContextProperty = schema && typeof schema === "object" && schema.properties && Object.prototype.hasOwnProperty.call(
9692
- schema.properties,
9693
- "context"
9694
- );
9695
- const requiresContext = hasContextProperty || schema && Array.isArray(schema.required) && schema.required.includes("context");
9696
- const contextWrapped = { context: parameters || {} };
9697
- const direct = parameters || {};
9698
- const attempts = requiresContext ? [contextWrapped, direct] : [direct, contextWrapped];
9699
- let lastError = void 0;
9700
- for (const args of attempts) {
9701
- try {
9702
- console.log("args", args);
9703
- const result = await tool2.execute(args);
9704
- if (result && result.isError) {
9705
- const errorText = result.content && result.content[0] && result.content[0].text ? result.content[0].text : "Unknown error";
9706
- throw new Error(errorText);
9707
- }
9708
- return { result };
9709
- } catch (err) {
9710
- lastError = err;
9711
- }
10036
+ const result = await tool2.execute({ context: parameters || {} });
10037
+ if (result && result.isError) {
10038
+ const errorText = result.content && result.content[0] && result.content[0].text ? result.content[0].text : "Unknown error";
10039
+ throw new Error(errorText);
9712
10040
  }
9713
- throw lastError;
10041
+ return { result };
9714
10042
  }
9715
10043
  async getResource(resourceUri, serverId) {
9716
10044
  let uri = resourceUri;