mcp-use 1.2.1 → 1.2.2-canary.0
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-C3SRZK7H.js +1339 -0
- package/dist/{chunk-JV7HAYUT.js → chunk-CPV4QNHD.js} +126 -293
- package/dist/{chunk-ZUEQQ6YK.js → chunk-EYAIJPBH.js} +3 -235
- package/dist/{chunk-MGUO7HXB.js → chunk-UVUM35MV.js} +3 -957
- package/dist/chunk-VPPILX7B.js +239 -0
- package/dist/index.cjs +223 -303
- package/dist/index.js +11 -10
- package/dist/{langfuse-6AJGHMAV.js → langfuse-MO3AMDBE.js} +2 -1
- package/dist/src/agents/prompts/system_prompt_builder.d.ts.map +1 -1
- package/dist/src/browser.cjs +67 -20
- package/dist/src/browser.js +10 -45
- package/dist/src/client/browser.d.ts.map +1 -1
- package/dist/src/connectors/base.d.ts +46 -4
- package/dist/src/connectors/base.d.ts.map +1 -1
- package/dist/src/connectors/http.d.ts.map +1 -1
- package/dist/src/connectors/websocket.d.ts +2 -5
- package/dist/src/connectors/websocket.d.ts.map +1 -1
- package/dist/src/react/index.cjs +1394 -285
- package/dist/src/react/index.js +3 -2
- package/dist/src/react/types.d.ts +22 -0
- package/dist/src/react/types.d.ts.map +1 -1
- package/dist/src/react/useMcp.d.ts +31 -0
- package/dist/src/react/useMcp.d.ts.map +1 -1
- package/package.json +3 -3
- package/dist/chunk-62GFHYCL.js +0 -300
package/dist/index.cjs
CHANGED
|
@@ -3325,6 +3325,7 @@ var BaseConnector = class {
|
|
|
3325
3325
|
client = null;
|
|
3326
3326
|
connectionManager = null;
|
|
3327
3327
|
toolsCache = null;
|
|
3328
|
+
capabilitiesCache = null;
|
|
3328
3329
|
connected = false;
|
|
3329
3330
|
opts;
|
|
3330
3331
|
constructor(opts = {}) {
|
|
@@ -3358,9 +3359,11 @@ var BaseConnector = class {
|
|
|
3358
3359
|
}
|
|
3359
3360
|
logger.debug("Caching server capabilities & tools");
|
|
3360
3361
|
const capabilities = this.client.getServerCapabilities();
|
|
3362
|
+
this.capabilitiesCache = capabilities;
|
|
3361
3363
|
const listToolsRes = await this.client.listTools(void 0, defaultRequestOptions);
|
|
3362
3364
|
this.toolsCache = listToolsRes.tools ?? [];
|
|
3363
3365
|
logger.debug(`Fetched ${this.toolsCache.length} tools from server`);
|
|
3366
|
+
logger.debug("Server capabilities:", capabilities);
|
|
3364
3367
|
return capabilities;
|
|
3365
3368
|
}
|
|
3366
3369
|
/** Lazily expose the cached tools list. */
|
|
@@ -3382,7 +3385,7 @@ var BaseConnector = class {
|
|
|
3382
3385
|
}
|
|
3383
3386
|
/**
|
|
3384
3387
|
* List resources from the server with optional pagination
|
|
3385
|
-
*
|
|
3388
|
+
*
|
|
3386
3389
|
* @param cursor - Optional cursor for pagination
|
|
3387
3390
|
* @param options - Request options
|
|
3388
3391
|
* @returns Resource list with optional nextCursor for pagination
|
|
@@ -3396,7 +3399,7 @@ var BaseConnector = class {
|
|
|
3396
3399
|
}
|
|
3397
3400
|
/**
|
|
3398
3401
|
* List all resources from the server, automatically handling pagination
|
|
3399
|
-
*
|
|
3402
|
+
*
|
|
3400
3403
|
* @param options - Request options
|
|
3401
3404
|
* @returns Complete list of all resources
|
|
3402
3405
|
*/
|
|
@@ -3404,19 +3407,31 @@ var BaseConnector = class {
|
|
|
3404
3407
|
if (!this.client) {
|
|
3405
3408
|
throw new Error("MCP client is not connected");
|
|
3406
3409
|
}
|
|
3407
|
-
|
|
3408
|
-
|
|
3409
|
-
|
|
3410
|
-
|
|
3411
|
-
|
|
3412
|
-
|
|
3413
|
-
|
|
3414
|
-
|
|
3415
|
-
|
|
3410
|
+
if (!this.capabilitiesCache?.resources) {
|
|
3411
|
+
logger.debug("Server does not advertise resources capability, skipping");
|
|
3412
|
+
return { resources: [] };
|
|
3413
|
+
}
|
|
3414
|
+
try {
|
|
3415
|
+
logger.debug("Listing all resources (with auto-pagination)");
|
|
3416
|
+
const allResources = [];
|
|
3417
|
+
let cursor = void 0;
|
|
3418
|
+
do {
|
|
3419
|
+
const result = await this.client.listResources({ cursor }, options);
|
|
3420
|
+
allResources.push(...result.resources || []);
|
|
3421
|
+
cursor = result.nextCursor;
|
|
3422
|
+
} while (cursor);
|
|
3423
|
+
return { resources: allResources };
|
|
3424
|
+
} catch (err) {
|
|
3425
|
+
if (err.code === -32601) {
|
|
3426
|
+
logger.debug("Server advertised resources but method not found");
|
|
3427
|
+
return { resources: [] };
|
|
3428
|
+
}
|
|
3429
|
+
throw err;
|
|
3430
|
+
}
|
|
3416
3431
|
}
|
|
3417
3432
|
/**
|
|
3418
3433
|
* List resource templates from the server
|
|
3419
|
-
*
|
|
3434
|
+
*
|
|
3420
3435
|
* @param options - Request options
|
|
3421
3436
|
* @returns List of available resource templates
|
|
3422
3437
|
*/
|
|
@@ -3434,11 +3449,11 @@ var BaseConnector = class {
|
|
|
3434
3449
|
}
|
|
3435
3450
|
logger.debug(`Reading resource ${uri}`);
|
|
3436
3451
|
const res = await this.client.readResource({ uri }, options);
|
|
3437
|
-
return
|
|
3452
|
+
return res;
|
|
3438
3453
|
}
|
|
3439
3454
|
/**
|
|
3440
3455
|
* Subscribe to resource updates
|
|
3441
|
-
*
|
|
3456
|
+
*
|
|
3442
3457
|
* @param uri - URI of the resource to subscribe to
|
|
3443
3458
|
* @param options - Request options
|
|
3444
3459
|
*/
|
|
@@ -3451,7 +3466,7 @@ var BaseConnector = class {
|
|
|
3451
3466
|
}
|
|
3452
3467
|
/**
|
|
3453
3468
|
* Unsubscribe from resource updates
|
|
3454
|
-
*
|
|
3469
|
+
*
|
|
3455
3470
|
* @param uri - URI of the resource to unsubscribe from
|
|
3456
3471
|
* @param options - Request options
|
|
3457
3472
|
*/
|
|
@@ -3466,8 +3481,20 @@ var BaseConnector = class {
|
|
|
3466
3481
|
if (!this.client) {
|
|
3467
3482
|
throw new Error("MCP client is not connected");
|
|
3468
3483
|
}
|
|
3469
|
-
|
|
3470
|
-
|
|
3484
|
+
if (!this.capabilitiesCache?.prompts) {
|
|
3485
|
+
logger.debug("Server does not advertise prompts capability, skipping");
|
|
3486
|
+
return { prompts: [] };
|
|
3487
|
+
}
|
|
3488
|
+
try {
|
|
3489
|
+
logger.debug("Listing prompts");
|
|
3490
|
+
return await this.client.listPrompts();
|
|
3491
|
+
} catch (err) {
|
|
3492
|
+
if (err.code === -32601) {
|
|
3493
|
+
logger.debug("Server advertised prompts but method not found");
|
|
3494
|
+
return { prompts: [] };
|
|
3495
|
+
}
|
|
3496
|
+
throw err;
|
|
3497
|
+
}
|
|
3471
3498
|
}
|
|
3472
3499
|
async getPrompt(name, args) {
|
|
3473
3500
|
if (!this.client) {
|
|
@@ -3563,7 +3590,9 @@ var HttpConnector = class extends BaseConnector {
|
|
|
3563
3590
|
logger.info("\u2705 Successfully connected via streamable HTTP");
|
|
3564
3591
|
} catch (err) {
|
|
3565
3592
|
let fallbackReason = "Unknown error";
|
|
3593
|
+
let is401Error = false;
|
|
3566
3594
|
if (err instanceof import_streamableHttp2.StreamableHTTPError) {
|
|
3595
|
+
is401Error = err.code === 401;
|
|
3567
3596
|
if (err.code === 400 && err.message.includes("Missing session ID")) {
|
|
3568
3597
|
fallbackReason = "Server requires session ID (FastMCP compatibility) - using SSE transport";
|
|
3569
3598
|
logger.warn(`\u26A0\uFE0F ${fallbackReason}`);
|
|
@@ -3577,6 +3606,7 @@ var HttpConnector = class extends BaseConnector {
|
|
|
3577
3606
|
} else if (err instanceof Error) {
|
|
3578
3607
|
const errorStr = err.toString();
|
|
3579
3608
|
const errorMsg = err.message || "";
|
|
3609
|
+
is401Error = errorStr.includes("401") || errorMsg.includes("Unauthorized");
|
|
3580
3610
|
if (errorStr.includes("Missing session ID") || errorStr.includes("Bad Request: Missing session ID") || errorMsg.includes("FastMCP session ID error")) {
|
|
3581
3611
|
fallbackReason = "Server requires session ID (FastMCP compatibility) - using SSE transport";
|
|
3582
3612
|
logger.warn(`\u26A0\uFE0F ${fallbackReason}`);
|
|
@@ -3588,6 +3618,13 @@ var HttpConnector = class extends BaseConnector {
|
|
|
3588
3618
|
logger.debug(fallbackReason);
|
|
3589
3619
|
}
|
|
3590
3620
|
}
|
|
3621
|
+
if (is401Error) {
|
|
3622
|
+
logger.info("Authentication required - skipping SSE fallback");
|
|
3623
|
+
await this.cleanupResources();
|
|
3624
|
+
const authError = new Error("Authentication required");
|
|
3625
|
+
authError.code = 401;
|
|
3626
|
+
throw authError;
|
|
3627
|
+
}
|
|
3591
3628
|
logger.info("\u{1F504} Falling back to SSE transport...");
|
|
3592
3629
|
try {
|
|
3593
3630
|
await this.connectWithSse(baseUrl);
|
|
@@ -3596,6 +3633,12 @@ var HttpConnector = class extends BaseConnector {
|
|
|
3596
3633
|
logger.error(` Streamable HTTP: ${fallbackReason}`);
|
|
3597
3634
|
logger.error(` SSE: ${sseErr}`);
|
|
3598
3635
|
await this.cleanupResources();
|
|
3636
|
+
const sseIs401 = sseErr?.message?.includes("401") || sseErr?.message?.includes("Unauthorized");
|
|
3637
|
+
if (sseIs401) {
|
|
3638
|
+
const authError = new Error("Authentication required");
|
|
3639
|
+
authError.code = 401;
|
|
3640
|
+
throw authError;
|
|
3641
|
+
}
|
|
3599
3642
|
throw new Error("Could not connect to server with any available transport");
|
|
3600
3643
|
}
|
|
3601
3644
|
}
|
|
@@ -3605,6 +3648,8 @@ var HttpConnector = class extends BaseConnector {
|
|
|
3605
3648
|
this.connectionManager = new StreamableHttpConnectionManager(
|
|
3606
3649
|
baseUrl,
|
|
3607
3650
|
{
|
|
3651
|
+
authProvider: this.opts.authProvider,
|
|
3652
|
+
// ← Pass OAuth provider to SDK
|
|
3608
3653
|
requestInit: {
|
|
3609
3654
|
headers: this.headers
|
|
3610
3655
|
},
|
|
@@ -4002,7 +4047,7 @@ var WebSocketConnector = class extends BaseConnector {
|
|
|
4002
4047
|
}
|
|
4003
4048
|
async readResource(uri) {
|
|
4004
4049
|
const res = await this.sendRequest("resources/read", { uri });
|
|
4005
|
-
return
|
|
4050
|
+
return res;
|
|
4006
4051
|
}
|
|
4007
4052
|
async request(method, params = null) {
|
|
4008
4053
|
return await this.sendRequest(method, params);
|
|
@@ -4821,14 +4866,45 @@ async function onMcpAuthorization() {
|
|
|
4821
4866
|
__name(onMcpAuthorization, "onMcpAuthorization");
|
|
4822
4867
|
|
|
4823
4868
|
// src/react/useMcp.ts
|
|
4824
|
-
var import_types = require("@modelcontextprotocol/sdk/types.js");
|
|
4825
4869
|
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
4870
|
var import_strict_url_sanitise2 = require("strict-url-sanitise");
|
|
4831
4871
|
|
|
4872
|
+
// src/client/browser.ts
|
|
4873
|
+
var BrowserMCPClient = class _BrowserMCPClient extends BaseMCPClient {
|
|
4874
|
+
static {
|
|
4875
|
+
__name(this, "BrowserMCPClient");
|
|
4876
|
+
}
|
|
4877
|
+
constructor(config2) {
|
|
4878
|
+
super(config2);
|
|
4879
|
+
}
|
|
4880
|
+
static fromDict(cfg) {
|
|
4881
|
+
return new _BrowserMCPClient(cfg);
|
|
4882
|
+
}
|
|
4883
|
+
/**
|
|
4884
|
+
* Create a connector from server configuration (Browser version)
|
|
4885
|
+
* Supports HTTP and WebSocket connectors only
|
|
4886
|
+
*/
|
|
4887
|
+
createConnectorFromConfig(serverConfig) {
|
|
4888
|
+
const { url, transport, headers, authToken, authProvider } = serverConfig;
|
|
4889
|
+
if (!url) {
|
|
4890
|
+
throw new Error("Server URL is required");
|
|
4891
|
+
}
|
|
4892
|
+
const connectorOptions = {
|
|
4893
|
+
headers,
|
|
4894
|
+
authToken,
|
|
4895
|
+
authProvider
|
|
4896
|
+
// ← Pass OAuth provider to connector
|
|
4897
|
+
};
|
|
4898
|
+
if (transport === "websocket" || url.startsWith("ws://") || url.startsWith("wss://")) {
|
|
4899
|
+
return new WebSocketConnector(url, connectorOptions);
|
|
4900
|
+
} else if (transport === "http" || url.startsWith("http://") || url.startsWith("https://")) {
|
|
4901
|
+
return new HttpConnector(url, connectorOptions);
|
|
4902
|
+
} else {
|
|
4903
|
+
return new HttpConnector(url, connectorOptions);
|
|
4904
|
+
}
|
|
4905
|
+
}
|
|
4906
|
+
};
|
|
4907
|
+
|
|
4832
4908
|
// src/utils/assert.ts
|
|
4833
4909
|
function assert(condition, message) {
|
|
4834
4910
|
if (!condition) {
|
|
@@ -4871,7 +4947,6 @@ function useMcp(options) {
|
|
|
4871
4947
|
const [log, setLog] = (0, import_react.useState)([]);
|
|
4872
4948
|
const [authUrl, setAuthUrl] = (0, import_react.useState)(void 0);
|
|
4873
4949
|
const clientRef = (0, import_react.useRef)(null);
|
|
4874
|
-
const transportRef = (0, import_react.useRef)(null);
|
|
4875
4950
|
const authProviderRef = (0, import_react.useRef)(null);
|
|
4876
4951
|
const connectingRef = (0, import_react.useRef)(false);
|
|
4877
4952
|
const isMountedRef = (0, import_react.useRef)(true);
|
|
@@ -4900,9 +4975,15 @@ function useMcp(options) {
|
|
|
4900
4975
|
connectingRef.current = false;
|
|
4901
4976
|
if (authTimeoutRef.current) clearTimeout(authTimeoutRef.current);
|
|
4902
4977
|
authTimeoutRef.current = null;
|
|
4903
|
-
|
|
4978
|
+
if (clientRef.current) {
|
|
4979
|
+
try {
|
|
4980
|
+
const serverName = "inspector-server";
|
|
4981
|
+
await clientRef.current.closeSession(serverName);
|
|
4982
|
+
} catch (err) {
|
|
4983
|
+
if (!quiet) addLog("warn", "Error closing session:", err);
|
|
4984
|
+
}
|
|
4985
|
+
}
|
|
4904
4986
|
clientRef.current = null;
|
|
4905
|
-
transportRef.current = null;
|
|
4906
4987
|
if (isMountedRef.current && !quiet) {
|
|
4907
4988
|
setState("discovering");
|
|
4908
4989
|
setTools([]);
|
|
@@ -4912,14 +4993,6 @@ function useMcp(options) {
|
|
|
4912
4993
|
setError(void 0);
|
|
4913
4994
|
setAuthUrl(void 0);
|
|
4914
4995
|
}
|
|
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
4996
|
},
|
|
4924
4997
|
[addLog]
|
|
4925
4998
|
);
|
|
@@ -4971,187 +5044,60 @@ function useMcp(options) {
|
|
|
4971
5044
|
addLog("debug", "BrowserOAuthClientProvider initialized in connect.");
|
|
4972
5045
|
}
|
|
4973
5046
|
if (!clientRef.current) {
|
|
4974
|
-
clientRef.current = new
|
|
4975
|
-
|
|
4976
|
-
{ capabilities: {} }
|
|
4977
|
-
);
|
|
4978
|
-
addLog("debug", "MCP Client initialized in connect.");
|
|
5047
|
+
clientRef.current = new BrowserMCPClient();
|
|
5048
|
+
addLog("debug", "BrowserMCPClient initialized in connect.");
|
|
4979
5049
|
}
|
|
4980
5050
|
const tryConnectWithTransport = /* @__PURE__ */ __name(async (transportTypeParam, isAuthRetry = false) => {
|
|
4981
|
-
addLog("info", `Attempting connection with ${transportTypeParam
|
|
4982
|
-
if (stateRef.current !== "authenticating") {
|
|
4983
|
-
setState("connecting");
|
|
4984
|
-
}
|
|
4985
|
-
let transportInstance;
|
|
5051
|
+
addLog("info", `Attempting connection with transport: ${transportTypeParam}`);
|
|
4986
5052
|
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
|
|
5053
|
+
const serverName = "inspector-server";
|
|
5054
|
+
const serverConfig = {
|
|
5055
|
+
url,
|
|
5056
|
+
transport: transportTypeParam === "sse" ? "http" : transportTypeParam
|
|
5004
5057
|
};
|
|
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");
|
|
5050
|
-
}
|
|
5051
|
-
};
|
|
5052
|
-
try {
|
|
5053
|
-
addLog("info", `Connecting client via ${transportTypeParam.toUpperCase()}...`);
|
|
5054
|
-
await clientRef.current.connect(transportInstance);
|
|
5055
|
-
addLog("info", `Client connected via ${transportTypeParam.toUpperCase()}. Loading tools, resources, and prompts...`);
|
|
5056
|
-
successfulTransportRef.current = transportTypeParam;
|
|
5057
|
-
setState("loading");
|
|
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);
|
|
5058
|
+
if (customHeaders && Object.keys(customHeaders).length > 0) {
|
|
5059
|
+
serverConfig.headers = customHeaders;
|
|
5064
5060
|
}
|
|
5065
|
-
|
|
5066
|
-
|
|
5067
|
-
|
|
5068
|
-
|
|
5069
|
-
|
|
5070
|
-
|
|
5071
|
-
|
|
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`);
|
|
5061
|
+
if (authProviderRef.current) {
|
|
5062
|
+
const tokens = await authProviderRef.current.tokens();
|
|
5063
|
+
if (tokens?.access_token) {
|
|
5064
|
+
serverConfig.headers = {
|
|
5065
|
+
...serverConfig.headers,
|
|
5066
|
+
Authorization: `Bearer ${tokens.access_token}`
|
|
5067
|
+
};
|
|
5085
5068
|
}
|
|
5086
|
-
addLog("info", summary.join(", ") + ".");
|
|
5087
|
-
setState("ready");
|
|
5088
|
-
connectAttemptRef.current = 0;
|
|
5089
|
-
return "success";
|
|
5090
|
-
} else {
|
|
5091
|
-
return "failed";
|
|
5092
5069
|
}
|
|
5093
|
-
|
|
5094
|
-
|
|
5095
|
-
|
|
5096
|
-
|
|
5097
|
-
|
|
5098
|
-
const
|
|
5099
|
-
|
|
5100
|
-
|
|
5101
|
-
|
|
5102
|
-
|
|
5103
|
-
|
|
5104
|
-
|
|
5105
|
-
|
|
5106
|
-
|
|
5107
|
-
|
|
5108
|
-
|
|
5109
|
-
|
|
5110
|
-
|
|
5111
|
-
|
|
5112
|
-
|
|
5113
|
-
if (preventAutoAuth && !existingTokens) {
|
|
5114
|
-
addLog("info", "Authentication required but auto-auth prevented. User action needed.");
|
|
5115
|
-
setState("pending_auth");
|
|
5116
|
-
return "auth_redirect";
|
|
5117
|
-
}
|
|
5118
|
-
if (stateRef.current !== "authenticating" && stateRef.current !== "pending_auth") {
|
|
5119
|
-
setState("authenticating");
|
|
5120
|
-
if (authTimeoutRef.current) clearTimeout(authTimeoutRef.current);
|
|
5121
|
-
authTimeoutRef.current = setTimeout(() => {
|
|
5122
|
-
if (isMountedRef.current) {
|
|
5123
|
-
const currentState = stateRef.current;
|
|
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);
|
|
5070
|
+
clientRef.current.addServer(serverName, {
|
|
5071
|
+
...serverConfig,
|
|
5072
|
+
authProvider: authProviderRef.current
|
|
5073
|
+
// ← SDK handles OAuth automatically!
|
|
5074
|
+
});
|
|
5075
|
+
const session = await clientRef.current.createSession(serverName);
|
|
5076
|
+
await session.initialize();
|
|
5077
|
+
addLog("info", "\u2705 Successfully connected to MCP server");
|
|
5078
|
+
setState("ready");
|
|
5079
|
+
successfulTransportRef.current = transportTypeParam;
|
|
5080
|
+
setTools(session.connector.tools || []);
|
|
5081
|
+
const resourcesResult = await session.connector.listAllResources();
|
|
5082
|
+
setResources(resourcesResult.resources || []);
|
|
5083
|
+
const promptsResult = await session.connector.listPrompts();
|
|
5084
|
+
setPrompts(promptsResult.prompts || []);
|
|
5085
|
+
return "success";
|
|
5086
|
+
} catch (err) {
|
|
5087
|
+
const errorMessage = err?.message || String(err);
|
|
5088
|
+
if (err.code === 401 || errorMessage.includes("401") || errorMessage.includes("Unauthorized")) {
|
|
5089
|
+
if (customHeaders && Object.keys(customHeaders).length > 0) {
|
|
5147
5090
|
failConnection(
|
|
5148
|
-
|
|
5149
|
-
sdkAuthError instanceof Error ? sdkAuthError : void 0
|
|
5091
|
+
"Authentication failed: Server returned 401 Unauthorized. Check your Authorization header value is correct."
|
|
5150
5092
|
);
|
|
5151
5093
|
return "failed";
|
|
5152
5094
|
}
|
|
5095
|
+
failConnection(
|
|
5096
|
+
"Authentication required: Server returned 401 Unauthorized. Add an Authorization header in the Custom Headers section (e.g., Authorization: Bearer YOUR_API_KEY)."
|
|
5097
|
+
);
|
|
5098
|
+
return "failed";
|
|
5153
5099
|
}
|
|
5154
|
-
failConnection(
|
|
5100
|
+
failConnection(errorMessage, err);
|
|
5155
5101
|
return "failed";
|
|
5156
5102
|
}
|
|
5157
5103
|
}, "tryConnectWithTransport");
|
|
@@ -5203,55 +5149,20 @@ function useMcp(options) {
|
|
|
5203
5149
|
}
|
|
5204
5150
|
addLog("info", `Calling tool: ${name}`, args);
|
|
5205
5151
|
try {
|
|
5206
|
-
const
|
|
5152
|
+
const serverName = "inspector-server";
|
|
5153
|
+
const session = clientRef.current.getSession(serverName);
|
|
5154
|
+
if (!session) {
|
|
5155
|
+
throw new Error("No active session found");
|
|
5156
|
+
}
|
|
5157
|
+
const result = await session.connector.callTool(name, args || {});
|
|
5207
5158
|
addLog("info", `Tool "${name}" call successful:`, result);
|
|
5208
5159
|
return result;
|
|
5209
5160
|
} 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;
|
|
5161
|
+
addLog("error", `Tool "${name}" call failed:`, err);
|
|
5162
|
+
throw err;
|
|
5252
5163
|
}
|
|
5253
5164
|
},
|
|
5254
|
-
[state
|
|
5165
|
+
[state]
|
|
5255
5166
|
);
|
|
5256
5167
|
const retry = (0, import_react.useCallback)(() => {
|
|
5257
5168
|
if (stateRef.current === "failed") {
|
|
@@ -5282,17 +5193,7 @@ function useMcp(options) {
|
|
|
5282
5193
|
try {
|
|
5283
5194
|
assert(authProviderRef.current, "Auth Provider not available for manual auth");
|
|
5284
5195
|
assert(url, "Server URL is required for authentication");
|
|
5285
|
-
|
|
5286
|
-
const authResult = await (0, import_auth2.auth)(authProviderRef.current, { serverUrl: baseUrl });
|
|
5287
|
-
if (!isMountedRef.current) return;
|
|
5288
|
-
if (authResult === "AUTHORIZED") {
|
|
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
|
-
}
|
|
5196
|
+
addLog("info", "Redirecting for manual authentication. Waiting for callback...");
|
|
5296
5197
|
} catch (authError) {
|
|
5297
5198
|
if (!isMountedRef.current) return;
|
|
5298
5199
|
if (authTimeoutRef.current) clearTimeout(authTimeoutRef.current);
|
|
@@ -5325,75 +5226,93 @@ function useMcp(options) {
|
|
|
5325
5226
|
addLog("warn", "Auth provider not initialized, cannot clear storage.");
|
|
5326
5227
|
}
|
|
5327
5228
|
}, [url, addLog, disconnect]);
|
|
5328
|
-
const listResources = (0, import_react.useCallback)(
|
|
5329
|
-
|
|
5330
|
-
|
|
5331
|
-
|
|
5332
|
-
addLog("info", "Listing resources...");
|
|
5333
|
-
try {
|
|
5334
|
-
const resourcesResponse = await clientRef.current.request({ method: "resources/list" }, import_types.ListResourcesResultSchema);
|
|
5335
|
-
if (isMountedRef.current) {
|
|
5336
|
-
setResources(resourcesResponse.resources);
|
|
5337
|
-
setResourceTemplates(Array.isArray(resourcesResponse.resourceTemplates) ? resourcesResponse.resourceTemplates : []);
|
|
5338
|
-
addLog(
|
|
5339
|
-
"info",
|
|
5340
|
-
`Listed ${resourcesResponse.resources.length} resources, ${Array.isArray(resourcesResponse.resourceTemplates) ? resourcesResponse.resourceTemplates.length : 0} resource templates.`
|
|
5341
|
-
);
|
|
5229
|
+
const listResources = (0, import_react.useCallback)(
|
|
5230
|
+
async () => {
|
|
5231
|
+
if (stateRef.current !== "ready" || !clientRef.current) {
|
|
5232
|
+
throw new Error(`MCP client is not ready (current state: ${state}). Cannot list resources.`);
|
|
5342
5233
|
}
|
|
5343
|
-
|
|
5344
|
-
|
|
5345
|
-
|
|
5346
|
-
|
|
5347
|
-
|
|
5234
|
+
addLog("info", "Listing resources");
|
|
5235
|
+
try {
|
|
5236
|
+
const serverName = "inspector-server";
|
|
5237
|
+
const session = clientRef.current.getSession(serverName);
|
|
5238
|
+
if (!session) {
|
|
5239
|
+
throw new Error("No active session found");
|
|
5240
|
+
}
|
|
5241
|
+
const resourcesResult = await session.connector.listAllResources();
|
|
5242
|
+
setResources(resourcesResult.resources || []);
|
|
5243
|
+
addLog("info", "Resources listed successfully");
|
|
5244
|
+
} catch (err) {
|
|
5245
|
+
addLog("error", "List resources failed:", err);
|
|
5246
|
+
throw err;
|
|
5247
|
+
}
|
|
5248
|
+
},
|
|
5249
|
+
[state]
|
|
5250
|
+
);
|
|
5348
5251
|
const readResource = (0, import_react.useCallback)(
|
|
5349
5252
|
async (uri) => {
|
|
5350
5253
|
if (stateRef.current !== "ready" || !clientRef.current) {
|
|
5351
|
-
throw new Error(`MCP client is not ready (current state: ${state}). Cannot read resource
|
|
5254
|
+
throw new Error(`MCP client is not ready (current state: ${state}). Cannot read resource.`);
|
|
5352
5255
|
}
|
|
5353
5256
|
addLog("info", `Reading resource: ${uri}`);
|
|
5354
5257
|
try {
|
|
5355
|
-
const
|
|
5356
|
-
|
|
5258
|
+
const serverName = "inspector-server";
|
|
5259
|
+
const session = clientRef.current.getSession(serverName);
|
|
5260
|
+
if (!session) {
|
|
5261
|
+
throw new Error("No active session found");
|
|
5262
|
+
}
|
|
5263
|
+
const result = await session.connector.readResource(uri);
|
|
5264
|
+
addLog("info", "Resource read successful:", result);
|
|
5357
5265
|
return result;
|
|
5358
5266
|
} catch (err) {
|
|
5359
|
-
addLog("error",
|
|
5267
|
+
addLog("error", "Resource read failed:", err);
|
|
5360
5268
|
throw err;
|
|
5361
5269
|
}
|
|
5362
5270
|
},
|
|
5363
|
-
[state
|
|
5271
|
+
[state]
|
|
5364
5272
|
);
|
|
5365
|
-
const listPrompts = (0, import_react.useCallback)(
|
|
5366
|
-
|
|
5367
|
-
|
|
5368
|
-
|
|
5369
|
-
addLog("info", "Listing prompts...");
|
|
5370
|
-
try {
|
|
5371
|
-
const promptsResponse = await clientRef.current.request({ method: "prompts/list" }, import_types.ListPromptsResultSchema);
|
|
5372
|
-
if (isMountedRef.current) {
|
|
5373
|
-
setPrompts(promptsResponse.prompts);
|
|
5374
|
-
addLog("info", `Listed ${promptsResponse.prompts.length} prompts.`);
|
|
5273
|
+
const listPrompts = (0, import_react.useCallback)(
|
|
5274
|
+
async () => {
|
|
5275
|
+
if (stateRef.current !== "ready" || !clientRef.current) {
|
|
5276
|
+
throw new Error(`MCP client is not ready (current state: ${state}). Cannot list prompts.`);
|
|
5375
5277
|
}
|
|
5376
|
-
|
|
5377
|
-
|
|
5378
|
-
|
|
5379
|
-
|
|
5380
|
-
|
|
5278
|
+
addLog("info", "Listing prompts");
|
|
5279
|
+
try {
|
|
5280
|
+
const serverName = "inspector-server";
|
|
5281
|
+
const session = clientRef.current.getSession(serverName);
|
|
5282
|
+
if (!session) {
|
|
5283
|
+
throw new Error("No active session found");
|
|
5284
|
+
}
|
|
5285
|
+
const promptsResult = await session.connector.listPrompts();
|
|
5286
|
+
setPrompts(promptsResult.prompts || []);
|
|
5287
|
+
addLog("info", "Prompts listed successfully");
|
|
5288
|
+
} catch (err) {
|
|
5289
|
+
addLog("error", "List prompts failed:", err);
|
|
5290
|
+
throw err;
|
|
5291
|
+
}
|
|
5292
|
+
},
|
|
5293
|
+
[state]
|
|
5294
|
+
);
|
|
5381
5295
|
const getPrompt = (0, import_react.useCallback)(
|
|
5382
5296
|
async (name, args) => {
|
|
5383
5297
|
if (stateRef.current !== "ready" || !clientRef.current) {
|
|
5384
|
-
throw new Error(`MCP client is not ready (current state: ${state}). Cannot get prompt
|
|
5298
|
+
throw new Error(`MCP client is not ready (current state: ${state}). Cannot get prompt.`);
|
|
5385
5299
|
}
|
|
5386
5300
|
addLog("info", `Getting prompt: ${name}`, args);
|
|
5387
5301
|
try {
|
|
5388
|
-
const
|
|
5389
|
-
|
|
5302
|
+
const serverName = "inspector-server";
|
|
5303
|
+
const session = clientRef.current.getSession(serverName);
|
|
5304
|
+
if (!session) {
|
|
5305
|
+
throw new Error("No active session found");
|
|
5306
|
+
}
|
|
5307
|
+
const result = await session.connector.getPrompt(name, args || {});
|
|
5308
|
+
addLog("info", `Prompt "${name}" retrieved successfully:`, result);
|
|
5390
5309
|
return result;
|
|
5391
5310
|
} catch (err) {
|
|
5392
|
-
addLog("error", `
|
|
5311
|
+
addLog("error", `Prompt "${name}" retrieval failed:`, err);
|
|
5393
5312
|
throw err;
|
|
5394
5313
|
}
|
|
5395
5314
|
},
|
|
5396
|
-
[state
|
|
5315
|
+
[state]
|
|
5397
5316
|
);
|
|
5398
5317
|
const connectRef = (0, import_react.useRef)(connect);
|
|
5399
5318
|
const failConnectionRef = (0, import_react.useRef)(failConnection);
|
|
@@ -5486,9 +5405,10 @@ function useMcp(options) {
|
|
|
5486
5405
|
error,
|
|
5487
5406
|
log,
|
|
5488
5407
|
authUrl,
|
|
5408
|
+
client: clientRef.current,
|
|
5489
5409
|
callTool,
|
|
5490
|
-
listResources,
|
|
5491
5410
|
readResource,
|
|
5411
|
+
listResources,
|
|
5492
5412
|
listPrompts,
|
|
5493
5413
|
getPrompt,
|
|
5494
5414
|
retry,
|