@modelcontextprotocol/inspector 0.16.1 → 0.16.3

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-DCwiUoWl.js","assets/oauthUtils-DTcoXpSP.js","assets/OAuthDebugCallback-BNuktUej.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
  );
@@ -16317,10 +16403,10 @@ class DebugInspectorOAuthClientProvider extends InspectorOAuthClientProvider {
16317
16403
  );
16318
16404
  }
16319
16405
  }
16320
- let crypto;
16321
- crypto = globalThis.crypto;
16406
+ let crypto$1;
16407
+ crypto$1 = globalThis.crypto;
16322
16408
  async function getRandomValues(size2) {
16323
- return (await crypto).getRandomValues(new Uint8Array(size2));
16409
+ return (await crypto$1).getRandomValues(new Uint8Array(size2));
16324
16410
  }
16325
16411
  async function random(size2) {
16326
16412
  const mask = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789-._~";
@@ -16336,7 +16422,7 @@ async function generateVerifier(length) {
16336
16422
  return await random(length);
16337
16423
  }
16338
16424
  async function generateChallenge(code_verifier) {
16339
- const buffer = await (await crypto).subtle.digest("SHA-256", new TextEncoder().encode(code_verifier));
16425
+ const buffer = await (await crypto$1).subtle.digest("SHA-256", new TextEncoder().encode(code_verifier));
16340
16426
  return btoa(String.fromCharCode(...new Uint8Array(buffer))).replace(/\//g, "_").replace(/\+/g, "-").replace(/=/g, "");
16341
16427
  }
16342
16428
  async function pkceChallenge(length) {
@@ -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
+ continue;
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
  }
@@ -16817,6 +17095,12 @@ const oauthTransitions = {
16817
17095
  if (metadata.scopes_supported) {
16818
17096
  scope = metadata.scopes_supported.join(" ");
16819
17097
  }
17098
+ const array = new Uint8Array(32);
17099
+ crypto.getRandomValues(array);
17100
+ const state = Array.from(
17101
+ array,
17102
+ (byte) => byte.toString(16).padStart(2, "0")
17103
+ ).join("");
16820
17104
  const { authorizationUrl, codeVerifier } = await startAuthorization(
16821
17105
  context.serverUrl,
16822
17106
  {
@@ -16824,6 +17108,7 @@ const oauthTransitions = {
16824
17108
  clientInformation,
16825
17109
  redirectUrl: context.provider.redirectUrl,
16826
17110
  scope,
17111
+ state,
16827
17112
  resource: context.state.resource ?? void 0
16828
17113
  }
16829
17114
  );
@@ -23023,6 +23308,7 @@ class Protocol {
23023
23308
  this._responseHandlers = /* @__PURE__ */ new Map();
23024
23309
  this._progressHandlers = /* @__PURE__ */ new Map();
23025
23310
  this._timeoutInfo = /* @__PURE__ */ new Map();
23311
+ this._pendingDebouncedNotifications = /* @__PURE__ */ new Set();
23026
23312
  this.setNotificationHandler(CancelledNotificationSchema, (notification) => {
23027
23313
  const controller = this._requestHandlerAbortControllers.get(notification.params.requestId);
23028
23314
  controller === null || controller === void 0 ? void 0 : controller.abort(notification.params.reason);
@@ -23104,6 +23390,7 @@ class Protocol {
23104
23390
  const responseHandlers = this._responseHandlers;
23105
23391
  this._responseHandlers = /* @__PURE__ */ new Map();
23106
23392
  this._progressHandlers.clear();
23393
+ this._pendingDebouncedNotifications.clear();
23107
23394
  this._transport = void 0;
23108
23395
  (_a = this.onclose) === null || _a === void 0 ? void 0 : _a.call(this);
23109
23396
  const error = new McpError(ErrorCode.ConnectionClosed, "Connection closed");
@@ -23124,10 +23411,11 @@ class Protocol {
23124
23411
  Promise.resolve().then(() => handler(notification)).catch((error) => this._onerror(new Error(`Uncaught error in notification handler: ${error}`)));
23125
23412
  }
23126
23413
  _onrequest(request, extra) {
23127
- var _a, _b, _c, _d;
23414
+ var _a, _b;
23128
23415
  const handler = (_a = this._requestHandlers.get(request.method)) !== null && _a !== void 0 ? _a : this.fallbackRequestHandler;
23416
+ const capturedTransport = this._transport;
23129
23417
  if (handler === void 0) {
23130
- (_b = this._transport) === null || _b === void 0 ? void 0 : _b.send({
23418
+ capturedTransport === null || capturedTransport === void 0 ? void 0 : capturedTransport.send({
23131
23419
  jsonrpc: "2.0",
23132
23420
  id: request.id,
23133
23421
  error: {
@@ -23141,8 +23429,8 @@ class Protocol {
23141
23429
  this._requestHandlerAbortControllers.set(request.id, abortController);
23142
23430
  const fullExtra = {
23143
23431
  signal: abortController.signal,
23144
- sessionId: (_c = this._transport) === null || _c === void 0 ? void 0 : _c.sessionId,
23145
- _meta: (_d = request.params) === null || _d === void 0 ? void 0 : _d._meta,
23432
+ sessionId: capturedTransport === null || capturedTransport === void 0 ? void 0 : capturedTransport.sessionId,
23433
+ _meta: (_b = request.params) === null || _b === void 0 ? void 0 : _b._meta,
23146
23434
  sendNotification: (notification) => this.notification(notification, { relatedRequestId: request.id }),
23147
23435
  sendRequest: (r2, resultSchema, options) => this.request(r2, resultSchema, { ...options, relatedRequestId: request.id }),
23148
23436
  authInfo: extra === null || extra === void 0 ? void 0 : extra.authInfo,
@@ -23150,26 +23438,25 @@ class Protocol {
23150
23438
  requestInfo: extra === null || extra === void 0 ? void 0 : extra.requestInfo
23151
23439
  };
23152
23440
  Promise.resolve().then(() => handler(request, fullExtra)).then((result) => {
23153
- var _a2;
23154
23441
  if (abortController.signal.aborted) {
23155
23442
  return;
23156
23443
  }
23157
- return (_a2 = this._transport) === null || _a2 === void 0 ? void 0 : _a2.send({
23444
+ return capturedTransport === null || capturedTransport === void 0 ? void 0 : capturedTransport.send({
23158
23445
  result,
23159
23446
  jsonrpc: "2.0",
23160
23447
  id: request.id
23161
23448
  });
23162
23449
  }, (error) => {
23163
- var _a2, _b2;
23450
+ var _a2;
23164
23451
  if (abortController.signal.aborted) {
23165
23452
  return;
23166
23453
  }
23167
- return (_a2 = this._transport) === null || _a2 === void 0 ? void 0 : _a2.send({
23454
+ return capturedTransport === null || capturedTransport === void 0 ? void 0 : capturedTransport.send({
23168
23455
  jsonrpc: "2.0",
23169
23456
  id: request.id,
23170
23457
  error: {
23171
23458
  code: Number.isSafeInteger(error["code"]) ? error["code"] : ErrorCode.InternalError,
23172
- message: (_b2 = error.message) !== null && _b2 !== void 0 ? _b2 : "Internal error"
23459
+ message: (_a2 = error.message) !== null && _a2 !== void 0 ? _a2 : "Internal error"
23173
23460
  }
23174
23461
  });
23175
23462
  }).catch((error) => this._onerror(new Error(`Failed to send response: ${error}`))).finally(() => {
@@ -23303,10 +23590,32 @@ class Protocol {
23303
23590
  * Emits a notification, which is a one-way message that does not expect a response.
23304
23591
  */
23305
23592
  async notification(notification, options) {
23593
+ var _a, _b;
23306
23594
  if (!this._transport) {
23307
23595
  throw new Error("Not connected");
23308
23596
  }
23309
23597
  this.assertNotificationCapability(notification.method);
23598
+ const debouncedMethods = (_b = (_a = this._options) === null || _a === void 0 ? void 0 : _a.debouncedNotificationMethods) !== null && _b !== void 0 ? _b : [];
23599
+ const canDebounce = debouncedMethods.includes(notification.method) && !notification.params && !(options === null || options === void 0 ? void 0 : options.relatedRequestId);
23600
+ if (canDebounce) {
23601
+ if (this._pendingDebouncedNotifications.has(notification.method)) {
23602
+ return;
23603
+ }
23604
+ this._pendingDebouncedNotifications.add(notification.method);
23605
+ Promise.resolve().then(() => {
23606
+ var _a2;
23607
+ this._pendingDebouncedNotifications.delete(notification.method);
23608
+ if (!this._transport) {
23609
+ return;
23610
+ }
23611
+ const jsonrpcNotification2 = {
23612
+ ...notification,
23613
+ jsonrpc: "2.0"
23614
+ };
23615
+ (_a2 = this._transport) === null || _a2 === void 0 ? void 0 : _a2.send(jsonrpcNotification2, options).catch((error) => this._onerror(error));
23616
+ });
23617
+ return;
23618
+ }
23310
23619
  const jsonrpcNotification = {
23311
23620
  ...notification,
23312
23621
  jsonrpc: "2.0"
@@ -23981,7 +24290,7 @@ class SSEClientTransport {
23981
24290
  }
23982
24291
  let result;
23983
24292
  try {
23984
- result = await auth(this._authProvider, { serverUrl: this._url, resourceMetadataUrl: this._resourceMetadataUrl });
24293
+ result = await auth(this._authProvider, { serverUrl: this._url, resourceMetadataUrl: this._resourceMetadataUrl, fetchFn: this._fetch });
23985
24294
  } catch (error) {
23986
24295
  (_a = this.onerror) === null || _a === void 0 ? void 0 : _a.call(this, error);
23987
24296
  throw error;
@@ -24080,7 +24389,7 @@ class SSEClientTransport {
24080
24389
  if (!this._authProvider) {
24081
24390
  throw new UnauthorizedError("No auth provider");
24082
24391
  }
24083
- const result = await auth(this._authProvider, { serverUrl: this._url, authorizationCode, resourceMetadataUrl: this._resourceMetadataUrl });
24392
+ const result = await auth(this._authProvider, { serverUrl: this._url, authorizationCode, resourceMetadataUrl: this._resourceMetadataUrl, fetchFn: this._fetch });
24084
24393
  if (result !== "AUTHORIZED") {
24085
24394
  throw new UnauthorizedError("Failed to authorize");
24086
24395
  }
@@ -24110,7 +24419,7 @@ class SSEClientTransport {
24110
24419
  if (!response.ok) {
24111
24420
  if (response.status === 401 && this._authProvider) {
24112
24421
  this._resourceMetadataUrl = extractResourceMetadataUrl(response);
24113
- const result = await auth(this._authProvider, { serverUrl: this._url, resourceMetadataUrl: this._resourceMetadataUrl });
24422
+ const result = await auth(this._authProvider, { serverUrl: this._url, resourceMetadataUrl: this._resourceMetadataUrl, fetchFn: this._fetch });
24114
24423
  if (result !== "AUTHORIZED") {
24115
24424
  throw new UnauthorizedError();
24116
24425
  }
@@ -24180,7 +24489,7 @@ class StreamableHTTPClientTransport {
24180
24489
  }
24181
24490
  let result;
24182
24491
  try {
24183
- result = await auth(this._authProvider, { serverUrl: this._url, resourceMetadataUrl: this._resourceMetadataUrl });
24492
+ result = await auth(this._authProvider, { serverUrl: this._url, resourceMetadataUrl: this._resourceMetadataUrl, fetchFn: this._fetch });
24184
24493
  } catch (error) {
24185
24494
  (_a = this.onerror) === null || _a === void 0 ? void 0 : _a.call(this, error);
24186
24495
  throw error;
@@ -24234,7 +24543,7 @@ class StreamableHTTPClientTransport {
24234
24543
  }
24235
24544
  throw new StreamableHTTPError(response.status, `Failed to open SSE stream: ${response.statusText}`);
24236
24545
  }
24237
- this._handleSseStream(response.body, options);
24546
+ this._handleSseStream(response.body, options, true);
24238
24547
  } catch (error) {
24239
24548
  (_c = this.onerror) === null || _c === void 0 ? void 0 : _c.call(this, error);
24240
24549
  throw error;
@@ -24285,7 +24594,7 @@ class StreamableHTTPClientTransport {
24285
24594
  });
24286
24595
  }, delay);
24287
24596
  }
24288
- _handleSseStream(stream, options) {
24597
+ _handleSseStream(stream, options, isReconnectable) {
24289
24598
  if (!stream) {
24290
24599
  return;
24291
24600
  }
@@ -24318,17 +24627,15 @@ class StreamableHTTPClientTransport {
24318
24627
  }
24319
24628
  } catch (error) {
24320
24629
  (_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
- }
24630
+ if (isReconnectable && this._abortController && !this._abortController.signal.aborted) {
24631
+ try {
24632
+ this._scheduleReconnection({
24633
+ resumptionToken: lastEventId,
24634
+ onresumptiontoken,
24635
+ replayMessageId
24636
+ }, 0);
24637
+ } catch (error2) {
24638
+ (_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
24639
  }
24333
24640
  }
24334
24641
  }
@@ -24348,7 +24655,7 @@ class StreamableHTTPClientTransport {
24348
24655
  if (!this._authProvider) {
24349
24656
  throw new UnauthorizedError("No auth provider");
24350
24657
  }
24351
- const result = await auth(this._authProvider, { serverUrl: this._url, authorizationCode, resourceMetadataUrl: this._resourceMetadataUrl });
24658
+ const result = await auth(this._authProvider, { serverUrl: this._url, authorizationCode, resourceMetadataUrl: this._resourceMetadataUrl, fetchFn: this._fetch });
24352
24659
  if (result !== "AUTHORIZED") {
24353
24660
  throw new UnauthorizedError("Failed to authorize");
24354
24661
  }
@@ -24387,7 +24694,7 @@ class StreamableHTTPClientTransport {
24387
24694
  if (!response.ok) {
24388
24695
  if (response.status === 401 && this._authProvider) {
24389
24696
  this._resourceMetadataUrl = extractResourceMetadataUrl(response);
24390
- const result = await auth(this._authProvider, { serverUrl: this._url, resourceMetadataUrl: this._resourceMetadataUrl });
24697
+ const result = await auth(this._authProvider, { serverUrl: this._url, resourceMetadataUrl: this._resourceMetadataUrl, fetchFn: this._fetch });
24391
24698
  if (result !== "AUTHORIZED") {
24392
24699
  throw new UnauthorizedError();
24393
24700
  }
@@ -24410,7 +24717,7 @@ class StreamableHTTPClientTransport {
24410
24717
  const contentType = response.headers.get("content-type");
24411
24718
  if (hasRequests) {
24412
24719
  if (contentType === null || contentType === void 0 ? void 0 : contentType.includes("text/event-stream")) {
24413
- this._handleSseStream(response.body, { onresumptiontoken });
24720
+ this._handleSseStream(response.body, { onresumptiontoken }, false);
24414
24721
  } else if (contentType === null || contentType === void 0 ? void 0 : contentType.includes("application/json")) {
24415
24722
  const data2 = await response.json();
24416
24723
  const responseMessages = Array.isArray(data2) ? data2.map((msg) => JSONRPCMessageSchema.parse(msg)) : [JSONRPCMessageSchema.parse(data2)];
@@ -24479,7 +24786,7 @@ const StdErrNotificationSchema = NotificationSchema.extend({
24479
24786
  ClientNotificationSchema.or(
24480
24787
  StdErrNotificationSchema
24481
24788
  ).or(ServerNotificationSchema).or(NotificationSchema);
24482
- const version$1 = "0.16.1";
24789
+ const version$1 = "0.16.3";
24483
24790
  const packageJson = {
24484
24791
  version: version$1
24485
24792
  };
@@ -24607,11 +24914,15 @@ function useConnection({
24607
24914
  env,
24608
24915
  bearerToken,
24609
24916
  headerName,
24917
+ oauthClientId,
24918
+ oauthScope,
24610
24919
  config,
24611
24920
  onNotification,
24612
24921
  onStdErrNotification,
24613
24922
  onPendingRequest,
24614
- getRoots
24923
+ onElicitationRequest,
24924
+ getRoots,
24925
+ defaultLoggingLevel
24615
24926
  }) {
24616
24927
  const [connectionStatus, setConnectionStatus] = reactExports.useState("disconnected");
24617
24928
  const { toast: toast2 } = useToast();
@@ -24621,7 +24932,21 @@ function useConnection({
24621
24932
  null
24622
24933
  );
24623
24934
  const [requestHistory, setRequestHistory] = reactExports.useState([]);
24624
- const [completionsSupported, setCompletionsSupported] = reactExports.useState(true);
24935
+ const [completionsSupported, setCompletionsSupported] = reactExports.useState(false);
24936
+ reactExports.useEffect(() => {
24937
+ if (!oauthClientId) {
24938
+ clearClientInformationFromSessionStorage({
24939
+ serverUrl: sseUrl,
24940
+ isPreregistered: true
24941
+ });
24942
+ return;
24943
+ }
24944
+ saveClientInformationToSessionStorage({
24945
+ serverUrl: sseUrl,
24946
+ clientInformation: { client_id: oauthClientId },
24947
+ isPreregistered: true
24948
+ });
24949
+ }, [oauthClientId, sseUrl]);
24625
24950
  const pushHistory = (request, response) => {
24626
24951
  setRequestHistory((prev) => [
24627
24952
  ...prev,
@@ -24675,7 +25000,7 @@ function useConnection({
24675
25000
  throw e;
24676
25001
  }
24677
25002
  };
24678
- const handleCompletion = async (ref2, argName, value, signal) => {
25003
+ const handleCompletion = async (ref2, argName, value, context, signal) => {
24679
25004
  if (!mcpClient || !completionsSupported) {
24680
25005
  return [];
24681
25006
  }
@@ -24689,6 +25014,11 @@ function useConnection({
24689
25014
  ref: ref2
24690
25015
  }
24691
25016
  };
25017
+ if (context) {
25018
+ request["params"]["context"] = {
25019
+ arguments: context
25020
+ };
25021
+ }
24692
25022
  try {
24693
25023
  const response = await makeRequest(request, CompleteResultSchema, {
24694
25024
  signal,
@@ -24760,7 +25090,10 @@ function useConnection({
24760
25090
  const handleAuthError = async (error) => {
24761
25091
  if (is401Error(error)) {
24762
25092
  const serverAuthProvider = new InspectorOAuthClientProvider(sseUrl);
24763
- const result = await auth(serverAuthProvider, { serverUrl: sseUrl });
25093
+ const result = await auth(serverAuthProvider, {
25094
+ serverUrl: sseUrl,
25095
+ scope: oauthScope
25096
+ });
24764
25097
  return result === "AUTHORIZED";
24765
25098
  }
24766
25099
  return false;
@@ -24775,6 +25108,7 @@ function useConnection({
24775
25108
  {
24776
25109
  capabilities: {
24777
25110
  sampling: {},
25111
+ elicitation: {},
24778
25112
  roots: {
24779
25113
  listChanged: true
24780
25114
  }
@@ -24934,7 +25268,7 @@ function useConnection({
24934
25268
  throw error;
24935
25269
  }
24936
25270
  setServerCapabilities(capabilities ?? null);
24937
- setCompletionsSupported(true);
25271
+ setCompletionsSupported((capabilities == null ? void 0 : capabilities.completions) !== void 0);
24938
25272
  if (onPendingRequest) {
24939
25273
  client2.setRequestHandler(CreateMessageRequestSchema, (request) => {
24940
25274
  return new Promise((resolve, reject) => {
@@ -24947,6 +25281,16 @@ function useConnection({
24947
25281
  return { roots: getRoots() };
24948
25282
  });
24949
25283
  }
25284
+ if ((capabilities == null ? void 0 : capabilities.logging) && defaultLoggingLevel) {
25285
+ await client2.setLoggingLevel(defaultLoggingLevel);
25286
+ }
25287
+ if (onElicitationRequest) {
25288
+ client2.setRequestHandler(ElicitRequestSchema, async (request) => {
25289
+ return new Promise((resolve) => {
25290
+ onElicitationRequest(request, resolve);
25291
+ });
25292
+ });
25293
+ }
24950
25294
  setMcpClient(client2);
24951
25295
  setConnectionStatus("connected");
24952
25296
  } catch (e) {
@@ -29224,7 +29568,7 @@ const flip$2 = function(options) {
29224
29568
  const ignoreCrossAxisOverflow = checkCrossAxis === "alignment" ? initialSideAxis !== getSideAxis(nextPlacement) : false;
29225
29569
  if (!ignoreCrossAxisOverflow || // We leave the current main axis only if every placement on that axis
29226
29570
  // overflows the main axis.
29227
- overflowsData.every((d) => d.overflows[0] > 0 && getSideAxis(d.placement) === initialSideAxis)) {
29571
+ overflowsData.every((d) => getSideAxis(d.placement) === initialSideAxis ? d.overflows[0] > 0 : true)) {
29228
29572
  return {
29229
29573
  data: {
29230
29574
  index: nextIndex,
@@ -31439,7 +31783,7 @@ function useCompletionState(handleCompletion, completionsSupported = true, debou
31439
31783
  }, [cleanup]);
31440
31784
  const requestCompletions = reactExports.useMemo(() => {
31441
31785
  return debounce(
31442
- async (ref2, argName, value) => {
31786
+ async (ref2, argName, value, context) => {
31443
31787
  if (!completionsSupported) {
31444
31788
  return;
31445
31789
  }
@@ -31451,10 +31795,14 @@ function useCompletionState(handleCompletion, completionsSupported = true, debou
31451
31795
  loading: { ...prev.loading, [argName]: true }
31452
31796
  }));
31453
31797
  try {
31798
+ if (context !== void 0) {
31799
+ delete context[argName];
31800
+ }
31454
31801
  const values = await handleCompletion(
31455
31802
  ref2,
31456
31803
  argName,
31457
31804
  value,
31805
+ context,
31458
31806
  abortController.signal
31459
31807
  );
31460
31808
  if (!abortController.signal.aborted) {
@@ -31465,6 +31813,7 @@ function useCompletionState(handleCompletion, completionsSupported = true, debou
31465
31813
  }));
31466
31814
  }
31467
31815
  } catch {
31816
+ console.error("completion failed");
31468
31817
  if (!abortController.signal.aborted) {
31469
31818
  setState((prev) => ({
31470
31819
  ...prev,
@@ -31520,7 +31869,8 @@ const PromptsTab = ({
31520
31869
  name: selectedPrompt.name
31521
31870
  },
31522
31871
  argName,
31523
- value
31872
+ value,
31873
+ promptArgs
31524
31874
  );
31525
31875
  }
31526
31876
  };
@@ -31846,7 +32196,8 @@ const ResourcesTab = ({
31846
32196
  uri: selectedTemplate.uriTemplate
31847
32197
  },
31848
32198
  key,
31849
- value
32199
+ value,
32200
+ templateValues
31850
32201
  );
31851
32202
  }
31852
32203
  };
@@ -34003,10 +34354,10 @@ const JsonEditor = ({
34003
34354
  };
34004
34355
  const isSimpleObject = (schema) => {
34005
34356
  const supportedTypes = ["string", "number", "integer", "boolean", "null"];
34006
- if (supportedTypes.includes(schema.type)) return true;
34357
+ if (schema.type && supportedTypes.includes(schema.type)) return true;
34007
34358
  if (schema.type === "object") {
34008
34359
  return Object.values(schema.properties ?? {}).every(
34009
- (prop) => supportedTypes.includes(prop.type)
34360
+ (prop) => prop.type && supportedTypes.includes(prop.type)
34010
34361
  );
34011
34362
  }
34012
34363
  if (schema.type === "array") {
@@ -34130,20 +34481,95 @@ const DynamicJsonForm = ({
34130
34481
  }
34131
34482
  const isRequired = ((_a = parentSchema == null ? void 0 : parentSchema.required) == null ? void 0 : _a.includes(propertyName || "")) ?? false;
34132
34483
  switch (propSchema.type) {
34133
- case "string":
34484
+ case "string": {
34485
+ if (propSchema.oneOf && propSchema.oneOf.every(
34486
+ (option) => typeof option.const === "string" && typeof option.title === "string"
34487
+ )) {
34488
+ return /* @__PURE__ */ jsxRuntimeExports.jsxs(
34489
+ "select",
34490
+ {
34491
+ value: currentValue ?? "",
34492
+ onChange: (e) => {
34493
+ const val = e.target.value;
34494
+ if (!val && !isRequired) {
34495
+ handleFieldChange(path, void 0);
34496
+ } else {
34497
+ handleFieldChange(path, val);
34498
+ }
34499
+ },
34500
+ required: isRequired,
34501
+ 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",
34502
+ children: [
34503
+ /* @__PURE__ */ jsxRuntimeExports.jsx("option", { value: "", children: "Select an option..." }),
34504
+ propSchema.oneOf.map((option) => /* @__PURE__ */ jsxRuntimeExports.jsx(
34505
+ "option",
34506
+ {
34507
+ value: option.const,
34508
+ children: option.title
34509
+ },
34510
+ option.const
34511
+ ))
34512
+ ]
34513
+ }
34514
+ );
34515
+ }
34516
+ if (propSchema.enum) {
34517
+ return /* @__PURE__ */ jsxRuntimeExports.jsxs(
34518
+ "select",
34519
+ {
34520
+ value: currentValue ?? "",
34521
+ onChange: (e) => {
34522
+ const val = e.target.value;
34523
+ if (!val && !isRequired) {
34524
+ handleFieldChange(path, void 0);
34525
+ } else {
34526
+ handleFieldChange(path, val);
34527
+ }
34528
+ },
34529
+ required: isRequired,
34530
+ 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",
34531
+ children: [
34532
+ /* @__PURE__ */ jsxRuntimeExports.jsx("option", { value: "", children: "Select an option..." }),
34533
+ propSchema.enum.map((option) => /* @__PURE__ */ jsxRuntimeExports.jsx("option", { value: option, children: option }, option))
34534
+ ]
34535
+ }
34536
+ );
34537
+ }
34538
+ let inputType = "text";
34539
+ switch (propSchema.format) {
34540
+ case "email":
34541
+ inputType = "email";
34542
+ break;
34543
+ case "uri":
34544
+ inputType = "url";
34545
+ break;
34546
+ case "date":
34547
+ inputType = "date";
34548
+ break;
34549
+ case "date-time":
34550
+ inputType = "datetime-local";
34551
+ break;
34552
+ default:
34553
+ inputType = "text";
34554
+ break;
34555
+ }
34134
34556
  return /* @__PURE__ */ jsxRuntimeExports.jsx(
34135
34557
  Input,
34136
34558
  {
34137
- type: "text",
34559
+ type: inputType,
34138
34560
  value: currentValue ?? "",
34139
34561
  onChange: (e) => {
34140
34562
  const val = e.target.value;
34141
34563
  handleFieldChange(path, val);
34142
34564
  },
34143
34565
  placeholder: propSchema.description,
34144
- required: isRequired
34566
+ required: isRequired,
34567
+ minLength: propSchema.minLength,
34568
+ maxLength: propSchema.maxLength,
34569
+ pattern: propSchema.pattern
34145
34570
  }
34146
34571
  );
34572
+ }
34147
34573
  case "number":
34148
34574
  return /* @__PURE__ */ jsxRuntimeExports.jsx(
34149
34575
  Input,
@@ -34162,7 +34588,9 @@ const DynamicJsonForm = ({
34162
34588
  }
34163
34589
  },
34164
34590
  placeholder: propSchema.description,
34165
- required: isRequired
34591
+ required: isRequired,
34592
+ min: propSchema.minimum,
34593
+ max: propSchema.maximum
34166
34594
  }
34167
34595
  );
34168
34596
  case "integer":
@@ -34184,7 +34612,9 @@ const DynamicJsonForm = ({
34184
34612
  }
34185
34613
  },
34186
34614
  placeholder: propSchema.description,
34187
- required: isRequired
34615
+ required: isRequired,
34616
+ min: propSchema.minimum,
34617
+ max: propSchema.maximum
34188
34618
  }
34189
34619
  );
34190
34620
  case "boolean":
@@ -35856,7 +36286,7 @@ const useTheme = () => {
35856
36286
  [theme, setThemeWithSideEffect]
35857
36287
  );
35858
36288
  };
35859
- const version = "0.16.1";
36289
+ const version = "0.16.3";
35860
36290
  var [createTooltipContext, createTooltipScope] = createContextScope("Tooltip", [
35861
36291
  createPopperScope
35862
36292
  ]);
@@ -36355,6 +36785,10 @@ const Sidebar = ({
36355
36785
  setBearerToken,
36356
36786
  headerName,
36357
36787
  setHeaderName,
36788
+ oauthClientId,
36789
+ setOauthClientId,
36790
+ oauthScope,
36791
+ setOauthScope,
36358
36792
  onConnect,
36359
36793
  onDisconnect,
36360
36794
  stdErrNotifications,
@@ -36367,7 +36801,7 @@ const Sidebar = ({
36367
36801
  }) => {
36368
36802
  const [theme, setTheme] = useTheme();
36369
36803
  const [showEnvVars, setShowEnvVars] = reactExports.useState(false);
36370
- const [showBearerToken, setShowBearerToken] = reactExports.useState(false);
36804
+ const [showAuthConfig, setShowAuthConfig] = reactExports.useState(false);
36371
36805
  const [showConfig, setShowConfig] = reactExports.useState(false);
36372
36806
  const [shownEnvVars, setShownEnvVars] = reactExports.useState(/* @__PURE__ */ new Set());
36373
36807
  const [copiedServerEntry, setCopiedServerEntry] = reactExports.useState(false);
@@ -36524,22 +36958,10 @@ const Sidebar = ({
36524
36958
  }
36525
36959
  )
36526
36960
  ] })
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(
36961
+ ] }) : /* @__PURE__ */ jsxRuntimeExports.jsx(jsxRuntimeExports.Fragment, { children: /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "space-y-2", children: [
36962
+ /* @__PURE__ */ jsxRuntimeExports.jsx("label", { className: "text-sm font-medium", htmlFor: "sse-url-input", children: "URL" }),
36963
+ sseUrl ? /* @__PURE__ */ jsxRuntimeExports.jsxs(Tooltip, { children: [
36964
+ /* @__PURE__ */ jsxRuntimeExports.jsx(TooltipTrigger, { asChild: true, children: /* @__PURE__ */ jsxRuntimeExports.jsx(
36543
36965
  Input,
36544
36966
  {
36545
36967
  id: "sse-url-input",
@@ -36548,58 +36970,19 @@ const Sidebar = ({
36548
36970
  onChange: (e) => setSseUrl(e.target.value),
36549
36971
  className: "font-mono"
36550
36972
  }
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
- ] }),
36973
+ ) }),
36974
+ /* @__PURE__ */ jsxRuntimeExports.jsx(TooltipContent, { children: sseUrl })
36975
+ ] }) : /* @__PURE__ */ jsxRuntimeExports.jsx(
36976
+ Input,
36977
+ {
36978
+ id: "sse-url-input",
36979
+ placeholder: "URL",
36980
+ value: sseUrl,
36981
+ onChange: (e) => setSseUrl(e.target.value),
36982
+ className: "font-mono"
36983
+ }
36984
+ )
36985
+ ] }) }),
36603
36986
  transportType === "stdio" && /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "space-y-2", children: [
36604
36987
  /* @__PURE__ */ jsxRuntimeExports.jsxs(
36605
36988
  Button,
@@ -36755,6 +37138,98 @@ const Sidebar = ({
36755
37138
  /* @__PURE__ */ jsxRuntimeExports.jsx(TooltipContent, { children: "Copy Servers File" })
36756
37139
  ] })
36757
37140
  ] }),
37141
+ /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "space-y-2", children: [
37142
+ /* @__PURE__ */ jsxRuntimeExports.jsxs(
37143
+ Button,
37144
+ {
37145
+ variant: "outline",
37146
+ onClick: () => setShowAuthConfig(!showAuthConfig),
37147
+ className: "flex items-center w-full",
37148
+ "data-testid": "auth-button",
37149
+ "aria-expanded": showAuthConfig,
37150
+ children: [
37151
+ showAuthConfig ? /* @__PURE__ */ jsxRuntimeExports.jsx(ChevronDown, { className: "w-4 h-4 mr-2" }) : /* @__PURE__ */ jsxRuntimeExports.jsx(ChevronRight, { className: "w-4 h-4 mr-2" }),
37152
+ "Authentication"
37153
+ ]
37154
+ }
37155
+ ),
37156
+ showAuthConfig && /* @__PURE__ */ jsxRuntimeExports.jsxs(jsxRuntimeExports.Fragment, { children: [
37157
+ /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "space-y-2 p-3 rounded border", children: [
37158
+ /* @__PURE__ */ jsxRuntimeExports.jsx("h4", { className: "text-sm font-semibold flex items-center", children: "API Token Authentication" }),
37159
+ /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "space-y-2", children: [
37160
+ /* @__PURE__ */ jsxRuntimeExports.jsx("label", { className: "text-sm font-medium", children: "Header Name" }),
37161
+ /* @__PURE__ */ jsxRuntimeExports.jsx(
37162
+ Input,
37163
+ {
37164
+ placeholder: "Authorization",
37165
+ onChange: (e) => setHeaderName && setHeaderName(e.target.value),
37166
+ "data-testid": "header-input",
37167
+ className: "font-mono",
37168
+ value: headerName
37169
+ }
37170
+ ),
37171
+ /* @__PURE__ */ jsxRuntimeExports.jsx(
37172
+ "label",
37173
+ {
37174
+ className: "text-sm font-medium",
37175
+ htmlFor: "bearer-token-input",
37176
+ children: "Bearer Token"
37177
+ }
37178
+ ),
37179
+ /* @__PURE__ */ jsxRuntimeExports.jsx(
37180
+ Input,
37181
+ {
37182
+ id: "bearer-token-input",
37183
+ placeholder: "Bearer Token",
37184
+ value: bearerToken,
37185
+ onChange: (e) => setBearerToken(e.target.value),
37186
+ "data-testid": "bearer-token-input",
37187
+ className: "font-mono",
37188
+ type: "password"
37189
+ }
37190
+ )
37191
+ ] })
37192
+ ] }),
37193
+ transportType !== "stdio" && // OAuth Configuration
37194
+ /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "space-y-2 p-3 rounded border", children: [
37195
+ /* @__PURE__ */ jsxRuntimeExports.jsx("h4", { className: "text-sm font-semibold flex items-center", children: "OAuth 2.0 Flow" }),
37196
+ /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "space-y-2", children: [
37197
+ /* @__PURE__ */ jsxRuntimeExports.jsx("label", { className: "text-sm font-medium", children: "Client ID" }),
37198
+ /* @__PURE__ */ jsxRuntimeExports.jsx(
37199
+ Input,
37200
+ {
37201
+ placeholder: "Client ID",
37202
+ onChange: (e) => setOauthClientId(e.target.value),
37203
+ value: oauthClientId,
37204
+ "data-testid": "oauth-client-id-input",
37205
+ className: "font-mono"
37206
+ }
37207
+ ),
37208
+ /* @__PURE__ */ jsxRuntimeExports.jsx("label", { className: "text-sm font-medium", children: "Redirect URL" }),
37209
+ /* @__PURE__ */ jsxRuntimeExports.jsx(
37210
+ Input,
37211
+ {
37212
+ readOnly: true,
37213
+ placeholder: "Redirect URL",
37214
+ value: window.location.origin + "/oauth/callback",
37215
+ className: "font-mono"
37216
+ }
37217
+ ),
37218
+ /* @__PURE__ */ jsxRuntimeExports.jsx("label", { className: "text-sm font-medium", children: "Scope" }),
37219
+ /* @__PURE__ */ jsxRuntimeExports.jsx(
37220
+ Input,
37221
+ {
37222
+ placeholder: "Scope (space-separated)",
37223
+ onChange: (e) => setOauthScope(e.target.value),
37224
+ value: oauthScope,
37225
+ "data-testid": "oauth-scope-input",
37226
+ className: "font-mono"
37227
+ }
37228
+ )
37229
+ ] })
37230
+ ] })
37231
+ ] })
37232
+ ] }),
36758
37233
  /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "space-y-2", children: [
36759
37234
  /* @__PURE__ */ jsxRuntimeExports.jsxs(
36760
37235
  Button,
@@ -37302,42 +37777,112 @@ const Textarea = reactExports.forwardRef(
37302
37777
  }
37303
37778
  );
37304
37779
  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
- };
37780
+ const ResourceLinkView = reactExports.memo(
37781
+ ({
37782
+ uri,
37783
+ name,
37784
+ description: description2,
37785
+ mimeType,
37786
+ resourceContent,
37787
+ onReadResource
37788
+ }) => {
37789
+ const [{ expanded, loading }, setState] = reactExports.useState({
37790
+ expanded: false,
37791
+ loading: false
37792
+ });
37793
+ const expandedContent = reactExports.useMemo(
37794
+ () => expanded && resourceContent ? /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "mt-2", children: [
37795
+ /* @__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:" }) }),
37796
+ /* @__PURE__ */ jsxRuntimeExports.jsx(JsonView, { data: resourceContent, className: "bg-background" })
37797
+ ] }) : null,
37798
+ [expanded, resourceContent]
37799
+ );
37800
+ const handleClick = reactExports.useCallback(() => {
37801
+ if (!onReadResource) return;
37802
+ if (!expanded) {
37803
+ setState((prev) => ({ ...prev, expanded: true, loading: true }));
37804
+ onReadResource(uri);
37805
+ setState((prev) => ({ ...prev, loading: false }));
37806
+ } else {
37807
+ setState((prev) => ({ ...prev, expanded: false }));
37808
+ }
37809
+ }, [expanded, onReadResource, uri]);
37810
+ const handleKeyDown = reactExports.useCallback(
37811
+ (e) => {
37812
+ if ((e.key === "Enter" || e.key === " ") && onReadResource) {
37813
+ e.preventDefault();
37814
+ handleClick();
37815
+ }
37816
+ },
37817
+ [handleClick, onReadResource]
37818
+ );
37819
+ return /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "text-sm text-foreground bg-secondary py-2 px-3 rounded", children: [
37820
+ /* @__PURE__ */ jsxRuntimeExports.jsx(
37821
+ "div",
37822
+ {
37823
+ 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",
37824
+ onClick: onReadResource ? handleClick : void 0,
37825
+ onKeyDown: onReadResource ? handleKeyDown : void 0,
37826
+ tabIndex: onReadResource ? 0 : -1,
37827
+ role: "button",
37828
+ "aria-expanded": expanded,
37829
+ "aria-label": `${expanded ? "Collapse" : "Expand"} resource ${uri}`,
37830
+ children: /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "flex-1 min-w-0", children: [
37831
+ /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "flex items-start justify-between gap-2 mb-1", children: [
37832
+ /* @__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 }),
37833
+ /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "flex items-center gap-2 flex-shrink-0", children: [
37834
+ 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 }),
37835
+ 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 ? "▼" : "▶" }) })
37836
+ ] })
37837
+ ] }),
37838
+ name && /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "font-semibold text-sm text-gray-900 dark:text-gray-100 mb-1", children: name }),
37839
+ description2 && /* @__PURE__ */ jsxRuntimeExports.jsx("p", { className: "text-sm text-gray-600 dark:text-gray-300 leading-relaxed", children: description2 })
37840
+ ] })
37841
+ }
37842
+ ),
37843
+ expandedContent
37844
+ ] });
37311
37845
  }
37312
- const textContent = unstructuredContent[0].text;
37313
- if (!textContent) {
37846
+ );
37847
+ const checkContentCompatibility = (structuredContent, unstructuredContent) => {
37848
+ const textBlocks = unstructuredContent.filter(
37849
+ (block) => block.type === "text"
37850
+ );
37851
+ if (textBlocks.length === 0) {
37314
37852
  return {
37315
37853
  isCompatible: false,
37316
- message: "Text content is empty"
37854
+ message: "No text blocks to match structured content"
37317
37855
  };
37318
37856
  }
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
- };
37857
+ for (const textBlock of textBlocks) {
37858
+ const textContent = textBlock.text;
37859
+ if (!textContent) {
37860
+ continue;
37861
+ }
37862
+ try {
37863
+ const parsedContent = JSON.parse(textContent);
37864
+ const isEqual = JSON.stringify(parsedContent) === JSON.stringify(structuredContent);
37865
+ if (isEqual) {
37866
+ return {
37867
+ isCompatible: true,
37868
+ message: `Structured content matches text block${textBlocks.length > 1 ? " (multiple blocks)" : ""}${unstructuredContent.length > textBlocks.length ? " + other content" : ""}`
37869
+ };
37870
+ }
37871
+ } catch {
37872
+ continue;
37332
37873
  }
37333
- } catch {
37334
- return {
37335
- isCompatible: false,
37336
- message: "Unstructured content is not valid JSON"
37337
- };
37338
37874
  }
37875
+ return {
37876
+ isCompatible: false,
37877
+ message: "No text block matches structured content"
37878
+ };
37339
37879
  };
37340
- const ToolResults = ({ toolResult, selectedTool }) => {
37880
+ const ToolResults = ({
37881
+ toolResult,
37882
+ selectedTool,
37883
+ resourceContent,
37884
+ onReadResource
37885
+ }) => {
37341
37886
  if (!toolResult) return null;
37342
37887
  if ("content" in toolResult) {
37343
37888
  const parsedResult = CallToolResultSchema.safeParse(toolResult);
@@ -37395,6 +37940,10 @@ const ToolResults = ({ toolResult, selectedTool }) => {
37395
37940
  )
37396
37941
  ] })
37397
37942
  ] }),
37943
+ structuredResult._meta && /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "mb-4", children: [
37944
+ /* @__PURE__ */ jsxRuntimeExports.jsx("h5", { className: "font-semibold mb-2 text-sm", children: "Meta:" }),
37945
+ /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "bg-gray-50 dark:bg-gray-900 p-3 rounded-lg", children: /* @__PURE__ */ jsxRuntimeExports.jsx(JsonView, { data: structuredResult._meta }) })
37946
+ ] }),
37398
37947
  !structuredResult.structuredContent && validationResult && !validationResult.isValid && /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "mb-4", children: /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "bg-red-100 dark:bg-red-900 text-red-800 dark:text-red-200 p-2 rounded text-sm", children: [
37399
37948
  "✗ Validation Error: ",
37400
37949
  validationResult.error
@@ -37434,7 +37983,18 @@ const ToolResults = ({ toolResult, selectedTool }) => {
37434
37983
  className: "w-full",
37435
37984
  children: /* @__PURE__ */ jsxRuntimeExports.jsx("p", { children: "Your browser does not support audio playback" })
37436
37985
  }
37437
- ) : /* @__PURE__ */ jsxRuntimeExports.jsx(JsonView, { data: item.resource }))
37986
+ ) : /* @__PURE__ */ jsxRuntimeExports.jsx(JsonView, { data: item.resource })),
37987
+ item.type === "resource_link" && /* @__PURE__ */ jsxRuntimeExports.jsx(
37988
+ ResourceLinkView,
37989
+ {
37990
+ uri: item.uri,
37991
+ name: item.name,
37992
+ description: item.description,
37993
+ mimeType: item.mimeType,
37994
+ resourceContent: resourceContent[item.uri] || "",
37995
+ onReadResource
37996
+ }
37997
+ )
37438
37998
  ] }, index2);
37439
37999
  })
37440
38000
  ] })
@@ -37447,6 +38007,7 @@ const ToolResults = ({ toolResult, selectedTool }) => {
37447
38007
  }
37448
38008
  return null;
37449
38009
  };
38010
+ const hasMeta = (tool) => typeof tool._meta !== "undefined";
37450
38011
  const ToolsTab = ({
37451
38012
  tools,
37452
38013
  listTools,
@@ -37455,11 +38016,14 @@ const ToolsTab = ({
37455
38016
  selectedTool,
37456
38017
  setSelectedTool,
37457
38018
  toolResult,
37458
- nextCursor
38019
+ nextCursor,
38020
+ resourceContent,
38021
+ onReadResource
37459
38022
  }) => {
37460
38023
  const [params, setParams] = reactExports.useState({});
37461
38024
  const [isToolRunning, setIsToolRunning] = reactExports.useState(false);
37462
38025
  const [isOutputSchemaExpanded, setIsOutputSchemaExpanded] = reactExports.useState(false);
38026
+ const [isMetaExpanded, setIsMetaExpanded] = reactExports.useState(false);
37463
38027
  reactExports.useEffect(() => {
37464
38028
  const params2 = Object.entries(
37465
38029
  (selectedTool == null ? void 0 : selectedTool.inputSchema.properties) ?? []
@@ -37631,6 +38195,34 @@ const ToolsTab = ({
37631
38195
  }
37632
38196
  )
37633
38197
  ] }),
38198
+ selectedTool && hasMeta(selectedTool) && selectedTool._meta && /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "bg-gray-50 dark:bg-gray-900 p-3 rounded-lg", children: [
38199
+ /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "flex items-center justify-between mb-2", children: [
38200
+ /* @__PURE__ */ jsxRuntimeExports.jsx("h4", { className: "text-sm font-semibold", children: "Meta:" }),
38201
+ /* @__PURE__ */ jsxRuntimeExports.jsx(
38202
+ Button,
38203
+ {
38204
+ size: "sm",
38205
+ variant: "ghost",
38206
+ onClick: () => setIsMetaExpanded(!isMetaExpanded),
38207
+ className: "h-6 px-2",
38208
+ children: isMetaExpanded ? /* @__PURE__ */ jsxRuntimeExports.jsxs(jsxRuntimeExports.Fragment, { children: [
38209
+ /* @__PURE__ */ jsxRuntimeExports.jsx(ChevronUp, { className: "h-3 w-3 mr-1" }),
38210
+ "Collapse"
38211
+ ] }) : /* @__PURE__ */ jsxRuntimeExports.jsxs(jsxRuntimeExports.Fragment, { children: [
38212
+ /* @__PURE__ */ jsxRuntimeExports.jsx(ChevronDown, { className: "h-3 w-3 mr-1" }),
38213
+ "Expand"
38214
+ ] })
38215
+ }
38216
+ )
38217
+ ] }),
38218
+ /* @__PURE__ */ jsxRuntimeExports.jsx(
38219
+ "div",
38220
+ {
38221
+ className: `transition-all ${isMetaExpanded ? "" : "max-h-[8rem] overflow-y-auto"}`,
38222
+ children: /* @__PURE__ */ jsxRuntimeExports.jsx(JsonView, { data: selectedTool._meta })
38223
+ }
38224
+ )
38225
+ ] }),
37634
38226
  /* @__PURE__ */ jsxRuntimeExports.jsx(
37635
38227
  Button,
37636
38228
  {
@@ -37656,19 +38248,159 @@ const ToolsTab = ({
37656
38248
  ToolResults,
37657
38249
  {
37658
38250
  toolResult,
37659
- selectedTool
38251
+ selectedTool,
38252
+ resourceContent,
38253
+ onReadResource
37660
38254
  }
37661
38255
  )
37662
38256
  ] }) : /* @__PURE__ */ jsxRuntimeExports.jsx(Alert, { children: /* @__PURE__ */ jsxRuntimeExports.jsx(AlertDescription, { children: "Select a tool from the list to view its details and run it" }) }) })
37663
38257
  ] })
37664
38258
  ] }) });
37665
38259
  };
38260
+ const ElicitationRequest = ({
38261
+ request,
38262
+ onResolve
38263
+ }) => {
38264
+ const [formData, setFormData] = reactExports.useState({});
38265
+ const [validationError, setValidationError] = reactExports.useState(null);
38266
+ reactExports.useEffect(() => {
38267
+ const defaultValue = generateDefaultValue(request.request.requestedSchema);
38268
+ setFormData(defaultValue);
38269
+ setValidationError(null);
38270
+ }, [request.request.requestedSchema]);
38271
+ const validateEmailFormat = (email) => {
38272
+ const emailRegex2 = /^[^\s@]+@[^\s@]+\.[^\s@]+$/;
38273
+ return emailRegex2.test(email);
38274
+ };
38275
+ const validateFormData = (data2, schema) => {
38276
+ if (schema.type === "object" && schema.properties && typeof data2 === "object" && data2 !== null) {
38277
+ const dataObj = data2;
38278
+ if (Array.isArray(schema.required)) {
38279
+ for (const field of schema.required) {
38280
+ const value = dataObj[field];
38281
+ if (value === void 0 || value === null || value === "") {
38282
+ setValidationError(`Required field missing: ${field}`);
38283
+ return false;
38284
+ }
38285
+ }
38286
+ }
38287
+ for (const [fieldName, fieldValue] of Object.entries(dataObj)) {
38288
+ const fieldSchema = schema.properties[fieldName];
38289
+ if (fieldSchema && fieldSchema.format === "email" && typeof fieldValue === "string") {
38290
+ if (!validateEmailFormat(fieldValue)) {
38291
+ setValidationError(`Invalid email format: ${fieldName}`);
38292
+ return false;
38293
+ }
38294
+ }
38295
+ }
38296
+ }
38297
+ return true;
38298
+ };
38299
+ const handleAccept = () => {
38300
+ try {
38301
+ if (!validateFormData(formData, request.request.requestedSchema)) {
38302
+ return;
38303
+ }
38304
+ const ajv2 = new Ajv();
38305
+ const validate2 = ajv2.compile(request.request.requestedSchema);
38306
+ const isValid2 = validate2(formData);
38307
+ if (!isValid2) {
38308
+ const errorMessage = ajv2.errorsText(validate2.errors);
38309
+ setValidationError(errorMessage);
38310
+ return;
38311
+ }
38312
+ onResolve(request.id, {
38313
+ action: "accept",
38314
+ content: formData
38315
+ });
38316
+ } catch (error) {
38317
+ setValidationError(
38318
+ error instanceof Error ? error.message : "Validation failed"
38319
+ );
38320
+ }
38321
+ };
38322
+ const handleDecline = () => {
38323
+ onResolve(request.id, { action: "decline" });
38324
+ };
38325
+ const handleCancel = () => {
38326
+ onResolve(request.id, { action: "cancel" });
38327
+ };
38328
+ const schemaTitle = request.request.requestedSchema.title || "Information Request";
38329
+ const schemaDescription = request.request.requestedSchema.description;
38330
+ return /* @__PURE__ */ jsxRuntimeExports.jsxs(
38331
+ "div",
38332
+ {
38333
+ "data-testid": "elicitation-request",
38334
+ className: "flex gap-4 p-4 border rounded-lg space-y-4",
38335
+ children: [
38336
+ /* @__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: [
38337
+ /* @__PURE__ */ jsxRuntimeExports.jsx("h4", { className: "font-semibold", children: schemaTitle }),
38338
+ /* @__PURE__ */ jsxRuntimeExports.jsx("p", { className: "text-sm", children: request.request.message }),
38339
+ schemaDescription && /* @__PURE__ */ jsxRuntimeExports.jsx("p", { className: "text-xs text-muted-foreground", children: schemaDescription }),
38340
+ /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "mt-2", children: [
38341
+ /* @__PURE__ */ jsxRuntimeExports.jsx("h5", { className: "text-xs font-medium mb-1", children: "Request Schema:" }),
38342
+ /* @__PURE__ */ jsxRuntimeExports.jsx(
38343
+ JsonView,
38344
+ {
38345
+ data: JSON.stringify(request.request.requestedSchema, null, 2)
38346
+ }
38347
+ )
38348
+ ] })
38349
+ ] }) }),
38350
+ /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "flex-1 space-y-4", children: [
38351
+ /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "space-y-2", children: [
38352
+ /* @__PURE__ */ jsxRuntimeExports.jsx("h4", { className: "font-medium", children: "Response Form" }),
38353
+ /* @__PURE__ */ jsxRuntimeExports.jsx(
38354
+ DynamicJsonForm,
38355
+ {
38356
+ schema: request.request.requestedSchema,
38357
+ value: formData,
38358
+ onChange: (newValue) => {
38359
+ setFormData(newValue);
38360
+ setValidationError(null);
38361
+ }
38362
+ }
38363
+ ),
38364
+ 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: [
38365
+ /* @__PURE__ */ jsxRuntimeExports.jsx("strong", { children: "Validation Error:" }),
38366
+ " ",
38367
+ validationError
38368
+ ] }) })
38369
+ ] }),
38370
+ /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "flex space-x-2 mt-1", children: [
38371
+ /* @__PURE__ */ jsxRuntimeExports.jsx(Button, { type: "button", onClick: handleAccept, children: "Submit" }),
38372
+ /* @__PURE__ */ jsxRuntimeExports.jsx(Button, { type: "button", variant: "outline", onClick: handleDecline, children: "Decline" }),
38373
+ /* @__PURE__ */ jsxRuntimeExports.jsx(Button, { type: "button", variant: "outline", onClick: handleCancel, children: "Cancel" })
38374
+ ] })
38375
+ ] })
38376
+ ]
38377
+ }
38378
+ );
38379
+ };
38380
+ const ElicitationTab = ({ pendingRequests, onResolve }) => {
38381
+ return /* @__PURE__ */ jsxRuntimeExports.jsx(TabsContent, { value: "elicitations", children: /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "h-96", children: [
38382
+ /* @__PURE__ */ jsxRuntimeExports.jsx(Alert, { children: /* @__PURE__ */ jsxRuntimeExports.jsx(AlertDescription, { children: "When the server requests information from the user, requests will appear here for response." }) }),
38383
+ /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "mt-4 space-y-4", children: [
38384
+ /* @__PURE__ */ jsxRuntimeExports.jsx("h3", { className: "text-lg font-semibold", children: "Recent Requests" }),
38385
+ pendingRequests.map((request) => /* @__PURE__ */ jsxRuntimeExports.jsx(
38386
+ ElicitationRequest,
38387
+ {
38388
+ request,
38389
+ onResolve
38390
+ },
38391
+ request.id
38392
+ )),
38393
+ pendingRequests.length === 0 && /* @__PURE__ */ jsxRuntimeExports.jsx("p", { className: "text-gray-500", children: "No pending requests" })
38394
+ ] })
38395
+ ] }) });
38396
+ };
37666
38397
  const CONFIG_LOCAL_STORAGE_KEY = "inspectorConfig_v1";
37667
38398
  const App = () => {
37668
38399
  var _a;
37669
38400
  const [resources, setResources] = reactExports.useState([]);
37670
38401
  const [resourceTemplates, setResourceTemplates] = reactExports.useState([]);
37671
38402
  const [resourceContent, setResourceContent] = reactExports.useState("");
38403
+ const [resourceContentMap, setResourceContentMap] = reactExports.useState({});
37672
38404
  const [prompts, setPrompts] = reactExports.useState([]);
37673
38405
  const [promptContent, setPromptContent] = reactExports.useState("");
37674
38406
  const [tools, setTools] = reactExports.useState([]);
@@ -37696,7 +38428,14 @@ const App = () => {
37696
38428
  const [headerName, setHeaderName] = reactExports.useState(() => {
37697
38429
  return localStorage.getItem("lastHeaderName") || "";
37698
38430
  });
38431
+ const [oauthClientId, setOauthClientId] = reactExports.useState(() => {
38432
+ return localStorage.getItem("lastOauthClientId") || "";
38433
+ });
38434
+ const [oauthScope, setOauthScope] = reactExports.useState(() => {
38435
+ return localStorage.getItem("lastOauthScope") || "";
38436
+ });
37699
38437
  const [pendingSampleRequests, setPendingSampleRequests] = reactExports.useState([]);
38438
+ const [pendingElicitationRequests, setPendingElicitationRequests] = reactExports.useState([]);
37700
38439
  const [isAuthDebuggerVisible, setIsAuthDebuggerVisible] = reactExports.useState(false);
37701
38440
  const [authState, setAuthState] = reactExports.useState(EMPTY_DEBUGGER_STATE);
37702
38441
  const updateAuthState = (updates) => {
@@ -37715,6 +38454,16 @@ const App = () => {
37715
38454
  const [nextPromptCursor, setNextPromptCursor] = reactExports.useState();
37716
38455
  const [nextToolCursor, setNextToolCursor] = reactExports.useState();
37717
38456
  const progressTokenRef = reactExports.useRef(0);
38457
+ const [activeTab, setActiveTab] = reactExports.useState(() => {
38458
+ const hash = window.location.hash.slice(1);
38459
+ const initialTab = hash || "resources";
38460
+ return initialTab;
38461
+ });
38462
+ const currentTabRef = reactExports.useRef(activeTab);
38463
+ const lastToolCallOriginTabRef = reactExports.useRef(activeTab);
38464
+ reactExports.useEffect(() => {
38465
+ currentTabRef.current = activeTab;
38466
+ }, [activeTab]);
37718
38467
  const { height: historyPaneHeight, handleDragStart } = useDraggablePane(300);
37719
38468
  const {
37720
38469
  width: sidebarWidth,
@@ -37740,6 +38489,8 @@ const App = () => {
37740
38489
  env,
37741
38490
  bearerToken,
37742
38491
  headerName,
38492
+ oauthClientId,
38493
+ oauthScope,
37743
38494
  config,
37744
38495
  onNotification: (notification) => {
37745
38496
  setNotifications((prev) => [...prev, notification]);
@@ -37756,8 +38507,51 @@ const App = () => {
37756
38507
  { id: nextRequestId.current++, request, resolve, reject }
37757
38508
  ]);
37758
38509
  },
37759
- getRoots: () => rootsRef.current
38510
+ onElicitationRequest: (request, resolve) => {
38511
+ const currentTab = lastToolCallOriginTabRef.current;
38512
+ setPendingElicitationRequests((prev) => [
38513
+ ...prev,
38514
+ {
38515
+ id: nextRequestId.current++,
38516
+ request: {
38517
+ id: nextRequestId.current,
38518
+ message: request.params.message,
38519
+ requestedSchema: request.params.requestedSchema
38520
+ },
38521
+ originatingTab: currentTab,
38522
+ resolve,
38523
+ decline: (error) => {
38524
+ console.error("Elicitation request rejected:", error);
38525
+ }
38526
+ }
38527
+ ]);
38528
+ setActiveTab("elicitations");
38529
+ window.location.hash = "elicitations";
38530
+ },
38531
+ getRoots: () => rootsRef.current,
38532
+ defaultLoggingLevel: logLevel
37760
38533
  });
38534
+ reactExports.useEffect(() => {
38535
+ if (serverCapabilities) {
38536
+ const hash = window.location.hash.slice(1);
38537
+ const validTabs = [
38538
+ ...(serverCapabilities == null ? void 0 : serverCapabilities.resources) ? ["resources"] : [],
38539
+ ...(serverCapabilities == null ? void 0 : serverCapabilities.prompts) ? ["prompts"] : [],
38540
+ ...(serverCapabilities == null ? void 0 : serverCapabilities.tools) ? ["tools"] : [],
38541
+ "ping",
38542
+ "sampling",
38543
+ "elicitations",
38544
+ "roots",
38545
+ "auth"
38546
+ ];
38547
+ const isValidTab = validTabs.includes(hash);
38548
+ if (!isValidTab) {
38549
+ const defaultTab = (serverCapabilities == null ? void 0 : serverCapabilities.resources) ? "resources" : (serverCapabilities == null ? void 0 : serverCapabilities.prompts) ? "prompts" : (serverCapabilities == null ? void 0 : serverCapabilities.tools) ? "tools" : "ping";
38550
+ setActiveTab(defaultTab);
38551
+ window.location.hash = defaultTab;
38552
+ }
38553
+ }
38554
+ }, [serverCapabilities]);
37761
38555
  reactExports.useEffect(() => {
37762
38556
  localStorage.setItem("lastCommand", command);
37763
38557
  }, [command]);
@@ -37776,6 +38570,12 @@ const App = () => {
37776
38570
  reactExports.useEffect(() => {
37777
38571
  localStorage.setItem("lastHeaderName", headerName);
37778
38572
  }, [headerName]);
38573
+ reactExports.useEffect(() => {
38574
+ localStorage.setItem("lastOauthClientId", oauthClientId);
38575
+ }, [oauthClientId]);
38576
+ reactExports.useEffect(() => {
38577
+ localStorage.setItem("lastOauthScope", oauthScope);
38578
+ }, [oauthScope]);
37779
38579
  reactExports.useEffect(() => {
37780
38580
  saveInspectorConfig(CONFIG_LOCAL_STORAGE_KEY, config);
37781
38581
  }, [config]);
@@ -37882,6 +38682,14 @@ const App = () => {
37882
38682
  if (data2.defaultArgs) {
37883
38683
  setArgs(data2.defaultArgs);
37884
38684
  }
38685
+ if (data2.defaultTransport) {
38686
+ setTransportType(
38687
+ data2.defaultTransport
38688
+ );
38689
+ }
38690
+ if (data2.defaultServerUrl) {
38691
+ setSseUrl(data2.defaultServerUrl);
38692
+ }
37885
38693
  }).catch(
37886
38694
  (error) => console.error("Error fetching default environment:", error)
37887
38695
  );
@@ -37890,10 +38698,27 @@ const App = () => {
37890
38698
  rootsRef.current = roots;
37891
38699
  }, [roots]);
37892
38700
  reactExports.useEffect(() => {
37893
- if (!window.location.hash) {
37894
- window.location.hash = "resources";
38701
+ if (mcpClient && !window.location.hash) {
38702
+ const defaultTab = (serverCapabilities == null ? void 0 : serverCapabilities.resources) ? "resources" : (serverCapabilities == null ? void 0 : serverCapabilities.prompts) ? "prompts" : (serverCapabilities == null ? void 0 : serverCapabilities.tools) ? "tools" : "ping";
38703
+ window.location.hash = defaultTab;
38704
+ } else if (!mcpClient && window.location.hash) {
38705
+ window.history.replaceState(
38706
+ null,
38707
+ "",
38708
+ window.location.pathname + window.location.search
38709
+ );
37895
38710
  }
37896
- }, []);
38711
+ }, [mcpClient, serverCapabilities]);
38712
+ reactExports.useEffect(() => {
38713
+ const handleHashChange = () => {
38714
+ const hash = window.location.hash.slice(1);
38715
+ if (hash && hash !== activeTab) {
38716
+ setActiveTab(hash);
38717
+ }
38718
+ };
38719
+ window.addEventListener("hashchange", handleHashChange);
38720
+ return () => window.removeEventListener("hashchange", handleHashChange);
38721
+ }, [activeTab]);
37897
38722
  const handleApproveSampling = (id, result) => {
37898
38723
  setPendingSampleRequests((prev) => {
37899
38724
  const request = prev.find((r2) => r2.id === id);
@@ -37908,6 +38733,36 @@ const App = () => {
37908
38733
  return prev.filter((r2) => r2.id !== id);
37909
38734
  });
37910
38735
  };
38736
+ const handleResolveElicitation = (id, response) => {
38737
+ setPendingElicitationRequests((prev) => {
38738
+ const request = prev.find((r2) => r2.id === id);
38739
+ if (request) {
38740
+ request.resolve(response);
38741
+ if (request.originatingTab) {
38742
+ const originatingTab = request.originatingTab;
38743
+ const validTabs = [
38744
+ ...(serverCapabilities == null ? void 0 : serverCapabilities.resources) ? ["resources"] : [],
38745
+ ...(serverCapabilities == null ? void 0 : serverCapabilities.prompts) ? ["prompts"] : [],
38746
+ ...(serverCapabilities == null ? void 0 : serverCapabilities.tools) ? ["tools"] : [],
38747
+ "ping",
38748
+ "sampling",
38749
+ "elicitations",
38750
+ "roots",
38751
+ "auth"
38752
+ ];
38753
+ if (validTabs.includes(originatingTab)) {
38754
+ setActiveTab(originatingTab);
38755
+ window.location.hash = originatingTab;
38756
+ setTimeout(() => {
38757
+ setActiveTab(originatingTab);
38758
+ window.location.hash = originatingTab;
38759
+ }, 100);
38760
+ }
38761
+ }
38762
+ }
38763
+ return prev.filter((r2) => r2.id !== id);
38764
+ });
38765
+ };
37911
38766
  const clearError = (tabKey) => {
37912
38767
  setErrors((prev) => ({ ...prev, [tabKey]: null }));
37913
38768
  };
@@ -37955,7 +38810,20 @@ const App = () => {
37955
38810
  );
37956
38811
  setNextResourceTemplateCursor(response.nextCursor);
37957
38812
  };
38813
+ const getPrompt = async (name, args2 = {}) => {
38814
+ lastToolCallOriginTabRef.current = currentTabRef.current;
38815
+ const response = await sendMCPRequest(
38816
+ {
38817
+ method: "prompts/get",
38818
+ params: { name, arguments: args2 }
38819
+ },
38820
+ GetPromptResultSchema,
38821
+ "prompts"
38822
+ );
38823
+ setPromptContent(JSON.stringify(response, null, 2));
38824
+ };
37958
38825
  const readResource = async (uri) => {
38826
+ lastToolCallOriginTabRef.current = currentTabRef.current;
37959
38827
  const response = await sendMCPRequest(
37960
38828
  {
37961
38829
  method: "resources/read",
@@ -37964,7 +38832,12 @@ const App = () => {
37964
38832
  ReadResourceResultSchema,
37965
38833
  "resources"
37966
38834
  );
37967
- setResourceContent(JSON.stringify(response, null, 2));
38835
+ const content = JSON.stringify(response, null, 2);
38836
+ setResourceContent(content);
38837
+ setResourceContentMap((prev) => ({
38838
+ ...prev,
38839
+ [uri]: content
38840
+ }));
37968
38841
  };
37969
38842
  const subscribeToResource = async (uri) => {
37970
38843
  if (!resourceSubscriptions.has(uri)) {
@@ -38008,17 +38881,6 @@ const App = () => {
38008
38881
  setPrompts(response.prompts);
38009
38882
  setNextPromptCursor(response.nextCursor);
38010
38883
  };
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
38884
  const listTools = async () => {
38023
38885
  const response = await sendMCPRequest(
38024
38886
  {
@@ -38033,6 +38895,7 @@ const App = () => {
38033
38895
  cacheToolOutputSchemas(response.tools);
38034
38896
  };
38035
38897
  const callTool = async (name, params) => {
38898
+ lastToolCallOriginTabRef.current = currentTabRef.current;
38036
38899
  try {
38037
38900
  const response = await sendMCPRequest(
38038
38901
  {
@@ -38089,13 +38952,13 @@ const App = () => {
38089
38952
  ) });
38090
38953
  if (window.location.pathname === "/oauth/callback") {
38091
38954
  const OAuthCallback = React.lazy(
38092
- () => __vitePreload(() => import("./OAuthCallback-CaDIOg8Q.js"), true ? __vite__mapDeps([0,1]) : void 0)
38955
+ () => __vitePreload(() => import("./OAuthCallback-DCwiUoWl.js"), true ? __vite__mapDeps([0,1]) : void 0)
38093
38956
  );
38094
38957
  return /* @__PURE__ */ jsxRuntimeExports.jsx(reactExports.Suspense, { fallback: /* @__PURE__ */ jsxRuntimeExports.jsx("div", { children: "Loading..." }), children: /* @__PURE__ */ jsxRuntimeExports.jsx(OAuthCallback, { onConnect: onOAuthConnect }) });
38095
38958
  }
38096
38959
  if (window.location.pathname === "/oauth/callback/debug") {
38097
38960
  const OAuthDebugCallback = React.lazy(
38098
- () => __vitePreload(() => import("./OAuthDebugCallback-Ccjj44Wa.js"), true ? __vite__mapDeps([2,1]) : void 0)
38961
+ () => __vitePreload(() => import("./OAuthDebugCallback-BNuktUej.js"), true ? __vite__mapDeps([2,1]) : void 0)
38099
38962
  );
38100
38963
  return /* @__PURE__ */ jsxRuntimeExports.jsx(reactExports.Suspense, { fallback: /* @__PURE__ */ jsxRuntimeExports.jsx("div", { children: "Loading..." }), children: /* @__PURE__ */ jsxRuntimeExports.jsx(OAuthDebugCallback, { onConnect: onOAuthDebugConnect }) });
38101
38964
  }
@@ -38131,6 +38994,10 @@ const App = () => {
38131
38994
  setBearerToken,
38132
38995
  headerName,
38133
38996
  setHeaderName,
38997
+ oauthClientId,
38998
+ setOauthClientId,
38999
+ oauthScope,
39000
+ setOauthScope,
38134
39001
  onConnect: connectMcpServer,
38135
39002
  onDisconnect: disconnectMcpServer,
38136
39003
  stdErrNotifications,
@@ -38165,11 +39032,12 @@ const App = () => {
38165
39032
  /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "flex-1 overflow-auto", children: mcpClient ? /* @__PURE__ */ jsxRuntimeExports.jsxs(
38166
39033
  Tabs,
38167
39034
  {
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",
39035
+ value: activeTab,
38171
39036
  className: "w-full p-4",
38172
- onValueChange: (value) => window.location.hash = value,
39037
+ onValueChange: (value) => {
39038
+ setActiveTab(value);
39039
+ window.location.hash = value;
39040
+ },
38173
39041
  children: [
38174
39042
  /* @__PURE__ */ jsxRuntimeExports.jsxs(TabsList, { className: "mb-4 py-0", children: [
38175
39043
  /* @__PURE__ */ jsxRuntimeExports.jsxs(
@@ -38214,6 +39082,11 @@ const App = () => {
38214
39082
  "Sampling",
38215
39083
  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
39084
  ] }),
39085
+ /* @__PURE__ */ jsxRuntimeExports.jsxs(TabsTrigger, { value: "elicitations", className: "relative", children: [
39086
+ /* @__PURE__ */ jsxRuntimeExports.jsx(MessageSquare, { className: "w-4 h-4 mr-2" }),
39087
+ "Elicitations",
39088
+ 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 })
39089
+ ] }),
38217
39090
  /* @__PURE__ */ jsxRuntimeExports.jsxs(TabsTrigger, { value: "roots", children: [
38218
39091
  /* @__PURE__ */ jsxRuntimeExports.jsx(FolderTree, { className: "w-4 h-4 mr-2" }),
38219
39092
  "Roots"
@@ -38342,7 +39215,12 @@ const App = () => {
38342
39215
  },
38343
39216
  toolResult,
38344
39217
  nextCursor: nextToolCursor,
38345
- error: errors.tools
39218
+ error: errors.tools,
39219
+ resourceContent: resourceContentMap,
39220
+ onReadResource: (uri) => {
39221
+ clearError("resources");
39222
+ readResource(uri);
39223
+ }
38346
39224
  }
38347
39225
  ),
38348
39226
  /* @__PURE__ */ jsxRuntimeExports.jsx(ConsoleTab, {}),
@@ -38367,6 +39245,13 @@ const App = () => {
38367
39245
  onReject: handleRejectSampling
38368
39246
  }
38369
39247
  ),
39248
+ /* @__PURE__ */ jsxRuntimeExports.jsx(
39249
+ ElicitationTab,
39250
+ {
39251
+ pendingRequests: pendingElicitationRequests,
39252
+ onResolve: handleResolveElicitation
39253
+ }
39254
+ ),
38370
39255
  /* @__PURE__ */ jsxRuntimeExports.jsx(
38371
39256
  RootsTab,
38372
39257
  {