@modelcontextprotocol/inspector-client 0.16.0 → 0.16.2

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.
@@ -1,4 +1,4 @@
1
- const __vite__mapDeps=(i,m=__vite__mapDeps,d=(m.f||(m.f=["assets/OAuthCallback-DMQy4ibj.js","assets/oauthUtils-DTcoXpSP.js","assets/OAuthDebugCallback-9JxBAysc.js"])))=>i.map(i=>d[i]);
1
+ const __vite__mapDeps=(i,m=__vite__mapDeps,d=(m.f||(m.f=["assets/OAuthCallback-CC1cu0Zx.js","assets/oauthUtils-DTcoXpSP.js","assets/OAuthDebugCallback-_4BLxVDe.js"])))=>i.map(i=>d[i]);
2
2
  function _mergeNamespaces(n, m2) {
3
3
  for (var i = 0; i < m2.length; i++) {
4
4
  const e = m2[i];
@@ -15408,11 +15408,19 @@ const TextResourceContentsSchema = ResourceContentsSchema.extend({
15408
15408
  */
15409
15409
  text: stringType()
15410
15410
  });
15411
+ const Base64Schema = stringType().refine((val) => {
15412
+ try {
15413
+ atob(val);
15414
+ return true;
15415
+ } catch (_a) {
15416
+ return false;
15417
+ }
15418
+ }, { message: "Invalid Base64 string" });
15411
15419
  const BlobResourceContentsSchema = ResourceContentsSchema.extend({
15412
15420
  /**
15413
15421
  * A base64-encoded string representing the binary data of the item.
15414
15422
  */
15415
- blob: stringType().base64()
15423
+ blob: Base64Schema
15416
15424
  });
15417
15425
  const ResourceSchema = BaseMetadataSchema.extend({
15418
15426
  /**
@@ -15575,7 +15583,7 @@ const ImageContentSchema = objectType({
15575
15583
  /**
15576
15584
  * The base64-encoded image data.
15577
15585
  */
15578
- data: stringType().base64(),
15586
+ data: Base64Schema,
15579
15587
  /**
15580
15588
  * The MIME type of the image. Different providers may support different image types.
15581
15589
  */
@@ -15591,7 +15599,7 @@ const AudioContentSchema = objectType({
15591
15599
  /**
15592
15600
  * The base64-encoded audio data.
15593
15601
  */
15594
- data: stringType().base64(),
15602
+ data: Base64Schema,
15595
15603
  /**
15596
15604
  * The MIME type of the audio. Different providers may support different audio types.
15597
15605
  */
@@ -16101,14 +16109,56 @@ const OAuthMetadataSchema = objectType({
16101
16109
  introspection_endpoint_auth_signing_alg_values_supported: arrayType(stringType()).optional(),
16102
16110
  code_challenge_methods_supported: arrayType(stringType()).optional()
16103
16111
  }).passthrough();
16112
+ const OpenIdProviderMetadataSchema = objectType({
16113
+ issuer: stringType(),
16114
+ authorization_endpoint: stringType(),
16115
+ token_endpoint: stringType(),
16116
+ userinfo_endpoint: stringType().optional(),
16117
+ jwks_uri: stringType(),
16118
+ registration_endpoint: stringType().optional(),
16119
+ scopes_supported: arrayType(stringType()).optional(),
16120
+ response_types_supported: arrayType(stringType()),
16121
+ response_modes_supported: arrayType(stringType()).optional(),
16122
+ grant_types_supported: arrayType(stringType()).optional(),
16123
+ acr_values_supported: arrayType(stringType()).optional(),
16124
+ subject_types_supported: arrayType(stringType()),
16125
+ id_token_signing_alg_values_supported: arrayType(stringType()),
16126
+ id_token_encryption_alg_values_supported: arrayType(stringType()).optional(),
16127
+ id_token_encryption_enc_values_supported: arrayType(stringType()).optional(),
16128
+ userinfo_signing_alg_values_supported: arrayType(stringType()).optional(),
16129
+ userinfo_encryption_alg_values_supported: arrayType(stringType()).optional(),
16130
+ userinfo_encryption_enc_values_supported: arrayType(stringType()).optional(),
16131
+ request_object_signing_alg_values_supported: arrayType(stringType()).optional(),
16132
+ request_object_encryption_alg_values_supported: arrayType(stringType()).optional(),
16133
+ request_object_encryption_enc_values_supported: arrayType(stringType()).optional(),
16134
+ token_endpoint_auth_methods_supported: arrayType(stringType()).optional(),
16135
+ token_endpoint_auth_signing_alg_values_supported: arrayType(stringType()).optional(),
16136
+ display_values_supported: arrayType(stringType()).optional(),
16137
+ claim_types_supported: arrayType(stringType()).optional(),
16138
+ claims_supported: arrayType(stringType()).optional(),
16139
+ service_documentation: stringType().optional(),
16140
+ claims_locales_supported: arrayType(stringType()).optional(),
16141
+ ui_locales_supported: arrayType(stringType()).optional(),
16142
+ claims_parameter_supported: booleanType().optional(),
16143
+ request_parameter_supported: booleanType().optional(),
16144
+ request_uri_parameter_supported: booleanType().optional(),
16145
+ require_request_uri_registration: booleanType().optional(),
16146
+ op_policy_uri: stringType().optional(),
16147
+ op_tos_uri: stringType().optional()
16148
+ }).passthrough();
16149
+ const OpenIdProviderDiscoveryMetadataSchema = OpenIdProviderMetadataSchema.merge(OAuthMetadataSchema.pick({
16150
+ code_challenge_methods_supported: true
16151
+ }));
16104
16152
  const OAuthTokensSchema = objectType({
16105
16153
  access_token: stringType(),
16154
+ id_token: stringType().optional(),
16155
+ // Optional for OAuth 2.1, but necessary in OpenID Connect
16106
16156
  token_type: stringType(),
16107
16157
  expires_in: numberType().optional(),
16108
16158
  scope: stringType().optional(),
16109
16159
  refresh_token: stringType().optional()
16110
16160
  }).strip();
16111
- objectType({
16161
+ const OAuthErrorResponseSchema = objectType({
16112
16162
  error: stringType(),
16113
16163
  error_description: stringType().optional(),
16114
16164
  error_uri: stringType().optional()
@@ -16151,6 +16201,7 @@ const SESSION_KEYS = {
16151
16201
  SERVER_URL: "mcp_server_url",
16152
16202
  TOKENS: "mcp_tokens",
16153
16203
  CLIENT_INFORMATION: "mcp_client_information",
16204
+ PREREGISTERED_CLIENT_INFORMATION: "mcp_preregistered_client_information",
16154
16205
  SERVER_METADATA: "mcp_server_metadata",
16155
16206
  AUTH_DEBUGGER_STATE: "mcp_auth_debugger_state"
16156
16207
  };
@@ -16207,6 +16258,41 @@ const EMPTY_DEBUGGER_STATE = {
16207
16258
  statusMessage: null,
16208
16259
  validationError: null
16209
16260
  };
16261
+ const getClientInformationFromSessionStorage = async ({
16262
+ serverUrl,
16263
+ isPreregistered
16264
+ }) => {
16265
+ const key = getServerSpecificKey(
16266
+ isPreregistered ? SESSION_KEYS.PREREGISTERED_CLIENT_INFORMATION : SESSION_KEYS.CLIENT_INFORMATION,
16267
+ serverUrl
16268
+ );
16269
+ const value = sessionStorage.getItem(key);
16270
+ if (!value) {
16271
+ return void 0;
16272
+ }
16273
+ return await OAuthClientInformationSchema.parseAsync(JSON.parse(value));
16274
+ };
16275
+ const saveClientInformationToSessionStorage = ({
16276
+ serverUrl,
16277
+ clientInformation,
16278
+ isPreregistered
16279
+ }) => {
16280
+ const key = getServerSpecificKey(
16281
+ isPreregistered ? SESSION_KEYS.PREREGISTERED_CLIENT_INFORMATION : SESSION_KEYS.CLIENT_INFORMATION,
16282
+ serverUrl
16283
+ );
16284
+ sessionStorage.setItem(key, JSON.stringify(clientInformation));
16285
+ };
16286
+ const clearClientInformationFromSessionStorage = ({
16287
+ serverUrl,
16288
+ isPreregistered
16289
+ }) => {
16290
+ const key = getServerSpecificKey(
16291
+ isPreregistered ? SESSION_KEYS.PREREGISTERED_CLIENT_INFORMATION : SESSION_KEYS.CLIENT_INFORMATION,
16292
+ serverUrl
16293
+ );
16294
+ sessionStorage.removeItem(key);
16295
+ };
16210
16296
  class InspectorOAuthClientProvider {
16211
16297
  constructor(serverUrl) {
16212
16298
  this.serverUrl = serverUrl;
@@ -16226,22 +16312,21 @@ class InspectorOAuthClientProvider {
16226
16312
  };
16227
16313
  }
16228
16314
  async clientInformation() {
16229
- const key = getServerSpecificKey(
16230
- SESSION_KEYS.CLIENT_INFORMATION,
16231
- this.serverUrl
16232
- );
16233
- const value = sessionStorage.getItem(key);
16234
- if (!value) {
16235
- return void 0;
16236
- }
16237
- return await OAuthClientInformationSchema.parseAsync(JSON.parse(value));
16315
+ const preregisteredClientInformation = await getClientInformationFromSessionStorage({
16316
+ serverUrl: this.serverUrl,
16317
+ isPreregistered: true
16318
+ });
16319
+ return preregisteredClientInformation ?? await getClientInformationFromSessionStorage({
16320
+ serverUrl: this.serverUrl,
16321
+ isPreregistered: false
16322
+ });
16238
16323
  }
16239
16324
  saveClientInformation(clientInformation) {
16240
- const key = getServerSpecificKey(
16241
- SESSION_KEYS.CLIENT_INFORMATION,
16242
- this.serverUrl
16243
- );
16244
- sessionStorage.setItem(key, JSON.stringify(clientInformation));
16325
+ saveClientInformationToSessionStorage({
16326
+ serverUrl: this.serverUrl,
16327
+ clientInformation,
16328
+ isPreregistered: false
16329
+ });
16245
16330
  }
16246
16331
  async tokens() {
16247
16332
  const key = getServerSpecificKey(SESSION_KEYS.TOKENS, this.serverUrl);
@@ -16277,9 +16362,10 @@ class InspectorOAuthClientProvider {
16277
16362
  return verifier;
16278
16363
  }
16279
16364
  clear() {
16280
- sessionStorage.removeItem(
16281
- getServerSpecificKey(SESSION_KEYS.CLIENT_INFORMATION, this.serverUrl)
16282
- );
16365
+ clearClientInformationFromSessionStorage({
16366
+ serverUrl: this.serverUrl,
16367
+ isPreregistered: false
16368
+ });
16283
16369
  sessionStorage.removeItem(
16284
16370
  getServerSpecificKey(SESSION_KEYS.TOKENS, this.serverUrl)
16285
16371
  );
@@ -16370,23 +16456,193 @@ function checkResourceAllowed({ requestedResource, configuredResource }) {
16370
16456
  const configuredPath = configured.pathname.endsWith("/") ? configured.pathname : configured.pathname + "/";
16371
16457
  return requestedPath.startsWith(configuredPath);
16372
16458
  }
16459
+ class OAuthError extends Error {
16460
+ constructor(message, errorUri) {
16461
+ super(message);
16462
+ this.errorUri = errorUri;
16463
+ this.name = this.constructor.name;
16464
+ }
16465
+ /**
16466
+ * Converts the error to a standard OAuth error response object
16467
+ */
16468
+ toResponseObject() {
16469
+ const response = {
16470
+ error: this.errorCode,
16471
+ error_description: this.message
16472
+ };
16473
+ if (this.errorUri) {
16474
+ response.error_uri = this.errorUri;
16475
+ }
16476
+ return response;
16477
+ }
16478
+ get errorCode() {
16479
+ return this.constructor.errorCode;
16480
+ }
16481
+ }
16482
+ class InvalidRequestError extends OAuthError {
16483
+ }
16484
+ InvalidRequestError.errorCode = "invalid_request";
16485
+ class InvalidClientError extends OAuthError {
16486
+ }
16487
+ InvalidClientError.errorCode = "invalid_client";
16488
+ class InvalidGrantError extends OAuthError {
16489
+ }
16490
+ InvalidGrantError.errorCode = "invalid_grant";
16491
+ class UnauthorizedClientError extends OAuthError {
16492
+ }
16493
+ UnauthorizedClientError.errorCode = "unauthorized_client";
16494
+ class UnsupportedGrantTypeError extends OAuthError {
16495
+ }
16496
+ UnsupportedGrantTypeError.errorCode = "unsupported_grant_type";
16497
+ class InvalidScopeError extends OAuthError {
16498
+ }
16499
+ InvalidScopeError.errorCode = "invalid_scope";
16500
+ class AccessDeniedError extends OAuthError {
16501
+ }
16502
+ AccessDeniedError.errorCode = "access_denied";
16503
+ class ServerError extends OAuthError {
16504
+ }
16505
+ ServerError.errorCode = "server_error";
16506
+ class TemporarilyUnavailableError extends OAuthError {
16507
+ }
16508
+ TemporarilyUnavailableError.errorCode = "temporarily_unavailable";
16509
+ class UnsupportedResponseTypeError extends OAuthError {
16510
+ }
16511
+ UnsupportedResponseTypeError.errorCode = "unsupported_response_type";
16512
+ class UnsupportedTokenTypeError extends OAuthError {
16513
+ }
16514
+ UnsupportedTokenTypeError.errorCode = "unsupported_token_type";
16515
+ class InvalidTokenError extends OAuthError {
16516
+ }
16517
+ InvalidTokenError.errorCode = "invalid_token";
16518
+ class MethodNotAllowedError extends OAuthError {
16519
+ }
16520
+ MethodNotAllowedError.errorCode = "method_not_allowed";
16521
+ class TooManyRequestsError extends OAuthError {
16522
+ }
16523
+ TooManyRequestsError.errorCode = "too_many_requests";
16524
+ class InvalidClientMetadataError extends OAuthError {
16525
+ }
16526
+ InvalidClientMetadataError.errorCode = "invalid_client_metadata";
16527
+ class InsufficientScopeError extends OAuthError {
16528
+ }
16529
+ InsufficientScopeError.errorCode = "insufficient_scope";
16530
+ const OAUTH_ERRORS = {
16531
+ [InvalidRequestError.errorCode]: InvalidRequestError,
16532
+ [InvalidClientError.errorCode]: InvalidClientError,
16533
+ [InvalidGrantError.errorCode]: InvalidGrantError,
16534
+ [UnauthorizedClientError.errorCode]: UnauthorizedClientError,
16535
+ [UnsupportedGrantTypeError.errorCode]: UnsupportedGrantTypeError,
16536
+ [InvalidScopeError.errorCode]: InvalidScopeError,
16537
+ [AccessDeniedError.errorCode]: AccessDeniedError,
16538
+ [ServerError.errorCode]: ServerError,
16539
+ [TemporarilyUnavailableError.errorCode]: TemporarilyUnavailableError,
16540
+ [UnsupportedResponseTypeError.errorCode]: UnsupportedResponseTypeError,
16541
+ [UnsupportedTokenTypeError.errorCode]: UnsupportedTokenTypeError,
16542
+ [InvalidTokenError.errorCode]: InvalidTokenError,
16543
+ [MethodNotAllowedError.errorCode]: MethodNotAllowedError,
16544
+ [TooManyRequestsError.errorCode]: TooManyRequestsError,
16545
+ [InvalidClientMetadataError.errorCode]: InvalidClientMetadataError,
16546
+ [InsufficientScopeError.errorCode]: InsufficientScopeError
16547
+ };
16373
16548
  class UnauthorizedError extends Error {
16374
16549
  constructor(message) {
16375
16550
  super(message !== null && message !== void 0 ? message : "Unauthorized");
16376
16551
  }
16377
16552
  }
16378
- async function auth(provider, { serverUrl, authorizationCode, scope, resourceMetadataUrl }) {
16553
+ function selectClientAuthMethod(clientInformation, supportedMethods) {
16554
+ const hasClientSecret = clientInformation.client_secret !== void 0;
16555
+ if (supportedMethods.length === 0) {
16556
+ return hasClientSecret ? "client_secret_post" : "none";
16557
+ }
16558
+ if (hasClientSecret && supportedMethods.includes("client_secret_basic")) {
16559
+ return "client_secret_basic";
16560
+ }
16561
+ if (hasClientSecret && supportedMethods.includes("client_secret_post")) {
16562
+ return "client_secret_post";
16563
+ }
16564
+ if (supportedMethods.includes("none")) {
16565
+ return "none";
16566
+ }
16567
+ return hasClientSecret ? "client_secret_post" : "none";
16568
+ }
16569
+ function applyClientAuthentication(method, clientInformation, headers, params) {
16570
+ const { client_id, client_secret } = clientInformation;
16571
+ switch (method) {
16572
+ case "client_secret_basic":
16573
+ applyBasicAuth(client_id, client_secret, headers);
16574
+ return;
16575
+ case "client_secret_post":
16576
+ applyPostAuth(client_id, client_secret, params);
16577
+ return;
16578
+ case "none":
16579
+ applyPublicAuth(client_id, params);
16580
+ return;
16581
+ default:
16582
+ throw new Error(`Unsupported client authentication method: ${method}`);
16583
+ }
16584
+ }
16585
+ function applyBasicAuth(clientId, clientSecret, headers) {
16586
+ if (!clientSecret) {
16587
+ throw new Error("client_secret_basic authentication requires a client_secret");
16588
+ }
16589
+ const credentials = btoa(`${clientId}:${clientSecret}`);
16590
+ headers.set("Authorization", `Basic ${credentials}`);
16591
+ }
16592
+ function applyPostAuth(clientId, clientSecret, params) {
16593
+ params.set("client_id", clientId);
16594
+ if (clientSecret) {
16595
+ params.set("client_secret", clientSecret);
16596
+ }
16597
+ }
16598
+ function applyPublicAuth(clientId, params) {
16599
+ params.set("client_id", clientId);
16600
+ }
16601
+ async function parseErrorResponse(input) {
16602
+ const statusCode = input instanceof Response ? input.status : void 0;
16603
+ const body = input instanceof Response ? await input.text() : input;
16604
+ try {
16605
+ const result = OAuthErrorResponseSchema.parse(JSON.parse(body));
16606
+ const { error, error_description, error_uri } = result;
16607
+ const errorClass = OAUTH_ERRORS[error] || ServerError;
16608
+ return new errorClass(error_description || "", error_uri);
16609
+ } catch (error) {
16610
+ const errorMessage = `${statusCode ? `HTTP ${statusCode}: ` : ""}Invalid OAuth error response: ${error}. Raw body: ${body}`;
16611
+ return new ServerError(errorMessage);
16612
+ }
16613
+ }
16614
+ async function auth(provider, options) {
16615
+ var _a, _b;
16616
+ try {
16617
+ return await authInternal(provider, options);
16618
+ } catch (error) {
16619
+ if (error instanceof InvalidClientError || error instanceof UnauthorizedClientError) {
16620
+ await ((_a = provider.invalidateCredentials) === null || _a === void 0 ? void 0 : _a.call(provider, "all"));
16621
+ return await authInternal(provider, options);
16622
+ } else if (error instanceof InvalidGrantError) {
16623
+ await ((_b = provider.invalidateCredentials) === null || _b === void 0 ? void 0 : _b.call(provider, "tokens"));
16624
+ return await authInternal(provider, options);
16625
+ }
16626
+ throw error;
16627
+ }
16628
+ }
16629
+ async function authInternal(provider, { serverUrl, authorizationCode, scope, resourceMetadataUrl, fetchFn }) {
16379
16630
  let resourceMetadata;
16380
- let authorizationServerUrl = serverUrl;
16631
+ let authorizationServerUrl;
16381
16632
  try {
16382
- resourceMetadata = await discoverOAuthProtectedResourceMetadata(serverUrl, { resourceMetadataUrl });
16633
+ resourceMetadata = await discoverOAuthProtectedResourceMetadata(serverUrl, { resourceMetadataUrl }, fetchFn);
16383
16634
  if (resourceMetadata.authorization_servers && resourceMetadata.authorization_servers.length > 0) {
16384
16635
  authorizationServerUrl = resourceMetadata.authorization_servers[0];
16385
16636
  }
16386
16637
  } catch (_a) {
16387
16638
  }
16639
+ if (!authorizationServerUrl) {
16640
+ authorizationServerUrl = serverUrl;
16641
+ }
16388
16642
  const resource = await selectResourceURL(serverUrl, provider, resourceMetadata);
16389
- const metadata = await discoverOAuthMetadata(authorizationServerUrl);
16643
+ const metadata = await discoverAuthorizationServerMetadata(authorizationServerUrl, {
16644
+ fetchFn
16645
+ });
16390
16646
  let clientInformation = await Promise.resolve(provider.clientInformation());
16391
16647
  if (!clientInformation) {
16392
16648
  if (authorizationCode !== void 0) {
@@ -16410,7 +16666,9 @@ async function auth(provider, { serverUrl, authorizationCode, scope, resourceMet
16410
16666
  authorizationCode,
16411
16667
  codeVerifier: codeVerifier2,
16412
16668
  redirectUri: provider.redirectUrl,
16413
- resource
16669
+ resource,
16670
+ addClientAuthentication: provider.addClientAuthentication,
16671
+ fetchFn
16414
16672
  });
16415
16673
  await provider.saveTokens(tokens2);
16416
16674
  return "AUTHORIZED";
@@ -16422,11 +16680,16 @@ async function auth(provider, { serverUrl, authorizationCode, scope, resourceMet
16422
16680
  metadata,
16423
16681
  clientInformation,
16424
16682
  refreshToken: tokens.refresh_token,
16425
- resource
16683
+ resource,
16684
+ addClientAuthentication: provider.addClientAuthentication
16426
16685
  });
16427
16686
  await provider.saveTokens(newTokens);
16428
16687
  return "AUTHORIZED";
16429
- } catch (_b) {
16688
+ } catch (error) {
16689
+ if (!(error instanceof OAuthError) || error instanceof ServerError) ;
16690
+ else {
16691
+ throw error;
16692
+ }
16430
16693
  }
16431
16694
  }
16432
16695
  const state = provider.state ? await provider.state() : void 0;
@@ -16475,29 +16738,12 @@ function extractResourceMetadataUrl(res) {
16475
16738
  return void 0;
16476
16739
  }
16477
16740
  }
16478
- async function discoverOAuthProtectedResourceMetadata(serverUrl, opts) {
16479
- var _a;
16480
- let url;
16481
- if (opts === null || opts === void 0 ? void 0 : opts.resourceMetadataUrl) {
16482
- url = new URL(opts === null || opts === void 0 ? void 0 : opts.resourceMetadataUrl);
16483
- } else {
16484
- url = new URL("/.well-known/oauth-protected-resource", serverUrl);
16485
- }
16486
- let response;
16487
- try {
16488
- response = await fetch(url, {
16489
- headers: {
16490
- "MCP-Protocol-Version": (_a = opts === null || opts === void 0 ? void 0 : opts.protocolVersion) !== null && _a !== void 0 ? _a : LATEST_PROTOCOL_VERSION
16491
- }
16492
- });
16493
- } catch (error) {
16494
- if (error instanceof TypeError) {
16495
- response = await fetch(url);
16496
- } else {
16497
- throw error;
16498
- }
16499
- }
16500
- if (response.status === 404) {
16741
+ async function discoverOAuthProtectedResourceMetadata(serverUrl, opts, fetchFn = fetch) {
16742
+ const response = await discoverMetadataWithFallback(serverUrl, "oauth-protected-resource", fetchFn, {
16743
+ protocolVersion: opts === null || opts === void 0 ? void 0 : opts.protocolVersion,
16744
+ metadataUrl: opts === null || opts === void 0 ? void 0 : opts.resourceMetadataUrl
16745
+ });
16746
+ if (!response || response.status === 404) {
16501
16747
  throw new Error(`Resource server does not implement OAuth 2.0 Protected Resource Metadata.`);
16502
16748
  }
16503
16749
  if (!response.ok) {
@@ -16505,13 +16751,13 @@ async function discoverOAuthProtectedResourceMetadata(serverUrl, opts) {
16505
16751
  }
16506
16752
  return OAuthProtectedResourceMetadataSchema.parse(await response.json());
16507
16753
  }
16508
- async function fetchWithCorsRetry(url, headers) {
16754
+ async function fetchWithCorsRetry(url, headers, fetchFn = fetch) {
16509
16755
  try {
16510
- return await fetch(url, { headers });
16756
+ return await fetchFn(url, { headers });
16511
16757
  } catch (error) {
16512
16758
  if (error instanceof TypeError) {
16513
16759
  if (headers) {
16514
- return fetchWithCorsRetry(url);
16760
+ return fetchWithCorsRetry(url, void 0, fetchFn);
16515
16761
  } else {
16516
16762
  return void 0;
16517
16763
  }
@@ -16519,33 +16765,55 @@ async function fetchWithCorsRetry(url, headers) {
16519
16765
  throw error;
16520
16766
  }
16521
16767
  }
16522
- function buildWellKnownPath(pathname) {
16523
- let wellKnownPath = `/.well-known/oauth-authorization-server${pathname}`;
16768
+ function buildWellKnownPath(wellKnownPrefix, pathname = "", options = {}) {
16524
16769
  if (pathname.endsWith("/")) {
16525
- wellKnownPath = wellKnownPath.slice(0, -1);
16770
+ pathname = pathname.slice(0, -1);
16526
16771
  }
16527
- return wellKnownPath;
16772
+ return options.prependPathname ? `${pathname}/.well-known/${wellKnownPrefix}` : `/.well-known/${wellKnownPrefix}${pathname}`;
16528
16773
  }
16529
- async function tryMetadataDiscovery(url, protocolVersion) {
16774
+ async function tryMetadataDiscovery(url, protocolVersion, fetchFn = fetch) {
16530
16775
  const headers = {
16531
16776
  "MCP-Protocol-Version": protocolVersion
16532
16777
  };
16533
- return await fetchWithCorsRetry(url, headers);
16778
+ return await fetchWithCorsRetry(url, headers, fetchFn);
16534
16779
  }
16535
16780
  function shouldAttemptFallback(response, pathname) {
16536
16781
  return !response || response.status === 404 && pathname !== "/";
16537
16782
  }
16538
- async function discoverOAuthMetadata(authorizationServerUrl, opts) {
16539
- var _a;
16540
- const issuer = new URL(authorizationServerUrl);
16541
- const protocolVersion = (_a = void 0) !== null && _a !== void 0 ? _a : LATEST_PROTOCOL_VERSION;
16542
- const wellKnownPath = buildWellKnownPath(issuer.pathname);
16543
- const pathAwareUrl = new URL(wellKnownPath, issuer);
16544
- let response = await tryMetadataDiscovery(pathAwareUrl, protocolVersion);
16545
- if (shouldAttemptFallback(response, issuer.pathname)) {
16546
- const rootUrl = new URL("/.well-known/oauth-authorization-server", issuer);
16547
- response = await tryMetadataDiscovery(rootUrl, protocolVersion);
16783
+ async function discoverMetadataWithFallback(serverUrl, wellKnownType, fetchFn, opts) {
16784
+ var _a, _b;
16785
+ const issuer = new URL(serverUrl);
16786
+ const protocolVersion = (_a = opts === null || opts === void 0 ? void 0 : opts.protocolVersion) !== null && _a !== void 0 ? _a : LATEST_PROTOCOL_VERSION;
16787
+ let url;
16788
+ if (opts === null || opts === void 0 ? void 0 : opts.metadataUrl) {
16789
+ url = new URL(opts.metadataUrl);
16790
+ } else {
16791
+ const wellKnownPath = buildWellKnownPath(wellKnownType, issuer.pathname);
16792
+ url = new URL(wellKnownPath, (_b = opts === null || opts === void 0 ? void 0 : opts.metadataServerUrl) !== null && _b !== void 0 ? _b : issuer);
16793
+ url.search = issuer.search;
16794
+ }
16795
+ let response = await tryMetadataDiscovery(url, protocolVersion, fetchFn);
16796
+ if (!(opts === null || opts === void 0 ? void 0 : opts.metadataUrl) && shouldAttemptFallback(response, issuer.pathname)) {
16797
+ const rootUrl = new URL(`/.well-known/${wellKnownType}`, issuer);
16798
+ response = await tryMetadataDiscovery(rootUrl, protocolVersion, fetchFn);
16799
+ }
16800
+ return response;
16801
+ }
16802
+ async function discoverOAuthMetadata(issuer, { authorizationServerUrl, protocolVersion } = {}, fetchFn = fetch) {
16803
+ if (typeof issuer === "string") {
16804
+ issuer = new URL(issuer);
16805
+ }
16806
+ if (!authorizationServerUrl) {
16807
+ authorizationServerUrl = issuer;
16808
+ }
16809
+ if (typeof authorizationServerUrl === "string") {
16810
+ authorizationServerUrl = new URL(authorizationServerUrl);
16548
16811
  }
16812
+ protocolVersion !== null && protocolVersion !== void 0 ? protocolVersion : protocolVersion = LATEST_PROTOCOL_VERSION;
16813
+ const response = await discoverMetadataWithFallback(authorizationServerUrl, "oauth-authorization-server", fetchFn, {
16814
+ protocolVersion,
16815
+ metadataServerUrl: authorizationServerUrl
16816
+ });
16549
16817
  if (!response || response.status === 404) {
16550
16818
  return void 0;
16551
16819
  }
@@ -16554,6 +16822,70 @@ async function discoverOAuthMetadata(authorizationServerUrl, opts) {
16554
16822
  }
16555
16823
  return OAuthMetadataSchema.parse(await response.json());
16556
16824
  }
16825
+ function buildDiscoveryUrls(authorizationServerUrl) {
16826
+ const url = typeof authorizationServerUrl === "string" ? new URL(authorizationServerUrl) : authorizationServerUrl;
16827
+ const hasPath = url.pathname !== "/";
16828
+ const urlsToTry = [];
16829
+ if (!hasPath) {
16830
+ urlsToTry.push({
16831
+ url: new URL("/.well-known/oauth-authorization-server", url.origin),
16832
+ type: "oauth"
16833
+ });
16834
+ urlsToTry.push({
16835
+ url: new URL(`/.well-known/openid-configuration`, url.origin),
16836
+ type: "oidc"
16837
+ });
16838
+ return urlsToTry;
16839
+ }
16840
+ let pathname = url.pathname;
16841
+ if (pathname.endsWith("/")) {
16842
+ pathname = pathname.slice(0, -1);
16843
+ }
16844
+ urlsToTry.push({
16845
+ url: new URL(`/.well-known/oauth-authorization-server${pathname}`, url.origin),
16846
+ type: "oauth"
16847
+ });
16848
+ urlsToTry.push({
16849
+ url: new URL("/.well-known/oauth-authorization-server", url.origin),
16850
+ type: "oauth"
16851
+ });
16852
+ urlsToTry.push({
16853
+ url: new URL(`/.well-known/openid-configuration${pathname}`, url.origin),
16854
+ type: "oidc"
16855
+ });
16856
+ urlsToTry.push({
16857
+ url: new URL(`${pathname}/.well-known/openid-configuration`, url.origin),
16858
+ type: "oidc"
16859
+ });
16860
+ return urlsToTry;
16861
+ }
16862
+ async function discoverAuthorizationServerMetadata(authorizationServerUrl, { fetchFn = fetch, protocolVersion = LATEST_PROTOCOL_VERSION } = {}) {
16863
+ var _a;
16864
+ const headers = { "MCP-Protocol-Version": protocolVersion };
16865
+ const urlsToTry = buildDiscoveryUrls(authorizationServerUrl);
16866
+ for (const { url: endpointUrl, type: type2 } of urlsToTry) {
16867
+ const response = await fetchWithCorsRetry(endpointUrl, headers, fetchFn);
16868
+ if (!response) {
16869
+ throw new Error(`CORS error trying to load ${type2 === "oauth" ? "OAuth" : "OpenID provider"} metadata from ${endpointUrl}`);
16870
+ }
16871
+ if (!response.ok) {
16872
+ if (response.status >= 400 && response.status < 500) {
16873
+ continue;
16874
+ }
16875
+ throw new Error(`HTTP ${response.status} trying to load ${type2 === "oauth" ? "OAuth" : "OpenID provider"} metadata from ${endpointUrl}`);
16876
+ }
16877
+ if (type2 === "oauth") {
16878
+ return OAuthMetadataSchema.parse(await response.json());
16879
+ } else {
16880
+ const metadata = OpenIdProviderDiscoveryMetadataSchema.parse(await response.json());
16881
+ if (!((_a = metadata.code_challenge_methods_supported) === null || _a === void 0 ? void 0 : _a.includes("S256"))) {
16882
+ throw new Error(`Incompatible OIDC provider at ${endpointUrl}: does not support S256 code challenge method required by MCP specification`);
16883
+ }
16884
+ return metadata;
16885
+ }
16886
+ }
16887
+ return void 0;
16888
+ }
16557
16889
  async function startAuthorization(authorizationServerUrl, { metadata, clientInformation, redirectUrl, scope, state, resource }) {
16558
16890
  const responseType = "code";
16559
16891
  const codeChallengeMethod = "S256";
@@ -16583,48 +16915,53 @@ async function startAuthorization(authorizationServerUrl, { metadata, clientInfo
16583
16915
  if (scope) {
16584
16916
  authorizationUrl.searchParams.set("scope", scope);
16585
16917
  }
16918
+ if (scope === null || scope === void 0 ? void 0 : scope.includes("offline_access")) {
16919
+ authorizationUrl.searchParams.append("prompt", "consent");
16920
+ }
16586
16921
  if (resource) {
16587
16922
  authorizationUrl.searchParams.set("resource", resource.href);
16588
16923
  }
16589
16924
  return { authorizationUrl, codeVerifier };
16590
16925
  }
16591
- async function exchangeAuthorization(authorizationServerUrl, { metadata, clientInformation, authorizationCode, codeVerifier, redirectUri, resource }) {
16926
+ async function exchangeAuthorization(authorizationServerUrl, { metadata, clientInformation, authorizationCode, codeVerifier, redirectUri, resource, addClientAuthentication, fetchFn }) {
16927
+ var _a;
16592
16928
  const grantType = "authorization_code";
16593
- let tokenUrl;
16594
- if (metadata) {
16595
- tokenUrl = new URL(metadata.token_endpoint);
16596
- if (metadata.grant_types_supported && !metadata.grant_types_supported.includes(grantType)) {
16597
- throw new Error(`Incompatible auth server: does not support grant type ${grantType}`);
16598
- }
16599
- } else {
16600
- tokenUrl = new URL("/token", authorizationServerUrl);
16929
+ const tokenUrl = (metadata === null || metadata === void 0 ? void 0 : metadata.token_endpoint) ? new URL(metadata.token_endpoint) : new URL("/token", authorizationServerUrl);
16930
+ if ((metadata === null || metadata === void 0 ? void 0 : metadata.grant_types_supported) && !metadata.grant_types_supported.includes(grantType)) {
16931
+ throw new Error(`Incompatible auth server: does not support grant type ${grantType}`);
16601
16932
  }
16933
+ const headers = new Headers({
16934
+ "Content-Type": "application/x-www-form-urlencoded",
16935
+ "Accept": "application/json"
16936
+ });
16602
16937
  const params = new URLSearchParams({
16603
16938
  grant_type: grantType,
16604
- client_id: clientInformation.client_id,
16605
16939
  code: authorizationCode,
16606
16940
  code_verifier: codeVerifier,
16607
16941
  redirect_uri: String(redirectUri)
16608
16942
  });
16609
- if (clientInformation.client_secret) {
16610
- params.set("client_secret", clientInformation.client_secret);
16943
+ if (addClientAuthentication) {
16944
+ addClientAuthentication(headers, params, authorizationServerUrl, metadata);
16945
+ } else {
16946
+ const supportedMethods = (_a = metadata === null || metadata === void 0 ? void 0 : metadata.token_endpoint_auth_methods_supported) !== null && _a !== void 0 ? _a : [];
16947
+ const authMethod = selectClientAuthMethod(clientInformation, supportedMethods);
16948
+ applyClientAuthentication(authMethod, clientInformation, headers, params);
16611
16949
  }
16612
16950
  if (resource) {
16613
16951
  params.set("resource", resource.href);
16614
16952
  }
16615
- const response = await fetch(tokenUrl, {
16953
+ const response = await (fetchFn !== null && fetchFn !== void 0 ? fetchFn : fetch)(tokenUrl, {
16616
16954
  method: "POST",
16617
- headers: {
16618
- "Content-Type": "application/x-www-form-urlencoded"
16619
- },
16955
+ headers,
16620
16956
  body: params
16621
16957
  });
16622
16958
  if (!response.ok) {
16623
- throw new Error(`Token exchange failed: HTTP ${response.status}`);
16959
+ throw await parseErrorResponse(response);
16624
16960
  }
16625
16961
  return OAuthTokensSchema.parse(await response.json());
16626
16962
  }
16627
- async function refreshAuthorization(authorizationServerUrl, { metadata, clientInformation, refreshToken, resource }) {
16963
+ async function refreshAuthorization(authorizationServerUrl, { metadata, clientInformation, refreshToken, resource, addClientAuthentication, fetchFn }) {
16964
+ var _a;
16628
16965
  const grantType = "refresh_token";
16629
16966
  let tokenUrl;
16630
16967
  if (metadata) {
@@ -16635,30 +16972,34 @@ async function refreshAuthorization(authorizationServerUrl, { metadata, clientIn
16635
16972
  } else {
16636
16973
  tokenUrl = new URL("/token", authorizationServerUrl);
16637
16974
  }
16975
+ const headers = new Headers({
16976
+ "Content-Type": "application/x-www-form-urlencoded"
16977
+ });
16638
16978
  const params = new URLSearchParams({
16639
16979
  grant_type: grantType,
16640
- client_id: clientInformation.client_id,
16641
16980
  refresh_token: refreshToken
16642
16981
  });
16643
- if (clientInformation.client_secret) {
16644
- params.set("client_secret", clientInformation.client_secret);
16982
+ if (addClientAuthentication) {
16983
+ addClientAuthentication(headers, params, authorizationServerUrl, metadata);
16984
+ } else {
16985
+ const supportedMethods = (_a = metadata === null || metadata === void 0 ? void 0 : metadata.token_endpoint_auth_methods_supported) !== null && _a !== void 0 ? _a : [];
16986
+ const authMethod = selectClientAuthMethod(clientInformation, supportedMethods);
16987
+ applyClientAuthentication(authMethod, clientInformation, headers, params);
16645
16988
  }
16646
16989
  if (resource) {
16647
16990
  params.set("resource", resource.href);
16648
16991
  }
16649
- const response = await fetch(tokenUrl, {
16992
+ const response = await (fetchFn !== null && fetchFn !== void 0 ? fetchFn : fetch)(tokenUrl, {
16650
16993
  method: "POST",
16651
- headers: {
16652
- "Content-Type": "application/x-www-form-urlencoded"
16653
- },
16994
+ headers,
16654
16995
  body: params
16655
16996
  });
16656
16997
  if (!response.ok) {
16657
- throw new Error(`Token refresh failed: HTTP ${response.status}`);
16998
+ throw await parseErrorResponse(response);
16658
16999
  }
16659
17000
  return OAuthTokensSchema.parse({ refresh_token: refreshToken, ...await response.json() });
16660
17001
  }
16661
- async function registerClient(authorizationServerUrl, { metadata, clientMetadata }) {
17002
+ async function registerClient(authorizationServerUrl, { metadata, clientMetadata, fetchFn }) {
16662
17003
  let registrationUrl;
16663
17004
  if (metadata) {
16664
17005
  if (!metadata.registration_endpoint) {
@@ -16668,7 +17009,7 @@ async function registerClient(authorizationServerUrl, { metadata, clientMetadata
16668
17009
  } else {
16669
17010
  registrationUrl = new URL("/register", authorizationServerUrl);
16670
17011
  }
16671
- const response = await fetch(registrationUrl, {
17012
+ const response = await (fetchFn !== null && fetchFn !== void 0 ? fetchFn : fetch)(registrationUrl, {
16672
17013
  method: "POST",
16673
17014
  headers: {
16674
17015
  "Content-Type": "application/json"
@@ -16676,7 +17017,7 @@ async function registerClient(authorizationServerUrl, { metadata, clientMetadata
16676
17017
  body: JSON.stringify(clientMetadata)
16677
17018
  });
16678
17019
  if (!response.ok) {
16679
- throw new Error(`Dynamic client registration failed: HTTP ${response.status}`);
17020
+ throw await parseErrorResponse(response);
16680
17021
  }
16681
17022
  return OAuthClientInformationFullSchema.parse(await response.json());
16682
17023
  }
@@ -22960,6 +23301,7 @@ class Protocol {
22960
23301
  this._responseHandlers = /* @__PURE__ */ new Map();
22961
23302
  this._progressHandlers = /* @__PURE__ */ new Map();
22962
23303
  this._timeoutInfo = /* @__PURE__ */ new Map();
23304
+ this._pendingDebouncedNotifications = /* @__PURE__ */ new Set();
22963
23305
  this.setNotificationHandler(CancelledNotificationSchema, (notification) => {
22964
23306
  const controller = this._requestHandlerAbortControllers.get(notification.params.requestId);
22965
23307
  controller === null || controller === void 0 ? void 0 : controller.abort(notification.params.reason);
@@ -23041,6 +23383,7 @@ class Protocol {
23041
23383
  const responseHandlers = this._responseHandlers;
23042
23384
  this._responseHandlers = /* @__PURE__ */ new Map();
23043
23385
  this._progressHandlers.clear();
23386
+ this._pendingDebouncedNotifications.clear();
23044
23387
  this._transport = void 0;
23045
23388
  (_a = this.onclose) === null || _a === void 0 ? void 0 : _a.call(this);
23046
23389
  const error = new McpError(ErrorCode.ConnectionClosed, "Connection closed");
@@ -23240,10 +23583,32 @@ class Protocol {
23240
23583
  * Emits a notification, which is a one-way message that does not expect a response.
23241
23584
  */
23242
23585
  async notification(notification, options) {
23586
+ var _a, _b;
23243
23587
  if (!this._transport) {
23244
23588
  throw new Error("Not connected");
23245
23589
  }
23246
23590
  this.assertNotificationCapability(notification.method);
23591
+ const debouncedMethods = (_b = (_a = this._options) === null || _a === void 0 ? void 0 : _a.debouncedNotificationMethods) !== null && _b !== void 0 ? _b : [];
23592
+ const canDebounce = debouncedMethods.includes(notification.method) && !notification.params && !(options === null || options === void 0 ? void 0 : options.relatedRequestId);
23593
+ if (canDebounce) {
23594
+ if (this._pendingDebouncedNotifications.has(notification.method)) {
23595
+ return;
23596
+ }
23597
+ this._pendingDebouncedNotifications.add(notification.method);
23598
+ Promise.resolve().then(() => {
23599
+ var _a2;
23600
+ this._pendingDebouncedNotifications.delete(notification.method);
23601
+ if (!this._transport) {
23602
+ return;
23603
+ }
23604
+ const jsonrpcNotification2 = {
23605
+ ...notification,
23606
+ jsonrpc: "2.0"
23607
+ };
23608
+ (_a2 = this._transport) === null || _a2 === void 0 ? void 0 : _a2.send(jsonrpcNotification2, options).catch((error) => this._onerror(error));
23609
+ });
23610
+ return;
23611
+ }
23247
23612
  const jsonrpcNotification = {
23248
23613
  ...notification,
23249
23614
  jsonrpc: "2.0"
@@ -23918,7 +24283,7 @@ class SSEClientTransport {
23918
24283
  }
23919
24284
  let result;
23920
24285
  try {
23921
- result = await auth(this._authProvider, { serverUrl: this._url, resourceMetadataUrl: this._resourceMetadataUrl });
24286
+ result = await auth(this._authProvider, { serverUrl: this._url, resourceMetadataUrl: this._resourceMetadataUrl, fetchFn: this._fetch });
23922
24287
  } catch (error) {
23923
24288
  (_a = this.onerror) === null || _a === void 0 ? void 0 : _a.call(this, error);
23924
24289
  throw error;
@@ -23930,9 +24295,7 @@ class SSEClientTransport {
23930
24295
  }
23931
24296
  async _commonHeaders() {
23932
24297
  var _a;
23933
- const headers = {
23934
- ...(_a = this._requestInit) === null || _a === void 0 ? void 0 : _a.headers
23935
- };
24298
+ const headers = {};
23936
24299
  if (this._authProvider) {
23937
24300
  const tokens = await this._authProvider.tokens();
23938
24301
  if (tokens) {
@@ -23942,7 +24305,7 @@ class SSEClientTransport {
23942
24305
  if (this._protocolVersion) {
23943
24306
  headers["mcp-protocol-version"] = this._protocolVersion;
23944
24307
  }
23945
- return headers;
24308
+ return new Headers({ ...headers, ...(_a = this._requestInit) === null || _a === void 0 ? void 0 : _a.headers });
23946
24309
  }
23947
24310
  _startOrAuth() {
23948
24311
  var _a, _b, _c;
@@ -23952,12 +24315,10 @@ class SSEClientTransport {
23952
24315
  ...this._eventSourceInit,
23953
24316
  fetch: async (url, init) => {
23954
24317
  const headers = await this._commonHeaders();
24318
+ headers.set("Accept", "text/event-stream");
23955
24319
  const response = await fetchImpl(url, {
23956
24320
  ...init,
23957
- headers: new Headers({
23958
- ...headers,
23959
- Accept: "text/event-stream"
23960
- })
24321
+ headers
23961
24322
  });
23962
24323
  if (response.status === 401 && response.headers.has("www-authenticate")) {
23963
24324
  this._resourceMetadataUrl = extractResourceMetadataUrl(response);
@@ -24021,7 +24382,7 @@ class SSEClientTransport {
24021
24382
  if (!this._authProvider) {
24022
24383
  throw new UnauthorizedError("No auth provider");
24023
24384
  }
24024
- const result = await auth(this._authProvider, { serverUrl: this._url, authorizationCode, resourceMetadataUrl: this._resourceMetadataUrl });
24385
+ const result = await auth(this._authProvider, { serverUrl: this._url, authorizationCode, resourceMetadataUrl: this._resourceMetadataUrl, fetchFn: this._fetch });
24025
24386
  if (result !== "AUTHORIZED") {
24026
24387
  throw new UnauthorizedError("Failed to authorize");
24027
24388
  }
@@ -24038,8 +24399,7 @@ class SSEClientTransport {
24038
24399
  throw new Error("Not connected");
24039
24400
  }
24040
24401
  try {
24041
- const commonHeaders = await this._commonHeaders();
24042
- const headers = new Headers(commonHeaders);
24402
+ const headers = await this._commonHeaders();
24043
24403
  headers.set("content-type", "application/json");
24044
24404
  const init = {
24045
24405
  ...this._requestInit,
@@ -24052,7 +24412,7 @@ class SSEClientTransport {
24052
24412
  if (!response.ok) {
24053
24413
  if (response.status === 401 && this._authProvider) {
24054
24414
  this._resourceMetadataUrl = extractResourceMetadataUrl(response);
24055
- const result = await auth(this._authProvider, { serverUrl: this._url, resourceMetadataUrl: this._resourceMetadataUrl });
24415
+ const result = await auth(this._authProvider, { serverUrl: this._url, resourceMetadataUrl: this._resourceMetadataUrl, fetchFn: this._fetch });
24056
24416
  if (result !== "AUTHORIZED") {
24057
24417
  throw new UnauthorizedError();
24058
24418
  }
@@ -24122,7 +24482,7 @@ class StreamableHTTPClientTransport {
24122
24482
  }
24123
24483
  let result;
24124
24484
  try {
24125
- result = await auth(this._authProvider, { serverUrl: this._url, resourceMetadataUrl: this._resourceMetadataUrl });
24485
+ result = await auth(this._authProvider, { serverUrl: this._url, resourceMetadataUrl: this._resourceMetadataUrl, fetchFn: this._fetch });
24126
24486
  } catch (error) {
24127
24487
  (_a = this.onerror) === null || _a === void 0 ? void 0 : _a.call(this, error);
24128
24488
  throw error;
@@ -24176,7 +24536,7 @@ class StreamableHTTPClientTransport {
24176
24536
  }
24177
24537
  throw new StreamableHTTPError(response.status, `Failed to open SSE stream: ${response.statusText}`);
24178
24538
  }
24179
- this._handleSseStream(response.body, options);
24539
+ this._handleSseStream(response.body, options, true);
24180
24540
  } catch (error) {
24181
24541
  (_c = this.onerror) === null || _c === void 0 ? void 0 : _c.call(this, error);
24182
24542
  throw error;
@@ -24227,7 +24587,7 @@ class StreamableHTTPClientTransport {
24227
24587
  });
24228
24588
  }, delay);
24229
24589
  }
24230
- _handleSseStream(stream, options) {
24590
+ _handleSseStream(stream, options, isReconnectable) {
24231
24591
  if (!stream) {
24232
24592
  return;
24233
24593
  }
@@ -24260,17 +24620,15 @@ class StreamableHTTPClientTransport {
24260
24620
  }
24261
24621
  } catch (error) {
24262
24622
  (_c = this.onerror) === null || _c === void 0 ? void 0 : _c.call(this, new Error(`SSE stream disconnected: ${error}`));
24263
- if (this._abortController && !this._abortController.signal.aborted) {
24264
- if (lastEventId !== void 0) {
24265
- try {
24266
- this._scheduleReconnection({
24267
- resumptionToken: lastEventId,
24268
- onresumptiontoken,
24269
- replayMessageId
24270
- }, 0);
24271
- } catch (error2) {
24272
- (_d = this.onerror) === null || _d === void 0 ? void 0 : _d.call(this, new Error(`Failed to reconnect: ${error2 instanceof Error ? error2.message : String(error2)}`));
24273
- }
24623
+ if (isReconnectable && this._abortController && !this._abortController.signal.aborted) {
24624
+ try {
24625
+ this._scheduleReconnection({
24626
+ resumptionToken: lastEventId,
24627
+ onresumptiontoken,
24628
+ replayMessageId
24629
+ }, 0);
24630
+ } catch (error2) {
24631
+ (_d = this.onerror) === null || _d === void 0 ? void 0 : _d.call(this, new Error(`Failed to reconnect: ${error2 instanceof Error ? error2.message : String(error2)}`));
24274
24632
  }
24275
24633
  }
24276
24634
  }
@@ -24290,7 +24648,7 @@ class StreamableHTTPClientTransport {
24290
24648
  if (!this._authProvider) {
24291
24649
  throw new UnauthorizedError("No auth provider");
24292
24650
  }
24293
- const result = await auth(this._authProvider, { serverUrl: this._url, authorizationCode, resourceMetadataUrl: this._resourceMetadataUrl });
24651
+ const result = await auth(this._authProvider, { serverUrl: this._url, authorizationCode, resourceMetadataUrl: this._resourceMetadataUrl, fetchFn: this._fetch });
24294
24652
  if (result !== "AUTHORIZED") {
24295
24653
  throw new UnauthorizedError("Failed to authorize");
24296
24654
  }
@@ -24329,7 +24687,7 @@ class StreamableHTTPClientTransport {
24329
24687
  if (!response.ok) {
24330
24688
  if (response.status === 401 && this._authProvider) {
24331
24689
  this._resourceMetadataUrl = extractResourceMetadataUrl(response);
24332
- const result = await auth(this._authProvider, { serverUrl: this._url, resourceMetadataUrl: this._resourceMetadataUrl });
24690
+ const result = await auth(this._authProvider, { serverUrl: this._url, resourceMetadataUrl: this._resourceMetadataUrl, fetchFn: this._fetch });
24333
24691
  if (result !== "AUTHORIZED") {
24334
24692
  throw new UnauthorizedError();
24335
24693
  }
@@ -24352,7 +24710,7 @@ class StreamableHTTPClientTransport {
24352
24710
  const contentType = response.headers.get("content-type");
24353
24711
  if (hasRequests) {
24354
24712
  if (contentType === null || contentType === void 0 ? void 0 : contentType.includes("text/event-stream")) {
24355
- this._handleSseStream(response.body, { onresumptiontoken });
24713
+ this._handleSseStream(response.body, { onresumptiontoken }, false);
24356
24714
  } else if (contentType === null || contentType === void 0 ? void 0 : contentType.includes("application/json")) {
24357
24715
  const data2 = await response.json();
24358
24716
  const responseMessages = Array.isArray(data2) ? data2.map((msg) => JSONRPCMessageSchema.parse(msg)) : [JSONRPCMessageSchema.parse(data2)];
@@ -24421,7 +24779,7 @@ const StdErrNotificationSchema = NotificationSchema.extend({
24421
24779
  ClientNotificationSchema.or(
24422
24780
  StdErrNotificationSchema
24423
24781
  ).or(ServerNotificationSchema).or(NotificationSchema);
24424
- const version$1 = "0.16.0";
24782
+ const version$1 = "0.16.2";
24425
24783
  const packageJson = {
24426
24784
  version: version$1
24427
24785
  };
@@ -24549,10 +24907,13 @@ function useConnection({
24549
24907
  env,
24550
24908
  bearerToken,
24551
24909
  headerName,
24910
+ oauthClientId,
24911
+ oauthScope,
24552
24912
  config,
24553
24913
  onNotification,
24554
24914
  onStdErrNotification,
24555
24915
  onPendingRequest,
24916
+ onElicitationRequest,
24556
24917
  getRoots
24557
24918
  }) {
24558
24919
  const [connectionStatus, setConnectionStatus] = reactExports.useState("disconnected");
@@ -24563,7 +24924,21 @@ function useConnection({
24563
24924
  null
24564
24925
  );
24565
24926
  const [requestHistory, setRequestHistory] = reactExports.useState([]);
24566
- const [completionsSupported, setCompletionsSupported] = reactExports.useState(true);
24927
+ const [completionsSupported, setCompletionsSupported] = reactExports.useState(false);
24928
+ reactExports.useEffect(() => {
24929
+ if (!oauthClientId) {
24930
+ clearClientInformationFromSessionStorage({
24931
+ serverUrl: sseUrl,
24932
+ isPreregistered: true
24933
+ });
24934
+ return;
24935
+ }
24936
+ saveClientInformationToSessionStorage({
24937
+ serverUrl: sseUrl,
24938
+ clientInformation: { client_id: oauthClientId },
24939
+ isPreregistered: true
24940
+ });
24941
+ }, [oauthClientId, sseUrl]);
24567
24942
  const pushHistory = (request, response) => {
24568
24943
  setRequestHistory((prev) => [
24569
24944
  ...prev,
@@ -24702,7 +25077,10 @@ function useConnection({
24702
25077
  const handleAuthError = async (error) => {
24703
25078
  if (is401Error(error)) {
24704
25079
  const serverAuthProvider = new InspectorOAuthClientProvider(sseUrl);
24705
- const result = await auth(serverAuthProvider, { serverUrl: sseUrl });
25080
+ const result = await auth(serverAuthProvider, {
25081
+ serverUrl: sseUrl,
25082
+ scope: oauthScope
25083
+ });
24706
25084
  return result === "AUTHORIZED";
24707
25085
  }
24708
25086
  return false;
@@ -24717,6 +25095,7 @@ function useConnection({
24717
25095
  {
24718
25096
  capabilities: {
24719
25097
  sampling: {},
25098
+ elicitation: {},
24720
25099
  roots: {
24721
25100
  listChanged: true
24722
25101
  }
@@ -24876,7 +25255,7 @@ function useConnection({
24876
25255
  throw error;
24877
25256
  }
24878
25257
  setServerCapabilities(capabilities ?? null);
24879
- setCompletionsSupported(true);
25258
+ setCompletionsSupported((capabilities == null ? void 0 : capabilities.completions) !== void 0);
24880
25259
  if (onPendingRequest) {
24881
25260
  client2.setRequestHandler(CreateMessageRequestSchema, (request) => {
24882
25261
  return new Promise((resolve, reject) => {
@@ -24889,6 +25268,13 @@ function useConnection({
24889
25268
  return { roots: getRoots() };
24890
25269
  });
24891
25270
  }
25271
+ if (onElicitationRequest) {
25272
+ client2.setRequestHandler(ElicitRequestSchema, async (request) => {
25273
+ return new Promise((resolve) => {
25274
+ onElicitationRequest(request, resolve);
25275
+ });
25276
+ });
25277
+ }
24892
25278
  setMcpClient(client2);
24893
25279
  setConnectionStatus("connected");
24894
25280
  } catch (e) {
@@ -33945,10 +34331,10 @@ const JsonEditor = ({
33945
34331
  };
33946
34332
  const isSimpleObject = (schema) => {
33947
34333
  const supportedTypes = ["string", "number", "integer", "boolean", "null"];
33948
- if (supportedTypes.includes(schema.type)) return true;
34334
+ if (schema.type && supportedTypes.includes(schema.type)) return true;
33949
34335
  if (schema.type === "object") {
33950
34336
  return Object.values(schema.properties ?? {}).every(
33951
- (prop) => supportedTypes.includes(prop.type)
34337
+ (prop) => prop.type && supportedTypes.includes(prop.type)
33952
34338
  );
33953
34339
  }
33954
34340
  if (schema.type === "array") {
@@ -34072,20 +34458,95 @@ const DynamicJsonForm = ({
34072
34458
  }
34073
34459
  const isRequired = ((_a = parentSchema == null ? void 0 : parentSchema.required) == null ? void 0 : _a.includes(propertyName || "")) ?? false;
34074
34460
  switch (propSchema.type) {
34075
- case "string":
34461
+ case "string": {
34462
+ if (propSchema.oneOf && propSchema.oneOf.every(
34463
+ (option) => typeof option.const === "string" && typeof option.title === "string"
34464
+ )) {
34465
+ return /* @__PURE__ */ jsxRuntimeExports.jsxs(
34466
+ "select",
34467
+ {
34468
+ value: currentValue ?? "",
34469
+ onChange: (e) => {
34470
+ const val = e.target.value;
34471
+ if (!val && !isRequired) {
34472
+ handleFieldChange(path, void 0);
34473
+ } else {
34474
+ handleFieldChange(path, val);
34475
+ }
34476
+ },
34477
+ required: isRequired,
34478
+ className: "w-full px-3 py-2 border border-gray-300 rounded-md focus:outline-none focus:ring-2 focus:ring-blue-500 dark:border-gray-600 dark:bg-gray-800",
34479
+ children: [
34480
+ /* @__PURE__ */ jsxRuntimeExports.jsx("option", { value: "", children: "Select an option..." }),
34481
+ propSchema.oneOf.map((option) => /* @__PURE__ */ jsxRuntimeExports.jsx(
34482
+ "option",
34483
+ {
34484
+ value: option.const,
34485
+ children: option.title
34486
+ },
34487
+ option.const
34488
+ ))
34489
+ ]
34490
+ }
34491
+ );
34492
+ }
34493
+ if (propSchema.enum) {
34494
+ return /* @__PURE__ */ jsxRuntimeExports.jsxs(
34495
+ "select",
34496
+ {
34497
+ value: currentValue ?? "",
34498
+ onChange: (e) => {
34499
+ const val = e.target.value;
34500
+ if (!val && !isRequired) {
34501
+ handleFieldChange(path, void 0);
34502
+ } else {
34503
+ handleFieldChange(path, val);
34504
+ }
34505
+ },
34506
+ required: isRequired,
34507
+ className: "w-full px-3 py-2 border border-gray-300 rounded-md focus:outline-none focus:ring-2 focus:ring-blue-500 dark:border-gray-600 dark:bg-gray-800",
34508
+ children: [
34509
+ /* @__PURE__ */ jsxRuntimeExports.jsx("option", { value: "", children: "Select an option..." }),
34510
+ propSchema.enum.map((option) => /* @__PURE__ */ jsxRuntimeExports.jsx("option", { value: option, children: option }, option))
34511
+ ]
34512
+ }
34513
+ );
34514
+ }
34515
+ let inputType = "text";
34516
+ switch (propSchema.format) {
34517
+ case "email":
34518
+ inputType = "email";
34519
+ break;
34520
+ case "uri":
34521
+ inputType = "url";
34522
+ break;
34523
+ case "date":
34524
+ inputType = "date";
34525
+ break;
34526
+ case "date-time":
34527
+ inputType = "datetime-local";
34528
+ break;
34529
+ default:
34530
+ inputType = "text";
34531
+ break;
34532
+ }
34076
34533
  return /* @__PURE__ */ jsxRuntimeExports.jsx(
34077
34534
  Input,
34078
34535
  {
34079
- type: "text",
34536
+ type: inputType,
34080
34537
  value: currentValue ?? "",
34081
34538
  onChange: (e) => {
34082
34539
  const val = e.target.value;
34083
34540
  handleFieldChange(path, val);
34084
34541
  },
34085
34542
  placeholder: propSchema.description,
34086
- required: isRequired
34543
+ required: isRequired,
34544
+ minLength: propSchema.minLength,
34545
+ maxLength: propSchema.maxLength,
34546
+ pattern: propSchema.pattern
34087
34547
  }
34088
34548
  );
34549
+ }
34089
34550
  case "number":
34090
34551
  return /* @__PURE__ */ jsxRuntimeExports.jsx(
34091
34552
  Input,
@@ -34104,7 +34565,9 @@ const DynamicJsonForm = ({
34104
34565
  }
34105
34566
  },
34106
34567
  placeholder: propSchema.description,
34107
- required: isRequired
34568
+ required: isRequired,
34569
+ min: propSchema.minimum,
34570
+ max: propSchema.maximum
34108
34571
  }
34109
34572
  );
34110
34573
  case "integer":
@@ -34126,7 +34589,9 @@ const DynamicJsonForm = ({
34126
34589
  }
34127
34590
  },
34128
34591
  placeholder: propSchema.description,
34129
- required: isRequired
34592
+ required: isRequired,
34593
+ min: propSchema.minimum,
34594
+ max: propSchema.maximum
34130
34595
  }
34131
34596
  );
34132
34597
  case "boolean":
@@ -35798,7 +36263,7 @@ const useTheme = () => {
35798
36263
  [theme, setThemeWithSideEffect]
35799
36264
  );
35800
36265
  };
35801
- const version = "0.16.0";
36266
+ const version = "0.16.2";
35802
36267
  var [createTooltipContext, createTooltipScope] = createContextScope("Tooltip", [
35803
36268
  createPopperScope
35804
36269
  ]);
@@ -36297,6 +36762,10 @@ const Sidebar = ({
36297
36762
  setBearerToken,
36298
36763
  headerName,
36299
36764
  setHeaderName,
36765
+ oauthClientId,
36766
+ setOauthClientId,
36767
+ oauthScope,
36768
+ setOauthScope,
36300
36769
  onConnect,
36301
36770
  onDisconnect,
36302
36771
  stdErrNotifications,
@@ -36309,7 +36778,7 @@ const Sidebar = ({
36309
36778
  }) => {
36310
36779
  const [theme, setTheme] = useTheme();
36311
36780
  const [showEnvVars, setShowEnvVars] = reactExports.useState(false);
36312
- const [showBearerToken, setShowBearerToken] = reactExports.useState(false);
36781
+ const [showAuthConfig, setShowAuthConfig] = reactExports.useState(false);
36313
36782
  const [showConfig, setShowConfig] = reactExports.useState(false);
36314
36783
  const [shownEnvVars, setShownEnvVars] = reactExports.useState(/* @__PURE__ */ new Set());
36315
36784
  const [copiedServerEntry, setCopiedServerEntry] = reactExports.useState(false);
@@ -36466,22 +36935,10 @@ const Sidebar = ({
36466
36935
  }
36467
36936
  )
36468
36937
  ] })
36469
- ] }) : /* @__PURE__ */ jsxRuntimeExports.jsxs(jsxRuntimeExports.Fragment, { children: [
36470
- /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "space-y-2", children: [
36471
- /* @__PURE__ */ jsxRuntimeExports.jsx("label", { className: "text-sm font-medium", htmlFor: "sse-url-input", children: "URL" }),
36472
- sseUrl ? /* @__PURE__ */ jsxRuntimeExports.jsxs(Tooltip, { children: [
36473
- /* @__PURE__ */ jsxRuntimeExports.jsx(TooltipTrigger, { asChild: true, children: /* @__PURE__ */ jsxRuntimeExports.jsx(
36474
- Input,
36475
- {
36476
- id: "sse-url-input",
36477
- placeholder: "URL",
36478
- value: sseUrl,
36479
- onChange: (e) => setSseUrl(e.target.value),
36480
- className: "font-mono"
36481
- }
36482
- ) }),
36483
- /* @__PURE__ */ jsxRuntimeExports.jsx(TooltipContent, { children: sseUrl })
36484
- ] }) : /* @__PURE__ */ jsxRuntimeExports.jsx(
36938
+ ] }) : /* @__PURE__ */ jsxRuntimeExports.jsx(jsxRuntimeExports.Fragment, { children: /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "space-y-2", children: [
36939
+ /* @__PURE__ */ jsxRuntimeExports.jsx("label", { className: "text-sm font-medium", htmlFor: "sse-url-input", children: "URL" }),
36940
+ sseUrl ? /* @__PURE__ */ jsxRuntimeExports.jsxs(Tooltip, { children: [
36941
+ /* @__PURE__ */ jsxRuntimeExports.jsx(TooltipTrigger, { asChild: true, children: /* @__PURE__ */ jsxRuntimeExports.jsx(
36485
36942
  Input,
36486
36943
  {
36487
36944
  id: "sse-url-input",
@@ -36490,58 +36947,19 @@ const Sidebar = ({
36490
36947
  onChange: (e) => setSseUrl(e.target.value),
36491
36948
  className: "font-mono"
36492
36949
  }
36493
- )
36494
- ] }),
36495
- /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "space-y-2", children: [
36496
- /* @__PURE__ */ jsxRuntimeExports.jsxs(
36497
- Button,
36498
- {
36499
- variant: "outline",
36500
- onClick: () => setShowBearerToken(!showBearerToken),
36501
- className: "flex items-center w-full",
36502
- "data-testid": "auth-button",
36503
- "aria-expanded": showBearerToken,
36504
- children: [
36505
- showBearerToken ? /* @__PURE__ */ jsxRuntimeExports.jsx(ChevronDown, { className: "w-4 h-4 mr-2" }) : /* @__PURE__ */ jsxRuntimeExports.jsx(ChevronRight, { className: "w-4 h-4 mr-2" }),
36506
- "Authentication"
36507
- ]
36508
- }
36509
- ),
36510
- showBearerToken && /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "space-y-2", children: [
36511
- /* @__PURE__ */ jsxRuntimeExports.jsx("label", { className: "text-sm font-medium", children: "Header Name" }),
36512
- /* @__PURE__ */ jsxRuntimeExports.jsx(
36513
- Input,
36514
- {
36515
- placeholder: "Authorization",
36516
- onChange: (e) => setHeaderName && setHeaderName(e.target.value),
36517
- "data-testid": "header-input",
36518
- className: "font-mono",
36519
- value: headerName
36520
- }
36521
- ),
36522
- /* @__PURE__ */ jsxRuntimeExports.jsx(
36523
- "label",
36524
- {
36525
- className: "text-sm font-medium",
36526
- htmlFor: "bearer-token-input",
36527
- children: "Bearer Token"
36528
- }
36529
- ),
36530
- /* @__PURE__ */ jsxRuntimeExports.jsx(
36531
- Input,
36532
- {
36533
- id: "bearer-token-input",
36534
- placeholder: "Bearer Token",
36535
- value: bearerToken,
36536
- onChange: (e) => setBearerToken(e.target.value),
36537
- "data-testid": "bearer-token-input",
36538
- className: "font-mono",
36539
- type: "password"
36540
- }
36541
- )
36542
- ] })
36543
- ] })
36544
- ] }),
36950
+ ) }),
36951
+ /* @__PURE__ */ jsxRuntimeExports.jsx(TooltipContent, { children: sseUrl })
36952
+ ] }) : /* @__PURE__ */ jsxRuntimeExports.jsx(
36953
+ Input,
36954
+ {
36955
+ id: "sse-url-input",
36956
+ placeholder: "URL",
36957
+ value: sseUrl,
36958
+ onChange: (e) => setSseUrl(e.target.value),
36959
+ className: "font-mono"
36960
+ }
36961
+ )
36962
+ ] }) }),
36545
36963
  transportType === "stdio" && /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "space-y-2", children: [
36546
36964
  /* @__PURE__ */ jsxRuntimeExports.jsxs(
36547
36965
  Button,
@@ -36697,6 +37115,98 @@ const Sidebar = ({
36697
37115
  /* @__PURE__ */ jsxRuntimeExports.jsx(TooltipContent, { children: "Copy Servers File" })
36698
37116
  ] })
36699
37117
  ] }),
37118
+ /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "space-y-2", children: [
37119
+ /* @__PURE__ */ jsxRuntimeExports.jsxs(
37120
+ Button,
37121
+ {
37122
+ variant: "outline",
37123
+ onClick: () => setShowAuthConfig(!showAuthConfig),
37124
+ className: "flex items-center w-full",
37125
+ "data-testid": "auth-button",
37126
+ "aria-expanded": showAuthConfig,
37127
+ children: [
37128
+ showAuthConfig ? /* @__PURE__ */ jsxRuntimeExports.jsx(ChevronDown, { className: "w-4 h-4 mr-2" }) : /* @__PURE__ */ jsxRuntimeExports.jsx(ChevronRight, { className: "w-4 h-4 mr-2" }),
37129
+ "Authentication"
37130
+ ]
37131
+ }
37132
+ ),
37133
+ showAuthConfig && /* @__PURE__ */ jsxRuntimeExports.jsxs(jsxRuntimeExports.Fragment, { children: [
37134
+ /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "space-y-2 p-3 rounded border", children: [
37135
+ /* @__PURE__ */ jsxRuntimeExports.jsx("h4", { className: "text-sm font-semibold flex items-center", children: "API Token Authentication" }),
37136
+ /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "space-y-2", children: [
37137
+ /* @__PURE__ */ jsxRuntimeExports.jsx("label", { className: "text-sm font-medium", children: "Header Name" }),
37138
+ /* @__PURE__ */ jsxRuntimeExports.jsx(
37139
+ Input,
37140
+ {
37141
+ placeholder: "Authorization",
37142
+ onChange: (e) => setHeaderName && setHeaderName(e.target.value),
37143
+ "data-testid": "header-input",
37144
+ className: "font-mono",
37145
+ value: headerName
37146
+ }
37147
+ ),
37148
+ /* @__PURE__ */ jsxRuntimeExports.jsx(
37149
+ "label",
37150
+ {
37151
+ className: "text-sm font-medium",
37152
+ htmlFor: "bearer-token-input",
37153
+ children: "Bearer Token"
37154
+ }
37155
+ ),
37156
+ /* @__PURE__ */ jsxRuntimeExports.jsx(
37157
+ Input,
37158
+ {
37159
+ id: "bearer-token-input",
37160
+ placeholder: "Bearer Token",
37161
+ value: bearerToken,
37162
+ onChange: (e) => setBearerToken(e.target.value),
37163
+ "data-testid": "bearer-token-input",
37164
+ className: "font-mono",
37165
+ type: "password"
37166
+ }
37167
+ )
37168
+ ] })
37169
+ ] }),
37170
+ transportType !== "stdio" && // OAuth Configuration
37171
+ /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "space-y-2 p-3 rounded border", children: [
37172
+ /* @__PURE__ */ jsxRuntimeExports.jsx("h4", { className: "text-sm font-semibold flex items-center", children: "OAuth 2.0 Flow" }),
37173
+ /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "space-y-2", children: [
37174
+ /* @__PURE__ */ jsxRuntimeExports.jsx("label", { className: "text-sm font-medium", children: "Client ID" }),
37175
+ /* @__PURE__ */ jsxRuntimeExports.jsx(
37176
+ Input,
37177
+ {
37178
+ placeholder: "Client ID",
37179
+ onChange: (e) => setOauthClientId(e.target.value),
37180
+ value: oauthClientId,
37181
+ "data-testid": "oauth-client-id-input",
37182
+ className: "font-mono"
37183
+ }
37184
+ ),
37185
+ /* @__PURE__ */ jsxRuntimeExports.jsx("label", { className: "text-sm font-medium", children: "Redirect URL" }),
37186
+ /* @__PURE__ */ jsxRuntimeExports.jsx(
37187
+ Input,
37188
+ {
37189
+ readOnly: true,
37190
+ placeholder: "Redirect URL",
37191
+ value: window.location.origin + "/oauth/callback",
37192
+ className: "font-mono"
37193
+ }
37194
+ ),
37195
+ /* @__PURE__ */ jsxRuntimeExports.jsx("label", { className: "text-sm font-medium", children: "Scope" }),
37196
+ /* @__PURE__ */ jsxRuntimeExports.jsx(
37197
+ Input,
37198
+ {
37199
+ placeholder: "Scope (space-separated)",
37200
+ onChange: (e) => setOauthScope(e.target.value),
37201
+ value: oauthScope,
37202
+ "data-testid": "oauth-scope-input",
37203
+ className: "font-mono"
37204
+ }
37205
+ )
37206
+ ] })
37207
+ ] })
37208
+ ] })
37209
+ ] }),
36700
37210
  /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "space-y-2", children: [
36701
37211
  /* @__PURE__ */ jsxRuntimeExports.jsxs(
36702
37212
  Button,
@@ -37244,42 +37754,112 @@ const Textarea = reactExports.forwardRef(
37244
37754
  }
37245
37755
  );
37246
37756
  Textarea.displayName = "Textarea";
37247
- const checkContentCompatibility = (structuredContent, unstructuredContent) => {
37248
- if (unstructuredContent.length !== 1 || unstructuredContent[0].type !== "text") {
37249
- return {
37250
- isCompatible: false,
37251
- message: "Unstructured content is not a single text block"
37252
- };
37757
+ const ResourceLinkView = reactExports.memo(
37758
+ ({
37759
+ uri,
37760
+ name,
37761
+ description: description2,
37762
+ mimeType,
37763
+ resourceContent,
37764
+ onReadResource
37765
+ }) => {
37766
+ const [{ expanded, loading }, setState] = reactExports.useState({
37767
+ expanded: false,
37768
+ loading: false
37769
+ });
37770
+ const expandedContent = reactExports.useMemo(
37771
+ () => expanded && resourceContent ? /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "mt-2", children: [
37772
+ /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "flex justify-between items-center mb-1", children: /* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "font-semibold text-green-600", children: "Resource:" }) }),
37773
+ /* @__PURE__ */ jsxRuntimeExports.jsx(JsonView, { data: resourceContent, className: "bg-background" })
37774
+ ] }) : null,
37775
+ [expanded, resourceContent]
37776
+ );
37777
+ const handleClick = reactExports.useCallback(() => {
37778
+ if (!onReadResource) return;
37779
+ if (!expanded) {
37780
+ setState((prev) => ({ ...prev, expanded: true, loading: true }));
37781
+ onReadResource(uri);
37782
+ setState((prev) => ({ ...prev, loading: false }));
37783
+ } else {
37784
+ setState((prev) => ({ ...prev, expanded: false }));
37785
+ }
37786
+ }, [expanded, onReadResource, uri]);
37787
+ const handleKeyDown = reactExports.useCallback(
37788
+ (e) => {
37789
+ if ((e.key === "Enter" || e.key === " ") && onReadResource) {
37790
+ e.preventDefault();
37791
+ handleClick();
37792
+ }
37793
+ },
37794
+ [handleClick, onReadResource]
37795
+ );
37796
+ return /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "text-sm text-foreground bg-secondary py-2 px-3 rounded", children: [
37797
+ /* @__PURE__ */ jsxRuntimeExports.jsx(
37798
+ "div",
37799
+ {
37800
+ className: "flex justify-between items-center cursor-pointer focus:outline-none focus-visible:ring-2 focus-visible:ring-blue-500 focus-visible:ring-offset-1 rounded",
37801
+ onClick: onReadResource ? handleClick : void 0,
37802
+ onKeyDown: onReadResource ? handleKeyDown : void 0,
37803
+ tabIndex: onReadResource ? 0 : -1,
37804
+ role: "button",
37805
+ "aria-expanded": expanded,
37806
+ "aria-label": `${expanded ? "Collapse" : "Expand"} resource ${uri}`,
37807
+ children: /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "flex-1 min-w-0", children: [
37808
+ /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "flex items-start justify-between gap-2 mb-1", children: [
37809
+ /* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "text-sm text-blue-600 dark:text-blue-400 hover:text-blue-800 dark:hover:text-blue-300 hover:underline px-1 py-0.5 break-all font-mono flex-1 min-w-0", children: uri }),
37810
+ /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "flex items-center gap-2 flex-shrink-0", children: [
37811
+ mimeType && /* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "inline-flex items-center px-2 py-1 rounded-full text-xs font-medium bg-blue-100 text-blue-800 dark:bg-blue-900 dark:text-blue-200", children: mimeType }),
37812
+ onReadResource && /* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "ml-2 flex-shrink-0", "aria-hidden": "true", children: loading ? /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "w-4 h-4 border-2 border-blue-500 border-t-transparent rounded-full animate-spin" }) : /* @__PURE__ */ jsxRuntimeExports.jsx("span", { children: expanded ? "▼" : "▶" }) })
37813
+ ] })
37814
+ ] }),
37815
+ name && /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "font-semibold text-sm text-gray-900 dark:text-gray-100 mb-1", children: name }),
37816
+ description2 && /* @__PURE__ */ jsxRuntimeExports.jsx("p", { className: "text-sm text-gray-600 dark:text-gray-300 leading-relaxed", children: description2 })
37817
+ ] })
37818
+ }
37819
+ ),
37820
+ expandedContent
37821
+ ] });
37253
37822
  }
37254
- const textContent = unstructuredContent[0].text;
37255
- if (!textContent) {
37823
+ );
37824
+ const checkContentCompatibility = (structuredContent, unstructuredContent) => {
37825
+ const textBlocks = unstructuredContent.filter(
37826
+ (block) => block.type === "text"
37827
+ );
37828
+ if (textBlocks.length === 0) {
37256
37829
  return {
37257
37830
  isCompatible: false,
37258
- message: "Text content is empty"
37831
+ message: "No text blocks to match structured content"
37259
37832
  };
37260
37833
  }
37261
- try {
37262
- const parsedContent = JSON.parse(textContent);
37263
- const isEqual = JSON.stringify(parsedContent) === JSON.stringify(structuredContent);
37264
- if (isEqual) {
37265
- return {
37266
- isCompatible: true,
37267
- message: "Unstructured content matches structured content"
37268
- };
37269
- } else {
37270
- return {
37271
- isCompatible: false,
37272
- message: "Parsed JSON does not match structured content"
37273
- };
37834
+ for (const textBlock of textBlocks) {
37835
+ const textContent = textBlock.text;
37836
+ if (!textContent) {
37837
+ continue;
37838
+ }
37839
+ try {
37840
+ const parsedContent = JSON.parse(textContent);
37841
+ const isEqual = JSON.stringify(parsedContent) === JSON.stringify(structuredContent);
37842
+ if (isEqual) {
37843
+ return {
37844
+ isCompatible: true,
37845
+ message: `Structured content matches text block${textBlocks.length > 1 ? " (multiple blocks)" : ""}${unstructuredContent.length > textBlocks.length ? " + other content" : ""}`
37846
+ };
37847
+ }
37848
+ } catch {
37849
+ continue;
37274
37850
  }
37275
- } catch {
37276
- return {
37277
- isCompatible: false,
37278
- message: "Unstructured content is not valid JSON"
37279
- };
37280
37851
  }
37852
+ return {
37853
+ isCompatible: false,
37854
+ message: "No text block matches structured content"
37855
+ };
37281
37856
  };
37282
- const ToolResults = ({ toolResult, selectedTool }) => {
37857
+ const ToolResults = ({
37858
+ toolResult,
37859
+ selectedTool,
37860
+ resourceContent,
37861
+ onReadResource
37862
+ }) => {
37283
37863
  if (!toolResult) return null;
37284
37864
  if ("content" in toolResult) {
37285
37865
  const parsedResult = CallToolResultSchema.safeParse(toolResult);
@@ -37376,7 +37956,18 @@ const ToolResults = ({ toolResult, selectedTool }) => {
37376
37956
  className: "w-full",
37377
37957
  children: /* @__PURE__ */ jsxRuntimeExports.jsx("p", { children: "Your browser does not support audio playback" })
37378
37958
  }
37379
- ) : /* @__PURE__ */ jsxRuntimeExports.jsx(JsonView, { data: item.resource }))
37959
+ ) : /* @__PURE__ */ jsxRuntimeExports.jsx(JsonView, { data: item.resource })),
37960
+ item.type === "resource_link" && /* @__PURE__ */ jsxRuntimeExports.jsx(
37961
+ ResourceLinkView,
37962
+ {
37963
+ uri: item.uri,
37964
+ name: item.name,
37965
+ description: item.description,
37966
+ mimeType: item.mimeType,
37967
+ resourceContent: resourceContent[item.uri] || "",
37968
+ onReadResource
37969
+ }
37970
+ )
37380
37971
  ] }, index2);
37381
37972
  })
37382
37973
  ] })
@@ -37397,7 +37988,9 @@ const ToolsTab = ({
37397
37988
  selectedTool,
37398
37989
  setSelectedTool,
37399
37990
  toolResult,
37400
- nextCursor
37991
+ nextCursor,
37992
+ resourceContent,
37993
+ onReadResource
37401
37994
  }) => {
37402
37995
  const [params, setParams] = reactExports.useState({});
37403
37996
  const [isToolRunning, setIsToolRunning] = reactExports.useState(false);
@@ -37598,19 +38191,159 @@ const ToolsTab = ({
37598
38191
  ToolResults,
37599
38192
  {
37600
38193
  toolResult,
37601
- selectedTool
38194
+ selectedTool,
38195
+ resourceContent,
38196
+ onReadResource
37602
38197
  }
37603
38198
  )
37604
38199
  ] }) : /* @__PURE__ */ jsxRuntimeExports.jsx(Alert, { children: /* @__PURE__ */ jsxRuntimeExports.jsx(AlertDescription, { children: "Select a tool from the list to view its details and run it" }) }) })
37605
38200
  ] })
37606
38201
  ] }) });
37607
38202
  };
38203
+ const ElicitationRequest = ({
38204
+ request,
38205
+ onResolve
38206
+ }) => {
38207
+ const [formData, setFormData] = reactExports.useState({});
38208
+ const [validationError, setValidationError] = reactExports.useState(null);
38209
+ reactExports.useEffect(() => {
38210
+ const defaultValue = generateDefaultValue(request.request.requestedSchema);
38211
+ setFormData(defaultValue);
38212
+ setValidationError(null);
38213
+ }, [request.request.requestedSchema]);
38214
+ const validateEmailFormat = (email) => {
38215
+ const emailRegex2 = /^[^\s@]+@[^\s@]+\.[^\s@]+$/;
38216
+ return emailRegex2.test(email);
38217
+ };
38218
+ const validateFormData = (data2, schema) => {
38219
+ if (schema.type === "object" && schema.properties && typeof data2 === "object" && data2 !== null) {
38220
+ const dataObj = data2;
38221
+ if (Array.isArray(schema.required)) {
38222
+ for (const field of schema.required) {
38223
+ const value = dataObj[field];
38224
+ if (value === void 0 || value === null || value === "") {
38225
+ setValidationError(`Required field missing: ${field}`);
38226
+ return false;
38227
+ }
38228
+ }
38229
+ }
38230
+ for (const [fieldName, fieldValue] of Object.entries(dataObj)) {
38231
+ const fieldSchema = schema.properties[fieldName];
38232
+ if (fieldSchema && fieldSchema.format === "email" && typeof fieldValue === "string") {
38233
+ if (!validateEmailFormat(fieldValue)) {
38234
+ setValidationError(`Invalid email format: ${fieldName}`);
38235
+ return false;
38236
+ }
38237
+ }
38238
+ }
38239
+ }
38240
+ return true;
38241
+ };
38242
+ const handleAccept = () => {
38243
+ try {
38244
+ if (!validateFormData(formData, request.request.requestedSchema)) {
38245
+ return;
38246
+ }
38247
+ const ajv2 = new Ajv();
38248
+ const validate2 = ajv2.compile(request.request.requestedSchema);
38249
+ const isValid2 = validate2(formData);
38250
+ if (!isValid2) {
38251
+ const errorMessage = ajv2.errorsText(validate2.errors);
38252
+ setValidationError(errorMessage);
38253
+ return;
38254
+ }
38255
+ onResolve(request.id, {
38256
+ action: "accept",
38257
+ content: formData
38258
+ });
38259
+ } catch (error) {
38260
+ setValidationError(
38261
+ error instanceof Error ? error.message : "Validation failed"
38262
+ );
38263
+ }
38264
+ };
38265
+ const handleDecline = () => {
38266
+ onResolve(request.id, { action: "decline" });
38267
+ };
38268
+ const handleCancel = () => {
38269
+ onResolve(request.id, { action: "cancel" });
38270
+ };
38271
+ const schemaTitle = request.request.requestedSchema.title || "Information Request";
38272
+ const schemaDescription = request.request.requestedSchema.description;
38273
+ return /* @__PURE__ */ jsxRuntimeExports.jsxs(
38274
+ "div",
38275
+ {
38276
+ "data-testid": "elicitation-request",
38277
+ className: "flex gap-4 p-4 border rounded-lg space-y-4",
38278
+ children: [
38279
+ /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "flex-1 bg-gray-50 dark:bg-gray-800 dark:text-gray-100 p-2 rounded", children: /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "space-y-2", children: [
38280
+ /* @__PURE__ */ jsxRuntimeExports.jsx("h4", { className: "font-semibold", children: schemaTitle }),
38281
+ /* @__PURE__ */ jsxRuntimeExports.jsx("p", { className: "text-sm", children: request.request.message }),
38282
+ schemaDescription && /* @__PURE__ */ jsxRuntimeExports.jsx("p", { className: "text-xs text-muted-foreground", children: schemaDescription }),
38283
+ /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "mt-2", children: [
38284
+ /* @__PURE__ */ jsxRuntimeExports.jsx("h5", { className: "text-xs font-medium mb-1", children: "Request Schema:" }),
38285
+ /* @__PURE__ */ jsxRuntimeExports.jsx(
38286
+ JsonView,
38287
+ {
38288
+ data: JSON.stringify(request.request.requestedSchema, null, 2)
38289
+ }
38290
+ )
38291
+ ] })
38292
+ ] }) }),
38293
+ /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "flex-1 space-y-4", children: [
38294
+ /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "space-y-2", children: [
38295
+ /* @__PURE__ */ jsxRuntimeExports.jsx("h4", { className: "font-medium", children: "Response Form" }),
38296
+ /* @__PURE__ */ jsxRuntimeExports.jsx(
38297
+ DynamicJsonForm,
38298
+ {
38299
+ schema: request.request.requestedSchema,
38300
+ value: formData,
38301
+ onChange: (newValue) => {
38302
+ setFormData(newValue);
38303
+ setValidationError(null);
38304
+ }
38305
+ }
38306
+ ),
38307
+ validationError && /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "mt-4 p-3 bg-red-50 dark:bg-red-900/20 border border-red-200 dark:border-red-800 rounded-md", children: /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "text-sm text-red-600 dark:text-red-400", children: [
38308
+ /* @__PURE__ */ jsxRuntimeExports.jsx("strong", { children: "Validation Error:" }),
38309
+ " ",
38310
+ validationError
38311
+ ] }) })
38312
+ ] }),
38313
+ /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "flex space-x-2 mt-1", children: [
38314
+ /* @__PURE__ */ jsxRuntimeExports.jsx(Button, { type: "button", onClick: handleAccept, children: "Submit" }),
38315
+ /* @__PURE__ */ jsxRuntimeExports.jsx(Button, { type: "button", variant: "outline", onClick: handleDecline, children: "Decline" }),
38316
+ /* @__PURE__ */ jsxRuntimeExports.jsx(Button, { type: "button", variant: "outline", onClick: handleCancel, children: "Cancel" })
38317
+ ] })
38318
+ ] })
38319
+ ]
38320
+ }
38321
+ );
38322
+ };
38323
+ const ElicitationTab = ({ pendingRequests, onResolve }) => {
38324
+ return /* @__PURE__ */ jsxRuntimeExports.jsx(TabsContent, { value: "elicitations", children: /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "h-96", children: [
38325
+ /* @__PURE__ */ jsxRuntimeExports.jsx(Alert, { children: /* @__PURE__ */ jsxRuntimeExports.jsx(AlertDescription, { children: "When the server requests information from the user, requests will appear here for response." }) }),
38326
+ /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "mt-4 space-y-4", children: [
38327
+ /* @__PURE__ */ jsxRuntimeExports.jsx("h3", { className: "text-lg font-semibold", children: "Recent Requests" }),
38328
+ pendingRequests.map((request) => /* @__PURE__ */ jsxRuntimeExports.jsx(
38329
+ ElicitationRequest,
38330
+ {
38331
+ request,
38332
+ onResolve
38333
+ },
38334
+ request.id
38335
+ )),
38336
+ pendingRequests.length === 0 && /* @__PURE__ */ jsxRuntimeExports.jsx("p", { className: "text-gray-500", children: "No pending requests" })
38337
+ ] })
38338
+ ] }) });
38339
+ };
37608
38340
  const CONFIG_LOCAL_STORAGE_KEY = "inspectorConfig_v1";
37609
38341
  const App = () => {
37610
38342
  var _a;
37611
38343
  const [resources, setResources] = reactExports.useState([]);
37612
38344
  const [resourceTemplates, setResourceTemplates] = reactExports.useState([]);
37613
38345
  const [resourceContent, setResourceContent] = reactExports.useState("");
38346
+ const [resourceContentMap, setResourceContentMap] = reactExports.useState({});
37614
38347
  const [prompts, setPrompts] = reactExports.useState([]);
37615
38348
  const [promptContent, setPromptContent] = reactExports.useState("");
37616
38349
  const [tools, setTools] = reactExports.useState([]);
@@ -37638,7 +38371,14 @@ const App = () => {
37638
38371
  const [headerName, setHeaderName] = reactExports.useState(() => {
37639
38372
  return localStorage.getItem("lastHeaderName") || "";
37640
38373
  });
38374
+ const [oauthClientId, setOauthClientId] = reactExports.useState(() => {
38375
+ return localStorage.getItem("lastOauthClientId") || "";
38376
+ });
38377
+ const [oauthScope, setOauthScope] = reactExports.useState(() => {
38378
+ return localStorage.getItem("lastOauthScope") || "";
38379
+ });
37641
38380
  const [pendingSampleRequests, setPendingSampleRequests] = reactExports.useState([]);
38381
+ const [pendingElicitationRequests, setPendingElicitationRequests] = reactExports.useState([]);
37642
38382
  const [isAuthDebuggerVisible, setIsAuthDebuggerVisible] = reactExports.useState(false);
37643
38383
  const [authState, setAuthState] = reactExports.useState(EMPTY_DEBUGGER_STATE);
37644
38384
  const updateAuthState = (updates) => {
@@ -37657,6 +38397,16 @@ const App = () => {
37657
38397
  const [nextPromptCursor, setNextPromptCursor] = reactExports.useState();
37658
38398
  const [nextToolCursor, setNextToolCursor] = reactExports.useState();
37659
38399
  const progressTokenRef = reactExports.useRef(0);
38400
+ const [activeTab, setActiveTab] = reactExports.useState(() => {
38401
+ const hash = window.location.hash.slice(1);
38402
+ const initialTab = hash || "resources";
38403
+ return initialTab;
38404
+ });
38405
+ const currentTabRef = reactExports.useRef(activeTab);
38406
+ const lastToolCallOriginTabRef = reactExports.useRef(activeTab);
38407
+ reactExports.useEffect(() => {
38408
+ currentTabRef.current = activeTab;
38409
+ }, [activeTab]);
37660
38410
  const { height: historyPaneHeight, handleDragStart } = useDraggablePane(300);
37661
38411
  const {
37662
38412
  width: sidebarWidth,
@@ -37682,6 +38432,8 @@ const App = () => {
37682
38432
  env,
37683
38433
  bearerToken,
37684
38434
  headerName,
38435
+ oauthClientId,
38436
+ oauthScope,
37685
38437
  config,
37686
38438
  onNotification: (notification) => {
37687
38439
  setNotifications((prev) => [...prev, notification]);
@@ -37698,8 +38450,50 @@ const App = () => {
37698
38450
  { id: nextRequestId.current++, request, resolve, reject }
37699
38451
  ]);
37700
38452
  },
38453
+ onElicitationRequest: (request, resolve) => {
38454
+ const currentTab = lastToolCallOriginTabRef.current;
38455
+ setPendingElicitationRequests((prev) => [
38456
+ ...prev,
38457
+ {
38458
+ id: nextRequestId.current++,
38459
+ request: {
38460
+ id: nextRequestId.current,
38461
+ message: request.params.message,
38462
+ requestedSchema: request.params.requestedSchema
38463
+ },
38464
+ originatingTab: currentTab,
38465
+ resolve,
38466
+ decline: (error) => {
38467
+ console.error("Elicitation request rejected:", error);
38468
+ }
38469
+ }
38470
+ ]);
38471
+ setActiveTab("elicitations");
38472
+ window.location.hash = "elicitations";
38473
+ },
37701
38474
  getRoots: () => rootsRef.current
37702
38475
  });
38476
+ reactExports.useEffect(() => {
38477
+ if (serverCapabilities) {
38478
+ const hash = window.location.hash.slice(1);
38479
+ const validTabs = [
38480
+ ...(serverCapabilities == null ? void 0 : serverCapabilities.resources) ? ["resources"] : [],
38481
+ ...(serverCapabilities == null ? void 0 : serverCapabilities.prompts) ? ["prompts"] : [],
38482
+ ...(serverCapabilities == null ? void 0 : serverCapabilities.tools) ? ["tools"] : [],
38483
+ "ping",
38484
+ "sampling",
38485
+ "elicitations",
38486
+ "roots",
38487
+ "auth"
38488
+ ];
38489
+ const isValidTab = validTabs.includes(hash);
38490
+ if (!isValidTab) {
38491
+ const defaultTab = (serverCapabilities == null ? void 0 : serverCapabilities.resources) ? "resources" : (serverCapabilities == null ? void 0 : serverCapabilities.prompts) ? "prompts" : (serverCapabilities == null ? void 0 : serverCapabilities.tools) ? "tools" : "ping";
38492
+ setActiveTab(defaultTab);
38493
+ window.location.hash = defaultTab;
38494
+ }
38495
+ }
38496
+ }, [serverCapabilities]);
37703
38497
  reactExports.useEffect(() => {
37704
38498
  localStorage.setItem("lastCommand", command);
37705
38499
  }, [command]);
@@ -37718,6 +38512,12 @@ const App = () => {
37718
38512
  reactExports.useEffect(() => {
37719
38513
  localStorage.setItem("lastHeaderName", headerName);
37720
38514
  }, [headerName]);
38515
+ reactExports.useEffect(() => {
38516
+ localStorage.setItem("lastOauthClientId", oauthClientId);
38517
+ }, [oauthClientId]);
38518
+ reactExports.useEffect(() => {
38519
+ localStorage.setItem("lastOauthScope", oauthScope);
38520
+ }, [oauthScope]);
37721
38521
  reactExports.useEffect(() => {
37722
38522
  saveInspectorConfig(CONFIG_LOCAL_STORAGE_KEY, config);
37723
38523
  }, [config]);
@@ -37836,6 +38636,16 @@ const App = () => {
37836
38636
  window.location.hash = "resources";
37837
38637
  }
37838
38638
  }, []);
38639
+ reactExports.useEffect(() => {
38640
+ const handleHashChange = () => {
38641
+ const hash = window.location.hash.slice(1);
38642
+ if (hash && hash !== activeTab) {
38643
+ setActiveTab(hash);
38644
+ }
38645
+ };
38646
+ window.addEventListener("hashchange", handleHashChange);
38647
+ return () => window.removeEventListener("hashchange", handleHashChange);
38648
+ }, [activeTab]);
37839
38649
  const handleApproveSampling = (id, result) => {
37840
38650
  setPendingSampleRequests((prev) => {
37841
38651
  const request = prev.find((r2) => r2.id === id);
@@ -37850,6 +38660,36 @@ const App = () => {
37850
38660
  return prev.filter((r2) => r2.id !== id);
37851
38661
  });
37852
38662
  };
38663
+ const handleResolveElicitation = (id, response) => {
38664
+ setPendingElicitationRequests((prev) => {
38665
+ const request = prev.find((r2) => r2.id === id);
38666
+ if (request) {
38667
+ request.resolve(response);
38668
+ if (request.originatingTab) {
38669
+ const originatingTab = request.originatingTab;
38670
+ const validTabs = [
38671
+ ...(serverCapabilities == null ? void 0 : serverCapabilities.resources) ? ["resources"] : [],
38672
+ ...(serverCapabilities == null ? void 0 : serverCapabilities.prompts) ? ["prompts"] : [],
38673
+ ...(serverCapabilities == null ? void 0 : serverCapabilities.tools) ? ["tools"] : [],
38674
+ "ping",
38675
+ "sampling",
38676
+ "elicitations",
38677
+ "roots",
38678
+ "auth"
38679
+ ];
38680
+ if (validTabs.includes(originatingTab)) {
38681
+ setActiveTab(originatingTab);
38682
+ window.location.hash = originatingTab;
38683
+ setTimeout(() => {
38684
+ setActiveTab(originatingTab);
38685
+ window.location.hash = originatingTab;
38686
+ }, 100);
38687
+ }
38688
+ }
38689
+ }
38690
+ return prev.filter((r2) => r2.id !== id);
38691
+ });
38692
+ };
37853
38693
  const clearError = (tabKey) => {
37854
38694
  setErrors((prev) => ({ ...prev, [tabKey]: null }));
37855
38695
  };
@@ -37897,7 +38737,20 @@ const App = () => {
37897
38737
  );
37898
38738
  setNextResourceTemplateCursor(response.nextCursor);
37899
38739
  };
38740
+ const getPrompt = async (name, args2 = {}) => {
38741
+ lastToolCallOriginTabRef.current = currentTabRef.current;
38742
+ const response = await sendMCPRequest(
38743
+ {
38744
+ method: "prompts/get",
38745
+ params: { name, arguments: args2 }
38746
+ },
38747
+ GetPromptResultSchema,
38748
+ "prompts"
38749
+ );
38750
+ setPromptContent(JSON.stringify(response, null, 2));
38751
+ };
37900
38752
  const readResource = async (uri) => {
38753
+ lastToolCallOriginTabRef.current = currentTabRef.current;
37901
38754
  const response = await sendMCPRequest(
37902
38755
  {
37903
38756
  method: "resources/read",
@@ -37906,7 +38759,12 @@ const App = () => {
37906
38759
  ReadResourceResultSchema,
37907
38760
  "resources"
37908
38761
  );
37909
- setResourceContent(JSON.stringify(response, null, 2));
38762
+ const content = JSON.stringify(response, null, 2);
38763
+ setResourceContent(content);
38764
+ setResourceContentMap((prev) => ({
38765
+ ...prev,
38766
+ [uri]: content
38767
+ }));
37910
38768
  };
37911
38769
  const subscribeToResource = async (uri) => {
37912
38770
  if (!resourceSubscriptions.has(uri)) {
@@ -37950,17 +38808,6 @@ const App = () => {
37950
38808
  setPrompts(response.prompts);
37951
38809
  setNextPromptCursor(response.nextCursor);
37952
38810
  };
37953
- const getPrompt = async (name, args2 = {}) => {
37954
- const response = await sendMCPRequest(
37955
- {
37956
- method: "prompts/get",
37957
- params: { name, arguments: args2 }
37958
- },
37959
- GetPromptResultSchema,
37960
- "prompts"
37961
- );
37962
- setPromptContent(JSON.stringify(response, null, 2));
37963
- };
37964
38811
  const listTools = async () => {
37965
38812
  const response = await sendMCPRequest(
37966
38813
  {
@@ -37975,6 +38822,7 @@ const App = () => {
37975
38822
  cacheToolOutputSchemas(response.tools);
37976
38823
  };
37977
38824
  const callTool = async (name, params) => {
38825
+ lastToolCallOriginTabRef.current = currentTabRef.current;
37978
38826
  try {
37979
38827
  const response = await sendMCPRequest(
37980
38828
  {
@@ -38031,13 +38879,13 @@ const App = () => {
38031
38879
  ) });
38032
38880
  if (window.location.pathname === "/oauth/callback") {
38033
38881
  const OAuthCallback = React.lazy(
38034
- () => __vitePreload(() => import("./OAuthCallback-DMQy4ibj.js"), true ? __vite__mapDeps([0,1]) : void 0)
38882
+ () => __vitePreload(() => import("./OAuthCallback-CC1cu0Zx.js"), true ? __vite__mapDeps([0,1]) : void 0)
38035
38883
  );
38036
38884
  return /* @__PURE__ */ jsxRuntimeExports.jsx(reactExports.Suspense, { fallback: /* @__PURE__ */ jsxRuntimeExports.jsx("div", { children: "Loading..." }), children: /* @__PURE__ */ jsxRuntimeExports.jsx(OAuthCallback, { onConnect: onOAuthConnect }) });
38037
38885
  }
38038
38886
  if (window.location.pathname === "/oauth/callback/debug") {
38039
38887
  const OAuthDebugCallback = React.lazy(
38040
- () => __vitePreload(() => import("./OAuthDebugCallback-9JxBAysc.js"), true ? __vite__mapDeps([2,1]) : void 0)
38888
+ () => __vitePreload(() => import("./OAuthDebugCallback-_4BLxVDe.js"), true ? __vite__mapDeps([2,1]) : void 0)
38041
38889
  );
38042
38890
  return /* @__PURE__ */ jsxRuntimeExports.jsx(reactExports.Suspense, { fallback: /* @__PURE__ */ jsxRuntimeExports.jsx("div", { children: "Loading..." }), children: /* @__PURE__ */ jsxRuntimeExports.jsx(OAuthDebugCallback, { onConnect: onOAuthDebugConnect }) });
38043
38891
  }
@@ -38073,6 +38921,10 @@ const App = () => {
38073
38921
  setBearerToken,
38074
38922
  headerName,
38075
38923
  setHeaderName,
38924
+ oauthClientId,
38925
+ setOauthClientId,
38926
+ oauthScope,
38927
+ setOauthScope,
38076
38928
  onConnect: connectMcpServer,
38077
38929
  onDisconnect: disconnectMcpServer,
38078
38930
  stdErrNotifications,
@@ -38107,11 +38959,12 @@ const App = () => {
38107
38959
  /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "flex-1 overflow-auto", children: mcpClient ? /* @__PURE__ */ jsxRuntimeExports.jsxs(
38108
38960
  Tabs,
38109
38961
  {
38110
- defaultValue: Object.keys(serverCapabilities ?? {}).includes(
38111
- window.location.hash.slice(1)
38112
- ) ? window.location.hash.slice(1) : (serverCapabilities == null ? void 0 : serverCapabilities.resources) ? "resources" : (serverCapabilities == null ? void 0 : serverCapabilities.prompts) ? "prompts" : (serverCapabilities == null ? void 0 : serverCapabilities.tools) ? "tools" : "ping",
38962
+ value: activeTab,
38113
38963
  className: "w-full p-4",
38114
- onValueChange: (value) => window.location.hash = value,
38964
+ onValueChange: (value) => {
38965
+ setActiveTab(value);
38966
+ window.location.hash = value;
38967
+ },
38115
38968
  children: [
38116
38969
  /* @__PURE__ */ jsxRuntimeExports.jsxs(TabsList, { className: "mb-4 py-0", children: [
38117
38970
  /* @__PURE__ */ jsxRuntimeExports.jsxs(
@@ -38156,6 +39009,11 @@ const App = () => {
38156
39009
  "Sampling",
38157
39010
  pendingSampleRequests.length > 0 && /* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "absolute -top-1 -right-1 bg-red-500 text-white text-xs rounded-full h-4 w-4 flex items-center justify-center", children: pendingSampleRequests.length })
38158
39011
  ] }),
39012
+ /* @__PURE__ */ jsxRuntimeExports.jsxs(TabsTrigger, { value: "elicitations", className: "relative", children: [
39013
+ /* @__PURE__ */ jsxRuntimeExports.jsx(MessageSquare, { className: "w-4 h-4 mr-2" }),
39014
+ "Elicitations",
39015
+ pendingElicitationRequests.length > 0 && /* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "absolute -top-1 -right-1 bg-red-500 text-white text-xs rounded-full h-4 w-4 flex items-center justify-center", children: pendingElicitationRequests.length })
39016
+ ] }),
38159
39017
  /* @__PURE__ */ jsxRuntimeExports.jsxs(TabsTrigger, { value: "roots", children: [
38160
39018
  /* @__PURE__ */ jsxRuntimeExports.jsx(FolderTree, { className: "w-4 h-4 mr-2" }),
38161
39019
  "Roots"
@@ -38284,7 +39142,12 @@ const App = () => {
38284
39142
  },
38285
39143
  toolResult,
38286
39144
  nextCursor: nextToolCursor,
38287
- error: errors.tools
39145
+ error: errors.tools,
39146
+ resourceContent: resourceContentMap,
39147
+ onReadResource: (uri) => {
39148
+ clearError("resources");
39149
+ readResource(uri);
39150
+ }
38288
39151
  }
38289
39152
  ),
38290
39153
  /* @__PURE__ */ jsxRuntimeExports.jsx(ConsoleTab, {}),
@@ -38309,6 +39172,13 @@ const App = () => {
38309
39172
  onReject: handleRejectSampling
38310
39173
  }
38311
39174
  ),
39175
+ /* @__PURE__ */ jsxRuntimeExports.jsx(
39176
+ ElicitationTab,
39177
+ {
39178
+ pendingRequests: pendingElicitationRequests,
39179
+ onResolve: handleResolveElicitation
39180
+ }
39181
+ ),
38312
39182
  /* @__PURE__ */ jsxRuntimeExports.jsx(
38313
39183
  RootsTab,
38314
39184
  {