mcp-use 1.2.1 → 1.2.2-canary.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/dist/.tsbuildinfo +1 -1
- package/dist/chunk-3RJENWH4.js +248 -0
- package/dist/{chunk-MGUO7HXB.js → chunk-7UX634PO.js} +307 -1066
- package/dist/chunk-KLIBVJ3Z.js +759 -0
- package/dist/chunk-MZLETWQQ.js +250 -0
- package/dist/chunk-RSGKBEHH.js +1411 -0
- package/dist/index.cjs +880 -541
- package/dist/index.d.ts +24 -24
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +92 -33
- package/dist/{langfuse-6AJGHMAV.js → langfuse-LCJ6VJEP.js} +2 -1
- package/dist/src/adapters/base.d.ts +2 -2
- package/dist/src/adapters/base.d.ts.map +1 -1
- package/dist/src/adapters/index.d.ts +2 -2
- package/dist/src/adapters/index.d.ts.map +1 -1
- package/dist/src/adapters/langchain_adapter.d.ts +4 -4
- package/dist/src/adapters/langchain_adapter.d.ts.map +1 -1
- package/dist/src/agents/base.d.ts +1 -1
- package/dist/src/agents/base.d.ts.map +1 -1
- package/dist/src/agents/index.d.ts +3 -3
- package/dist/src/agents/index.d.ts.map +1 -1
- package/dist/src/agents/mcp_agent.d.ts +12 -12
- package/dist/src/agents/mcp_agent.d.ts.map +1 -1
- package/dist/src/agents/prompts/system_prompt_builder.d.ts +2 -2
- package/dist/src/agents/prompts/system_prompt_builder.d.ts.map +1 -1
- package/dist/src/agents/prompts/templates.d.ts.map +1 -1
- package/dist/src/agents/remote.d.ts +2 -2
- package/dist/src/agents/remote.d.ts.map +1 -1
- package/dist/src/agents/types.d.ts +1 -1
- package/dist/src/agents/types.d.ts.map +1 -1
- package/dist/src/agents/utils/ai_sdk.d.ts +1 -1
- package/dist/src/agents/utils/ai_sdk.d.ts.map +1 -1
- package/dist/src/agents/utils/index.d.ts +1 -1
- package/dist/src/agents/utils/index.d.ts.map +1 -1
- package/dist/src/auth/browser-provider.d.ts +2 -2
- package/dist/src/auth/browser-provider.d.ts.map +1 -1
- package/dist/src/auth/callback.d.ts.map +1 -1
- package/dist/src/auth/index.d.ts +3 -3
- package/dist/src/auth/index.d.ts.map +1 -1
- package/dist/src/auth/types.d.ts +1 -1
- package/dist/src/auth/types.d.ts.map +1 -1
- package/dist/src/browser.cjs +573 -219
- package/dist/src/browser.d.ts +17 -17
- package/dist/src/browser.d.ts.map +1 -1
- package/dist/src/browser.js +17 -46
- package/dist/src/client/base.d.ts +2 -2
- package/dist/src/client/base.d.ts.map +1 -1
- package/dist/src/client/browser.d.ts +2 -2
- package/dist/src/client/browser.d.ts.map +1 -1
- package/dist/src/client.d.ts +2 -2
- package/dist/src/client.d.ts.map +1 -1
- package/dist/src/config.d.ts +1 -1
- package/dist/src/config.d.ts.map +1 -1
- package/dist/src/connectors/base.d.ts +51 -9
- package/dist/src/connectors/base.d.ts.map +1 -1
- package/dist/src/connectors/http.d.ts +3 -3
- package/dist/src/connectors/http.d.ts.map +1 -1
- package/dist/src/connectors/index.d.ts +4 -4
- package/dist/src/connectors/index.d.ts.map +1 -1
- package/dist/src/connectors/stdio.d.ts +3 -3
- package/dist/src/connectors/stdio.d.ts.map +1 -1
- package/dist/src/connectors/websocket.d.ts +4 -7
- package/dist/src/connectors/websocket.d.ts.map +1 -1
- package/dist/src/logging.d.ts +4 -4
- package/dist/src/logging.d.ts.map +1 -1
- package/dist/src/managers/index.d.ts +2 -2
- package/dist/src/managers/index.d.ts.map +1 -1
- package/dist/src/managers/server_manager.d.ts +4 -4
- package/dist/src/managers/server_manager.d.ts.map +1 -1
- package/dist/src/managers/tools/acquire_active_mcp_server.d.ts +3 -3
- package/dist/src/managers/tools/acquire_active_mcp_server.d.ts.map +1 -1
- package/dist/src/managers/tools/add_server_from_config.d.ts +3 -3
- package/dist/src/managers/tools/add_server_from_config.d.ts.map +1 -1
- package/dist/src/managers/tools/base.d.ts +6 -6
- package/dist/src/managers/tools/base.d.ts.map +1 -1
- package/dist/src/managers/tools/connect_mcp_server.d.ts +4 -4
- package/dist/src/managers/tools/connect_mcp_server.d.ts.map +1 -1
- package/dist/src/managers/tools/index.d.ts +5 -5
- package/dist/src/managers/tools/index.d.ts.map +1 -1
- package/dist/src/managers/tools/list_mcp_servers.d.ts +3 -3
- package/dist/src/managers/tools/list_mcp_servers.d.ts.map +1 -1
- package/dist/src/managers/tools/release_mcp_server_connection.d.ts +3 -3
- package/dist/src/managers/tools/release_mcp_server_connection.d.ts.map +1 -1
- package/dist/src/managers/types.d.ts +3 -3
- package/dist/src/managers/types.d.ts.map +1 -1
- package/dist/src/oauth-helper.d.ts.map +1 -1
- package/dist/src/observability/index.d.ts +3 -3
- package/dist/src/observability/index.d.ts.map +1 -1
- package/dist/src/observability/langfuse.d.ts +1 -1
- package/dist/src/observability/langfuse.d.ts.map +1 -1
- package/dist/src/observability/manager.d.ts +1 -1
- package/dist/src/observability/manager.d.ts.map +1 -1
- package/dist/src/observability/types.d.ts +1 -1
- package/dist/src/observability/types.d.ts.map +1 -1
- package/dist/src/react/index.cjs +1571 -321
- package/dist/src/react/index.d.ts +6 -6
- package/dist/src/react/index.d.ts.map +1 -1
- package/dist/src/react/index.js +3 -2
- package/dist/src/react/types.d.ts +27 -5
- package/dist/src/react/types.d.ts.map +1 -1
- package/dist/src/react/useMcp.d.ts +32 -1
- package/dist/src/react/useMcp.d.ts.map +1 -1
- package/dist/src/react/useWidget.d.ts +5 -2
- package/dist/src/react/useWidget.d.ts.map +1 -1
- package/dist/src/react/widget-types.d.ts +3 -3
- package/dist/src/react/widget-types.d.ts.map +1 -1
- package/dist/src/server/adapters/mcp-ui-adapter.d.ts +3 -3
- package/dist/src/server/adapters/mcp-ui-adapter.d.ts.map +1 -1
- package/dist/src/server/index.cjs +170 -50
- package/dist/src/server/index.d.ts +4 -4
- package/dist/src/server/index.d.ts.map +1 -1
- package/dist/src/server/index.js +174 -51
- package/dist/src/server/logging.d.ts +1 -1
- package/dist/src/server/logging.d.ts.map +1 -1
- package/dist/src/server/mcp-server.d.ts +29 -29
- package/dist/src/server/mcp-server.d.ts.map +1 -1
- package/dist/src/server/types/common.d.ts +2 -2
- package/dist/src/server/types/common.d.ts.map +1 -1
- package/dist/src/server/types/index.d.ts +4 -4
- package/dist/src/server/types/index.d.ts.map +1 -1
- package/dist/src/server/types/prompt.d.ts +2 -2
- package/dist/src/server/types/prompt.d.ts.map +1 -1
- package/dist/src/server/types/resource.d.ts +24 -24
- package/dist/src/server/types/resource.d.ts.map +1 -1
- package/dist/src/server/types/tool.d.ts +3 -3
- package/dist/src/server/types/tool.d.ts.map +1 -1
- package/dist/src/server/types/widget.d.ts +1 -1
- package/dist/src/server/types.d.ts +1 -1
- package/dist/src/server/types.d.ts.map +1 -1
- package/dist/src/session.d.ts +1 -1
- package/dist/src/session.d.ts.map +1 -1
- package/dist/src/task_managers/base.d.ts.map +1 -1
- package/dist/src/task_managers/index.d.ts +5 -5
- package/dist/src/task_managers/index.d.ts.map +1 -1
- package/dist/src/task_managers/sse.d.ts +3 -3
- package/dist/src/task_managers/sse.d.ts.map +1 -1
- package/dist/src/task_managers/stdio.d.ts +4 -4
- package/dist/src/task_managers/stdio.d.ts.map +1 -1
- package/dist/src/task_managers/streamable_http.d.ts +3 -3
- package/dist/src/task_managers/streamable_http.d.ts.map +1 -1
- package/dist/src/task_managers/websocket.d.ts +2 -2
- package/dist/src/task_managers/websocket.d.ts.map +1 -1
- package/dist/src/telemetry/events.d.ts.map +1 -1
- package/dist/src/telemetry/index.d.ts +4 -4
- package/dist/src/telemetry/index.d.ts.map +1 -1
- package/dist/src/telemetry/telemetry.d.ts +1 -1
- package/dist/src/telemetry/telemetry.d.ts.map +1 -1
- package/dist/src/telemetry/utils.d.ts +1 -1
- package/dist/src/telemetry/utils.d.ts.map +1 -1
- package/dist/tsup.config.d.ts.map +1 -1
- package/dist/vitest.config.d.ts.map +1 -1
- package/package.json +3 -3
- package/dist/chunk-62GFHYCL.js +0 -300
- package/dist/chunk-JV7HAYUT.js +0 -860
- package/dist/chunk-ZUEQQ6YK.js +0 -444
package/dist/index.cjs
CHANGED
|
@@ -90,7 +90,15 @@ var init_logging = __esm({
|
|
|
90
90
|
this._level = level;
|
|
91
91
|
}
|
|
92
92
|
shouldLog(level) {
|
|
93
|
-
const levels = [
|
|
93
|
+
const levels = [
|
|
94
|
+
"error",
|
|
95
|
+
"warn",
|
|
96
|
+
"info",
|
|
97
|
+
"http",
|
|
98
|
+
"verbose",
|
|
99
|
+
"debug",
|
|
100
|
+
"silly"
|
|
101
|
+
];
|
|
94
102
|
const currentIndex = levels.indexOf(this._level);
|
|
95
103
|
const messageIndex = levels.indexOf(level);
|
|
96
104
|
return messageIndex <= currentIndex;
|
|
@@ -163,7 +171,10 @@ var init_logging = __esm({
|
|
|
163
171
|
if (!isNodeJSEnvironment()) {
|
|
164
172
|
if (!this.simpleInstances[name]) {
|
|
165
173
|
const debugEnv = typeof process !== "undefined" && process.env?.DEBUG || void 0;
|
|
166
|
-
this.simpleInstances[name] = new SimpleConsoleLogger(
|
|
174
|
+
this.simpleInstances[name] = new SimpleConsoleLogger(
|
|
175
|
+
name,
|
|
176
|
+
resolveLevel(debugEnv)
|
|
177
|
+
);
|
|
167
178
|
}
|
|
168
179
|
return this.simpleInstances[name];
|
|
169
180
|
}
|
|
@@ -237,10 +248,8 @@ var init_logging = __esm({
|
|
|
237
248
|
}
|
|
238
249
|
static setDebug(enabled) {
|
|
239
250
|
let level;
|
|
240
|
-
if (enabled === 2 || enabled === true)
|
|
241
|
-
|
|
242
|
-
else if (enabled === 1)
|
|
243
|
-
level = "info";
|
|
251
|
+
if (enabled === 2 || enabled === true) level = "debug";
|
|
252
|
+
else if (enabled === 1) level = "info";
|
|
244
253
|
else level = "info";
|
|
245
254
|
Object.values(this.simpleInstances).forEach((logger2) => {
|
|
246
255
|
logger2.level = level;
|
|
@@ -280,7 +289,9 @@ async function initializeLangfuse(agentId, metadata, metadataProvider, tagsProvi
|
|
|
280
289
|
try {
|
|
281
290
|
const langfuseModule = await import("langfuse-langchain").catch(() => null);
|
|
282
291
|
if (!langfuseModule) {
|
|
283
|
-
logger.debug(
|
|
292
|
+
logger.debug(
|
|
293
|
+
"Langfuse package not installed - tracing disabled. Install with: npm install @langfuse/langchain"
|
|
294
|
+
);
|
|
284
295
|
return;
|
|
285
296
|
}
|
|
286
297
|
const { CallbackHandler } = langfuseModule;
|
|
@@ -309,10 +320,23 @@ async function initializeLangfuse(agentId, metadata, metadataProvider, tagsProvi
|
|
|
309
320
|
const enhancedTags = [...tags || [], ...customTags];
|
|
310
321
|
const enhancedMetadata = { ...metadata2 || {}, ...metadataToAdd };
|
|
311
322
|
if (this.verbose) {
|
|
312
|
-
logger.debug(
|
|
313
|
-
|
|
323
|
+
logger.debug(
|
|
324
|
+
`Langfuse: Chain start with custom tags: ${JSON.stringify(enhancedTags)}`
|
|
325
|
+
);
|
|
326
|
+
logger.debug(
|
|
327
|
+
`Langfuse: Chain start with metadata: ${JSON.stringify(enhancedMetadata)}`
|
|
328
|
+
);
|
|
314
329
|
}
|
|
315
|
-
return super.handleChainStart(
|
|
330
|
+
return super.handleChainStart(
|
|
331
|
+
chain,
|
|
332
|
+
inputs,
|
|
333
|
+
runId,
|
|
334
|
+
parentRunId,
|
|
335
|
+
enhancedTags,
|
|
336
|
+
enhancedMetadata,
|
|
337
|
+
name,
|
|
338
|
+
kwargs
|
|
339
|
+
);
|
|
316
340
|
}
|
|
317
341
|
// Get custom tags based on environment and agent configuration
|
|
318
342
|
getCustomTags() {
|
|
@@ -388,7 +412,9 @@ async function initializeLangfuse(agentId, metadata, metadataProvider, tagsProvi
|
|
|
388
412
|
async handleRetrieverStart(...args) {
|
|
389
413
|
logger.debug("Langfuse: Retriever start intercepted");
|
|
390
414
|
if (this.verbose) {
|
|
391
|
-
logger.debug(
|
|
415
|
+
logger.debug(
|
|
416
|
+
`Langfuse: Retriever start args: ${JSON.stringify(args)}`
|
|
417
|
+
);
|
|
392
418
|
}
|
|
393
419
|
return super.handleRetrieverStart(...args);
|
|
394
420
|
}
|
|
@@ -414,9 +440,13 @@ async function initializeLangfuse(agentId, metadata, metadataProvider, tagsProvi
|
|
|
414
440
|
secretKey: process.env.LANGFUSE_SECRET_KEY,
|
|
415
441
|
baseUrl: process.env.LANGFUSE_HOST || process.env.LANGFUSE_BASEURL || "https://cloud.langfuse.com",
|
|
416
442
|
flushAt: Number.parseInt(process.env.LANGFUSE_FLUSH_AT || "15"),
|
|
417
|
-
flushInterval: Number.parseInt(
|
|
443
|
+
flushInterval: Number.parseInt(
|
|
444
|
+
process.env.LANGFUSE_FLUSH_INTERVAL || "10000"
|
|
445
|
+
),
|
|
418
446
|
release: process.env.LANGFUSE_RELEASE,
|
|
419
|
-
requestTimeout: Number.parseInt(
|
|
447
|
+
requestTimeout: Number.parseInt(
|
|
448
|
+
process.env.LANGFUSE_REQUEST_TIMEOUT || "10000"
|
|
449
|
+
),
|
|
420
450
|
enabled: process.env.LANGFUSE_ENABLED !== "false",
|
|
421
451
|
// Set trace name - can be customized via metadata.trace_name or defaults to 'mcp-use-agent'
|
|
422
452
|
traceName: initialMetadata.trace_name || process.env.LANGFUSE_TRACE_NAME || "mcp-use-agent",
|
|
@@ -426,14 +456,29 @@ async function initializeLangfuse(agentId, metadata, metadataProvider, tagsProvi
|
|
|
426
456
|
tags: initialTags.length > 0 ? initialTags : void 0,
|
|
427
457
|
metadata: initialMetadata || void 0
|
|
428
458
|
};
|
|
429
|
-
logger.debug(
|
|
430
|
-
|
|
431
|
-
|
|
432
|
-
|
|
433
|
-
|
|
434
|
-
|
|
435
|
-
|
|
436
|
-
|
|
459
|
+
logger.debug(
|
|
460
|
+
"Langfuse handler config:",
|
|
461
|
+
JSON.stringify(
|
|
462
|
+
{
|
|
463
|
+
traceName: config2.traceName,
|
|
464
|
+
sessionId: config2.sessionId,
|
|
465
|
+
userId: config2.userId,
|
|
466
|
+
tags: config2.tags
|
|
467
|
+
},
|
|
468
|
+
null,
|
|
469
|
+
2
|
|
470
|
+
)
|
|
471
|
+
);
|
|
472
|
+
langfuseState.handler = new LoggingCallbackHandler(
|
|
473
|
+
config2,
|
|
474
|
+
agentId,
|
|
475
|
+
metadata,
|
|
476
|
+
metadataProvider,
|
|
477
|
+
tagsProvider
|
|
478
|
+
);
|
|
479
|
+
logger.debug(
|
|
480
|
+
"Langfuse observability initialized successfully with logging enabled"
|
|
481
|
+
);
|
|
437
482
|
try {
|
|
438
483
|
const langfuseCore = await import("langfuse").catch(() => null);
|
|
439
484
|
if (langfuseCore) {
|
|
@@ -467,7 +512,9 @@ var init_langfuse = __esm({
|
|
|
467
512
|
};
|
|
468
513
|
__name(initializeLangfuse, "initializeLangfuse");
|
|
469
514
|
if (langfuseDisabled) {
|
|
470
|
-
logger.debug(
|
|
515
|
+
logger.debug(
|
|
516
|
+
"Langfuse tracing disabled via MCP_USE_LANGFUSE environment variable"
|
|
517
|
+
);
|
|
471
518
|
} else if (!process.env.LANGFUSE_PUBLIC_KEY || !process.env.LANGFUSE_SECRET_KEY) {
|
|
472
519
|
logger.debug(
|
|
473
520
|
"Langfuse API keys not found - tracing disabled. Set LANGFUSE_PUBLIC_KEY and LANGFUSE_SECRET_KEY to enable"
|
|
@@ -682,9 +729,14 @@ var LangChainAdapter = class extends BaseAdapter {
|
|
|
682
729
|
// Blank is acceptable but discouraged.
|
|
683
730
|
schema: argsSchema,
|
|
684
731
|
func: /* @__PURE__ */ __name(async (input) => {
|
|
685
|
-
logger.debug(
|
|
732
|
+
logger.debug(
|
|
733
|
+
`MCP tool "${mcpTool.name}" received input: ${JSON.stringify(input)}`
|
|
734
|
+
);
|
|
686
735
|
try {
|
|
687
|
-
const result = await connector.callTool(
|
|
736
|
+
const result = await connector.callTool(
|
|
737
|
+
mcpTool.name,
|
|
738
|
+
input
|
|
739
|
+
);
|
|
688
740
|
return JSON.stringify(result);
|
|
689
741
|
} catch (err) {
|
|
690
742
|
logger.error(`Error executing MCP tool: ${err.message}`);
|
|
@@ -844,7 +896,9 @@ var ConnectMCPServerTool = class extends MCPServerTool {
|
|
|
844
896
|
const numTools = serverTools.length;
|
|
845
897
|
return `Connected to MCP server '${serverName}'. ${numTools} tools are now available.`;
|
|
846
898
|
} catch (error) {
|
|
847
|
-
logger.error(
|
|
899
|
+
logger.error(
|
|
900
|
+
`Error connecting to server '${serverName}': ${String(error)}`
|
|
901
|
+
);
|
|
848
902
|
return `Failed to connect to server '${serverName}': ${String(error)}`;
|
|
849
903
|
}
|
|
850
904
|
}
|
|
@@ -880,7 +934,9 @@ var ListMCPServersTool = class extends MCPServerTool {
|
|
|
880
934
|
outputLines.push(`${numberOfTools} tools available for this server
|
|
881
935
|
`);
|
|
882
936
|
} catch (error) {
|
|
883
|
-
logger.error(
|
|
937
|
+
logger.error(
|
|
938
|
+
`Unexpected error listing tools for server '${serverName}': ${String(error)}`
|
|
939
|
+
);
|
|
884
940
|
}
|
|
885
941
|
}
|
|
886
942
|
return outputLines.join("\n");
|
|
@@ -941,10 +997,10 @@ var ServerManager = class {
|
|
|
941
997
|
}
|
|
942
998
|
const tableData = allServerNames.map((name) => ({
|
|
943
999
|
"Server Name": name,
|
|
944
|
-
|
|
945
|
-
|
|
1000
|
+
Connected: activeSessionNames.includes(name) ? "\u2705" : "\u274C",
|
|
1001
|
+
Initialized: this.initializedServers[name] ? "\u2705" : "\u274C",
|
|
946
1002
|
"Tool Count": this.serverTools[name]?.length ?? 0,
|
|
947
|
-
|
|
1003
|
+
Active: this.activeServer === name ? "\u2705" : "\u274C"
|
|
948
1004
|
}));
|
|
949
1005
|
logger.info(`Server Manager State: [${context}]`);
|
|
950
1006
|
console.table(tableData);
|
|
@@ -961,13 +1017,19 @@ var ServerManager = class {
|
|
|
961
1017
|
try {
|
|
962
1018
|
let session = null;
|
|
963
1019
|
session = this.client.getSession(serverName);
|
|
964
|
-
logger.debug(
|
|
1020
|
+
logger.debug(
|
|
1021
|
+
`Using existing session for server '${serverName}' to prefetch tools.`
|
|
1022
|
+
);
|
|
965
1023
|
if (!session) {
|
|
966
1024
|
session = await this.client.createSession(serverName).catch((createSessionError) => {
|
|
967
|
-
logger.warn(
|
|
1025
|
+
logger.warn(
|
|
1026
|
+
`Could not create session for '${serverName}' during prefetch: ${createSessionError}`
|
|
1027
|
+
);
|
|
968
1028
|
return null;
|
|
969
1029
|
});
|
|
970
|
-
logger.debug(
|
|
1030
|
+
logger.debug(
|
|
1031
|
+
`Temporarily created session for '${serverName}' to prefetch tools.`
|
|
1032
|
+
);
|
|
971
1033
|
}
|
|
972
1034
|
if (session) {
|
|
973
1035
|
const connector = session.connector;
|
|
@@ -975,7 +1037,9 @@ var ServerManager = class {
|
|
|
975
1037
|
try {
|
|
976
1038
|
tools = await this.adapter.createToolsFromConnectors([connector]);
|
|
977
1039
|
} catch (toolFetchError) {
|
|
978
|
-
logger.error(
|
|
1040
|
+
logger.error(
|
|
1041
|
+
`Failed to create tools from connector for server '${serverName}': ${toolFetchError}`
|
|
1042
|
+
);
|
|
979
1043
|
continue;
|
|
980
1044
|
}
|
|
981
1045
|
const cachedTools = this.serverTools[serverName];
|
|
@@ -983,7 +1047,9 @@ var ServerManager = class {
|
|
|
983
1047
|
if (toolsChanged) {
|
|
984
1048
|
this.serverTools[serverName] = tools;
|
|
985
1049
|
this.initializedServers[serverName] = true;
|
|
986
|
-
logger.debug(
|
|
1050
|
+
logger.debug(
|
|
1051
|
+
`Prefetched ${tools.length} tools for server '${serverName}'.`
|
|
1052
|
+
);
|
|
987
1053
|
} else {
|
|
988
1054
|
logger.debug(
|
|
989
1055
|
`Tools for server '${serverName}' unchanged, using cached version.`
|
|
@@ -991,7 +1057,9 @@ var ServerManager = class {
|
|
|
991
1057
|
}
|
|
992
1058
|
}
|
|
993
1059
|
} catch (outerError) {
|
|
994
|
-
logger.error(
|
|
1060
|
+
logger.error(
|
|
1061
|
+
`Error prefetching tools for server '${serverName}': ${outerError}`
|
|
1062
|
+
);
|
|
995
1063
|
}
|
|
996
1064
|
}
|
|
997
1065
|
}
|
|
@@ -1057,8 +1125,15 @@ var ObservabilityManager = class {
|
|
|
1057
1125
|
const { langfuseHandler: langfuseHandler2, langfuseInitPromise: langfuseInitPromise2 } = await Promise.resolve().then(() => (init_langfuse(), langfuse_exports));
|
|
1058
1126
|
if (this.agentId || this.metadata || this.metadataProvider || this.tagsProvider) {
|
|
1059
1127
|
const { initializeLangfuse: initializeLangfuse2 } = await Promise.resolve().then(() => (init_langfuse(), langfuse_exports));
|
|
1060
|
-
await initializeLangfuse2(
|
|
1061
|
-
|
|
1128
|
+
await initializeLangfuse2(
|
|
1129
|
+
this.agentId,
|
|
1130
|
+
this.metadata,
|
|
1131
|
+
this.metadataProvider,
|
|
1132
|
+
this.tagsProvider
|
|
1133
|
+
);
|
|
1134
|
+
logger.debug(
|
|
1135
|
+
`ObservabilityManager: Reinitialized Langfuse with agent ID: ${this.agentId}, metadata: ${JSON.stringify(this.metadata)}`
|
|
1136
|
+
);
|
|
1062
1137
|
} else {
|
|
1063
1138
|
const initPromise = langfuseInitPromise2();
|
|
1064
1139
|
if (initPromise) {
|
|
@@ -1082,16 +1157,22 @@ var ObservabilityManager = class {
|
|
|
1082
1157
|
*/
|
|
1083
1158
|
async getCallbacks() {
|
|
1084
1159
|
if (!this.observe) {
|
|
1085
|
-
logger.debug(
|
|
1160
|
+
logger.debug(
|
|
1161
|
+
"ObservabilityManager: Observability disabled via observe=false"
|
|
1162
|
+
);
|
|
1086
1163
|
return [];
|
|
1087
1164
|
}
|
|
1088
1165
|
if (this.customCallbacks) {
|
|
1089
|
-
logger.debug(
|
|
1166
|
+
logger.debug(
|
|
1167
|
+
`ObservabilityManager: Using ${this.customCallbacks.length} custom callbacks`
|
|
1168
|
+
);
|
|
1090
1169
|
return this.customCallbacks;
|
|
1091
1170
|
}
|
|
1092
1171
|
await this.collectAvailableHandlers();
|
|
1093
1172
|
if (this.availableHandlers.length > 0) {
|
|
1094
|
-
logger.debug(
|
|
1173
|
+
logger.debug(
|
|
1174
|
+
`ObservabilityManager: Using ${this.availableHandlers.length} handlers`
|
|
1175
|
+
);
|
|
1095
1176
|
} else {
|
|
1096
1177
|
logger.debug("ObservabilityManager: No callbacks configured");
|
|
1097
1178
|
}
|
|
@@ -1148,7 +1229,9 @@ var ObservabilityManager = class {
|
|
|
1148
1229
|
this.customCallbacks = [];
|
|
1149
1230
|
}
|
|
1150
1231
|
this.customCallbacks.push(callback);
|
|
1151
|
-
logger.debug(
|
|
1232
|
+
logger.debug(
|
|
1233
|
+
`ObservabilityManager: Added custom callback: ${callback.constructor.name}`
|
|
1234
|
+
);
|
|
1152
1235
|
}
|
|
1153
1236
|
/**
|
|
1154
1237
|
* Clear all custom callbacks.
|
|
@@ -1280,7 +1363,15 @@ function getModelName(llm) {
|
|
|
1280
1363
|
if ("_identifyingParams" in llm) {
|
|
1281
1364
|
const identifyingParams = llm._identifyingParams;
|
|
1282
1365
|
if (typeof identifyingParams === "object" && identifyingParams !== null) {
|
|
1283
|
-
for (const key of [
|
|
1366
|
+
for (const key of [
|
|
1367
|
+
"model",
|
|
1368
|
+
"modelName",
|
|
1369
|
+
"model_name",
|
|
1370
|
+
"modelId",
|
|
1371
|
+
"model_id",
|
|
1372
|
+
"deploymentName",
|
|
1373
|
+
"deployment_name"
|
|
1374
|
+
]) {
|
|
1284
1375
|
if (key in identifyingParams) {
|
|
1285
1376
|
return String(identifyingParams[key]);
|
|
1286
1377
|
}
|
|
@@ -1371,8 +1462,16 @@ var Telemetry = class _Telemetry {
|
|
|
1371
1462
|
__name(this, "Telemetry");
|
|
1372
1463
|
}
|
|
1373
1464
|
static instance = null;
|
|
1374
|
-
USER_ID_PATH = path2.join(
|
|
1375
|
-
|
|
1465
|
+
USER_ID_PATH = path2.join(
|
|
1466
|
+
getCacheHome(),
|
|
1467
|
+
"mcp_use_3",
|
|
1468
|
+
"telemetry_user_id"
|
|
1469
|
+
);
|
|
1470
|
+
VERSION_DOWNLOAD_PATH = path2.join(
|
|
1471
|
+
getCacheHome(),
|
|
1472
|
+
"mcp_use",
|
|
1473
|
+
"download_version"
|
|
1474
|
+
);
|
|
1376
1475
|
PROJECT_API_KEY = "phc_lyTtbYwvkdSbrcMQNPiKiiRWrrM1seyKIMjycSvItEI";
|
|
1377
1476
|
HOST = "https://eu.i.posthog.com";
|
|
1378
1477
|
SCARF_GATEWAY_URL = "https://mcpuse.gateway.scarf.sh/events-ts";
|
|
@@ -1392,17 +1491,18 @@ var Telemetry = class _Telemetry {
|
|
|
1392
1491
|
} else if (!isNodeJS) {
|
|
1393
1492
|
this._posthogClient = null;
|
|
1394
1493
|
this._scarfClient = null;
|
|
1395
|
-
logger.debug(
|
|
1494
|
+
logger.debug(
|
|
1495
|
+
"Telemetry disabled - non-Node.js environment detected (e.g., Cloudflare Workers)"
|
|
1496
|
+
);
|
|
1396
1497
|
} else {
|
|
1397
|
-
logger.info(
|
|
1498
|
+
logger.info(
|
|
1499
|
+
"Anonymized telemetry enabled. Set MCP_USE_ANONYMIZED_TELEMETRY=false to disable."
|
|
1500
|
+
);
|
|
1398
1501
|
try {
|
|
1399
|
-
this._posthogClient = new import_posthog_node.PostHog(
|
|
1400
|
-
this.
|
|
1401
|
-
|
|
1402
|
-
|
|
1403
|
-
disableGeoip: false
|
|
1404
|
-
}
|
|
1405
|
-
);
|
|
1502
|
+
this._posthogClient = new import_posthog_node.PostHog(this.PROJECT_API_KEY, {
|
|
1503
|
+
host: this.HOST,
|
|
1504
|
+
disableGeoip: false
|
|
1505
|
+
});
|
|
1406
1506
|
} catch (e) {
|
|
1407
1507
|
logger.warn(`Failed to initialize PostHog telemetry: ${e}`);
|
|
1408
1508
|
this._posthogClient = null;
|
|
@@ -1512,7 +1612,9 @@ var Telemetry = class _Telemetry {
|
|
|
1512
1612
|
if (!fs2.existsSync(this.VERSION_DOWNLOAD_PATH)) {
|
|
1513
1613
|
shouldTrack = true;
|
|
1514
1614
|
firstDownload = true;
|
|
1515
|
-
fs2.mkdirSync(path2.dirname(this.VERSION_DOWNLOAD_PATH), {
|
|
1615
|
+
fs2.mkdirSync(path2.dirname(this.VERSION_DOWNLOAD_PATH), {
|
|
1616
|
+
recursive: true
|
|
1617
|
+
});
|
|
1516
1618
|
fs2.writeFileSync(this.VERSION_DOWNLOAD_PATH, currentVersion);
|
|
1517
1619
|
} else {
|
|
1518
1620
|
const savedVersion = fs2.readFileSync(this.VERSION_DOWNLOAD_PATH, "utf-8").trim();
|
|
@@ -1523,7 +1625,9 @@ var Telemetry = class _Telemetry {
|
|
|
1523
1625
|
}
|
|
1524
1626
|
}
|
|
1525
1627
|
if (shouldTrack) {
|
|
1526
|
-
logger.debug(
|
|
1628
|
+
logger.debug(
|
|
1629
|
+
`Tracking package download event with properties: ${JSON.stringify(properties)}`
|
|
1630
|
+
);
|
|
1527
1631
|
const eventProperties = { ...properties || {} };
|
|
1528
1632
|
eventProperties.mcp_use_version = currentVersion;
|
|
1529
1633
|
eventProperties.user_id = this.userId;
|
|
@@ -1581,8 +1685,7 @@ function generateToolDescriptions(tools, disallowedTools) {
|
|
|
1581
1685
|
const disallowedSet = new Set(disallowedTools ?? []);
|
|
1582
1686
|
const descriptions = [];
|
|
1583
1687
|
for (const tool of tools) {
|
|
1584
|
-
if (disallowedSet.has(tool.name))
|
|
1585
|
-
continue;
|
|
1688
|
+
if (disallowedSet.has(tool.name)) continue;
|
|
1586
1689
|
const escaped = tool.description.replace(/\{/g, "{{").replace(/\}/g, "}}");
|
|
1587
1690
|
descriptions.push(`- ${tool.name}: ${escaped}`);
|
|
1588
1691
|
}
|
|
@@ -1595,7 +1698,9 @@ function buildSystemPromptContent(template, toolDescriptionLines, additionalInst
|
|
|
1595
1698
|
if (template.includes("{tool_descriptions}")) {
|
|
1596
1699
|
content = template.replace("{tool_descriptions}", block);
|
|
1597
1700
|
} else {
|
|
1598
|
-
console.warn(
|
|
1701
|
+
console.warn(
|
|
1702
|
+
"`{tool_descriptions}` placeholder not found; appending at end."
|
|
1703
|
+
);
|
|
1599
1704
|
content = `${template}
|
|
1600
1705
|
|
|
1601
1706
|
Available tools:
|
|
@@ -1751,7 +1856,9 @@ var RemoteAgent = class {
|
|
|
1751
1856
|
`Agent not found: Agent '${this.agentId}' does not exist or you don't have access to it. Please verify the agent ID and ensure it exists in your account.`
|
|
1752
1857
|
);
|
|
1753
1858
|
}
|
|
1754
|
-
throw new Error(
|
|
1859
|
+
throw new Error(
|
|
1860
|
+
`Failed to create chat session: ${statusCode} - ${responseText}`
|
|
1861
|
+
);
|
|
1755
1862
|
}
|
|
1756
1863
|
const chatData = await response.json();
|
|
1757
1864
|
const chatId = chatData.id;
|
|
@@ -1824,8 +1931,12 @@ var RemoteAgent = class {
|
|
|
1824
1931
|
"Internal server error occurred during agent execution. Please try again later or contact support if the issue persists."
|
|
1825
1932
|
);
|
|
1826
1933
|
} else {
|
|
1827
|
-
logger.error(
|
|
1828
|
-
|
|
1934
|
+
logger.error(
|
|
1935
|
+
`\u274C Remote execution failed with status ${statusCode}: ${responseText}`
|
|
1936
|
+
);
|
|
1937
|
+
throw new Error(
|
|
1938
|
+
`Remote agent execution failed: ${statusCode} - ${responseText}`
|
|
1939
|
+
);
|
|
1829
1940
|
}
|
|
1830
1941
|
}
|
|
1831
1942
|
const result = await response.json();
|
|
@@ -1876,7 +1987,13 @@ Raw error: ${result}`
|
|
|
1876
1987
|
}
|
|
1877
1988
|
// eslint-disable-next-line require-yield
|
|
1878
1989
|
async *stream(query, maxSteps, manageConnector, externalHistory, outputSchema) {
|
|
1879
|
-
const result = await this.run(
|
|
1990
|
+
const result = await this.run(
|
|
1991
|
+
query,
|
|
1992
|
+
maxSteps,
|
|
1993
|
+
manageConnector,
|
|
1994
|
+
externalHistory,
|
|
1995
|
+
outputSchema
|
|
1996
|
+
);
|
|
1880
1997
|
return result;
|
|
1881
1998
|
}
|
|
1882
1999
|
async close() {
|
|
@@ -1952,7 +2069,9 @@ var MCPAgent = class {
|
|
|
1952
2069
|
return;
|
|
1953
2070
|
}
|
|
1954
2071
|
if (!options.llm) {
|
|
1955
|
-
throw new Error(
|
|
2072
|
+
throw new Error(
|
|
2073
|
+
"llm is required for local execution. For remote execution, provide agentId instead."
|
|
2074
|
+
);
|
|
1956
2075
|
}
|
|
1957
2076
|
this.llm = options.llm;
|
|
1958
2077
|
this.client = options.client;
|
|
@@ -1970,11 +2089,15 @@ var MCPAgent = class {
|
|
|
1970
2089
|
this.verbose = options.verbose ?? false;
|
|
1971
2090
|
this.observe = options.observe ?? true;
|
|
1972
2091
|
if (!this.client && this.connectors.length === 0) {
|
|
1973
|
-
throw new Error(
|
|
2092
|
+
throw new Error(
|
|
2093
|
+
"Either 'client' or at least one 'connector' must be provided."
|
|
2094
|
+
);
|
|
1974
2095
|
}
|
|
1975
2096
|
if (this.useServerManager) {
|
|
1976
2097
|
if (!this.client) {
|
|
1977
|
-
throw new Error(
|
|
2098
|
+
throw new Error(
|
|
2099
|
+
"'client' must be provided when 'useServerManager' is true."
|
|
2100
|
+
);
|
|
1978
2101
|
}
|
|
1979
2102
|
this.adapter = options.adapter ?? new LangChainAdapter(this.disallowedTools);
|
|
1980
2103
|
this.serverManager = options.serverManagerFactory?.(this.client) ?? new ServerManager(this.client, this.adapter);
|
|
@@ -2034,25 +2157,37 @@ var MCPAgent = class {
|
|
|
2034
2157
|
} else {
|
|
2035
2158
|
if (this.client) {
|
|
2036
2159
|
this.sessions = this.client.getAllActiveSessions();
|
|
2037
|
-
logger.info(
|
|
2160
|
+
logger.info(
|
|
2161
|
+
`\u{1F50C} Found ${Object.keys(this.sessions).length} existing sessions`
|
|
2162
|
+
);
|
|
2038
2163
|
if (Object.keys(this.sessions).length === 0) {
|
|
2039
2164
|
logger.info("\u{1F504} No active sessions found, creating new ones...");
|
|
2040
2165
|
this.sessions = await this.client.createAllSessions();
|
|
2041
|
-
logger.info(
|
|
2166
|
+
logger.info(
|
|
2167
|
+
`\u2705 Created ${Object.keys(this.sessions).length} new sessions`
|
|
2168
|
+
);
|
|
2042
2169
|
}
|
|
2043
2170
|
this._tools = await LangChainAdapter.createTools(this.client);
|
|
2044
2171
|
this._tools.push(...this.additionalTools);
|
|
2045
|
-
logger.info(
|
|
2172
|
+
logger.info(
|
|
2173
|
+
`\u{1F6E0}\uFE0F Created ${this._tools.length} LangChain tools from client`
|
|
2174
|
+
);
|
|
2046
2175
|
} else {
|
|
2047
|
-
logger.info(
|
|
2176
|
+
logger.info(
|
|
2177
|
+
`\u{1F517} Connecting to ${this.connectors.length} direct connectors...`
|
|
2178
|
+
);
|
|
2048
2179
|
for (const connector of this.connectors) {
|
|
2049
2180
|
if (!connector.isClientConnected) {
|
|
2050
2181
|
await connector.connect();
|
|
2051
2182
|
}
|
|
2052
2183
|
}
|
|
2053
|
-
this._tools = await this.adapter.createToolsFromConnectors(
|
|
2184
|
+
this._tools = await this.adapter.createToolsFromConnectors(
|
|
2185
|
+
this.connectors
|
|
2186
|
+
);
|
|
2054
2187
|
this._tools.push(...this.additionalTools);
|
|
2055
|
-
logger.info(
|
|
2188
|
+
logger.info(
|
|
2189
|
+
`\u{1F6E0}\uFE0F Created ${this._tools.length} LangChain tools from connectors`
|
|
2190
|
+
);
|
|
2056
2191
|
}
|
|
2057
2192
|
logger.info(`\u{1F9F0} Found ${this._tools.length} tools across all connectors`);
|
|
2058
2193
|
await this.createSystemMessageFromTools(this._tools);
|
|
@@ -2062,7 +2197,9 @@ var MCPAgent = class {
|
|
|
2062
2197
|
const mcpServerInfo = this.getMCPServerInfo();
|
|
2063
2198
|
if (Object.keys(mcpServerInfo).length > 0) {
|
|
2064
2199
|
this.setMetadata(mcpServerInfo);
|
|
2065
|
-
logger.debug(
|
|
2200
|
+
logger.debug(
|
|
2201
|
+
`MCP server info added to metadata: ${JSON.stringify(mcpServerInfo)}`
|
|
2202
|
+
);
|
|
2066
2203
|
}
|
|
2067
2204
|
logger.info("\u2728 Agent initialization complete");
|
|
2068
2205
|
}
|
|
@@ -2080,7 +2217,9 @@ var MCPAgent = class {
|
|
|
2080
2217
|
if (this.memoryEnabled) {
|
|
2081
2218
|
this.conversationHistory = [
|
|
2082
2219
|
this.systemMessage,
|
|
2083
|
-
...this.conversationHistory.filter(
|
|
2220
|
+
...this.conversationHistory.filter(
|
|
2221
|
+
(m) => !(m instanceof import_langchain2.SystemMessage)
|
|
2222
|
+
)
|
|
2084
2223
|
];
|
|
2085
2224
|
}
|
|
2086
2225
|
}
|
|
@@ -2098,7 +2237,9 @@ var MCPAgent = class {
|
|
|
2098
2237
|
systemPrompt: systemContent,
|
|
2099
2238
|
middleware
|
|
2100
2239
|
});
|
|
2101
|
-
logger.debug(
|
|
2240
|
+
logger.debug(
|
|
2241
|
+
`Created agent with max_steps=${this.maxSteps} (via ModelCallLimitMiddleware) and ${this.callbacks.length} callbacks`
|
|
2242
|
+
);
|
|
2102
2243
|
return agent;
|
|
2103
2244
|
}
|
|
2104
2245
|
getConversationHistory() {
|
|
@@ -2108,8 +2249,7 @@ var MCPAgent = class {
|
|
|
2108
2249
|
this.conversationHistory = this.memoryEnabled && this.systemMessage ? [this.systemMessage] : [];
|
|
2109
2250
|
}
|
|
2110
2251
|
addToHistory(message) {
|
|
2111
|
-
if (this.memoryEnabled)
|
|
2112
|
-
this.conversationHistory.push(message);
|
|
2252
|
+
if (this.memoryEnabled) this.conversationHistory.push(message);
|
|
2113
2253
|
}
|
|
2114
2254
|
getSystemMessage() {
|
|
2115
2255
|
return this.systemMessage;
|
|
@@ -2117,7 +2257,9 @@ var MCPAgent = class {
|
|
|
2117
2257
|
setSystemMessage(message) {
|
|
2118
2258
|
this.systemMessage = new import_langchain2.SystemMessage(message);
|
|
2119
2259
|
if (this.memoryEnabled) {
|
|
2120
|
-
this.conversationHistory = this.conversationHistory.filter(
|
|
2260
|
+
this.conversationHistory = this.conversationHistory.filter(
|
|
2261
|
+
(m) => !(m instanceof import_langchain2.SystemMessage)
|
|
2262
|
+
);
|
|
2121
2263
|
this.conversationHistory.unshift(this.systemMessage);
|
|
2122
2264
|
}
|
|
2123
2265
|
if (this._initialized && this._tools.length) {
|
|
@@ -2129,7 +2271,9 @@ var MCPAgent = class {
|
|
|
2129
2271
|
this.disallowedTools = disallowedTools;
|
|
2130
2272
|
this.adapter = new LangChainAdapter(this.disallowedTools);
|
|
2131
2273
|
if (this._initialized) {
|
|
2132
|
-
logger.debug(
|
|
2274
|
+
logger.debug(
|
|
2275
|
+
"Agent already initialized. Changes will take effect on next initialization."
|
|
2276
|
+
);
|
|
2133
2277
|
}
|
|
2134
2278
|
}
|
|
2135
2279
|
getDisallowedTools() {
|
|
@@ -2195,16 +2339,22 @@ var MCPAgent = class {
|
|
|
2195
2339
|
try {
|
|
2196
2340
|
const serialized = JSON.stringify(value);
|
|
2197
2341
|
if (serialized.length > 1e3) {
|
|
2198
|
-
logger.warn(
|
|
2342
|
+
logger.warn(
|
|
2343
|
+
`Metadata value for key '${sanitizedKey}' is too large. Truncating.`
|
|
2344
|
+
);
|
|
2199
2345
|
sanitized[sanitizedKey] = `${serialized.substring(0, 1e3)}...`;
|
|
2200
2346
|
} else {
|
|
2201
2347
|
sanitized[sanitizedKey] = value;
|
|
2202
2348
|
}
|
|
2203
2349
|
} catch (error) {
|
|
2204
|
-
logger.warn(
|
|
2350
|
+
logger.warn(
|
|
2351
|
+
`Failed to serialize metadata value for key '${sanitizedKey}': ${error}. Skipping.`
|
|
2352
|
+
);
|
|
2205
2353
|
}
|
|
2206
2354
|
} else {
|
|
2207
|
-
logger.warn(
|
|
2355
|
+
logger.warn(
|
|
2356
|
+
`Unsupported metadata value type for key '${sanitizedKey}': ${typeof value}. Skipping.`
|
|
2357
|
+
);
|
|
2208
2358
|
}
|
|
2209
2359
|
}
|
|
2210
2360
|
return sanitized;
|
|
@@ -2251,15 +2401,24 @@ var MCPAgent = class {
|
|
|
2251
2401
|
};
|
|
2252
2402
|
}
|
|
2253
2403
|
} catch (error) {
|
|
2254
|
-
logger.warn(
|
|
2255
|
-
|
|
2404
|
+
logger.warn(
|
|
2405
|
+
`Failed to get config for server '${serverName}': ${error}`
|
|
2406
|
+
);
|
|
2407
|
+
serverConfigs[serverName] = {
|
|
2408
|
+
type: "error",
|
|
2409
|
+
error: "config_unavailable"
|
|
2410
|
+
};
|
|
2256
2411
|
}
|
|
2257
2412
|
}
|
|
2258
2413
|
serverInfo.mcp_server_configs = serverConfigs;
|
|
2259
2414
|
} else if (this.connectors && this.connectors.length > 0) {
|
|
2260
2415
|
serverInfo.mcp_servers_count = this.connectors.length;
|
|
2261
|
-
serverInfo.mcp_server_names = this.connectors.map(
|
|
2262
|
-
|
|
2416
|
+
serverInfo.mcp_server_names = this.connectors.map(
|
|
2417
|
+
(c) => c.publicIdentifier
|
|
2418
|
+
);
|
|
2419
|
+
serverInfo.mcp_server_types = this.connectors.map(
|
|
2420
|
+
(c) => c.constructor.name
|
|
2421
|
+
);
|
|
2263
2422
|
}
|
|
2264
2423
|
} catch (error) {
|
|
2265
2424
|
logger.warn(`Failed to collect MCP server info: ${error}`);
|
|
@@ -2313,7 +2472,13 @@ var MCPAgent = class {
|
|
|
2313
2472
|
}
|
|
2314
2473
|
async run(query, maxSteps, manageConnector, externalHistory, outputSchema) {
|
|
2315
2474
|
if (this.isRemote && this.remoteAgent) {
|
|
2316
|
-
return this.remoteAgent.run(
|
|
2475
|
+
return this.remoteAgent.run(
|
|
2476
|
+
query,
|
|
2477
|
+
maxSteps,
|
|
2478
|
+
manageConnector,
|
|
2479
|
+
externalHistory,
|
|
2480
|
+
outputSchema
|
|
2481
|
+
);
|
|
2317
2482
|
}
|
|
2318
2483
|
const generator = this.stream(
|
|
2319
2484
|
query,
|
|
@@ -2326,7 +2491,13 @@ var MCPAgent = class {
|
|
|
2326
2491
|
}
|
|
2327
2492
|
async *stream(query, maxSteps, manageConnector = true, externalHistory, outputSchema) {
|
|
2328
2493
|
if (this.isRemote && this.remoteAgent) {
|
|
2329
|
-
const result = await this.remoteAgent.run(
|
|
2494
|
+
const result = await this.remoteAgent.run(
|
|
2495
|
+
query,
|
|
2496
|
+
maxSteps,
|
|
2497
|
+
manageConnector,
|
|
2498
|
+
externalHistory,
|
|
2499
|
+
outputSchema
|
|
2500
|
+
);
|
|
2330
2501
|
return result;
|
|
2331
2502
|
}
|
|
2332
2503
|
let initializedHere = false;
|
|
@@ -2371,27 +2542,31 @@ var MCPAgent = class {
|
|
|
2371
2542
|
logger.info("\u{1F3C1} Starting agent execution");
|
|
2372
2543
|
const maxRestarts = 3;
|
|
2373
2544
|
let restartCount = 0;
|
|
2374
|
-
const accumulatedMessages = [
|
|
2545
|
+
const accumulatedMessages = [
|
|
2546
|
+
...langchainHistory,
|
|
2547
|
+
new import_langchain2.HumanMessage(query)
|
|
2548
|
+
];
|
|
2375
2549
|
while (restartCount <= maxRestarts) {
|
|
2376
2550
|
const inputs = { messages: accumulatedMessages };
|
|
2377
2551
|
let shouldRestart = false;
|
|
2378
|
-
const stream = await this._agentExecutor.stream(
|
|
2379
|
-
|
|
2380
|
-
|
|
2381
|
-
|
|
2382
|
-
|
|
2383
|
-
|
|
2384
|
-
|
|
2385
|
-
|
|
2386
|
-
|
|
2387
|
-
|
|
2388
|
-
|
|
2389
|
-
...this.metadata.session_id && { sessionId: this.metadata.session_id }
|
|
2552
|
+
const stream = await this._agentExecutor.stream(inputs, {
|
|
2553
|
+
streamMode: "updates",
|
|
2554
|
+
// Get updates as they happen
|
|
2555
|
+
callbacks: this.callbacks,
|
|
2556
|
+
metadata: this.getMetadata(),
|
|
2557
|
+
tags: this.getTags(),
|
|
2558
|
+
// Set trace name for LangChain/Langfuse
|
|
2559
|
+
runName: this.metadata.trace_name || "mcp-use-agent",
|
|
2560
|
+
// Pass sessionId for Langfuse if present in metadata
|
|
2561
|
+
...this.metadata.session_id && {
|
|
2562
|
+
sessionId: this.metadata.session_id
|
|
2390
2563
|
}
|
|
2391
|
-
);
|
|
2564
|
+
});
|
|
2392
2565
|
for await (const chunk of stream) {
|
|
2393
2566
|
for (const [nodeName, nodeOutput] of Object.entries(chunk)) {
|
|
2394
|
-
logger.debug(
|
|
2567
|
+
logger.debug(
|
|
2568
|
+
`\u{1F4E6} Node '${nodeName}' output: ${JSON.stringify(nodeOutput)}`
|
|
2569
|
+
);
|
|
2395
2570
|
if (nodeOutput && typeof nodeOutput === "object" && "messages" in nodeOutput) {
|
|
2396
2571
|
let messages = nodeOutput.messages;
|
|
2397
2572
|
if (!Array.isArray(messages)) {
|
|
@@ -2413,7 +2588,9 @@ var MCPAgent = class {
|
|
|
2413
2588
|
if (toolInputStr.length > 100) {
|
|
2414
2589
|
toolInputStr = `${toolInputStr.slice(0, 97)}...`;
|
|
2415
2590
|
}
|
|
2416
|
-
logger.info(
|
|
2591
|
+
logger.info(
|
|
2592
|
+
`\u{1F527} Tool call: ${toolName} with input: ${toolInputStr}`
|
|
2593
|
+
);
|
|
2417
2594
|
yield {
|
|
2418
2595
|
action: {
|
|
2419
2596
|
tool: toolName,
|
|
@@ -2435,9 +2612,15 @@ var MCPAgent = class {
|
|
|
2435
2612
|
logger.info(`\u{1F4C4} Tool result: ${observationStr}`);
|
|
2436
2613
|
if (this.useServerManager && this.serverManager) {
|
|
2437
2614
|
const currentTools = this.serverManager.tools;
|
|
2438
|
-
const currentToolNames = new Set(
|
|
2439
|
-
|
|
2440
|
-
|
|
2615
|
+
const currentToolNames = new Set(
|
|
2616
|
+
currentTools.map((t) => t.name)
|
|
2617
|
+
);
|
|
2618
|
+
const existingToolNames = new Set(
|
|
2619
|
+
this._tools.map((t) => t.name)
|
|
2620
|
+
);
|
|
2621
|
+
if (currentToolNames.size !== existingToolNames.size || [...currentToolNames].some(
|
|
2622
|
+
(n) => !existingToolNames.has(n)
|
|
2623
|
+
)) {
|
|
2441
2624
|
logger.info(
|
|
2442
2625
|
`\u{1F504} Tools changed during execution. New tools: ${[...currentToolNames].join(", ")}`
|
|
2443
2626
|
);
|
|
@@ -2472,7 +2655,9 @@ var MCPAgent = class {
|
|
|
2472
2655
|
break;
|
|
2473
2656
|
}
|
|
2474
2657
|
if (restartCount > maxRestarts) {
|
|
2475
|
-
logger.warn(
|
|
2658
|
+
logger.warn(
|
|
2659
|
+
`\u26A0\uFE0F Max restarts (${maxRestarts}) reached. Continuing with current tools.`
|
|
2660
|
+
);
|
|
2476
2661
|
break;
|
|
2477
2662
|
}
|
|
2478
2663
|
}
|
|
@@ -2491,17 +2676,25 @@ var MCPAgent = class {
|
|
|
2491
2676
|
outputSchema
|
|
2492
2677
|
);
|
|
2493
2678
|
if (this.memoryEnabled) {
|
|
2494
|
-
this.addToHistory(
|
|
2679
|
+
this.addToHistory(
|
|
2680
|
+
new import_langchain2.AIMessage(
|
|
2681
|
+
`Structured result: ${JSON.stringify(structuredResult)}`
|
|
2682
|
+
)
|
|
2683
|
+
);
|
|
2495
2684
|
}
|
|
2496
2685
|
logger.info("\u2705 Structured output successful");
|
|
2497
2686
|
success = true;
|
|
2498
2687
|
return structuredResult;
|
|
2499
2688
|
} catch (e) {
|
|
2500
2689
|
logger.error(`\u274C Structured output failed: ${e}`);
|
|
2501
|
-
throw new Error(
|
|
2690
|
+
throw new Error(
|
|
2691
|
+
`Failed to generate structured output: ${e instanceof Error ? e.message : String(e)}`
|
|
2692
|
+
);
|
|
2502
2693
|
}
|
|
2503
2694
|
}
|
|
2504
|
-
logger.info(
|
|
2695
|
+
logger.info(
|
|
2696
|
+
`\u{1F389} Agent execution complete in ${((Date.now() - startTime) / 1e3).toFixed(2)} seconds`
|
|
2697
|
+
);
|
|
2505
2698
|
success = true;
|
|
2506
2699
|
return finalOutput || "No output generated";
|
|
2507
2700
|
} catch (e) {
|
|
@@ -2528,7 +2721,9 @@ var MCPAgent = class {
|
|
|
2528
2721
|
modelProvider: this.modelProvider,
|
|
2529
2722
|
modelName: this.modelName,
|
|
2530
2723
|
serverCount,
|
|
2531
|
-
serverIdentifiers: this.connectors.map(
|
|
2724
|
+
serverIdentifiers: this.connectors.map(
|
|
2725
|
+
(connector) => connector.publicIdentifier
|
|
2726
|
+
),
|
|
2532
2727
|
totalToolsAvailable: toolsAvailable.length,
|
|
2533
2728
|
toolsAvailableNames: toolsAvailable.map((t) => t.name),
|
|
2534
2729
|
maxStepsConfigured: this.maxSteps,
|
|
@@ -2632,7 +2827,10 @@ var MCPAgent = class {
|
|
|
2632
2827
|
logger.info(`\u26A0\uFE0F Skipped message of type: ${msg.constructor.name}`);
|
|
2633
2828
|
}
|
|
2634
2829
|
}
|
|
2635
|
-
const inputs = [
|
|
2830
|
+
const inputs = [
|
|
2831
|
+
...langchainHistory,
|
|
2832
|
+
new import_langchain2.HumanMessage(query)
|
|
2833
|
+
];
|
|
2636
2834
|
logger.info("callbacks", this.callbacks);
|
|
2637
2835
|
const eventStream = agentExecutor.streamEvents(
|
|
2638
2836
|
{ messages: inputs },
|
|
@@ -2645,7 +2843,9 @@ var MCPAgent = class {
|
|
|
2645
2843
|
// Set trace name for LangChain/Langfuse
|
|
2646
2844
|
runName: this.metadata.trace_name || "mcp-use-agent",
|
|
2647
2845
|
// Pass sessionId for Langfuse if present in metadata
|
|
2648
|
-
...this.metadata.session_id && {
|
|
2846
|
+
...this.metadata.session_id && {
|
|
2847
|
+
sessionId: this.metadata.session_id
|
|
2848
|
+
}
|
|
2649
2849
|
}
|
|
2650
2850
|
);
|
|
2651
2851
|
for await (const event of eventStream) {
|
|
@@ -2664,7 +2864,9 @@ var MCPAgent = class {
|
|
|
2664
2864
|
}
|
|
2665
2865
|
const normalizedContent = this._normalizeOutput(chunk.content);
|
|
2666
2866
|
finalResponse += normalizedContent;
|
|
2667
|
-
logger.debug(
|
|
2867
|
+
logger.debug(
|
|
2868
|
+
`\u{1F4DD} Accumulated response length: ${finalResponse.length}`
|
|
2869
|
+
);
|
|
2668
2870
|
}
|
|
2669
2871
|
}
|
|
2670
2872
|
yield event;
|
|
@@ -2721,7 +2923,11 @@ var MCPAgent = class {
|
|
|
2721
2923
|
data: { output: conversionResult }
|
|
2722
2924
|
};
|
|
2723
2925
|
if (this.memoryEnabled) {
|
|
2724
|
-
this.addToHistory(
|
|
2926
|
+
this.addToHistory(
|
|
2927
|
+
new import_langchain2.AIMessage(
|
|
2928
|
+
`Structured result: ${JSON.stringify(conversionResult)}`
|
|
2929
|
+
)
|
|
2930
|
+
);
|
|
2725
2931
|
}
|
|
2726
2932
|
logger.info("\u2705 Structured output successful");
|
|
2727
2933
|
}
|
|
@@ -2740,7 +2946,9 @@ var MCPAgent = class {
|
|
|
2740
2946
|
} catch (e) {
|
|
2741
2947
|
logger.error(`\u274C Error during streamEvents: ${e}`);
|
|
2742
2948
|
if (initializedHere && manageConnector) {
|
|
2743
|
-
logger.info(
|
|
2949
|
+
logger.info(
|
|
2950
|
+
"\u{1F9F9} Cleaning up resources after initialization error in streamEvents"
|
|
2951
|
+
);
|
|
2744
2952
|
await this.close();
|
|
2745
2953
|
}
|
|
2746
2954
|
throw e;
|
|
@@ -2760,7 +2968,9 @@ var MCPAgent = class {
|
|
|
2760
2968
|
modelProvider: this.modelProvider,
|
|
2761
2969
|
modelName: this.modelName,
|
|
2762
2970
|
serverCount,
|
|
2763
|
-
serverIdentifiers: this.connectors.map(
|
|
2971
|
+
serverIdentifiers: this.connectors.map(
|
|
2972
|
+
(connector) => connector.publicIdentifier
|
|
2973
|
+
),
|
|
2764
2974
|
totalToolsAvailable: this._tools.length,
|
|
2765
2975
|
toolsAvailableNames: this._tools.map((t) => t.name),
|
|
2766
2976
|
maxStepsConfigured: this.maxSteps,
|
|
@@ -2788,11 +2998,15 @@ var MCPAgent = class {
|
|
|
2788
2998
|
* @param outputSchema - The Zod schema to validate against
|
|
2789
2999
|
*/
|
|
2790
3000
|
async _attemptStructuredOutput(rawResult, llm, outputSchema) {
|
|
2791
|
-
logger.info(
|
|
3001
|
+
logger.info(
|
|
3002
|
+
`\u{1F504} Attempting structured output with schema: ${JSON.stringify(outputSchema, null, 2)}`
|
|
3003
|
+
);
|
|
2792
3004
|
logger.info(`\u{1F504} Raw result: ${JSON.stringify(rawResult, null, 2)}`);
|
|
2793
3005
|
let structuredLlm = null;
|
|
2794
3006
|
let schemaDescription = "";
|
|
2795
|
-
logger.debug(
|
|
3007
|
+
logger.debug(
|
|
3008
|
+
`\u{1F504} Structured output requested, schema: ${JSON.stringify((0, import_zod_to_json_schema2.zodToJsonSchema)(outputSchema), null, 2)}`
|
|
3009
|
+
);
|
|
2796
3010
|
if (llm && "withStructuredOutput" in llm && typeof llm.withStructuredOutput === "function") {
|
|
2797
3011
|
structuredLlm = llm.withStructuredOutput(outputSchema);
|
|
2798
3012
|
} else if (llm) {
|
|
@@ -2844,11 +3058,17 @@ var MCPAgent = class {
|
|
|
2844
3058
|
`;
|
|
2845
3059
|
}
|
|
2846
3060
|
try {
|
|
2847
|
-
logger.info(
|
|
3061
|
+
logger.info(
|
|
3062
|
+
`\u{1F504} Structured output attempt ${attempt} - using streaming approach`
|
|
3063
|
+
);
|
|
2848
3064
|
const contentPreview = textContent.length > 300 ? `${textContent.slice(0, 300)}...` : textContent;
|
|
2849
|
-
logger.info(
|
|
2850
|
-
|
|
2851
|
-
|
|
3065
|
+
logger.info(
|
|
3066
|
+
`\u{1F504} Content being formatted (${textContent.length} chars): ${contentPreview}`
|
|
3067
|
+
);
|
|
3068
|
+
logger.info(
|
|
3069
|
+
`\u{1F504} Full format prompt (${formatPrompt.length} chars):
|
|
3070
|
+
${formatPrompt}`
|
|
3071
|
+
);
|
|
2852
3072
|
const stream = await structuredLlm.stream(formatPrompt);
|
|
2853
3073
|
let structuredResult = null;
|
|
2854
3074
|
let chunkCount = 0;
|
|
@@ -2874,19 +3094,30 @@ ${formatPrompt}`);
|
|
|
2874
3094
|
logger.info(`\u{1F504} Structured output streaming: ${chunkCount} chunks`);
|
|
2875
3095
|
}
|
|
2876
3096
|
}
|
|
2877
|
-
logger.info(
|
|
3097
|
+
logger.info(
|
|
3098
|
+
`\u{1F504} Structured result attempt ${attempt}: ${JSON.stringify(structuredResult, null, 2)}`
|
|
3099
|
+
);
|
|
2878
3100
|
if (!structuredResult) {
|
|
2879
3101
|
throw new Error("No structured result received from stream");
|
|
2880
3102
|
}
|
|
2881
|
-
const validatedResult = this._validateStructuredResult(
|
|
3103
|
+
const validatedResult = this._validateStructuredResult(
|
|
3104
|
+
structuredResult,
|
|
3105
|
+
outputSchema
|
|
3106
|
+
);
|
|
2882
3107
|
logger.info(`\u2705 Structured output successful on attempt ${attempt}`);
|
|
2883
3108
|
return validatedResult;
|
|
2884
3109
|
} catch (e) {
|
|
2885
3110
|
lastError = e instanceof Error ? e.message : String(e);
|
|
2886
|
-
logger.warn(
|
|
3111
|
+
logger.warn(
|
|
3112
|
+
`\u26A0\uFE0F Structured output attempt ${attempt} failed: ${lastError}`
|
|
3113
|
+
);
|
|
2887
3114
|
if (attempt === maxRetries) {
|
|
2888
|
-
logger.error(
|
|
2889
|
-
|
|
3115
|
+
logger.error(
|
|
3116
|
+
`\u274C All ${maxRetries} structured output attempts failed`
|
|
3117
|
+
);
|
|
3118
|
+
throw new Error(
|
|
3119
|
+
`Failed to generate valid structured output after ${maxRetries} attempts. Last error: ${lastError}`
|
|
3120
|
+
);
|
|
2890
3121
|
}
|
|
2891
3122
|
continue;
|
|
2892
3123
|
}
|
|
@@ -2901,14 +3132,18 @@ ${formatPrompt}`);
|
|
|
2901
3132
|
const validatedResult = outputSchema.parse(structuredResult);
|
|
2902
3133
|
const schemaType = outputSchema;
|
|
2903
3134
|
if (schemaType._def && schemaType._def.shape) {
|
|
2904
|
-
for (const [fieldName, fieldSchema] of Object.entries(
|
|
3135
|
+
for (const [fieldName, fieldSchema] of Object.entries(
|
|
3136
|
+
schemaType._def.shape
|
|
3137
|
+
)) {
|
|
2905
3138
|
const field = fieldSchema;
|
|
2906
3139
|
const isOptional = field.isOptional?.() ?? field._def?.typeName === "ZodOptional";
|
|
2907
3140
|
const isNullable = field.isNullable?.() ?? field._def?.typeName === "ZodNullable";
|
|
2908
3141
|
if (!isOptional && !isNullable) {
|
|
2909
3142
|
const value = validatedResult[fieldName];
|
|
2910
3143
|
if (value === null || value === void 0 || typeof value === "string" && !value.trim() || Array.isArray(value) && value.length === 0) {
|
|
2911
|
-
throw new Error(
|
|
3144
|
+
throw new Error(
|
|
3145
|
+
`Required field '${fieldName}' is missing or empty`
|
|
3146
|
+
);
|
|
2912
3147
|
}
|
|
2913
3148
|
}
|
|
2914
3149
|
}
|
|
@@ -3059,7 +3294,9 @@ var BaseMCPClient = class {
|
|
|
3059
3294
|
async closeSession(serverName) {
|
|
3060
3295
|
const session = this.sessions[serverName];
|
|
3061
3296
|
if (!session) {
|
|
3062
|
-
logger.warn(
|
|
3297
|
+
logger.warn(
|
|
3298
|
+
`No session exists for server ${serverName}, nothing to close`
|
|
3299
|
+
);
|
|
3063
3300
|
return;
|
|
3064
3301
|
}
|
|
3065
3302
|
try {
|
|
@@ -3086,7 +3323,9 @@ var BaseMCPClient = class {
|
|
|
3086
3323
|
}
|
|
3087
3324
|
}
|
|
3088
3325
|
if (errors.length) {
|
|
3089
|
-
logger.error(
|
|
3326
|
+
logger.error(
|
|
3327
|
+
`Encountered ${errors.length} errors while closing sessions`
|
|
3328
|
+
);
|
|
3090
3329
|
} else {
|
|
3091
3330
|
logger.debug("All sessions closed successfully");
|
|
3092
3331
|
}
|
|
@@ -3192,7 +3431,9 @@ var ConnectionManager = class {
|
|
|
3192
3431
|
try {
|
|
3193
3432
|
await this.closeConnection(this._connection);
|
|
3194
3433
|
} catch (closeErr) {
|
|
3195
|
-
logger.warn(
|
|
3434
|
+
logger.warn(
|
|
3435
|
+
`Error closing connection in ${this.constructor.name}: ${closeErr}`
|
|
3436
|
+
);
|
|
3196
3437
|
}
|
|
3197
3438
|
this._connection = null;
|
|
3198
3439
|
}
|
|
@@ -3325,6 +3566,7 @@ var BaseConnector = class {
|
|
|
3325
3566
|
client = null;
|
|
3326
3567
|
connectionManager = null;
|
|
3327
3568
|
toolsCache = null;
|
|
3569
|
+
capabilitiesCache = null;
|
|
3328
3570
|
connected = false;
|
|
3329
3571
|
opts;
|
|
3330
3572
|
constructor(opts = {}) {
|
|
@@ -3358,9 +3600,14 @@ var BaseConnector = class {
|
|
|
3358
3600
|
}
|
|
3359
3601
|
logger.debug("Caching server capabilities & tools");
|
|
3360
3602
|
const capabilities = this.client.getServerCapabilities();
|
|
3361
|
-
|
|
3603
|
+
this.capabilitiesCache = capabilities;
|
|
3604
|
+
const listToolsRes = await this.client.listTools(
|
|
3605
|
+
void 0,
|
|
3606
|
+
defaultRequestOptions
|
|
3607
|
+
);
|
|
3362
3608
|
this.toolsCache = listToolsRes.tools ?? [];
|
|
3363
3609
|
logger.debug(`Fetched ${this.toolsCache.length} tools from server`);
|
|
3610
|
+
logger.debug("Server capabilities:", capabilities);
|
|
3364
3611
|
return capabilities;
|
|
3365
3612
|
}
|
|
3366
3613
|
/** Lazily expose the cached tools list. */
|
|
@@ -3376,13 +3623,17 @@ var BaseConnector = class {
|
|
|
3376
3623
|
throw new Error("MCP client is not connected");
|
|
3377
3624
|
}
|
|
3378
3625
|
logger.debug(`Calling tool '${name}' with args`, args);
|
|
3379
|
-
const res = await this.client.callTool(
|
|
3626
|
+
const res = await this.client.callTool(
|
|
3627
|
+
{ name, arguments: args },
|
|
3628
|
+
void 0,
|
|
3629
|
+
options
|
|
3630
|
+
);
|
|
3380
3631
|
logger.debug(`Tool '${name}' returned`, res);
|
|
3381
3632
|
return res;
|
|
3382
3633
|
}
|
|
3383
3634
|
/**
|
|
3384
3635
|
* List resources from the server with optional pagination
|
|
3385
|
-
*
|
|
3636
|
+
*
|
|
3386
3637
|
* @param cursor - Optional cursor for pagination
|
|
3387
3638
|
* @param options - Request options
|
|
3388
3639
|
* @returns Resource list with optional nextCursor for pagination
|
|
@@ -3396,7 +3647,7 @@ var BaseConnector = class {
|
|
|
3396
3647
|
}
|
|
3397
3648
|
/**
|
|
3398
3649
|
* List all resources from the server, automatically handling pagination
|
|
3399
|
-
*
|
|
3650
|
+
*
|
|
3400
3651
|
* @param options - Request options
|
|
3401
3652
|
* @returns Complete list of all resources
|
|
3402
3653
|
*/
|
|
@@ -3404,19 +3655,31 @@ var BaseConnector = class {
|
|
|
3404
3655
|
if (!this.client) {
|
|
3405
3656
|
throw new Error("MCP client is not connected");
|
|
3406
3657
|
}
|
|
3407
|
-
|
|
3408
|
-
|
|
3409
|
-
|
|
3410
|
-
|
|
3411
|
-
|
|
3412
|
-
|
|
3413
|
-
|
|
3414
|
-
|
|
3415
|
-
|
|
3658
|
+
if (!this.capabilitiesCache?.resources) {
|
|
3659
|
+
logger.debug("Server does not advertise resources capability, skipping");
|
|
3660
|
+
return { resources: [] };
|
|
3661
|
+
}
|
|
3662
|
+
try {
|
|
3663
|
+
logger.debug("Listing all resources (with auto-pagination)");
|
|
3664
|
+
const allResources = [];
|
|
3665
|
+
let cursor = void 0;
|
|
3666
|
+
do {
|
|
3667
|
+
const result = await this.client.listResources({ cursor }, options);
|
|
3668
|
+
allResources.push(...result.resources || []);
|
|
3669
|
+
cursor = result.nextCursor;
|
|
3670
|
+
} while (cursor);
|
|
3671
|
+
return { resources: allResources };
|
|
3672
|
+
} catch (err) {
|
|
3673
|
+
if (err.code === -32601) {
|
|
3674
|
+
logger.debug("Server advertised resources but method not found");
|
|
3675
|
+
return { resources: [] };
|
|
3676
|
+
}
|
|
3677
|
+
throw err;
|
|
3678
|
+
}
|
|
3416
3679
|
}
|
|
3417
3680
|
/**
|
|
3418
3681
|
* List resource templates from the server
|
|
3419
|
-
*
|
|
3682
|
+
*
|
|
3420
3683
|
* @param options - Request options
|
|
3421
3684
|
* @returns List of available resource templates
|
|
3422
3685
|
*/
|
|
@@ -3434,11 +3697,11 @@ var BaseConnector = class {
|
|
|
3434
3697
|
}
|
|
3435
3698
|
logger.debug(`Reading resource ${uri}`);
|
|
3436
3699
|
const res = await this.client.readResource({ uri }, options);
|
|
3437
|
-
return
|
|
3700
|
+
return res;
|
|
3438
3701
|
}
|
|
3439
3702
|
/**
|
|
3440
3703
|
* Subscribe to resource updates
|
|
3441
|
-
*
|
|
3704
|
+
*
|
|
3442
3705
|
* @param uri - URI of the resource to subscribe to
|
|
3443
3706
|
* @param options - Request options
|
|
3444
3707
|
*/
|
|
@@ -3451,7 +3714,7 @@ var BaseConnector = class {
|
|
|
3451
3714
|
}
|
|
3452
3715
|
/**
|
|
3453
3716
|
* Unsubscribe from resource updates
|
|
3454
|
-
*
|
|
3717
|
+
*
|
|
3455
3718
|
* @param uri - URI of the resource to unsubscribe from
|
|
3456
3719
|
* @param options - Request options
|
|
3457
3720
|
*/
|
|
@@ -3466,8 +3729,20 @@ var BaseConnector = class {
|
|
|
3466
3729
|
if (!this.client) {
|
|
3467
3730
|
throw new Error("MCP client is not connected");
|
|
3468
3731
|
}
|
|
3469
|
-
|
|
3470
|
-
|
|
3732
|
+
if (!this.capabilitiesCache?.prompts) {
|
|
3733
|
+
logger.debug("Server does not advertise prompts capability, skipping");
|
|
3734
|
+
return { prompts: [] };
|
|
3735
|
+
}
|
|
3736
|
+
try {
|
|
3737
|
+
logger.debug("Listing prompts");
|
|
3738
|
+
return await this.client.listPrompts();
|
|
3739
|
+
} catch (err) {
|
|
3740
|
+
if (err.code === -32601) {
|
|
3741
|
+
logger.debug("Server advertised prompts but method not found");
|
|
3742
|
+
return { prompts: [] };
|
|
3743
|
+
}
|
|
3744
|
+
throw err;
|
|
3745
|
+
}
|
|
3471
3746
|
}
|
|
3472
3747
|
async getPrompt(name, args) {
|
|
3473
3748
|
if (!this.client) {
|
|
@@ -3482,7 +3757,11 @@ var BaseConnector = class {
|
|
|
3482
3757
|
throw new Error("MCP client is not connected");
|
|
3483
3758
|
}
|
|
3484
3759
|
logger.debug(`Sending raw request '${method}' with params`, params);
|
|
3485
|
-
return await this.client.request(
|
|
3760
|
+
return await this.client.request(
|
|
3761
|
+
{ method, params: params ?? {} },
|
|
3762
|
+
void 0,
|
|
3763
|
+
options
|
|
3764
|
+
);
|
|
3486
3765
|
}
|
|
3487
3766
|
/**
|
|
3488
3767
|
* Helper to tear down the client & connection manager safely.
|
|
@@ -3541,7 +3820,10 @@ var HttpConnector = class extends BaseConnector {
|
|
|
3541
3820
|
}
|
|
3542
3821
|
this.timeout = opts.timeout ?? 3e4;
|
|
3543
3822
|
this.sseReadTimeout = opts.sseReadTimeout ?? 3e5;
|
|
3544
|
-
this.clientInfo = opts.clientInfo ?? {
|
|
3823
|
+
this.clientInfo = opts.clientInfo ?? {
|
|
3824
|
+
name: "http-connector",
|
|
3825
|
+
version: "1.0.0"
|
|
3826
|
+
};
|
|
3545
3827
|
this.preferSse = opts.preferSse ?? false;
|
|
3546
3828
|
}
|
|
3547
3829
|
/** Establish connection to the MCP implementation via HTTP (streamable or SSE). */
|
|
@@ -3563,7 +3845,9 @@ var HttpConnector = class extends BaseConnector {
|
|
|
3563
3845
|
logger.info("\u2705 Successfully connected via streamable HTTP");
|
|
3564
3846
|
} catch (err) {
|
|
3565
3847
|
let fallbackReason = "Unknown error";
|
|
3848
|
+
let is401Error = false;
|
|
3566
3849
|
if (err instanceof import_streamableHttp2.StreamableHTTPError) {
|
|
3850
|
+
is401Error = err.code === 401;
|
|
3567
3851
|
if (err.code === 400 && err.message.includes("Missing session ID")) {
|
|
3568
3852
|
fallbackReason = "Server requires session ID (FastMCP compatibility) - using SSE transport";
|
|
3569
3853
|
logger.warn(`\u26A0\uFE0F ${fallbackReason}`);
|
|
@@ -3577,6 +3861,7 @@ var HttpConnector = class extends BaseConnector {
|
|
|
3577
3861
|
} else if (err instanceof Error) {
|
|
3578
3862
|
const errorStr = err.toString();
|
|
3579
3863
|
const errorMsg = err.message || "";
|
|
3864
|
+
is401Error = errorStr.includes("401") || errorMsg.includes("Unauthorized");
|
|
3580
3865
|
if (errorStr.includes("Missing session ID") || errorStr.includes("Bad Request: Missing session ID") || errorMsg.includes("FastMCP session ID error")) {
|
|
3581
3866
|
fallbackReason = "Server requires session ID (FastMCP compatibility) - using SSE transport";
|
|
3582
3867
|
logger.warn(`\u26A0\uFE0F ${fallbackReason}`);
|
|
@@ -3588,6 +3873,13 @@ var HttpConnector = class extends BaseConnector {
|
|
|
3588
3873
|
logger.debug(fallbackReason);
|
|
3589
3874
|
}
|
|
3590
3875
|
}
|
|
3876
|
+
if (is401Error) {
|
|
3877
|
+
logger.info("Authentication required - skipping SSE fallback");
|
|
3878
|
+
await this.cleanupResources();
|
|
3879
|
+
const authError = new Error("Authentication required");
|
|
3880
|
+
authError.code = 401;
|
|
3881
|
+
throw authError;
|
|
3882
|
+
}
|
|
3591
3883
|
logger.info("\u{1F504} Falling back to SSE transport...");
|
|
3592
3884
|
try {
|
|
3593
3885
|
await this.connectWithSse(baseUrl);
|
|
@@ -3596,27 +3888,34 @@ var HttpConnector = class extends BaseConnector {
|
|
|
3596
3888
|
logger.error(` Streamable HTTP: ${fallbackReason}`);
|
|
3597
3889
|
logger.error(` SSE: ${sseErr}`);
|
|
3598
3890
|
await this.cleanupResources();
|
|
3599
|
-
|
|
3891
|
+
const sseIs401 = sseErr?.message?.includes("401") || sseErr?.message?.includes("Unauthorized");
|
|
3892
|
+
if (sseIs401) {
|
|
3893
|
+
const authError = new Error("Authentication required");
|
|
3894
|
+
authError.code = 401;
|
|
3895
|
+
throw authError;
|
|
3896
|
+
}
|
|
3897
|
+
throw new Error(
|
|
3898
|
+
"Could not connect to server with any available transport"
|
|
3899
|
+
);
|
|
3600
3900
|
}
|
|
3601
3901
|
}
|
|
3602
3902
|
}
|
|
3603
3903
|
async connectWithStreamableHttp(baseUrl) {
|
|
3604
3904
|
try {
|
|
3605
|
-
this.connectionManager = new StreamableHttpConnectionManager(
|
|
3606
|
-
|
|
3607
|
-
|
|
3608
|
-
|
|
3609
|
-
|
|
3610
|
-
|
|
3611
|
-
|
|
3612
|
-
|
|
3613
|
-
|
|
3614
|
-
|
|
3615
|
-
|
|
3616
|
-
|
|
3617
|
-
}
|
|
3905
|
+
this.connectionManager = new StreamableHttpConnectionManager(baseUrl, {
|
|
3906
|
+
authProvider: this.opts.authProvider,
|
|
3907
|
+
// ← Pass OAuth provider to SDK
|
|
3908
|
+
requestInit: {
|
|
3909
|
+
headers: this.headers
|
|
3910
|
+
},
|
|
3911
|
+
// Pass through timeout and other options
|
|
3912
|
+
reconnectionOptions: {
|
|
3913
|
+
maxReconnectionDelay: 3e4,
|
|
3914
|
+
initialReconnectionDelay: 1e3,
|
|
3915
|
+
reconnectionDelayGrowFactor: 1.5,
|
|
3916
|
+
maxRetries: 2
|
|
3618
3917
|
}
|
|
3619
|
-
);
|
|
3918
|
+
});
|
|
3620
3919
|
const transport = await this.connectionManager.start();
|
|
3621
3920
|
this.client = new import_client.Client(this.clientInfo, this.opts.clientOptions);
|
|
3622
3921
|
try {
|
|
@@ -3625,7 +3924,9 @@ var HttpConnector = class extends BaseConnector {
|
|
|
3625
3924
|
if (connectErr instanceof Error) {
|
|
3626
3925
|
const errMsg = connectErr.message || connectErr.toString();
|
|
3627
3926
|
if (errMsg.includes("Missing session ID") || errMsg.includes("Bad Request: Missing session ID")) {
|
|
3628
|
-
const wrappedError = new Error(
|
|
3927
|
+
const wrappedError = new Error(
|
|
3928
|
+
`FastMCP session ID error: ${errMsg}`
|
|
3929
|
+
);
|
|
3629
3930
|
wrappedError.cause = connectErr;
|
|
3630
3931
|
throw wrappedError;
|
|
3631
3932
|
}
|
|
@@ -3634,7 +3935,9 @@ var HttpConnector = class extends BaseConnector {
|
|
|
3634
3935
|
}
|
|
3635
3936
|
this.connected = true;
|
|
3636
3937
|
this.transportType = "streamable-http";
|
|
3637
|
-
logger.debug(
|
|
3938
|
+
logger.debug(
|
|
3939
|
+
`Successfully connected to MCP implementation via streamable HTTP: ${baseUrl}`
|
|
3940
|
+
);
|
|
3638
3941
|
} catch (err) {
|
|
3639
3942
|
await this.cleanupResources();
|
|
3640
3943
|
throw err;
|
|
@@ -3642,20 +3945,19 @@ var HttpConnector = class extends BaseConnector {
|
|
|
3642
3945
|
}
|
|
3643
3946
|
async connectWithSse(baseUrl) {
|
|
3644
3947
|
try {
|
|
3645
|
-
this.connectionManager = new SseConnectionManager(
|
|
3646
|
-
|
|
3647
|
-
|
|
3648
|
-
requestInit: {
|
|
3649
|
-
headers: this.headers
|
|
3650
|
-
}
|
|
3948
|
+
this.connectionManager = new SseConnectionManager(baseUrl, {
|
|
3949
|
+
requestInit: {
|
|
3950
|
+
headers: this.headers
|
|
3651
3951
|
}
|
|
3652
|
-
);
|
|
3952
|
+
});
|
|
3653
3953
|
const transport = await this.connectionManager.start();
|
|
3654
3954
|
this.client = new import_client.Client(this.clientInfo, this.opts.clientOptions);
|
|
3655
3955
|
await this.client.connect(transport);
|
|
3656
3956
|
this.connected = true;
|
|
3657
3957
|
this.transportType = "sse";
|
|
3658
|
-
logger.debug(
|
|
3958
|
+
logger.debug(
|
|
3959
|
+
`Successfully connected to MCP implementation via HTTP/SSE: ${baseUrl}`
|
|
3960
|
+
);
|
|
3659
3961
|
} catch (err) {
|
|
3660
3962
|
await this.cleanupResources();
|
|
3661
3963
|
throw err;
|
|
@@ -3710,7 +4012,9 @@ var StdioConnectionManager = class extends ConnectionManager {
|
|
|
3710
4012
|
async establishConnection() {
|
|
3711
4013
|
this._transport = new import_stdio.StdioClientTransport(this.serverParams);
|
|
3712
4014
|
if (this._transport.stderr && typeof this._transport.stderr.pipe === "function") {
|
|
3713
|
-
this._transport.stderr.pipe(
|
|
4015
|
+
this._transport.stderr.pipe(
|
|
4016
|
+
this.errlog
|
|
4017
|
+
);
|
|
3714
4018
|
}
|
|
3715
4019
|
logger.debug(`${this.constructor.name} connected successfully`);
|
|
3716
4020
|
return this._transport;
|
|
@@ -3754,7 +4058,10 @@ var StdioConnector = class extends BaseConnector {
|
|
|
3754
4058
|
this.args = args;
|
|
3755
4059
|
this.env = env;
|
|
3756
4060
|
this.errlog = errlog;
|
|
3757
|
-
this.clientInfo = rest.clientInfo ?? {
|
|
4061
|
+
this.clientInfo = rest.clientInfo ?? {
|
|
4062
|
+
name: "stdio-connector",
|
|
4063
|
+
version: "1.0.0"
|
|
4064
|
+
};
|
|
3758
4065
|
}
|
|
3759
4066
|
/** Establish connection to the MCP implementation. */
|
|
3760
4067
|
async connect() {
|
|
@@ -3779,12 +4086,17 @@ var StdioConnector = class extends BaseConnector {
|
|
|
3779
4086
|
args: this.args,
|
|
3780
4087
|
env: mergedEnv
|
|
3781
4088
|
};
|
|
3782
|
-
this.connectionManager = new StdioConnectionManager(
|
|
4089
|
+
this.connectionManager = new StdioConnectionManager(
|
|
4090
|
+
serverParams,
|
|
4091
|
+
this.errlog
|
|
4092
|
+
);
|
|
3783
4093
|
const transport = await this.connectionManager.start();
|
|
3784
4094
|
this.client = new import_client2.Client(this.clientInfo, this.opts.clientOptions);
|
|
3785
4095
|
await this.client.connect(transport);
|
|
3786
4096
|
this.connected = true;
|
|
3787
|
-
logger.debug(
|
|
4097
|
+
logger.debug(
|
|
4098
|
+
`Successfully connected to MCP implementation: ${this.command}`
|
|
4099
|
+
);
|
|
3788
4100
|
} catch (err) {
|
|
3789
4101
|
logger.error(`Failed to connect to MCP implementation: ${err}`);
|
|
3790
4102
|
await this.cleanupResources();
|
|
@@ -3793,7 +4105,7 @@ var StdioConnector = class extends BaseConnector {
|
|
|
3793
4105
|
}
|
|
3794
4106
|
get publicIdentifier() {
|
|
3795
4107
|
return {
|
|
3796
|
-
|
|
4108
|
+
type: "stdio",
|
|
3797
4109
|
"command&args": `${this.command} ${this.args.join(" ")}`
|
|
3798
4110
|
};
|
|
3799
4111
|
}
|
|
@@ -3826,7 +4138,9 @@ var WebSocketConnectionManager = class extends ConnectionManager {
|
|
|
3826
4138
|
async establishConnection() {
|
|
3827
4139
|
logger.debug(`Connecting to WebSocket: ${this.url}`);
|
|
3828
4140
|
return new Promise((resolve, reject) => {
|
|
3829
|
-
const ws = new import_ws.default(this.url, {
|
|
4141
|
+
const ws = new import_ws.default(this.url, {
|
|
4142
|
+
headers: this.headers
|
|
4143
|
+
});
|
|
3830
4144
|
this._ws = ws;
|
|
3831
4145
|
const onOpen = /* @__PURE__ */ __name(() => {
|
|
3832
4146
|
cleanup();
|
|
@@ -3886,8 +4200,7 @@ var WebSocketConnector = class extends BaseConnector {
|
|
|
3886
4200
|
super();
|
|
3887
4201
|
this.url = url;
|
|
3888
4202
|
this.headers = { ...opts.headers ?? {} };
|
|
3889
|
-
if (opts.authToken)
|
|
3890
|
-
this.headers.Authorization = `Bearer ${opts.authToken}`;
|
|
4203
|
+
if (opts.authToken) this.headers.Authorization = `Bearer ${opts.authToken}`;
|
|
3891
4204
|
}
|
|
3892
4205
|
async connect() {
|
|
3893
4206
|
if (this.connected) {
|
|
@@ -3896,7 +4209,10 @@ var WebSocketConnector = class extends BaseConnector {
|
|
|
3896
4209
|
}
|
|
3897
4210
|
logger.debug(`Connecting via WebSocket: ${this.url}`);
|
|
3898
4211
|
try {
|
|
3899
|
-
this.connectionManager = new WebSocketConnectionManager(
|
|
4212
|
+
this.connectionManager = new WebSocketConnectionManager(
|
|
4213
|
+
this.url,
|
|
4214
|
+
this.headers
|
|
4215
|
+
);
|
|
3900
4216
|
this.ws = await this.connectionManager.start();
|
|
3901
4217
|
this.receiverTask = this.receiveLoop();
|
|
3902
4218
|
this.connected = true;
|
|
@@ -3917,8 +4233,7 @@ var WebSocketConnector = class extends BaseConnector {
|
|
|
3917
4233
|
this.connected = false;
|
|
3918
4234
|
}
|
|
3919
4235
|
sendRequest(method, params = null) {
|
|
3920
|
-
if (!this.ws)
|
|
3921
|
-
throw new Error("WebSocket is not connected");
|
|
4236
|
+
if (!this.ws) throw new Error("WebSocket is not connected");
|
|
3922
4237
|
const id = (0, import_uuid2.v4)();
|
|
3923
4238
|
const payload = JSON.stringify({ id, method, params: params ?? {} });
|
|
3924
4239
|
return new Promise((resolve, reject) => {
|
|
@@ -3932,8 +4247,7 @@ var WebSocketConnector = class extends BaseConnector {
|
|
|
3932
4247
|
});
|
|
3933
4248
|
}
|
|
3934
4249
|
async receiveLoop() {
|
|
3935
|
-
if (!this.ws)
|
|
3936
|
-
return;
|
|
4250
|
+
if (!this.ws) return;
|
|
3937
4251
|
const socket = this.ws;
|
|
3938
4252
|
const onMessage = /* @__PURE__ */ __name((msg) => {
|
|
3939
4253
|
let data;
|
|
@@ -3947,10 +4261,8 @@ var WebSocketConnector = class extends BaseConnector {
|
|
|
3947
4261
|
if (id && this.pending.has(id)) {
|
|
3948
4262
|
const { resolve, reject } = this.pending.get(id);
|
|
3949
4263
|
this.pending.delete(id);
|
|
3950
|
-
if ("result" in data)
|
|
3951
|
-
|
|
3952
|
-
else if ("error" in data)
|
|
3953
|
-
reject(data.error);
|
|
4264
|
+
if ("result" in data) resolve(data.result);
|
|
4265
|
+
else if ("error" in data) reject(data.error);
|
|
3954
4266
|
} else {
|
|
3955
4267
|
logger.debug("Received unsolicited message", data);
|
|
3956
4268
|
}
|
|
@@ -4002,20 +4314,18 @@ var WebSocketConnector = class extends BaseConnector {
|
|
|
4002
4314
|
}
|
|
4003
4315
|
async readResource(uri) {
|
|
4004
4316
|
const res = await this.sendRequest("resources/read", { uri });
|
|
4005
|
-
return
|
|
4317
|
+
return res;
|
|
4006
4318
|
}
|
|
4007
4319
|
async request(method, params = null) {
|
|
4008
4320
|
return await this.sendRequest(method, params);
|
|
4009
4321
|
}
|
|
4010
4322
|
get tools() {
|
|
4011
|
-
if (!this.toolsCache)
|
|
4012
|
-
throw new Error("MCP client is not initialized");
|
|
4323
|
+
if (!this.toolsCache) throw new Error("MCP client is not initialized");
|
|
4013
4324
|
return this.toolsCache;
|
|
4014
4325
|
}
|
|
4015
4326
|
async cleanupResources() {
|
|
4016
|
-
if (this.receiverTask)
|
|
4017
|
-
|
|
4018
|
-
});
|
|
4327
|
+
if (this.receiverTask) await this.receiverTask.catch(() => {
|
|
4328
|
+
});
|
|
4019
4329
|
this.receiverTask = null;
|
|
4020
4330
|
this.rejectAll(new Error("WebSocket disconnected"));
|
|
4021
4331
|
if (this.connectionManager) {
|
|
@@ -4200,7 +4510,7 @@ var OAuthHelper = class {
|
|
|
4200
4510
|
const response = await fetch(serverUrl, {
|
|
4201
4511
|
method: "GET",
|
|
4202
4512
|
headers: {
|
|
4203
|
-
|
|
4513
|
+
Accept: "text/event-stream",
|
|
4204
4514
|
"Cache-Control": "no-cache"
|
|
4205
4515
|
},
|
|
4206
4516
|
redirect: "manual",
|
|
@@ -4216,16 +4526,29 @@ var OAuthHelper = class {
|
|
|
4216
4526
|
console.log("\u{1F510} [OAuthHelper] Authentication required for:", serverUrl);
|
|
4217
4527
|
return true;
|
|
4218
4528
|
}
|
|
4219
|
-
console.log(
|
|
4529
|
+
console.log(
|
|
4530
|
+
"\u2705 [OAuthHelper] No authentication required for:",
|
|
4531
|
+
serverUrl
|
|
4532
|
+
);
|
|
4220
4533
|
return false;
|
|
4221
4534
|
} catch (error) {
|
|
4222
|
-
console.warn(
|
|
4535
|
+
console.warn(
|
|
4536
|
+
"\u26A0\uFE0F [OAuthHelper] Could not check auth requirement for:",
|
|
4537
|
+
serverUrl,
|
|
4538
|
+
error
|
|
4539
|
+
);
|
|
4223
4540
|
if (error.name === "TypeError" && (error.message?.includes("CORS") || error.message?.includes("Failed to fetch"))) {
|
|
4224
|
-
console.log(
|
|
4541
|
+
console.log(
|
|
4542
|
+
"\u{1F50D} [OAuthHelper] CORS blocked direct check, using heuristics for:",
|
|
4543
|
+
serverUrl
|
|
4544
|
+
);
|
|
4225
4545
|
return this.checkAuthByHeuristics(serverUrl);
|
|
4226
4546
|
}
|
|
4227
4547
|
if (error.name === "AbortError") {
|
|
4228
|
-
console.log(
|
|
4548
|
+
console.log(
|
|
4549
|
+
"\u23F0 [OAuthHelper] Request timeout, assuming no auth required for:",
|
|
4550
|
+
serverUrl
|
|
4551
|
+
);
|
|
4229
4552
|
return false;
|
|
4230
4553
|
}
|
|
4231
4554
|
return this.checkAuthByHeuristics(serverUrl);
|
|
@@ -4235,7 +4558,10 @@ var OAuthHelper = class {
|
|
|
4235
4558
|
* Fallback heuristics for determining auth requirements when direct checking fails
|
|
4236
4559
|
*/
|
|
4237
4560
|
checkAuthByHeuristics(serverUrl) {
|
|
4238
|
-
console.log(
|
|
4561
|
+
console.log(
|
|
4562
|
+
"\u{1F50D} [OAuthHelper] Using heuristics to determine auth for:",
|
|
4563
|
+
serverUrl
|
|
4564
|
+
);
|
|
4239
4565
|
const authRequiredPatterns = [
|
|
4240
4566
|
/api\.githubcopilot\.com/i,
|
|
4241
4567
|
// GitHub Copilot
|
|
@@ -4268,17 +4594,26 @@ var OAuthHelper = class {
|
|
|
4268
4594
|
];
|
|
4269
4595
|
for (const pattern of noAuthPatterns) {
|
|
4270
4596
|
if (pattern.test(serverUrl)) {
|
|
4271
|
-
console.log(
|
|
4597
|
+
console.log(
|
|
4598
|
+
"\u2705 [OAuthHelper] Heuristic: No auth required (matches no-auth pattern):",
|
|
4599
|
+
serverUrl
|
|
4600
|
+
);
|
|
4272
4601
|
return false;
|
|
4273
4602
|
}
|
|
4274
4603
|
}
|
|
4275
4604
|
for (const pattern of authRequiredPatterns) {
|
|
4276
4605
|
if (pattern.test(serverUrl)) {
|
|
4277
|
-
console.log(
|
|
4606
|
+
console.log(
|
|
4607
|
+
"\u{1F510} [OAuthHelper] Heuristic: Auth required (matches auth pattern):",
|
|
4608
|
+
serverUrl
|
|
4609
|
+
);
|
|
4278
4610
|
return true;
|
|
4279
4611
|
}
|
|
4280
4612
|
}
|
|
4281
|
-
console.log(
|
|
4613
|
+
console.log(
|
|
4614
|
+
"\u2753 [OAuthHelper] Heuristic: Unknown pattern, assuming no auth required:",
|
|
4615
|
+
serverUrl
|
|
4616
|
+
);
|
|
4282
4617
|
return false;
|
|
4283
4618
|
}
|
|
4284
4619
|
/**
|
|
@@ -4287,7 +4622,10 @@ var OAuthHelper = class {
|
|
|
4287
4622
|
async discoverOAuthConfig(serverUrl) {
|
|
4288
4623
|
try {
|
|
4289
4624
|
const discoveryUrl = `${serverUrl}/.well-known/oauth-authorization-server`;
|
|
4290
|
-
console.log(
|
|
4625
|
+
console.log(
|
|
4626
|
+
"\u{1F50D} [OAuthHelper] Attempting OAuth discovery at:",
|
|
4627
|
+
discoveryUrl
|
|
4628
|
+
);
|
|
4291
4629
|
const response = await fetch(discoveryUrl);
|
|
4292
4630
|
if (!response.ok) {
|
|
4293
4631
|
console.error("\u274C [OAuthHelper] OAuth discovery failed:", {
|
|
@@ -4295,7 +4633,9 @@ var OAuthHelper = class {
|
|
|
4295
4633
|
statusText: response.statusText,
|
|
4296
4634
|
url: discoveryUrl
|
|
4297
4635
|
});
|
|
4298
|
-
throw new Error(
|
|
4636
|
+
throw new Error(
|
|
4637
|
+
`OAuth discovery failed: ${response.status} ${response.statusText}`
|
|
4638
|
+
);
|
|
4299
4639
|
}
|
|
4300
4640
|
this.discovery = await response.json();
|
|
4301
4641
|
console.log("\u2705 [OAuthHelper] OAuth discovery successful:", {
|
|
@@ -4314,7 +4654,9 @@ var OAuthHelper = class {
|
|
|
4314
4654
|
*/
|
|
4315
4655
|
async registerClient(_serverUrl) {
|
|
4316
4656
|
if (!this.discovery) {
|
|
4317
|
-
throw new Error(
|
|
4657
|
+
throw new Error(
|
|
4658
|
+
"OAuth discovery not performed. Call discoverOAuthConfig first."
|
|
4659
|
+
);
|
|
4318
4660
|
}
|
|
4319
4661
|
if (!this.discovery.registration_endpoint) {
|
|
4320
4662
|
throw new Error("Server does not support dynamic client registration");
|
|
@@ -4343,7 +4685,9 @@ var OAuthHelper = class {
|
|
|
4343
4685
|
});
|
|
4344
4686
|
if (!response.ok) {
|
|
4345
4687
|
const errorText = await response.text();
|
|
4346
|
-
throw new Error(
|
|
4688
|
+
throw new Error(
|
|
4689
|
+
`Client registration failed: ${response.status} ${response.statusText} - ${errorText}`
|
|
4690
|
+
);
|
|
4347
4691
|
}
|
|
4348
4692
|
this.clientRegistration = await response.json();
|
|
4349
4693
|
console.log("\u2705 [OAuthHelper] Client registered successfully:", {
|
|
@@ -4361,7 +4705,9 @@ var OAuthHelper = class {
|
|
|
4361
4705
|
*/
|
|
4362
4706
|
generateAuthUrl(serverUrl, additionalParams) {
|
|
4363
4707
|
if (!this.discovery) {
|
|
4364
|
-
throw new Error(
|
|
4708
|
+
throw new Error(
|
|
4709
|
+
"OAuth discovery not performed. Call discoverOAuthConfig first."
|
|
4710
|
+
);
|
|
4365
4711
|
}
|
|
4366
4712
|
if (!this.clientRegistration) {
|
|
4367
4713
|
throw new Error("Client not registered. Call registerClient first.");
|
|
@@ -4381,7 +4727,9 @@ var OAuthHelper = class {
|
|
|
4381
4727
|
*/
|
|
4382
4728
|
async exchangeCodeForToken(serverUrl, code, codeVerifier) {
|
|
4383
4729
|
if (!this.discovery) {
|
|
4384
|
-
throw new Error(
|
|
4730
|
+
throw new Error(
|
|
4731
|
+
"OAuth discovery not performed. Call discoverOAuthConfig first."
|
|
4732
|
+
);
|
|
4385
4733
|
}
|
|
4386
4734
|
if (!this.clientRegistration) {
|
|
4387
4735
|
throw new Error("Client not registered. Call registerClient first.");
|
|
@@ -4404,7 +4752,9 @@ var OAuthHelper = class {
|
|
|
4404
4752
|
});
|
|
4405
4753
|
if (!response.ok) {
|
|
4406
4754
|
const error = await response.text();
|
|
4407
|
-
throw new Error(
|
|
4755
|
+
throw new Error(
|
|
4756
|
+
`Token exchange failed: ${response.status} ${response.statusText} - ${error}`
|
|
4757
|
+
);
|
|
4408
4758
|
}
|
|
4409
4759
|
return await response.json();
|
|
4410
4760
|
}
|
|
@@ -4442,7 +4792,9 @@ var OAuthHelper = class {
|
|
|
4442
4792
|
"width=500,height=600,scrollbars=yes,resizable=yes,status=yes,location=yes"
|
|
4443
4793
|
);
|
|
4444
4794
|
if (!authWindow) {
|
|
4445
|
-
throw new Error(
|
|
4795
|
+
throw new Error(
|
|
4796
|
+
"Failed to open authentication window. Please allow popups for this site and try again."
|
|
4797
|
+
);
|
|
4446
4798
|
}
|
|
4447
4799
|
console.log("\u2705 [OAuthHelper] OAuth popup opened successfully");
|
|
4448
4800
|
} catch (error) {
|
|
@@ -4577,7 +4929,10 @@ var BrowserOAuthClientProvider = class {
|
|
|
4577
4929
|
try {
|
|
4578
4930
|
return JSON.parse(data);
|
|
4579
4931
|
} catch (e) {
|
|
4580
|
-
console.warn(
|
|
4932
|
+
console.warn(
|
|
4933
|
+
`[${this.storageKeyPrefix}] Failed to parse client information:`,
|
|
4934
|
+
e
|
|
4935
|
+
);
|
|
4581
4936
|
localStorage.removeItem(key);
|
|
4582
4937
|
return void 0;
|
|
4583
4938
|
}
|
|
@@ -4659,7 +5014,11 @@ var BrowserOAuthClientProvider = class {
|
|
|
4659
5014
|
const sanitizedAuthUrl = await this.prepareAuthorizationUrl(authorizationUrl);
|
|
4660
5015
|
const popupFeatures = "width=600,height=700,resizable=yes,scrollbars=yes,status=yes";
|
|
4661
5016
|
try {
|
|
4662
|
-
const popup = window.open(
|
|
5017
|
+
const popup = window.open(
|
|
5018
|
+
sanitizedAuthUrl,
|
|
5019
|
+
`mcp_auth_${this.serverUrlHash}`,
|
|
5020
|
+
popupFeatures
|
|
5021
|
+
);
|
|
4663
5022
|
if (this.onPopupWindow) {
|
|
4664
5023
|
this.onPopupWindow(sanitizedAuthUrl, popupFeatures, popup);
|
|
4665
5024
|
}
|
|
@@ -4669,10 +5028,15 @@ var BrowserOAuthClientProvider = class {
|
|
|
4669
5028
|
);
|
|
4670
5029
|
} else {
|
|
4671
5030
|
popup.focus();
|
|
4672
|
-
console.info(
|
|
5031
|
+
console.info(
|
|
5032
|
+
`[${this.storageKeyPrefix}] Redirecting to authorization URL in popup.`
|
|
5033
|
+
);
|
|
4673
5034
|
}
|
|
4674
5035
|
} catch (e) {
|
|
4675
|
-
console.error(
|
|
5036
|
+
console.error(
|
|
5037
|
+
`[${this.storageKeyPrefix}] Error opening popup window:`,
|
|
5038
|
+
e
|
|
5039
|
+
);
|
|
4676
5040
|
}
|
|
4677
5041
|
}
|
|
4678
5042
|
// --- Helper Methods ---
|
|
@@ -4703,7 +5067,10 @@ var BrowserOAuthClientProvider = class {
|
|
|
4703
5067
|
}
|
|
4704
5068
|
}
|
|
4705
5069
|
} catch (e) {
|
|
4706
|
-
console.warn(
|
|
5070
|
+
console.warn(
|
|
5071
|
+
`[${this.storageKeyPrefix}] Error parsing state key ${key} during clearStorage:`,
|
|
5072
|
+
e
|
|
5073
|
+
);
|
|
4707
5074
|
}
|
|
4708
5075
|
}
|
|
4709
5076
|
}
|
|
@@ -4737,23 +5104,36 @@ async function onMcpAuthorization() {
|
|
|
4737
5104
|
const error = queryParams.get("error");
|
|
4738
5105
|
const errorDescription = queryParams.get("error_description");
|
|
4739
5106
|
const logPrefix = "[mcp-callback]";
|
|
4740
|
-
console.log(`${logPrefix} Handling callback...`, {
|
|
5107
|
+
console.log(`${logPrefix} Handling callback...`, {
|
|
5108
|
+
code,
|
|
5109
|
+
state,
|
|
5110
|
+
error,
|
|
5111
|
+
errorDescription
|
|
5112
|
+
});
|
|
4741
5113
|
let provider = null;
|
|
4742
5114
|
let storedStateData = null;
|
|
4743
5115
|
const stateKey = state ? `mcp:auth:state_${state}` : null;
|
|
4744
5116
|
try {
|
|
4745
5117
|
if (error) {
|
|
4746
|
-
throw new Error(
|
|
5118
|
+
throw new Error(
|
|
5119
|
+
`OAuth error: ${error} - ${errorDescription || "No description provided."}`
|
|
5120
|
+
);
|
|
4747
5121
|
}
|
|
4748
5122
|
if (!code) {
|
|
4749
|
-
throw new Error(
|
|
5123
|
+
throw new Error(
|
|
5124
|
+
"Authorization code not found in callback query parameters."
|
|
5125
|
+
);
|
|
4750
5126
|
}
|
|
4751
5127
|
if (!state || !stateKey) {
|
|
4752
|
-
throw new Error(
|
|
5128
|
+
throw new Error(
|
|
5129
|
+
"State parameter not found or invalid in callback query parameters."
|
|
5130
|
+
);
|
|
4753
5131
|
}
|
|
4754
5132
|
const storedStateJSON = localStorage.getItem(stateKey);
|
|
4755
5133
|
if (!storedStateJSON) {
|
|
4756
|
-
throw new Error(
|
|
5134
|
+
throw new Error(
|
|
5135
|
+
`Invalid or expired state parameter "${state}". No matching state found in storage.`
|
|
5136
|
+
);
|
|
4757
5137
|
}
|
|
4758
5138
|
try {
|
|
4759
5139
|
storedStateData = JSON.parse(storedStateJSON);
|
|
@@ -4762,38 +5142,59 @@ async function onMcpAuthorization() {
|
|
|
4762
5142
|
}
|
|
4763
5143
|
if (!storedStateData.expiry || storedStateData.expiry < Date.now()) {
|
|
4764
5144
|
localStorage.removeItem(stateKey);
|
|
4765
|
-
throw new Error(
|
|
5145
|
+
throw new Error(
|
|
5146
|
+
"OAuth state has expired. Please try initiating authentication again."
|
|
5147
|
+
);
|
|
4766
5148
|
}
|
|
4767
5149
|
if (!storedStateData.providerOptions) {
|
|
4768
5150
|
throw new Error("Stored state is missing required provider options.");
|
|
4769
5151
|
}
|
|
4770
5152
|
const { serverUrl, ...providerOptions } = storedStateData.providerOptions;
|
|
4771
|
-
console.log(
|
|
5153
|
+
console.log(
|
|
5154
|
+
`${logPrefix} Re-instantiating provider for server: ${serverUrl}`
|
|
5155
|
+
);
|
|
4772
5156
|
provider = new BrowserOAuthClientProvider(serverUrl, providerOptions);
|
|
4773
5157
|
console.log(`${logPrefix} Calling SDK auth() to exchange code...`);
|
|
4774
5158
|
const baseUrl = new URL(serverUrl).origin;
|
|
4775
|
-
const authResult = await (0, import_auth.auth)(provider, {
|
|
5159
|
+
const authResult = await (0, import_auth.auth)(provider, {
|
|
5160
|
+
serverUrl: baseUrl,
|
|
5161
|
+
authorizationCode: code
|
|
5162
|
+
});
|
|
4776
5163
|
if (authResult === "AUTHORIZED") {
|
|
4777
|
-
console.log(
|
|
5164
|
+
console.log(
|
|
5165
|
+
`${logPrefix} Authorization successful via SDK auth(). Notifying opener...`
|
|
5166
|
+
);
|
|
4778
5167
|
if (window.opener && !window.opener.closed) {
|
|
4779
|
-
window.opener.postMessage(
|
|
5168
|
+
window.opener.postMessage(
|
|
5169
|
+
{ type: "mcp_auth_callback", success: true },
|
|
5170
|
+
window.location.origin
|
|
5171
|
+
);
|
|
4780
5172
|
window.close();
|
|
4781
5173
|
} else {
|
|
4782
|
-
console.warn(
|
|
5174
|
+
console.warn(
|
|
5175
|
+
`${logPrefix} No opener window detected. Redirecting to root.`
|
|
5176
|
+
);
|
|
4783
5177
|
const pathParts = window.location.pathname.split("/").filter(Boolean);
|
|
4784
5178
|
const basePath = pathParts.length > 0 && pathParts[pathParts.length - 1] === "callback" ? "/" + pathParts.slice(0, -2).join("/") : "/";
|
|
4785
5179
|
window.location.href = basePath || "/";
|
|
4786
5180
|
}
|
|
4787
5181
|
localStorage.removeItem(stateKey);
|
|
4788
5182
|
} else {
|
|
4789
|
-
console.warn(
|
|
4790
|
-
|
|
5183
|
+
console.warn(
|
|
5184
|
+
`${logPrefix} SDK auth() returned unexpected status: ${authResult}`
|
|
5185
|
+
);
|
|
5186
|
+
throw new Error(
|
|
5187
|
+
`Unexpected result from authentication library: ${authResult}`
|
|
5188
|
+
);
|
|
4791
5189
|
}
|
|
4792
5190
|
} catch (err) {
|
|
4793
5191
|
console.error(`${logPrefix} Error during OAuth callback handling:`, err);
|
|
4794
5192
|
const errorMessage = err instanceof Error ? err.message : String(err);
|
|
4795
5193
|
if (window.opener && !window.opener.closed) {
|
|
4796
|
-
window.opener.postMessage(
|
|
5194
|
+
window.opener.postMessage(
|
|
5195
|
+
{ type: "mcp_auth_callback", success: false, error: errorMessage },
|
|
5196
|
+
window.location.origin
|
|
5197
|
+
);
|
|
4797
5198
|
}
|
|
4798
5199
|
try {
|
|
4799
5200
|
document.body.innerHTML = `
|
|
@@ -4807,7 +5208,10 @@ async function onMcpAuthorization() {
|
|
|
4807
5208
|
</div>
|
|
4808
5209
|
`;
|
|
4809
5210
|
} catch (displayError) {
|
|
4810
|
-
console.error(
|
|
5211
|
+
console.error(
|
|
5212
|
+
`${logPrefix} Could not display error in callback window:`,
|
|
5213
|
+
displayError
|
|
5214
|
+
);
|
|
4811
5215
|
}
|
|
4812
5216
|
if (stateKey) {
|
|
4813
5217
|
localStorage.removeItem(stateKey);
|
|
@@ -4821,14 +5225,45 @@ async function onMcpAuthorization() {
|
|
|
4821
5225
|
__name(onMcpAuthorization, "onMcpAuthorization");
|
|
4822
5226
|
|
|
4823
5227
|
// src/react/useMcp.ts
|
|
4824
|
-
var import_types = require("@modelcontextprotocol/sdk/types.js");
|
|
4825
5228
|
var import_react = require("react");
|
|
4826
|
-
var import_auth2 = require("@modelcontextprotocol/sdk/client/auth.js");
|
|
4827
|
-
var import_client3 = require("@modelcontextprotocol/sdk/client/index.js");
|
|
4828
|
-
var import_sse3 = require("@modelcontextprotocol/sdk/client/sse.js");
|
|
4829
|
-
var import_streamableHttp3 = require("@modelcontextprotocol/sdk/client/streamableHttp.js");
|
|
4830
5229
|
var import_strict_url_sanitise2 = require("strict-url-sanitise");
|
|
4831
5230
|
|
|
5231
|
+
// src/client/browser.ts
|
|
5232
|
+
var BrowserMCPClient = class _BrowserMCPClient extends BaseMCPClient {
|
|
5233
|
+
static {
|
|
5234
|
+
__name(this, "BrowserMCPClient");
|
|
5235
|
+
}
|
|
5236
|
+
constructor(config2) {
|
|
5237
|
+
super(config2);
|
|
5238
|
+
}
|
|
5239
|
+
static fromDict(cfg) {
|
|
5240
|
+
return new _BrowserMCPClient(cfg);
|
|
5241
|
+
}
|
|
5242
|
+
/**
|
|
5243
|
+
* Create a connector from server configuration (Browser version)
|
|
5244
|
+
* Supports HTTP and WebSocket connectors only
|
|
5245
|
+
*/
|
|
5246
|
+
createConnectorFromConfig(serverConfig) {
|
|
5247
|
+
const { url, transport, headers, authToken, authProvider } = serverConfig;
|
|
5248
|
+
if (!url) {
|
|
5249
|
+
throw new Error("Server URL is required");
|
|
5250
|
+
}
|
|
5251
|
+
const connectorOptions = {
|
|
5252
|
+
headers,
|
|
5253
|
+
authToken,
|
|
5254
|
+
authProvider
|
|
5255
|
+
// ← Pass OAuth provider to connector
|
|
5256
|
+
};
|
|
5257
|
+
if (transport === "websocket" || url.startsWith("ws://") || url.startsWith("wss://")) {
|
|
5258
|
+
return new WebSocketConnector(url, connectorOptions);
|
|
5259
|
+
} else if (transport === "http" || url.startsWith("http://") || url.startsWith("https://")) {
|
|
5260
|
+
return new HttpConnector(url, connectorOptions);
|
|
5261
|
+
} else {
|
|
5262
|
+
return new HttpConnector(url, connectorOptions);
|
|
5263
|
+
}
|
|
5264
|
+
}
|
|
5265
|
+
};
|
|
5266
|
+
|
|
4832
5267
|
// src/utils/assert.ts
|
|
4833
5268
|
function assert(condition, message) {
|
|
4834
5269
|
if (!condition) {
|
|
@@ -4847,7 +5282,9 @@ function useMcp(options) {
|
|
|
4847
5282
|
enabled = true,
|
|
4848
5283
|
clientName,
|
|
4849
5284
|
clientUri,
|
|
4850
|
-
callbackUrl = typeof window !== "undefined" ? (0, import_strict_url_sanitise2.sanitizeUrl)(
|
|
5285
|
+
callbackUrl = typeof window !== "undefined" ? (0, import_strict_url_sanitise2.sanitizeUrl)(
|
|
5286
|
+
new URL("/oauth/callback", window.location.origin).toString()
|
|
5287
|
+
) : "/oauth/callback",
|
|
4851
5288
|
storageKeyPrefix = "mcp:auth",
|
|
4852
5289
|
clientConfig = {},
|
|
4853
5290
|
customHeaders = {},
|
|
@@ -4871,7 +5308,6 @@ function useMcp(options) {
|
|
|
4871
5308
|
const [log, setLog] = (0, import_react.useState)([]);
|
|
4872
5309
|
const [authUrl, setAuthUrl] = (0, import_react.useState)(void 0);
|
|
4873
5310
|
const clientRef = (0, import_react.useRef)(null);
|
|
4874
|
-
const transportRef = (0, import_react.useRef)(null);
|
|
4875
5311
|
const authProviderRef = (0, import_react.useRef)(null);
|
|
4876
5312
|
const connectingRef = (0, import_react.useRef)(false);
|
|
4877
5313
|
const isMountedRef = (0, import_react.useRef)(true);
|
|
@@ -4889,7 +5325,10 @@ function useMcp(options) {
|
|
|
4889
5325
|
const fullMessage = args.length > 0 ? `${message} ${args.map((arg) => JSON.stringify(arg)).join(" ")}` : message;
|
|
4890
5326
|
console[level](`[useMcp] ${fullMessage}`);
|
|
4891
5327
|
if (isMountedRef.current) {
|
|
4892
|
-
setLog((prevLog) => [
|
|
5328
|
+
setLog((prevLog) => [
|
|
5329
|
+
...prevLog.slice(-100),
|
|
5330
|
+
{ level, message: fullMessage, timestamp: Date.now() }
|
|
5331
|
+
]);
|
|
4893
5332
|
}
|
|
4894
5333
|
},
|
|
4895
5334
|
[]
|
|
@@ -4900,9 +5339,15 @@ function useMcp(options) {
|
|
|
4900
5339
|
connectingRef.current = false;
|
|
4901
5340
|
if (authTimeoutRef.current) clearTimeout(authTimeoutRef.current);
|
|
4902
5341
|
authTimeoutRef.current = null;
|
|
4903
|
-
|
|
5342
|
+
if (clientRef.current) {
|
|
5343
|
+
try {
|
|
5344
|
+
const serverName = "inspector-server";
|
|
5345
|
+
await clientRef.current.closeSession(serverName);
|
|
5346
|
+
} catch (err) {
|
|
5347
|
+
if (!quiet) addLog("warn", "Error closing session:", err);
|
|
5348
|
+
}
|
|
5349
|
+
}
|
|
4904
5350
|
clientRef.current = null;
|
|
4905
|
-
transportRef.current = null;
|
|
4906
5351
|
if (isMountedRef.current && !quiet) {
|
|
4907
5352
|
setState("discovering");
|
|
4908
5353
|
setTools([]);
|
|
@@ -4912,14 +5357,6 @@ function useMcp(options) {
|
|
|
4912
5357
|
setError(void 0);
|
|
4913
5358
|
setAuthUrl(void 0);
|
|
4914
5359
|
}
|
|
4915
|
-
if (transport) {
|
|
4916
|
-
try {
|
|
4917
|
-
await transport.close();
|
|
4918
|
-
if (!quiet) addLog("debug", "Transport closed");
|
|
4919
|
-
} catch (err) {
|
|
4920
|
-
if (!quiet) addLog("warn", "Error closing transport:", err);
|
|
4921
|
-
}
|
|
4922
|
-
}
|
|
4923
5360
|
},
|
|
4924
5361
|
[addLog]
|
|
4925
5362
|
);
|
|
@@ -4932,7 +5369,11 @@ function useMcp(options) {
|
|
|
4932
5369
|
const manualUrl = authProviderRef.current?.getLastAttemptedAuthUrl();
|
|
4933
5370
|
if (manualUrl) {
|
|
4934
5371
|
setAuthUrl(manualUrl);
|
|
4935
|
-
addLog(
|
|
5372
|
+
addLog(
|
|
5373
|
+
"info",
|
|
5374
|
+
"Manual authentication URL may be available.",
|
|
5375
|
+
manualUrl
|
|
5376
|
+
);
|
|
4936
5377
|
}
|
|
4937
5378
|
}
|
|
4938
5379
|
connectingRef.current = false;
|
|
@@ -4941,7 +5382,10 @@ function useMcp(options) {
|
|
|
4941
5382
|
);
|
|
4942
5383
|
const connect = (0, import_react.useCallback)(async () => {
|
|
4943
5384
|
if (!enabled || !url) {
|
|
4944
|
-
addLog(
|
|
5385
|
+
addLog(
|
|
5386
|
+
"debug",
|
|
5387
|
+
enabled ? "No server URL provided, skipping connection." : "Connection disabled via enabled flag."
|
|
5388
|
+
);
|
|
4945
5389
|
return;
|
|
4946
5390
|
}
|
|
4947
5391
|
if (connectingRef.current) {
|
|
@@ -4958,7 +5402,10 @@ function useMcp(options) {
|
|
|
4958
5402
|
setAuthUrl(void 0);
|
|
4959
5403
|
successfulTransportRef.current = null;
|
|
4960
5404
|
setState("discovering");
|
|
4961
|
-
addLog(
|
|
5405
|
+
addLog(
|
|
5406
|
+
"info",
|
|
5407
|
+
`Connecting attempt #${connectAttemptRef.current} to ${url}...`
|
|
5408
|
+
);
|
|
4962
5409
|
if (!authProviderRef.current) {
|
|
4963
5410
|
authProviderRef.current = new BrowserOAuthClientProvider(url, {
|
|
4964
5411
|
storageKeyPrefix,
|
|
@@ -4971,187 +5418,63 @@ function useMcp(options) {
|
|
|
4971
5418
|
addLog("debug", "BrowserOAuthClientProvider initialized in connect.");
|
|
4972
5419
|
}
|
|
4973
5420
|
if (!clientRef.current) {
|
|
4974
|
-
clientRef.current = new
|
|
4975
|
-
|
|
4976
|
-
{ capabilities: {} }
|
|
4977
|
-
);
|
|
4978
|
-
addLog("debug", "MCP Client initialized in connect.");
|
|
5421
|
+
clientRef.current = new BrowserMCPClient();
|
|
5422
|
+
addLog("debug", "BrowserMCPClient initialized in connect.");
|
|
4979
5423
|
}
|
|
4980
5424
|
const tryConnectWithTransport = /* @__PURE__ */ __name(async (transportTypeParam, isAuthRetry = false) => {
|
|
4981
|
-
addLog(
|
|
4982
|
-
|
|
4983
|
-
|
|
4984
|
-
|
|
4985
|
-
let transportInstance;
|
|
5425
|
+
addLog(
|
|
5426
|
+
"info",
|
|
5427
|
+
`Attempting connection with transport: ${transportTypeParam}`
|
|
5428
|
+
);
|
|
4986
5429
|
try {
|
|
4987
|
-
|
|
4988
|
-
|
|
4989
|
-
|
|
4990
|
-
|
|
4991
|
-
transportRef.current = null;
|
|
4992
|
-
}
|
|
4993
|
-
const commonOptions = {
|
|
4994
|
-
authProvider: authProviderRef.current,
|
|
4995
|
-
requestInit: {
|
|
4996
|
-
headers: {
|
|
4997
|
-
Accept: "application/json, text/event-stream",
|
|
4998
|
-
...customHeaders
|
|
4999
|
-
}
|
|
5000
|
-
}
|
|
5001
|
-
// Note: The MCP SDK's SSEClientTransport doesn't expose timeout configuration directly
|
|
5002
|
-
// Timeout handling is managed by the underlying EventSource and browser/Node.js fetch implementations
|
|
5003
|
-
// The timeout and sseReadTimeout options are preserved for future use or custom implementations
|
|
5430
|
+
const serverName = "inspector-server";
|
|
5431
|
+
const serverConfig = {
|
|
5432
|
+
url,
|
|
5433
|
+
transport: transportTypeParam === "sse" ? "http" : transportTypeParam
|
|
5004
5434
|
};
|
|
5005
|
-
|
|
5006
|
-
|
|
5007
|
-
addLog("debug", `Creating ${transportTypeParam.toUpperCase()} transport for URL: ${targetUrl.toString()}`);
|
|
5008
|
-
if (transportTypeParam === "http") {
|
|
5009
|
-
addLog("debug", "Creating StreamableHTTPClientTransport...");
|
|
5010
|
-
transportInstance = new import_streamableHttp3.StreamableHTTPClientTransport(targetUrl, commonOptions);
|
|
5011
|
-
addLog("debug", "StreamableHTTPClientTransport created successfully");
|
|
5012
|
-
} else {
|
|
5013
|
-
addLog("debug", "Creating SSEClientTransport...");
|
|
5014
|
-
transportInstance = new import_sse3.SSEClientTransport(targetUrl, commonOptions);
|
|
5015
|
-
addLog("debug", "SSEClientTransport created successfully");
|
|
5016
|
-
}
|
|
5017
|
-
transportRef.current = transportInstance;
|
|
5018
|
-
addLog("debug", `${transportTypeParam.toUpperCase()} transport created and assigned to ref.`);
|
|
5019
|
-
} catch (err) {
|
|
5020
|
-
failConnection(
|
|
5021
|
-
`Failed to create ${transportTypeParam.toUpperCase()} transport: ${err instanceof Error ? err.message : String(err)}`,
|
|
5022
|
-
err instanceof Error ? err : void 0
|
|
5023
|
-
);
|
|
5024
|
-
return "failed";
|
|
5025
|
-
}
|
|
5026
|
-
transportInstance.onmessage = (message) => {
|
|
5027
|
-
addLog("debug", `[Transport] Received: ${JSON.stringify(message)}`);
|
|
5028
|
-
clientRef.current?.handleMessage?.(message);
|
|
5029
|
-
};
|
|
5030
|
-
transportInstance.onerror = (err) => {
|
|
5031
|
-
addLog("warn", `Transport error event (${transportTypeParam.toUpperCase()}):`, err);
|
|
5032
|
-
failConnection(`Transport error (${transportTypeParam.toUpperCase()}): ${err.message}`, err);
|
|
5033
|
-
};
|
|
5034
|
-
transportInstance.onclose = () => {
|
|
5035
|
-
if (!isMountedRef.current || connectingRef.current) return;
|
|
5036
|
-
addLog("info", `Transport connection closed (${successfulTransportRef.current || "unknown"} type).`);
|
|
5037
|
-
const currentState = stateRef.current;
|
|
5038
|
-
const currentAutoReconnect = autoReconnectRef.current;
|
|
5039
|
-
if (currentState === "ready" && currentAutoReconnect) {
|
|
5040
|
-
const delay = typeof currentAutoReconnect === "number" ? currentAutoReconnect : DEFAULT_RECONNECT_DELAY;
|
|
5041
|
-
addLog("info", `Attempting to reconnect in ${delay}ms...`);
|
|
5042
|
-
setState("connecting");
|
|
5043
|
-
setTimeout(() => {
|
|
5044
|
-
if (isMountedRef.current) {
|
|
5045
|
-
connect();
|
|
5046
|
-
}
|
|
5047
|
-
}, delay);
|
|
5048
|
-
} else if (currentState !== "failed" && currentState !== "authenticating") {
|
|
5049
|
-
failConnection("Cannot connect to server");
|
|
5435
|
+
if (customHeaders && Object.keys(customHeaders).length > 0) {
|
|
5436
|
+
serverConfig.headers = customHeaders;
|
|
5050
5437
|
}
|
|
5051
|
-
|
|
5052
|
-
|
|
5053
|
-
|
|
5054
|
-
|
|
5055
|
-
|
|
5056
|
-
|
|
5057
|
-
|
|
5058
|
-
const toolsResponse = await clientRef.current.request({ method: "tools/list" }, import_types.ListToolsResultSchema);
|
|
5059
|
-
let resourcesResponse = { resources: [], resourceTemplates: [] };
|
|
5060
|
-
try {
|
|
5061
|
-
resourcesResponse = await clientRef.current.request({ method: "resources/list" }, import_types.ListResourcesResultSchema);
|
|
5062
|
-
} catch (err) {
|
|
5063
|
-
addLog("debug", "Server does not support resources/list method", err);
|
|
5064
|
-
}
|
|
5065
|
-
let promptsResponse = { prompts: [] };
|
|
5066
|
-
try {
|
|
5067
|
-
promptsResponse = await clientRef.current.request({ method: "prompts/list" }, import_types.ListPromptsResultSchema);
|
|
5068
|
-
} catch (err) {
|
|
5069
|
-
addLog("debug", "Server does not support prompts/list method", err);
|
|
5070
|
-
}
|
|
5071
|
-
if (isMountedRef.current) {
|
|
5072
|
-
setTools(toolsResponse.tools);
|
|
5073
|
-
setResources(resourcesResponse.resources);
|
|
5074
|
-
setResourceTemplates(Array.isArray(resourcesResponse.resourceTemplates) ? resourcesResponse.resourceTemplates : []);
|
|
5075
|
-
setPrompts(promptsResponse.prompts);
|
|
5076
|
-
const summary = [`Loaded ${toolsResponse.tools.length} tools`];
|
|
5077
|
-
if (resourcesResponse.resources.length > 0 || resourcesResponse.resourceTemplates && resourcesResponse.resourceTemplates.length > 0) {
|
|
5078
|
-
summary.push(`${resourcesResponse.resources.length} resources`);
|
|
5079
|
-
if (Array.isArray(resourcesResponse.resourceTemplates) && resourcesResponse.resourceTemplates.length > 0) {
|
|
5080
|
-
summary.push(`${resourcesResponse.resourceTemplates.length} resource templates`);
|
|
5081
|
-
}
|
|
5082
|
-
}
|
|
5083
|
-
if (promptsResponse.prompts.length > 0) {
|
|
5084
|
-
summary.push(`${promptsResponse.prompts.length} prompts`);
|
|
5438
|
+
if (authProviderRef.current) {
|
|
5439
|
+
const tokens = await authProviderRef.current.tokens();
|
|
5440
|
+
if (tokens?.access_token) {
|
|
5441
|
+
serverConfig.headers = {
|
|
5442
|
+
...serverConfig.headers,
|
|
5443
|
+
Authorization: `Bearer ${tokens.access_token}`
|
|
5444
|
+
};
|
|
5085
5445
|
}
|
|
5086
|
-
addLog("info", summary.join(", ") + ".");
|
|
5087
|
-
setState("ready");
|
|
5088
|
-
connectAttemptRef.current = 0;
|
|
5089
|
-
return "success";
|
|
5090
|
-
} else {
|
|
5091
|
-
return "failed";
|
|
5092
|
-
}
|
|
5093
|
-
} catch (connectErr) {
|
|
5094
|
-
addLog("debug", `Client connect error via ${transportTypeParam.toUpperCase()}:`, connectErr);
|
|
5095
|
-
const errorInstance = connectErr instanceof Error ? connectErr : new Error(String(connectErr));
|
|
5096
|
-
const errorMessage = errorInstance.message;
|
|
5097
|
-
const is404 = errorMessage.includes("404") || errorMessage.includes("Not Found");
|
|
5098
|
-
const is405 = errorMessage.includes("405") || errorMessage.includes("Method Not Allowed");
|
|
5099
|
-
const isLikelyCors = errorMessage === "Failed to fetch" || errorMessage === "NetworkError when attempting to fetch resource." || errorMessage === "Load failed";
|
|
5100
|
-
if (transportTypeParam === "http" && (is404 || is405 || isLikelyCors)) {
|
|
5101
|
-
addLog("warn", `HTTP transport failed (${isLikelyCors ? "CORS" : is404 ? "404" : "405"}), will try fallback.`);
|
|
5102
|
-
return "fallback";
|
|
5103
5446
|
}
|
|
5104
|
-
|
|
5105
|
-
|
|
5106
|
-
|
|
5107
|
-
|
|
5108
|
-
|
|
5109
|
-
|
|
5110
|
-
|
|
5111
|
-
|
|
5112
|
-
|
|
5113
|
-
|
|
5114
|
-
|
|
5115
|
-
|
|
5116
|
-
|
|
5117
|
-
|
|
5118
|
-
|
|
5119
|
-
|
|
5120
|
-
|
|
5121
|
-
|
|
5122
|
-
|
|
5123
|
-
|
|
5124
|
-
if (currentState === "authenticating") {
|
|
5125
|
-
failConnection("Authentication timed out. Please try again.");
|
|
5126
|
-
}
|
|
5127
|
-
}
|
|
5128
|
-
}, AUTH_TIMEOUT);
|
|
5129
|
-
}
|
|
5130
|
-
try {
|
|
5131
|
-
assert(url, "Server URL is required for authentication");
|
|
5132
|
-
const baseUrl = new URL(url).origin;
|
|
5133
|
-
const authResult = await (0, import_auth2.auth)(authProviderRef.current, { serverUrl: baseUrl });
|
|
5134
|
-
if (!isMountedRef.current) return "failed";
|
|
5135
|
-
if (authResult === "AUTHORIZED") {
|
|
5136
|
-
addLog("info", "Authentication successful via existing token or refresh. Retrying transport connection...");
|
|
5137
|
-
if (authTimeoutRef.current) clearTimeout(authTimeoutRef.current);
|
|
5138
|
-
authTimeoutRef.current = null;
|
|
5139
|
-
return await tryConnectWithTransport(transportTypeParam, true);
|
|
5140
|
-
} else if (authResult === "REDIRECT") {
|
|
5141
|
-
addLog("info", "Redirecting for authentication. Waiting for callback...");
|
|
5142
|
-
return "auth_redirect";
|
|
5143
|
-
}
|
|
5144
|
-
} catch (sdkAuthError) {
|
|
5145
|
-
if (!isMountedRef.current) return "failed";
|
|
5146
|
-
if (authTimeoutRef.current) clearTimeout(authTimeoutRef.current);
|
|
5447
|
+
clientRef.current.addServer(serverName, {
|
|
5448
|
+
...serverConfig,
|
|
5449
|
+
authProvider: authProviderRef.current
|
|
5450
|
+
// ← SDK handles OAuth automatically!
|
|
5451
|
+
});
|
|
5452
|
+
const session = await clientRef.current.createSession(serverName);
|
|
5453
|
+
await session.initialize();
|
|
5454
|
+
addLog("info", "\u2705 Successfully connected to MCP server");
|
|
5455
|
+
setState("ready");
|
|
5456
|
+
successfulTransportRef.current = transportTypeParam;
|
|
5457
|
+
setTools(session.connector.tools || []);
|
|
5458
|
+
const resourcesResult = await session.connector.listAllResources();
|
|
5459
|
+
setResources(resourcesResult.resources || []);
|
|
5460
|
+
const promptsResult = await session.connector.listPrompts();
|
|
5461
|
+
setPrompts(promptsResult.prompts || []);
|
|
5462
|
+
return "success";
|
|
5463
|
+
} catch (err) {
|
|
5464
|
+
const errorMessage = err?.message || String(err);
|
|
5465
|
+
if (err.code === 401 || errorMessage.includes("401") || errorMessage.includes("Unauthorized")) {
|
|
5466
|
+
if (customHeaders && Object.keys(customHeaders).length > 0) {
|
|
5147
5467
|
failConnection(
|
|
5148
|
-
|
|
5149
|
-
sdkAuthError instanceof Error ? sdkAuthError : void 0
|
|
5468
|
+
"Authentication failed: Server returned 401 Unauthorized. Check your Authorization header value is correct."
|
|
5150
5469
|
);
|
|
5151
5470
|
return "failed";
|
|
5152
5471
|
}
|
|
5472
|
+
failConnection(
|
|
5473
|
+
"Authentication required: Server returned 401 Unauthorized. Add an Authorization header in the Custom Headers section (e.g., Authorization: Bearer YOUR_API_KEY)."
|
|
5474
|
+
);
|
|
5475
|
+
return "failed";
|
|
5153
5476
|
}
|
|
5154
|
-
failConnection(
|
|
5477
|
+
failConnection(errorMessage, err);
|
|
5155
5478
|
return "failed";
|
|
5156
5479
|
}
|
|
5157
5480
|
}, "tryConnectWithTransport");
|
|
@@ -5199,66 +5522,36 @@ function useMcp(options) {
|
|
|
5199
5522
|
const callTool = (0, import_react.useCallback)(
|
|
5200
5523
|
async (name, args) => {
|
|
5201
5524
|
if (stateRef.current !== "ready" || !clientRef.current) {
|
|
5202
|
-
throw new Error(
|
|
5525
|
+
throw new Error(
|
|
5526
|
+
`MCP client is not ready (current state: ${state}). Cannot call tool "${name}".`
|
|
5527
|
+
);
|
|
5203
5528
|
}
|
|
5204
5529
|
addLog("info", `Calling tool: ${name}`, args);
|
|
5205
5530
|
try {
|
|
5206
|
-
const
|
|
5531
|
+
const serverName = "inspector-server";
|
|
5532
|
+
const session = clientRef.current.getSession(serverName);
|
|
5533
|
+
if (!session) {
|
|
5534
|
+
throw new Error("No active session found");
|
|
5535
|
+
}
|
|
5536
|
+
const result = await session.connector.callTool(name, args || {});
|
|
5207
5537
|
addLog("info", `Tool "${name}" call successful:`, result);
|
|
5208
5538
|
return result;
|
|
5209
5539
|
} catch (err) {
|
|
5210
|
-
addLog("error", `
|
|
5211
|
-
|
|
5212
|
-
if (errorInstance instanceof import_auth2.UnauthorizedError || errorInstance.message.includes("Unauthorized") || errorInstance.message.includes("401")) {
|
|
5213
|
-
addLog("warn", "Tool call unauthorized, attempting re-authentication...");
|
|
5214
|
-
setState("authenticating");
|
|
5215
|
-
if (authTimeoutRef.current) clearTimeout(authTimeoutRef.current);
|
|
5216
|
-
authTimeoutRef.current = setTimeout(() => {
|
|
5217
|
-
if (isMountedRef.current) {
|
|
5218
|
-
const currentState2 = stateRef.current;
|
|
5219
|
-
if (currentState2 === "authenticating") {
|
|
5220
|
-
failConnection("Authentication timed out. Please try again.");
|
|
5221
|
-
}
|
|
5222
|
-
}
|
|
5223
|
-
}, AUTH_TIMEOUT);
|
|
5224
|
-
try {
|
|
5225
|
-
assert(authProviderRef.current, "Auth Provider not available for tool re-auth");
|
|
5226
|
-
assert(url, "Server URL is required for authentication");
|
|
5227
|
-
const baseUrl = new URL(url).origin;
|
|
5228
|
-
const authResult = await (0, import_auth2.auth)(authProviderRef.current, { serverUrl: baseUrl });
|
|
5229
|
-
if (!isMountedRef.current) return;
|
|
5230
|
-
if (authResult === "AUTHORIZED") {
|
|
5231
|
-
addLog("info", "Re-authentication successful. Retrying tool call is recommended, or reconnecting.");
|
|
5232
|
-
if (authTimeoutRef.current) clearTimeout(authTimeoutRef.current);
|
|
5233
|
-
connectingRef.current = false;
|
|
5234
|
-
connect();
|
|
5235
|
-
} else if (authResult === "REDIRECT") {
|
|
5236
|
-
addLog("info", "Redirecting for re-authentication for tool call.");
|
|
5237
|
-
}
|
|
5238
|
-
} catch (sdkAuthError) {
|
|
5239
|
-
if (!isMountedRef.current) return;
|
|
5240
|
-
if (authTimeoutRef.current) clearTimeout(authTimeoutRef.current);
|
|
5241
|
-
failConnection(
|
|
5242
|
-
`Re-authentication failed: ${sdkAuthError instanceof Error ? sdkAuthError.message : String(sdkAuthError)}`,
|
|
5243
|
-
sdkAuthError instanceof Error ? sdkAuthError : void 0
|
|
5244
|
-
);
|
|
5245
|
-
}
|
|
5246
|
-
}
|
|
5247
|
-
const currentState = stateRef.current;
|
|
5248
|
-
if (currentState !== "authenticating") {
|
|
5249
|
-
throw err;
|
|
5250
|
-
}
|
|
5251
|
-
return void 0;
|
|
5540
|
+
addLog("error", `Tool "${name}" call failed:`, err);
|
|
5541
|
+
throw err;
|
|
5252
5542
|
}
|
|
5253
5543
|
},
|
|
5254
|
-
[state
|
|
5544
|
+
[state]
|
|
5255
5545
|
);
|
|
5256
5546
|
const retry = (0, import_react.useCallback)(() => {
|
|
5257
5547
|
if (stateRef.current === "failed") {
|
|
5258
5548
|
addLog("info", "Retry requested...");
|
|
5259
5549
|
connect();
|
|
5260
5550
|
} else {
|
|
5261
|
-
addLog(
|
|
5551
|
+
addLog(
|
|
5552
|
+
"warn",
|
|
5553
|
+
`Retry called but state is not 'failed' (state: ${stateRef.current}). Ignoring.`
|
|
5554
|
+
);
|
|
5262
5555
|
}
|
|
5263
5556
|
}, [addLog, connect]);
|
|
5264
5557
|
const authenticate = (0, import_react.useCallback)(async () => {
|
|
@@ -5280,19 +5573,15 @@ function useMcp(options) {
|
|
|
5280
5573
|
}
|
|
5281
5574
|
}, AUTH_TIMEOUT);
|
|
5282
5575
|
try {
|
|
5283
|
-
assert(
|
|
5576
|
+
assert(
|
|
5577
|
+
authProviderRef.current,
|
|
5578
|
+
"Auth Provider not available for manual auth"
|
|
5579
|
+
);
|
|
5284
5580
|
assert(url, "Server URL is required for authentication");
|
|
5285
|
-
|
|
5286
|
-
|
|
5287
|
-
|
|
5288
|
-
|
|
5289
|
-
addLog("info", "Manual authentication successful. Re-attempting connection...");
|
|
5290
|
-
if (authTimeoutRef.current) clearTimeout(authTimeoutRef.current);
|
|
5291
|
-
connectingRef.current = false;
|
|
5292
|
-
connect();
|
|
5293
|
-
} else if (authResult === "REDIRECT") {
|
|
5294
|
-
addLog("info", "Redirecting for manual authentication. Waiting for callback...");
|
|
5295
|
-
}
|
|
5581
|
+
addLog(
|
|
5582
|
+
"info",
|
|
5583
|
+
"Redirecting for manual authentication. Waiting for callback..."
|
|
5584
|
+
);
|
|
5296
5585
|
} catch (authError) {
|
|
5297
5586
|
if (!isMountedRef.current) return;
|
|
5298
5587
|
if (authTimeoutRef.current) clearTimeout(authTimeoutRef.current);
|
|
@@ -5302,7 +5591,10 @@ function useMcp(options) {
|
|
|
5302
5591
|
);
|
|
5303
5592
|
}
|
|
5304
5593
|
} else if (currentState === "authenticating") {
|
|
5305
|
-
addLog(
|
|
5594
|
+
addLog(
|
|
5595
|
+
"warn",
|
|
5596
|
+
"Already attempting authentication. Check for blocked popups or wait for timeout."
|
|
5597
|
+
);
|
|
5306
5598
|
const manualUrl = authProviderRef.current?.getLastAttemptedAuthUrl();
|
|
5307
5599
|
if (manualUrl && !authUrl) {
|
|
5308
5600
|
setAuthUrl(manualUrl);
|
|
@@ -5327,73 +5619,93 @@ function useMcp(options) {
|
|
|
5327
5619
|
}, [url, addLog, disconnect]);
|
|
5328
5620
|
const listResources = (0, import_react.useCallback)(async () => {
|
|
5329
5621
|
if (stateRef.current !== "ready" || !clientRef.current) {
|
|
5330
|
-
throw new Error(
|
|
5622
|
+
throw new Error(
|
|
5623
|
+
`MCP client is not ready (current state: ${state}). Cannot list resources.`
|
|
5624
|
+
);
|
|
5331
5625
|
}
|
|
5332
|
-
addLog("info", "Listing resources
|
|
5626
|
+
addLog("info", "Listing resources");
|
|
5333
5627
|
try {
|
|
5334
|
-
const
|
|
5335
|
-
|
|
5336
|
-
|
|
5337
|
-
|
|
5338
|
-
addLog(
|
|
5339
|
-
"info",
|
|
5340
|
-
`Listed ${resourcesResponse.resources.length} resources, ${Array.isArray(resourcesResponse.resourceTemplates) ? resourcesResponse.resourceTemplates.length : 0} resource templates.`
|
|
5341
|
-
);
|
|
5628
|
+
const serverName = "inspector-server";
|
|
5629
|
+
const session = clientRef.current.getSession(serverName);
|
|
5630
|
+
if (!session) {
|
|
5631
|
+
throw new Error("No active session found");
|
|
5342
5632
|
}
|
|
5633
|
+
const resourcesResult = await session.connector.listAllResources();
|
|
5634
|
+
setResources(resourcesResult.resources || []);
|
|
5635
|
+
addLog("info", "Resources listed successfully");
|
|
5343
5636
|
} catch (err) {
|
|
5344
|
-
addLog("error",
|
|
5637
|
+
addLog("error", "List resources failed:", err);
|
|
5345
5638
|
throw err;
|
|
5346
5639
|
}
|
|
5347
|
-
}, [state
|
|
5640
|
+
}, [state]);
|
|
5348
5641
|
const readResource = (0, import_react.useCallback)(
|
|
5349
5642
|
async (uri) => {
|
|
5350
5643
|
if (stateRef.current !== "ready" || !clientRef.current) {
|
|
5351
|
-
throw new Error(
|
|
5644
|
+
throw new Error(
|
|
5645
|
+
`MCP client is not ready (current state: ${state}). Cannot read resource.`
|
|
5646
|
+
);
|
|
5352
5647
|
}
|
|
5353
5648
|
addLog("info", `Reading resource: ${uri}`);
|
|
5354
5649
|
try {
|
|
5355
|
-
const
|
|
5356
|
-
|
|
5650
|
+
const serverName = "inspector-server";
|
|
5651
|
+
const session = clientRef.current.getSession(serverName);
|
|
5652
|
+
if (!session) {
|
|
5653
|
+
throw new Error("No active session found");
|
|
5654
|
+
}
|
|
5655
|
+
const result = await session.connector.readResource(uri);
|
|
5656
|
+
addLog("info", "Resource read successful:", result);
|
|
5357
5657
|
return result;
|
|
5358
5658
|
} catch (err) {
|
|
5359
|
-
addLog("error",
|
|
5659
|
+
addLog("error", "Resource read failed:", err);
|
|
5360
5660
|
throw err;
|
|
5361
5661
|
}
|
|
5362
5662
|
},
|
|
5363
|
-
[state
|
|
5663
|
+
[state]
|
|
5364
5664
|
);
|
|
5365
5665
|
const listPrompts = (0, import_react.useCallback)(async () => {
|
|
5366
5666
|
if (stateRef.current !== "ready" || !clientRef.current) {
|
|
5367
|
-
throw new Error(
|
|
5667
|
+
throw new Error(
|
|
5668
|
+
`MCP client is not ready (current state: ${state}). Cannot list prompts.`
|
|
5669
|
+
);
|
|
5368
5670
|
}
|
|
5369
|
-
addLog("info", "Listing prompts
|
|
5671
|
+
addLog("info", "Listing prompts");
|
|
5370
5672
|
try {
|
|
5371
|
-
const
|
|
5372
|
-
|
|
5373
|
-
|
|
5374
|
-
|
|
5673
|
+
const serverName = "inspector-server";
|
|
5674
|
+
const session = clientRef.current.getSession(serverName);
|
|
5675
|
+
if (!session) {
|
|
5676
|
+
throw new Error("No active session found");
|
|
5375
5677
|
}
|
|
5678
|
+
const promptsResult = await session.connector.listPrompts();
|
|
5679
|
+
setPrompts(promptsResult.prompts || []);
|
|
5680
|
+
addLog("info", "Prompts listed successfully");
|
|
5376
5681
|
} catch (err) {
|
|
5377
|
-
addLog("error",
|
|
5682
|
+
addLog("error", "List prompts failed:", err);
|
|
5378
5683
|
throw err;
|
|
5379
5684
|
}
|
|
5380
|
-
}, [state
|
|
5685
|
+
}, [state]);
|
|
5381
5686
|
const getPrompt = (0, import_react.useCallback)(
|
|
5382
5687
|
async (name, args) => {
|
|
5383
5688
|
if (stateRef.current !== "ready" || !clientRef.current) {
|
|
5384
|
-
throw new Error(
|
|
5689
|
+
throw new Error(
|
|
5690
|
+
`MCP client is not ready (current state: ${state}). Cannot get prompt.`
|
|
5691
|
+
);
|
|
5385
5692
|
}
|
|
5386
5693
|
addLog("info", `Getting prompt: ${name}`, args);
|
|
5387
5694
|
try {
|
|
5388
|
-
const
|
|
5389
|
-
|
|
5695
|
+
const serverName = "inspector-server";
|
|
5696
|
+
const session = clientRef.current.getSession(serverName);
|
|
5697
|
+
if (!session) {
|
|
5698
|
+
throw new Error("No active session found");
|
|
5699
|
+
}
|
|
5700
|
+
const result = await session.connector.getPrompt(name, args || {});
|
|
5701
|
+
addLog("info", `Prompt "${name}" retrieved successfully:`, result);
|
|
5390
5702
|
return result;
|
|
5391
5703
|
} catch (err) {
|
|
5392
|
-
addLog("error", `
|
|
5704
|
+
addLog("error", `Prompt "${name}" retrieval failed:`, err);
|
|
5393
5705
|
throw err;
|
|
5394
5706
|
}
|
|
5395
5707
|
},
|
|
5396
|
-
[state
|
|
5708
|
+
[state]
|
|
5397
5709
|
);
|
|
5398
5710
|
const connectRef = (0, import_react.useRef)(connect);
|
|
5399
5711
|
const failConnectionRef = (0, import_react.useRef)(failConnection);
|
|
@@ -5409,19 +5721,30 @@ function useMcp(options) {
|
|
|
5409
5721
|
if (authTimeoutRef.current) clearTimeout(authTimeoutRef.current);
|
|
5410
5722
|
authTimeoutRef.current = null;
|
|
5411
5723
|
if (event.data.success) {
|
|
5412
|
-
addLog(
|
|
5724
|
+
addLog(
|
|
5725
|
+
"info",
|
|
5726
|
+
"Authentication successful via popup. Reconnecting client..."
|
|
5727
|
+
);
|
|
5413
5728
|
if (connectingRef.current) {
|
|
5414
|
-
addLog(
|
|
5729
|
+
addLog(
|
|
5730
|
+
"debug",
|
|
5731
|
+
"Connection attempt already in progress, resetting flag to allow reconnection."
|
|
5732
|
+
);
|
|
5415
5733
|
}
|
|
5416
5734
|
connectingRef.current = false;
|
|
5417
5735
|
setTimeout(() => {
|
|
5418
5736
|
if (isMountedRef.current) {
|
|
5419
|
-
addLog(
|
|
5737
|
+
addLog(
|
|
5738
|
+
"debug",
|
|
5739
|
+
"Initiating reconnection after successful auth callback."
|
|
5740
|
+
);
|
|
5420
5741
|
connectRef.current();
|
|
5421
5742
|
}
|
|
5422
5743
|
}, 100);
|
|
5423
5744
|
} else {
|
|
5424
|
-
failConnectionRef.current(
|
|
5745
|
+
failConnectionRef.current(
|
|
5746
|
+
`Authentication failed in callback: ${event.data.error || "Unknown reason."}`
|
|
5747
|
+
);
|
|
5425
5748
|
}
|
|
5426
5749
|
}
|
|
5427
5750
|
}, "messageHandler");
|
|
@@ -5436,7 +5759,10 @@ function useMcp(options) {
|
|
|
5436
5759
|
(0, import_react.useEffect)(() => {
|
|
5437
5760
|
isMountedRef.current = true;
|
|
5438
5761
|
if (!enabled || !url) {
|
|
5439
|
-
addLog(
|
|
5762
|
+
addLog(
|
|
5763
|
+
"debug",
|
|
5764
|
+
enabled ? "No server URL provided, skipping connection." : "Connection disabled via enabled flag."
|
|
5765
|
+
);
|
|
5440
5766
|
setState("discovering");
|
|
5441
5767
|
return () => {
|
|
5442
5768
|
isMountedRef.current = false;
|
|
@@ -5453,7 +5779,10 @@ function useMcp(options) {
|
|
|
5453
5779
|
preventAutoAuth,
|
|
5454
5780
|
onPopupWindow
|
|
5455
5781
|
});
|
|
5456
|
-
addLog(
|
|
5782
|
+
addLog(
|
|
5783
|
+
"debug",
|
|
5784
|
+
"BrowserOAuthClientProvider initialized/updated on mount/option change."
|
|
5785
|
+
);
|
|
5457
5786
|
}
|
|
5458
5787
|
connect();
|
|
5459
5788
|
return () => {
|
|
@@ -5461,7 +5790,16 @@ function useMcp(options) {
|
|
|
5461
5790
|
addLog("debug", "useMcp unmounting, disconnecting.");
|
|
5462
5791
|
disconnect(true);
|
|
5463
5792
|
};
|
|
5464
|
-
}, [
|
|
5793
|
+
}, [
|
|
5794
|
+
url,
|
|
5795
|
+
enabled,
|
|
5796
|
+
storageKeyPrefix,
|
|
5797
|
+
callbackUrl,
|
|
5798
|
+
clientName,
|
|
5799
|
+
clientUri,
|
|
5800
|
+
clientConfig.name,
|
|
5801
|
+
clientConfig.version
|
|
5802
|
+
]);
|
|
5465
5803
|
(0, import_react.useEffect)(() => {
|
|
5466
5804
|
let retryTimeoutId = null;
|
|
5467
5805
|
if (state === "failed" && autoRetry && connectAttemptRef.current > 0) {
|
|
@@ -5486,9 +5824,10 @@ function useMcp(options) {
|
|
|
5486
5824
|
error,
|
|
5487
5825
|
log,
|
|
5488
5826
|
authUrl,
|
|
5827
|
+
client: clientRef.current,
|
|
5489
5828
|
callTool,
|
|
5490
|
-
listResources,
|
|
5491
5829
|
readResource,
|
|
5830
|
+
listResources,
|
|
5492
5831
|
listPrompts,
|
|
5493
5832
|
getPrompt,
|
|
5494
5833
|
retry,
|
|
@@ -5518,17 +5857,11 @@ function useOpenAiGlobal(key) {
|
|
|
5518
5857
|
onChange();
|
|
5519
5858
|
}, "handleSetGlobal");
|
|
5520
5859
|
if (typeof window !== "undefined") {
|
|
5521
|
-
window.addEventListener(
|
|
5522
|
-
SET_GLOBALS_EVENT_TYPE,
|
|
5523
|
-
handleSetGlobal
|
|
5524
|
-
);
|
|
5860
|
+
window.addEventListener(SET_GLOBALS_EVENT_TYPE, handleSetGlobal);
|
|
5525
5861
|
}
|
|
5526
5862
|
return () => {
|
|
5527
5863
|
if (typeof window !== "undefined") {
|
|
5528
|
-
window.removeEventListener(
|
|
5529
|
-
SET_GLOBALS_EVENT_TYPE,
|
|
5530
|
-
handleSetGlobal
|
|
5531
|
-
);
|
|
5864
|
+
window.removeEventListener(SET_GLOBALS_EVENT_TYPE, handleSetGlobal);
|
|
5532
5865
|
}
|
|
5533
5866
|
};
|
|
5534
5867
|
},
|
|
@@ -5538,7 +5871,10 @@ function useOpenAiGlobal(key) {
|
|
|
5538
5871
|
__name(useOpenAiGlobal, "useOpenAiGlobal");
|
|
5539
5872
|
function useWidget(defaultProps) {
|
|
5540
5873
|
console.log(window?.location?.search, window.openai);
|
|
5541
|
-
const isOpenAiAvailable = (0, import_react2.useMemo)(
|
|
5874
|
+
const isOpenAiAvailable = (0, import_react2.useMemo)(
|
|
5875
|
+
() => typeof window !== "undefined" && !!window.openai,
|
|
5876
|
+
[]
|
|
5877
|
+
);
|
|
5542
5878
|
const provider = (0, import_react2.useMemo)(() => {
|
|
5543
5879
|
return isOpenAiAvailable ? "openai" : "mcp-ui";
|
|
5544
5880
|
}, [isOpenAiAvailable]);
|
|
@@ -5579,12 +5915,15 @@ function useWidget(defaultProps) {
|
|
|
5579
5915
|
},
|
|
5580
5916
|
[]
|
|
5581
5917
|
);
|
|
5582
|
-
const sendFollowUpMessage = (0, import_react2.useCallback)(
|
|
5583
|
-
|
|
5584
|
-
|
|
5585
|
-
|
|
5586
|
-
|
|
5587
|
-
|
|
5918
|
+
const sendFollowUpMessage = (0, import_react2.useCallback)(
|
|
5919
|
+
async (prompt) => {
|
|
5920
|
+
if (!window.openai?.sendFollowUpMessage) {
|
|
5921
|
+
throw new Error("window.openai.sendFollowUpMessage is not available");
|
|
5922
|
+
}
|
|
5923
|
+
return window.openai.sendFollowUpMessage({ prompt });
|
|
5924
|
+
},
|
|
5925
|
+
[]
|
|
5926
|
+
);
|
|
5588
5927
|
const openExternal = (0, import_react2.useCallback)((href) => {
|
|
5589
5928
|
if (!window.openai?.openExternal) {
|
|
5590
5929
|
throw new Error("window.openai.openExternal is not available");
|