@mcp-use/client 2.0.0-beta.13 → 2.0.0-beta.14

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/index.d.ts CHANGED
@@ -8,7 +8,7 @@
8
8
  import "./telemetry/configure-node.js";
9
9
  export { auth, UnauthorizedError } from "@modelcontextprotocol/client";
10
10
  export { completeOAuthFlow, isUnauthorized } from "./auth/flow.js";
11
- export { createOAuthProvider, NodeOAuthClientProvider, OAuthFlowError, type NodeOAuthOptions, type OAuthProviderOptions, } from "./auth/node.js";
11
+ export { createOAuthProvider, NodeOAuthClientProvider, OAuthFlowError, type NodeOAuthAuthorizationResponse, type NodeOAuthOptions, type OAuthProviderOptions, } from "./auth/node.js";
12
12
  export { FileKVStore } from "./auth/storage-file.js";
13
13
  export * from "./core/config.js";
14
14
  export * from "./core/node.js";
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,OAAO,+BAA+B,CAAC;AAEvC,OAAO,EAAE,IAAI,EAAE,iBAAiB,EAAE,MAAM,8BAA8B,CAAC;AACvE,OAAO,EAAE,iBAAiB,EAAE,cAAc,EAAE,MAAM,gBAAgB,CAAC;AACnE,OAAO,EACL,mBAAmB,EACnB,uBAAuB,EACvB,cAAc,EACd,KAAK,gBAAgB,EACrB,KAAK,oBAAoB,GAC1B,MAAM,gBAAgB,CAAC;AACxB,OAAO,EAAE,WAAW,EAAE,MAAM,wBAAwB,CAAC;AACrD,cAAc,kBAAkB,CAAC;AACjC,cAAc,gBAAgB,CAAC;AAC/B,cAAc,mBAAmB,CAAC;AAGlC,cAAc,qBAAqB,CAAC;AACpC,cAAc,qBAAqB,CAAC;AACpC,cAAc,sBAAsB,CAAC;AAGrC,cAAc,kCAAkC,CAAC;AAGjD,cAAc,0BAA0B,CAAC;AAGzC,OAAO,EACL,kBAAkB,EAClB,iBAAiB,EACjB,GAAG,EACH,SAAS,EACT,QAAQ,EACR,cAAc,EACd,YAAY,EACZ,eAAe,GAChB,MAAM,sBAAsB,CAAC;AAC9B,OAAO,EAAE,MAAM,EAAE,MAAM,oBAAoB,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,OAAO,+BAA+B,CAAC;AAEvC,OAAO,EAAE,IAAI,EAAE,iBAAiB,EAAE,MAAM,8BAA8B,CAAC;AACvE,OAAO,EAAE,iBAAiB,EAAE,cAAc,EAAE,MAAM,gBAAgB,CAAC;AACnE,OAAO,EACL,mBAAmB,EACnB,uBAAuB,EACvB,cAAc,EACd,KAAK,8BAA8B,EACnC,KAAK,gBAAgB,EACrB,KAAK,oBAAoB,GAC1B,MAAM,gBAAgB,CAAC;AACxB,OAAO,EAAE,WAAW,EAAE,MAAM,wBAAwB,CAAC;AACrD,cAAc,kBAAkB,CAAC;AACjC,cAAc,gBAAgB,CAAC;AAC/B,cAAc,mBAAmB,CAAC;AAGlC,cAAc,qBAAqB,CAAC;AACpC,cAAc,qBAAqB,CAAC;AACpC,cAAc,sBAAsB,CAAC;AAGrC,cAAc,kCAAkC,CAAC;AAGjD,cAAc,0BAA0B,CAAC;AAGzC,OAAO,EACL,kBAAkB,EAClB,iBAAiB,EACjB,GAAG,EACH,SAAS,EACT,QAAQ,EACR,cAAc,EACd,YAAY,EACZ,eAAe,GAChB,MAAM,sBAAsB,CAAC;AAC9B,OAAO,EAAE,MAAM,EAAE,MAAM,oBAAoB,CAAC"}
package/dist/index.js CHANGED
@@ -802,6 +802,8 @@ var init_connection_manager = __esm({
802
802
  _connection = null;
803
803
  _task = null;
804
804
  _abortController = null;
805
+ _startPromise = null;
806
+ _stopPromise = null;
805
807
  constructor() {
806
808
  this.reset();
807
809
  }
@@ -811,10 +813,21 @@ var init_connection_manager = __esm({
811
813
  * @returns The established connection.
812
814
  * @throws If the connection cannot be established.
813
815
  */
814
- async start() {
816
+ start() {
817
+ if (this._stopPromise) {
818
+ return this._stopPromise.then(() => this.start());
819
+ }
820
+ if (this._startPromise) return this._startPromise;
815
821
  this.reset();
816
822
  logger.debug(`Starting ${this.constructor.name}`);
817
823
  this._task = this.connectionTask();
824
+ this._startPromise = this.waitUntilReady().catch((error) => {
825
+ this._startPromise = null;
826
+ throw error;
827
+ });
828
+ return this._startPromise;
829
+ }
830
+ async waitUntilReady() {
818
831
  await this._readyPromise;
819
832
  if (this._exception) {
820
833
  throw this._exception;
@@ -827,7 +840,18 @@ var init_connection_manager = __esm({
827
840
  /**
828
841
  * Stop the connection manager and close the connection.
829
842
  */
830
- async stop() {
843
+ stop() {
844
+ if (this._stopPromise) return this._stopPromise;
845
+ if (!this._task) return Promise.resolve();
846
+ const trackedStop = this.stopTask().finally(() => {
847
+ if (this._stopPromise === trackedStop) {
848
+ this._stopPromise = null;
849
+ }
850
+ });
851
+ this._stopPromise = trackedStop;
852
+ return trackedStop;
853
+ }
854
+ async stopTask() {
831
855
  if (this._task && this._abortController) {
832
856
  logger.debug(`Cancelling ${this.constructor.name} task`);
833
857
  this._abortController.abort();
@@ -842,6 +866,8 @@ var init_connection_manager = __esm({
842
866
  }
843
867
  }
844
868
  await this._donePromise;
869
+ this._task = null;
870
+ this._startPromise = null;
845
871
  logger.debug(`${this.constructor.name} task completed`);
846
872
  }
847
873
  /**
@@ -1108,7 +1134,7 @@ init_connector_telemetry();
1108
1134
  init_logging();
1109
1135
 
1110
1136
  // src/utils/version.ts
1111
- var VERSION = "2.0.0-beta.13";
1137
+ var VERSION = "2.0.0-beta.14";
1112
1138
  function getPackageVersion() {
1113
1139
  return VERSION;
1114
1140
  }
@@ -1128,16 +1154,13 @@ var MCPAgentExecutionEvent = class extends BaseTelemetryEvent {
1128
1154
  return {
1129
1155
  // Core execution info
1130
1156
  execution_method: this.data.executionMethod,
1131
- query: this.data.query,
1132
1157
  query_length: this.data.query.length,
1133
1158
  success: this.data.success,
1134
1159
  // Agent configuration
1135
1160
  model_provider: this.data.modelProvider,
1136
1161
  model_name: this.data.modelName,
1137
1162
  server_count: this.data.serverCount,
1138
- server_identifiers: this.data.serverIdentifiers,
1139
1163
  total_tools_available: this.data.totalToolsAvailable,
1140
- tools_available_names: this.data.toolsAvailableNames,
1141
1164
  max_steps_configured: this.data.maxStepsConfigured,
1142
1165
  memory_enabled: this.data.memoryEnabled,
1143
1166
  use_server_manager: this.data.useServerManager,
@@ -1148,8 +1171,6 @@ var MCPAgentExecutionEvent = class extends BaseTelemetryEvent {
1148
1171
  // Execution results (always include, even if null)
1149
1172
  steps_taken: this.data.stepsTaken ?? null,
1150
1173
  tools_used_count: this.data.toolsUsedCount ?? null,
1151
- tools_used_names: this.data.toolsUsedNames ?? null,
1152
- response: this.data.response ?? null,
1153
1174
  response_length: this.data.response ? this.data.response.length : null,
1154
1175
  execution_time_ms: this.data.executionTimeMs ?? null,
1155
1176
  error_type: this.data.errorType ?? null,
@@ -1245,21 +1266,72 @@ async function telFetch(url, init) {
1245
1266
  }
1246
1267
  var POSTHOG_HOST = "https://eu.i.posthog.com";
1247
1268
  var POSTHOG_API_KEY = "phc_lyTtbYwvkdSbrcMQNPiKiiRWrrM1seyKIMjycSvItEI";
1248
- function capturePostHog(params) {
1249
- const host = params.host ?? POSTHOG_HOST;
1250
- const apiKey = params.apiKey ?? POSTHOG_API_KEY;
1251
- return telFetch(`${host}/i/v0/e/`, {
1252
- method: "POST",
1253
- headers: { "Content-Type": "application/json" },
1254
- keepalive: true,
1255
- body: JSON.stringify({
1269
+ var CONTENT_PROPERTY = /(^|_)(arguments?|args|body|command|headers?|location|message|query|response|secret|subject|token|uri|url|user_agent)(_|$)/i;
1270
+ var IDENTIFYING_PROPERTY = /(^|_)(server_identifiers?|server_names?|servers|tool_names?|tools_(available|used)_names)(_|$)/i;
1271
+ var AGGREGATE_PROPERTY = /(_count|_length|_duration(?:_ms)?|_time_ms|(^|_)num_[a-z0-9_]+)$/i;
1272
+ function normalizePropertyKey(key) {
1273
+ return key.replace(/([a-z0-9])([A-Z])/g, "$1_$2").replace(/[^a-z0-9_$]+/gi, "_").toLowerCase();
1274
+ }
1275
+ function sanitizeValue(value, seen) {
1276
+ if (Array.isArray(value)) {
1277
+ if (seen.has(value)) {
1278
+ throw new TypeError("Cyclic telemetry properties are not supported");
1279
+ }
1280
+ seen.add(value);
1281
+ const sanitized = value.map((item) => sanitizeValue(item, seen));
1282
+ seen.delete(value);
1283
+ return sanitized;
1284
+ }
1285
+ if (value !== null && typeof value === "object" && (Object.getPrototypeOf(value) === Object.prototype || Object.getPrototypeOf(value) === null)) {
1286
+ if (seen.has(value)) {
1287
+ throw new TypeError("Cyclic telemetry properties are not supported");
1288
+ }
1289
+ seen.add(value);
1290
+ const sanitized = sanitizeProperties(
1291
+ value,
1292
+ seen
1293
+ );
1294
+ seen.delete(value);
1295
+ return sanitized;
1296
+ }
1297
+ return value;
1298
+ }
1299
+ function sanitizeProperties(properties, seen = /* @__PURE__ */ new WeakSet()) {
1300
+ const sanitized = {};
1301
+ for (const [key, value] of Object.entries(properties)) {
1302
+ const normalizedKey = normalizePropertyKey(key);
1303
+ if (AGGREGATE_PROPERTY.test(normalizedKey)) {
1304
+ if (value === null || typeof value === "number") {
1305
+ sanitized[key] = value;
1306
+ }
1307
+ continue;
1308
+ }
1309
+ if (IDENTIFYING_PROPERTY.test(normalizedKey) || CONTENT_PROPERTY.test(normalizedKey)) {
1310
+ continue;
1311
+ }
1312
+ sanitized[key] = sanitizeValue(value, seen);
1313
+ }
1314
+ return sanitized;
1315
+ }
1316
+ async function capturePostHog(params) {
1317
+ try {
1318
+ const host = params.host ?? POSTHOG_HOST;
1319
+ const apiKey = params.apiKey ?? POSTHOG_API_KEY;
1320
+ const body = JSON.stringify({
1256
1321
  api_key: apiKey,
1257
1322
  event: params.event,
1258
1323
  distinct_id: params.distinctId,
1259
- properties: params.properties,
1324
+ properties: sanitizeProperties(params.properties),
1260
1325
  timestamp: (/* @__PURE__ */ new Date()).toISOString()
1261
- })
1262
- });
1326
+ });
1327
+ await telFetch(`${host}/i/v0/e/`, {
1328
+ method: "POST",
1329
+ headers: { "Content-Type": "application/json" },
1330
+ keepalive: true,
1331
+ body
1332
+ });
1333
+ } catch {
1334
+ }
1263
1335
  }
1264
1336
 
1265
1337
  // src/telemetry/telemetry.ts
@@ -1789,11 +1861,12 @@ async function completeOAuthFlow(provider, serverUrl, options = {}) {
1789
1861
  throw new Error(`Unexpected OAuth auth() result: ${result}`);
1790
1862
  }
1791
1863
  }
1792
- if (typeof flowProvider.getAuthorizationCode === "function") {
1793
- const code = await flowProvider.getAuthorizationCode();
1864
+ if (typeof flowProvider.getAuthorizationResponse === "function" || typeof flowProvider.getAuthorizationCode === "function") {
1865
+ const response = typeof flowProvider.getAuthorizationResponse === "function" ? await flowProvider.getAuthorizationResponse() : { code: await flowProvider.getAuthorizationCode() };
1794
1866
  await auth(provider, {
1795
1867
  serverUrl,
1796
- authorizationCode: code,
1868
+ authorizationCode: response.code,
1869
+ ...response.iss !== void 0 ? { iss: response.iss } : {},
1797
1870
  fetchFn
1798
1871
  });
1799
1872
  return;
@@ -1807,6 +1880,8 @@ async function waitForBrowserAuthComplete(provider, timeoutMs) {
1807
1880
  );
1808
1881
  }
1809
1882
  if (provider.useRedirectFlow) {
1883
+ await new Promise(() => {
1884
+ });
1810
1885
  return;
1811
1886
  }
1812
1887
  const tokensKey = provider.getKey?.("tokens");
@@ -1823,25 +1898,29 @@ async function waitForBrowserAuthComplete(provider, timeoutMs) {
1823
1898
  } catch {
1824
1899
  }
1825
1900
  }
1826
- const result = await runAuthPopup({
1827
- popup: null,
1828
- state,
1829
- tokensKey,
1830
- timeoutMs
1831
- });
1832
- switch (result.kind) {
1833
- case "success":
1834
- return;
1835
- case "cancelled":
1836
- throw new Error("OAuth authentication was cancelled.");
1837
- case "timeout":
1838
- throw new Error(
1839
- `OAuth callback not received within ${timeoutMs}ms. Ensure /oauth/callback calls onMcpAuthorization().`
1840
- );
1841
- case "error":
1842
- throw new Error(result.error);
1843
- default:
1844
- throw new Error("Unexpected OAuth popup result");
1901
+ try {
1902
+ const result = await runAuthPopup({
1903
+ popup: null,
1904
+ state,
1905
+ tokensKey,
1906
+ timeoutMs
1907
+ });
1908
+ switch (result.kind) {
1909
+ case "success":
1910
+ return;
1911
+ case "cancelled":
1912
+ throw new Error("OAuth authentication was cancelled.");
1913
+ case "timeout":
1914
+ throw new Error(
1915
+ `OAuth callback not received within ${timeoutMs}ms. Ensure /oauth/callback calls onMcpAuthorization().`
1916
+ );
1917
+ case "error":
1918
+ throw new Error(result.error);
1919
+ default:
1920
+ throw new Error("Unexpected OAuth popup result");
1921
+ }
1922
+ } finally {
1923
+ provider.markFlowComplete?.();
1845
1924
  }
1846
1925
  }
1847
1926
 
@@ -2207,7 +2286,7 @@ var OAuthSessionStore = class _OAuthSessionStore {
2207
2286
  */
2208
2287
  async storeAuthorizationState(authorizationUrl, opts = {}) {
2209
2288
  const state = globalThis.crypto.randomUUID();
2210
- const stateKey = `${this.storageKeyPrefix}:state_${state}`;
2289
+ const stateKey = `${this.storageKeyPrefix}_${this.serverUrlHash}_state_${state}`;
2211
2290
  const stateData = {
2212
2291
  serverUrlHash: this.serverUrlHash,
2213
2292
  expiry: Date.now() + 1e3 * 60 * 10,
@@ -2316,7 +2395,7 @@ var NodeOAuthClientProvider = class _NodeOAuthClientProvider {
2316
2395
  server = null;
2317
2396
  /** Currently in-flight deferred — used to prevent overlapping flows. */
2318
2397
  pending = null;
2319
- /** Latest deferred (settled or in-flight) what `getAuthorizationCode()` returns. */
2398
+ /** Latest deferred (settled or in-flight) for the loopback response. */
2320
2399
  lastFlow = null;
2321
2400
  pendingTimer = null;
2322
2401
  constructor(serverUrl, port, session, kv, options) {
@@ -2443,15 +2522,25 @@ var NodeOAuthClientProvider = class _NodeOAuthClientProvider {
2443
2522
  }
2444
2523
  /**
2445
2524
  * Resolves with the authorization code captured by the loopback callback.
2525
+ *
2526
+ * @remarks This compatibility method omits the RFC 9207 issuer. OAuth flow
2527
+ * orchestrators should use {@link getAuthorizationResponse} when available.
2446
2528
  * Must be called after `redirectToAuthorization()`. Returns the same
2447
2529
  * promise whether the callback has fired or not — callers may subscribe
2448
2530
  * before or after.
2449
2531
  */
2450
2532
  getAuthorizationCode() {
2533
+ return this.getAuthorizationResponse().then((response) => response.code);
2534
+ }
2535
+ /**
2536
+ * Resolves with the authorization code and RFC 9207 issuer captured by the
2537
+ * loopback callback.
2538
+ */
2539
+ getAuthorizationResponse() {
2451
2540
  if (!this.lastFlow) {
2452
2541
  return Promise.reject(
2453
2542
  new Error(
2454
- "NodeOAuthClientProvider.getAuthorizationCode() called before redirectToAuthorization()"
2543
+ "NodeOAuthClientProvider.getAuthorizationResponse() called before redirectToAuthorization()"
2455
2544
  )
2456
2545
  );
2457
2546
  }
@@ -2506,11 +2595,11 @@ var NodeOAuthClientProvider = class _NodeOAuthClientProvider {
2506
2595
  this.server = null;
2507
2596
  }
2508
2597
  }
2509
- resolvePending(code) {
2598
+ resolvePending(response) {
2510
2599
  const p = this.pending;
2511
2600
  this.pending = null;
2512
2601
  this.stopLoopback();
2513
- p?.resolve(code);
2602
+ p?.resolve(response);
2514
2603
  }
2515
2604
  rejectPending(err) {
2516
2605
  const p = this.pending;
@@ -2527,6 +2616,7 @@ var NodeOAuthClientProvider = class _NodeOAuthClientProvider {
2527
2616
  }
2528
2617
  const code = url.searchParams.get("code");
2529
2618
  const state = url.searchParams.get("state");
2619
+ const iss = url.searchParams.get("iss") ?? void 0;
2530
2620
  const err = url.searchParams.get("error");
2531
2621
  const errDesc = url.searchParams.get("error_description") ?? void 0;
2532
2622
  if (err) {
@@ -2544,7 +2634,7 @@ var NodeOAuthClientProvider = class _NodeOAuthClientProvider {
2544
2634
  res.statusCode = 200;
2545
2635
  res.setHeader("content-type", "text/html; charset=utf-8");
2546
2636
  res.end(SUCCESS_HTML);
2547
- this.resolvePending(code);
2637
+ this.resolvePending({ code, ...iss !== void 0 ? { iss } : {} });
2548
2638
  }
2549
2639
  };
2550
2640
  async function defaultOpener(url) {