@mcp-use/client 2.1.0 → 2.1.1-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/auth/browser.d.ts +8 -0
- package/dist/auth/browser.d.ts.map +1 -1
- package/dist/auth/flow.d.ts +9 -0
- package/dist/auth/flow.d.ts.map +1 -1
- package/dist/core/browser.d.ts.map +1 -1
- package/dist/core/config.d.ts +6 -0
- package/dist/core/config.d.ts.map +1 -1
- package/dist/core/session.d.ts +17 -0
- package/dist/core/session.d.ts.map +1 -1
- package/dist/index-browser.d.ts +1 -1
- package/dist/index-browser.d.ts.map +1 -1
- package/dist/index-browser.js +269 -41
- package/dist/index-browser.js.map +1 -1
- package/dist/index.d.ts +1 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +635 -408
- package/dist/index.js.map +1 -1
- package/dist/react/McpClientProvider.d.ts.map +1 -1
- package/dist/react/index.d.ts +1 -0
- package/dist/react/index.d.ts.map +1 -1
- package/dist/react/index.js +421 -143
- package/dist/react/index.js.map +1 -1
- package/dist/react/types.d.ts +10 -1
- package/dist/react/types.d.ts.map +1 -1
- package/dist/react/useMcp-operations.d.ts +1 -0
- package/dist/react/useMcp-operations.d.ts.map +1 -1
- package/dist/react/useMcp.d.ts.map +1 -1
- package/dist/transport/base.d.ts +11 -1
- package/dist/transport/base.d.ts.map +1 -1
- package/dist/transport/http.d.ts +11 -0
- package/dist/transport/http.d.ts.map +1 -1
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -142,6 +142,268 @@ var init_logging = __esm({
|
|
|
142
142
|
}
|
|
143
143
|
});
|
|
144
144
|
|
|
145
|
+
// src/auth/popup.ts
|
|
146
|
+
function hasStoredTokens(tokensKey) {
|
|
147
|
+
try {
|
|
148
|
+
return typeof localStorage !== "undefined" && !!localStorage.getItem(tokensKey);
|
|
149
|
+
} catch {
|
|
150
|
+
return false;
|
|
151
|
+
}
|
|
152
|
+
}
|
|
153
|
+
function runAuthPopup({
|
|
154
|
+
popup,
|
|
155
|
+
state,
|
|
156
|
+
tokensKey,
|
|
157
|
+
timeoutMs = 5 * 6e4,
|
|
158
|
+
closePollMs = 1e3,
|
|
159
|
+
closeGraceMs = 2e4,
|
|
160
|
+
expectedOrigin = typeof window !== "undefined" ? window.location.origin : ""
|
|
161
|
+
}) {
|
|
162
|
+
return new Promise((resolve) => {
|
|
163
|
+
let settled = false;
|
|
164
|
+
let closeTimer = null;
|
|
165
|
+
let timeoutTimer = null;
|
|
166
|
+
let graceTimer = null;
|
|
167
|
+
let broadcastChannel = null;
|
|
168
|
+
const cleanup = () => {
|
|
169
|
+
if (closeTimer) {
|
|
170
|
+
clearInterval(closeTimer);
|
|
171
|
+
closeTimer = null;
|
|
172
|
+
}
|
|
173
|
+
if (timeoutTimer) {
|
|
174
|
+
clearTimeout(timeoutTimer);
|
|
175
|
+
timeoutTimer = null;
|
|
176
|
+
}
|
|
177
|
+
if (graceTimer) {
|
|
178
|
+
clearTimeout(graceTimer);
|
|
179
|
+
graceTimer = null;
|
|
180
|
+
}
|
|
181
|
+
if (typeof window !== "undefined") {
|
|
182
|
+
window.removeEventListener("message", messageHandler);
|
|
183
|
+
window.removeEventListener("storage", storageHandler);
|
|
184
|
+
}
|
|
185
|
+
if (broadcastChannel) {
|
|
186
|
+
try {
|
|
187
|
+
broadcastChannel.removeEventListener("message", broadcastHandler);
|
|
188
|
+
broadcastChannel.close();
|
|
189
|
+
} catch {
|
|
190
|
+
}
|
|
191
|
+
broadcastChannel = null;
|
|
192
|
+
}
|
|
193
|
+
};
|
|
194
|
+
const settle = (result) => {
|
|
195
|
+
if (settled) return;
|
|
196
|
+
settled = true;
|
|
197
|
+
cleanup();
|
|
198
|
+
resolve(result);
|
|
199
|
+
};
|
|
200
|
+
const handlePayload = (payload) => {
|
|
201
|
+
if (!payload || payload.type !== MCP_AUTH_CALLBACK_MESSAGE_TYPE) return;
|
|
202
|
+
if (payload.state && state && payload.state !== state) return;
|
|
203
|
+
if (payload.success) {
|
|
204
|
+
settle({ kind: "success" });
|
|
205
|
+
} else {
|
|
206
|
+
settle({
|
|
207
|
+
kind: "error",
|
|
208
|
+
error: payload.error ?? "Authentication failed in callback."
|
|
209
|
+
});
|
|
210
|
+
}
|
|
211
|
+
};
|
|
212
|
+
const messageHandler = (event) => {
|
|
213
|
+
if (expectedOrigin && event.origin !== expectedOrigin) return;
|
|
214
|
+
handlePayload(event.data);
|
|
215
|
+
};
|
|
216
|
+
const broadcastHandler = (event) => {
|
|
217
|
+
handlePayload(event.data);
|
|
218
|
+
};
|
|
219
|
+
const storageHandler = (event) => {
|
|
220
|
+
if (event.key !== tokensKey) return;
|
|
221
|
+
if (event.newValue) settle({ kind: "success" });
|
|
222
|
+
};
|
|
223
|
+
if (typeof window !== "undefined") {
|
|
224
|
+
window.addEventListener("message", messageHandler);
|
|
225
|
+
window.addEventListener("storage", storageHandler);
|
|
226
|
+
}
|
|
227
|
+
if (typeof BroadcastChannel !== "undefined") {
|
|
228
|
+
try {
|
|
229
|
+
broadcastChannel = new BroadcastChannel(MCP_AUTH_BROADCAST_CHANNEL);
|
|
230
|
+
broadcastChannel.addEventListener("message", broadcastHandler);
|
|
231
|
+
} catch {
|
|
232
|
+
broadcastChannel = null;
|
|
233
|
+
}
|
|
234
|
+
}
|
|
235
|
+
if (popup) {
|
|
236
|
+
closeTimer = setInterval(() => {
|
|
237
|
+
if (settled) return;
|
|
238
|
+
let closed = false;
|
|
239
|
+
try {
|
|
240
|
+
closed = popup.closed;
|
|
241
|
+
} catch {
|
|
242
|
+
closed = false;
|
|
243
|
+
}
|
|
244
|
+
if (!closed) return;
|
|
245
|
+
if (closeTimer) {
|
|
246
|
+
clearInterval(closeTimer);
|
|
247
|
+
closeTimer = null;
|
|
248
|
+
}
|
|
249
|
+
if (hasStoredTokens(tokensKey)) {
|
|
250
|
+
settle({ kind: "success" });
|
|
251
|
+
return;
|
|
252
|
+
}
|
|
253
|
+
graceTimer = setTimeout(() => {
|
|
254
|
+
settle(
|
|
255
|
+
hasStoredTokens(tokensKey) ? { kind: "success" } : { kind: "cancelled" }
|
|
256
|
+
);
|
|
257
|
+
}, closeGraceMs);
|
|
258
|
+
}, closePollMs);
|
|
259
|
+
}
|
|
260
|
+
timeoutTimer = setTimeout(() => {
|
|
261
|
+
settle(
|
|
262
|
+
hasStoredTokens(tokensKey) ? { kind: "success" } : { kind: "timeout" }
|
|
263
|
+
);
|
|
264
|
+
}, timeoutMs);
|
|
265
|
+
});
|
|
266
|
+
}
|
|
267
|
+
var MCP_AUTH_BROADCAST_CHANNEL, MCP_AUTH_CALLBACK_MESSAGE_TYPE;
|
|
268
|
+
var init_popup = __esm({
|
|
269
|
+
"src/auth/popup.ts"() {
|
|
270
|
+
"use strict";
|
|
271
|
+
MCP_AUTH_BROADCAST_CHANNEL = "mcp_auth_callback";
|
|
272
|
+
MCP_AUTH_CALLBACK_MESSAGE_TYPE = "mcp_auth_callback";
|
|
273
|
+
}
|
|
274
|
+
});
|
|
275
|
+
|
|
276
|
+
// src/auth/flow.ts
|
|
277
|
+
import {
|
|
278
|
+
auth,
|
|
279
|
+
InsufficientScopeError,
|
|
280
|
+
UnauthorizedError
|
|
281
|
+
} from "@modelcontextprotocol/client";
|
|
282
|
+
function isUnauthorized(err, depth = 0) {
|
|
283
|
+
if (!err || depth > 5) return false;
|
|
284
|
+
if (err instanceof UnauthorizedError) return true;
|
|
285
|
+
if (err instanceof Error) {
|
|
286
|
+
const code = err.code;
|
|
287
|
+
if (code === 401) return true;
|
|
288
|
+
if (err.name === "UnauthorizedError") return true;
|
|
289
|
+
const message = err.message ?? "";
|
|
290
|
+
if (message.includes("401") || message.includes("Unauthorized")) {
|
|
291
|
+
return true;
|
|
292
|
+
}
|
|
293
|
+
if (err.cause && isUnauthorized(err.cause, depth + 1)) return true;
|
|
294
|
+
const data = err.data;
|
|
295
|
+
if (data?.cause && isUnauthorized(data.cause, depth + 1)) return true;
|
|
296
|
+
}
|
|
297
|
+
return false;
|
|
298
|
+
}
|
|
299
|
+
function isOAuthInteractionRequired(err, depth = 0) {
|
|
300
|
+
if (!err || depth > 5) return false;
|
|
301
|
+
if (err instanceof InsufficientScopeError || err instanceof UnauthorizedError) {
|
|
302
|
+
return true;
|
|
303
|
+
}
|
|
304
|
+
if (err instanceof Error) {
|
|
305
|
+
if (err.name === "InsufficientScopeError" || err.name === "UnauthorizedError") {
|
|
306
|
+
return true;
|
|
307
|
+
}
|
|
308
|
+
if (err.cause && isOAuthInteractionRequired(err.cause, depth + 1)) {
|
|
309
|
+
return true;
|
|
310
|
+
}
|
|
311
|
+
const data = err.data;
|
|
312
|
+
if (data?.cause && isOAuthInteractionRequired(data.cause, depth + 1)) {
|
|
313
|
+
return true;
|
|
314
|
+
}
|
|
315
|
+
}
|
|
316
|
+
return false;
|
|
317
|
+
}
|
|
318
|
+
async function completeOAuthFlow(provider, serverUrl, options = {}) {
|
|
319
|
+
const flowProvider = provider;
|
|
320
|
+
const timeoutMs = options.timeoutMs ?? DEFAULT_AUTH_TIMEOUT_MS;
|
|
321
|
+
const fetchFn = options.fetchFn ?? flowProvider.getProxyFetch?.() ?? void 0;
|
|
322
|
+
if (!flowProvider.hasPendingFlow) {
|
|
323
|
+
const result = await auth(provider, { serverUrl, fetchFn });
|
|
324
|
+
if (result === "AUTHORIZED") return;
|
|
325
|
+
if (result !== "REDIRECT") {
|
|
326
|
+
throw new Error(`Unexpected OAuth auth() result: ${result}`);
|
|
327
|
+
}
|
|
328
|
+
}
|
|
329
|
+
if (flowProvider.preventAutoAuth === true && typeof flowProvider.startAuthorization === "function") {
|
|
330
|
+
flowProvider.startAuthorization();
|
|
331
|
+
}
|
|
332
|
+
if (typeof flowProvider.getAuthorizationResponse === "function" || typeof flowProvider.getAuthorizationCode === "function") {
|
|
333
|
+
const response = typeof flowProvider.getAuthorizationResponse === "function" ? await flowProvider.getAuthorizationResponse() : { code: await flowProvider.getAuthorizationCode() };
|
|
334
|
+
if (options.finishAuthorization) {
|
|
335
|
+
await options.finishAuthorization(response.code, response.iss);
|
|
336
|
+
} else {
|
|
337
|
+
await auth(provider, {
|
|
338
|
+
serverUrl,
|
|
339
|
+
authorizationCode: response.code,
|
|
340
|
+
...response.iss !== void 0 ? { iss: response.iss } : {},
|
|
341
|
+
fetchFn
|
|
342
|
+
});
|
|
343
|
+
}
|
|
344
|
+
return;
|
|
345
|
+
}
|
|
346
|
+
await waitForBrowserAuthComplete(flowProvider, timeoutMs);
|
|
347
|
+
}
|
|
348
|
+
async function waitForBrowserAuthComplete(provider, timeoutMs) {
|
|
349
|
+
if (typeof window === "undefined") {
|
|
350
|
+
throw new Error(
|
|
351
|
+
"OAuth redirect requires a browser environment or a provider with getAuthorizationCode()"
|
|
352
|
+
);
|
|
353
|
+
}
|
|
354
|
+
if (provider.useRedirectFlow) {
|
|
355
|
+
await new Promise(() => {
|
|
356
|
+
});
|
|
357
|
+
return;
|
|
358
|
+
}
|
|
359
|
+
const tokensKey = provider.getKey?.("tokens");
|
|
360
|
+
if (!tokensKey) {
|
|
361
|
+
throw new Error(
|
|
362
|
+
"Browser OAuth provider must expose getKey() for token storage"
|
|
363
|
+
);
|
|
364
|
+
}
|
|
365
|
+
let state = null;
|
|
366
|
+
const authUrl = provider.getLastAttemptedAuthUrl?.();
|
|
367
|
+
if (authUrl) {
|
|
368
|
+
try {
|
|
369
|
+
state = new URL(authUrl).searchParams.get("state");
|
|
370
|
+
} catch {
|
|
371
|
+
}
|
|
372
|
+
}
|
|
373
|
+
try {
|
|
374
|
+
const result = await runAuthPopup({
|
|
375
|
+
popup: null,
|
|
376
|
+
state,
|
|
377
|
+
tokensKey,
|
|
378
|
+
timeoutMs
|
|
379
|
+
});
|
|
380
|
+
switch (result.kind) {
|
|
381
|
+
case "success":
|
|
382
|
+
return;
|
|
383
|
+
case "cancelled":
|
|
384
|
+
throw new Error("OAuth authentication was cancelled.");
|
|
385
|
+
case "timeout":
|
|
386
|
+
throw new Error(
|
|
387
|
+
`OAuth callback not received within ${timeoutMs}ms. Ensure /oauth/callback calls onMcpAuthorization().`
|
|
388
|
+
);
|
|
389
|
+
case "error":
|
|
390
|
+
throw new Error(result.error);
|
|
391
|
+
default:
|
|
392
|
+
throw new Error("Unexpected OAuth popup result");
|
|
393
|
+
}
|
|
394
|
+
} finally {
|
|
395
|
+
provider.markFlowComplete?.();
|
|
396
|
+
}
|
|
397
|
+
}
|
|
398
|
+
var DEFAULT_AUTH_TIMEOUT_MS;
|
|
399
|
+
var init_flow = __esm({
|
|
400
|
+
"src/auth/flow.ts"() {
|
|
401
|
+
"use strict";
|
|
402
|
+
init_popup();
|
|
403
|
+
DEFAULT_AUTH_TIMEOUT_MS = 5 * 6e4;
|
|
404
|
+
}
|
|
405
|
+
});
|
|
406
|
+
|
|
145
407
|
// src/utils/json-schema-validator.ts
|
|
146
408
|
import {
|
|
147
409
|
CfWorkerJsonSchemaValidator
|
|
@@ -190,6 +452,7 @@ var init_base = __esm({
|
|
|
190
452
|
"src/transport/base.ts"() {
|
|
191
453
|
"use strict";
|
|
192
454
|
init_logging();
|
|
455
|
+
init_flow();
|
|
193
456
|
init_connector_telemetry();
|
|
194
457
|
passthroughResultSchema = {
|
|
195
458
|
"~standard": {
|
|
@@ -204,6 +467,7 @@ var init_base = __esm({
|
|
|
204
467
|
toolsCache = null;
|
|
205
468
|
capabilitiesCache = null;
|
|
206
469
|
serverInfoCache = null;
|
|
470
|
+
authorizationCache;
|
|
207
471
|
connected = false;
|
|
208
472
|
opts;
|
|
209
473
|
notificationHandlers = [];
|
|
@@ -467,6 +731,21 @@ var init_base = __esm({
|
|
|
467
731
|
"setupElicitationHandler: Elicitation handler registered successfully"
|
|
468
732
|
);
|
|
469
733
|
}
|
|
734
|
+
/**
|
|
735
|
+
* Run one logical MCP operation. HTTP connectors override this host seam to
|
|
736
|
+
* finish an SDK-started interactive OAuth flow and retry exactly once.
|
|
737
|
+
*/
|
|
738
|
+
async executeRequest(operation) {
|
|
739
|
+
return operation();
|
|
740
|
+
}
|
|
741
|
+
/** OAuth state discovered for the active connection, when available. */
|
|
742
|
+
get authorization() {
|
|
743
|
+
return this.authorizationCache;
|
|
744
|
+
}
|
|
745
|
+
/** Start optional OAuth for a connected mixed-auth server. */
|
|
746
|
+
async authenticate() {
|
|
747
|
+
throw new Error("This connector does not support interactive OAuth");
|
|
748
|
+
}
|
|
470
749
|
/**
|
|
471
750
|
* Disconnects the SDK client and releases transport resources.
|
|
472
751
|
*
|
|
@@ -514,13 +793,13 @@ var init_base = __esm({
|
|
|
514
793
|
icons: serverInfo.icons
|
|
515
794
|
} : null;
|
|
516
795
|
try {
|
|
517
|
-
const listToolsRes = await this.
|
|
518
|
-
void 0,
|
|
519
|
-
defaultRequestOptions
|
|
796
|
+
const listToolsRes = await this.executeRequest(
|
|
797
|
+
() => this.client.listTools(void 0, defaultRequestOptions)
|
|
520
798
|
);
|
|
521
799
|
this.toolsCache = listToolsRes.tools ?? [];
|
|
522
800
|
logger.debug(`Fetched ${this.toolsCache.length} tools from server`);
|
|
523
801
|
} catch (err) {
|
|
802
|
+
if (isOAuthInteractionRequired(err)) throw err;
|
|
524
803
|
const error = err;
|
|
525
804
|
if (error.code === -32601) {
|
|
526
805
|
logger.debug("Server does not implement tools/list, assuming no tools");
|
|
@@ -594,9 +873,8 @@ var init_base = __esm({
|
|
|
594
873
|
const progressHandler = enhancedOptions?.onprogress;
|
|
595
874
|
if (progressHandler) this.activeProgressHandlers.add(progressHandler);
|
|
596
875
|
try {
|
|
597
|
-
const res = await this.
|
|
598
|
-
{ name, arguments: args },
|
|
599
|
-
enhancedOptions
|
|
876
|
+
const res = await this.executeRequest(
|
|
877
|
+
() => this.client.callTool({ name, arguments: args }, enhancedOptions)
|
|
600
878
|
);
|
|
601
879
|
logger.debug(`Tool '${name}' returned`, res);
|
|
602
880
|
return res;
|
|
@@ -616,7 +894,9 @@ var init_base = __esm({
|
|
|
616
894
|
throw new Error("MCP client is not connected");
|
|
617
895
|
}
|
|
618
896
|
logger.debug("[listTools] Fetching fresh tools from server...");
|
|
619
|
-
const result = await this.
|
|
897
|
+
const result = await this.executeRequest(
|
|
898
|
+
() => this.client.listTools(void 0, options)
|
|
899
|
+
);
|
|
620
900
|
const tools = result.tools ? [...result.tools] : [];
|
|
621
901
|
logger.debug(
|
|
622
902
|
`[listTools] Returned ${tools.length} tools:`,
|
|
@@ -636,7 +916,9 @@ var init_base = __esm({
|
|
|
636
916
|
throw new Error("MCP client is not connected");
|
|
637
917
|
}
|
|
638
918
|
logger.debug("Listing resources", cursor ? `with cursor: ${cursor}` : "");
|
|
639
|
-
return await this.
|
|
919
|
+
return await this.executeRequest(
|
|
920
|
+
() => this.client.listResources({ cursor }, options)
|
|
921
|
+
);
|
|
640
922
|
}
|
|
641
923
|
/**
|
|
642
924
|
* List all resources from the server, automatically handling pagination
|
|
@@ -654,14 +936,16 @@ var init_base = __esm({
|
|
|
654
936
|
}
|
|
655
937
|
try {
|
|
656
938
|
logger.debug("Listing all resources (with auto-pagination)");
|
|
657
|
-
|
|
658
|
-
|
|
659
|
-
|
|
660
|
-
|
|
661
|
-
|
|
662
|
-
|
|
663
|
-
|
|
664
|
-
|
|
939
|
+
return await this.executeRequest(async () => {
|
|
940
|
+
const allResources = [];
|
|
941
|
+
let cursor = void 0;
|
|
942
|
+
do {
|
|
943
|
+
const result = await this.client.listResources({ cursor }, options);
|
|
944
|
+
allResources.push(...result.resources || []);
|
|
945
|
+
cursor = result.nextCursor;
|
|
946
|
+
} while (cursor);
|
|
947
|
+
return { resources: allResources };
|
|
948
|
+
});
|
|
665
949
|
} catch (err) {
|
|
666
950
|
const error = err;
|
|
667
951
|
if (error.code === -32601) {
|
|
@@ -682,7 +966,9 @@ var init_base = __esm({
|
|
|
682
966
|
throw new Error("MCP client is not connected");
|
|
683
967
|
}
|
|
684
968
|
logger.debug("Listing resource templates");
|
|
685
|
-
return await this.
|
|
969
|
+
return await this.executeRequest(
|
|
970
|
+
() => this.client.listResourceTemplates(void 0, options)
|
|
971
|
+
);
|
|
686
972
|
}
|
|
687
973
|
/**
|
|
688
974
|
* Request completion suggestions for a prompt or resource template argument
|
|
@@ -696,7 +982,9 @@ var init_base = __esm({
|
|
|
696
982
|
throw new Error("MCP client is not connected");
|
|
697
983
|
}
|
|
698
984
|
logger.debug("[complete] Requesting completions for:", params.ref);
|
|
699
|
-
const result = await this.
|
|
985
|
+
const result = await this.executeRequest(
|
|
986
|
+
() => this.client.complete(params, options)
|
|
987
|
+
);
|
|
700
988
|
logger.debug(
|
|
701
989
|
`[complete] Received ${result.completion.values.length} suggestions`
|
|
702
990
|
);
|
|
@@ -714,7 +1002,9 @@ var init_base = __esm({
|
|
|
714
1002
|
throw new Error("MCP client is not connected");
|
|
715
1003
|
}
|
|
716
1004
|
logger.debug(`Reading resource ${uri}`);
|
|
717
|
-
const res = await this.
|
|
1005
|
+
const res = await this.executeRequest(
|
|
1006
|
+
() => this.client.readResource({ uri }, options)
|
|
1007
|
+
);
|
|
718
1008
|
return res;
|
|
719
1009
|
}
|
|
720
1010
|
/**
|
|
@@ -728,7 +1018,9 @@ var init_base = __esm({
|
|
|
728
1018
|
throw new Error("MCP client is not connected");
|
|
729
1019
|
}
|
|
730
1020
|
logger.debug(`Subscribing to resource: ${uri}`);
|
|
731
|
-
return await this.
|
|
1021
|
+
return await this.executeRequest(
|
|
1022
|
+
() => this.client.subscribeResource({ uri }, options)
|
|
1023
|
+
);
|
|
732
1024
|
}
|
|
733
1025
|
/**
|
|
734
1026
|
* Unsubscribe from resource updates
|
|
@@ -741,7 +1033,9 @@ var init_base = __esm({
|
|
|
741
1033
|
throw new Error("MCP client is not connected");
|
|
742
1034
|
}
|
|
743
1035
|
logger.debug(`Unsubscribing from resource: ${uri}`);
|
|
744
|
-
return await this.
|
|
1036
|
+
return await this.executeRequest(
|
|
1037
|
+
() => this.client.unsubscribeResource({ uri }, options)
|
|
1038
|
+
);
|
|
745
1039
|
}
|
|
746
1040
|
/**
|
|
747
1041
|
* Lists prompts exposed by the server.
|
|
@@ -758,7 +1052,7 @@ var init_base = __esm({
|
|
|
758
1052
|
}
|
|
759
1053
|
try {
|
|
760
1054
|
logger.debug("Listing prompts");
|
|
761
|
-
return await this.client.listPrompts();
|
|
1055
|
+
return await this.executeRequest(() => this.client.listPrompts());
|
|
762
1056
|
} catch (err) {
|
|
763
1057
|
const error = err;
|
|
764
1058
|
if (error.code === -32601) {
|
|
@@ -780,7 +1074,9 @@ var init_base = __esm({
|
|
|
780
1074
|
throw new Error("MCP client is not connected");
|
|
781
1075
|
}
|
|
782
1076
|
logger.debug(`Getting prompt ${name}`);
|
|
783
|
-
return await this.
|
|
1077
|
+
return await this.executeRequest(
|
|
1078
|
+
() => this.client.getPrompt({ name, arguments: args })
|
|
1079
|
+
);
|
|
784
1080
|
}
|
|
785
1081
|
/**
|
|
786
1082
|
* Sends a raw, potentially non-standard request through the SDK client.
|
|
@@ -795,10 +1091,12 @@ var init_base = __esm({
|
|
|
795
1091
|
throw new Error("MCP client is not connected");
|
|
796
1092
|
}
|
|
797
1093
|
logger.debug(`Sending raw request '${method}' with params`, params);
|
|
798
|
-
return await this.
|
|
799
|
-
|
|
800
|
-
|
|
801
|
-
|
|
1094
|
+
return await this.executeRequest(
|
|
1095
|
+
() => this.client.request(
|
|
1096
|
+
{ method, params: params ?? {} },
|
|
1097
|
+
passthroughResultSchema,
|
|
1098
|
+
options
|
|
1099
|
+
)
|
|
802
1100
|
);
|
|
803
1101
|
}
|
|
804
1102
|
/**
|
|
@@ -831,6 +1129,7 @@ var init_base = __esm({
|
|
|
831
1129
|
}
|
|
832
1130
|
}
|
|
833
1131
|
this.toolsCache = null;
|
|
1132
|
+
this.authorizationCache = void 0;
|
|
834
1133
|
if (issues.length) {
|
|
835
1134
|
logger.warn(`Resource cleanup finished with ${issues.length} issue(s)`);
|
|
836
1135
|
}
|
|
@@ -1219,7 +1518,7 @@ init_connector_telemetry();
|
|
|
1219
1518
|
init_logging();
|
|
1220
1519
|
|
|
1221
1520
|
// src/utils/version.ts
|
|
1222
|
-
var VERSION = "2.1.0";
|
|
1521
|
+
var VERSION = "2.1.1-canary.0";
|
|
1223
1522
|
function getPackageVersion() {
|
|
1224
1523
|
return VERSION;
|
|
1225
1524
|
}
|
|
@@ -1617,397 +1916,174 @@ var Telemetry = class _Telemetry {
|
|
|
1617
1916
|
};
|
|
1618
1917
|
const p = capturePostHog({
|
|
1619
1918
|
host: HOST,
|
|
1620
|
-
apiKey: PROJECT_API_KEY,
|
|
1621
|
-
event: event.name,
|
|
1622
|
-
distinctId: currentUserId,
|
|
1623
|
-
properties
|
|
1624
|
-
});
|
|
1625
|
-
this._pending.add(p);
|
|
1626
|
-
void p.finally(() => this._pending.delete(p));
|
|
1627
|
-
}
|
|
1628
|
-
async trackAgentExecution(data) {
|
|
1629
|
-
if (!this.isEnabled) return;
|
|
1630
|
-
await this.capture(new MCPAgentExecutionEvent(data));
|
|
1631
|
-
}
|
|
1632
|
-
async trackMCPClientInit(data) {
|
|
1633
|
-
if (!this.isEnabled) return;
|
|
1634
|
-
await this.capture(new MCPClientInitEvent(data));
|
|
1635
|
-
}
|
|
1636
|
-
async trackConnectorInit(data) {
|
|
1637
|
-
if (!this.isEnabled) return;
|
|
1638
|
-
await this.capture(new ConnectorInitEvent(data));
|
|
1639
|
-
}
|
|
1640
|
-
async trackClientAddServer(serverName, serverConfig) {
|
|
1641
|
-
if (!this.isEnabled) return;
|
|
1642
|
-
await this.capture(new ClientAddServerEvent({ serverName, serverConfig }));
|
|
1643
|
-
}
|
|
1644
|
-
async trackClientRemoveServer(serverName) {
|
|
1645
|
-
if (!this.isEnabled) return;
|
|
1646
|
-
await this.capture(new ClientRemoveServerEvent({ serverName }));
|
|
1647
|
-
}
|
|
1648
|
-
async trackUseMcpConnection(data) {
|
|
1649
|
-
if (!this.isEnabled) return;
|
|
1650
|
-
await this.capture({
|
|
1651
|
-
name: "usemcp_connection",
|
|
1652
|
-
properties: {
|
|
1653
|
-
url_domain: new URL(data.url).hostname,
|
|
1654
|
-
transport_type: data.transportType,
|
|
1655
|
-
success: data.success,
|
|
1656
|
-
error_type: data.errorType ?? null,
|
|
1657
|
-
connection_time_ms: data.connectionTimeMs ?? null,
|
|
1658
|
-
has_oauth: data.hasOAuth,
|
|
1659
|
-
has_sampling: data.hasSampling,
|
|
1660
|
-
has_elicitation: data.hasElicitation
|
|
1661
|
-
}
|
|
1662
|
-
});
|
|
1663
|
-
}
|
|
1664
|
-
async trackUseMcpToolCall(data) {
|
|
1665
|
-
if (!this.isEnabled) return;
|
|
1666
|
-
await this.capture({
|
|
1667
|
-
name: "usemcp_tool_call",
|
|
1668
|
-
properties: {
|
|
1669
|
-
tool_name: data.toolName,
|
|
1670
|
-
success: data.success,
|
|
1671
|
-
error_type: data.errorType ?? null,
|
|
1672
|
-
execution_time_ms: data.executionTimeMs ?? null
|
|
1673
|
-
}
|
|
1674
|
-
});
|
|
1675
|
-
}
|
|
1676
|
-
async trackUseMcpResourceRead(data) {
|
|
1677
|
-
if (!this.isEnabled) return;
|
|
1678
|
-
await this.capture({
|
|
1679
|
-
name: "usemcp_resource_read",
|
|
1680
|
-
properties: {
|
|
1681
|
-
resource_uri_scheme: data.resourceUri.split(":")[0],
|
|
1682
|
-
success: data.success,
|
|
1683
|
-
error_type: data.errorType ?? null
|
|
1684
|
-
}
|
|
1685
|
-
});
|
|
1686
|
-
}
|
|
1687
|
-
identify(userId, properties) {
|
|
1688
|
-
this._currUserId = userId;
|
|
1689
|
-
this._storage?.setUserId(userId);
|
|
1690
|
-
if (this._telemetryEnabled) {
|
|
1691
|
-
void capturePostHog({
|
|
1692
|
-
host: HOST,
|
|
1693
|
-
apiKey: PROJECT_API_KEY,
|
|
1694
|
-
event: "$identify",
|
|
1695
|
-
distinctId: userId,
|
|
1696
|
-
properties: { $set: properties ?? {} }
|
|
1697
|
-
});
|
|
1698
|
-
}
|
|
1699
|
-
}
|
|
1700
|
-
reset() {
|
|
1701
|
-
this._currUserId = null;
|
|
1702
|
-
}
|
|
1703
|
-
flush() {
|
|
1704
|
-
void Promise.allSettled([...this._pending]);
|
|
1705
|
-
}
|
|
1706
|
-
async shutdown() {
|
|
1707
|
-
try {
|
|
1708
|
-
await Promise.allSettled([...this._pending]);
|
|
1709
|
-
logger.debug("Telemetry fetch captures flushed");
|
|
1710
|
-
} catch (e) {
|
|
1711
|
-
logger.debug(`Error flushing telemetry captures: ${e}`);
|
|
1712
|
-
}
|
|
1713
|
-
}
|
|
1714
|
-
};
|
|
1715
|
-
var Tel = Telemetry;
|
|
1716
|
-
function setTelemetrySource(source) {
|
|
1717
|
-
Tel.getInstance().setSource(source);
|
|
1718
|
-
}
|
|
1719
|
-
function setProductVersion(version) {
|
|
1720
|
-
Tel.getInstance().setProductVersion(version);
|
|
1721
|
-
}
|
|
1722
|
-
|
|
1723
|
-
// src/telemetry/telemetry-node.ts
|
|
1724
|
-
function getCacheHome(os, path2) {
|
|
1725
|
-
const envVar = process.env.XDG_CACHE_HOME;
|
|
1726
|
-
if (envVar && path2.isAbsolute(envVar)) {
|
|
1727
|
-
return envVar;
|
|
1728
|
-
}
|
|
1729
|
-
const homeDir = os.homedir();
|
|
1730
|
-
if (process.platform === "win32") {
|
|
1731
|
-
const appdata = process.env.LOCALAPPDATA || process.env.APPDATA;
|
|
1732
|
-
if (appdata) return appdata;
|
|
1733
|
-
return path2.join(homeDir, "AppData", "Local");
|
|
1734
|
-
}
|
|
1735
|
-
if (process.platform === "darwin") {
|
|
1736
|
-
return path2.join(homeDir, "Library", "Caches");
|
|
1737
|
-
}
|
|
1738
|
-
return path2.join(homeDir, ".cache");
|
|
1739
|
-
}
|
|
1740
|
-
function createFsStorage() {
|
|
1741
|
-
let fs2;
|
|
1742
|
-
let os;
|
|
1743
|
-
let path2;
|
|
1744
|
-
try {
|
|
1745
|
-
fs2 = __require("fs");
|
|
1746
|
-
os = __require("os");
|
|
1747
|
-
path2 = __require("path");
|
|
1748
|
-
} catch {
|
|
1749
|
-
return {
|
|
1750
|
-
getUserId: () => null,
|
|
1751
|
-
setUserId: () => void 0
|
|
1752
|
-
};
|
|
1753
|
-
}
|
|
1754
|
-
const cacheHome = getCacheHome(os, path2);
|
|
1755
|
-
const userIdPath = path2.join(cacheHome, "mcp_use_3", "telemetry_user_id");
|
|
1756
|
-
return {
|
|
1757
|
-
getUserId() {
|
|
1758
|
-
try {
|
|
1759
|
-
if (!fs2.existsSync(userIdPath)) return null;
|
|
1760
|
-
return fs2.readFileSync(userIdPath, "utf-8").trim() || null;
|
|
1761
|
-
} catch {
|
|
1762
|
-
return null;
|
|
1763
|
-
}
|
|
1764
|
-
},
|
|
1765
|
-
setUserId(id) {
|
|
1766
|
-
try {
|
|
1767
|
-
fs2.mkdirSync(path2.dirname(userIdPath), { recursive: true });
|
|
1768
|
-
fs2.writeFileSync(userIdPath, id);
|
|
1769
|
-
} catch {
|
|
1770
|
-
}
|
|
1771
|
-
}
|
|
1772
|
-
};
|
|
1773
|
-
}
|
|
1774
|
-
configureTelemetryStorage(createFsStorage());
|
|
1775
|
-
|
|
1776
|
-
// src/telemetry/configure-node.ts
|
|
1777
|
-
setClientTelemetryTracker({
|
|
1778
|
-
addServer: (name, config) => Telemetry.getInstance().trackClientAddServer(name, config).catch(() => void 0),
|
|
1779
|
-
removeServer: (name) => Telemetry.getInstance().trackClientRemoveServer(name).catch(() => void 0)
|
|
1780
|
-
});
|
|
1781
|
-
setConnectorTelemetryTracker(
|
|
1782
|
-
(data) => Telemetry.getInstance().trackConnectorInit(data).catch(() => void 0)
|
|
1783
|
-
);
|
|
1784
|
-
|
|
1785
|
-
// src/index.ts
|
|
1786
|
-
import { auth as auth2, UnauthorizedError as UnauthorizedError3 } from "@modelcontextprotocol/client";
|
|
1787
|
-
|
|
1788
|
-
// src/auth/flow.ts
|
|
1789
|
-
import {
|
|
1790
|
-
auth,
|
|
1791
|
-
UnauthorizedError
|
|
1792
|
-
} from "@modelcontextprotocol/client";
|
|
1793
|
-
|
|
1794
|
-
// src/auth/popup.ts
|
|
1795
|
-
var MCP_AUTH_BROADCAST_CHANNEL = "mcp_auth_callback";
|
|
1796
|
-
var MCP_AUTH_CALLBACK_MESSAGE_TYPE = "mcp_auth_callback";
|
|
1797
|
-
function hasStoredTokens(tokensKey) {
|
|
1798
|
-
try {
|
|
1799
|
-
return typeof localStorage !== "undefined" && !!localStorage.getItem(tokensKey);
|
|
1800
|
-
} catch {
|
|
1801
|
-
return false;
|
|
1802
|
-
}
|
|
1803
|
-
}
|
|
1804
|
-
function runAuthPopup({
|
|
1805
|
-
popup,
|
|
1806
|
-
state,
|
|
1807
|
-
tokensKey,
|
|
1808
|
-
timeoutMs = 5 * 6e4,
|
|
1809
|
-
closePollMs = 1e3,
|
|
1810
|
-
closeGraceMs = 2e4,
|
|
1811
|
-
expectedOrigin = typeof window !== "undefined" ? window.location.origin : ""
|
|
1812
|
-
}) {
|
|
1813
|
-
return new Promise((resolve) => {
|
|
1814
|
-
let settled = false;
|
|
1815
|
-
let closeTimer = null;
|
|
1816
|
-
let timeoutTimer = null;
|
|
1817
|
-
let graceTimer = null;
|
|
1818
|
-
let broadcastChannel = null;
|
|
1819
|
-
const cleanup = () => {
|
|
1820
|
-
if (closeTimer) {
|
|
1821
|
-
clearInterval(closeTimer);
|
|
1822
|
-
closeTimer = null;
|
|
1823
|
-
}
|
|
1824
|
-
if (timeoutTimer) {
|
|
1825
|
-
clearTimeout(timeoutTimer);
|
|
1826
|
-
timeoutTimer = null;
|
|
1827
|
-
}
|
|
1828
|
-
if (graceTimer) {
|
|
1829
|
-
clearTimeout(graceTimer);
|
|
1830
|
-
graceTimer = null;
|
|
1831
|
-
}
|
|
1832
|
-
if (typeof window !== "undefined") {
|
|
1833
|
-
window.removeEventListener("message", messageHandler);
|
|
1834
|
-
window.removeEventListener("storage", storageHandler);
|
|
1835
|
-
}
|
|
1836
|
-
if (broadcastChannel) {
|
|
1837
|
-
try {
|
|
1838
|
-
broadcastChannel.removeEventListener("message", broadcastHandler);
|
|
1839
|
-
broadcastChannel.close();
|
|
1840
|
-
} catch {
|
|
1841
|
-
}
|
|
1842
|
-
broadcastChannel = null;
|
|
1843
|
-
}
|
|
1844
|
-
};
|
|
1845
|
-
const settle = (result) => {
|
|
1846
|
-
if (settled) return;
|
|
1847
|
-
settled = true;
|
|
1848
|
-
cleanup();
|
|
1849
|
-
resolve(result);
|
|
1850
|
-
};
|
|
1851
|
-
const handlePayload = (payload) => {
|
|
1852
|
-
if (!payload || payload.type !== MCP_AUTH_CALLBACK_MESSAGE_TYPE) return;
|
|
1853
|
-
if (payload.state && state && payload.state !== state) return;
|
|
1854
|
-
if (payload.success) {
|
|
1855
|
-
settle({ kind: "success" });
|
|
1856
|
-
} else {
|
|
1857
|
-
settle({
|
|
1858
|
-
kind: "error",
|
|
1859
|
-
error: payload.error ?? "Authentication failed in callback."
|
|
1860
|
-
});
|
|
1861
|
-
}
|
|
1862
|
-
};
|
|
1863
|
-
const messageHandler = (event) => {
|
|
1864
|
-
if (expectedOrigin && event.origin !== expectedOrigin) return;
|
|
1865
|
-
handlePayload(event.data);
|
|
1866
|
-
};
|
|
1867
|
-
const broadcastHandler = (event) => {
|
|
1868
|
-
handlePayload(event.data);
|
|
1869
|
-
};
|
|
1870
|
-
const storageHandler = (event) => {
|
|
1871
|
-
if (event.key !== tokensKey) return;
|
|
1872
|
-
if (event.newValue) settle({ kind: "success" });
|
|
1873
|
-
};
|
|
1874
|
-
if (typeof window !== "undefined") {
|
|
1875
|
-
window.addEventListener("message", messageHandler);
|
|
1876
|
-
window.addEventListener("storage", storageHandler);
|
|
1877
|
-
}
|
|
1878
|
-
if (typeof BroadcastChannel !== "undefined") {
|
|
1879
|
-
try {
|
|
1880
|
-
broadcastChannel = new BroadcastChannel(MCP_AUTH_BROADCAST_CHANNEL);
|
|
1881
|
-
broadcastChannel.addEventListener("message", broadcastHandler);
|
|
1882
|
-
} catch {
|
|
1883
|
-
broadcastChannel = null;
|
|
1884
|
-
}
|
|
1885
|
-
}
|
|
1886
|
-
if (popup) {
|
|
1887
|
-
closeTimer = setInterval(() => {
|
|
1888
|
-
if (settled) return;
|
|
1889
|
-
let closed = false;
|
|
1890
|
-
try {
|
|
1891
|
-
closed = popup.closed;
|
|
1892
|
-
} catch {
|
|
1893
|
-
closed = false;
|
|
1894
|
-
}
|
|
1895
|
-
if (!closed) return;
|
|
1896
|
-
if (closeTimer) {
|
|
1897
|
-
clearInterval(closeTimer);
|
|
1898
|
-
closeTimer = null;
|
|
1899
|
-
}
|
|
1900
|
-
if (hasStoredTokens(tokensKey)) {
|
|
1901
|
-
settle({ kind: "success" });
|
|
1902
|
-
return;
|
|
1903
|
-
}
|
|
1904
|
-
graceTimer = setTimeout(() => {
|
|
1905
|
-
settle(
|
|
1906
|
-
hasStoredTokens(tokensKey) ? { kind: "success" } : { kind: "cancelled" }
|
|
1907
|
-
);
|
|
1908
|
-
}, closeGraceMs);
|
|
1909
|
-
}, closePollMs);
|
|
1910
|
-
}
|
|
1911
|
-
timeoutTimer = setTimeout(() => {
|
|
1912
|
-
settle(
|
|
1913
|
-
hasStoredTokens(tokensKey) ? { kind: "success" } : { kind: "timeout" }
|
|
1914
|
-
);
|
|
1915
|
-
}, timeoutMs);
|
|
1916
|
-
});
|
|
1917
|
-
}
|
|
1918
|
-
|
|
1919
|
-
// src/auth/flow.ts
|
|
1920
|
-
var DEFAULT_AUTH_TIMEOUT_MS = 5 * 6e4;
|
|
1921
|
-
function isUnauthorized(err, depth = 0) {
|
|
1922
|
-
if (!err || depth > 5) return false;
|
|
1923
|
-
if (err instanceof UnauthorizedError) return true;
|
|
1924
|
-
if (err instanceof Error) {
|
|
1925
|
-
const code = err.code;
|
|
1926
|
-
if (code === 401) return true;
|
|
1927
|
-
if (err.name === "UnauthorizedError") return true;
|
|
1928
|
-
const message = err.message ?? "";
|
|
1929
|
-
if (message.includes("401") || message.includes("Unauthorized")) {
|
|
1930
|
-
return true;
|
|
1931
|
-
}
|
|
1932
|
-
if (err.cause && isUnauthorized(err.cause, depth + 1)) return true;
|
|
1933
|
-
const data = err.data;
|
|
1934
|
-
if (data?.cause && isUnauthorized(data.cause, depth + 1)) return true;
|
|
1919
|
+
apiKey: PROJECT_API_KEY,
|
|
1920
|
+
event: event.name,
|
|
1921
|
+
distinctId: currentUserId,
|
|
1922
|
+
properties
|
|
1923
|
+
});
|
|
1924
|
+
this._pending.add(p);
|
|
1925
|
+
void p.finally(() => this._pending.delete(p));
|
|
1935
1926
|
}
|
|
1936
|
-
|
|
1937
|
-
|
|
1938
|
-
|
|
1939
|
-
const flowProvider = provider;
|
|
1940
|
-
const timeoutMs = options.timeoutMs ?? DEFAULT_AUTH_TIMEOUT_MS;
|
|
1941
|
-
const fetchFn = options.fetchFn ?? flowProvider.getProxyFetch?.() ?? void 0;
|
|
1942
|
-
if (!flowProvider.hasPendingFlow) {
|
|
1943
|
-
const result = await auth(provider, { serverUrl, fetchFn });
|
|
1944
|
-
if (result === "AUTHORIZED") return;
|
|
1945
|
-
if (result !== "REDIRECT") {
|
|
1946
|
-
throw new Error(`Unexpected OAuth auth() result: ${result}`);
|
|
1947
|
-
}
|
|
1927
|
+
async trackAgentExecution(data) {
|
|
1928
|
+
if (!this.isEnabled) return;
|
|
1929
|
+
await this.capture(new MCPAgentExecutionEvent(data));
|
|
1948
1930
|
}
|
|
1949
|
-
|
|
1950
|
-
|
|
1951
|
-
await
|
|
1952
|
-
|
|
1953
|
-
|
|
1954
|
-
|
|
1955
|
-
|
|
1931
|
+
async trackMCPClientInit(data) {
|
|
1932
|
+
if (!this.isEnabled) return;
|
|
1933
|
+
await this.capture(new MCPClientInitEvent(data));
|
|
1934
|
+
}
|
|
1935
|
+
async trackConnectorInit(data) {
|
|
1936
|
+
if (!this.isEnabled) return;
|
|
1937
|
+
await this.capture(new ConnectorInitEvent(data));
|
|
1938
|
+
}
|
|
1939
|
+
async trackClientAddServer(serverName, serverConfig) {
|
|
1940
|
+
if (!this.isEnabled) return;
|
|
1941
|
+
await this.capture(new ClientAddServerEvent({ serverName, serverConfig }));
|
|
1942
|
+
}
|
|
1943
|
+
async trackClientRemoveServer(serverName) {
|
|
1944
|
+
if (!this.isEnabled) return;
|
|
1945
|
+
await this.capture(new ClientRemoveServerEvent({ serverName }));
|
|
1946
|
+
}
|
|
1947
|
+
async trackUseMcpConnection(data) {
|
|
1948
|
+
if (!this.isEnabled) return;
|
|
1949
|
+
await this.capture({
|
|
1950
|
+
name: "usemcp_connection",
|
|
1951
|
+
properties: {
|
|
1952
|
+
url_domain: new URL(data.url).hostname,
|
|
1953
|
+
transport_type: data.transportType,
|
|
1954
|
+
success: data.success,
|
|
1955
|
+
error_type: data.errorType ?? null,
|
|
1956
|
+
connection_time_ms: data.connectionTimeMs ?? null,
|
|
1957
|
+
has_oauth: data.hasOAuth,
|
|
1958
|
+
has_sampling: data.hasSampling,
|
|
1959
|
+
has_elicitation: data.hasElicitation
|
|
1960
|
+
}
|
|
1956
1961
|
});
|
|
1957
|
-
return;
|
|
1958
1962
|
}
|
|
1959
|
-
|
|
1960
|
-
|
|
1961
|
-
|
|
1962
|
-
|
|
1963
|
-
|
|
1964
|
-
|
|
1965
|
-
|
|
1963
|
+
async trackUseMcpToolCall(data) {
|
|
1964
|
+
if (!this.isEnabled) return;
|
|
1965
|
+
await this.capture({
|
|
1966
|
+
name: "usemcp_tool_call",
|
|
1967
|
+
properties: {
|
|
1968
|
+
tool_name: data.toolName,
|
|
1969
|
+
success: data.success,
|
|
1970
|
+
error_type: data.errorType ?? null,
|
|
1971
|
+
execution_time_ms: data.executionTimeMs ?? null
|
|
1972
|
+
}
|
|
1973
|
+
});
|
|
1966
1974
|
}
|
|
1967
|
-
|
|
1968
|
-
|
|
1975
|
+
async trackUseMcpResourceRead(data) {
|
|
1976
|
+
if (!this.isEnabled) return;
|
|
1977
|
+
await this.capture({
|
|
1978
|
+
name: "usemcp_resource_read",
|
|
1979
|
+
properties: {
|
|
1980
|
+
resource_uri_scheme: data.resourceUri.split(":")[0],
|
|
1981
|
+
success: data.success,
|
|
1982
|
+
error_type: data.errorType ?? null
|
|
1983
|
+
}
|
|
1969
1984
|
});
|
|
1970
|
-
return;
|
|
1971
1985
|
}
|
|
1972
|
-
|
|
1973
|
-
|
|
1974
|
-
|
|
1975
|
-
|
|
1976
|
-
|
|
1986
|
+
identify(userId, properties) {
|
|
1987
|
+
this._currUserId = userId;
|
|
1988
|
+
this._storage?.setUserId(userId);
|
|
1989
|
+
if (this._telemetryEnabled) {
|
|
1990
|
+
void capturePostHog({
|
|
1991
|
+
host: HOST,
|
|
1992
|
+
apiKey: PROJECT_API_KEY,
|
|
1993
|
+
event: "$identify",
|
|
1994
|
+
distinctId: userId,
|
|
1995
|
+
properties: { $set: properties ?? {} }
|
|
1996
|
+
});
|
|
1997
|
+
}
|
|
1977
1998
|
}
|
|
1978
|
-
|
|
1979
|
-
|
|
1980
|
-
|
|
1999
|
+
reset() {
|
|
2000
|
+
this._currUserId = null;
|
|
2001
|
+
}
|
|
2002
|
+
flush() {
|
|
2003
|
+
void Promise.allSettled([...this._pending]);
|
|
2004
|
+
}
|
|
2005
|
+
async shutdown() {
|
|
1981
2006
|
try {
|
|
1982
|
-
|
|
1983
|
-
|
|
2007
|
+
await Promise.allSettled([...this._pending]);
|
|
2008
|
+
logger.debug("Telemetry fetch captures flushed");
|
|
2009
|
+
} catch (e) {
|
|
2010
|
+
logger.debug(`Error flushing telemetry captures: ${e}`);
|
|
1984
2011
|
}
|
|
1985
2012
|
}
|
|
2013
|
+
};
|
|
2014
|
+
var Tel = Telemetry;
|
|
2015
|
+
function setTelemetrySource(source) {
|
|
2016
|
+
Tel.getInstance().setSource(source);
|
|
2017
|
+
}
|
|
2018
|
+
function setProductVersion(version) {
|
|
2019
|
+
Tel.getInstance().setProductVersion(version);
|
|
2020
|
+
}
|
|
2021
|
+
|
|
2022
|
+
// src/telemetry/telemetry-node.ts
|
|
2023
|
+
function getCacheHome(os, path2) {
|
|
2024
|
+
const envVar = process.env.XDG_CACHE_HOME;
|
|
2025
|
+
if (envVar && path2.isAbsolute(envVar)) {
|
|
2026
|
+
return envVar;
|
|
2027
|
+
}
|
|
2028
|
+
const homeDir = os.homedir();
|
|
2029
|
+
if (process.platform === "win32") {
|
|
2030
|
+
const appdata = process.env.LOCALAPPDATA || process.env.APPDATA;
|
|
2031
|
+
if (appdata) return appdata;
|
|
2032
|
+
return path2.join(homeDir, "AppData", "Local");
|
|
2033
|
+
}
|
|
2034
|
+
if (process.platform === "darwin") {
|
|
2035
|
+
return path2.join(homeDir, "Library", "Caches");
|
|
2036
|
+
}
|
|
2037
|
+
return path2.join(homeDir, ".cache");
|
|
2038
|
+
}
|
|
2039
|
+
function createFsStorage() {
|
|
2040
|
+
let fs2;
|
|
2041
|
+
let os;
|
|
2042
|
+
let path2;
|
|
1986
2043
|
try {
|
|
1987
|
-
|
|
1988
|
-
|
|
1989
|
-
|
|
1990
|
-
|
|
1991
|
-
|
|
1992
|
-
|
|
1993
|
-
|
|
1994
|
-
|
|
1995
|
-
return;
|
|
1996
|
-
case "cancelled":
|
|
1997
|
-
throw new Error("OAuth authentication was cancelled.");
|
|
1998
|
-
case "timeout":
|
|
1999
|
-
throw new Error(
|
|
2000
|
-
`OAuth callback not received within ${timeoutMs}ms. Ensure /oauth/callback calls onMcpAuthorization().`
|
|
2001
|
-
);
|
|
2002
|
-
case "error":
|
|
2003
|
-
throw new Error(result.error);
|
|
2004
|
-
default:
|
|
2005
|
-
throw new Error("Unexpected OAuth popup result");
|
|
2006
|
-
}
|
|
2007
|
-
} finally {
|
|
2008
|
-
provider.markFlowComplete?.();
|
|
2044
|
+
fs2 = __require("fs");
|
|
2045
|
+
os = __require("os");
|
|
2046
|
+
path2 = __require("path");
|
|
2047
|
+
} catch {
|
|
2048
|
+
return {
|
|
2049
|
+
getUserId: () => null,
|
|
2050
|
+
setUserId: () => void 0
|
|
2051
|
+
};
|
|
2009
2052
|
}
|
|
2053
|
+
const cacheHome = getCacheHome(os, path2);
|
|
2054
|
+
const userIdPath = path2.join(cacheHome, "mcp_use_3", "telemetry_user_id");
|
|
2055
|
+
return {
|
|
2056
|
+
getUserId() {
|
|
2057
|
+
try {
|
|
2058
|
+
if (!fs2.existsSync(userIdPath)) return null;
|
|
2059
|
+
return fs2.readFileSync(userIdPath, "utf-8").trim() || null;
|
|
2060
|
+
} catch {
|
|
2061
|
+
return null;
|
|
2062
|
+
}
|
|
2063
|
+
},
|
|
2064
|
+
setUserId(id) {
|
|
2065
|
+
try {
|
|
2066
|
+
fs2.mkdirSync(path2.dirname(userIdPath), { recursive: true });
|
|
2067
|
+
fs2.writeFileSync(userIdPath, id);
|
|
2068
|
+
} catch {
|
|
2069
|
+
}
|
|
2070
|
+
}
|
|
2071
|
+
};
|
|
2010
2072
|
}
|
|
2073
|
+
configureTelemetryStorage(createFsStorage());
|
|
2074
|
+
|
|
2075
|
+
// src/telemetry/configure-node.ts
|
|
2076
|
+
setClientTelemetryTracker({
|
|
2077
|
+
addServer: (name, config) => Telemetry.getInstance().trackClientAddServer(name, config).catch(() => void 0),
|
|
2078
|
+
removeServer: (name) => Telemetry.getInstance().trackClientRemoveServer(name).catch(() => void 0)
|
|
2079
|
+
});
|
|
2080
|
+
setConnectorTelemetryTracker(
|
|
2081
|
+
(data) => Telemetry.getInstance().trackConnectorInit(data).catch(() => void 0)
|
|
2082
|
+
);
|
|
2083
|
+
|
|
2084
|
+
// src/index.ts
|
|
2085
|
+
init_flow();
|
|
2086
|
+
import { auth as auth2, UnauthorizedError as UnauthorizedError3 } from "@modelcontextprotocol/client";
|
|
2011
2087
|
|
|
2012
2088
|
// src/auth/node.ts
|
|
2013
2089
|
import { createServer as createNetServer } from "net";
|
|
@@ -2840,16 +2916,19 @@ async function createOAuthProvider(serverUrl, options = {}) {
|
|
|
2840
2916
|
}
|
|
2841
2917
|
|
|
2842
2918
|
// src/transport/http.ts
|
|
2919
|
+
init_flow();
|
|
2843
2920
|
init_json_schema_validator();
|
|
2844
2921
|
init_logging();
|
|
2845
2922
|
init_base();
|
|
2846
2923
|
import {
|
|
2847
2924
|
Client,
|
|
2925
|
+
discoverOAuthProtectedResourceMetadata,
|
|
2848
2926
|
SdkError,
|
|
2849
2927
|
SdkHttpError,
|
|
2850
2928
|
StreamableHTTPClientTransport,
|
|
2851
2929
|
UnauthorizedError as UnauthorizedError2
|
|
2852
2930
|
} from "@modelcontextprotocol/client";
|
|
2931
|
+
var MIXED_AUTH_DISCOVERY_TIMEOUT_MS = 2e3;
|
|
2853
2932
|
function detectUnauthorized(err, depth = 0) {
|
|
2854
2933
|
if (!err || depth > 5) return false;
|
|
2855
2934
|
if (err instanceof UnauthorizedError2) return true;
|
|
@@ -2863,6 +2942,11 @@ function detectUnauthorized(err, depth = 0) {
|
|
|
2863
2942
|
}
|
|
2864
2943
|
return false;
|
|
2865
2944
|
}
|
|
2945
|
+
function isOAuthClientProvider(provider) {
|
|
2946
|
+
return Boolean(
|
|
2947
|
+
provider && "redirectToAuthorization" in provider && typeof provider.redirectToAuthorization === "function" && "tokens" in provider && typeof provider.tokens === "function"
|
|
2948
|
+
);
|
|
2949
|
+
}
|
|
2866
2950
|
function createMcpProxyFetch(logicalServerUrl, proxyUrl, baseFetch, serverId) {
|
|
2867
2951
|
const logical = new URL(logicalServerUrl);
|
|
2868
2952
|
const proxy = proxyUrl.replace(/\/$/, "");
|
|
@@ -2888,6 +2972,31 @@ function createMcpProxyFetch(logicalServerUrl, proxyUrl, baseFetch, serverId) {
|
|
|
2888
2972
|
);
|
|
2889
2973
|
};
|
|
2890
2974
|
}
|
|
2975
|
+
function createDeadlineFetch(baseFetch, deadlineSignal) {
|
|
2976
|
+
return async (input, init) => {
|
|
2977
|
+
const requestSignal = init?.signal;
|
|
2978
|
+
if (!requestSignal) {
|
|
2979
|
+
return baseFetch(input, { ...init, signal: deadlineSignal });
|
|
2980
|
+
}
|
|
2981
|
+
const controller = new AbortController();
|
|
2982
|
+
const abortFromRequest = () => controller.abort(requestSignal.reason);
|
|
2983
|
+
const abortFromDeadline = () => controller.abort(deadlineSignal.reason);
|
|
2984
|
+
if (requestSignal.aborted) abortFromRequest();
|
|
2985
|
+
else
|
|
2986
|
+
requestSignal.addEventListener("abort", abortFromRequest, { once: true });
|
|
2987
|
+
if (deadlineSignal.aborted) abortFromDeadline();
|
|
2988
|
+
else
|
|
2989
|
+
deadlineSignal.addEventListener("abort", abortFromDeadline, {
|
|
2990
|
+
once: true
|
|
2991
|
+
});
|
|
2992
|
+
try {
|
|
2993
|
+
return await baseFetch(input, { ...init, signal: controller.signal });
|
|
2994
|
+
} finally {
|
|
2995
|
+
requestSignal.removeEventListener("abort", abortFromRequest);
|
|
2996
|
+
deadlineSignal.removeEventListener("abort", abortFromDeadline);
|
|
2997
|
+
}
|
|
2998
|
+
};
|
|
2999
|
+
}
|
|
2891
3000
|
var HttpConnector = class extends BaseConnector {
|
|
2892
3001
|
baseUrl;
|
|
2893
3002
|
headers;
|
|
@@ -2898,8 +3007,11 @@ var HttpConnector = class extends BaseConnector {
|
|
|
2898
3007
|
gatewayUrl;
|
|
2899
3008
|
serverId;
|
|
2900
3009
|
reconnectionOptions;
|
|
3010
|
+
detectMixedAuth;
|
|
2901
3011
|
transportType = null;
|
|
2902
3012
|
streamableTransport = null;
|
|
3013
|
+
hadAccessTokenAtConnect = false;
|
|
3014
|
+
pendingOAuthCompletion = null;
|
|
2903
3015
|
/**
|
|
2904
3016
|
* Creates an HTTP connector.
|
|
2905
3017
|
*
|
|
@@ -2930,6 +3042,99 @@ var HttpConnector = class extends BaseConnector {
|
|
|
2930
3042
|
};
|
|
2931
3043
|
this.protocolNegotiation = opts.protocolNegotiation ?? "auto";
|
|
2932
3044
|
this.reconnectionOptions = opts.reconnectionOptions;
|
|
3045
|
+
this.detectMixedAuth = opts.detectMixedAuth ?? true;
|
|
3046
|
+
}
|
|
3047
|
+
get oauthProvider() {
|
|
3048
|
+
return isOAuthClientProvider(this.opts.authProvider) ? this.opts.authProvider : void 0;
|
|
3049
|
+
}
|
|
3050
|
+
async completeInteractiveAuthorization() {
|
|
3051
|
+
const provider = this.oauthProvider;
|
|
3052
|
+
if (!provider) {
|
|
3053
|
+
throw new Error("No OAuth client provider is configured");
|
|
3054
|
+
}
|
|
3055
|
+
if (!this.pendingOAuthCompletion) {
|
|
3056
|
+
this.pendingOAuthCompletion = completeOAuthFlow(provider, this.baseUrl, {
|
|
3057
|
+
fetchFn: this.customFetch,
|
|
3058
|
+
finishAuthorization: async (code, iss) => {
|
|
3059
|
+
const transport = this.streamableTransport;
|
|
3060
|
+
if (!transport) {
|
|
3061
|
+
throw new Error("OAuth transport is no longer connected");
|
|
3062
|
+
}
|
|
3063
|
+
await transport.finishAuth(code, iss);
|
|
3064
|
+
}
|
|
3065
|
+
}).then(() => {
|
|
3066
|
+
if (this.authorizationCache) {
|
|
3067
|
+
this.authorizationCache = {
|
|
3068
|
+
...this.authorizationCache,
|
|
3069
|
+
authenticated: true
|
|
3070
|
+
};
|
|
3071
|
+
}
|
|
3072
|
+
}).finally(() => {
|
|
3073
|
+
this.pendingOAuthCompletion = null;
|
|
3074
|
+
});
|
|
3075
|
+
}
|
|
3076
|
+
await this.pendingOAuthCompletion;
|
|
3077
|
+
}
|
|
3078
|
+
async executeRequest(operation) {
|
|
3079
|
+
try {
|
|
3080
|
+
return await operation();
|
|
3081
|
+
} catch (error) {
|
|
3082
|
+
const provider = this.oauthProvider;
|
|
3083
|
+
if (!provider || provider.preventAutoAuth === true || !isOAuthInteractionRequired(error)) {
|
|
3084
|
+
throw error;
|
|
3085
|
+
}
|
|
3086
|
+
await this.completeInteractiveAuthorization();
|
|
3087
|
+
return operation();
|
|
3088
|
+
}
|
|
3089
|
+
}
|
|
3090
|
+
/** Authenticate an already-connected server without requiring a 401 first. */
|
|
3091
|
+
async authenticate() {
|
|
3092
|
+
if (!this.connected || !this.streamableTransport) {
|
|
3093
|
+
throw new Error("MCP client is not connected");
|
|
3094
|
+
}
|
|
3095
|
+
await this.completeInteractiveAuthorization();
|
|
3096
|
+
}
|
|
3097
|
+
async initialize(defaultRequestOptions = this.opts.defaultRequestOptions ?? {}) {
|
|
3098
|
+
const capabilities = await super.initialize(defaultRequestOptions);
|
|
3099
|
+
if (!this.detectMixedAuth || !this.oauthProvider || this.hadAccessTokenAtConnect) {
|
|
3100
|
+
return capabilities;
|
|
3101
|
+
}
|
|
3102
|
+
const controller = new AbortController();
|
|
3103
|
+
let timeout;
|
|
3104
|
+
const discoveryTimeout = new Promise((_, reject) => {
|
|
3105
|
+
timeout = setTimeout(() => {
|
|
3106
|
+
const error = new Error(
|
|
3107
|
+
`Mixed-auth metadata discovery timed out after ${MIXED_AUTH_DISCOVERY_TIMEOUT_MS}ms`
|
|
3108
|
+
);
|
|
3109
|
+
controller.abort(error);
|
|
3110
|
+
reject(error);
|
|
3111
|
+
}, MIXED_AUTH_DISCOVERY_TIMEOUT_MS);
|
|
3112
|
+
});
|
|
3113
|
+
const baseFetch = this.customFetch ?? globalThis.fetch.bind(globalThis);
|
|
3114
|
+
try {
|
|
3115
|
+
const metadata = await Promise.race([
|
|
3116
|
+
discoverOAuthProtectedResourceMetadata(
|
|
3117
|
+
this.baseUrl,
|
|
3118
|
+
{ protocolVersion: this.negotiatedProtocolVersion },
|
|
3119
|
+
createDeadlineFetch(baseFetch, controller.signal)
|
|
3120
|
+
),
|
|
3121
|
+
discoveryTimeout
|
|
3122
|
+
]);
|
|
3123
|
+
this.authorizationCache = {
|
|
3124
|
+
mode: "mixed",
|
|
3125
|
+
authenticated: false,
|
|
3126
|
+
...metadata.resource ? { resource: metadata.resource } : {},
|
|
3127
|
+
...metadata.scopes_supported ? { scopesSupported: [...metadata.scopes_supported] } : {}
|
|
3128
|
+
};
|
|
3129
|
+
logger.info(
|
|
3130
|
+
"OAuth protected-resource metadata found after anonymous connection; server uses mixed auth"
|
|
3131
|
+
);
|
|
3132
|
+
} catch (error) {
|
|
3133
|
+
logger.debug("Mixed-auth metadata was not discovered:", error);
|
|
3134
|
+
} finally {
|
|
3135
|
+
if (timeout) clearTimeout(timeout);
|
|
3136
|
+
}
|
|
3137
|
+
return capabilities;
|
|
2933
3138
|
}
|
|
2934
3139
|
buildClientOptions() {
|
|
2935
3140
|
return {
|
|
@@ -3036,6 +3241,16 @@ var HttpConnector = class extends BaseConnector {
|
|
|
3036
3241
|
}
|
|
3037
3242
|
const baseUrl = this.baseUrl;
|
|
3038
3243
|
logger.debug(`Connecting to MCP implementation via HTTP: ${baseUrl}`);
|
|
3244
|
+
const oauthProvider = this.oauthProvider;
|
|
3245
|
+
if (oauthProvider) {
|
|
3246
|
+
try {
|
|
3247
|
+
this.hadAccessTokenAtConnect = Boolean(
|
|
3248
|
+
(await oauthProvider.tokens())?.access_token
|
|
3249
|
+
);
|
|
3250
|
+
} catch {
|
|
3251
|
+
this.hadAccessTokenAtConnect = false;
|
|
3252
|
+
}
|
|
3253
|
+
}
|
|
3039
3254
|
try {
|
|
3040
3255
|
await this.connectWithStreamableHttp(baseUrl);
|
|
3041
3256
|
logger.debug("\u2705 Successfully connected via streamable HTTP");
|
|
@@ -3387,6 +3602,7 @@ function createConnectorFromConfig(serverConfig, connectorOptions) {
|
|
|
3387
3602
|
fetch: serverConfig.fetch,
|
|
3388
3603
|
authToken: serverConfig.authToken,
|
|
3389
3604
|
authProvider: serverConfig.authProvider,
|
|
3605
|
+
detectMixedAuth: serverConfig.detectMixedAuth,
|
|
3390
3606
|
protocolNegotiation: serverConfig.protocolNegotiation,
|
|
3391
3607
|
timeout: serverConfig.timeout,
|
|
3392
3608
|
roots: serverConfig.roots,
|
|
@@ -3404,6 +3620,7 @@ import fs from "fs";
|
|
|
3404
3620
|
import path from "path";
|
|
3405
3621
|
|
|
3406
3622
|
// src/core/base.ts
|
|
3623
|
+
init_flow();
|
|
3407
3624
|
init_logging();
|
|
3408
3625
|
|
|
3409
3626
|
// src/core/skills.ts
|
|
@@ -3636,6 +3853,14 @@ var MCPConnection = class {
|
|
|
3636
3853
|
get serverInfo() {
|
|
3637
3854
|
return this.connector.serverInfo;
|
|
3638
3855
|
}
|
|
3856
|
+
/** OAuth state discovered for this connection, when available. */
|
|
3857
|
+
get authorization() {
|
|
3858
|
+
return this.connector.authorization;
|
|
3859
|
+
}
|
|
3860
|
+
/** Authenticate an already-connected mixed-auth server. */
|
|
3861
|
+
async authenticate() {
|
|
3862
|
+
await this.connector.authenticate();
|
|
3863
|
+
}
|
|
3639
3864
|
/**
|
|
3640
3865
|
* The negotiated protocol era for this session's connection:
|
|
3641
3866
|
* `"legacy"` (2025-era) or `"modern"` (2026-07-28-era).
|
|
@@ -3668,7 +3893,8 @@ var MCPConnection = class {
|
|
|
3668
3893
|
...server ? { server } : {},
|
|
3669
3894
|
capabilities,
|
|
3670
3895
|
instructions: this.connector.instructions,
|
|
3671
|
-
extensions
|
|
3896
|
+
extensions,
|
|
3897
|
+
...this.authorization ? { authorization: this.authorization } : {}
|
|
3672
3898
|
};
|
|
3673
3899
|
}
|
|
3674
3900
|
/**
|
|
@@ -3899,7 +4125,7 @@ var MCPConnection = class {
|
|
|
3899
4125
|
};
|
|
3900
4126
|
|
|
3901
4127
|
// src/core/base.ts
|
|
3902
|
-
function
|
|
4128
|
+
function isOAuthClientProvider2(provider) {
|
|
3903
4129
|
return !!provider && typeof provider === "object" && "redirectUrl" in provider && "clientMetadata" in provider;
|
|
3904
4130
|
}
|
|
3905
4131
|
var BaseMCPClient = class {
|
|
@@ -4132,7 +4358,7 @@ var BaseMCPClient = class {
|
|
|
4132
4358
|
...serverConfig,
|
|
4133
4359
|
authProvider: oauthProvider
|
|
4134
4360
|
};
|
|
4135
|
-
} else if ("authProvider" in serverConfig && serverConfig.authProvider &&
|
|
4361
|
+
} else if ("authProvider" in serverConfig && serverConfig.authProvider && isOAuthClientProvider2(serverConfig.authProvider)) {
|
|
4136
4362
|
oauthProvider = serverConfig.authProvider;
|
|
4137
4363
|
}
|
|
4138
4364
|
const openSession = async () => {
|
|
@@ -5818,6 +6044,7 @@ export {
|
|
|
5818
6044
|
createOAuthProvider,
|
|
5819
6045
|
decline,
|
|
5820
6046
|
getDefaults,
|
|
6047
|
+
isOAuthInteractionRequired,
|
|
5821
6048
|
isUnauthorized,
|
|
5822
6049
|
isVMAvailable,
|
|
5823
6050
|
loadConfigFile,
|