@modelcontextprotocol/inspector-client 0.16.1 → 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-CaDIOg8Q.js","assets/oauthUtils-DTcoXpSP.js","assets/OAuthDebugCallback-Ccjj44Wa.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,6 +16456,95 @@ 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");
@@ -16423,19 +16598,50 @@ function applyPostAuth(clientId, clientSecret, params) {
16423
16598
  function applyPublicAuth(clientId, params) {
16424
16599
  params.set("client_id", clientId);
16425
16600
  }
16426
- async function auth(provider, { serverUrl, authorizationCode, scope, resourceMetadataUrl }) {
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 }) {
16427
16630
  let resourceMetadata;
16428
- let authorizationServerUrl = serverUrl;
16631
+ let authorizationServerUrl;
16429
16632
  try {
16430
- resourceMetadata = await discoverOAuthProtectedResourceMetadata(serverUrl, { resourceMetadataUrl });
16633
+ resourceMetadata = await discoverOAuthProtectedResourceMetadata(serverUrl, { resourceMetadataUrl }, fetchFn);
16431
16634
  if (resourceMetadata.authorization_servers && resourceMetadata.authorization_servers.length > 0) {
16432
16635
  authorizationServerUrl = resourceMetadata.authorization_servers[0];
16433
16636
  }
16434
16637
  } catch (_a) {
16435
16638
  }
16639
+ if (!authorizationServerUrl) {
16640
+ authorizationServerUrl = serverUrl;
16641
+ }
16436
16642
  const resource = await selectResourceURL(serverUrl, provider, resourceMetadata);
16437
- const metadata = await discoverOAuthMetadata(serverUrl, {
16438
- authorizationServerUrl
16643
+ const metadata = await discoverAuthorizationServerMetadata(authorizationServerUrl, {
16644
+ fetchFn
16439
16645
  });
16440
16646
  let clientInformation = await Promise.resolve(provider.clientInformation());
16441
16647
  if (!clientInformation) {
@@ -16461,7 +16667,8 @@ async function auth(provider, { serverUrl, authorizationCode, scope, resourceMet
16461
16667
  codeVerifier: codeVerifier2,
16462
16668
  redirectUri: provider.redirectUrl,
16463
16669
  resource,
16464
- addClientAuthentication: provider.addClientAuthentication
16670
+ addClientAuthentication: provider.addClientAuthentication,
16671
+ fetchFn
16465
16672
  });
16466
16673
  await provider.saveTokens(tokens2);
16467
16674
  return "AUTHORIZED";
@@ -16478,7 +16685,11 @@ async function auth(provider, { serverUrl, authorizationCode, scope, resourceMet
16478
16685
  });
16479
16686
  await provider.saveTokens(newTokens);
16480
16687
  return "AUTHORIZED";
16481
- } catch (_b) {
16688
+ } catch (error) {
16689
+ if (!(error instanceof OAuthError) || error instanceof ServerError) ;
16690
+ else {
16691
+ throw error;
16692
+ }
16482
16693
  }
16483
16694
  }
16484
16695
  const state = provider.state ? await provider.state() : void 0;
@@ -16527,8 +16738,8 @@ function extractResourceMetadataUrl(res) {
16527
16738
  return void 0;
16528
16739
  }
16529
16740
  }
16530
- async function discoverOAuthProtectedResourceMetadata(serverUrl, opts) {
16531
- const response = await discoverMetadataWithFallback(serverUrl, "oauth-protected-resource", {
16741
+ async function discoverOAuthProtectedResourceMetadata(serverUrl, opts, fetchFn = fetch) {
16742
+ const response = await discoverMetadataWithFallback(serverUrl, "oauth-protected-resource", fetchFn, {
16532
16743
  protocolVersion: opts === null || opts === void 0 ? void 0 : opts.protocolVersion,
16533
16744
  metadataUrl: opts === null || opts === void 0 ? void 0 : opts.resourceMetadataUrl
16534
16745
  });
@@ -16540,13 +16751,13 @@ async function discoverOAuthProtectedResourceMetadata(serverUrl, opts) {
16540
16751
  }
16541
16752
  return OAuthProtectedResourceMetadataSchema.parse(await response.json());
16542
16753
  }
16543
- async function fetchWithCorsRetry(url, headers) {
16754
+ async function fetchWithCorsRetry(url, headers, fetchFn = fetch) {
16544
16755
  try {
16545
- return await fetch(url, { headers });
16756
+ return await fetchFn(url, { headers });
16546
16757
  } catch (error) {
16547
16758
  if (error instanceof TypeError) {
16548
16759
  if (headers) {
16549
- return fetchWithCorsRetry(url);
16760
+ return fetchWithCorsRetry(url, void 0, fetchFn);
16550
16761
  } else {
16551
16762
  return void 0;
16552
16763
  }
@@ -16554,23 +16765,22 @@ async function fetchWithCorsRetry(url, headers) {
16554
16765
  throw error;
16555
16766
  }
16556
16767
  }
16557
- function buildWellKnownPath(wellKnownPrefix, pathname) {
16558
- let wellKnownPath = `/.well-known/${wellKnownPrefix}${pathname}`;
16768
+ function buildWellKnownPath(wellKnownPrefix, pathname = "", options = {}) {
16559
16769
  if (pathname.endsWith("/")) {
16560
- wellKnownPath = wellKnownPath.slice(0, -1);
16770
+ pathname = pathname.slice(0, -1);
16561
16771
  }
16562
- return wellKnownPath;
16772
+ return options.prependPathname ? `${pathname}/.well-known/${wellKnownPrefix}` : `/.well-known/${wellKnownPrefix}${pathname}`;
16563
16773
  }
16564
- async function tryMetadataDiscovery(url, protocolVersion) {
16774
+ async function tryMetadataDiscovery(url, protocolVersion, fetchFn = fetch) {
16565
16775
  const headers = {
16566
16776
  "MCP-Protocol-Version": protocolVersion
16567
16777
  };
16568
- return await fetchWithCorsRetry(url, headers);
16778
+ return await fetchWithCorsRetry(url, headers, fetchFn);
16569
16779
  }
16570
16780
  function shouldAttemptFallback(response, pathname) {
16571
16781
  return !response || response.status === 404 && pathname !== "/";
16572
16782
  }
16573
- async function discoverMetadataWithFallback(serverUrl, wellKnownType, opts) {
16783
+ async function discoverMetadataWithFallback(serverUrl, wellKnownType, fetchFn, opts) {
16574
16784
  var _a, _b;
16575
16785
  const issuer = new URL(serverUrl);
16576
16786
  const protocolVersion = (_a = opts === null || opts === void 0 ? void 0 : opts.protocolVersion) !== null && _a !== void 0 ? _a : LATEST_PROTOCOL_VERSION;
@@ -16582,14 +16792,14 @@ async function discoverMetadataWithFallback(serverUrl, wellKnownType, opts) {
16582
16792
  url = new URL(wellKnownPath, (_b = opts === null || opts === void 0 ? void 0 : opts.metadataServerUrl) !== null && _b !== void 0 ? _b : issuer);
16583
16793
  url.search = issuer.search;
16584
16794
  }
16585
- let response = await tryMetadataDiscovery(url, protocolVersion);
16795
+ let response = await tryMetadataDiscovery(url, protocolVersion, fetchFn);
16586
16796
  if (!(opts === null || opts === void 0 ? void 0 : opts.metadataUrl) && shouldAttemptFallback(response, issuer.pathname)) {
16587
16797
  const rootUrl = new URL(`/.well-known/${wellKnownType}`, issuer);
16588
- response = await tryMetadataDiscovery(rootUrl, protocolVersion);
16798
+ response = await tryMetadataDiscovery(rootUrl, protocolVersion, fetchFn);
16589
16799
  }
16590
16800
  return response;
16591
16801
  }
16592
- async function discoverOAuthMetadata(issuer, { authorizationServerUrl, protocolVersion } = {}) {
16802
+ async function discoverOAuthMetadata(issuer, { authorizationServerUrl, protocolVersion } = {}, fetchFn = fetch) {
16593
16803
  if (typeof issuer === "string") {
16594
16804
  issuer = new URL(issuer);
16595
16805
  }
@@ -16600,7 +16810,7 @@ async function discoverOAuthMetadata(issuer, { authorizationServerUrl, protocolV
16600
16810
  authorizationServerUrl = new URL(authorizationServerUrl);
16601
16811
  }
16602
16812
  protocolVersion !== null && protocolVersion !== void 0 ? protocolVersion : protocolVersion = LATEST_PROTOCOL_VERSION;
16603
- const response = await discoverMetadataWithFallback(issuer, "oauth-authorization-server", {
16813
+ const response = await discoverMetadataWithFallback(authorizationServerUrl, "oauth-authorization-server", fetchFn, {
16604
16814
  protocolVersion,
16605
16815
  metadataServerUrl: authorizationServerUrl
16606
16816
  });
@@ -16612,6 +16822,70 @@ async function discoverOAuthMetadata(issuer, { authorizationServerUrl, protocolV
16612
16822
  }
16613
16823
  return OAuthMetadataSchema.parse(await response.json());
16614
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
+ }
16615
16889
  async function startAuthorization(authorizationServerUrl, { metadata, clientInformation, redirectUrl, scope, state, resource }) {
16616
16890
  const responseType = "code";
16617
16891
  const codeChallengeMethod = "S256";
@@ -16641,12 +16915,15 @@ async function startAuthorization(authorizationServerUrl, { metadata, clientInfo
16641
16915
  if (scope) {
16642
16916
  authorizationUrl.searchParams.set("scope", scope);
16643
16917
  }
16918
+ if (scope === null || scope === void 0 ? void 0 : scope.includes("offline_access")) {
16919
+ authorizationUrl.searchParams.append("prompt", "consent");
16920
+ }
16644
16921
  if (resource) {
16645
16922
  authorizationUrl.searchParams.set("resource", resource.href);
16646
16923
  }
16647
16924
  return { authorizationUrl, codeVerifier };
16648
16925
  }
16649
- async function exchangeAuthorization(authorizationServerUrl, { metadata, clientInformation, authorizationCode, codeVerifier, redirectUri, resource, addClientAuthentication }) {
16926
+ async function exchangeAuthorization(authorizationServerUrl, { metadata, clientInformation, authorizationCode, codeVerifier, redirectUri, resource, addClientAuthentication, fetchFn }) {
16650
16927
  var _a;
16651
16928
  const grantType = "authorization_code";
16652
16929
  const tokenUrl = (metadata === null || metadata === void 0 ? void 0 : metadata.token_endpoint) ? new URL(metadata.token_endpoint) : new URL("/token", authorizationServerUrl);
@@ -16654,7 +16931,8 @@ async function exchangeAuthorization(authorizationServerUrl, { metadata, clientI
16654
16931
  throw new Error(`Incompatible auth server: does not support grant type ${grantType}`);
16655
16932
  }
16656
16933
  const headers = new Headers({
16657
- "Content-Type": "application/x-www-form-urlencoded"
16934
+ "Content-Type": "application/x-www-form-urlencoded",
16935
+ "Accept": "application/json"
16658
16936
  });
16659
16937
  const params = new URLSearchParams({
16660
16938
  grant_type: grantType,
@@ -16672,17 +16950,17 @@ async function exchangeAuthorization(authorizationServerUrl, { metadata, clientI
16672
16950
  if (resource) {
16673
16951
  params.set("resource", resource.href);
16674
16952
  }
16675
- const response = await fetch(tokenUrl, {
16953
+ const response = await (fetchFn !== null && fetchFn !== void 0 ? fetchFn : fetch)(tokenUrl, {
16676
16954
  method: "POST",
16677
16955
  headers,
16678
16956
  body: params
16679
16957
  });
16680
16958
  if (!response.ok) {
16681
- throw new Error(`Token exchange failed: HTTP ${response.status}`);
16959
+ throw await parseErrorResponse(response);
16682
16960
  }
16683
16961
  return OAuthTokensSchema.parse(await response.json());
16684
16962
  }
16685
- async function refreshAuthorization(authorizationServerUrl, { metadata, clientInformation, refreshToken, resource, addClientAuthentication }) {
16963
+ async function refreshAuthorization(authorizationServerUrl, { metadata, clientInformation, refreshToken, resource, addClientAuthentication, fetchFn }) {
16686
16964
  var _a;
16687
16965
  const grantType = "refresh_token";
16688
16966
  let tokenUrl;
@@ -16711,17 +16989,17 @@ async function refreshAuthorization(authorizationServerUrl, { metadata, clientIn
16711
16989
  if (resource) {
16712
16990
  params.set("resource", resource.href);
16713
16991
  }
16714
- const response = await fetch(tokenUrl, {
16992
+ const response = await (fetchFn !== null && fetchFn !== void 0 ? fetchFn : fetch)(tokenUrl, {
16715
16993
  method: "POST",
16716
16994
  headers,
16717
16995
  body: params
16718
16996
  });
16719
16997
  if (!response.ok) {
16720
- throw new Error(`Token refresh failed: HTTP ${response.status}`);
16998
+ throw await parseErrorResponse(response);
16721
16999
  }
16722
17000
  return OAuthTokensSchema.parse({ refresh_token: refreshToken, ...await response.json() });
16723
17001
  }
16724
- async function registerClient(authorizationServerUrl, { metadata, clientMetadata }) {
17002
+ async function registerClient(authorizationServerUrl, { metadata, clientMetadata, fetchFn }) {
16725
17003
  let registrationUrl;
16726
17004
  if (metadata) {
16727
17005
  if (!metadata.registration_endpoint) {
@@ -16731,7 +17009,7 @@ async function registerClient(authorizationServerUrl, { metadata, clientMetadata
16731
17009
  } else {
16732
17010
  registrationUrl = new URL("/register", authorizationServerUrl);
16733
17011
  }
16734
- const response = await fetch(registrationUrl, {
17012
+ const response = await (fetchFn !== null && fetchFn !== void 0 ? fetchFn : fetch)(registrationUrl, {
16735
17013
  method: "POST",
16736
17014
  headers: {
16737
17015
  "Content-Type": "application/json"
@@ -16739,7 +17017,7 @@ async function registerClient(authorizationServerUrl, { metadata, clientMetadata
16739
17017
  body: JSON.stringify(clientMetadata)
16740
17018
  });
16741
17019
  if (!response.ok) {
16742
- throw new Error(`Dynamic client registration failed: HTTP ${response.status}`);
17020
+ throw await parseErrorResponse(response);
16743
17021
  }
16744
17022
  return OAuthClientInformationFullSchema.parse(await response.json());
16745
17023
  }
@@ -23023,6 +23301,7 @@ class Protocol {
23023
23301
  this._responseHandlers = /* @__PURE__ */ new Map();
23024
23302
  this._progressHandlers = /* @__PURE__ */ new Map();
23025
23303
  this._timeoutInfo = /* @__PURE__ */ new Map();
23304
+ this._pendingDebouncedNotifications = /* @__PURE__ */ new Set();
23026
23305
  this.setNotificationHandler(CancelledNotificationSchema, (notification) => {
23027
23306
  const controller = this._requestHandlerAbortControllers.get(notification.params.requestId);
23028
23307
  controller === null || controller === void 0 ? void 0 : controller.abort(notification.params.reason);
@@ -23104,6 +23383,7 @@ class Protocol {
23104
23383
  const responseHandlers = this._responseHandlers;
23105
23384
  this._responseHandlers = /* @__PURE__ */ new Map();
23106
23385
  this._progressHandlers.clear();
23386
+ this._pendingDebouncedNotifications.clear();
23107
23387
  this._transport = void 0;
23108
23388
  (_a = this.onclose) === null || _a === void 0 ? void 0 : _a.call(this);
23109
23389
  const error = new McpError(ErrorCode.ConnectionClosed, "Connection closed");
@@ -23303,10 +23583,32 @@ class Protocol {
23303
23583
  * Emits a notification, which is a one-way message that does not expect a response.
23304
23584
  */
23305
23585
  async notification(notification, options) {
23586
+ var _a, _b;
23306
23587
  if (!this._transport) {
23307
23588
  throw new Error("Not connected");
23308
23589
  }
23309
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
+ }
23310
23612
  const jsonrpcNotification = {
23311
23613
  ...notification,
23312
23614
  jsonrpc: "2.0"
@@ -23981,7 +24283,7 @@ class SSEClientTransport {
23981
24283
  }
23982
24284
  let result;
23983
24285
  try {
23984
- 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 });
23985
24287
  } catch (error) {
23986
24288
  (_a = this.onerror) === null || _a === void 0 ? void 0 : _a.call(this, error);
23987
24289
  throw error;
@@ -24080,7 +24382,7 @@ class SSEClientTransport {
24080
24382
  if (!this._authProvider) {
24081
24383
  throw new UnauthorizedError("No auth provider");
24082
24384
  }
24083
- 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 });
24084
24386
  if (result !== "AUTHORIZED") {
24085
24387
  throw new UnauthorizedError("Failed to authorize");
24086
24388
  }
@@ -24110,7 +24412,7 @@ class SSEClientTransport {
24110
24412
  if (!response.ok) {
24111
24413
  if (response.status === 401 && this._authProvider) {
24112
24414
  this._resourceMetadataUrl = extractResourceMetadataUrl(response);
24113
- 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 });
24114
24416
  if (result !== "AUTHORIZED") {
24115
24417
  throw new UnauthorizedError();
24116
24418
  }
@@ -24180,7 +24482,7 @@ class StreamableHTTPClientTransport {
24180
24482
  }
24181
24483
  let result;
24182
24484
  try {
24183
- 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 });
24184
24486
  } catch (error) {
24185
24487
  (_a = this.onerror) === null || _a === void 0 ? void 0 : _a.call(this, error);
24186
24488
  throw error;
@@ -24234,7 +24536,7 @@ class StreamableHTTPClientTransport {
24234
24536
  }
24235
24537
  throw new StreamableHTTPError(response.status, `Failed to open SSE stream: ${response.statusText}`);
24236
24538
  }
24237
- this._handleSseStream(response.body, options);
24539
+ this._handleSseStream(response.body, options, true);
24238
24540
  } catch (error) {
24239
24541
  (_c = this.onerror) === null || _c === void 0 ? void 0 : _c.call(this, error);
24240
24542
  throw error;
@@ -24285,7 +24587,7 @@ class StreamableHTTPClientTransport {
24285
24587
  });
24286
24588
  }, delay);
24287
24589
  }
24288
- _handleSseStream(stream, options) {
24590
+ _handleSseStream(stream, options, isReconnectable) {
24289
24591
  if (!stream) {
24290
24592
  return;
24291
24593
  }
@@ -24318,17 +24620,15 @@ class StreamableHTTPClientTransport {
24318
24620
  }
24319
24621
  } catch (error) {
24320
24622
  (_c = this.onerror) === null || _c === void 0 ? void 0 : _c.call(this, new Error(`SSE stream disconnected: ${error}`));
24321
- if (this._abortController && !this._abortController.signal.aborted) {
24322
- if (lastEventId !== void 0) {
24323
- try {
24324
- this._scheduleReconnection({
24325
- resumptionToken: lastEventId,
24326
- onresumptiontoken,
24327
- replayMessageId
24328
- }, 0);
24329
- } catch (error2) {
24330
- (_d = this.onerror) === null || _d === void 0 ? void 0 : _d.call(this, new Error(`Failed to reconnect: ${error2 instanceof Error ? error2.message : String(error2)}`));
24331
- }
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)}`));
24332
24632
  }
24333
24633
  }
24334
24634
  }
@@ -24348,7 +24648,7 @@ class StreamableHTTPClientTransport {
24348
24648
  if (!this._authProvider) {
24349
24649
  throw new UnauthorizedError("No auth provider");
24350
24650
  }
24351
- 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 });
24352
24652
  if (result !== "AUTHORIZED") {
24353
24653
  throw new UnauthorizedError("Failed to authorize");
24354
24654
  }
@@ -24387,7 +24687,7 @@ class StreamableHTTPClientTransport {
24387
24687
  if (!response.ok) {
24388
24688
  if (response.status === 401 && this._authProvider) {
24389
24689
  this._resourceMetadataUrl = extractResourceMetadataUrl(response);
24390
- 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 });
24391
24691
  if (result !== "AUTHORIZED") {
24392
24692
  throw new UnauthorizedError();
24393
24693
  }
@@ -24410,7 +24710,7 @@ class StreamableHTTPClientTransport {
24410
24710
  const contentType = response.headers.get("content-type");
24411
24711
  if (hasRequests) {
24412
24712
  if (contentType === null || contentType === void 0 ? void 0 : contentType.includes("text/event-stream")) {
24413
- this._handleSseStream(response.body, { onresumptiontoken });
24713
+ this._handleSseStream(response.body, { onresumptiontoken }, false);
24414
24714
  } else if (contentType === null || contentType === void 0 ? void 0 : contentType.includes("application/json")) {
24415
24715
  const data2 = await response.json();
24416
24716
  const responseMessages = Array.isArray(data2) ? data2.map((msg) => JSONRPCMessageSchema.parse(msg)) : [JSONRPCMessageSchema.parse(data2)];
@@ -24479,7 +24779,7 @@ const StdErrNotificationSchema = NotificationSchema.extend({
24479
24779
  ClientNotificationSchema.or(
24480
24780
  StdErrNotificationSchema
24481
24781
  ).or(ServerNotificationSchema).or(NotificationSchema);
24482
- const version$1 = "0.16.1";
24782
+ const version$1 = "0.16.2";
24483
24783
  const packageJson = {
24484
24784
  version: version$1
24485
24785
  };
@@ -24607,10 +24907,13 @@ function useConnection({
24607
24907
  env,
24608
24908
  bearerToken,
24609
24909
  headerName,
24910
+ oauthClientId,
24911
+ oauthScope,
24610
24912
  config,
24611
24913
  onNotification,
24612
24914
  onStdErrNotification,
24613
24915
  onPendingRequest,
24916
+ onElicitationRequest,
24614
24917
  getRoots
24615
24918
  }) {
24616
24919
  const [connectionStatus, setConnectionStatus] = reactExports.useState("disconnected");
@@ -24621,7 +24924,21 @@ function useConnection({
24621
24924
  null
24622
24925
  );
24623
24926
  const [requestHistory, setRequestHistory] = reactExports.useState([]);
24624
- 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]);
24625
24942
  const pushHistory = (request, response) => {
24626
24943
  setRequestHistory((prev) => [
24627
24944
  ...prev,
@@ -24760,7 +25077,10 @@ function useConnection({
24760
25077
  const handleAuthError = async (error) => {
24761
25078
  if (is401Error(error)) {
24762
25079
  const serverAuthProvider = new InspectorOAuthClientProvider(sseUrl);
24763
- const result = await auth(serverAuthProvider, { serverUrl: sseUrl });
25080
+ const result = await auth(serverAuthProvider, {
25081
+ serverUrl: sseUrl,
25082
+ scope: oauthScope
25083
+ });
24764
25084
  return result === "AUTHORIZED";
24765
25085
  }
24766
25086
  return false;
@@ -24775,6 +25095,7 @@ function useConnection({
24775
25095
  {
24776
25096
  capabilities: {
24777
25097
  sampling: {},
25098
+ elicitation: {},
24778
25099
  roots: {
24779
25100
  listChanged: true
24780
25101
  }
@@ -24934,7 +25255,7 @@ function useConnection({
24934
25255
  throw error;
24935
25256
  }
24936
25257
  setServerCapabilities(capabilities ?? null);
24937
- setCompletionsSupported(true);
25258
+ setCompletionsSupported((capabilities == null ? void 0 : capabilities.completions) !== void 0);
24938
25259
  if (onPendingRequest) {
24939
25260
  client2.setRequestHandler(CreateMessageRequestSchema, (request) => {
24940
25261
  return new Promise((resolve, reject) => {
@@ -24947,6 +25268,13 @@ function useConnection({
24947
25268
  return { roots: getRoots() };
24948
25269
  });
24949
25270
  }
25271
+ if (onElicitationRequest) {
25272
+ client2.setRequestHandler(ElicitRequestSchema, async (request) => {
25273
+ return new Promise((resolve) => {
25274
+ onElicitationRequest(request, resolve);
25275
+ });
25276
+ });
25277
+ }
24950
25278
  setMcpClient(client2);
24951
25279
  setConnectionStatus("connected");
24952
25280
  } catch (e) {
@@ -34003,10 +34331,10 @@ const JsonEditor = ({
34003
34331
  };
34004
34332
  const isSimpleObject = (schema) => {
34005
34333
  const supportedTypes = ["string", "number", "integer", "boolean", "null"];
34006
- if (supportedTypes.includes(schema.type)) return true;
34334
+ if (schema.type && supportedTypes.includes(schema.type)) return true;
34007
34335
  if (schema.type === "object") {
34008
34336
  return Object.values(schema.properties ?? {}).every(
34009
- (prop) => supportedTypes.includes(prop.type)
34337
+ (prop) => prop.type && supportedTypes.includes(prop.type)
34010
34338
  );
34011
34339
  }
34012
34340
  if (schema.type === "array") {
@@ -34130,20 +34458,95 @@ const DynamicJsonForm = ({
34130
34458
  }
34131
34459
  const isRequired = ((_a = parentSchema == null ? void 0 : parentSchema.required) == null ? void 0 : _a.includes(propertyName || "")) ?? false;
34132
34460
  switch (propSchema.type) {
34133
- 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
+ }
34134
34533
  return /* @__PURE__ */ jsxRuntimeExports.jsx(
34135
34534
  Input,
34136
34535
  {
34137
- type: "text",
34536
+ type: inputType,
34138
34537
  value: currentValue ?? "",
34139
34538
  onChange: (e) => {
34140
34539
  const val = e.target.value;
34141
34540
  handleFieldChange(path, val);
34142
34541
  },
34143
34542
  placeholder: propSchema.description,
34144
- required: isRequired
34543
+ required: isRequired,
34544
+ minLength: propSchema.minLength,
34545
+ maxLength: propSchema.maxLength,
34546
+ pattern: propSchema.pattern
34145
34547
  }
34146
34548
  );
34549
+ }
34147
34550
  case "number":
34148
34551
  return /* @__PURE__ */ jsxRuntimeExports.jsx(
34149
34552
  Input,
@@ -34162,7 +34565,9 @@ const DynamicJsonForm = ({
34162
34565
  }
34163
34566
  },
34164
34567
  placeholder: propSchema.description,
34165
- required: isRequired
34568
+ required: isRequired,
34569
+ min: propSchema.minimum,
34570
+ max: propSchema.maximum
34166
34571
  }
34167
34572
  );
34168
34573
  case "integer":
@@ -34184,7 +34589,9 @@ const DynamicJsonForm = ({
34184
34589
  }
34185
34590
  },
34186
34591
  placeholder: propSchema.description,
34187
- required: isRequired
34592
+ required: isRequired,
34593
+ min: propSchema.minimum,
34594
+ max: propSchema.maximum
34188
34595
  }
34189
34596
  );
34190
34597
  case "boolean":
@@ -35856,7 +36263,7 @@ const useTheme = () => {
35856
36263
  [theme, setThemeWithSideEffect]
35857
36264
  );
35858
36265
  };
35859
- const version = "0.16.1";
36266
+ const version = "0.16.2";
35860
36267
  var [createTooltipContext, createTooltipScope] = createContextScope("Tooltip", [
35861
36268
  createPopperScope
35862
36269
  ]);
@@ -36355,6 +36762,10 @@ const Sidebar = ({
36355
36762
  setBearerToken,
36356
36763
  headerName,
36357
36764
  setHeaderName,
36765
+ oauthClientId,
36766
+ setOauthClientId,
36767
+ oauthScope,
36768
+ setOauthScope,
36358
36769
  onConnect,
36359
36770
  onDisconnect,
36360
36771
  stdErrNotifications,
@@ -36367,7 +36778,7 @@ const Sidebar = ({
36367
36778
  }) => {
36368
36779
  const [theme, setTheme] = useTheme();
36369
36780
  const [showEnvVars, setShowEnvVars] = reactExports.useState(false);
36370
- const [showBearerToken, setShowBearerToken] = reactExports.useState(false);
36781
+ const [showAuthConfig, setShowAuthConfig] = reactExports.useState(false);
36371
36782
  const [showConfig, setShowConfig] = reactExports.useState(false);
36372
36783
  const [shownEnvVars, setShownEnvVars] = reactExports.useState(/* @__PURE__ */ new Set());
36373
36784
  const [copiedServerEntry, setCopiedServerEntry] = reactExports.useState(false);
@@ -36524,22 +36935,10 @@ const Sidebar = ({
36524
36935
  }
36525
36936
  )
36526
36937
  ] })
36527
- ] }) : /* @__PURE__ */ jsxRuntimeExports.jsxs(jsxRuntimeExports.Fragment, { children: [
36528
- /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "space-y-2", children: [
36529
- /* @__PURE__ */ jsxRuntimeExports.jsx("label", { className: "text-sm font-medium", htmlFor: "sse-url-input", children: "URL" }),
36530
- sseUrl ? /* @__PURE__ */ jsxRuntimeExports.jsxs(Tooltip, { children: [
36531
- /* @__PURE__ */ jsxRuntimeExports.jsx(TooltipTrigger, { asChild: true, children: /* @__PURE__ */ jsxRuntimeExports.jsx(
36532
- Input,
36533
- {
36534
- id: "sse-url-input",
36535
- placeholder: "URL",
36536
- value: sseUrl,
36537
- onChange: (e) => setSseUrl(e.target.value),
36538
- className: "font-mono"
36539
- }
36540
- ) }),
36541
- /* @__PURE__ */ jsxRuntimeExports.jsx(TooltipContent, { children: sseUrl })
36542
- ] }) : /* @__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(
36543
36942
  Input,
36544
36943
  {
36545
36944
  id: "sse-url-input",
@@ -36548,58 +36947,19 @@ const Sidebar = ({
36548
36947
  onChange: (e) => setSseUrl(e.target.value),
36549
36948
  className: "font-mono"
36550
36949
  }
36551
- )
36552
- ] }),
36553
- /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "space-y-2", children: [
36554
- /* @__PURE__ */ jsxRuntimeExports.jsxs(
36555
- Button,
36556
- {
36557
- variant: "outline",
36558
- onClick: () => setShowBearerToken(!showBearerToken),
36559
- className: "flex items-center w-full",
36560
- "data-testid": "auth-button",
36561
- "aria-expanded": showBearerToken,
36562
- children: [
36563
- showBearerToken ? /* @__PURE__ */ jsxRuntimeExports.jsx(ChevronDown, { className: "w-4 h-4 mr-2" }) : /* @__PURE__ */ jsxRuntimeExports.jsx(ChevronRight, { className: "w-4 h-4 mr-2" }),
36564
- "Authentication"
36565
- ]
36566
- }
36567
- ),
36568
- showBearerToken && /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "space-y-2", children: [
36569
- /* @__PURE__ */ jsxRuntimeExports.jsx("label", { className: "text-sm font-medium", children: "Header Name" }),
36570
- /* @__PURE__ */ jsxRuntimeExports.jsx(
36571
- Input,
36572
- {
36573
- placeholder: "Authorization",
36574
- onChange: (e) => setHeaderName && setHeaderName(e.target.value),
36575
- "data-testid": "header-input",
36576
- className: "font-mono",
36577
- value: headerName
36578
- }
36579
- ),
36580
- /* @__PURE__ */ jsxRuntimeExports.jsx(
36581
- "label",
36582
- {
36583
- className: "text-sm font-medium",
36584
- htmlFor: "bearer-token-input",
36585
- children: "Bearer Token"
36586
- }
36587
- ),
36588
- /* @__PURE__ */ jsxRuntimeExports.jsx(
36589
- Input,
36590
- {
36591
- id: "bearer-token-input",
36592
- placeholder: "Bearer Token",
36593
- value: bearerToken,
36594
- onChange: (e) => setBearerToken(e.target.value),
36595
- "data-testid": "bearer-token-input",
36596
- className: "font-mono",
36597
- type: "password"
36598
- }
36599
- )
36600
- ] })
36601
- ] })
36602
- ] }),
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
+ ] }) }),
36603
36963
  transportType === "stdio" && /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "space-y-2", children: [
36604
36964
  /* @__PURE__ */ jsxRuntimeExports.jsxs(
36605
36965
  Button,
@@ -36755,6 +37115,98 @@ const Sidebar = ({
36755
37115
  /* @__PURE__ */ jsxRuntimeExports.jsx(TooltipContent, { children: "Copy Servers File" })
36756
37116
  ] })
36757
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
+ ] }),
36758
37210
  /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "space-y-2", children: [
36759
37211
  /* @__PURE__ */ jsxRuntimeExports.jsxs(
36760
37212
  Button,
@@ -37302,42 +37754,112 @@ const Textarea = reactExports.forwardRef(
37302
37754
  }
37303
37755
  );
37304
37756
  Textarea.displayName = "Textarea";
37305
- const checkContentCompatibility = (structuredContent, unstructuredContent) => {
37306
- if (unstructuredContent.length !== 1 || unstructuredContent[0].type !== "text") {
37307
- return {
37308
- isCompatible: false,
37309
- message: "Unstructured content is not a single text block"
37310
- };
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
+ ] });
37311
37822
  }
37312
- const textContent = unstructuredContent[0].text;
37313
- if (!textContent) {
37823
+ );
37824
+ const checkContentCompatibility = (structuredContent, unstructuredContent) => {
37825
+ const textBlocks = unstructuredContent.filter(
37826
+ (block) => block.type === "text"
37827
+ );
37828
+ if (textBlocks.length === 0) {
37314
37829
  return {
37315
37830
  isCompatible: false,
37316
- message: "Text content is empty"
37831
+ message: "No text blocks to match structured content"
37317
37832
  };
37318
37833
  }
37319
- try {
37320
- const parsedContent = JSON.parse(textContent);
37321
- const isEqual = JSON.stringify(parsedContent) === JSON.stringify(structuredContent);
37322
- if (isEqual) {
37323
- return {
37324
- isCompatible: true,
37325
- message: "Unstructured content matches structured content"
37326
- };
37327
- } else {
37328
- return {
37329
- isCompatible: false,
37330
- message: "Parsed JSON does not match structured content"
37331
- };
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;
37332
37850
  }
37333
- } catch {
37334
- return {
37335
- isCompatible: false,
37336
- message: "Unstructured content is not valid JSON"
37337
- };
37338
37851
  }
37852
+ return {
37853
+ isCompatible: false,
37854
+ message: "No text block matches structured content"
37855
+ };
37339
37856
  };
37340
- const ToolResults = ({ toolResult, selectedTool }) => {
37857
+ const ToolResults = ({
37858
+ toolResult,
37859
+ selectedTool,
37860
+ resourceContent,
37861
+ onReadResource
37862
+ }) => {
37341
37863
  if (!toolResult) return null;
37342
37864
  if ("content" in toolResult) {
37343
37865
  const parsedResult = CallToolResultSchema.safeParse(toolResult);
@@ -37434,7 +37956,18 @@ const ToolResults = ({ toolResult, selectedTool }) => {
37434
37956
  className: "w-full",
37435
37957
  children: /* @__PURE__ */ jsxRuntimeExports.jsx("p", { children: "Your browser does not support audio playback" })
37436
37958
  }
37437
- ) : /* @__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
+ )
37438
37971
  ] }, index2);
37439
37972
  })
37440
37973
  ] })
@@ -37455,7 +37988,9 @@ const ToolsTab = ({
37455
37988
  selectedTool,
37456
37989
  setSelectedTool,
37457
37990
  toolResult,
37458
- nextCursor
37991
+ nextCursor,
37992
+ resourceContent,
37993
+ onReadResource
37459
37994
  }) => {
37460
37995
  const [params, setParams] = reactExports.useState({});
37461
37996
  const [isToolRunning, setIsToolRunning] = reactExports.useState(false);
@@ -37656,19 +38191,159 @@ const ToolsTab = ({
37656
38191
  ToolResults,
37657
38192
  {
37658
38193
  toolResult,
37659
- selectedTool
38194
+ selectedTool,
38195
+ resourceContent,
38196
+ onReadResource
37660
38197
  }
37661
38198
  )
37662
38199
  ] }) : /* @__PURE__ */ jsxRuntimeExports.jsx(Alert, { children: /* @__PURE__ */ jsxRuntimeExports.jsx(AlertDescription, { children: "Select a tool from the list to view its details and run it" }) }) })
37663
38200
  ] })
37664
38201
  ] }) });
37665
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
+ };
37666
38340
  const CONFIG_LOCAL_STORAGE_KEY = "inspectorConfig_v1";
37667
38341
  const App = () => {
37668
38342
  var _a;
37669
38343
  const [resources, setResources] = reactExports.useState([]);
37670
38344
  const [resourceTemplates, setResourceTemplates] = reactExports.useState([]);
37671
38345
  const [resourceContent, setResourceContent] = reactExports.useState("");
38346
+ const [resourceContentMap, setResourceContentMap] = reactExports.useState({});
37672
38347
  const [prompts, setPrompts] = reactExports.useState([]);
37673
38348
  const [promptContent, setPromptContent] = reactExports.useState("");
37674
38349
  const [tools, setTools] = reactExports.useState([]);
@@ -37696,7 +38371,14 @@ const App = () => {
37696
38371
  const [headerName, setHeaderName] = reactExports.useState(() => {
37697
38372
  return localStorage.getItem("lastHeaderName") || "";
37698
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
+ });
37699
38380
  const [pendingSampleRequests, setPendingSampleRequests] = reactExports.useState([]);
38381
+ const [pendingElicitationRequests, setPendingElicitationRequests] = reactExports.useState([]);
37700
38382
  const [isAuthDebuggerVisible, setIsAuthDebuggerVisible] = reactExports.useState(false);
37701
38383
  const [authState, setAuthState] = reactExports.useState(EMPTY_DEBUGGER_STATE);
37702
38384
  const updateAuthState = (updates) => {
@@ -37715,6 +38397,16 @@ const App = () => {
37715
38397
  const [nextPromptCursor, setNextPromptCursor] = reactExports.useState();
37716
38398
  const [nextToolCursor, setNextToolCursor] = reactExports.useState();
37717
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]);
37718
38410
  const { height: historyPaneHeight, handleDragStart } = useDraggablePane(300);
37719
38411
  const {
37720
38412
  width: sidebarWidth,
@@ -37740,6 +38432,8 @@ const App = () => {
37740
38432
  env,
37741
38433
  bearerToken,
37742
38434
  headerName,
38435
+ oauthClientId,
38436
+ oauthScope,
37743
38437
  config,
37744
38438
  onNotification: (notification) => {
37745
38439
  setNotifications((prev) => [...prev, notification]);
@@ -37756,8 +38450,50 @@ const App = () => {
37756
38450
  { id: nextRequestId.current++, request, resolve, reject }
37757
38451
  ]);
37758
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
+ },
37759
38474
  getRoots: () => rootsRef.current
37760
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]);
37761
38497
  reactExports.useEffect(() => {
37762
38498
  localStorage.setItem("lastCommand", command);
37763
38499
  }, [command]);
@@ -37776,6 +38512,12 @@ const App = () => {
37776
38512
  reactExports.useEffect(() => {
37777
38513
  localStorage.setItem("lastHeaderName", headerName);
37778
38514
  }, [headerName]);
38515
+ reactExports.useEffect(() => {
38516
+ localStorage.setItem("lastOauthClientId", oauthClientId);
38517
+ }, [oauthClientId]);
38518
+ reactExports.useEffect(() => {
38519
+ localStorage.setItem("lastOauthScope", oauthScope);
38520
+ }, [oauthScope]);
37779
38521
  reactExports.useEffect(() => {
37780
38522
  saveInspectorConfig(CONFIG_LOCAL_STORAGE_KEY, config);
37781
38523
  }, [config]);
@@ -37894,6 +38636,16 @@ const App = () => {
37894
38636
  window.location.hash = "resources";
37895
38637
  }
37896
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]);
37897
38649
  const handleApproveSampling = (id, result) => {
37898
38650
  setPendingSampleRequests((prev) => {
37899
38651
  const request = prev.find((r2) => r2.id === id);
@@ -37908,6 +38660,36 @@ const App = () => {
37908
38660
  return prev.filter((r2) => r2.id !== id);
37909
38661
  });
37910
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
+ };
37911
38693
  const clearError = (tabKey) => {
37912
38694
  setErrors((prev) => ({ ...prev, [tabKey]: null }));
37913
38695
  };
@@ -37955,7 +38737,20 @@ const App = () => {
37955
38737
  );
37956
38738
  setNextResourceTemplateCursor(response.nextCursor);
37957
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
+ };
37958
38752
  const readResource = async (uri) => {
38753
+ lastToolCallOriginTabRef.current = currentTabRef.current;
37959
38754
  const response = await sendMCPRequest(
37960
38755
  {
37961
38756
  method: "resources/read",
@@ -37964,7 +38759,12 @@ const App = () => {
37964
38759
  ReadResourceResultSchema,
37965
38760
  "resources"
37966
38761
  );
37967
- 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
+ }));
37968
38768
  };
37969
38769
  const subscribeToResource = async (uri) => {
37970
38770
  if (!resourceSubscriptions.has(uri)) {
@@ -38008,17 +38808,6 @@ const App = () => {
38008
38808
  setPrompts(response.prompts);
38009
38809
  setNextPromptCursor(response.nextCursor);
38010
38810
  };
38011
- const getPrompt = async (name, args2 = {}) => {
38012
- const response = await sendMCPRequest(
38013
- {
38014
- method: "prompts/get",
38015
- params: { name, arguments: args2 }
38016
- },
38017
- GetPromptResultSchema,
38018
- "prompts"
38019
- );
38020
- setPromptContent(JSON.stringify(response, null, 2));
38021
- };
38022
38811
  const listTools = async () => {
38023
38812
  const response = await sendMCPRequest(
38024
38813
  {
@@ -38033,6 +38822,7 @@ const App = () => {
38033
38822
  cacheToolOutputSchemas(response.tools);
38034
38823
  };
38035
38824
  const callTool = async (name, params) => {
38825
+ lastToolCallOriginTabRef.current = currentTabRef.current;
38036
38826
  try {
38037
38827
  const response = await sendMCPRequest(
38038
38828
  {
@@ -38089,13 +38879,13 @@ const App = () => {
38089
38879
  ) });
38090
38880
  if (window.location.pathname === "/oauth/callback") {
38091
38881
  const OAuthCallback = React.lazy(
38092
- () => __vitePreload(() => import("./OAuthCallback-CaDIOg8Q.js"), true ? __vite__mapDeps([0,1]) : void 0)
38882
+ () => __vitePreload(() => import("./OAuthCallback-CC1cu0Zx.js"), true ? __vite__mapDeps([0,1]) : void 0)
38093
38883
  );
38094
38884
  return /* @__PURE__ */ jsxRuntimeExports.jsx(reactExports.Suspense, { fallback: /* @__PURE__ */ jsxRuntimeExports.jsx("div", { children: "Loading..." }), children: /* @__PURE__ */ jsxRuntimeExports.jsx(OAuthCallback, { onConnect: onOAuthConnect }) });
38095
38885
  }
38096
38886
  if (window.location.pathname === "/oauth/callback/debug") {
38097
38887
  const OAuthDebugCallback = React.lazy(
38098
- () => __vitePreload(() => import("./OAuthDebugCallback-Ccjj44Wa.js"), true ? __vite__mapDeps([2,1]) : void 0)
38888
+ () => __vitePreload(() => import("./OAuthDebugCallback-_4BLxVDe.js"), true ? __vite__mapDeps([2,1]) : void 0)
38099
38889
  );
38100
38890
  return /* @__PURE__ */ jsxRuntimeExports.jsx(reactExports.Suspense, { fallback: /* @__PURE__ */ jsxRuntimeExports.jsx("div", { children: "Loading..." }), children: /* @__PURE__ */ jsxRuntimeExports.jsx(OAuthDebugCallback, { onConnect: onOAuthDebugConnect }) });
38101
38891
  }
@@ -38131,6 +38921,10 @@ const App = () => {
38131
38921
  setBearerToken,
38132
38922
  headerName,
38133
38923
  setHeaderName,
38924
+ oauthClientId,
38925
+ setOauthClientId,
38926
+ oauthScope,
38927
+ setOauthScope,
38134
38928
  onConnect: connectMcpServer,
38135
38929
  onDisconnect: disconnectMcpServer,
38136
38930
  stdErrNotifications,
@@ -38165,11 +38959,12 @@ const App = () => {
38165
38959
  /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "flex-1 overflow-auto", children: mcpClient ? /* @__PURE__ */ jsxRuntimeExports.jsxs(
38166
38960
  Tabs,
38167
38961
  {
38168
- defaultValue: Object.keys(serverCapabilities ?? {}).includes(
38169
- window.location.hash.slice(1)
38170
- ) ? 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,
38171
38963
  className: "w-full p-4",
38172
- onValueChange: (value) => window.location.hash = value,
38964
+ onValueChange: (value) => {
38965
+ setActiveTab(value);
38966
+ window.location.hash = value;
38967
+ },
38173
38968
  children: [
38174
38969
  /* @__PURE__ */ jsxRuntimeExports.jsxs(TabsList, { className: "mb-4 py-0", children: [
38175
38970
  /* @__PURE__ */ jsxRuntimeExports.jsxs(
@@ -38214,6 +39009,11 @@ const App = () => {
38214
39009
  "Sampling",
38215
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 })
38216
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
+ ] }),
38217
39017
  /* @__PURE__ */ jsxRuntimeExports.jsxs(TabsTrigger, { value: "roots", children: [
38218
39018
  /* @__PURE__ */ jsxRuntimeExports.jsx(FolderTree, { className: "w-4 h-4 mr-2" }),
38219
39019
  "Roots"
@@ -38342,7 +39142,12 @@ const App = () => {
38342
39142
  },
38343
39143
  toolResult,
38344
39144
  nextCursor: nextToolCursor,
38345
- error: errors.tools
39145
+ error: errors.tools,
39146
+ resourceContent: resourceContentMap,
39147
+ onReadResource: (uri) => {
39148
+ clearError("resources");
39149
+ readResource(uri);
39150
+ }
38346
39151
  }
38347
39152
  ),
38348
39153
  /* @__PURE__ */ jsxRuntimeExports.jsx(ConsoleTab, {}),
@@ -38367,6 +39172,13 @@ const App = () => {
38367
39172
  onReject: handleRejectSampling
38368
39173
  }
38369
39174
  ),
39175
+ /* @__PURE__ */ jsxRuntimeExports.jsx(
39176
+ ElicitationTab,
39177
+ {
39178
+ pendingRequests: pendingElicitationRequests,
39179
+ onResolve: handleResolveElicitation
39180
+ }
39181
+ ),
38370
39182
  /* @__PURE__ */ jsxRuntimeExports.jsx(
38371
39183
  RootsTab,
38372
39184
  {