@modelcontextprotocol/inspector 2.7.0 → 2.9.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -165,6 +165,10 @@ var ModernListSkillsResultSchema = ListSkillsResultSchema.extend({
165
165
  var GetSkillEnvelopeSchema = z.looseObject({
166
166
  skill: SkillEntrySchema
167
167
  });
168
+ var ModernGetSkillEnvelopeSchema = GetSkillEnvelopeSchema.extend({
169
+ ttlMs: z.int().min(0),
170
+ cacheScope: z.enum(["public", "private"])
171
+ });
168
172
  var GetSkillResultSchema = GetSkillEnvelopeSchema.transform(
169
173
  (result) => result.skill
170
174
  );
@@ -788,6 +792,176 @@ var SECRET_FIELD_OAUTH_CLIENT_SECRET = "oauth-client-secret";
788
792
  var SECRET_FIELD_IDP_CLIENT_SECRET = "idp-client-secret";
789
793
  var envSecretField = (envKey) => `env:${envKey}`;
790
794
 
795
+ // ../../core/json/localRefs.ts
796
+ var SUBSCHEMA_KEYWORDS = /* @__PURE__ */ new Set([
797
+ "items",
798
+ "contains",
799
+ "not",
800
+ "propertyNames",
801
+ "if",
802
+ "then",
803
+ "else",
804
+ "additionalProperties",
805
+ "unevaluatedProperties",
806
+ "additionalItems",
807
+ "unevaluatedItems",
808
+ "contentSchema"
809
+ ]);
810
+ var SUBSCHEMA_ARRAY_KEYWORDS = /* @__PURE__ */ new Set([
811
+ "allOf",
812
+ "anyOf",
813
+ "oneOf",
814
+ "prefixItems"
815
+ ]);
816
+ var SUBSCHEMA_MAP_KEYWORDS = /* @__PURE__ */ new Set([
817
+ "properties",
818
+ "patternProperties",
819
+ "dependentSchemas",
820
+ // Pre-2019 spelling of `dependentSchemas`; its array values are property
821
+ // name lists, which are not schemas and pass through untouched.
822
+ "dependencies",
823
+ "$defs",
824
+ "definitions"
825
+ ]);
826
+ var NON_CONSTRAINT_SIBLINGS = /* @__PURE__ */ new Set([
827
+ "title",
828
+ "description",
829
+ "default",
830
+ "examples",
831
+ "deprecated",
832
+ "readOnly",
833
+ "writeOnly",
834
+ // Non-standard labels for `enum` values, read by both form builders.
835
+ "enumNames",
836
+ "$comment",
837
+ "$schema",
838
+ "$id",
839
+ "$defs",
840
+ "definitions"
841
+ ]);
842
+ var EXPANSION_BUDGET = 1e4;
843
+ var MAX_DEPTH = 64;
844
+ var Bail = class extends Error {
845
+ };
846
+ function spend(traversal) {
847
+ traversal.remaining -= 1;
848
+ if (traversal.remaining < 0) throw new Bail();
849
+ }
850
+ function mapSubschemas(node, visit) {
851
+ const result = {};
852
+ for (const [key, value] of Object.entries(node)) {
853
+ let next = value;
854
+ if (SUBSCHEMA_KEYWORDS.has(key)) {
855
+ next = Array.isArray(value) ? value.map(visit) : visit(value);
856
+ } else if (SUBSCHEMA_ARRAY_KEYWORDS.has(key) && Array.isArray(value)) {
857
+ next = value.map(visit);
858
+ } else if (SUBSCHEMA_MAP_KEYWORDS.has(key) && isRecord(value)) {
859
+ next = mapNames(value, visit);
860
+ }
861
+ define(result, key, next);
862
+ }
863
+ return result;
864
+ }
865
+ function mapNames(map, visit) {
866
+ const result = {};
867
+ for (const [name, value] of Object.entries(map)) {
868
+ define(result, name, Array.isArray(value) ? value : visit(value));
869
+ }
870
+ return result;
871
+ }
872
+ function define(target, key, value) {
873
+ Object.defineProperty(target, key, {
874
+ value,
875
+ writable: true,
876
+ enumerable: true,
877
+ configurable: true
878
+ });
879
+ }
880
+ function isRecord(value) {
881
+ return typeof value === "object" && value !== null && !Array.isArray(value);
882
+ }
883
+ function resolvePointer(root, ref) {
884
+ if (!ref.startsWith("#")) return void 0;
885
+ let pointer;
886
+ try {
887
+ pointer = decodeURIComponent(ref.slice(1));
888
+ } catch {
889
+ return void 0;
890
+ }
891
+ if (pointer === "") return root;
892
+ if (!pointer.startsWith("/")) return void 0;
893
+ let current = root;
894
+ for (const token of pointer.slice(1).split("/")) {
895
+ if (/~(?![01])/.test(token)) return void 0;
896
+ const segment = token.replace(/~1/g, "/").replace(/~0/g, "~");
897
+ if (Array.isArray(current)) {
898
+ const index = Number(segment);
899
+ if (!/^(0|[1-9]\d*)$/.test(segment) || index >= current.length) {
900
+ return void 0;
901
+ }
902
+ current = current[index];
903
+ } else if (isRecord(current) && Object.hasOwn(current, segment)) {
904
+ current = current[segment];
905
+ } else {
906
+ return void 0;
907
+ }
908
+ }
909
+ return current;
910
+ }
911
+ function containsRef(node, depth) {
912
+ if (depth > MAX_DEPTH) throw new Bail();
913
+ if (!isRecord(node)) return false;
914
+ if (typeof node.$ref === "string") return true;
915
+ let found = false;
916
+ mapSubschemas(node, (child) => {
917
+ found ||= containsRef(child, depth + 1);
918
+ return child;
919
+ });
920
+ return found;
921
+ }
922
+ function inline(node, traversal, depth) {
923
+ if (depth > MAX_DEPTH) throw new Bail();
924
+ if (!isRecord(node)) return node;
925
+ if (node !== traversal.root && typeof node.$id === "string") return node;
926
+ spend(traversal);
927
+ const visit = (child) => inline(child, traversal, depth + 1);
928
+ const ref = node.$ref;
929
+ const siblingsConstrain = Object.keys(node).some(
930
+ (key) => key !== "$ref" && !NON_CONSTRAINT_SIBLINGS.has(key)
931
+ );
932
+ if (typeof ref === "string" && !siblingsConstrain && !traversal.active.has(ref)) {
933
+ const target = resolvePointer(traversal.root, ref);
934
+ if (isRecord(target)) {
935
+ traversal.active.add(ref);
936
+ const resolved2 = visit(target);
937
+ traversal.active.delete(ref);
938
+ const siblings = { ...node };
939
+ delete siblings.$ref;
940
+ return { ...resolved2, ...mapSubschemas(siblings, visit) };
941
+ }
942
+ }
943
+ return mapSubschemas(node, visit);
944
+ }
945
+ var cache = /* @__PURE__ */ new WeakMap();
946
+ function inlineLocalRefs(schema) {
947
+ if (!isRecord(schema)) return schema;
948
+ const cached = cache.get(schema);
949
+ if (cached !== void 0) return cached;
950
+ let resolved2;
951
+ try {
952
+ resolved2 = containsRef(schema, 0) ? inline(
953
+ schema,
954
+ { root: schema, active: /* @__PURE__ */ new Set(), remaining: EXPANSION_BUDGET },
955
+ 0
956
+ ) : schema;
957
+ } catch (error) {
958
+ if (!(error instanceof Bail)) throw error;
959
+ resolved2 = schema;
960
+ }
961
+ cache.set(schema, resolved2);
962
+ return resolved2;
963
+ }
964
+
791
965
  // ../../core/json/nullableUnion.ts
792
966
  var RENDERABLE_TYPES = [
793
967
  "string",
@@ -1386,7 +1560,7 @@ function convertToolParameters(tool, params) {
1386
1560
  function convertParametersForSchema(inputSchema, params) {
1387
1561
  const result = {};
1388
1562
  const { base, branches } = resolveRootUnion(
1389
- inputSchema ?? {}
1563
+ inlineLocalRefs(inputSchema ?? {})
1390
1564
  );
1391
1565
  const properties = coercionProperties(base, branches, params);
1392
1566
  for (const [key, value] of Object.entries(params)) {
@@ -1578,7 +1752,7 @@ function oauthEndpointOverridesFromSettings(settings) {
1578
1752
  };
1579
1753
  }
1580
1754
  function storedFieldsToInspectorSettings(stored) {
1581
- const hasAny = stored.headers !== void 0 || stored.metadata !== void 0 || stored.connectionTimeout !== void 0 || stored.requestTimeout !== void 0 || stored.taskTtl !== void 0 || stored.autoRefreshOnListChanged !== void 0 || stored.paginatedLists !== void 0 || stored.advertisedExtensions !== void 0 || stored.maxFetchRequests !== void 0 || stored.skillCatalogMaxSkills !== void 0 || stored.skillCatalogMaxBytes !== void 0 || stored.oauth !== void 0 || stored.roots !== void 0 || stored.protocolEra !== void 0 || stored.modernLogLevel !== void 0 || stored.env !== void 0 || stored.cwd !== void 0;
1755
+ const hasAny = stored.headers !== void 0 || stored.metadata !== void 0 || stored.connectionTimeout !== void 0 || stored.requestTimeout !== void 0 || stored.taskTtl !== void 0 || stored.autoRefreshOnListChanged !== void 0 || stored.paginatedLists !== void 0 || stored.suppressNotificationStream !== void 0 || stored.advertisedExtensions !== void 0 || stored.maxFetchRequests !== void 0 || stored.skillCatalogMaxSkills !== void 0 || stored.skillCatalogMaxBytes !== void 0 || stored.oauth !== void 0 || stored.roots !== void 0 || stored.protocolEra !== void 0 || stored.modernLogLevel !== void 0 || stored.env !== void 0 || stored.cwd !== void 0;
1582
1756
  if (!hasAny) return void 0;
1583
1757
  const headersPairs = stored.headers ? Object.entries(stored.headers).map(([key, value]) => ({ key, value })) : [];
1584
1758
  const settings = {
@@ -1610,6 +1784,9 @@ function storedFieldsToInspectorSettings(stored) {
1610
1784
  if (isSkillCatalogLimit(stored.skillCatalogMaxBytes)) {
1611
1785
  settings.skillCatalogMaxBytes = stored.skillCatalogMaxBytes;
1612
1786
  }
1787
+ if (stored.suppressNotificationStream === true) {
1788
+ settings.suppressNotificationStream = true;
1789
+ }
1613
1790
  if (isProtocolEra(stored.protocolEra)) {
1614
1791
  settings.protocolEra = stored.protocolEra;
1615
1792
  }
@@ -1661,6 +1838,7 @@ var INSPECTOR_FIELD_KEY_MAP = {
1661
1838
  taskTtl: true,
1662
1839
  autoRefreshOnListChanged: true,
1663
1840
  paginatedLists: true,
1841
+ suppressNotificationStream: true,
1664
1842
  advertisedExtensions: true,
1665
1843
  maxFetchRequests: true,
1666
1844
  skillCatalogMaxSkills: true,
@@ -2015,7 +2193,7 @@ function secretStorageCaveat(info) {
2015
2193
  return `The secrets file could not be read (${info.encryptionUnknown}). Saving a secret will fail rather than overwrite it.`;
2016
2194
  }
2017
2195
  if (info.plaintext) {
2018
- return info.pendingEncryption ? "Existing secrets in this file are still unencrypted (file mode 0600). They are re-encrypted the next time a secret is saved." : "Secrets are stored unencrypted (file mode 0600). Set MCP_INSPECTOR_SECRET_KEY to encrypt them.";
2196
+ return info.pendingEncryption ? "Existing secrets in this file are still unencrypted (file mode 0600). They are re-encrypted the next time a secret is saved." : "Secrets are stored unencrypted (file mode 0600). Set MCP_INSPECTOR_SECRET_KEY or MCP_INSPECTOR_SECRET_KEY_FILE to encrypt them.";
2019
2197
  }
2020
2198
  return void 0;
2021
2199
  }
@@ -2030,9 +2208,23 @@ function secretStorageSummary(info) {
2030
2208
 
2031
2209
  // ../../core/auth/node/file-secret-store.ts
2032
2210
  import * as crypto2 from "crypto";
2211
+ import { readFileSync as readFileSync2, statSync as statSync2 } from "fs";
2033
2212
  import * as fs3 from "fs/promises";
2034
2213
  import * as path3 from "path";
2035
2214
 
2215
+ // ../../core/storage/own-entry.ts
2216
+ function setOwnEntry(map, key, value) {
2217
+ Object.defineProperty(map, key, {
2218
+ value,
2219
+ enumerable: true,
2220
+ writable: true,
2221
+ configurable: true
2222
+ });
2223
+ }
2224
+ function getOwnEntry(map, key) {
2225
+ return map !== void 0 && Object.hasOwn(map, key) ? map[key] : void 0;
2226
+ }
2227
+
2036
2228
  // ../../core/auth/node/file-lock.ts
2037
2229
  import nodeFs, { statSync, rmdirSync } from "fs";
2038
2230
  import * as fs2 from "fs/promises";
@@ -2091,6 +2283,12 @@ var SecretStoreUnavailableError = class extends Error {
2091
2283
  this.name = "SecretStoreUnavailableError";
2092
2284
  }
2093
2285
  };
2286
+ var SecretFileLockHeldError = class extends SecretStoreUnavailableError {
2287
+ constructor(message, options) {
2288
+ super(message, options);
2289
+ this.name = "SecretFileLockHeldError";
2290
+ }
2291
+ };
2094
2292
  var KeychainUnavailableError = class extends SecretStoreUnavailableError {
2095
2293
  constructor(cause) {
2096
2294
  const message = cause instanceof Error ? cause.message : String(cause);
@@ -2121,6 +2319,7 @@ async function probeKeyringAvailable() {
2121
2319
  try {
2122
2320
  const entry = new keyring.mod.AsyncEntry(SERVICE_NAME, PROBE_ACCOUNT);
2123
2321
  await entry.getPassword();
2322
+ await keyring.mod.findCredentialsAsync(SERVICE_NAME);
2124
2323
  return { available: true };
2125
2324
  } catch (err) {
2126
2325
  return {
@@ -2130,6 +2329,7 @@ async function probeKeyringAvailable() {
2130
2329
  }
2131
2330
  }
2132
2331
  var PROBE_ACCOUNT = "__inspector:probe";
2332
+ var isNoEntryError = (err) => err instanceof Error && /no (matching )?entry/i.test(err.message);
2133
2333
  var KeyringSecretStore = class {
2134
2334
  /**
2135
2335
  * The intolerant read. Same lookup as {@link get}, minus the catch — a
@@ -2181,23 +2381,27 @@ var KeyringSecretStore = class {
2181
2381
  async delete(serverId, field) {
2182
2382
  try {
2183
2383
  const keyring = await loadKeyring();
2184
- if (!keyring.ok) return;
2384
+ if (!keyring.ok) throw new KeychainUnavailableError(keyring.err);
2185
2385
  const entry = new keyring.mod.AsyncEntry(
2186
2386
  SERVICE_NAME,
2187
2387
  buildAccount(serverId, field)
2188
2388
  );
2189
2389
  await entry.deleteCredential();
2190
- } catch {
2390
+ } catch (err) {
2391
+ if (isNoEntryError(err)) return;
2392
+ if (err instanceof KeychainUnavailableError) throw err;
2393
+ throw new KeychainUnavailableError(err);
2191
2394
  }
2192
2395
  }
2193
2396
  async deleteAllForServer(serverId) {
2194
2397
  let creds;
2195
2398
  try {
2196
2399
  const keyring = await loadKeyring();
2197
- if (!keyring.ok) return;
2400
+ if (!keyring.ok) throw new KeychainUnavailableError(keyring.err);
2198
2401
  creds = await keyring.mod.findCredentialsAsync(SERVICE_NAME);
2199
- } catch {
2200
- return;
2402
+ } catch (err) {
2403
+ if (err instanceof KeychainUnavailableError) throw err;
2404
+ throw new KeychainUnavailableError(err);
2201
2405
  }
2202
2406
  const prefix = `${serverId}:`;
2203
2407
  for (const c of creds) {
@@ -2211,6 +2415,25 @@ var KeyringSecretStore = class {
2211
2415
  async function secretStoreGetStrict(store, serverId, field) {
2212
2416
  return store.getStrict ? store.getStrict(serverId, field) : store.get(serverId, field);
2213
2417
  }
2418
+ async function snapshotSecretFields(store, serverId, fields) {
2419
+ return Promise.all(
2420
+ fields.map(async (field) => ({
2421
+ serverId,
2422
+ field,
2423
+ value: await secretStoreGetStrict(store, serverId, field)
2424
+ }))
2425
+ );
2426
+ }
2427
+ async function restoreSecretFields(store, snapshot, onRestoreFailure) {
2428
+ for (const { serverId, field, value } of snapshot) {
2429
+ try {
2430
+ if (value === null) await store.delete(serverId, field);
2431
+ else await store.set(serverId, field, value);
2432
+ } catch (error) {
2433
+ onRestoreFailure(error);
2434
+ }
2435
+ }
2436
+ }
2214
2437
  async function secretStoreGetMany(store, requests) {
2215
2438
  if (store.getMany) return store.getMany(requests);
2216
2439
  const out = {};
@@ -2223,16 +2446,44 @@ async function secretStoreGetMany(store, requests) {
2223
2446
  );
2224
2447
  const found = {};
2225
2448
  for (const [field, value] of entries) {
2226
- if (value !== null) found[field] = value;
2449
+ if (value !== null) setOwnEntry(found, field, value);
2450
+ }
2451
+ setOwnEntry(out, serverId, found);
2452
+ })
2453
+ );
2454
+ return out;
2455
+ }
2456
+ async function secretStoreGetManyStrict(store, requests) {
2457
+ if (store.getManyStrict) return store.getManyStrict(requests);
2458
+ const out = {};
2459
+ await Promise.all(
2460
+ requests.map(async ({ serverId, fields }) => {
2461
+ const entries = await Promise.all(
2462
+ fields.map(
2463
+ async (field) => [
2464
+ field,
2465
+ await secretStoreGetStrict(store, serverId, field)
2466
+ ]
2467
+ )
2468
+ );
2469
+ const found = {};
2470
+ for (const [field, value] of entries) {
2471
+ if (value !== null) setOwnEntry(found, field, value);
2227
2472
  }
2228
- out[serverId] = found;
2473
+ setOwnEntry(out, serverId, found);
2229
2474
  })
2230
2475
  );
2231
2476
  return out;
2232
2477
  }
2478
+ async function settleStoreMutations(mutations) {
2479
+ const results = await Promise.allSettled(mutations);
2480
+ for (const result of results) {
2481
+ if (result.status === "rejected") throw result.reason;
2482
+ }
2483
+ }
2233
2484
  async function secretStoreSetMany(store, serverId, values) {
2234
2485
  if (store.setMany) return store.setMany(serverId, values);
2235
- await Promise.all(
2486
+ await settleStoreMutations(
2236
2487
  Object.entries(values).map(
2237
2488
  ([field, value]) => store.set(serverId, field, value)
2238
2489
  )
@@ -2401,7 +2652,7 @@ async function openSecretFileLock(filePath) {
2401
2652
  });
2402
2653
  } catch (err) {
2403
2654
  if (isStuckOrHeld(err, lockPathOf(target))) {
2404
- throw new SecretStoreUnavailableError(
2655
+ throw new SecretFileLockHeldError(
2405
2656
  `Could not save to the secrets file at ${target}: its lock (${lockPathOf(target)}) was still held after the ${Math.round(RETRY_BUDGET_MS / 1e3)} seconds this save waited. Its secrets are intact; the value you just entered was not saved. If no other Inspector is running, remove that lock and try again.`
2406
2657
  );
2407
2658
  }
@@ -2460,7 +2711,63 @@ var SCRYPT_N = 16384;
2460
2711
  var SCRYPT_R = 8;
2461
2712
  var SCRYPT_P = 1;
2462
2713
  var SECRET_KEY_ENV = "MCP_INSPECTOR_SECRET_KEY";
2714
+ var SECRET_KEY_FILE_ENV = "MCP_INSPECTOR_SECRET_KEY_FILE";
2715
+ function isSameFile(a, b) {
2716
+ if (path3.resolve(a) === path3.resolve(b)) return true;
2717
+ try {
2718
+ const sa = statSync2(a);
2719
+ const sb = statSync2(b);
2720
+ return sa.dev === sb.dev && sa.ino === sb.ino;
2721
+ } catch {
2722
+ return false;
2723
+ }
2724
+ }
2725
+ function resolveSecretPassphrase(env2 = process.env, secretFilePath) {
2726
+ const direct = env2[SECRET_KEY_ENV];
2727
+ const hasDirect = direct !== void 0 && direct.trim() !== "";
2728
+ const rawKeyFile = env2[SECRET_KEY_FILE_ENV];
2729
+ const wantsKeyFile = rawKeyFile !== void 0;
2730
+ const keyFile = rawKeyFile?.trim();
2731
+ if (hasDirect && wantsKeyFile) {
2732
+ return {
2733
+ problem: `both ${SECRET_KEY_ENV} and ${SECRET_KEY_FILE_ENV} are set; set only one`
2734
+ };
2735
+ }
2736
+ if (hasDirect) return { passphrase: direct };
2737
+ if (!wantsKeyFile) return {};
2738
+ if (!keyFile) {
2739
+ return { problem: `${SECRET_KEY_FILE_ENV} is set but empty` };
2740
+ }
2741
+ const resolved2 = path3.resolve(keyFile);
2742
+ if (secretFilePath !== void 0 && isSameFile(resolved2, secretFilePath)) {
2743
+ return {
2744
+ problem: `${SECRET_KEY_FILE_ENV} (${resolved2}) is the secrets file itself; point it at a separate key file`
2745
+ };
2746
+ }
2747
+ let contents;
2748
+ try {
2749
+ contents = readFileSync2(resolved2, "utf-8");
2750
+ } catch (err) {
2751
+ return {
2752
+ // `String(err)` rather than `.message`: `readFileSync` only ever throws
2753
+ // an `Error`, so an `instanceof` guard would be a branch no test can take.
2754
+ problem: `${SECRET_KEY_FILE_ENV} (${resolved2}) could not be read: ${String(err)}`
2755
+ };
2756
+ }
2757
+ const passphrase = contents.replace(/[\r\n]+$/, "");
2758
+ if (passphrase.trim() === "") {
2759
+ return { problem: `${SECRET_KEY_FILE_ENV} (${resolved2}) is empty` };
2760
+ }
2761
+ return { passphrase };
2762
+ }
2463
2763
  var buildAccount2 = (serverId, field) => `${serverId}:${field}`;
2764
+ function assertSecretString(field, value) {
2765
+ if (typeof value !== "string") {
2766
+ throw new TypeError(
2767
+ `Refusing to store a non-string secret value (${typeof value}) for "${field}": the secrets file holds only strings, and writing this would make the whole file unreadable.`
2768
+ );
2769
+ }
2770
+ }
2464
2771
  function asSecretMap(value, filePath) {
2465
2772
  if (typeof value !== "object" || value === null || Array.isArray(value)) {
2466
2773
  throw new SecretStoreUnavailableError(
@@ -2479,7 +2786,7 @@ function asSecretMap(value, filePath) {
2479
2786
  var SecretFileKeyMismatchError = class extends SecretStoreUnavailableError {
2480
2787
  constructor(filePath, hasKey) {
2481
2788
  super(
2482
- hasKey ? `The secrets file at ${filePath} could not be decrypted with the current ${SECRET_KEY_ENV}. Refusing to write, which would overwrite the existing secrets. Restore the original passphrase, or delete the file to start over.` : `The secrets file at ${filePath} is encrypted but ${SECRET_KEY_ENV} is not set. Refusing to write, which would overwrite the existing secrets. Set the passphrase this file was written with, or delete the file to start over.`
2789
+ hasKey ? `The secrets file at ${filePath} could not be decrypted with the current ${SECRET_KEY_ENV} (or ${SECRET_KEY_FILE_ENV}). Refusing to write, which would overwrite the existing secrets. Restore the original passphrase, or delete the file to start over.` : `The secrets file at ${filePath} is encrypted but ${SECRET_KEY_ENV} is not set (nor ${SECRET_KEY_FILE_ENV}). Refusing to write, which would overwrite the existing secrets. Set the passphrase this file was written with, or delete the file to start over.`
2483
2790
  );
2484
2791
  this.name = "SecretFileKeyMismatchError";
2485
2792
  }
@@ -2537,10 +2844,17 @@ function encryptedEnvelopeProblem(parsed) {
2537
2844
  var FileSecretStore = class {
2538
2845
  filePath;
2539
2846
  passphrase;
2847
+ /**
2848
+ * Why a configured key could not be obtained. While set, every read throws
2849
+ * and every write refuses — see {@link SecretPassphrase}.
2850
+ */
2851
+ keyProblem;
2540
2852
  constructor(options) {
2541
2853
  this.filePath = options.filePath;
2542
- const raw = options.passphrase ?? process.env[SECRET_KEY_ENV];
2854
+ const resolved2 = options.passphrase !== void 0 ? { passphrase: options.passphrase } : resolveSecretPassphrase(process.env, this.filePath);
2855
+ const raw = resolved2.passphrase;
2543
2856
  this.passphrase = raw && raw.trim() ? raw : void 0;
2857
+ this.keyProblem = resolved2.problem;
2544
2858
  }
2545
2859
  /**
2546
2860
  * True when the *next write* will encrypt. This is the configured policy,
@@ -2555,7 +2869,8 @@ var FileSecretStore = class {
2555
2869
  * no file yet, or when it cannot be read or parsed.
2556
2870
  *
2557
2871
  * Separate from {@link encrypted} because the two genuinely disagree for a
2558
- * whole session: adding `MCP_INSPECTOR_SECRET_KEY` to an install that
2872
+ * whole session: adding a passphrase (`MCP_INSPECTOR_SECRET_KEY` or
2873
+ * `MCP_INSPECTOR_SECRET_KEY_FILE`) to an install that
2559
2874
  * already has a plaintext file flips `encrypted` to true immediately,
2560
2875
  * while the bytes stay readable until the next `set`. A descriptor built
2561
2876
  * from the policy would tell that user "File (encrypted)" while their
@@ -2579,6 +2894,9 @@ var FileSecretStore = class {
2579
2894
  * `set` is in fact about to refuse.
2580
2895
  */
2581
2896
  async readOnDiskEncryption() {
2897
+ if (this.keyProblem !== void 0) {
2898
+ return { state: "unreadable", detail: this.keyProblem };
2899
+ }
2582
2900
  let raw;
2583
2901
  try {
2584
2902
  raw = await readStoreFile(this.filePath);
@@ -2616,7 +2934,7 @@ var FileSecretStore = class {
2616
2934
  } catch (err) {
2617
2935
  return {
2618
2936
  state: "unreadable",
2619
- detail: err instanceof SecretFileKeyMismatchError ? `it cannot be decrypted with the current ${SECRET_KEY_ENV}` : err instanceof Error ? err.message : String(err)
2937
+ detail: err instanceof SecretFileKeyMismatchError ? `it cannot be decrypted with the current ${SECRET_KEY_ENV} (or ${SECRET_KEY_FILE_ENV})` : err instanceof Error ? err.message : String(err)
2620
2938
  };
2621
2939
  }
2622
2940
  return { state: "encrypted" };
@@ -2667,6 +2985,11 @@ var FileSecretStore = class {
2667
2985
  return this.serialize(() => this.readMap());
2668
2986
  }
2669
2987
  async readMap() {
2988
+ if (this.keyProblem !== void 0) {
2989
+ throw new SecretStoreUnavailableError(
2990
+ `The secrets file at ${this.filePath} cannot be used: ${this.keyProblem}. Refusing to read or write it rather than store secrets unencrypted.`
2991
+ );
2992
+ }
2670
2993
  const raw = await readStoreFile(this.filePath);
2671
2994
  if (raw === null) return null;
2672
2995
  let parsed;
@@ -2703,7 +3026,9 @@ var FileSecretStore = class {
2703
3026
  let plain;
2704
3027
  try {
2705
3028
  const key = await this.deriveKey(parsed.kdf);
2706
- const decipher = crypto2.createDecipheriv(CIPHER, key, parts.iv);
3029
+ const decipher = crypto2.createDecipheriv(CIPHER, key, parts.iv, {
3030
+ authTagLength: GCM_TAG_BYTES
3031
+ });
2707
3032
  decipher.setAuthTag(parts.tag);
2708
3033
  plain = Buffer.concat([
2709
3034
  decipher.update(parts.body),
@@ -2737,7 +3062,9 @@ var FileSecretStore = class {
2737
3062
  };
2738
3063
  const key = await this.deriveKey(kdf);
2739
3064
  const iv = crypto2.randomBytes(IV_BYTES);
2740
- const cipher = crypto2.createCipheriv(CIPHER, key, iv);
3065
+ const cipher = crypto2.createCipheriv(CIPHER, key, iv, {
3066
+ authTagLength: GCM_TAG_BYTES
3067
+ });
2741
3068
  const body = Buffer.concat([
2742
3069
  cipher.update(JSON.stringify(map), "utf-8"),
2743
3070
  cipher.final()
@@ -2902,9 +3229,36 @@ var FileSecretStore = class {
2902
3229
  const found = {};
2903
3230
  for (const field of fields) {
2904
3231
  const value = map?.[buildAccount2(serverId, field)];
2905
- if (value !== void 0) found[field] = value;
3232
+ if (value !== void 0) setOwnEntry(found, field, value);
2906
3233
  }
2907
- out[serverId] = found;
3234
+ setOwnEntry(out, serverId, found);
3235
+ }
3236
+ return out;
3237
+ }
3238
+ /**
3239
+ * Bulk twin of {@link getStrict}: the same single-pass read as
3240
+ * {@link getMany}, but an unreadable store throws (with the typed advice
3241
+ * {@link getStrict} attaches) instead of yielding no fields — required by
3242
+ * OAuth read hydration, whose result later drives store deletions.
3243
+ */
3244
+ async getManyStrict(requests) {
3245
+ let map;
3246
+ try {
3247
+ map = await this.serialize(() => this.readMap());
3248
+ } catch (err) {
3249
+ if (err instanceof SecretStoreUnavailableError) throw err;
3250
+ throw new SecretStoreUnavailableError(
3251
+ `Could not read the secrets file at ${this.filePath}: ${err instanceof Error ? err.message : String(err)}`
3252
+ );
3253
+ }
3254
+ const out = {};
3255
+ for (const { serverId, fields } of requests) {
3256
+ const found = {};
3257
+ for (const field of fields) {
3258
+ const value = map?.[buildAccount2(serverId, field)];
3259
+ if (value !== void 0) setOwnEntry(found, field, value);
3260
+ }
3261
+ setOwnEntry(out, serverId, found);
2908
3262
  }
2909
3263
  return out;
2910
3264
  }
@@ -2948,6 +3302,9 @@ var FileSecretStore = class {
2948
3302
  */
2949
3303
  async setMany(serverId, values) {
2950
3304
  if (Object.keys(values).length === 0) return;
3305
+ for (const [field, value] of Object.entries(values)) {
3306
+ assertSecretString(field, value);
3307
+ }
2951
3308
  await this.serialize(
2952
3309
  () => this.mutate((map) => {
2953
3310
  const next = { ...map };
@@ -2959,6 +3316,7 @@ var FileSecretStore = class {
2959
3316
  );
2960
3317
  }
2961
3318
  async set(serverId, field, value) {
3319
+ assertSecretString(field, value);
2962
3320
  await this.serialize(
2963
3321
  () => this.mutate((map) => ({
2964
3322
  ...map,
@@ -2974,9 +3332,11 @@ var FileSecretStore = class {
2974
3332
  await this.deleteWhere((key) => key.startsWith(prefix));
2975
3333
  }
2976
3334
  /**
2977
- * Shared delete body. Silent on every failure, matching the keyring store:
2978
- * every reason a delete can fail collapses to "the entry isn't there
2979
- * anymore", and `set` is the operation that reports a broken store.
3335
+ * Shared delete body. Same confirmed-delete contract as the keyring
3336
+ * store: a deletion that cannot be confirmed (unreadable file, failed
3337
+ * decrypt, failed write) must escape, because reporting success would
3338
+ * let a caller commit state that assumes the entry is gone — once the
3339
+ * file becomes readable again, a later read would resurrect it.
2980
3340
  */
2981
3341
  async deleteWhere(match) {
2982
3342
  try {
@@ -2989,7 +3349,12 @@ var FileSecretStore = class {
2989
3349
  return next;
2990
3350
  })
2991
3351
  );
2992
- } catch {
3352
+ } catch (err) {
3353
+ if (err instanceof SecretStoreUnavailableError) throw err;
3354
+ throw new SecretStoreUnavailableError(
3355
+ `Could not delete from the secrets file: ${err instanceof Error ? err.message : String(err)}`,
3356
+ { cause: err }
3357
+ );
2993
3358
  }
2994
3359
  }
2995
3360
  };
@@ -3022,6 +3387,7 @@ async function readSecretFilePermissions(filePath) {
3022
3387
  var SECRET_STORE_ENV = "MCP_INSPECTOR_SECRET_STORE";
3023
3388
  var SECRET_FILE_ENV = "MCP_INSPECTOR_SECRET_FILE";
3024
3389
  var STORAGE_DIR_ENV = "MCP_STORAGE_DIR";
3390
+ var SECRET_STORAGE_DOCS_URL = "https://github.com/modelcontextprotocol/inspector/blob/main/docs/secret-storage.md";
3025
3391
  var KINDS = ["keyring", "file", "memory"];
3026
3392
  function parseSecretStoreEnv(raw) {
3027
3393
  const value = raw?.trim().toLowerCase();
@@ -3164,6 +3530,11 @@ function warnAboutSecretStorage(info) {
3164
3530
  }
3165
3531
  const caveat = secretStorageCaveat(info);
3166
3532
  if (caveat) console.warn(`[mcp-inspector] ${caveat}`);
3533
+ if (info.reason === "fallback" || caveat) {
3534
+ console.warn(
3535
+ `[mcp-inspector] How the secret store is chosen, and how to secure it: ${SECRET_STORAGE_DOCS_URL}`
3536
+ );
3537
+ }
3167
3538
  }
3168
3539
  var resolved;
3169
3540
  function resolveSecretStore() {
@@ -3359,6 +3730,9 @@ var DeferredSecretStore = class {
3359
3730
  async getMany(requests) {
3360
3731
  return secretStoreGetMany(await this.target(), requests);
3361
3732
  }
3733
+ async getManyStrict(requests) {
3734
+ return secretStoreGetManyStrict(await this.target(), requests);
3735
+ }
3362
3736
  async get(serverId, field) {
3363
3737
  return (await this.target()).get(serverId, field);
3364
3738
  }
@@ -3576,12 +3950,31 @@ function redactJsonValue(value) {
3576
3950
  }
3577
3951
  return value;
3578
3952
  }
3953
+ function joinSensitiveContinuations(body) {
3954
+ const out = [];
3955
+ let sensitiveAt = -1;
3956
+ for (const pair of body.split("&")) {
3957
+ const eq = pair.indexOf("=");
3958
+ if (eq === -1) {
3959
+ if (sensitiveAt !== -1 && pair.length > 0) {
3960
+ out[sensitiveAt] += `%26${pair}`;
3961
+ } else {
3962
+ out.push(pair);
3963
+ }
3964
+ continue;
3965
+ }
3966
+ const [key] = new URLSearchParams(pair).keys();
3967
+ sensitiveAt = isSensitiveField(key) && eq < pair.length - 1 ? out.length : -1;
3968
+ out.push(pair);
3969
+ }
3970
+ return out.join("&");
3971
+ }
3579
3972
  function redactBody(body, contentType) {
3580
3973
  if (!body) return body;
3581
3974
  const type = (contentType ?? "").toLowerCase();
3582
3975
  if (type.includes("application/x-www-form-urlencoded")) {
3583
3976
  try {
3584
- const params = new URLSearchParams(body);
3977
+ const params = new URLSearchParams(joinSensitiveContinuations(body));
3585
3978
  let changed = false;
3586
3979
  for (const key of new Set(params.keys())) {
3587
3980
  if (isSensitiveField(key)) {
@@ -4305,6 +4698,73 @@ function createProxyFetch() {
4305
4698
  };
4306
4699
  }
4307
4700
 
4701
+ // ../../core/mcp/node/notificationHeadersFetch.ts
4702
+ import { PROTOCOL_VERSION_META_KEY } from "@modelcontextprotocol/client";
4703
+ function createNotificationHeadersFetch(baseFetch) {
4704
+ return (input, init) => {
4705
+ const method = modernNotificationMethod(init);
4706
+ if (method === void 0) return baseFetch(input, init);
4707
+ const headers = new Headers(init?.headers);
4708
+ headers.set("mcp-protocol-version", method.version);
4709
+ headers.set("mcp-method", method.method);
4710
+ return baseFetch(input, { ...init, headers });
4711
+ };
4712
+ }
4713
+ function modernNotificationMethod(init) {
4714
+ if (init?.method?.toUpperCase() !== "POST") return void 0;
4715
+ if (typeof init.body !== "string") return void 0;
4716
+ let message;
4717
+ try {
4718
+ message = JSON.parse(init.body);
4719
+ } catch {
4720
+ return void 0;
4721
+ }
4722
+ if (!isRecord2(message) || "id" in message) return void 0;
4723
+ if (typeof message.method !== "string") return void 0;
4724
+ const meta = isRecord2(message.params) ? message.params._meta : void 0;
4725
+ const version = isRecord2(meta) ? meta[PROTOCOL_VERSION_META_KEY] : void 0;
4726
+ if (typeof version !== "string" || version < MODERN_PROTOCOL_VERSION) {
4727
+ return void 0;
4728
+ }
4729
+ return { method: message.method, version };
4730
+ }
4731
+ function isRecord2(value) {
4732
+ return typeof value === "object" && value !== null && !Array.isArray(value);
4733
+ }
4734
+
4735
+ // ../../core/mcp/node/suppressNotificationStreamFetch.ts
4736
+ function createSuppressNotificationStreamFetch(baseFetch, endpoint) {
4737
+ return async (input, init) => {
4738
+ if (isStandaloneStreamRequest(input, init, endpoint)) {
4739
+ return new Response(null, {
4740
+ status: 405,
4741
+ statusText: "Method Not Allowed"
4742
+ });
4743
+ }
4744
+ return baseFetch(input, init);
4745
+ };
4746
+ }
4747
+ function requestUrl(input) {
4748
+ const raw = input instanceof Request ? input.url : input instanceof URL ? input.href : input;
4749
+ try {
4750
+ return new URL(raw);
4751
+ } catch {
4752
+ return void 0;
4753
+ }
4754
+ }
4755
+ function isStandaloneStreamRequest(input, init, endpoint) {
4756
+ const request = input instanceof Request ? input : void 0;
4757
+ const method = (init?.method ?? request?.method ?? "GET").toUpperCase();
4758
+ if (method !== "GET") return false;
4759
+ const url = requestUrl(input);
4760
+ if (!url || url.origin !== endpoint.origin || url.pathname !== endpoint.pathname || url.search !== endpoint.search) {
4761
+ return false;
4762
+ }
4763
+ const headers = new Headers(init?.headers ?? request?.headers);
4764
+ const accept = headers.get("accept")?.toLowerCase() ?? "";
4765
+ return accept.includes("text/event-stream") && !headers.has("last-event-id");
4766
+ }
4767
+
4308
4768
  // ../../core/mcp/node/transport.ts
4309
4769
  function headersFromSettings(settings) {
4310
4770
  if (!settings || settings.headers.length === 0) return void 0;
@@ -4392,10 +4852,14 @@ function createTransportNode(config, options = {}) {
4392
4852
  ...httpConfig.requestInit,
4393
4853
  ...headers && { headers }
4394
4854
  };
4855
+ const stampedFetch = createNotificationHeadersFetch(
4856
+ fetchWithOptionalAuthIntercept
4857
+ );
4858
+ const httpFetch = settings?.suppressNotificationStream === true ? createSuppressNotificationStreamFetch(stampedFetch, url) : stampedFetch;
4395
4859
  const transport = new StreamableHTTPClientTransport(url, {
4396
4860
  authProvider,
4397
4861
  requestInit,
4398
- fetch: fetchWithOptionalAuthIntercept,
4862
+ fetch: httpFetch,
4399
4863
  // SEP-2350: how the transport reacts to a `403 insufficient_scope`
4400
4864
  // challenge. Defaults to the SDK's `reauthorize` when unset.
4401
4865
  ...settings?.oauthOnInsufficientScope && {
@@ -4544,6 +5008,23 @@ function mergeSecretsIntoClientConfig(config, secrets) {
4544
5008
  }
4545
5009
 
4546
5010
  // ../../core/client/node-persistence.ts
5011
+ async function withClientConfigLock(filePath, action, body) {
5012
+ let entered = false;
5013
+ try {
5014
+ return await withSecretFileLock(filePath, async () => {
5015
+ entered = true;
5016
+ return body();
5017
+ });
5018
+ } catch (error) {
5019
+ if (!entered && error instanceof SecretFileLockHeldError) {
5020
+ throw new SecretFileLockHeldError(
5021
+ `Could not ${action} the client configuration: the file at ${filePath} is locked by another Inspector process and did not become available.`,
5022
+ { cause: error }
5023
+ );
5024
+ }
5025
+ throw error;
5026
+ }
5027
+ }
4547
5028
  async function readIdpSecretFromKeychain(secretStore) {
4548
5029
  const secret = await secretStore.get(
4549
5030
  CLIENT_KEYCHAIN_ID,
@@ -4553,29 +5034,39 @@ async function readIdpSecretFromKeychain(secretStore) {
4553
5034
  return { [SECRET_FIELD_IDP_CLIENT_SECRET]: secret };
4554
5035
  }
4555
5036
  async function migrateClientPlaintextSecret(filePath, config, secretStore) {
4556
- const { stripped, secrets } = extractSecretsFromClientConfig(config);
4557
- const value = secrets[SECRET_FIELD_IDP_CLIENT_SECRET];
4558
- if (!value) return config;
4559
5037
  try {
4560
- const existing = await secretStoreGetStrict(
4561
- secretStore,
4562
- CLIENT_KEYCHAIN_ID,
4563
- SECRET_FIELD_IDP_CLIENT_SECRET
4564
- );
4565
- if (existing === null) {
4566
- await secretStore.set(
4567
- CLIENT_KEYCHAIN_ID,
4568
- SECRET_FIELD_IDP_CLIENT_SECRET,
4569
- value
4570
- );
4571
- }
4572
- if (!await secretStoreIsDurable(secretStore)) return config;
4573
- await writeStoreFile(filePath, serializeStore(stripped));
4574
- return stripped;
5038
+ return await withClientConfigLock(filePath, "migrate", async () => {
5039
+ const raw = await readStoreFile(filePath);
5040
+ if (raw === null) return {};
5041
+ const fresh = parseClientConfig(parseStore(raw));
5042
+ const { stripped, secrets } = extractSecretsFromClientConfig(fresh);
5043
+ const value = secrets[SECRET_FIELD_IDP_CLIENT_SECRET];
5044
+ if (!value) return fresh;
5045
+ try {
5046
+ const existing = await secretStoreGetStrict(
5047
+ secretStore,
5048
+ CLIENT_KEYCHAIN_ID,
5049
+ SECRET_FIELD_IDP_CLIENT_SECRET
5050
+ );
5051
+ if (existing === null) {
5052
+ await secretStore.set(
5053
+ CLIENT_KEYCHAIN_ID,
5054
+ SECRET_FIELD_IDP_CLIENT_SECRET,
5055
+ value
5056
+ );
5057
+ }
5058
+ if (!await secretStoreIsDurable(secretStore)) return fresh;
5059
+ await writeStoreFile(filePath, serializeStore(stripped));
5060
+ return stripped;
5061
+ } catch (err) {
5062
+ if (err instanceof SecretStoreUnavailableError) {
5063
+ return fresh;
5064
+ }
5065
+ throw err;
5066
+ }
5067
+ });
4575
5068
  } catch (err) {
4576
- if (err instanceof SecretStoreUnavailableError) {
4577
- return config;
4578
- }
5069
+ if (err instanceof SecretFileLockHeldError) return config;
4579
5070
  throw err;
4580
5071
  }
4581
5072
  }
@@ -4778,7 +5269,7 @@ import {
4778
5269
  useCallback as useCallback14,
4779
5270
  useRef as useRef15
4780
5271
  } from "react";
4781
- import { Box as Box28, Text as Text25, useInput as useInput22, useApp } from "ink";
5272
+ import { Box as Box29, Text as Text26, useInput as useInput22, useApp } from "ink";
4782
5273
 
4783
5274
  // ../../core/mcp/inspectorClient.ts
4784
5275
  import { Client } from "@modelcontextprotocol/client";
@@ -4826,14 +5317,14 @@ var OBJECT_VALUED_SUBSCHEMA_KEYWORDS = /* @__PURE__ */ new Set([
4826
5317
  function pathName(path6) {
4827
5318
  return path6.length === 0 ? "<root>" : path6.join(".");
4828
5319
  }
4829
- function isRecord(node) {
5320
+ function isRecord3(node) {
4830
5321
  return node !== null && typeof node === "object";
4831
5322
  }
4832
5323
  function scanXMcpHeaderDeclarations(inputSchema) {
4833
5324
  const declarations = [];
4834
5325
  const seenLower = /* @__PURE__ */ new Map();
4835
5326
  const visit = (node, path6, reachable) => {
4836
- if (!isRecord(node)) return void 0;
5327
+ if (!isRecord3(node)) return void 0;
4837
5328
  const schema = node;
4838
5329
  if (X_MCP_HEADER_KEY in schema) {
4839
5330
  if (!reachable || path6.length === 0) {
@@ -4859,7 +5350,7 @@ function scanXMcpHeaderDeclarations(inputSchema) {
4859
5350
  declarations.push({ path: path6, headerName: raw, type });
4860
5351
  }
4861
5352
  const properties = schema.properties;
4862
- if (isRecord(properties)) {
5353
+ if (isRecord3(properties)) {
4863
5354
  for (const [key, child] of Object.entries(properties)) {
4864
5355
  const fault2 = visit(child, [...path6, key], reachable);
4865
5356
  if (fault2 !== void 0) return fault2;
@@ -4868,7 +5359,7 @@ function scanXMcpHeaderDeclarations(inputSchema) {
4868
5359
  for (const k of NON_REACHABLE_SUBSCHEMA_KEYWORDS) {
4869
5360
  const sub = schema[k];
4870
5361
  if (sub === void 0) continue;
4871
- const branches = Array.isArray(sub) ? sub : isRecord(sub) && OBJECT_VALUED_SUBSCHEMA_KEYWORDS.has(k) ? Object.values(sub) : [sub];
5362
+ const branches = Array.isArray(sub) ? sub : isRecord3(sub) && OBJECT_VALUED_SUBSCHEMA_KEYWORDS.has(k) ? Object.values(sub) : [sub];
4872
5363
  for (const branch of branches) {
4873
5364
  const fault2 = visit(branch, [...path6, `<${k}>`], false);
4874
5365
  if (fault2 !== void 0) return fault2;
@@ -5100,7 +5591,7 @@ import {
5100
5591
  LOG_LEVEL_META_KEY,
5101
5592
  CLIENT_CAPABILITIES_META_KEY,
5102
5593
  CLIENT_INFO_META_KEY,
5103
- PROTOCOL_VERSION_META_KEY,
5594
+ PROTOCOL_VERSION_META_KEY as PROTOCOL_VERSION_META_KEY2,
5104
5595
  RELATED_TASK_META_KEY as RELATED_TASK_META_KEY3
5105
5596
  } from "@modelcontextprotocol/client";
5106
5597
 
@@ -5169,10 +5660,13 @@ var ADVERTISABLE_EXTENSIONS = [
5169
5660
  {
5170
5661
  key: UI_EXTENSION_KEY,
5171
5662
  label: "MCP Apps UI (io.modelcontextprotocol/ui)",
5172
- // The MCP Apps UI extension. The Inspector always renders App tools, so it
5173
- // advertises this by default with the App resource MIME type it supports —
5174
- // a conforming server checks the `mimeTypes` before serving a UI resource.
5663
+ // The MCP Apps UI extension, advertised with the App resource MIME type the
5664
+ // Inspector renders — a conforming server checks the `mimeTypes` before
5665
+ // serving a UI resource. Default-on only where Apps can actually be
5666
+ // rendered (the web client); the CLI and TUI cannot, so they leave it off
5667
+ // unless explicitly overridden (#2403).
5175
5668
  defaultAdvertised: true,
5669
+ requiresAppRenderer: true,
5176
5670
  advertisement: { mimeTypes: [MCP_APP_MIME_TYPE] }
5177
5671
  },
5178
5672
  {
@@ -5188,10 +5682,13 @@ var ADVERTISABLE_EXTENSIONS = [
5188
5682
  defaultAdvertised: true
5189
5683
  }
5190
5684
  ];
5685
+ function isAdvertisedByDefault(ext, rendersApps) {
5686
+ return ext.defaultAdvertised && (!ext.requiresAppRenderer || rendersApps);
5687
+ }
5191
5688
  function buildClientExtensions(input) {
5192
5689
  const map = {};
5193
5690
  for (const ext of ADVERTISABLE_EXTENSIONS) {
5194
- const advertised = input.advertised?.[ext.key] ?? ext.defaultAdvertised;
5691
+ const advertised = input.advertised?.[ext.key] ?? isAdvertisedByDefault(ext, input.rendersApps === true);
5195
5692
  if (advertised) {
5196
5693
  map[ext.key] = ext.advertisement ? structuredClone(ext.advertisement) : {};
5197
5694
  }
@@ -6180,7 +6677,15 @@ function exemptMcpEndpoint(getServerUrl, negotiatesEndpoint) {
6180
6677
  }
6181
6678
  };
6182
6679
  }
6183
- var REQUEST_DEADLINES = /* @__PURE__ */ new WeakMap();
6680
+ var REQUEST_DEADLINES = /* @__PURE__ */ new WeakMap();
6681
+ function stampRequestDeadline(init, budget) {
6682
+ if (REQUEST_DEADLINES.has(init)) {
6683
+ throw new Error(
6684
+ "stampRequestDeadline: this RequestInit already carries a deadline \u2014 withOAuthRequestTimeout must build a fresh init per call (#2418)"
6685
+ );
6686
+ }
6687
+ REQUEST_DEADLINES.set(init, budget);
6688
+ }
6184
6689
  function requestHeadersOf(input, init) {
6185
6690
  if (init?.headers) return new Headers(init.headers);
6186
6691
  if (typeof input !== "string" && !(input instanceof URL)) {
@@ -6238,7 +6743,7 @@ function withOAuthRequestTimeout(fetchFn, timeoutMs = DEFAULT_OAUTH_REQUEST_TIME
6238
6743
  }
6239
6744
  });
6240
6745
  const nextInit = { ...init, signal };
6241
- REQUEST_DEADLINES.set(nextInit, budget);
6746
+ stampRequestDeadline(nextInit, budget);
6242
6747
  let settled;
6243
6748
  let drainReader;
6244
6749
  try {
@@ -6351,7 +6856,7 @@ function withRfc8414OidcCompat(fetchFn) {
6351
6856
  return response;
6352
6857
  }
6353
6858
  if (!probe.ok) {
6354
- await releaseBody(probe);
6859
+ releaseBodyDetached(probe);
6355
6860
  if (callerSignal?.aborted) {
6356
6861
  releaseBodyDetached(response);
6357
6862
  throw callerSignal.reason;
@@ -6375,7 +6880,7 @@ function withRfc8414OidcCompat(fetchFn) {
6375
6880
  return response;
6376
6881
  }
6377
6882
  const source = probe.url || candidate;
6378
- await releaseBody(response);
6883
+ releaseBodyDetached(response);
6379
6884
  console.warn(
6380
6885
  `[oauth] ${source} returned RFC 8414 OAuth 2.0 authorization server metadata, not an OpenID provider document. The MCP TypeScript SDK validates that path as OpenID Connect Discovery and would reject it (modelcontextprotocol/typescript-sdk#2733), so the Inspector is handing it to discovery as the RFC 8414 document it is.`
6381
6886
  );
@@ -7165,7 +7670,7 @@ async function collectGrants(snapshot) {
7165
7670
  return { grants, failures };
7166
7671
  }
7167
7672
  async function parseTokens(raw) {
7168
- return raw === void 0 || raw === null ? void 0 : await OAuthTokensSchema.parseAsync(raw);
7673
+ return raw === void 0 || raw === null ? void 0 : await OAuthTokensSchema.partial().parseAsync(raw);
7169
7674
  }
7170
7675
  async function parseClient(raw) {
7171
7676
  return raw === void 0 || raw === null ? void 0 : await OAuthClientInformationSchema.parseAsync(raw);
@@ -8946,6 +9451,14 @@ function progressTokenOf(message) {
8946
9451
  }
8947
9452
  return void 0;
8948
9453
  }
9454
+ function waitForProgressToken(waits, token) {
9455
+ const exact = waits.get(token);
9456
+ if (exact !== void 0 || typeof token === "number") {
9457
+ return exact;
9458
+ }
9459
+ const numeric = Number(token);
9460
+ return Number.isSafeInteger(numeric) ? waits.get(numeric) : void 0;
9461
+ }
8949
9462
 
8950
9463
  // ../../core/mcp/remote/remoteClientTransport.ts
8951
9464
  var DEFAULT_SSE_RESPONSE_TIMEOUT_MS = 6e4;
@@ -9422,8 +9935,8 @@ var RemoteClientTransport = class {
9422
9935
  });
9423
9936
  }
9424
9937
  /** Re-arm a pending request's SSE wait timeout on a matching progress note. */
9425
- resetSseResponseWait(requestId) {
9426
- this.sseResponseWaits.get(requestId)?.resetTimeout();
9938
+ resetSseResponseWait(progressToken) {
9939
+ waitForProgressToken(this.sseResponseWaits, progressToken)?.resetTimeout();
9427
9940
  }
9428
9941
  async postSend(message, options, retryCount) {
9429
9942
  const requestId = requestIdForMessage(message);
@@ -9628,6 +10141,11 @@ var InspectorClient = class _InspectorClient extends InspectorClientEventTarget
9628
10141
  requestTimeout;
9629
10142
  defaultMetadata;
9630
10143
  serverSettings;
10144
+ // The settings the current transport was built from. `serverSettings` is
10145
+ // replaced live on every settings save (#1444), but transport-level inputs
10146
+ // such as custom headers are fixed when the transport is created, so this
10147
+ // is what the open connection actually sends (#2460).
10148
+ transportSettings;
9631
10149
  versionNegotiation;
9632
10150
  status = "disconnected";
9633
10151
  // True only while an explicit disconnect() owns the teardown. close() can
@@ -9982,6 +10500,10 @@ var InspectorClient = class _InspectorClient extends InspectorClientEventTarget
9982
10500
  const advertisedExtensions = buildClientExtensions({
9983
10501
  enterpriseManaged: options.oauth?.enterpriseManaged ?? false,
9984
10502
  advertised: this.advertisedExtensions,
10503
+ // Only a client that can render Apps claims the UI extension by default
10504
+ // (#2403). An app-elicitation renderer is itself a claim to host an App,
10505
+ // so supplying one implies it.
10506
+ rendersApps: options.rendersApps === true || this.appElicitationRenderer !== void 0,
9985
10507
  // Read off the built `capabilities.elicitation.form` rather than
9986
10508
  // re-deriving from `options.elicit`: the nested MCP Apps `elicitation`
9987
10509
  // setting must never be advertised without the core form capability it
@@ -10407,6 +10929,7 @@ var InspectorClient = class _InspectorClient extends InspectorClientEventTarget
10407
10929
  }
10408
10930
  this.baseTransport = null;
10409
10931
  this.transport = null;
10932
+ this.transportSettings = void 0;
10410
10933
  this.transportHasAuthProvider = false;
10411
10934
  }
10412
10935
  /**
@@ -10880,6 +11403,7 @@ var InspectorClient = class _InspectorClient extends InspectorClientEventTarget
10880
11403
  transportOptions
10881
11404
  );
10882
11405
  this.baseTransport = baseTransport;
11406
+ this.transportSettings = transportOptions.settings;
10883
11407
  if (this.directAuthRecovery) {
10884
11408
  this.directAuthRecoveryActive = !(baseTransport instanceof RemoteClientTransport);
10885
11409
  }
@@ -11081,6 +11605,7 @@ var InspectorClient = class _InspectorClient extends InspectorClientEventTarget
11081
11605
  }
11082
11606
  this.baseTransport = null;
11083
11607
  this.transport = null;
11608
+ this.transportSettings = void 0;
11084
11609
  this.transportHasAuthProvider = false;
11085
11610
  this.clearPendingPeerRequests();
11086
11611
  if (this.status !== "disconnected") {
@@ -11237,7 +11762,7 @@ var InspectorClient = class _InspectorClient extends InspectorClientEventTarget
11237
11762
  ...params,
11238
11763
  _meta: {
11239
11764
  ...existingMeta,
11240
- [PROTOCOL_VERSION_META_KEY]: protocolVersion,
11765
+ [PROTOCOL_VERSION_META_KEY2]: protocolVersion,
11241
11766
  [CLIENT_INFO_META_KEY]: this.clientInfo,
11242
11767
  [CLIENT_CAPABILITIES_META_KEY]: clientCapabilities
11243
11768
  }
@@ -11813,6 +12338,13 @@ var InspectorClient = class _InspectorClient extends InspectorClientEventTarget
11813
12338
  getClientCapabilities() {
11814
12339
  return this.clientCapabilities;
11815
12340
  }
12341
+ /**
12342
+ * Get the client identity (name, version) this client reports to servers —
12343
+ * the caller's `clientIdentity`, or core's neutral fallback without one.
12344
+ */
12345
+ getClientInfo() {
12346
+ return this.clientInfo;
12347
+ }
11816
12348
  /**
11817
12349
  * Get server info (name, version)
11818
12350
  */
@@ -11864,6 +12396,16 @@ var InspectorClient = class _InspectorClient extends InspectorClientEventTarget
11864
12396
  getServerSettings() {
11865
12397
  return this.serverSettings;
11866
12398
  }
12399
+ /**
12400
+ * The settings the current transport was built from, or `undefined` when no
12401
+ * transport exists. Unlike {@link getServerSettings}, a live settings edit
12402
+ * does not change this: transport-level inputs (custom headers) apply only
12403
+ * when the next transport is created, so comparing the two tells a caller
12404
+ * whether an edit is still waiting on a reconnect (#2460).
12405
+ */
12406
+ getTransportSettings() {
12407
+ return this.transportSettings;
12408
+ }
11867
12409
  /**
11868
12410
  * Replace the in-memory per-server settings on a live client. Lets a settings
11869
12411
  * edit (e.g. toggling auto-refresh-on-list-changed) take effect on the
@@ -13385,10 +13927,9 @@ var InspectorClient = class _InspectorClient extends InspectorClientEventTarget
13385
13927
  * removes it before the result gets here (#2373).
13386
13928
  *
13387
13929
  * Separate from {@link getSkill} because the callers differ: the UIs want the
13388
- * entry, while the CLI prints the result and must not reshape it. SEP-2640
13389
- * explicitly leaves open whether this result carries `ttlMs` / `cacheScope`,
13390
- * so a server may send them — and unwrapping to the entry discards exactly
13391
- * those (Copilot).
13930
+ * entry, while the CLI prints the result and must not reshape it. A modern
13931
+ * result carries `ttlMs` / `cacheScope` (#2404), and unwrapping to the entry
13932
+ * discards exactly those (Copilot).
13392
13933
  */
13393
13934
  async getSkillResult(uri, metadata) {
13394
13935
  if (!this.client) {
@@ -13399,11 +13940,12 @@ var InspectorClient = class _InspectorClient extends InspectorClientEventTarget
13399
13940
  uri,
13400
13941
  ...effectiveMeta ? { _meta: effectiveMeta } : {}
13401
13942
  };
13943
+ const resultSchema = this.isModernEra() ? ModernGetSkillEnvelopeSchema : GetSkillEnvelopeSchema;
13402
13944
  try {
13403
13945
  return await this.invokeMcpClient(
13404
13946
  () => this.client.request(
13405
13947
  { method: SKILLS_GET_METHOD, params },
13406
- GetSkillEnvelopeSchema,
13948
+ resultSchema,
13407
13949
  this.getRequestOptions(this.progressTokenOf(metadata))
13408
13950
  ),
13409
13951
  { method: SKILLS_GET_METHOD }
@@ -15275,7 +15817,7 @@ import { useCallback as useCallback2, useEffect, useState } from "react";
15275
15817
  // ../../core/react/useStoreSnapshot.ts
15276
15818
  import { useCallback, useRef, useSyncExternalStore } from "react";
15277
15819
  function useStoreSnapshot(store, event, read, whenAbsent) {
15278
- const cache = useRef(null);
15820
+ const cache2 = useRef(null);
15279
15821
  const subscribe = useCallback(
15280
15822
  (onStoreChange) => {
15281
15823
  if (!store) return () => {
@@ -15289,12 +15831,12 @@ function useStoreSnapshot(store, event, read, whenAbsent) {
15289
15831
  );
15290
15832
  const getSnapshot = useCallback(() => {
15291
15833
  const revision = store ? store.getEventRevision(event) : 0;
15292
- const cached = cache.current;
15834
+ const cached = cache2.current;
15293
15835
  if (cached && Object.is(cached.store, store) && cached.event === event && cached.read === read && Object.is(cached.whenAbsent, whenAbsent) && cached.revision === revision) {
15294
15836
  return cached.value;
15295
15837
  }
15296
15838
  const value = store ? read(store) : whenAbsent;
15297
- cache.current = { store, event, read, whenAbsent, revision, value };
15839
+ cache2.current = { store, event, read, whenAbsent, revision, value };
15298
15840
  return value;
15299
15841
  }, [store, event, read, whenAbsent]);
15300
15842
  return useSyncExternalStore(subscribe, getSnapshot, getSnapshot);
@@ -15699,7 +16241,7 @@ function classifyAuthorizationServerMismatch(err) {
15699
16241
  }
15700
16242
 
15701
16243
  // ../../core/node/version.ts
15702
- import { readFileSync as readFileSync3 } from "fs";
16244
+ import { readFileSync as readFileSync4 } from "fs";
15703
16245
  import { dirname as dirname5, join as join3, parse } from "path";
15704
16246
  import { fileURLToPath } from "url";
15705
16247
  var ROOT_PACKAGE_NAME = "@modelcontextprotocol/inspector";
@@ -15711,7 +16253,7 @@ function readInspectorVersion(callerUrl) {
15711
16253
  let manifest;
15712
16254
  try {
15713
16255
  manifest = JSON.parse(
15714
- readFileSync3(join3(dir, "package.json"), "utf-8")
16256
+ readFileSync4(join3(dir, "package.json"), "utf-8")
15715
16257
  );
15716
16258
  } catch {
15717
16259
  }
@@ -15734,42 +16276,57 @@ import {
15734
16276
  function withIssuer(value, issuer) {
15735
16277
  return issuer === void 0 ? value : { ...value, issuer };
15736
16278
  }
15737
- var OAuthStorageBase = class {
16279
+ var OAuthStorageCoordination = class {
15738
16280
  loaded = false;
15739
16281
  loadPromise;
15740
16282
  /** Serializes persist writes so concurrent mutators cannot reorder POSTs. */
15741
16283
  persistQueue = Promise.resolve();
16284
+ };
16285
+ var OAuthStorageBase = class {
16286
+ coordination;
15742
16287
  memory;
15743
16288
  backend;
15744
- constructor(memory, backend) {
16289
+ constructor(memory, backend, coordination = new OAuthStorageCoordination()) {
15745
16290
  this.memory = memory;
15746
16291
  this.backend = backend;
16292
+ this.coordination = coordination;
15747
16293
  }
15748
16294
  load() {
15749
- if (!this.loadPromise) {
15750
- this.loadPromise = this.doLoad();
16295
+ const coordination = this.coordination;
16296
+ if (!coordination.loadPromise) {
16297
+ coordination.loadPromise = this.doLoad().catch((error) => {
16298
+ coordination.loadPromise = void 0;
16299
+ throw error;
16300
+ });
15751
16301
  }
15752
- return this.loadPromise;
16302
+ return coordination.loadPromise;
15753
16303
  }
15754
16304
  async doLoad() {
15755
- if (this.loaded) {
16305
+ if (this.coordination.loaded) {
15756
16306
  return;
15757
16307
  }
15758
16308
  const snapshot = await this.backend.read();
15759
16309
  if (snapshot) {
15760
16310
  this.memory.replace(snapshot);
15761
16311
  }
15762
- this.loaded = true;
16312
+ this.coordination.loaded = true;
15763
16313
  }
15764
16314
  async ensureLoaded() {
15765
16315
  await this.load();
15766
16316
  }
15767
- async persist() {
15768
- const snapshot = this.memory.snapshot();
15769
- const prior = this.persistQueue;
16317
+ /**
16318
+ * Flush memory to the backend, naming the sections the calling mutation
16319
+ * touched so shared-store backends can merge just those entries over a
16320
+ * fresh read (the clobber fix — see {@link OAuthPersistSections}). The
16321
+ * snapshot is taken *inside* the queued closure, so a write that waited in
16322
+ * the queue carries the state as of when it actually runs, coalescing with
16323
+ * any mutations that landed in memory while it waited.
16324
+ */
16325
+ async persist(sections) {
16326
+ const prior = this.coordination.persistQueue;
15770
16327
  const tracked = prior.catch(() => {
15771
- }).then(() => this.backend.write(snapshot));
15772
- this.persistQueue = tracked;
16328
+ }).then(() => this.backend.write(this.memory.snapshot(), sections));
16329
+ this.coordination.persistQueue = tracked;
15773
16330
  await tracked;
15774
16331
  }
15775
16332
  /**
@@ -15783,7 +16340,7 @@ var OAuthStorageBase = class {
15783
16340
  /** Read the issuer-bound slot for a read, if one exists. */
15784
16341
  issuerSlot(state, issuer) {
15785
16342
  const key = this.resolveReadIssuer(state, issuer);
15786
- return key ? state.byIssuer?.[key] : void 0;
16343
+ return key ? getOwnEntry(state.byIssuer, key) : void 0;
15787
16344
  }
15788
16345
  /**
15789
16346
  * Read-modify-write the `byIssuer[issuer]` slot, set `activeIssuer`, and clear
@@ -15794,7 +16351,9 @@ var OAuthStorageBase = class {
15794
16351
  const state = this.memory.getState().getServerState(serverUrl);
15795
16352
  const byIssuer = {
15796
16353
  ...state.byIssuer,
15797
- [issuer]: { ...state.byIssuer?.[issuer], ...updates }
16354
+ // The computed key defines an own property; the merge-base read needs
16355
+ // the own guard so an absent `__proto__` slot reads as undefined.
16356
+ [issuer]: { ...getOwnEntry(state.byIssuer, issuer), ...updates }
15798
16357
  };
15799
16358
  this.memory.getState().setServerState(serverUrl, {
15800
16359
  byIssuer,
@@ -15806,7 +16365,7 @@ var OAuthStorageBase = class {
15806
16365
  mapIssuerSlots(state, fn) {
15807
16366
  const byIssuer = {};
15808
16367
  for (const [key, slot] of Object.entries(state.byIssuer ?? {})) {
15809
- byIssuer[key] = { ...slot, ...fn(slot) };
16368
+ setOwnEntry(byIssuer, key, { ...slot, ...fn(slot) });
15810
16369
  }
15811
16370
  return byIssuer;
15812
16371
  }
@@ -15852,7 +16411,7 @@ var OAuthStorageBase = class {
15852
16411
  clientRegistrationKind: options.registrationKind
15853
16412
  });
15854
16413
  }
15855
- await this.persist();
16414
+ await this.persist({ servers: [serverUrl] });
15856
16415
  }
15857
16416
  async savePreregisteredClientInformation(serverUrl, clientInformation) {
15858
16417
  await this.ensureLoaded();
@@ -15860,7 +16419,7 @@ var OAuthStorageBase = class {
15860
16419
  preregisteredClientInformation: clientInformation,
15861
16420
  clientRegistrationKind: "static"
15862
16421
  });
15863
- await this.persist();
16422
+ await this.persist({ servers: [serverUrl] });
15864
16423
  }
15865
16424
  async clearClientInformation(serverUrl, isPreregistered, issuer) {
15866
16425
  await this.ensureLoaded();
@@ -15868,7 +16427,7 @@ var OAuthStorageBase = class {
15868
16427
  this.memory.getState().setServerState(serverUrl, {
15869
16428
  preregisteredClientInformation: void 0
15870
16429
  });
15871
- await this.persist();
16430
+ await this.persist({ servers: [serverUrl] });
15872
16431
  return;
15873
16432
  }
15874
16433
  if (issuer !== void 0) {
@@ -15891,7 +16450,7 @@ var OAuthStorageBase = class {
15891
16450
  clientRegistrationKind: void 0
15892
16451
  });
15893
16452
  }
15894
- await this.persist();
16453
+ await this.persist({ servers: [serverUrl] });
15895
16454
  }
15896
16455
  async getTokens(serverUrl, issuer) {
15897
16456
  await this.ensureLoaded();
@@ -15902,9 +16461,12 @@ var OAuthStorageBase = class {
15902
16461
  if (!tokens) {
15903
16462
  return void 0;
15904
16463
  }
15905
- const parsed = await OAuthTokensSchema3.parseAsync(tokens);
16464
+ const result = await OAuthTokensSchema3.safeParseAsync(tokens);
16465
+ if (!result.success) {
16466
+ return void 0;
16467
+ }
15906
16468
  return withIssuer(
15907
- parsed,
16469
+ result.data,
15908
16470
  fromSlot ? this.resolveReadIssuer(state, issuer) : void 0
15909
16471
  );
15910
16472
  }
@@ -15928,7 +16490,7 @@ var OAuthStorageBase = class {
15928
16490
  ...options?.enterpriseManaged === true && { enterpriseManaged: true }
15929
16491
  });
15930
16492
  }
15931
- await this.persist();
16493
+ await this.persist({ servers: [serverUrl] });
15932
16494
  }
15933
16495
  async clearTokens(serverUrl, issuer) {
15934
16496
  await this.ensureLoaded();
@@ -15947,7 +16509,7 @@ var OAuthStorageBase = class {
15947
16509
  }));
15948
16510
  this.memory.getState().setServerState(serverUrl, { byIssuer, tokens: void 0 });
15949
16511
  }
15950
- await this.persist();
16512
+ await this.persist({ servers: [serverUrl] });
15951
16513
  }
15952
16514
  async getCodeVerifier(serverUrl) {
15953
16515
  await this.ensureLoaded();
@@ -15957,12 +16519,12 @@ var OAuthStorageBase = class {
15957
16519
  async saveCodeVerifier(serverUrl, codeVerifier) {
15958
16520
  await this.ensureLoaded();
15959
16521
  this.memory.getState().setServerState(serverUrl, { codeVerifier });
15960
- await this.persist();
16522
+ await this.persist({ servers: [serverUrl] });
15961
16523
  }
15962
16524
  async clearCodeVerifier(serverUrl) {
15963
16525
  await this.ensureLoaded();
15964
16526
  this.memory.getState().setServerState(serverUrl, { codeVerifier: void 0 });
15965
- await this.persist();
16527
+ await this.persist({ servers: [serverUrl] });
15966
16528
  }
15967
16529
  async getScope(serverUrl) {
15968
16530
  await this.ensureLoaded();
@@ -15972,12 +16534,12 @@ var OAuthStorageBase = class {
15972
16534
  async saveScope(serverUrl, scope) {
15973
16535
  await this.ensureLoaded();
15974
16536
  this.memory.getState().setServerState(serverUrl, { scope });
15975
- await this.persist();
16537
+ await this.persist({ servers: [serverUrl] });
15976
16538
  }
15977
16539
  async clearScope(serverUrl) {
15978
16540
  await this.ensureLoaded();
15979
16541
  this.memory.getState().setServerState(serverUrl, { scope: void 0 });
15980
- await this.persist();
16542
+ await this.persist({ servers: [serverUrl] });
15981
16543
  }
15982
16544
  async getServerMetadata(serverUrl) {
15983
16545
  await this.ensureLoaded();
@@ -15987,12 +16549,12 @@ var OAuthStorageBase = class {
15987
16549
  async saveServerMetadata(serverUrl, metadata) {
15988
16550
  await this.ensureLoaded();
15989
16551
  this.memory.getState().setServerState(serverUrl, { serverMetadata: metadata });
15990
- await this.persist();
16552
+ await this.persist({ servers: [serverUrl] });
15991
16553
  }
15992
16554
  async clearServerMetadata(serverUrl) {
15993
16555
  await this.ensureLoaded();
15994
16556
  this.memory.getState().setServerState(serverUrl, { serverMetadata: void 0 });
15995
- await this.persist();
16557
+ await this.persist({ servers: [serverUrl] });
15996
16558
  }
15997
16559
  async getDiscoveryState(serverUrl) {
15998
16560
  await this.ensureLoaded();
@@ -16001,12 +16563,12 @@ var OAuthStorageBase = class {
16001
16563
  async saveDiscoveryState(serverUrl, state) {
16002
16564
  await this.ensureLoaded();
16003
16565
  this.memory.getState().setServerState(serverUrl, { discoveryState: state });
16004
- await this.persist();
16566
+ await this.persist({ servers: [serverUrl] });
16005
16567
  }
16006
16568
  async clearDiscoveryState(serverUrl) {
16007
16569
  await this.ensureLoaded();
16008
16570
  this.memory.getState().setServerState(serverUrl, { discoveryState: void 0 });
16009
- await this.persist();
16571
+ await this.persist({ servers: [serverUrl] });
16010
16572
  }
16011
16573
  async takeRevocationSnapshot(serverUrl) {
16012
16574
  await this.ensureLoaded();
@@ -16024,13 +16586,13 @@ var OAuthStorageBase = class {
16024
16586
  serverMetadata: state.serverMetadata
16025
16587
  };
16026
16588
  this.memory.getState().clearServerState(serverUrl);
16027
- await this.persist();
16589
+ await this.persist({ servers: [serverUrl] });
16028
16590
  return snapshot;
16029
16591
  }
16030
16592
  async clear(serverUrl) {
16031
16593
  await this.ensureLoaded();
16032
16594
  this.memory.getState().clearServerState(serverUrl);
16033
- await this.persist();
16595
+ await this.persist({ servers: [serverUrl] });
16034
16596
  }
16035
16597
  async getIdpSession(issuer) {
16036
16598
  await this.ensureLoaded();
@@ -16043,17 +16605,18 @@ var OAuthStorageBase = class {
16043
16605
  async saveIdpSession(issuer, session) {
16044
16606
  await this.ensureLoaded();
16045
16607
  this.memory.getState().setIdpSession(issuer, session);
16046
- await this.persist();
16608
+ await this.persist({ idpSessions: [issuer] });
16047
16609
  }
16048
16610
  async clearIdpSession(issuer) {
16049
16611
  await this.ensureLoaded();
16050
16612
  this.memory.getState().clearIdpSession(issuer);
16051
- await this.persist();
16613
+ await this.persist({ idpSessions: [issuer] });
16052
16614
  }
16053
16615
  async clearEnterpriseManagedResourceServers() {
16054
16616
  await this.ensureLoaded();
16617
+ const servers = Object.entries(this.memory.getState().servers).filter(([, state]) => state.enterpriseManaged === true).map(([url]) => url);
16055
16618
  this.memory.getState().clearEnterpriseManagedResourceServers();
16056
- await this.persist();
16619
+ await this.persist({ servers });
16057
16620
  }
16058
16621
  };
16059
16622
 
@@ -16071,13 +16634,15 @@ var OAuthMemoryStore = class {
16071
16634
  servers: this.servers,
16072
16635
  idpSessions: this.idpSessions,
16073
16636
  getServerState: (serverUrl) => {
16074
- return this.servers[serverUrl] || {};
16637
+ return getOwnEntry(this.servers, serverUrl) || {};
16075
16638
  },
16076
16639
  setServerState: (serverUrl, updates) => {
16077
16640
  this.servers = {
16078
16641
  ...this.servers,
16642
+ // Computed keys define own properties, so this write is safe for
16643
+ // `__proto__`; only the merge-base read needs the own guard.
16079
16644
  [serverUrl]: {
16080
- ...this.servers[serverUrl],
16645
+ ...getOwnEntry(this.servers, serverUrl),
16081
16646
  ...updates
16082
16647
  }
16083
16648
  };
@@ -16088,13 +16653,13 @@ var OAuthMemoryStore = class {
16088
16653
  this.servers = rest;
16089
16654
  },
16090
16655
  getIdpSession: (issuer) => {
16091
- return this.idpSessions[issuer] || {};
16656
+ return getOwnEntry(this.idpSessions, issuer) || {};
16092
16657
  },
16093
16658
  setIdpSession: (issuer, updates) => {
16094
16659
  this.idpSessions = {
16095
16660
  ...this.idpSessions,
16096
16661
  [issuer]: {
16097
- ...this.idpSessions[issuer],
16662
+ ...getOwnEntry(this.idpSessions, issuer),
16098
16663
  ...updates
16099
16664
  }
16100
16665
  };
@@ -16111,67 +16676,877 @@ var OAuthMemoryStore = class {
16111
16676
  delete rest[url];
16112
16677
  }
16113
16678
  }
16114
- this.servers = rest;
16679
+ this.servers = rest;
16680
+ }
16681
+ };
16682
+ }
16683
+ snapshot() {
16684
+ return {
16685
+ servers: { ...this.servers },
16686
+ idpSessions: { ...this.idpSessions }
16687
+ };
16688
+ }
16689
+ replace(snapshot) {
16690
+ this.servers = { ...snapshot.servers ?? {} };
16691
+ this.idpSessions = { ...snapshot.idpSessions ?? {} };
16692
+ }
16693
+ };
16694
+
16695
+ // ../../core/auth/oauth-persist.ts
16696
+ import { OAuthTokensSchema as OAuthTokensSchema4 } from "@modelcontextprotocol/core";
16697
+ function mergeOAuthSections(disk, snapshot, sections) {
16698
+ const merged = {
16699
+ servers: { ...disk?.servers },
16700
+ idpSessions: { ...disk?.idpSessions }
16701
+ };
16702
+ for (const url of sections.servers ?? []) {
16703
+ const value = getOwnEntry(snapshot.servers, url);
16704
+ if (value === void 0) {
16705
+ delete merged.servers[url];
16706
+ } else {
16707
+ setOwnEntry(merged.servers, url, value);
16708
+ }
16709
+ }
16710
+ for (const issuer of sections.idpSessions ?? []) {
16711
+ const value = getOwnEntry(snapshot.idpSessions, issuer);
16712
+ if (value === void 0) {
16713
+ delete merged.idpSessions[issuer];
16714
+ } else {
16715
+ setOwnEntry(merged.idpSessions, issuer, value);
16716
+ }
16717
+ }
16718
+ return merged;
16719
+ }
16720
+ function isRecord4(value) {
16721
+ return typeof value === "object" && value !== null && !Array.isArray(value);
16722
+ }
16723
+ function isEntryMap(value) {
16724
+ return isRecord4(value) && Object.values(value).every(isRecord4);
16725
+ }
16726
+ var VERBATIM_SECRET_KEYS = [
16727
+ "client_secret",
16728
+ "registration_access_token"
16729
+ ];
16730
+ function isValidClientInformation(value) {
16731
+ if (value === void 0) return true;
16732
+ if (!isRecord4(value)) return false;
16733
+ return VERBATIM_SECRET_KEYS.every(
16734
+ (key) => !Object.hasOwn(value, key) || typeof value[key] === "string"
16735
+ );
16736
+ }
16737
+ var PartialTokensSchema = OAuthTokensSchema4.partial();
16738
+ function isValidServerEntry(entry) {
16739
+ if (!isRecord4(entry)) return false;
16740
+ if (!isValidClientInformation(entry.clientInformation)) return false;
16741
+ if (!isValidClientInformation(entry.preregisteredClientInformation))
16742
+ return false;
16743
+ if (entry.byIssuer !== void 0) {
16744
+ if (!isRecord4(entry.byIssuer)) return false;
16745
+ for (const slot of Object.values(entry.byIssuer)) {
16746
+ if (!isRecord4(slot)) return false;
16747
+ if (!isValidClientInformation(slot.clientInformation)) return false;
16748
+ }
16749
+ }
16750
+ return true;
16751
+ }
16752
+ function snapshotFromPayload(payload) {
16753
+ const servers = payload.servers ?? {};
16754
+ const idpSessions = payload.idpSessions ?? {};
16755
+ if (!isEntryMap(servers) || !isEntryMap(idpSessions)) return null;
16756
+ if (!Object.values(servers).every(isValidServerEntry)) return null;
16757
+ return {
16758
+ servers,
16759
+ idpSessions
16760
+ };
16761
+ }
16762
+ function parseOAuthPersistBlob(raw) {
16763
+ if (raw === null || raw === void 0) {
16764
+ return null;
16765
+ }
16766
+ const parsed = typeof raw === "string" ? raw ? parseStore(raw) : null : raw;
16767
+ if (!isRecord4(parsed)) {
16768
+ return null;
16769
+ }
16770
+ if (isRecord4(parsed.state) && "version" in parsed) {
16771
+ return snapshotFromPayload(parsed.state);
16772
+ }
16773
+ if ("servers" in parsed || "idpSessions" in parsed) {
16774
+ return snapshotFromPayload(parsed);
16775
+ }
16776
+ return null;
16777
+ }
16778
+ function serializeOAuthPersistBlob(snapshot) {
16779
+ return serializeStore(snapshot);
16780
+ }
16781
+
16782
+ // ../../core/auth/node/oauth-secrets.ts
16783
+ import { OAuthTokensSchema as OAuthTokensSchema5 } from "@modelcontextprotocol/core";
16784
+ var PERSIST_TOKENS_ENV = "MCP_INSPECTOR_PERSIST_TOKENS";
16785
+ var warnedPolicyValues = /* @__PURE__ */ new Set();
16786
+ function getPersistTokensPolicy(env2 = process.env) {
16787
+ const raw = env2[PERSIST_TOKENS_ENV];
16788
+ if (raw === void 0 || raw === "") return "all";
16789
+ if (raw === "all" || raw === "access" || raw === "none") return raw;
16790
+ if (!warnedPolicyValues.has(raw)) {
16791
+ warnedPolicyValues.add(raw);
16792
+ console.warn(
16793
+ `[mcp-inspector] Ignoring invalid ${PERSIST_TOKENS_ENV}=${JSON.stringify(raw)} (expected "all", "access", or "none"); persisting all tokens.`
16794
+ );
16795
+ }
16796
+ return "all";
16797
+ }
16798
+ var oauthSecretServerId = (serverUrl) => `oauth+${encodeURIComponent(serverUrl)}`;
16799
+ var oauthIdpSecretServerId = (issuer) => `oauth-idp+${encodeURIComponent(issuer)}`;
16800
+ var issuerTokensField = (issuer) => `tokens:${issuer}`;
16801
+ var issuerClientSecretField = (issuer) => `client-secret:${issuer}`;
16802
+ var issuerRegistrationTokenField = (issuer) => `registration-token:${issuer}`;
16803
+ var LEGACY_TOKENS_FIELD = "tokens";
16804
+ var LEGACY_CLIENT_SECRET_FIELD = "client-secret";
16805
+ var LEGACY_REGISTRATION_TOKEN_FIELD = "registration-token";
16806
+ var PREREG_CLIENT_SECRET_FIELD = "prereg-client-secret";
16807
+ var PREREG_REGISTRATION_TOKEN_FIELD = "prereg-registration-token";
16808
+ var IDP_SESSION_FIELD = "idp-session";
16809
+ function applyTokensPolicy(tokens, policy) {
16810
+ if (policy === "none") return void 0;
16811
+ if (policy === "access" && tokens.refresh_token !== void 0) {
16812
+ const { refresh_token: _stripped, ...rest } = tokens;
16813
+ return rest;
16814
+ }
16815
+ return tokens;
16816
+ }
16817
+ var StorableTokensSchema = OAuthTokensSchema5.partial();
16818
+ function hasSecretBearingTokenField(tokens) {
16819
+ return tokens.access_token !== void 0 || tokens.refresh_token !== void 0 || tokens.id_token !== void 0;
16820
+ }
16821
+ function splitTokens(tokens, policy) {
16822
+ const kept = applyTokensPolicy(tokens, policy);
16823
+ if (!kept) return {};
16824
+ if (!StorableTokensSchema.safeParse(kept).success) {
16825
+ return { plaintext: kept };
16826
+ }
16827
+ if (!hasSecretBearingTokenField(kept)) {
16828
+ return {};
16829
+ }
16830
+ return { secret: JSON.stringify(kept) };
16831
+ }
16832
+ function splitClientInformation(info, fields, secrets) {
16833
+ const { client_secret, registration_access_token, ...publicInfo } = info;
16834
+ if (client_secret === void 0 && registration_access_token === void 0) {
16835
+ return info;
16836
+ }
16837
+ if (client_secret !== void 0) {
16838
+ secrets[fields.clientSecret] = client_secret;
16839
+ }
16840
+ if (registration_access_token !== void 0) {
16841
+ secrets[fields.registrationToken] = registration_access_token;
16842
+ }
16843
+ return publicInfo;
16844
+ }
16845
+ function joinClientInformation(info, fields, secrets) {
16846
+ const clientSecret = secrets[fields.clientSecret];
16847
+ const registrationToken = secrets[fields.registrationToken];
16848
+ if (clientSecret === void 0 && registrationToken === void 0) {
16849
+ return info;
16850
+ }
16851
+ return {
16852
+ ...info,
16853
+ ...clientSecret !== void 0 && { client_secret: clientSecret },
16854
+ ...registrationToken !== void 0 && {
16855
+ registration_access_token: registrationToken
16856
+ }
16857
+ };
16858
+ }
16859
+ var issuerClientInfoFields = (issuer) => ({
16860
+ clientSecret: issuerClientSecretField(issuer),
16861
+ registrationToken: issuerRegistrationTokenField(issuer)
16862
+ });
16863
+ var LEGACY_CLIENT_INFO_FIELDS = {
16864
+ clientSecret: LEGACY_CLIENT_SECRET_FIELD,
16865
+ registrationToken: LEGACY_REGISTRATION_TOKEN_FIELD
16866
+ };
16867
+ var PREREG_CLIENT_INFO_FIELDS = {
16868
+ clientSecret: PREREG_CLIENT_SECRET_FIELD,
16869
+ registrationToken: PREREG_REGISTRATION_TOKEN_FIELD
16870
+ };
16871
+ function splitServerOAuthState(state, policy) {
16872
+ const secrets = {};
16873
+ const residue = { ...state };
16874
+ if (state.byIssuer) {
16875
+ const byIssuer = {};
16876
+ for (const [issuer, slot] of Object.entries(state.byIssuer)) {
16877
+ const slotResidue = { ...slot };
16878
+ if (slot.tokens) {
16879
+ delete slotResidue.tokens;
16880
+ const tokenSplit = splitTokens(slot.tokens, policy);
16881
+ if (tokenSplit.secret !== void 0) {
16882
+ secrets[issuerTokensField(issuer)] = tokenSplit.secret;
16883
+ }
16884
+ if (tokenSplit.plaintext) slotResidue.tokens = tokenSplit.plaintext;
16885
+ }
16886
+ if (slot.clientInformation) {
16887
+ slotResidue.clientInformation = splitClientInformation(
16888
+ slot.clientInformation,
16889
+ issuerClientInfoFields(issuer),
16890
+ secrets
16891
+ );
16892
+ }
16893
+ setOwnEntry(byIssuer, issuer, slotResidue);
16894
+ }
16895
+ residue.byIssuer = byIssuer;
16896
+ }
16897
+ if (state.tokens) {
16898
+ delete residue.tokens;
16899
+ const tokenSplit = splitTokens(state.tokens, policy);
16900
+ if (tokenSplit.secret !== void 0) {
16901
+ secrets[LEGACY_TOKENS_FIELD] = tokenSplit.secret;
16902
+ }
16903
+ if (tokenSplit.plaintext) residue.tokens = tokenSplit.plaintext;
16904
+ }
16905
+ if (state.clientInformation) {
16906
+ residue.clientInformation = splitClientInformation(
16907
+ state.clientInformation,
16908
+ LEGACY_CLIENT_INFO_FIELDS,
16909
+ secrets
16910
+ );
16911
+ }
16912
+ if (state.preregisteredClientInformation) {
16913
+ residue.preregisteredClientInformation = splitClientInformation(
16914
+ state.preregisteredClientInformation,
16915
+ PREREG_CLIENT_INFO_FIELDS,
16916
+ secrets
16917
+ );
16918
+ }
16919
+ return { residue, secrets };
16920
+ }
16921
+ function parseStoredTokens(raw) {
16922
+ try {
16923
+ const parsed = JSON.parse(raw);
16924
+ if (StorableTokensSchema.safeParse(parsed).success && hasSecretBearingTokenField(parsed)) {
16925
+ return parsed;
16926
+ }
16927
+ } catch {
16928
+ }
16929
+ return void 0;
16930
+ }
16931
+ function parseStoredIdpSession(raw) {
16932
+ try {
16933
+ const parsed = JSON.parse(raw);
16934
+ if (typeof parsed === "object" && parsed !== null) {
16935
+ const { idToken, refreshToken } = parsed;
16936
+ const usable = {
16937
+ ...typeof idToken === "string" && { idToken },
16938
+ ...typeof refreshToken === "string" && { refreshToken }
16939
+ };
16940
+ if (Object.keys(usable).length > 0) return usable;
16941
+ }
16942
+ } catch {
16943
+ }
16944
+ return void 0;
16945
+ }
16946
+ function isUsableStoredSecret(field, raw) {
16947
+ if (field === LEGACY_TOKENS_FIELD || field.startsWith("tokens:")) {
16948
+ return parseStoredTokens(raw) !== void 0;
16949
+ }
16950
+ if (field === IDP_SESSION_FIELD) {
16951
+ return parseStoredIdpSession(raw) !== void 0;
16952
+ }
16953
+ return true;
16954
+ }
16955
+ function joinServerOAuthState(residue, secrets) {
16956
+ const joined = { ...residue };
16957
+ if (residue.byIssuer) {
16958
+ const byIssuer = {};
16959
+ for (const [issuer, slot] of Object.entries(residue.byIssuer)) {
16960
+ const joinedSlot = { ...slot };
16961
+ const tokensRaw = secrets[issuerTokensField(issuer)];
16962
+ if (tokensRaw !== void 0) {
16963
+ const tokens = parseStoredTokens(tokensRaw);
16964
+ if (tokens) joinedSlot.tokens = tokens;
16965
+ }
16966
+ if (joinedSlot.clientInformation) {
16967
+ joinedSlot.clientInformation = joinClientInformation(
16968
+ joinedSlot.clientInformation,
16969
+ issuerClientInfoFields(issuer),
16970
+ secrets
16971
+ );
16972
+ }
16973
+ setOwnEntry(byIssuer, issuer, joinedSlot);
16974
+ }
16975
+ joined.byIssuer = byIssuer;
16976
+ }
16977
+ const legacyTokensRaw = secrets[LEGACY_TOKENS_FIELD];
16978
+ if (legacyTokensRaw !== void 0) {
16979
+ const tokens = parseStoredTokens(legacyTokensRaw);
16980
+ if (tokens) joined.tokens = tokens;
16981
+ }
16982
+ if (joined.clientInformation) {
16983
+ joined.clientInformation = joinClientInformation(
16984
+ joined.clientInformation,
16985
+ LEGACY_CLIENT_INFO_FIELDS,
16986
+ secrets
16987
+ );
16988
+ }
16989
+ if (joined.preregisteredClientInformation) {
16990
+ joined.preregisteredClientInformation = joinClientInformation(
16991
+ joined.preregisteredClientInformation,
16992
+ PREREG_CLIENT_INFO_FIELDS,
16993
+ secrets
16994
+ );
16995
+ }
16996
+ return joined;
16997
+ }
16998
+ function splitIdpSession(session, policy) {
16999
+ const { idToken, refreshToken, ...residue } = session;
17000
+ const secrets = {};
17001
+ if (policy !== "none" && (idToken !== void 0 || refreshToken !== void 0)) {
17002
+ const kept = {
17003
+ ...typeof idToken === "string" && { idToken },
17004
+ ...policy === "all" && typeof refreshToken === "string" && { refreshToken }
17005
+ };
17006
+ if (Object.keys(kept).length > 0) {
17007
+ secrets[IDP_SESSION_FIELD] = JSON.stringify(kept);
17008
+ }
17009
+ }
17010
+ return { residue, secrets };
17011
+ }
17012
+ function joinIdpSession(residue, secrets) {
17013
+ const raw = secrets[IDP_SESSION_FIELD];
17014
+ if (raw === void 0) return { ...residue };
17015
+ const stored = parseStoredIdpSession(raw);
17016
+ return stored ? { ...residue, ...stored } : { ...residue };
17017
+ }
17018
+ function serverSecretFields(state) {
17019
+ const fields = /* @__PURE__ */ new Set([
17020
+ LEGACY_TOKENS_FIELD,
17021
+ LEGACY_CLIENT_SECRET_FIELD,
17022
+ LEGACY_REGISTRATION_TOKEN_FIELD,
17023
+ PREREG_CLIENT_SECRET_FIELD,
17024
+ PREREG_REGISTRATION_TOKEN_FIELD
17025
+ ]);
17026
+ for (const issuer of Object.keys(state?.byIssuer ?? {})) {
17027
+ fields.add(issuerTokensField(issuer));
17028
+ fields.add(issuerClientSecretField(issuer));
17029
+ fields.add(issuerRegistrationTokenField(issuer));
17030
+ }
17031
+ return [...fields];
17032
+ }
17033
+ function clientInfoHasPlaintext(info) {
17034
+ return info !== void 0 && (info.client_secret !== void 0 || info.registration_access_token !== void 0);
17035
+ }
17036
+ function snapshotHasPlaintextSecrets(snapshot) {
17037
+ for (const state of Object.values(snapshot.servers)) {
17038
+ if (state.tokens) return true;
17039
+ if (clientInfoHasPlaintext(state.clientInformation)) return true;
17040
+ if (clientInfoHasPlaintext(state.preregisteredClientInformation)) {
17041
+ return true;
17042
+ }
17043
+ for (const slot of Object.values(state.byIssuer ?? {})) {
17044
+ if (slot.tokens) return true;
17045
+ if (clientInfoHasPlaintext(slot.clientInformation)) return true;
17046
+ }
17047
+ }
17048
+ for (const session of Object.values(snapshot.idpSessions)) {
17049
+ if (session.idToken !== void 0 || session.refreshToken !== void 0) {
17050
+ return true;
17051
+ }
17052
+ }
17053
+ return false;
17054
+ }
17055
+
17056
+ // ../../core/auth/node/oauth-persist-file.ts
17057
+ var warnedStoreFailures = /* @__PURE__ */ new Set();
17058
+ function warnStoreWriteFailure(error) {
17059
+ const reason = error instanceof Error ? error.message : String(error);
17060
+ if (warnedStoreFailures.has(reason)) return;
17061
+ warnedStoreFailures.add(reason);
17062
+ console.warn(
17063
+ `[mcp-inspector] Could not write OAuth tokens to the secret store (${reason}). Tokens will be kept in memory for this session only and will NOT be persisted; expect to re-authorize after a restart.`
17064
+ );
17065
+ }
17066
+ function warnRestoreFailure(error) {
17067
+ const reason = error instanceof Error ? error.message : String(error);
17068
+ const key = `restore:${reason}`;
17069
+ if (warnedStoreFailures.has(key)) return;
17070
+ warnedStoreFailures.add(key);
17071
+ console.warn(
17072
+ `[mcp-inspector] Could not restore secret-store entries after a failed OAuth state write (${reason}). The secret store may be inconsistent with oauth.json; if a server's stored credentials stop working, re-authorize it.`
17073
+ );
17074
+ }
17075
+ function warnUnconfirmedFile(error) {
17076
+ const reason = error instanceof Error ? error.message : String(error);
17077
+ const key = `unconfirmed:${reason}`;
17078
+ if (warnedStoreFailures.has(key)) return;
17079
+ warnedStoreFailures.add(key);
17080
+ console.warn(
17081
+ `[mcp-inspector] Could not re-read oauth.json after a failed OAuth state save (${reason}). The file may still contain the interrupted save while the secret store was restored to the previous values; if a server's stored credentials stop working, re-authorize it.`
17082
+ );
17083
+ }
17084
+ function warnMigrationFailure(error) {
17085
+ const reason = error instanceof Error ? error.message : String(error);
17086
+ const key = `migration:${reason}`;
17087
+ if (warnedStoreFailures.has(key)) return;
17088
+ warnedStoreFailures.add(key);
17089
+ console.warn(
17090
+ `[mcp-inspector] Could not migrate plaintext OAuth secrets into the secret store (${reason}). The plaintext copy in oauth.json was kept and keeps working; migration will be retried on the next read.`
17091
+ );
17092
+ }
17093
+ function rethrowLockError(filePath, error, action = "save") {
17094
+ if (error instanceof SecretFileLockHeldError) {
17095
+ throw new SecretFileLockHeldError(
17096
+ `Could not ${action} OAuth state: the state file at ${filePath} is locked by another Inspector process and did not become available.`,
17097
+ { cause: error }
17098
+ );
17099
+ }
17100
+ throw error;
17101
+ }
17102
+ async function withOAuthStateLock(filePath, action, body) {
17103
+ let entered = false;
17104
+ try {
17105
+ return await withSecretFileLock(filePath, async () => {
17106
+ entered = true;
17107
+ return body();
17108
+ });
17109
+ } catch (error) {
17110
+ if (!entered) rethrowLockError(filePath, error, action);
17111
+ throw error;
17112
+ }
17113
+ }
17114
+ var OAuthStateFileUnrecognizedError = class extends Error {
17115
+ constructor(filePath, action) {
17116
+ super(
17117
+ `Refusing to ${action} OAuth state: ${filePath} exists but is not a recognized OAuth state file (it may be corrupt, truncated, or written by something else). Its entries are the only index of credentials in the OS keychain / secret store, so overwriting it would strand them. Restore the file from a backup or fix its JSON; deleting it starts fresh but abandons any credentials it indexed.`
17118
+ );
17119
+ this.name = "OAuthStateFileUnrecognizedError";
17120
+ }
17121
+ };
17122
+ async function readDiskForMutation(filePath, action) {
17123
+ const raw = await readStoreFile(filePath);
17124
+ const parsed = parseOAuthPersistBlob(raw);
17125
+ if (raw !== null && parsed === null) {
17126
+ throw new OAuthStateFileUnrecognizedError(filePath, action);
17127
+ }
17128
+ return parsed;
17129
+ }
17130
+ async function persistEntrySecrets(store, serverId, candidates, secrets, prior, allowDegrade) {
17131
+ const priorValue = new Map(prior.map(({ field, value }) => [field, value]));
17132
+ const changed = {};
17133
+ for (const [field, value] of Object.entries(secrets)) {
17134
+ if (priorValue.get(field) !== value) changed[field] = value;
17135
+ }
17136
+ try {
17137
+ if (Object.keys(changed).length > 0) {
17138
+ await secretStoreSetMany(store, serverId, changed);
17139
+ }
17140
+ } catch (error) {
17141
+ if (!allowDegrade) throw error;
17142
+ warnStoreWriteFailure(error);
17143
+ const touched = prior.filter(({ field }) => changed[field] !== void 0);
17144
+ let restoreFailure;
17145
+ await restoreSecretFields(store, touched, (err) => {
17146
+ restoreFailure = err;
17147
+ });
17148
+ if (restoreFailure !== void 0) throw restoreFailure;
17149
+ return false;
17150
+ }
17151
+ await settleStoreMutations(
17152
+ candidates.filter(
17153
+ (field) => secrets[field] === void 0 && priorValue.get(field) !== null
17154
+ ).map((field) => store.delete(serverId, field))
17155
+ );
17156
+ return true;
17157
+ }
17158
+ function revertEntryToDisk(merged, disk, key) {
17159
+ const diskEntry = getOwnEntry(disk, key);
17160
+ if (diskEntry === void 0) {
17161
+ if (Object.hasOwn(merged, key)) delete merged[key];
17162
+ } else {
17163
+ setOwnEntry(merged, key, diskEntry);
17164
+ }
17165
+ }
17166
+ function preserveNonDurableSecrets(diskSecrets, secrets) {
17167
+ const keep = {};
17168
+ for (const [field, value] of Object.entries(secrets)) {
17169
+ if (diskSecrets[field] === value) keep[field] = value;
17170
+ }
17171
+ return keep;
17172
+ }
17173
+ async function writeOAuthSections(filePath, snapshot, sections, secretStore = defaultSecretStore()) {
17174
+ const policy = getPersistTokensPolicy();
17175
+ const durable = await secretStoreIsDurable(secretStore);
17176
+ await withOAuthStateLock(filePath, "save", async () => {
17177
+ const restoreBaseline = /* @__PURE__ */ new Map();
17178
+ const ourWrites = /* @__PURE__ */ new Map();
17179
+ const priorKey = (p) => `${p.serverId}\0${p.field}`;
17180
+ const foldPriors = (priors) => {
17181
+ for (const prior of priors) {
17182
+ const key = priorKey(prior);
17183
+ if (restoreBaseline.has(key) && ourWrites.get(key) !== void 0 && prior.value === ourWrites.get(key)) {
17184
+ continue;
17185
+ }
17186
+ restoreBaseline.set(key, prior);
17187
+ }
17188
+ };
17189
+ const restoreToBaseline = () => restoreSecretFields(
17190
+ secretStore,
17191
+ [...restoreBaseline.values()],
17192
+ warnRestoreFailure
17193
+ );
17194
+ let unconfirmed = null;
17195
+ const reconcileFailure = async () => {
17196
+ if (unconfirmed !== null) {
17197
+ const committed = unconfirmed;
17198
+ let observed = null;
17199
+ let readable = true;
17200
+ try {
17201
+ observed = await readStoreFile(filePath);
17202
+ } catch (error) {
17203
+ readable = false;
17204
+ warnUnconfirmedFile(error);
17205
+ }
17206
+ if (readable && observed === committed.written) {
17207
+ const target = new Map(
17208
+ [...restoreBaseline].map(([key, { serverId, field, value }]) => [
17209
+ key,
17210
+ { serverId, field, value }
17211
+ ])
17212
+ );
17213
+ for (const [key, write] of committed.writes) target.set(key, write);
17214
+ try {
17215
+ await settleStoreMutations(
17216
+ [...target.values()].map(
17217
+ ({ serverId, field, value }) => value === null ? secretStore.delete(serverId, field) : secretStore.set(serverId, field, value)
17218
+ )
17219
+ );
17220
+ return true;
17221
+ } catch (error) {
17222
+ warnRestoreFailure(error);
17223
+ return false;
17224
+ }
17225
+ }
17226
+ }
17227
+ await restoreToBaseline();
17228
+ return false;
17229
+ };
17230
+ for (let attempt = 0; attempt < MAX_WRITE_ATTEMPTS; attempt++) {
17231
+ const priorSecrets = [];
17232
+ const attemptWrites = /* @__PURE__ */ new Map();
17233
+ let written;
17234
+ try {
17235
+ const disk = await readDiskForMutation(filePath, "save");
17236
+ const effective = sections ? {
17237
+ servers: sections.servers && [...new Set(sections.servers)],
17238
+ idpSessions: sections.idpSessions && [
17239
+ ...new Set(sections.idpSessions)
17240
+ ]
17241
+ } : {
17242
+ servers: [
17243
+ .../* @__PURE__ */ new Set([
17244
+ ...Object.keys(disk?.servers ?? {}),
17245
+ ...Object.keys(snapshot.servers)
17246
+ ])
17247
+ ],
17248
+ idpSessions: [
17249
+ .../* @__PURE__ */ new Set([
17250
+ ...Object.keys(disk?.idpSessions ?? {}),
17251
+ ...Object.keys(snapshot.idpSessions)
17252
+ ])
17253
+ ]
17254
+ };
17255
+ const merged = mergeOAuthSections(disk, snapshot, effective);
17256
+ for (const url of effective.servers ?? []) {
17257
+ const serverId = oauthSecretServerId(url);
17258
+ const next = getOwnEntry(snapshot.servers, url);
17259
+ const candidates = [
17260
+ .../* @__PURE__ */ new Set([
17261
+ ...serverSecretFields(getOwnEntry(disk?.servers, url)),
17262
+ ...serverSecretFields(next)
17263
+ ])
17264
+ ];
17265
+ const entryPrior = await snapshotSecretFields(
17266
+ secretStore,
17267
+ serverId,
17268
+ candidates
17269
+ );
17270
+ priorSecrets.push(...entryPrior);
17271
+ if (next === void 0) {
17272
+ for (const field of candidates) {
17273
+ ourWrites.set(priorKey({ serverId, field }), null);
17274
+ }
17275
+ await secretStore.deleteAllForServer(serverId);
17276
+ for (const field of candidates) {
17277
+ attemptWrites.set(priorKey({ serverId, field }), {
17278
+ serverId,
17279
+ field,
17280
+ value: null
17281
+ });
17282
+ }
17283
+ continue;
17284
+ }
17285
+ const { residue, secrets } = splitServerOAuthState(next, policy);
17286
+ for (const field of candidates) {
17287
+ ourWrites.set(
17288
+ priorKey({ serverId, field }),
17289
+ secrets[field] ?? null
17290
+ );
17291
+ }
17292
+ setOwnEntry(merged.servers, url, residue);
17293
+ if (!durable) {
17294
+ const diskEntry = getOwnEntry(disk?.servers, url);
17295
+ const keep = preserveNonDurableSecrets(
17296
+ diskEntry ? splitServerOAuthState(diskEntry, policy).secrets : {},
17297
+ secrets
17298
+ );
17299
+ if (Object.keys(keep).length > 0) {
17300
+ setOwnEntry(
17301
+ merged.servers,
17302
+ url,
17303
+ joinServerOAuthState(residue, keep)
17304
+ );
17305
+ }
17306
+ }
17307
+ const persisted = await persistEntrySecrets(
17308
+ secretStore,
17309
+ serverId,
17310
+ candidates,
17311
+ secrets,
17312
+ entryPrior,
17313
+ // Degrading is only sound when the disk entry is the pre-call
17314
+ // state this attempt's priors pair with; on a retry it may be an
17315
+ // earlier attempt's committed residue, so escalate into the
17316
+ // reconciling exit instead.
17317
+ attempt === 0
17318
+ );
17319
+ if (!persisted) {
17320
+ revertEntryToDisk(merged.servers, disk?.servers, url);
17321
+ continue;
17322
+ }
17323
+ for (const field of candidates) {
17324
+ attemptWrites.set(priorKey({ serverId, field }), {
17325
+ serverId,
17326
+ field,
17327
+ value: secrets[field] ?? null
17328
+ });
17329
+ }
17330
+ }
17331
+ for (const issuer of effective.idpSessions ?? []) {
17332
+ const serverId = oauthIdpSecretServerId(issuer);
17333
+ const next = getOwnEntry(snapshot.idpSessions, issuer);
17334
+ const entryPrior = await snapshotSecretFields(secretStore, serverId, [
17335
+ IDP_SESSION_FIELD
17336
+ ]);
17337
+ priorSecrets.push(...entryPrior);
17338
+ if (next === void 0) {
17339
+ ourWrites.set(
17340
+ priorKey({ serverId, field: IDP_SESSION_FIELD }),
17341
+ null
17342
+ );
17343
+ await secretStore.deleteAllForServer(serverId);
17344
+ attemptWrites.set(
17345
+ priorKey({ serverId, field: IDP_SESSION_FIELD }),
17346
+ {
17347
+ serverId,
17348
+ field: IDP_SESSION_FIELD,
17349
+ value: null
17350
+ }
17351
+ );
17352
+ continue;
17353
+ }
17354
+ const { residue, secrets } = splitIdpSession(next, policy);
17355
+ ourWrites.set(
17356
+ priorKey({ serverId, field: IDP_SESSION_FIELD }),
17357
+ secrets[IDP_SESSION_FIELD] ?? null
17358
+ );
17359
+ setOwnEntry(merged.idpSessions, issuer, residue);
17360
+ if (!durable) {
17361
+ const diskSession = getOwnEntry(disk?.idpSessions, issuer);
17362
+ const keep = preserveNonDurableSecrets(
17363
+ diskSession ? splitIdpSession(diskSession, policy).secrets : {},
17364
+ secrets
17365
+ );
17366
+ if (Object.keys(keep).length > 0) {
17367
+ setOwnEntry(
17368
+ merged.idpSessions,
17369
+ issuer,
17370
+ joinIdpSession(residue, keep)
17371
+ );
17372
+ }
17373
+ }
17374
+ const persisted = await persistEntrySecrets(
17375
+ secretStore,
17376
+ serverId,
17377
+ [IDP_SESSION_FIELD],
17378
+ secrets,
17379
+ entryPrior,
17380
+ // Same as the server loop: degrade on the first attempt only.
17381
+ attempt === 0
17382
+ );
17383
+ if (!persisted) {
17384
+ revertEntryToDisk(merged.idpSessions, disk?.idpSessions, issuer);
17385
+ continue;
17386
+ }
17387
+ attemptWrites.set(priorKey({ serverId, field: IDP_SESSION_FIELD }), {
17388
+ serverId,
17389
+ field: IDP_SESSION_FIELD,
17390
+ value: secrets[IDP_SESSION_FIELD] ?? null
17391
+ });
17392
+ }
17393
+ written = serializeOAuthPersistBlob(merged);
17394
+ await writeStoreFile(filePath, written);
17395
+ unconfirmed = { written, writes: attemptWrites };
17396
+ } catch (error) {
17397
+ foldPriors(priorSecrets);
17398
+ if (await reconcileFailure()) return;
17399
+ throw error;
16115
17400
  }
16116
- };
16117
- }
16118
- snapshot() {
16119
- return {
16120
- servers: { ...this.servers },
16121
- idpSessions: { ...this.idpSessions }
16122
- };
17401
+ foldPriors(priorSecrets);
17402
+ let observed;
17403
+ try {
17404
+ observed = await readStoreFile(filePath);
17405
+ } catch {
17406
+ continue;
17407
+ }
17408
+ if (observed === written) return;
17409
+ unconfirmed = null;
17410
+ }
17411
+ if (await reconcileFailure()) return;
17412
+ throw new SecretStoreUnavailableError(
17413
+ `Could not save OAuth state: another process kept overwriting ${filePath} (gave up after ${MAX_WRITE_ATTEMPTS} attempts). Re-run the action to retry.`
17414
+ );
17415
+ });
17416
+ }
17417
+ function secretRequestsFor(snapshot) {
17418
+ const requests = [];
17419
+ for (const [url, state] of Object.entries(snapshot.servers)) {
17420
+ requests.push({
17421
+ serverId: oauthSecretServerId(url),
17422
+ fields: serverSecretFields(state)
17423
+ });
16123
17424
  }
16124
- replace(snapshot) {
16125
- this.servers = { ...snapshot.servers ?? {} };
16126
- this.idpSessions = { ...snapshot.idpSessions ?? {} };
17425
+ for (const issuer of Object.keys(snapshot.idpSessions)) {
17426
+ requests.push({
17427
+ serverId: oauthIdpSecretServerId(issuer),
17428
+ fields: [IDP_SESSION_FIELD]
17429
+ });
16127
17430
  }
16128
- };
16129
-
16130
- // ../../core/auth/oauth-persist.ts
16131
- function isRecord2(value) {
16132
- return typeof value === "object" && value !== null && !Array.isArray(value);
17431
+ return requests;
16133
17432
  }
16134
- function snapshotFromPayload(payload) {
17433
+ async function joinSnapshot(snapshot, secretStore) {
17434
+ const requests = secretRequestsFor(snapshot);
17435
+ const values = requests.length > 0 ? await secretStoreGetManyStrict(secretStore, requests) : {};
16135
17436
  return {
16136
- servers: payload.servers ?? {},
16137
- idpSessions: payload.idpSessions ?? {}
17437
+ servers: Object.fromEntries(
17438
+ Object.entries(snapshot.servers).map(([url, state]) => [
17439
+ url,
17440
+ joinServerOAuthState(state, values[oauthSecretServerId(url)] ?? {})
17441
+ ])
17442
+ ),
17443
+ idpSessions: Object.fromEntries(
17444
+ Object.entries(snapshot.idpSessions).map(([issuer, session]) => [
17445
+ issuer,
17446
+ joinIdpSession(session, values[oauthIdpSecretServerId(issuer)] ?? {})
17447
+ ])
17448
+ )
16138
17449
  };
16139
17450
  }
16140
- function parseOAuthPersistBlob(raw) {
16141
- if (raw === null || raw === void 0) {
16142
- return null;
16143
- }
16144
- const parsed = typeof raw === "string" ? raw ? parseStore(raw) : null : raw;
16145
- if (!isRecord2(parsed)) {
16146
- return null;
16147
- }
16148
- if (isRecord2(parsed.state) && "version" in parsed) {
16149
- return snapshotFromPayload(parsed.state);
16150
- }
16151
- if ("servers" in parsed || "idpSessions" in parsed) {
16152
- return snapshotFromPayload(parsed);
16153
- }
16154
- return null;
17451
+ async function migratePlaintextSecrets(filePath, secretStore) {
17452
+ const raw = await readStoreFile(filePath);
17453
+ const fresh = parseOAuthPersistBlob(raw);
17454
+ if (!fresh || !snapshotHasPlaintextSecrets(fresh)) return;
17455
+ const migrateEntrySecrets = async (serverId, secrets) => {
17456
+ const absent = {};
17457
+ for (const [field, value] of Object.entries(secrets)) {
17458
+ const existing = await secretStoreGetStrict(secretStore, serverId, field);
17459
+ if (existing === null || !isUsableStoredSecret(field, existing)) {
17460
+ absent[field] = value;
17461
+ }
17462
+ }
17463
+ if (Object.keys(absent).length > 0) {
17464
+ await secretStoreSetMany(secretStore, serverId, absent);
17465
+ }
17466
+ };
17467
+ const residue = { servers: {}, idpSessions: {} };
17468
+ for (const [url, state] of Object.entries(fresh.servers)) {
17469
+ const split = splitServerOAuthState(state, "all");
17470
+ setOwnEntry(residue.servers, url, split.residue);
17471
+ await migrateEntrySecrets(oauthSecretServerId(url), split.secrets);
17472
+ }
17473
+ for (const [issuer, session] of Object.entries(fresh.idpSessions)) {
17474
+ const split = splitIdpSession(session, "all");
17475
+ setOwnEntry(residue.idpSessions, issuer, split.residue);
17476
+ await migrateEntrySecrets(oauthIdpSecretServerId(issuer), split.secrets);
17477
+ }
17478
+ const stripped = serializeOAuthPersistBlob(residue);
17479
+ if (stripped !== raw) {
17480
+ await writeStoreFile(filePath, stripped);
17481
+ }
17482
+ }
17483
+ async function readOAuthStore(filePath, secretStore = defaultSecretStore()) {
17484
+ return withOAuthStateLock(filePath, "read", async () => {
17485
+ let snapshot = parseOAuthPersistBlob(await readStoreFile(filePath));
17486
+ if (snapshot === null) return null;
17487
+ if (snapshotHasPlaintextSecrets(snapshot) && await secretStoreIsDurable(secretStore)) {
17488
+ try {
17489
+ await migratePlaintextSecrets(filePath, secretStore);
17490
+ snapshot = parseOAuthPersistBlob(await readStoreFile(filePath)) ?? snapshot;
17491
+ } catch (error) {
17492
+ warnMigrationFailure(error);
17493
+ }
17494
+ }
17495
+ return joinSnapshot(snapshot, secretStore);
17496
+ });
16155
17497
  }
16156
- function serializeOAuthPersistBlob(snapshot) {
16157
- return serializeStore(snapshot);
17498
+ async function removeOAuthStore(filePath, secretStore = defaultSecretStore()) {
17499
+ await withOAuthStateLock(filePath, "remove", async () => {
17500
+ const snapshot = await readDiskForMutation(filePath, "remove");
17501
+ if (snapshot) {
17502
+ const targets = [
17503
+ ...Object.entries(snapshot.servers).map(([url, state]) => ({
17504
+ id: oauthSecretServerId(url),
17505
+ fields: serverSecretFields(state)
17506
+ })),
17507
+ ...Object.keys(snapshot.idpSessions).map((issuer) => ({
17508
+ id: oauthIdpSecretServerId(issuer),
17509
+ fields: [IDP_SESSION_FIELD]
17510
+ }))
17511
+ ];
17512
+ const priorSecrets = [];
17513
+ try {
17514
+ for (const { id, fields } of targets) {
17515
+ priorSecrets.push(
17516
+ ...await snapshotSecretFields(secretStore, id, fields)
17517
+ );
17518
+ await secretStore.deleteAllForServer(id);
17519
+ }
17520
+ await deleteStoreFile(filePath);
17521
+ } catch (error) {
17522
+ await restoreSecretFields(
17523
+ secretStore,
17524
+ priorSecrets,
17525
+ warnRestoreFailure
17526
+ );
17527
+ throw error;
17528
+ }
17529
+ } else {
17530
+ await deleteStoreFile(filePath);
17531
+ }
17532
+ });
16158
17533
  }
16159
-
16160
- // ../../core/auth/node/oauth-persist-file.ts
16161
17534
  function createFileOAuthPersistBackend(options) {
17535
+ const secretStore = options.secretStore ?? defaultSecretStore();
16162
17536
  return {
16163
17537
  async read() {
16164
- const raw = await readStoreFile(options.filePath);
16165
- return parseOAuthPersistBlob(raw);
17538
+ return readOAuthStore(options.filePath, secretStore);
16166
17539
  },
16167
- async write(snapshot) {
16168
- await writeStoreFile(
17540
+ async write(snapshot, sections) {
17541
+ await writeOAuthSections(
16169
17542
  options.filePath,
16170
- serializeOAuthPersistBlob(snapshot)
17543
+ snapshot,
17544
+ sections,
17545
+ secretStore
16171
17546
  );
16172
17547
  },
16173
17548
  async remove() {
16174
- await deleteStoreFile(options.filePath);
17549
+ await removeOAuthStore(options.filePath, secretStore);
16175
17550
  }
16176
17551
  };
16177
17552
  }
@@ -16188,25 +17563,33 @@ function getStateFilePath(customPath) {
16188
17563
  }
16189
17564
  return DEFAULT_STATE_PATH;
16190
17565
  }
16191
- var memoryCache = /* @__PURE__ */ new Map();
16192
- function getSharedMemory(stateFilePath) {
17566
+ var sharedStateCache = /* @__PURE__ */ new Map();
17567
+ function getSharedState(stateFilePath) {
16193
17568
  const key = getStateFilePath(stateFilePath);
16194
- let memory = memoryCache.get(key);
16195
- if (!memory) {
16196
- memory = new OAuthMemoryStore();
16197
- memoryCache.set(key, memory);
17569
+ let shared = sharedStateCache.get(key);
17570
+ if (!shared) {
17571
+ shared = {
17572
+ memory: new OAuthMemoryStore(),
17573
+ coordination: new OAuthStorageCoordination()
17574
+ };
17575
+ sharedStateCache.set(key, shared);
16198
17576
  }
16199
- return memory;
17577
+ return shared;
16200
17578
  }
16201
17579
  var NodeOAuthStorage = class extends OAuthStorageBase {
16202
17580
  /**
16203
17581
  * @param storagePath - Optional path to state file. Default: ~/.mcp-inspector/storage/oauth.json
17582
+ * @param secretStore - Optional secret store for tokens/client secrets.
17583
+ * Default: the process-wide selected store. Tests inject an in-memory
17584
+ * double here so they never touch the OS keychain.
16204
17585
  */
16205
- constructor(storagePath) {
17586
+ constructor(storagePath, secretStore) {
16206
17587
  const filePath = getStateFilePath(storagePath);
17588
+ const shared = getSharedState(storagePath);
16207
17589
  super(
16208
- getSharedMemory(storagePath),
16209
- createFileOAuthPersistBackend({ filePath })
17590
+ shared.memory,
17591
+ createFileOAuthPersistBackend({ filePath, secretStore }),
17592
+ shared.coordination
16210
17593
  );
16211
17594
  }
16212
17595
  };
@@ -18141,7 +19524,11 @@ async function verifySkills(client, entries, metadata) {
18141
19524
  files,
18142
19525
  ...incomplete ? { incomplete } : {},
18143
19526
  ok: !hasError && !fileFailed,
18144
- outcome: hasError || fileFailed ? "failed" : incomplete !== void 0 ? "incomplete" : "verified"
19527
+ // Precedence runs from the loudest verdict down: a broken MUST outranks
19528
+ // an unfinished walk, and an unfinished walk outranks a skill that had
19529
+ // nothing to hash — a `"dynamic"` skill past the run's catalog budget
19530
+ // was not read at all, which `incomplete` already says more precisely.
19531
+ outcome: hasError || fileFailed ? "failed" : incomplete !== void 0 ? "incomplete" : entry.resources === DYNAMIC_RESOURCES ? "unverifiable" : "verified"
18145
19532
  });
18146
19533
  }
18147
19534
  return reports;
@@ -18173,6 +19560,7 @@ var FILE_COLOR = {
18173
19560
  };
18174
19561
  var VERIFY_STATUS = {
18175
19562
  verified: "[Verified \u2014 Enter to re-verify]",
19563
+ unverifiable: "[UNVERIFIABLE \u2014 Enter to re-verify]",
18176
19564
  incomplete: "[Verification INCOMPLETE \u2014 Enter to re-verify]",
18177
19565
  failed: "[Verification FAILED \u2014 Enter to re-verify]"
18178
19566
  };
@@ -18485,7 +19873,7 @@ var BOOLEAN_VALUED_KEYWORDS = /* @__PURE__ */ new Set([
18485
19873
  "additionalItems",
18486
19874
  "unevaluatedItems"
18487
19875
  ]);
18488
- var SUBSCHEMA_KEYWORDS = [
19876
+ var SUBSCHEMA_KEYWORDS2 = [
18489
19877
  "items",
18490
19878
  "contains",
18491
19879
  "not",
@@ -18502,13 +19890,13 @@ var SUBSCHEMA_KEYWORDS = [
18502
19890
  // real finding.
18503
19891
  "contentSchema"
18504
19892
  ];
18505
- var SUBSCHEMA_ARRAY_KEYWORDS = [
19893
+ var SUBSCHEMA_ARRAY_KEYWORDS2 = [
18506
19894
  "allOf",
18507
19895
  "anyOf",
18508
19896
  "oneOf",
18509
19897
  "prefixItems"
18510
19898
  ];
18511
- var SUBSCHEMA_MAP_KEYWORDS = [
19899
+ var SUBSCHEMA_MAP_KEYWORDS2 = [
18512
19900
  "properties",
18513
19901
  "patternProperties",
18514
19902
  "dependentSchemas",
@@ -18590,8 +19978,8 @@ function isPortableTypeUnion(type) {
18590
19978
  }
18591
19979
  return new Set(type).size === type.length;
18592
19980
  }
18593
- var MAX_DEPTH = 64;
18594
- function isRecord3(value) {
19981
+ var MAX_DEPTH2 = 64;
19982
+ function isRecord5(value) {
18595
19983
  return typeof value === "object" && value !== null && !Array.isArray(value);
18596
19984
  }
18597
19985
  function childPath(parent, key) {
@@ -18607,7 +19995,7 @@ function describeSchemaPath(schema, path6) {
18607
19995
  return path6 === "" ? schema : `${schema}.${path6}`;
18608
19996
  }
18609
19997
  function declaresAnyId(node, depth = 0) {
18610
- if (depth > MAX_DEPTH || !isRecord3(node)) return false;
19998
+ if (depth > MAX_DEPTH2 || !isRecord5(node)) return false;
18611
19999
  if (typeof node.$id === "string" && node.$id !== "") return true;
18612
20000
  let found = false;
18613
20001
  forEachSubschema(node, "", (child) => {
@@ -18626,21 +20014,21 @@ function add(ctx, rule, severity, path6, issue, suggestion) {
18626
20014
  });
18627
20015
  }
18628
20016
  function forEachSubschema(node, path6, visit) {
18629
- for (const key of SUBSCHEMA_MAP_KEYWORDS) {
20017
+ for (const key of SUBSCHEMA_MAP_KEYWORDS2) {
18630
20018
  const map = node[key];
18631
- if (!isRecord3(map)) continue;
20019
+ if (!isRecord5(map)) continue;
18632
20020
  for (const [name, sub] of Object.entries(map)) {
18633
20021
  visit(sub, childPath(childPath(path6, key), name), key);
18634
20022
  }
18635
20023
  }
18636
- for (const key of SUBSCHEMA_ARRAY_KEYWORDS) {
20024
+ for (const key of SUBSCHEMA_ARRAY_KEYWORDS2) {
18637
20025
  const arr = node[key];
18638
20026
  if (!Array.isArray(arr)) continue;
18639
20027
  arr.forEach((sub, i) => {
18640
20028
  visit(sub, indexPath(childPath(path6, key), i), key);
18641
20029
  });
18642
20030
  }
18643
- for (const key of SUBSCHEMA_KEYWORDS) {
20031
+ for (const key of SUBSCHEMA_KEYWORDS2) {
18644
20032
  if (!(key in node)) continue;
18645
20033
  const value = node[key];
18646
20034
  if (key === "items" && Array.isArray(value)) {
@@ -18659,7 +20047,7 @@ function booleanTrueSuggestion(keyword) {
18659
20047
  return 'Declare what the value actually is \u2014 e.g. `{"type": "object", "additionalProperties": true}` for a free-form object. That is a deliberate change of contract, not an equivalent rewrite: `true` accepts any JSON value at all.';
18660
20048
  }
18661
20049
  function walk(node, path6, keyword, depth, ctx) {
18662
- if (depth > MAX_DEPTH) return;
20050
+ if (depth > MAX_DEPTH2) return;
18663
20051
  if (typeof node === "boolean") {
18664
20052
  if (keyword !== void 0 && BOOLEAN_VALUED_KEYWORDS.has(keyword)) return;
18665
20053
  add(
@@ -18678,12 +20066,13 @@ function walk(node, path6, keyword, depth, ctx) {
18678
20066
  );
18679
20067
  return;
18680
20068
  }
18681
- if (!isRecord3(node)) return;
20069
+ if (!isRecord5(node)) return;
18682
20070
  lintNode(node, path6, keyword, ctx);
18683
20071
  forEachSubschema(node, path6, (child, childPathValue, childKeyword) => {
18684
20072
  walk(child, childPathValue, childKeyword, depth + 1, ctx);
18685
20073
  });
18686
20074
  }
20075
+ var NULL_BRANCH_CAVEAT = " A dialect with no `null` type, such as OpenAPI 3.0, still cannot express the `null` branch directly; there nullability is written `nullable: true`, which is not JSON Schema, so no single spelling is portable to both.";
18687
20076
  function lintNode(node, path6, keyword, ctx) {
18688
20077
  const type = node.type;
18689
20078
  if (Array.isArray(type) && isPortableTypeUnion(type)) {
@@ -18692,10 +20081,10 @@ function lintNode(node, path6, keyword, ctx) {
18692
20081
  "type-union",
18693
20082
  "warning",
18694
20083
  path6,
18695
- `\`type\` is an array (${JSON.stringify(type)}). The array form is legal JSON Schema, but several MCP clients read \`type\` as a single string and either reject the tool or drop the constraint.`,
20084
+ `\`type\` is an array (${JSON.stringify(type)}). This is legal JSON Schema, and some model providers recommend it for nullable fields, but it is less portable: a client that maps tool schemas onto a single-\`type\` dialect (such as the OpenAPI subset used for Gemini function declarations) may reject the tool or drop the constraint.`,
18696
20085
  `Split it into \`anyOf\` branches, each with a single \`type\` \u2014 \`{"anyOf": [${type.map((t) => `{"type": "${t}"}`).join(
18697
20086
  ", "
18698
- )}]}\`. (Making the property optional instead is a different contract: absent is not the same as \`null\`.)`
20087
+ )}]}\`. (Making the property optional instead is a different contract: absent is not the same as \`null\`.)${type.includes("null") ? NULL_BRANCH_CAVEAT : ""}`
18699
20088
  );
18700
20089
  }
18701
20090
  const ref = node.$ref;
@@ -19255,8 +20644,64 @@ function HistoryTab({
19255
20644
 
19256
20645
  // src/components/RequestsTab.tsx
19257
20646
  import React9, { useEffect as useEffect10, useRef as useRef12 } from "react";
19258
- import { Box as Box12, Text as Text11, useInput as useInput9 } from "ink";
20647
+ import { Box as Box13, Text as Text12, useInput as useInput9 } from "ink";
20648
+
20649
+ // src/components/BodyLines.tsx
20650
+ import { Box as Box12, Text as Text11 } from "ink";
20651
+
20652
+ // src/utils/bodyLines.ts
20653
+ var MAX_BODY_LINES = 500;
20654
+ var MAX_BODY_LINE_CHARS = 2e3;
20655
+ function formatBody(body) {
20656
+ try {
20657
+ return JSON.stringify(JSON.parse(body), null, 2);
20658
+ } catch {
20659
+ return body;
20660
+ }
20661
+ }
20662
+ function clipLine(line, maxChars) {
20663
+ if (line.length <= maxChars) return line;
20664
+ return `${line.slice(0, maxChars)}\u2026 (+${line.length - maxChars} chars)`;
20665
+ }
20666
+ function layoutBody(body, maxLines = MAX_BODY_LINES, maxLineChars = MAX_BODY_LINE_CHARS) {
20667
+ const all = formatBody(body).split("\n");
20668
+ return {
20669
+ lines: all.slice(0, maxLines).map((line) => clipLine(line, maxLineChars)),
20670
+ hiddenLines: Math.max(all.length - maxLines, 0),
20671
+ totalLines: all.length
20672
+ };
20673
+ }
20674
+
20675
+ // src/components/BodyLines.tsx
19259
20676
  import { Fragment as Fragment8, jsx as jsx12, jsxs as jsxs11 } from "react/jsx-runtime";
20677
+ function BodyLines({
20678
+ body,
20679
+ keyPrefix
20680
+ }) {
20681
+ const { lines, hiddenLines, totalLines } = layoutBody(body);
20682
+ return /* @__PURE__ */ jsxs11(Fragment8, { children: [
20683
+ lines.map((line, idx) => /* @__PURE__ */ jsx12(
20684
+ Box12,
20685
+ {
20686
+ marginTop: idx === 0 ? 1 : 0,
20687
+ paddingLeft: 2,
20688
+ flexShrink: 0,
20689
+ children: /* @__PURE__ */ jsx12(Text11, { dimColor: true, children: line })
20690
+ },
20691
+ `${keyPrefix}-${idx}`
20692
+ )),
20693
+ hiddenLines > 0 && /* @__PURE__ */ jsx12(Box12, { paddingLeft: 2, flexShrink: 0, children: /* @__PURE__ */ jsxs11(Text11, { dimColor: true, italic: true, children: [
20694
+ "\u2026 ",
20695
+ hiddenLines,
20696
+ " more lines not shown (",
20697
+ totalLines,
20698
+ " total)"
20699
+ ] }) })
20700
+ ] });
20701
+ }
20702
+
20703
+ // src/components/RequestsTab.tsx
20704
+ import { Fragment as Fragment9, jsx as jsx13, jsxs as jsxs12 } from "react/jsx-runtime";
19260
20705
  function RequestsTab({
19261
20706
  requests,
19262
20707
  width,
@@ -19324,9 +20769,9 @@ function RequestsTab({
19324
20769
  if (status >= 400) return "red";
19325
20770
  return "gray";
19326
20771
  };
19327
- return /* @__PURE__ */ jsxs11(Box12, { flexDirection: "row", width, height, children: [
19328
- /* @__PURE__ */ jsxs11(
19329
- Box12,
20772
+ return /* @__PURE__ */ jsxs12(Box13, { flexDirection: "row", width, height, children: [
20773
+ /* @__PURE__ */ jsxs12(
20774
+ Box13,
19330
20775
  {
19331
20776
  width: listWidth,
19332
20777
  height,
@@ -19338,8 +20783,8 @@ function RequestsTab({
19338
20783
  flexDirection: "column",
19339
20784
  paddingX: 1,
19340
20785
  children: [
19341
- /* @__PURE__ */ jsx12(Box12, { paddingY: 1, flexShrink: 0, children: /* @__PURE__ */ jsxs11(
19342
- Text11,
20786
+ /* @__PURE__ */ jsx13(Box13, { paddingY: 1, flexShrink: 0, children: /* @__PURE__ */ jsxs12(
20787
+ Text12,
19343
20788
  {
19344
20789
  bold: true,
19345
20790
  backgroundColor: focusedPane === "requests" ? "yellow" : void 0,
@@ -19350,8 +20795,8 @@ function RequestsTab({
19350
20795
  ]
19351
20796
  }
19352
20797
  ) }),
19353
- requests.length === 0 ? /* @__PURE__ */ jsx12(Box12, { paddingY: 1, children: /* @__PURE__ */ jsx12(Text11, { dimColor: true, children: "No requests" }) }) : /* @__PURE__ */ jsx12(
19354
- Box12,
20798
+ requests.length === 0 ? /* @__PURE__ */ jsx13(Box13, { paddingY: 1, children: /* @__PURE__ */ jsx13(Text12, { dimColor: true, children: "No requests" }) }) : /* @__PURE__ */ jsx13(
20799
+ Box13,
19355
20800
  {
19356
20801
  flexDirection: "column",
19357
20802
  height: visibleCount,
@@ -19364,14 +20809,14 @@ function RequestsTab({
19364
20809
  const statusText = req.responseStatus ? `${req.responseStatus}` : req.error ? "ERROR" : "...";
19365
20810
  const categoryLabel = req.category === "auth" ? "AUTH" : "MCP ";
19366
20811
  const methodPadded = req.method === "GET" ? "GET " : req.method;
19367
- return /* @__PURE__ */ jsx12(Box12, { paddingY: 0, flexShrink: 0, children: /* @__PURE__ */ jsxs11(Text11, { color: isSelected ? "white" : "white", children: [
20812
+ return /* @__PURE__ */ jsx13(Box13, { paddingY: 0, flexShrink: 0, children: /* @__PURE__ */ jsxs12(Text12, { color: isSelected ? "white" : "white", children: [
19368
20813
  isSelected ? "\u25B6 " : " ",
19369
- /* @__PURE__ */ jsx12(Text11, { children: categoryLabel }),
20814
+ /* @__PURE__ */ jsx13(Text12, { children: categoryLabel }),
19370
20815
  " ",
19371
- /* @__PURE__ */ jsx12(Text11, { color: statusColor, children: methodPadded }),
20816
+ /* @__PURE__ */ jsx13(Text12, { color: statusColor, children: methodPadded }),
19372
20817
  " ",
19373
- /* @__PURE__ */ jsx12(Text11, { dimColor: true, children: statusText }),
19374
- req.duration !== void 0 && /* @__PURE__ */ jsxs11(Text11, { dimColor: true, children: [
20818
+ /* @__PURE__ */ jsx13(Text12, { dimColor: true, children: statusText }),
20819
+ req.duration !== void 0 && /* @__PURE__ */ jsxs12(Text12, { dimColor: true, children: [
19375
20820
  " ",
19376
20821
  req.duration,
19377
20822
  "ms"
@@ -19383,8 +20828,8 @@ function RequestsTab({
19383
20828
  ]
19384
20829
  }
19385
20830
  ),
19386
- /* @__PURE__ */ jsx12(
19387
- Box12,
20831
+ /* @__PURE__ */ jsx13(
20832
+ Box13,
19388
20833
  {
19389
20834
  width: detailWidth,
19390
20835
  height,
@@ -19396,9 +20841,9 @@ function RequestsTab({
19396
20841
  borderBottom: false,
19397
20842
  borderLeft: false,
19398
20843
  borderRight: false,
19399
- children: selectedRequest ? /* @__PURE__ */ jsxs11(Fragment8, { children: [
19400
- /* @__PURE__ */ jsx12(Box12, { flexShrink: 0, paddingTop: 1, children: /* @__PURE__ */ jsxs11(
19401
- Text11,
20844
+ children: selectedRequest ? /* @__PURE__ */ jsxs12(Fragment9, { children: [
20845
+ /* @__PURE__ */ jsx13(Box13, { flexShrink: 0, paddingTop: 1, children: /* @__PURE__ */ jsxs12(
20846
+ Text12,
19402
20847
  {
19403
20848
  bold: true,
19404
20849
  backgroundColor: focusedPane === "details" ? "yellow" : void 0,
@@ -19410,17 +20855,17 @@ function RequestsTab({
19410
20855
  ]
19411
20856
  }
19412
20857
  ) }),
19413
- /* @__PURE__ */ jsxs11(ScrollView, { ref: scrollViewRef, height: height - 5, children: [
19414
- /* @__PURE__ */ jsx12(Box12, { marginTop: 1, flexShrink: 0, children: /* @__PURE__ */ jsxs11(Text11, { bold: true, children: [
20858
+ /* @__PURE__ */ jsxs12(ScrollView, { ref: scrollViewRef, height: height - 5, children: [
20859
+ /* @__PURE__ */ jsx13(Box13, { marginTop: 1, flexShrink: 0, children: /* @__PURE__ */ jsxs12(Text12, { bold: true, children: [
19415
20860
  "Category:",
19416
20861
  " ",
19417
- /* @__PURE__ */ jsx12(Text11, { children: selectedRequest.category === "auth" ? "auth" : "transport" })
20862
+ /* @__PURE__ */ jsx13(Text12, { children: selectedRequest.category === "auth" ? "auth" : "transport" })
19418
20863
  ] }) }),
19419
- selectedRequest.responseStatus !== void 0 ? /* @__PURE__ */ jsx12(Box12, { marginTop: 1, flexShrink: 0, children: /* @__PURE__ */ jsxs11(Text11, { bold: true, children: [
20864
+ selectedRequest.responseStatus !== void 0 ? /* @__PURE__ */ jsx13(Box13, { marginTop: 1, flexShrink: 0, children: /* @__PURE__ */ jsxs12(Text12, { bold: true, children: [
19420
20865
  "Status:",
19421
20866
  " ",
19422
- /* @__PURE__ */ jsxs11(
19423
- Text11,
20867
+ /* @__PURE__ */ jsxs12(
20868
+ Text12,
19424
20869
  {
19425
20870
  color: getStatusColor(selectedRequest.responseStatus),
19426
20871
  children: [
@@ -19430,54 +20875,44 @@ function RequestsTab({
19430
20875
  ]
19431
20876
  }
19432
20877
  )
19433
- ] }) }) : selectedRequest.error ? /* @__PURE__ */ jsx12(Box12, { marginTop: 1, flexShrink: 0, children: /* @__PURE__ */ jsxs11(Text11, { bold: true, color: "red", children: [
20878
+ ] }) }) : selectedRequest.error ? /* @__PURE__ */ jsx13(Box13, { marginTop: 1, flexShrink: 0, children: /* @__PURE__ */ jsxs12(Text12, { bold: true, color: "red", children: [
19434
20879
  "Error: ",
19435
20880
  selectedRequest.error
19436
- ] }) }) : /* @__PURE__ */ jsx12(Box12, { marginTop: 1, flexShrink: 0, children: /* @__PURE__ */ jsx12(Text11, { dimColor: true, italic: true, children: "Request in progress..." }) }),
19437
- selectedRequest.duration !== void 0 && /* @__PURE__ */ jsx12(Box12, { marginTop: 1, flexShrink: 0, children: /* @__PURE__ */ jsxs11(Text11, { dimColor: true, children: [
20881
+ ] }) }) : /* @__PURE__ */ jsx13(Box13, { marginTop: 1, flexShrink: 0, children: /* @__PURE__ */ jsx13(Text12, { dimColor: true, italic: true, children: "Request in progress..." }) }),
20882
+ selectedRequest.duration !== void 0 && /* @__PURE__ */ jsx13(Box13, { marginTop: 1, flexShrink: 0, children: /* @__PURE__ */ jsxs12(Text12, { dimColor: true, children: [
19438
20883
  selectedRequest.timestamp.toLocaleTimeString(),
19439
20884
  " (",
19440
20885
  selectedRequest.duration,
19441
20886
  "ms)"
19442
20887
  ] }) }),
19443
- /* @__PURE__ */ jsx12(Box12, { marginTop: 1, flexShrink: 0, children: /* @__PURE__ */ jsx12(Text11, { bold: true, children: "Request Headers:" }) }),
20888
+ /* @__PURE__ */ jsx13(Box13, { marginTop: 1, flexShrink: 0, children: /* @__PURE__ */ jsx13(Text12, { bold: true, children: "Request Headers:" }) }),
19444
20889
  Object.entries(selectedRequest.requestHeaders).map(
19445
- ([key, value]) => /* @__PURE__ */ jsx12(Box12, { marginTop: 0, paddingLeft: 2, flexShrink: 0, children: /* @__PURE__ */ jsxs11(Text11, { dimColor: true, children: [
20890
+ ([key, value]) => /* @__PURE__ */ jsx13(Box13, { marginTop: 0, paddingLeft: 2, flexShrink: 0, children: /* @__PURE__ */ jsxs12(Text12, { dimColor: true, children: [
19446
20891
  key,
19447
20892
  ": ",
19448
20893
  value
19449
20894
  ] }) }, key)
19450
20895
  ),
19451
- selectedRequest.requestBody && /* @__PURE__ */ jsxs11(Fragment8, { children: [
19452
- /* @__PURE__ */ jsx12(Box12, { marginTop: 1, flexShrink: 0, children: /* @__PURE__ */ jsx12(Text11, { bold: true, children: "Request Body:" }) }),
19453
- (() => {
19454
- try {
19455
- const parsed = JSON.parse(selectedRequest.requestBody);
19456
- return JSON.stringify(parsed, null, 2).split("\n").map((line, idx) => /* @__PURE__ */ jsx12(
19457
- Box12,
19458
- {
19459
- marginTop: idx === 0 ? 1 : 0,
19460
- paddingLeft: 2,
19461
- flexShrink: 0,
19462
- children: /* @__PURE__ */ jsx12(Text11, { dimColor: true, children: line })
19463
- },
19464
- `req-body-${idx}`
19465
- ));
19466
- } catch {
19467
- return /* @__PURE__ */ jsx12(Box12, { marginTop: 1, paddingLeft: 2, flexShrink: 0, children: /* @__PURE__ */ jsx12(Text11, { dimColor: true, children: selectedRequest.requestBody }) });
20896
+ selectedRequest.requestBody && /* @__PURE__ */ jsxs12(Fragment9, { children: [
20897
+ /* @__PURE__ */ jsx13(Box13, { marginTop: 1, flexShrink: 0, children: /* @__PURE__ */ jsx13(Text12, { bold: true, children: "Request Body:" }) }),
20898
+ /* @__PURE__ */ jsx13(
20899
+ BodyLines,
20900
+ {
20901
+ body: selectedRequest.requestBody,
20902
+ keyPrefix: "req-body"
19468
20903
  }
19469
- })()
20904
+ )
19470
20905
  ] }),
19471
- selectedRequest.responseHeaders && Object.keys(selectedRequest.responseHeaders).length > 0 && /* @__PURE__ */ jsxs11(Fragment8, { children: [
19472
- /* @__PURE__ */ jsx12(Box12, { marginTop: 1, flexShrink: 0, children: /* @__PURE__ */ jsx12(Text11, { bold: true, children: "Response Headers:" }) }),
20906
+ selectedRequest.responseHeaders && Object.keys(selectedRequest.responseHeaders).length > 0 && /* @__PURE__ */ jsxs12(Fragment9, { children: [
20907
+ /* @__PURE__ */ jsx13(Box13, { marginTop: 1, flexShrink: 0, children: /* @__PURE__ */ jsx13(Text12, { bold: true, children: "Response Headers:" }) }),
19473
20908
  Object.entries(selectedRequest.responseHeaders).map(
19474
- ([key, value]) => /* @__PURE__ */ jsx12(
19475
- Box12,
20909
+ ([key, value]) => /* @__PURE__ */ jsx13(
20910
+ Box13,
19476
20911
  {
19477
20912
  marginTop: 0,
19478
20913
  paddingLeft: 2,
19479
20914
  flexShrink: 0,
19480
- children: /* @__PURE__ */ jsxs11(Text11, { dimColor: true, children: [
20915
+ children: /* @__PURE__ */ jsxs12(Text12, { dimColor: true, children: [
19481
20916
  key,
19482
20917
  ": ",
19483
20918
  value
@@ -19487,38 +20922,28 @@ function RequestsTab({
19487
20922
  )
19488
20923
  )
19489
20924
  ] }),
19490
- selectedRequest.responseBody && /* @__PURE__ */ jsxs11(Fragment8, { children: [
19491
- /* @__PURE__ */ jsx12(Box12, { marginTop: 1, flexShrink: 0, children: /* @__PURE__ */ jsx12(Text11, { bold: true, children: "Response Body:" }) }),
19492
- (() => {
19493
- try {
19494
- const parsed = JSON.parse(selectedRequest.responseBody);
19495
- return JSON.stringify(parsed, null, 2).split("\n").map((line, idx) => /* @__PURE__ */ jsx12(
19496
- Box12,
19497
- {
19498
- marginTop: idx === 0 ? 1 : 0,
19499
- paddingLeft: 2,
19500
- flexShrink: 0,
19501
- children: /* @__PURE__ */ jsx12(Text11, { dimColor: true, children: line })
19502
- },
19503
- `resp-body-${idx}`
19504
- ));
19505
- } catch {
19506
- return /* @__PURE__ */ jsx12(Box12, { marginTop: 1, paddingLeft: 2, flexShrink: 0, children: /* @__PURE__ */ jsx12(Text11, { dimColor: true, children: selectedRequest.responseBody }) });
20925
+ selectedRequest.responseBody && /* @__PURE__ */ jsxs12(Fragment9, { children: [
20926
+ /* @__PURE__ */ jsx13(Box13, { marginTop: 1, flexShrink: 0, children: /* @__PURE__ */ jsx13(Text12, { bold: true, children: "Response Body:" }) }),
20927
+ /* @__PURE__ */ jsx13(
20928
+ BodyLines,
20929
+ {
20930
+ body: selectedRequest.responseBody,
20931
+ keyPrefix: "resp-body"
19507
20932
  }
19508
- })()
20933
+ )
19509
20934
  ] })
19510
20935
  ] }),
19511
- focusedPane === "details" && /* @__PURE__ */ jsx12(
19512
- Box12,
20936
+ focusedPane === "details" && /* @__PURE__ */ jsx13(
20937
+ Box13,
19513
20938
  {
19514
20939
  flexShrink: 0,
19515
20940
  height: 1,
19516
20941
  justifyContent: "center",
19517
20942
  backgroundColor: "gray",
19518
- children: /* @__PURE__ */ jsx12(Text11, { bold: true, color: "white", children: "\u2191/\u2193 to scroll, + to zoom" })
20943
+ children: /* @__PURE__ */ jsx13(Text12, { bold: true, color: "white", children: "\u2191/\u2193 to scroll, + to zoom" })
19519
20944
  }
19520
20945
  )
19521
- ] }) : /* @__PURE__ */ jsx12(Box12, { paddingY: 1, flexShrink: 0, children: /* @__PURE__ */ jsx12(Text11, { dimColor: true, children: "Select a request to view details" }) })
20946
+ ] }) : /* @__PURE__ */ jsx13(Box13, { paddingY: 1, flexShrink: 0, children: /* @__PURE__ */ jsx13(Text12, { dimColor: true, children: "Select a request to view details" }) })
19522
20947
  }
19523
20948
  )
19524
20949
  ] });
@@ -19526,16 +20951,16 @@ function RequestsTab({
19526
20951
 
19527
20952
  // src/components/ToolTestModal.tsx
19528
20953
  import React26, { useState as useState14 } from "react";
19529
- import { Box as Box24, Text as Text21, useInput as useInput18 } from "ink";
20954
+ import { Box as Box25, Text as Text22, useInput as useInput18 } from "ink";
19530
20955
 
19531
20956
  // node_modules/ink-form/lib/Form.js
19532
- import { Box as Box23, useFocusManager, useInput as useInput17 } from "ink";
20957
+ import { Box as Box24, useFocusManager, useInput as useInput17 } from "ink";
19533
20958
  import { useEffect as useEffect13, useMemo as useMemo3, useState as useState13 } from "react";
19534
20959
  import * as React24 from "react";
19535
20960
 
19536
20961
  // node_modules/ink-form/lib/FormHeader.js
19537
20962
  import * as React10 from "react";
19538
- import { Box as Box13, Text as Text12, useInput as useInput10 } from "ink";
20963
+ import { Box as Box14, Text as Text13, useInput as useInput10 } from "ink";
19539
20964
  var FormHeader = (props) => {
19540
20965
  const sections = props.form.sections;
19541
20966
  useInput10((input, key) => {
@@ -19552,42 +20977,42 @@ var FormHeader = (props) => {
19552
20977
  }
19553
20978
  }, { isActive: !props.editingField });
19554
20979
  return React10.createElement(
19555
- Box13,
20980
+ Box14,
19556
20981
  { borderStyle: "double", width: "100%", flexDirection: "column" },
19557
20982
  React10.createElement(
19558
- Box13,
20983
+ Box14,
19559
20984
  { width: "100%" },
19560
20985
  React10.createElement(
19561
- Box13,
20986
+ Box14,
19562
20987
  { flexGrow: 1 },
19563
- React10.createElement(Text12, { bold: true }, props.form.title)
20988
+ React10.createElement(Text13, { bold: true }, props.form.title)
19564
20989
  ),
19565
20990
  React10.createElement(
19566
- Box13,
20991
+ Box14,
19567
20992
  null,
19568
- React10.createElement(Text12, null, !props.editingField ? "Use arrow keys to move around" : "Press ESC to cancel, or Enter to complete field")
20993
+ React10.createElement(Text13, null, !props.editingField ? "Use arrow keys to move around" : "Press ESC to cancel, or Enter to complete field")
19569
20994
  )
19570
20995
  ),
19571
20996
  React10.createElement(
19572
- Box13,
20997
+ Box14,
19573
20998
  { width: "100%" },
19574
- React10.createElement(Box13, null, !props.editingField ? sections.map((section, id) => React10.createElement(
19575
- Box13,
20999
+ React10.createElement(Box14, null, !props.editingField ? sections.map((section, id) => React10.createElement(
21000
+ Box14,
19576
21001
  { key: section.title },
19577
21002
  React10.createElement(
19578
- Text12,
21003
+ Text13,
19579
21004
  { color: "gray" },
19580
21005
  "[",
19581
21006
  id + 1,
19582
21007
  "] "
19583
21008
  ),
19584
- React10.createElement(Text12, { color: props.currentTab === id ? "blue" : void 0, underline: props.currentTab === id }, section.title),
19585
- React10.createElement(Text12, null, " ")
21009
+ React10.createElement(Text13, { color: props.currentTab === id ? "blue" : void 0, underline: props.currentTab === id }, section.title),
21010
+ React10.createElement(Text13, null, " ")
19586
21011
  )) : React10.createElement(
19587
- Box13,
21012
+ Box14,
19588
21013
  null,
19589
21014
  React10.createElement(
19590
- Text12,
21015
+ Text13,
19591
21016
  null,
19592
21017
  "Editing ",
19593
21018
  props.editingField
@@ -19599,18 +21024,18 @@ var FormHeader = (props) => {
19599
21024
 
19600
21025
  // node_modules/ink-form/lib/FormFieldRenderer.js
19601
21026
  import React22, { useState as useState12 } from "react";
19602
- import { Box as Box21, useFocus, Text as Text19, useInput as useInput15 } from "ink";
21027
+ import { Box as Box22, useFocus, Text as Text20, useInput as useInput15 } from "ink";
19603
21028
 
19604
21029
  // node_modules/ink-form/lib/managers/FloatFormFieldManager.js
19605
21030
  import React13 from "react";
19606
21031
 
19607
21032
  // node_modules/ink-form/lib/NumberFieldRenderer.js
19608
21033
  import React12 from "react";
19609
- import { Box as Box14, Text as Text14, useInput as useInput12 } from "ink";
21034
+ import { Box as Box15, Text as Text15, useInput as useInput12 } from "ink";
19610
21035
 
19611
21036
  // node_modules/ink-text-input/build/index.js
19612
21037
  import React11, { useState as useState10, useEffect as useEffect11 } from "react";
19613
- import { Text as Text13, useInput as useInput11 } from "ink";
21038
+ import { Text as Text14, useInput as useInput11 } from "ink";
19614
21039
 
19615
21040
  // node_modules/chalk/source/vendor/ansi-styles/index.js
19616
21041
  var ANSI_BACKGROUND_OFFSET = 10;
@@ -20192,7 +21617,7 @@ function TextInput({ value: originalValue, placeholder = "", focus = true, mask,
20192
21617
  onChange(nextValue);
20193
21618
  }
20194
21619
  }, { isActive: focus });
20195
- return React11.createElement(Text13, null, placeholder ? value.length > 0 ? renderedValue : renderedPlaceholder : renderedValue);
21620
+ return React11.createElement(Text14, null, placeholder ? value.length > 0 ? renderedValue : renderedPlaceholder : renderedValue);
20196
21621
  }
20197
21622
  var build_default = TextInput;
20198
21623
 
@@ -20236,10 +21661,10 @@ var NumberFieldRenderer = (props) => {
20236
21661
  }
20237
21662
  });
20238
21663
  return React12.createElement(
20239
- Box14,
21664
+ Box15,
20240
21665
  { borderStyle: "round", width: "100%", flexDirection: "column" },
20241
21666
  React12.createElement(
20242
- Box14,
21667
+ Box15,
20243
21668
  null,
20244
21669
  React12.createElement(build_default, { value: "" + (props.value ?? ""), onChange: (value) => {
20245
21670
  if (regex.test(value)) {
@@ -20252,9 +21677,9 @@ var NumberFieldRenderer = (props) => {
20252
21677
  }, placeholder: props.field.placeholder, onSubmit: () => props.onSetEditingField(void 0) })
20253
21678
  ),
20254
21679
  React12.createElement(
20255
- Box14,
21680
+ Box15,
20256
21681
  null,
20257
- React12.createElement(Text14, { dimColor: true }, "Press UP/DOWN to increase or decrease the value.")
21682
+ React12.createElement(Text15, { dimColor: true }, "Press UP/DOWN to increase or decrease the value.")
20258
21683
  )
20259
21684
  );
20260
21685
  };
@@ -20276,11 +21701,11 @@ var IntegerFormFieldManager = class {
20276
21701
 
20277
21702
  // node_modules/ink-form/lib/managers/SelectFormFieldManager.js
20278
21703
  import React18 from "react";
20279
- import { Box as Box17 } from "ink";
21704
+ import { Box as Box18 } from "ink";
20280
21705
 
20281
21706
  // node_modules/ink-select-input/build/Indicator.js
20282
21707
  import React15 from "react";
20283
- import { Box as Box15, Text as Text15 } from "ink";
21708
+ import { Box as Box16, Text as Text16 } from "ink";
20284
21709
 
20285
21710
  // node_modules/is-unicode-supported/index.js
20286
21711
  import process3 from "process";
@@ -20571,15 +21996,15 @@ var replacements = Object.entries(specialMainSymbols);
20571
21996
 
20572
21997
  // node_modules/ink-select-input/build/Indicator.js
20573
21998
  function Indicator({ isSelected = false }) {
20574
- return React15.createElement(Box15, { marginRight: 1 }, isSelected ? React15.createElement(Text15, { color: "blue" }, figures_default.pointer) : React15.createElement(Text15, null, " "));
21999
+ return React15.createElement(Box16, { marginRight: 1 }, isSelected ? React15.createElement(Text16, { color: "blue" }, figures_default.pointer) : React15.createElement(Text16, null, " "));
20575
22000
  }
20576
22001
  var Indicator_default = Indicator;
20577
22002
 
20578
22003
  // node_modules/ink-select-input/build/Item.js
20579
22004
  import * as React16 from "react";
20580
- import { Text as Text16 } from "ink";
22005
+ import { Text as Text17 } from "ink";
20581
22006
  function Item({ isSelected = false, label }) {
20582
- return React16.createElement(Text16, { color: isSelected ? "blue" : void 0 }, label);
22007
+ return React16.createElement(Text17, { color: isSelected ? "blue" : void 0 }, label);
20583
22008
  }
20584
22009
  var Item_default = Item;
20585
22010
 
@@ -20610,7 +22035,7 @@ function toRotated(array, steps) {
20610
22035
  }
20611
22036
 
20612
22037
  // node_modules/ink-select-input/build/SelectInput.js
20613
- import { Box as Box16, useInput as useInput13 } from "ink";
22038
+ import { Box as Box17, useInput as useInput13 } from "ink";
20614
22039
  function SelectInput({ items = [], isFocused = true, initialIndex = 0, indicatorComponent = Indicator_default, itemComponent = Item_default, limit: customLimit, onSelect, onHighlight }) {
20615
22040
  const hasLimit = typeof customLimit === "number" && items.length > customLimit;
20616
22041
  const limit = hasLimit ? Math.min(customLimit, items.length) : items.length;
@@ -20677,12 +22102,12 @@ function SelectInput({ items = [], isFocused = true, initialIndex = 0, indicator
20677
22102
  onHighlight
20678
22103
  ]), { isActive: isFocused });
20679
22104
  const slicedItems = hasLimit ? toRotated(items, rotateIndex).slice(0, limit) : items;
20680
- return React17.createElement(Box16, { flexDirection: "column" }, slicedItems.map((item, index) => {
22105
+ return React17.createElement(Box17, { flexDirection: "column" }, slicedItems.map((item, index) => {
20681
22106
  const isSelected = index === selectedIndex;
20682
22107
  return (
20683
22108
  // @ts-expect-error - `key` can't be optional but `item.value` is generic T
20684
22109
  React17.createElement(
20685
- Box16,
22110
+ Box17,
20686
22111
  { key: item.key ?? item.value },
20687
22112
  React17.createElement(indicatorComponent, { isSelected }),
20688
22113
  React17.createElement(itemComponent, { ...item, isSelected })
@@ -20696,7 +22121,7 @@ var SelectInput_default = SelectInput;
20696
22121
  var SelectFormFieldManager = class {
20697
22122
  type = "select";
20698
22123
  renderField = (props) => React18.createElement(
20699
- Box17,
22124
+ Box18,
20700
22125
  { borderStyle: "round", width: "100%" },
20701
22126
  React18.createElement(SelectInput_default, { items: props.field.options.map((option) => ({ value: option.value, label: option.label ?? option.value })), onHighlight: (option) => props.onChange(option.value), initialIndex: props.field.options.findIndex((option) => option.value === props.value) ?? 0 })
20702
22127
  );
@@ -20705,11 +22130,11 @@ var SelectFormFieldManager = class {
20705
22130
 
20706
22131
  // node_modules/ink-form/lib/managers/StringFormFieldManager.js
20707
22132
  import React19 from "react";
20708
- import { Box as Box18, Transform } from "ink";
22133
+ import { Box as Box19, Transform } from "ink";
20709
22134
  var StringFormFieldManager = class {
20710
22135
  type = "string";
20711
22136
  renderField = (props) => React19.createElement(
20712
- Box18,
22137
+ Box19,
20713
22138
  { borderStyle: "round", width: "100%" },
20714
22139
  React19.createElement(build_default, { value: props.value ?? "", onChange: (value) => {
20715
22140
  props.onChange(value);
@@ -20725,7 +22150,7 @@ var StringFormFieldManager = class {
20725
22150
 
20726
22151
  // node_modules/ink-form/lib/managers/BooleanFormFieldManager.js
20727
22152
  import React20 from "react";
20728
- import { Box as Box19, Text as Text17, useInput as useInput14 } from "ink";
22153
+ import { Box as Box20, Text as Text18, useInput as useInput14 } from "ink";
20729
22154
  var BooleanFormFieldManager = class {
20730
22155
  type = "boolean";
20731
22156
  renderField = (props) => {
@@ -20735,21 +22160,21 @@ var BooleanFormFieldManager = class {
20735
22160
  }
20736
22161
  });
20737
22162
  return React20.createElement(
20738
- Box19,
22163
+ Box20,
20739
22164
  { width: "100%", borderStyle: "round", borderColor: props.value ? "green" : "gray", marginBottom: 2 },
20740
22165
  React20.createElement(
20741
- Box19,
22166
+ Box20,
20742
22167
  { marginRight: 2 },
20743
- React20.createElement(Text17, { color: props.value ? "green" : "gray" }, props.value === void 0 ? "[Not set]" : props.value ? "[True]" : "[False]")
22168
+ React20.createElement(Text18, { color: props.value ? "green" : "gray" }, props.value === void 0 ? "[Not set]" : props.value ? "[True]" : "[False]")
20744
22169
  ),
20745
22170
  React20.createElement(
20746
- Box19,
22171
+ Box20,
20747
22172
  { flexGrow: 1 },
20748
- React20.createElement(Text17, null, "Press Space to toggle value")
22173
+ React20.createElement(Text18, null, "Press Space to toggle value")
20749
22174
  )
20750
22175
  );
20751
22176
  };
20752
- renderValue = (props) => React20.createElement(Text17, null, props.value === void 0 ? "[Not set]" : props.value ? "[True]" : "[False]");
22177
+ renderValue = (props) => React20.createElement(Text18, null, props.value === void 0 ? "[Not set]" : props.value ? "[True]" : "[False]");
20753
22178
  };
20754
22179
 
20755
22180
  // node_modules/ink-form/lib/managers/managers.js
@@ -20766,20 +22191,20 @@ var getManager = (formFieldType, customManagers = []) => {
20766
22191
 
20767
22192
  // node_modules/ink-form/lib/DescriptionRenderer.js
20768
22193
  import React21 from "react";
20769
- import { Box as Box20, Text as Text18 } from "ink";
22194
+ import { Box as Box21, Text as Text19 } from "ink";
20770
22195
  var DescriptionRenderer = (props) => {
20771
22196
  if (!props.description) {
20772
22197
  return null;
20773
22198
  } else if (props.description.type) {
20774
22199
  return props.description;
20775
22200
  } else if (Array.isArray(props.description)) {
20776
- return React21.createElement(Box20, { flexDirection: "column" }, props.description.map((line) => React21.createElement(
20777
- Box20,
22201
+ return React21.createElement(Box21, { flexDirection: "column" }, props.description.map((line) => React21.createElement(
22202
+ Box21,
20778
22203
  { key: line, width: "100%", marginBottom: 1 },
20779
- React21.createElement(Text18, null, line)
22204
+ React21.createElement(Text19, null, line)
20780
22205
  )));
20781
22206
  } else {
20782
- return React21.createElement(Text18, null, props.description);
22207
+ return React21.createElement(Text19, null, props.description);
20783
22208
  }
20784
22209
  };
20785
22210
 
@@ -20822,24 +22247,24 @@ var FormFieldRenderer = (props) => {
20822
22247
  if (!isEditing) {
20823
22248
  const RenderValue = manager?.renderValue ?? (() => React22.createElement(React22.Fragment, null, props.value));
20824
22249
  return React22.createElement(
20825
- Box21,
22250
+ Box22,
20826
22251
  { marginX: 2, paddingX: 1, borderStyle: "round", borderColor: isFocused ? "blue" : void 0 },
20827
22252
  React22.createElement(
20828
- Box21,
22253
+ Box22,
20829
22254
  { flexGrow: 1 },
20830
- React22.createElement(Text19, { underline: isFocused, color: isFocused ? "blue" : void 0 }, props.field.label ?? props.field.name),
20831
- props.field.required && React22.createElement(Text19, { color: "red" }, "*"),
20832
- React22.createElement(Text19, null, ": "),
22255
+ React22.createElement(Text20, { underline: isFocused, color: isFocused ? "blue" : void 0 }, props.field.label ?? props.field.name),
22256
+ props.field.required && React22.createElement(Text20, { color: "red" }, "*"),
22257
+ React22.createElement(Text20, null, ": "),
20833
22258
  React22.createElement(
20834
- Text19,
22259
+ Text20,
20835
22260
  { dimColor: true },
20836
22261
  React22.createElement(RenderValue, { value: props.value, field: props.field })
20837
22262
  )
20838
22263
  ),
20839
22264
  isFocused && React22.createElement(
20840
- Box21,
22265
+ Box22,
20841
22266
  null,
20842
- React22.createElement(Text19, null, "Press enter to edit")
22267
+ React22.createElement(Text20, null, "Press enter to edit")
20843
22268
  )
20844
22269
  );
20845
22270
  } else {
@@ -20856,7 +22281,7 @@ var FormFieldRenderer = (props) => {
20856
22281
  };
20857
22282
  if (!manager) {
20858
22283
  component = React22.createElement(
20859
- Text19,
22284
+ Text20,
20860
22285
  { color: "red" },
20861
22286
  "No formfield manager for form field of type ",
20862
22287
  props.field.type,
@@ -20867,39 +22292,39 @@ var FormFieldRenderer = (props) => {
20867
22292
  component = React22.createElement(Field, { ...rendererProps });
20868
22293
  }
20869
22294
  return React22.createElement(
20870
- Box21,
22295
+ Box22,
20871
22296
  { paddingX: 3, paddingY: 1, flexDirection: "column" },
20872
22297
  React22.createElement(
20873
- Box21,
22298
+ Box22,
20874
22299
  null,
20875
- React22.createElement(Text19, null, props.field.label ?? props.field.name),
20876
- props.field.required && React22.createElement(Text19, { color: "red" }, "*"),
20877
- React22.createElement(Text19, null, ": ")
22300
+ React22.createElement(Text20, null, props.field.label ?? props.field.name),
22301
+ props.field.required && React22.createElement(Text20, { color: "red" }, "*"),
22302
+ React22.createElement(Text20, null, ": ")
20878
22303
  ),
20879
- React22.createElement(Box21, null, component),
22304
+ React22.createElement(Box22, null, component),
20880
22305
  props.field.description && React22.createElement(
20881
- Box21,
22306
+ Box22,
20882
22307
  null,
20883
22308
  React22.createElement(
20884
- Text19,
22309
+ Text20,
20885
22310
  { dimColor: true },
20886
22311
  React22.createElement(DescriptionRenderer, { description: props.field.description })
20887
22312
  )
20888
22313
  ),
20889
22314
  error && React22.createElement(
20890
- Box21,
22315
+ Box22,
20891
22316
  null,
20892
22317
  React22.createElement(
20893
- Text19,
22318
+ Text20,
20894
22319
  { color: "red" },
20895
22320
  "Error: ",
20896
22321
  error
20897
22322
  )
20898
22323
  ),
20899
22324
  React22.createElement(
20900
- Box21,
22325
+ Box22,
20901
22326
  { marginTop: 2 },
20902
- React22.createElement(Text19, { dimColor: true }, error ? React22.createElement(React22.Fragment, null, "Press ESC to cancel.") : React22.createElement(
22327
+ React22.createElement(Text20, { dimColor: true }, error ? React22.createElement(React22.Fragment, null, "Press ESC to cancel.") : React22.createElement(
20903
22328
  React22.Fragment,
20904
22329
  null,
20905
22330
  "Press ",
@@ -20918,7 +22343,7 @@ var canSubmit = (form, value) => {
20918
22343
 
20919
22344
  // node_modules/ink-form/lib/SubmitButton.js
20920
22345
  import React23 from "react";
20921
- import { Text as Text20, Box as Box22, useFocus as useFocus2, useInput as useInput16 } from "ink";
22346
+ import { Text as Text21, Box as Box23, useFocus as useFocus2, useInput as useInput16 } from "ink";
20922
22347
  var SubmitButton = (props) => {
20923
22348
  const { isFocused } = useFocus2({ isActive: props.canSubmit });
20924
22349
  useInput16((input, key) => {
@@ -20927,17 +22352,17 @@ var SubmitButton = (props) => {
20927
22352
  }
20928
22353
  });
20929
22354
  return React23.createElement(
20930
- Box22,
22355
+ Box23,
20931
22356
  { marginRight: 2 },
20932
22357
  React23.createElement(
20933
- Box22,
22358
+ Box23,
20934
22359
  { marginRight: 2, paddingY: 1 },
20935
- React23.createElement(Text20, null, !props.canSubmit ? "There are still required inputs you have not completed yet." : isFocused ? "Press Enter to submit form" : "Use the arrow keys to navigate to the submit button.")
22360
+ React23.createElement(Text21, null, !props.canSubmit ? "There are still required inputs you have not completed yet." : isFocused ? "Press Enter to submit form" : "Use the arrow keys to navigate to the submit button.")
20936
22361
  ),
20937
22362
  React23.createElement(
20938
- Box22,
22363
+ Box23,
20939
22364
  { borderStyle: "round", borderColor: !props.canSubmit ? "gray" : isFocused ? "blue" : "white", paddingX: 2 },
20940
- React23.createElement(Text20, { color: !props.canSubmit ? "gray" : isFocused ? "blue" : "white", bold: true, underline: isFocused }, props.canSubmit ? "Submit form" : "Cannot submit form yet")
22365
+ React23.createElement(Text21, { color: !props.canSubmit ? "gray" : isFocused ? "blue" : "white", bold: true, underline: isFocused }, props.canSubmit ? "Submit form" : "Cannot submit form yet")
20941
22366
  )
20942
22367
  );
20943
22368
  };
@@ -20978,17 +22403,17 @@ var Form = (props) => {
20978
22403
  }
20979
22404
  }, { isActive: !editingField });
20980
22405
  return React24.createElement(
20981
- Box23,
22406
+ Box24,
20982
22407
  { width: "100%", height: "100%", flexDirection: "column" },
20983
22408
  React24.createElement(FormHeader, { ...props, currentTab, onChangeTab: setCurrentTab, editingField }),
20984
22409
  !editingField && props.form.sections[currentTab].description && React24.createElement(
20985
- Box23,
22410
+ Box24,
20986
22411
  { marginX: 4 },
20987
22412
  React24.createElement(DescriptionRenderer, { description: props.form.sections[currentTab].description })
20988
22413
  ),
20989
- React24.createElement(Box23, { flexDirection: "column" }, currentTab > props.form.sections.length - 1 ? null : props.form.sections[currentTab].fields.map((field) => React24.createElement(FormFieldRenderer, { field, key: field.name, form: props.form, value: value[field.name], onChange: (v) => setValueAndPropagate({ ...value, [field.name]: v }), onSetEditingField: setEditingField, editingField, customManagers: props.customManagers }))),
22414
+ React24.createElement(Box24, { flexDirection: "column" }, currentTab > props.form.sections.length - 1 ? null : props.form.sections[currentTab].fields.map((field) => React24.createElement(FormFieldRenderer, { field, key: field.name, form: props.form, value: value[field.name], onChange: (v) => setValueAndPropagate({ ...value, [field.name]: v }), onSetEditingField: setEditingField, editingField, customManagers: props.customManagers }))),
20990
22415
  !editingField && React24.createElement(
20991
- Box23,
22416
+ Box24,
20992
22417
  { flexDirection: "row-reverse" },
20993
22418
  React24.createElement(SubmitButton, { canSubmit: canSubmitForm, onSubmit: () => props.onSubmit?.(value) })
20994
22419
  )
@@ -21260,7 +22685,7 @@ function missingRequiredFields(schema, decoded, rawValues = {}) {
21260
22685
  }
21261
22686
 
21262
22687
  // src/components/ToolTestModal.tsx
21263
- import { Fragment as Fragment9, jsx as jsx13, jsxs as jsxs12 } from "react/jsx-runtime";
22688
+ import { Fragment as Fragment10, jsx as jsx14, jsxs as jsxs13 } from "react/jsx-runtime";
21264
22689
  function ToolTestModal({
21265
22690
  tool,
21266
22691
  inspectorClient,
@@ -21289,7 +22714,8 @@ function ToolTestModal({
21289
22714
  process.stdout.off("resize", updateDimensions);
21290
22715
  };
21291
22716
  }, [width, height]);
21292
- const formStructure = tool?.inputSchema ? schemaToForm(tool.inputSchema, tool.name || "Unknown Tool") : {
22717
+ const inputSchema = inlineLocalRefs(tool?.inputSchema);
22718
+ const formStructure = inputSchema ? schemaToForm(inputSchema, tool?.name || "Unknown Tool") : {
21293
22719
  title: `Test Tool: ${tool?.name || "Unknown"}`,
21294
22720
  sections: [{ title: "Parameters", fields: [] }]
21295
22721
  };
@@ -21328,8 +22754,8 @@ function ToolTestModal({
21328
22754
  );
21329
22755
  const handleFormSubmit = async (rawValues) => {
21330
22756
  if (!inspectorClient || !tool) return;
21331
- const values = decodeFormValues(tool.inputSchema, rawValues);
21332
- const missing = missingRequiredFields(tool.inputSchema, values, rawValues);
22757
+ const values = decodeFormValues(inputSchema, rawValues);
22758
+ const missing = missingRequiredFields(inputSchema, values, rawValues);
21333
22759
  if (missing.length > 0) {
21334
22760
  setResult({
21335
22761
  input: values,
@@ -21385,8 +22811,8 @@ function ToolTestModal({
21385
22811
  };
21386
22812
  const modalWidth = terminalDimensions.width - 2;
21387
22813
  const modalHeight = terminalDimensions.height - 2;
21388
- return /* @__PURE__ */ jsx13(
21389
- Box24,
22814
+ return /* @__PURE__ */ jsx14(
22815
+ Box25,
21390
22816
  {
21391
22817
  position: "absolute",
21392
22818
  width: terminalDimensions.width,
@@ -21394,8 +22820,8 @@ function ToolTestModal({
21394
22820
  flexDirection: "column",
21395
22821
  justifyContent: "center",
21396
22822
  alignItems: "center",
21397
- children: /* @__PURE__ */ jsxs12(
21398
- Box24,
22823
+ children: /* @__PURE__ */ jsxs13(
22824
+ Box25,
21399
22825
  {
21400
22826
  width: modalWidth,
21401
22827
  height: modalHeight,
@@ -21406,40 +22832,40 @@ function ToolTestModal({
21406
22832
  paddingY: 1,
21407
22833
  backgroundColor: "black",
21408
22834
  children: [
21409
- /* @__PURE__ */ jsxs12(Box24, { flexShrink: 0, marginBottom: 1, children: [
21410
- /* @__PURE__ */ jsx13(Text21, { bold: true, color: "cyan", children: formStructure.title }),
21411
- /* @__PURE__ */ jsx13(Text21, { children: " " }),
21412
- /* @__PURE__ */ jsx13(Text21, { dimColor: true, children: "(Press ESC to close)" })
22835
+ /* @__PURE__ */ jsxs13(Box25, { flexShrink: 0, marginBottom: 1, children: [
22836
+ /* @__PURE__ */ jsx14(Text22, { bold: true, color: "cyan", children: formStructure.title }),
22837
+ /* @__PURE__ */ jsx14(Text22, { children: " " }),
22838
+ /* @__PURE__ */ jsx14(Text22, { dimColor: true, children: "(Press ESC to close)" })
21413
22839
  ] }),
21414
- /* @__PURE__ */ jsxs12(Box24, { flexGrow: 1, flexDirection: "column", overflow: "hidden", children: [
21415
- state === "form" && /* @__PURE__ */ jsx13(Box24, { flexGrow: 1, width: "100%", children: /* @__PURE__ */ jsx13(
22840
+ /* @__PURE__ */ jsxs13(Box25, { flexGrow: 1, flexDirection: "column", overflow: "hidden", children: [
22841
+ state === "form" && /* @__PURE__ */ jsx14(Box25, { flexGrow: 1, width: "100%", children: /* @__PURE__ */ jsx14(
21416
22842
  Form,
21417
22843
  {
21418
22844
  form: formStructure,
21419
22845
  onSubmit: (value) => void handleFormSubmit(value)
21420
22846
  }
21421
22847
  ) }),
21422
- state === "loading" && /* @__PURE__ */ jsx13(Box24, { flexGrow: 1, justifyContent: "center", alignItems: "center", children: /* @__PURE__ */ jsx13(Text21, { color: "yellow", children: "Calling tool..." }) }),
21423
- state === "results" && result && /* @__PURE__ */ jsx13(Box24, { flexGrow: 1, flexDirection: "column", overflow: "hidden", children: /* @__PURE__ */ jsxs12(ScrollView, { ref: scrollViewRef, children: [
21424
- /* @__PURE__ */ jsx13(Box24, { marginBottom: 1, flexShrink: 0, children: /* @__PURE__ */ jsxs12(Text21, { bold: true, color: "green", children: [
22848
+ state === "loading" && /* @__PURE__ */ jsx14(Box25, { flexGrow: 1, justifyContent: "center", alignItems: "center", children: /* @__PURE__ */ jsx14(Text22, { color: "yellow", children: "Calling tool..." }) }),
22849
+ state === "results" && result && /* @__PURE__ */ jsx14(Box25, { flexGrow: 1, flexDirection: "column", overflow: "hidden", children: /* @__PURE__ */ jsxs13(ScrollView, { ref: scrollViewRef, children: [
22850
+ /* @__PURE__ */ jsx14(Box25, { marginBottom: 1, flexShrink: 0, children: /* @__PURE__ */ jsxs13(Text22, { bold: true, color: "green", children: [
21425
22851
  "Duration: ",
21426
22852
  result.duration,
21427
22853
  "ms"
21428
22854
  ] }) }),
21429
- /* @__PURE__ */ jsxs12(Box24, { marginBottom: 1, flexShrink: 0, flexDirection: "column", children: [
21430
- /* @__PURE__ */ jsx13(Text21, { bold: true, color: "cyan", children: "Input:" }),
21431
- /* @__PURE__ */ jsx13(Box24, { paddingLeft: 2, children: /* @__PURE__ */ jsx13(Text21, { dimColor: true, children: JSON.stringify(result.input, null, 2) }) })
22855
+ /* @__PURE__ */ jsxs13(Box25, { marginBottom: 1, flexShrink: 0, flexDirection: "column", children: [
22856
+ /* @__PURE__ */ jsx14(Text22, { bold: true, color: "cyan", children: "Input:" }),
22857
+ /* @__PURE__ */ jsx14(Box25, { paddingLeft: 2, children: /* @__PURE__ */ jsx14(Text22, { dimColor: true, children: JSON.stringify(result.input, null, 2) }) })
21432
22858
  ] }),
21433
- result.error ? /* @__PURE__ */ jsxs12(Box24, { flexShrink: 0, flexDirection: "column", children: [
21434
- /* @__PURE__ */ jsx13(Text21, { bold: true, color: "red", children: "Error:" }),
21435
- /* @__PURE__ */ jsx13(Box24, { paddingLeft: 2, children: /* @__PURE__ */ jsx13(Text21, { color: "red", children: String(result.error) }) }),
21436
- result.errorDetails != null ? /* @__PURE__ */ jsxs12(Fragment9, { children: [
21437
- /* @__PURE__ */ jsx13(Box24, { marginTop: 1, children: /* @__PURE__ */ jsx13(Text21, { bold: true, color: "red", dimColor: true, children: "Error Details:" }) }),
21438
- /* @__PURE__ */ jsx13(Box24, { paddingLeft: 2, children: /* @__PURE__ */ jsx13(Text21, { dimColor: true, children: JSON.stringify(result.errorDetails, null, 2) }) })
22859
+ result.error ? /* @__PURE__ */ jsxs13(Box25, { flexShrink: 0, flexDirection: "column", children: [
22860
+ /* @__PURE__ */ jsx14(Text22, { bold: true, color: "red", children: "Error:" }),
22861
+ /* @__PURE__ */ jsx14(Box25, { paddingLeft: 2, children: /* @__PURE__ */ jsx14(Text22, { color: "red", children: String(result.error) }) }),
22862
+ result.errorDetails != null ? /* @__PURE__ */ jsxs13(Fragment10, { children: [
22863
+ /* @__PURE__ */ jsx14(Box25, { marginTop: 1, children: /* @__PURE__ */ jsx14(Text22, { bold: true, color: "red", dimColor: true, children: "Error Details:" }) }),
22864
+ /* @__PURE__ */ jsx14(Box25, { paddingLeft: 2, children: /* @__PURE__ */ jsx14(Text22, { dimColor: true, children: JSON.stringify(result.errorDetails, null, 2) }) })
21439
22865
  ] }) : null
21440
- ] }) : /* @__PURE__ */ jsxs12(Box24, { flexShrink: 0, flexDirection: "column", children: [
21441
- /* @__PURE__ */ jsx13(Text21, { bold: true, color: "green", children: "Output:" }),
21442
- /* @__PURE__ */ jsx13(Box24, { paddingLeft: 2, children: /* @__PURE__ */ jsx13(Text21, { dimColor: true, children: JSON.stringify(result.output, null, 2) }) })
22866
+ ] }) : /* @__PURE__ */ jsxs13(Box25, { flexShrink: 0, flexDirection: "column", children: [
22867
+ /* @__PURE__ */ jsx14(Text22, { bold: true, color: "green", children: "Output:" }),
22868
+ /* @__PURE__ */ jsx14(Box25, { paddingLeft: 2, children: /* @__PURE__ */ jsx14(Text22, { dimColor: true, children: JSON.stringify(result.output, null, 2) }) })
21443
22869
  ] })
21444
22870
  ] }) })
21445
22871
  ] })
@@ -21452,7 +22878,7 @@ function ToolTestModal({
21452
22878
 
21453
22879
  // src/components/ResourceTestModal.tsx
21454
22880
  import React27, { useState as useState15 } from "react";
21455
- import { Box as Box25, Text as Text22, useInput as useInput19 } from "ink";
22881
+ import { Box as Box26, Text as Text23, useInput as useInput19 } from "ink";
21456
22882
 
21457
22883
  // src/utils/uriTemplateToForm.ts
21458
22884
  import { UriTemplate as UriTemplate2 } from "@modelcontextprotocol/client";
@@ -21485,7 +22911,7 @@ function uriTemplateToForm(uriTemplate, templateName) {
21485
22911
  }
21486
22912
 
21487
22913
  // src/components/ResourceTestModal.tsx
21488
- import { Fragment as Fragment10, jsx as jsx14, jsxs as jsxs13 } from "react/jsx-runtime";
22914
+ import { Fragment as Fragment11, jsx as jsx15, jsxs as jsxs14 } from "react/jsx-runtime";
21489
22915
  function getErrorMessage(error) {
21490
22916
  if (error instanceof Error) {
21491
22917
  return error.message;
@@ -21634,8 +23060,8 @@ function ResourceTestModal({
21634
23060
  };
21635
23061
  const modalWidth = terminalDimensions.width - 2;
21636
23062
  const modalHeight = terminalDimensions.height - 2;
21637
- return /* @__PURE__ */ jsx14(
21638
- Box25,
23063
+ return /* @__PURE__ */ jsx15(
23064
+ Box26,
21639
23065
  {
21640
23066
  position: "absolute",
21641
23067
  width: terminalDimensions.width,
@@ -21643,8 +23069,8 @@ function ResourceTestModal({
21643
23069
  flexDirection: "column",
21644
23070
  justifyContent: "center",
21645
23071
  alignItems: "center",
21646
- children: /* @__PURE__ */ jsxs13(
21647
- Box25,
23072
+ children: /* @__PURE__ */ jsxs14(
23073
+ Box26,
21648
23074
  {
21649
23075
  width: modalWidth,
21650
23076
  height: modalHeight,
@@ -21655,15 +23081,15 @@ function ResourceTestModal({
21655
23081
  paddingY: 1,
21656
23082
  backgroundColor: "black",
21657
23083
  children: [
21658
- /* @__PURE__ */ jsxs13(Box25, { flexShrink: 0, marginBottom: 1, children: [
21659
- /* @__PURE__ */ jsx14(Text22, { bold: true, color: "cyan", children: formStructure.title }),
21660
- /* @__PURE__ */ jsx14(Text22, { children: " " }),
21661
- /* @__PURE__ */ jsx14(Text22, { dimColor: true, children: "(Press ESC to close)" })
23084
+ /* @__PURE__ */ jsxs14(Box26, { flexShrink: 0, marginBottom: 1, children: [
23085
+ /* @__PURE__ */ jsx15(Text23, { bold: true, color: "cyan", children: formStructure.title }),
23086
+ /* @__PURE__ */ jsx15(Text23, { children: " " }),
23087
+ /* @__PURE__ */ jsx15(Text23, { dimColor: true, children: "(Press ESC to close)" })
21662
23088
  ] }),
21663
- /* @__PURE__ */ jsxs13(Box25, { flexGrow: 1, flexDirection: "column", overflow: "hidden", children: [
21664
- state === "form" && /* @__PURE__ */ jsxs13(Box25, { flexGrow: 1, flexDirection: "column", children: [
21665
- template.description && /* @__PURE__ */ jsx14(Box25, { marginBottom: 1, flexShrink: 0, children: /* @__PURE__ */ jsx14(Text22, { dimColor: true, children: template.description }) }),
21666
- /* @__PURE__ */ jsx14(
23089
+ /* @__PURE__ */ jsxs14(Box26, { flexGrow: 1, flexDirection: "column", overflow: "hidden", children: [
23090
+ state === "form" && /* @__PURE__ */ jsxs14(Box26, { flexGrow: 1, flexDirection: "column", children: [
23091
+ template.description && /* @__PURE__ */ jsx15(Box26, { marginBottom: 1, flexShrink: 0, children: /* @__PURE__ */ jsx15(Text23, { dimColor: true, children: template.description }) }),
23092
+ /* @__PURE__ */ jsx15(
21667
23093
  Form,
21668
23094
  {
21669
23095
  form: formStructure,
@@ -21671,34 +23097,34 @@ function ResourceTestModal({
21671
23097
  }
21672
23098
  )
21673
23099
  ] }),
21674
- state === "loading" && /* @__PURE__ */ jsx14(Box25, { flexGrow: 1, justifyContent: "center", alignItems: "center", children: /* @__PURE__ */ jsx14(Text22, { color: "yellow", children: "Reading resource..." }) }),
21675
- state === "results" && result && /* @__PURE__ */ jsx14(Box25, { flexGrow: 1, flexDirection: "column", overflow: "hidden", children: /* @__PURE__ */ jsxs13(ScrollView, { ref: scrollViewRef, children: [
21676
- /* @__PURE__ */ jsx14(Box25, { marginBottom: 1, flexShrink: 0, children: /* @__PURE__ */ jsxs13(Text22, { bold: true, color: "green", children: [
23100
+ state === "loading" && /* @__PURE__ */ jsx15(Box26, { flexGrow: 1, justifyContent: "center", alignItems: "center", children: /* @__PURE__ */ jsx15(Text23, { color: "yellow", children: "Reading resource..." }) }),
23101
+ state === "results" && result && /* @__PURE__ */ jsx15(Box26, { flexGrow: 1, flexDirection: "column", overflow: "hidden", children: /* @__PURE__ */ jsxs14(ScrollView, { ref: scrollViewRef, children: [
23102
+ /* @__PURE__ */ jsx15(Box26, { marginBottom: 1, flexShrink: 0, children: /* @__PURE__ */ jsxs14(Text23, { bold: true, color: "green", children: [
21677
23103
  "Duration: ",
21678
23104
  result.duration,
21679
23105
  "ms"
21680
23106
  ] }) }),
21681
- /* @__PURE__ */ jsxs13(Box25, { marginBottom: 1, flexShrink: 0, children: [
21682
- /* @__PURE__ */ jsxs13(Text22, { bold: true, color: "cyan", children: [
23107
+ /* @__PURE__ */ jsxs14(Box26, { marginBottom: 1, flexShrink: 0, children: [
23108
+ /* @__PURE__ */ jsxs14(Text23, { bold: true, color: "cyan", children: [
21683
23109
  "URI:",
21684
23110
  " "
21685
23111
  ] }),
21686
- /* @__PURE__ */ jsx14(Text22, { dimColor: true, children: result.uri })
23112
+ /* @__PURE__ */ jsx15(Text23, { dimColor: true, children: result.uri })
21687
23113
  ] }),
21688
- /* @__PURE__ */ jsxs13(Box25, { marginBottom: 1, flexShrink: 0, flexDirection: "column", children: [
21689
- /* @__PURE__ */ jsx14(Text22, { bold: true, color: "cyan", children: "Template Values:" }),
21690
- /* @__PURE__ */ jsx14(Box25, { paddingLeft: 2, children: /* @__PURE__ */ jsx14(Text22, { dimColor: true, children: JSON.stringify(result.input, null, 2) }) })
23114
+ /* @__PURE__ */ jsxs14(Box26, { marginBottom: 1, flexShrink: 0, flexDirection: "column", children: [
23115
+ /* @__PURE__ */ jsx15(Text23, { bold: true, color: "cyan", children: "Template Values:" }),
23116
+ /* @__PURE__ */ jsx15(Box26, { paddingLeft: 2, children: /* @__PURE__ */ jsx15(Text23, { dimColor: true, children: JSON.stringify(result.input, null, 2) }) })
21691
23117
  ] }),
21692
- result.error ? /* @__PURE__ */ jsxs13(Box25, { flexShrink: 0, flexDirection: "column", children: [
21693
- /* @__PURE__ */ jsx14(Box25, { marginTop: 1, flexShrink: 0, children: /* @__PURE__ */ jsx14(Text22, { bold: true, color: "red", children: "Error:" }) }),
21694
- /* @__PURE__ */ jsx14(Box25, { marginTop: 1, paddingLeft: 2, flexShrink: 0, children: /* @__PURE__ */ jsx14(Text22, { color: "red", children: String(result.error) }) }),
21695
- result.errorDetails != null ? /* @__PURE__ */ jsxs13(Fragment10, { children: [
21696
- /* @__PURE__ */ jsx14(Box25, { marginTop: 1, flexShrink: 0, children: /* @__PURE__ */ jsx14(Text22, { bold: true, color: "red", dimColor: true, children: "Error Details:" }) }),
21697
- /* @__PURE__ */ jsx14(Box25, { marginTop: 1, paddingLeft: 2, flexShrink: 0, children: /* @__PURE__ */ jsx14(Text22, { dimColor: true, children: JSON.stringify(result.errorDetails, null, 2) }) })
23118
+ result.error ? /* @__PURE__ */ jsxs14(Box26, { flexShrink: 0, flexDirection: "column", children: [
23119
+ /* @__PURE__ */ jsx15(Box26, { marginTop: 1, flexShrink: 0, children: /* @__PURE__ */ jsx15(Text23, { bold: true, color: "red", children: "Error:" }) }),
23120
+ /* @__PURE__ */ jsx15(Box26, { marginTop: 1, paddingLeft: 2, flexShrink: 0, children: /* @__PURE__ */ jsx15(Text23, { color: "red", children: String(result.error) }) }),
23121
+ result.errorDetails != null ? /* @__PURE__ */ jsxs14(Fragment11, { children: [
23122
+ /* @__PURE__ */ jsx15(Box26, { marginTop: 1, flexShrink: 0, children: /* @__PURE__ */ jsx15(Text23, { bold: true, color: "red", dimColor: true, children: "Error Details:" }) }),
23123
+ /* @__PURE__ */ jsx15(Box26, { marginTop: 1, paddingLeft: 2, flexShrink: 0, children: /* @__PURE__ */ jsx15(Text23, { dimColor: true, children: JSON.stringify(result.errorDetails, null, 2) }) })
21698
23124
  ] }) : null
21699
- ] }) : /* @__PURE__ */ jsxs13(Box25, { flexShrink: 0, flexDirection: "column", children: [
21700
- /* @__PURE__ */ jsx14(Text22, { bold: true, color: "green", children: "Resource Content:" }),
21701
- /* @__PURE__ */ jsx14(Box25, { paddingLeft: 2, children: /* @__PURE__ */ jsx14(Text22, { dimColor: true, children: JSON.stringify(result.output, null, 2) }) })
23125
+ ] }) : /* @__PURE__ */ jsxs14(Box26, { flexShrink: 0, flexDirection: "column", children: [
23126
+ /* @__PURE__ */ jsx15(Text23, { bold: true, color: "green", children: "Resource Content:" }),
23127
+ /* @__PURE__ */ jsx15(Box26, { paddingLeft: 2, children: /* @__PURE__ */ jsx15(Text23, { dimColor: true, children: JSON.stringify(result.output, null, 2) }) })
21702
23128
  ] })
21703
23129
  ] }) })
21704
23130
  ] })
@@ -21711,7 +23137,7 @@ function ResourceTestModal({
21711
23137
 
21712
23138
  // src/components/PromptTestModal.tsx
21713
23139
  import React28, { useState as useState16 } from "react";
21714
- import { Box as Box26, Text as Text23, useInput as useInput20 } from "ink";
23140
+ import { Box as Box27, Text as Text24, useInput as useInput20 } from "ink";
21715
23141
 
21716
23142
  // src/utils/promptArgsToForm.ts
21717
23143
  function promptArgsToForm(promptArguments, promptName) {
@@ -21747,7 +23173,7 @@ function promptArgsToForm(promptArguments, promptName) {
21747
23173
  }
21748
23174
 
21749
23175
  // src/components/PromptTestModal.tsx
21750
- import { Fragment as Fragment11, jsx as jsx15, jsxs as jsxs14 } from "react/jsx-runtime";
23176
+ import { Fragment as Fragment12, jsx as jsx16, jsxs as jsxs15 } from "react/jsx-runtime";
21751
23177
  function getErrorMessage2(error) {
21752
23178
  if (error instanceof Error) {
21753
23179
  return error.message;
@@ -21869,8 +23295,8 @@ function PromptTestModal({
21869
23295
  };
21870
23296
  const modalWidth = terminalDimensions.width - 2;
21871
23297
  const modalHeight = terminalDimensions.height - 2;
21872
- return /* @__PURE__ */ jsx15(
21873
- Box26,
23298
+ return /* @__PURE__ */ jsx16(
23299
+ Box27,
21874
23300
  {
21875
23301
  position: "absolute",
21876
23302
  width: terminalDimensions.width,
@@ -21878,8 +23304,8 @@ function PromptTestModal({
21878
23304
  flexDirection: "column",
21879
23305
  justifyContent: "center",
21880
23306
  alignItems: "center",
21881
- children: /* @__PURE__ */ jsxs14(
21882
- Box26,
23307
+ children: /* @__PURE__ */ jsxs15(
23308
+ Box27,
21883
23309
  {
21884
23310
  width: modalWidth,
21885
23311
  height: modalHeight,
@@ -21890,15 +23316,15 @@ function PromptTestModal({
21890
23316
  paddingY: 1,
21891
23317
  backgroundColor: "black",
21892
23318
  children: [
21893
- /* @__PURE__ */ jsxs14(Box26, { flexShrink: 0, marginBottom: 1, children: [
21894
- /* @__PURE__ */ jsx15(Text23, { bold: true, color: "cyan", children: formStructure.title }),
21895
- /* @__PURE__ */ jsx15(Text23, { children: " " }),
21896
- /* @__PURE__ */ jsx15(Text23, { dimColor: true, children: "(Press ESC to close)" })
23319
+ /* @__PURE__ */ jsxs15(Box27, { flexShrink: 0, marginBottom: 1, children: [
23320
+ /* @__PURE__ */ jsx16(Text24, { bold: true, color: "cyan", children: formStructure.title }),
23321
+ /* @__PURE__ */ jsx16(Text24, { children: " " }),
23322
+ /* @__PURE__ */ jsx16(Text24, { dimColor: true, children: "(Press ESC to close)" })
21897
23323
  ] }),
21898
- /* @__PURE__ */ jsxs14(Box26, { flexGrow: 1, flexDirection: "column", overflow: "hidden", children: [
21899
- state === "form" && /* @__PURE__ */ jsxs14(Box26, { flexGrow: 1, flexDirection: "column", children: [
21900
- prompt.description && /* @__PURE__ */ jsx15(Box26, { marginBottom: 1, flexShrink: 0, children: /* @__PURE__ */ jsx15(Text23, { dimColor: true, children: prompt.description }) }),
21901
- /* @__PURE__ */ jsx15(
23324
+ /* @__PURE__ */ jsxs15(Box27, { flexGrow: 1, flexDirection: "column", overflow: "hidden", children: [
23325
+ state === "form" && /* @__PURE__ */ jsxs15(Box27, { flexGrow: 1, flexDirection: "column", children: [
23326
+ prompt.description && /* @__PURE__ */ jsx16(Box27, { marginBottom: 1, flexShrink: 0, children: /* @__PURE__ */ jsx16(Text24, { dimColor: true, children: prompt.description }) }),
23327
+ /* @__PURE__ */ jsx16(
21902
23328
  Form,
21903
23329
  {
21904
23330
  form: formStructure,
@@ -21906,27 +23332,27 @@ function PromptTestModal({
21906
23332
  }
21907
23333
  )
21908
23334
  ] }),
21909
- state === "loading" && /* @__PURE__ */ jsx15(Box26, { flexGrow: 1, justifyContent: "center", alignItems: "center", children: /* @__PURE__ */ jsx15(Text23, { color: "yellow", children: "Getting prompt..." }) }),
21910
- state === "results" && result && /* @__PURE__ */ jsx15(Box26, { flexGrow: 1, flexDirection: "column", overflow: "hidden", children: /* @__PURE__ */ jsxs14(ScrollView, { ref: scrollViewRef, children: [
21911
- /* @__PURE__ */ jsx15(Box26, { marginBottom: 1, flexShrink: 0, children: /* @__PURE__ */ jsxs14(Text23, { bold: true, color: "green", children: [
23335
+ state === "loading" && /* @__PURE__ */ jsx16(Box27, { flexGrow: 1, justifyContent: "center", alignItems: "center", children: /* @__PURE__ */ jsx16(Text24, { color: "yellow", children: "Getting prompt..." }) }),
23336
+ state === "results" && result && /* @__PURE__ */ jsx16(Box27, { flexGrow: 1, flexDirection: "column", overflow: "hidden", children: /* @__PURE__ */ jsxs15(ScrollView, { ref: scrollViewRef, children: [
23337
+ /* @__PURE__ */ jsx16(Box27, { marginBottom: 1, flexShrink: 0, children: /* @__PURE__ */ jsxs15(Text24, { bold: true, color: "green", children: [
21912
23338
  "Duration: ",
21913
23339
  result.duration,
21914
23340
  "ms"
21915
23341
  ] }) }),
21916
- Object.keys(result.input).length > 0 && /* @__PURE__ */ jsxs14(Box26, { marginBottom: 1, flexShrink: 0, flexDirection: "column", children: [
21917
- /* @__PURE__ */ jsx15(Text23, { bold: true, color: "cyan", children: "Arguments:" }),
21918
- /* @__PURE__ */ jsx15(Box26, { paddingLeft: 2, children: /* @__PURE__ */ jsx15(Text23, { dimColor: true, children: JSON.stringify(result.input, null, 2) }) })
23342
+ Object.keys(result.input).length > 0 && /* @__PURE__ */ jsxs15(Box27, { marginBottom: 1, flexShrink: 0, flexDirection: "column", children: [
23343
+ /* @__PURE__ */ jsx16(Text24, { bold: true, color: "cyan", children: "Arguments:" }),
23344
+ /* @__PURE__ */ jsx16(Box27, { paddingLeft: 2, children: /* @__PURE__ */ jsx16(Text24, { dimColor: true, children: JSON.stringify(result.input, null, 2) }) })
21919
23345
  ] }),
21920
- result.error ? /* @__PURE__ */ jsxs14(Box26, { flexShrink: 0, flexDirection: "column", children: [
21921
- /* @__PURE__ */ jsx15(Box26, { marginTop: 1, flexShrink: 0, children: /* @__PURE__ */ jsx15(Text23, { bold: true, color: "red", children: "Error:" }) }),
21922
- /* @__PURE__ */ jsx15(Box26, { marginTop: 1, paddingLeft: 2, flexShrink: 0, children: /* @__PURE__ */ jsx15(Text23, { color: "red", children: String(result.error) }) }),
21923
- result.errorDetails != null ? /* @__PURE__ */ jsxs14(Fragment11, { children: [
21924
- /* @__PURE__ */ jsx15(Box26, { marginTop: 1, flexShrink: 0, children: /* @__PURE__ */ jsx15(Text23, { bold: true, color: "red", dimColor: true, children: "Error Details:" }) }),
21925
- /* @__PURE__ */ jsx15(Box26, { marginTop: 1, paddingLeft: 2, flexShrink: 0, children: /* @__PURE__ */ jsx15(Text23, { dimColor: true, children: JSON.stringify(result.errorDetails, null, 2) }) })
23346
+ result.error ? /* @__PURE__ */ jsxs15(Box27, { flexShrink: 0, flexDirection: "column", children: [
23347
+ /* @__PURE__ */ jsx16(Box27, { marginTop: 1, flexShrink: 0, children: /* @__PURE__ */ jsx16(Text24, { bold: true, color: "red", children: "Error:" }) }),
23348
+ /* @__PURE__ */ jsx16(Box27, { marginTop: 1, paddingLeft: 2, flexShrink: 0, children: /* @__PURE__ */ jsx16(Text24, { color: "red", children: String(result.error) }) }),
23349
+ result.errorDetails != null ? /* @__PURE__ */ jsxs15(Fragment12, { children: [
23350
+ /* @__PURE__ */ jsx16(Box27, { marginTop: 1, flexShrink: 0, children: /* @__PURE__ */ jsx16(Text24, { bold: true, color: "red", dimColor: true, children: "Error Details:" }) }),
23351
+ /* @__PURE__ */ jsx16(Box27, { marginTop: 1, paddingLeft: 2, flexShrink: 0, children: /* @__PURE__ */ jsx16(Text24, { dimColor: true, children: JSON.stringify(result.errorDetails, null, 2) }) })
21926
23352
  ] }) : null
21927
- ] }) : /* @__PURE__ */ jsxs14(Box26, { flexShrink: 0, flexDirection: "column", children: [
21928
- /* @__PURE__ */ jsx15(Text23, { bold: true, color: "green", children: "Prompt Messages:" }),
21929
- /* @__PURE__ */ jsx15(Box26, { paddingLeft: 2, children: /* @__PURE__ */ jsx15(Text23, { dimColor: true, children: JSON.stringify(result.output, null, 2) }) })
23353
+ ] }) : /* @__PURE__ */ jsxs15(Box27, { flexShrink: 0, flexDirection: "column", children: [
23354
+ /* @__PURE__ */ jsx16(Text24, { bold: true, color: "green", children: "Prompt Messages:" }),
23355
+ /* @__PURE__ */ jsx16(Box27, { paddingLeft: 2, children: /* @__PURE__ */ jsx16(Text24, { dimColor: true, children: JSON.stringify(result.output, null, 2) }) })
21930
23356
  ] })
21931
23357
  ] }) })
21932
23358
  ] })
@@ -21939,8 +23365,8 @@ function PromptTestModal({
21939
23365
 
21940
23366
  // src/components/DetailsModal.tsx
21941
23367
  import React29, { useRef as useRef14 } from "react";
21942
- import { Box as Box27, Text as Text24, useInput as useInput21 } from "ink";
21943
- import { jsx as jsx16, jsxs as jsxs15 } from "react/jsx-runtime";
23368
+ import { Box as Box28, Text as Text25, useInput as useInput21 } from "ink";
23369
+ import { jsx as jsx17, jsxs as jsxs16 } from "react/jsx-runtime";
21944
23370
  function DetailsModal({
21945
23371
  title,
21946
23372
  content,
@@ -21986,8 +23412,8 @@ function DetailsModal({
21986
23412
  );
21987
23413
  const modalWidth = terminalDimensions.width - 2;
21988
23414
  const modalHeight = terminalDimensions.height - 2;
21989
- return /* @__PURE__ */ jsx16(
21990
- Box27,
23415
+ return /* @__PURE__ */ jsx17(
23416
+ Box28,
21991
23417
  {
21992
23418
  position: "absolute",
21993
23419
  width: terminalDimensions.width,
@@ -21995,8 +23421,8 @@ function DetailsModal({
21995
23421
  flexDirection: "column",
21996
23422
  justifyContent: "center",
21997
23423
  alignItems: "center",
21998
- children: /* @__PURE__ */ jsxs15(
21999
- Box27,
23424
+ children: /* @__PURE__ */ jsxs16(
23425
+ Box28,
22000
23426
  {
22001
23427
  width: modalWidth,
22002
23428
  height: modalHeight,
@@ -22007,12 +23433,12 @@ function DetailsModal({
22007
23433
  paddingY: 1,
22008
23434
  backgroundColor: "black",
22009
23435
  children: [
22010
- /* @__PURE__ */ jsxs15(Box27, { flexShrink: 0, marginBottom: 1, children: [
22011
- /* @__PURE__ */ jsx16(Text24, { bold: true, color: "cyan", children: title }),
22012
- /* @__PURE__ */ jsx16(Text24, { children: " " }),
22013
- /* @__PURE__ */ jsx16(Text24, { dimColor: true, children: "(Press ESC to close)" })
23436
+ /* @__PURE__ */ jsxs16(Box28, { flexShrink: 0, marginBottom: 1, children: [
23437
+ /* @__PURE__ */ jsx17(Text25, { bold: true, color: "cyan", children: title }),
23438
+ /* @__PURE__ */ jsx17(Text25, { children: " " }),
23439
+ /* @__PURE__ */ jsx17(Text25, { dimColor: true, children: "(Press ESC to close)" })
22014
23440
  ] }),
22015
- /* @__PURE__ */ jsx16(Box27, { flexGrow: 1, flexDirection: "column", overflow: "hidden", children: /* @__PURE__ */ jsx16(ScrollView, { ref: scrollViewRef, children: content }) })
23441
+ /* @__PURE__ */ jsx17(Box28, { flexGrow: 1, flexDirection: "column", overflow: "hidden", children: /* @__PURE__ */ jsx17(ScrollView, { ref: scrollViewRef, children: content }) })
22016
23442
  ]
22017
23443
  }
22018
23444
  )
@@ -22021,7 +23447,7 @@ function DetailsModal({
22021
23447
  }
22022
23448
 
22023
23449
  // src/App.tsx
22024
- import { Fragment as Fragment12, jsx as jsx17, jsxs as jsxs16 } from "react/jsx-runtime";
23450
+ import { Fragment as Fragment13, jsx as jsx18, jsxs as jsxs17 } from "react/jsx-runtime";
22025
23451
  var APP_NAME = "MCP Inspector TUI";
22026
23452
  var APP_DESCRIPTION = "Terminal User Interface for the Model Context Protocol Inspector";
22027
23453
  var APP_VERSION = readInspectorVersion(import.meta.url);
@@ -22709,48 +24135,48 @@ function App({
22709
24135
  managedTools,
22710
24136
  inspectorStderrLogs
22711
24137
  ]);
22712
- const renderResourceDetails = (resource) => /* @__PURE__ */ jsxs16(Fragment12, { children: [
22713
- "uri" in resource && resource.description && /* @__PURE__ */ jsx17(Fragment12, { children: resource.description.split("\n").map((line, idx) => /* @__PURE__ */ jsx17(
22714
- Box28,
24138
+ const renderResourceDetails = (resource) => /* @__PURE__ */ jsxs17(Fragment13, { children: [
24139
+ "uri" in resource && resource.description && /* @__PURE__ */ jsx18(Fragment13, { children: resource.description.split("\n").map((line, idx) => /* @__PURE__ */ jsx18(
24140
+ Box29,
22715
24141
  {
22716
24142
  marginTop: idx === 0 ? 0 : 0,
22717
24143
  flexShrink: 0,
22718
- children: /* @__PURE__ */ jsx17(Text25, { dimColor: true, children: line })
24144
+ children: /* @__PURE__ */ jsx18(Text26, { dimColor: true, children: line })
22719
24145
  },
22720
24146
  `desc-${idx}`
22721
24147
  )) }),
22722
- "uri" in resource && resource.uri && /* @__PURE__ */ jsxs16(Box28, { marginTop: 1, flexShrink: 0, children: [
22723
- /* @__PURE__ */ jsx17(Text25, { bold: true, children: "URI:" }),
22724
- /* @__PURE__ */ jsx17(Box28, { paddingLeft: 2, children: /* @__PURE__ */ jsx17(Text25, { dimColor: true, children: resource.uri }) })
24148
+ "uri" in resource && resource.uri && /* @__PURE__ */ jsxs17(Box29, { marginTop: 1, flexShrink: 0, children: [
24149
+ /* @__PURE__ */ jsx18(Text26, { bold: true, children: "URI:" }),
24150
+ /* @__PURE__ */ jsx18(Box29, { paddingLeft: 2, children: /* @__PURE__ */ jsx18(Text26, { dimColor: true, children: resource.uri }) })
22725
24151
  ] }),
22726
- "mimeType" in resource && resource.mimeType && /* @__PURE__ */ jsxs16(Box28, { marginTop: 1, flexShrink: 0, children: [
22727
- /* @__PURE__ */ jsx17(Text25, { bold: true, children: "MIME Type:" }),
22728
- /* @__PURE__ */ jsx17(Box28, { paddingLeft: 2, children: /* @__PURE__ */ jsx17(Text25, { dimColor: true, children: resource.mimeType }) })
24152
+ "mimeType" in resource && resource.mimeType && /* @__PURE__ */ jsxs17(Box29, { marginTop: 1, flexShrink: 0, children: [
24153
+ /* @__PURE__ */ jsx18(Text26, { bold: true, children: "MIME Type:" }),
24154
+ /* @__PURE__ */ jsx18(Box29, { paddingLeft: 2, children: /* @__PURE__ */ jsx18(Text26, { dimColor: true, children: resource.mimeType }) })
22729
24155
  ] }),
22730
- /* @__PURE__ */ jsxs16(Box28, { marginTop: 1, flexShrink: 0, flexDirection: "column", children: [
22731
- /* @__PURE__ */ jsx17(Text25, { bold: true, children: "Full JSON:" }),
22732
- /* @__PURE__ */ jsx17(Box28, { paddingLeft: 2, children: /* @__PURE__ */ jsx17(Text25, { dimColor: true, children: JSON.stringify(resource, null, 2) }) })
24156
+ /* @__PURE__ */ jsxs17(Box29, { marginTop: 1, flexShrink: 0, flexDirection: "column", children: [
24157
+ /* @__PURE__ */ jsx18(Text26, { bold: true, children: "Full JSON:" }),
24158
+ /* @__PURE__ */ jsx18(Box29, { paddingLeft: 2, children: /* @__PURE__ */ jsx18(Text26, { dimColor: true, children: JSON.stringify(resource, null, 2) }) })
22733
24159
  ] })
22734
24160
  ] });
22735
- const renderPromptDetails = (prompt) => /* @__PURE__ */ jsxs16(Fragment12, { children: [
22736
- prompt.description && /* @__PURE__ */ jsx17(Fragment12, { children: prompt.description.split("\n").map((line, idx) => /* @__PURE__ */ jsx17(
22737
- Box28,
24161
+ const renderPromptDetails = (prompt) => /* @__PURE__ */ jsxs17(Fragment13, { children: [
24162
+ prompt.description && /* @__PURE__ */ jsx18(Fragment13, { children: prompt.description.split("\n").map((line, idx) => /* @__PURE__ */ jsx18(
24163
+ Box29,
22738
24164
  {
22739
24165
  marginTop: idx === 0 ? 0 : 0,
22740
24166
  flexShrink: 0,
22741
- children: /* @__PURE__ */ jsx17(Text25, { dimColor: true, children: line })
24167
+ children: /* @__PURE__ */ jsx18(Text26, { dimColor: true, children: line })
22742
24168
  },
22743
24169
  `desc-${idx}`
22744
24170
  )) }),
22745
- prompt.arguments && prompt.arguments.length > 0 && /* @__PURE__ */ jsxs16(Fragment12, { children: [
22746
- /* @__PURE__ */ jsx17(Box28, { marginTop: 1, flexShrink: 0, children: /* @__PURE__ */ jsx17(Text25, { bold: true, children: "Arguments:" }) }),
22747
- prompt.arguments.map((arg, idx) => /* @__PURE__ */ jsx17(
22748
- Box28,
24171
+ prompt.arguments && prompt.arguments.length > 0 && /* @__PURE__ */ jsxs17(Fragment13, { children: [
24172
+ /* @__PURE__ */ jsx18(Box29, { marginTop: 1, flexShrink: 0, children: /* @__PURE__ */ jsx18(Text26, { bold: true, children: "Arguments:" }) }),
24173
+ prompt.arguments.map((arg, idx) => /* @__PURE__ */ jsx18(
24174
+ Box29,
22749
24175
  {
22750
24176
  marginTop: 1,
22751
24177
  paddingLeft: 2,
22752
24178
  flexShrink: 0,
22753
- children: /* @__PURE__ */ jsxs16(Text25, { dimColor: true, children: [
24179
+ children: /* @__PURE__ */ jsxs17(Text26, { dimColor: true, children: [
22754
24180
  "- ",
22755
24181
  arg.name,
22756
24182
  ":",
@@ -22761,134 +24187,102 @@ function App({
22761
24187
  `arg-${idx}`
22762
24188
  ))
22763
24189
  ] }),
22764
- /* @__PURE__ */ jsxs16(Box28, { marginTop: 1, flexShrink: 0, flexDirection: "column", children: [
22765
- /* @__PURE__ */ jsx17(Text25, { bold: true, children: "Full JSON:" }),
22766
- /* @__PURE__ */ jsx17(Box28, { paddingLeft: 2, children: /* @__PURE__ */ jsx17(Text25, { dimColor: true, children: JSON.stringify(prompt, null, 2) }) })
24190
+ /* @__PURE__ */ jsxs17(Box29, { marginTop: 1, flexShrink: 0, flexDirection: "column", children: [
24191
+ /* @__PURE__ */ jsx18(Text26, { bold: true, children: "Full JSON:" }),
24192
+ /* @__PURE__ */ jsx18(Box29, { paddingLeft: 2, children: /* @__PURE__ */ jsx18(Text26, { dimColor: true, children: JSON.stringify(prompt, null, 2) }) })
22767
24193
  ] })
22768
24194
  ] });
22769
- const renderToolDetails = (tool) => /* @__PURE__ */ jsxs16(Fragment12, { children: [
22770
- tool.description && /* @__PURE__ */ jsx17(Fragment12, { children: tool.description.split("\n").map((line, idx) => /* @__PURE__ */ jsx17(
22771
- Box28,
24195
+ const renderToolDetails = (tool) => /* @__PURE__ */ jsxs17(Fragment13, { children: [
24196
+ tool.description && /* @__PURE__ */ jsx18(Fragment13, { children: tool.description.split("\n").map((line, idx) => /* @__PURE__ */ jsx18(
24197
+ Box29,
22772
24198
  {
22773
24199
  marginTop: idx === 0 ? 0 : 0,
22774
24200
  flexShrink: 0,
22775
- children: /* @__PURE__ */ jsx17(Text25, { dimColor: true, children: line })
24201
+ children: /* @__PURE__ */ jsx18(Text26, { dimColor: true, children: line })
22776
24202
  },
22777
24203
  `desc-${idx}`
22778
24204
  )) }),
22779
- tool.inputSchema && /* @__PURE__ */ jsxs16(Box28, { marginTop: 1, flexShrink: 0, flexDirection: "column", children: [
22780
- /* @__PURE__ */ jsx17(Text25, { bold: true, children: "Input Schema:" }),
22781
- /* @__PURE__ */ jsx17(Box28, { paddingLeft: 2, children: /* @__PURE__ */ jsx17(Text25, { dimColor: true, children: JSON.stringify(tool.inputSchema, null, 2) }) })
24205
+ tool.inputSchema && /* @__PURE__ */ jsxs17(Box29, { marginTop: 1, flexShrink: 0, flexDirection: "column", children: [
24206
+ /* @__PURE__ */ jsx18(Text26, { bold: true, children: "Input Schema:" }),
24207
+ /* @__PURE__ */ jsx18(Box29, { paddingLeft: 2, children: /* @__PURE__ */ jsx18(Text26, { dimColor: true, children: JSON.stringify(tool.inputSchema, null, 2) }) })
22782
24208
  ] }),
22783
- /* @__PURE__ */ jsxs16(Box28, { marginTop: 1, flexShrink: 0, flexDirection: "column", children: [
22784
- /* @__PURE__ */ jsx17(Text25, { bold: true, children: "Full JSON:" }),
22785
- /* @__PURE__ */ jsx17(Box28, { paddingLeft: 2, children: /* @__PURE__ */ jsx17(Text25, { dimColor: true, children: JSON.stringify(tool, null, 2) }) })
24209
+ /* @__PURE__ */ jsxs17(Box29, { marginTop: 1, flexShrink: 0, flexDirection: "column", children: [
24210
+ /* @__PURE__ */ jsx18(Text26, { bold: true, children: "Full JSON:" }),
24211
+ /* @__PURE__ */ jsx18(Box29, { paddingLeft: 2, children: /* @__PURE__ */ jsx18(Text26, { dimColor: true, children: JSON.stringify(tool, null, 2) }) })
22786
24212
  ] })
22787
24213
  ] });
22788
- const renderRequestDetails = (request) => /* @__PURE__ */ jsxs16(Fragment12, { children: [
22789
- /* @__PURE__ */ jsx17(Box28, { flexShrink: 0, children: /* @__PURE__ */ jsxs16(Text25, { bold: true, children: [
24214
+ const renderRequestDetails = (request) => /* @__PURE__ */ jsxs17(Fragment13, { children: [
24215
+ /* @__PURE__ */ jsx18(Box29, { flexShrink: 0, children: /* @__PURE__ */ jsxs17(Text26, { bold: true, children: [
22790
24216
  request.method,
22791
24217
  " ",
22792
24218
  request.url
22793
24219
  ] }) }),
22794
- /* @__PURE__ */ jsx17(Box28, { marginTop: 1, flexShrink: 0, children: /* @__PURE__ */ jsxs16(Text25, { bold: true, children: [
24220
+ /* @__PURE__ */ jsx18(Box29, { marginTop: 1, flexShrink: 0, children: /* @__PURE__ */ jsxs17(Text26, { bold: true, children: [
22795
24221
  "Category:",
22796
24222
  " ",
22797
- /* @__PURE__ */ jsx17(Text25, { children: request.category === "auth" ? "auth" : "transport" })
24223
+ /* @__PURE__ */ jsx18(Text26, { children: request.category === "auth" ? "auth" : "transport" })
22798
24224
  ] }) }),
22799
- request.responseStatus !== void 0 ? /* @__PURE__ */ jsx17(Box28, { marginTop: 1, flexShrink: 0, children: /* @__PURE__ */ jsxs16(Text25, { bold: true, children: [
24225
+ request.responseStatus !== void 0 ? /* @__PURE__ */ jsx18(Box29, { marginTop: 1, flexShrink: 0, children: /* @__PURE__ */ jsxs17(Text26, { bold: true, children: [
22800
24226
  "Status: ",
22801
24227
  request.responseStatus,
22802
24228
  " ",
22803
24229
  request.responseStatusText || ""
22804
- ] }) }) : request.error ? /* @__PURE__ */ jsx17(Box28, { marginTop: 1, flexShrink: 0, children: /* @__PURE__ */ jsxs16(Text25, { bold: true, color: "red", children: [
24230
+ ] }) }) : request.error ? /* @__PURE__ */ jsx18(Box29, { marginTop: 1, flexShrink: 0, children: /* @__PURE__ */ jsxs17(Text26, { bold: true, color: "red", children: [
22805
24231
  "Error: ",
22806
24232
  request.error
22807
24233
  ] }) }) : null,
22808
- request.duration !== void 0 && /* @__PURE__ */ jsx17(Box28, { marginTop: 1, flexShrink: 0, children: /* @__PURE__ */ jsxs16(Text25, { dimColor: true, children: [
24234
+ request.duration !== void 0 && /* @__PURE__ */ jsx18(Box29, { marginTop: 1, flexShrink: 0, children: /* @__PURE__ */ jsxs17(Text26, { dimColor: true, children: [
22809
24235
  request.timestamp.toLocaleTimeString(),
22810
24236
  " (",
22811
24237
  request.duration,
22812
24238
  "ms)"
22813
24239
  ] }) }),
22814
- /* @__PURE__ */ jsxs16(Box28, { marginTop: 1, flexShrink: 0, children: [
22815
- /* @__PURE__ */ jsx17(Text25, { bold: true, children: "Request Headers:" }),
22816
- Object.entries(request.requestHeaders).map(([key, value]) => /* @__PURE__ */ jsx17(Box28, { marginTop: 0, paddingLeft: 2, flexShrink: 0, children: /* @__PURE__ */ jsxs16(Text25, { dimColor: true, children: [
24240
+ /* @__PURE__ */ jsxs17(Box29, { marginTop: 1, flexShrink: 0, children: [
24241
+ /* @__PURE__ */ jsx18(Text26, { bold: true, children: "Request Headers:" }),
24242
+ Object.entries(request.requestHeaders).map(([key, value]) => /* @__PURE__ */ jsx18(Box29, { marginTop: 0, paddingLeft: 2, flexShrink: 0, children: /* @__PURE__ */ jsxs17(Text26, { dimColor: true, children: [
22817
24243
  key,
22818
24244
  ": ",
22819
24245
  value
22820
24246
  ] }) }, key))
22821
24247
  ] }),
22822
- request.requestBody && /* @__PURE__ */ jsxs16(Fragment12, { children: [
22823
- /* @__PURE__ */ jsx17(Box28, { marginTop: 1, flexShrink: 0, children: /* @__PURE__ */ jsx17(Text25, { bold: true, children: "Request Body:" }) }),
22824
- (() => {
22825
- try {
22826
- const parsed = JSON.parse(request.requestBody);
22827
- return JSON.stringify(parsed, null, 2).split("\n").map((line, idx) => /* @__PURE__ */ jsx17(
22828
- Box28,
22829
- {
22830
- marginTop: idx === 0 ? 1 : 0,
22831
- paddingLeft: 2,
22832
- flexShrink: 0,
22833
- children: /* @__PURE__ */ jsx17(Text25, { dimColor: true, children: line })
22834
- },
22835
- `req-body-${idx}`
22836
- ));
22837
- } catch {
22838
- return /* @__PURE__ */ jsx17(Box28, { marginTop: 1, paddingLeft: 2, flexShrink: 0, children: /* @__PURE__ */ jsx17(Text25, { dimColor: true, children: request.requestBody }) });
22839
- }
22840
- })()
24248
+ request.requestBody && /* @__PURE__ */ jsxs17(Fragment13, { children: [
24249
+ /* @__PURE__ */ jsx18(Box29, { marginTop: 1, flexShrink: 0, children: /* @__PURE__ */ jsx18(Text26, { bold: true, children: "Request Body:" }) }),
24250
+ /* @__PURE__ */ jsx18(BodyLines, { body: request.requestBody, keyPrefix: "req-body" })
22841
24251
  ] }),
22842
- request.responseHeaders && Object.keys(request.responseHeaders).length > 0 && /* @__PURE__ */ jsxs16(Fragment12, { children: [
22843
- /* @__PURE__ */ jsx17(Box28, { marginTop: 1, flexShrink: 0, children: /* @__PURE__ */ jsx17(Text25, { bold: true, children: "Response Headers:" }) }),
22844
- Object.entries(request.responseHeaders).map(([key, value]) => /* @__PURE__ */ jsx17(Box28, { marginTop: 0, paddingLeft: 2, flexShrink: 0, children: /* @__PURE__ */ jsxs16(Text25, { dimColor: true, children: [
24252
+ request.responseHeaders && Object.keys(request.responseHeaders).length > 0 && /* @__PURE__ */ jsxs17(Fragment13, { children: [
24253
+ /* @__PURE__ */ jsx18(Box29, { marginTop: 1, flexShrink: 0, children: /* @__PURE__ */ jsx18(Text26, { bold: true, children: "Response Headers:" }) }),
24254
+ Object.entries(request.responseHeaders).map(([key, value]) => /* @__PURE__ */ jsx18(Box29, { marginTop: 0, paddingLeft: 2, flexShrink: 0, children: /* @__PURE__ */ jsxs17(Text26, { dimColor: true, children: [
22845
24255
  key,
22846
24256
  ": ",
22847
24257
  value
22848
24258
  ] }) }, key))
22849
24259
  ] }),
22850
- request.responseBody && /* @__PURE__ */ jsxs16(Fragment12, { children: [
22851
- /* @__PURE__ */ jsx17(Box28, { marginTop: 1, flexShrink: 0, children: /* @__PURE__ */ jsx17(Text25, { bold: true, children: "Response Body:" }) }),
22852
- (() => {
22853
- try {
22854
- const parsed = JSON.parse(request.responseBody);
22855
- return JSON.stringify(parsed, null, 2).split("\n").map((line, idx) => /* @__PURE__ */ jsx17(
22856
- Box28,
22857
- {
22858
- marginTop: idx === 0 ? 1 : 0,
22859
- paddingLeft: 2,
22860
- flexShrink: 0,
22861
- children: /* @__PURE__ */ jsx17(Text25, { dimColor: true, children: line })
22862
- },
22863
- `resp-body-${idx}`
22864
- ));
22865
- } catch {
22866
- return /* @__PURE__ */ jsx17(Box28, { marginTop: 1, paddingLeft: 2, flexShrink: 0, children: /* @__PURE__ */ jsx17(Text25, { dimColor: true, children: request.responseBody }) });
22867
- }
22868
- })()
24260
+ request.responseBody && /* @__PURE__ */ jsxs17(Fragment13, { children: [
24261
+ /* @__PURE__ */ jsx18(Box29, { marginTop: 1, flexShrink: 0, children: /* @__PURE__ */ jsx18(Text26, { bold: true, children: "Response Body:" }) }),
24262
+ /* @__PURE__ */ jsx18(BodyLines, { body: request.responseBody, keyPrefix: "resp-body" })
22869
24263
  ] })
22870
24264
  ] });
22871
- const renderMessageDetails = (message) => /* @__PURE__ */ jsxs16(Fragment12, { children: [
22872
- /* @__PURE__ */ jsx17(Box28, { flexShrink: 0, children: /* @__PURE__ */ jsxs16(Text25, { bold: true, children: [
24265
+ const renderMessageDetails = (message) => /* @__PURE__ */ jsxs17(Fragment13, { children: [
24266
+ /* @__PURE__ */ jsx18(Box29, { flexShrink: 0, children: /* @__PURE__ */ jsxs17(Text26, { bold: true, children: [
22873
24267
  "Direction: ",
22874
24268
  message.direction
22875
24269
  ] }) }),
22876
- /* @__PURE__ */ jsx17(Box28, { marginTop: 1, flexShrink: 0, children: /* @__PURE__ */ jsxs16(Text25, { dimColor: true, children: [
24270
+ /* @__PURE__ */ jsx18(Box29, { marginTop: 1, flexShrink: 0, children: /* @__PURE__ */ jsxs17(Text26, { dimColor: true, children: [
22877
24271
  message.timestamp.toLocaleTimeString(),
22878
24272
  message.duration !== void 0 && ` (${message.duration}ms)`
22879
24273
  ] }) }),
22880
- message.direction === "request" ? /* @__PURE__ */ jsxs16(Fragment12, { children: [
22881
- /* @__PURE__ */ jsxs16(Box28, { marginTop: 1, flexShrink: 0, flexDirection: "column", children: [
22882
- /* @__PURE__ */ jsx17(Text25, { bold: true, children: "Request:" }),
22883
- /* @__PURE__ */ jsx17(Box28, { paddingLeft: 2, children: /* @__PURE__ */ jsx17(Text25, { dimColor: true, children: JSON.stringify(message.message, null, 2) }) })
24274
+ message.direction === "request" ? /* @__PURE__ */ jsxs17(Fragment13, { children: [
24275
+ /* @__PURE__ */ jsxs17(Box29, { marginTop: 1, flexShrink: 0, flexDirection: "column", children: [
24276
+ /* @__PURE__ */ jsx18(Text26, { bold: true, children: "Request:" }),
24277
+ /* @__PURE__ */ jsx18(Box29, { paddingLeft: 2, children: /* @__PURE__ */ jsx18(Text26, { dimColor: true, children: JSON.stringify(message.message, null, 2) }) })
22884
24278
  ] }),
22885
- message.response && /* @__PURE__ */ jsxs16(Box28, { marginTop: 1, flexShrink: 0, flexDirection: "column", children: [
22886
- /* @__PURE__ */ jsx17(Text25, { bold: true, children: "Response:" }),
22887
- /* @__PURE__ */ jsx17(Box28, { paddingLeft: 2, children: /* @__PURE__ */ jsx17(Text25, { dimColor: true, children: JSON.stringify(message.response, null, 2) }) })
24279
+ message.response && /* @__PURE__ */ jsxs17(Box29, { marginTop: 1, flexShrink: 0, flexDirection: "column", children: [
24280
+ /* @__PURE__ */ jsx18(Text26, { bold: true, children: "Response:" }),
24281
+ /* @__PURE__ */ jsx18(Box29, { paddingLeft: 2, children: /* @__PURE__ */ jsx18(Text26, { dimColor: true, children: JSON.stringify(message.response, null, 2) }) })
22888
24282
  ] })
22889
- ] }) : /* @__PURE__ */ jsxs16(Box28, { marginTop: 1, flexShrink: 0, flexDirection: "column", children: [
22890
- /* @__PURE__ */ jsx17(Text25, { bold: true, children: message.direction === "response" ? "Response:" : "Notification:" }),
22891
- /* @__PURE__ */ jsx17(Box28, { paddingLeft: 2, children: /* @__PURE__ */ jsx17(Text25, { dimColor: true, children: JSON.stringify(message.message, null, 2) }) })
24283
+ ] }) : /* @__PURE__ */ jsxs17(Box29, { marginTop: 1, flexShrink: 0, flexDirection: "column", children: [
24284
+ /* @__PURE__ */ jsx18(Text26, { bold: true, children: message.direction === "response" ? "Response:" : "Notification:" }),
24285
+ /* @__PURE__ */ jsx18(Box29, { paddingLeft: 2, children: /* @__PURE__ */ jsx18(Text26, { dimColor: true, children: JSON.stringify(message.message, null, 2) }) })
22892
24286
  ] })
22893
24287
  ] });
22894
24288
  useEffect14(() => {
@@ -23079,15 +24473,15 @@ function App({
23079
24473
  return "\u25CB";
23080
24474
  }
23081
24475
  };
23082
- return /* @__PURE__ */ jsxs16(
23083
- Box28,
24476
+ return /* @__PURE__ */ jsxs17(
24477
+ Box29,
23084
24478
  {
23085
24479
  flexDirection: "column",
23086
24480
  width: dimensions.width,
23087
24481
  height: dimensions.height,
23088
24482
  children: [
23089
- /* @__PURE__ */ jsxs16(
23090
- Box28,
24483
+ /* @__PURE__ */ jsxs17(
24484
+ Box29,
23091
24485
  {
23092
24486
  width: dimensions.width,
23093
24487
  height: headerHeight,
@@ -23099,29 +24493,29 @@ function App({
23099
24493
  justifyContent: "space-between",
23100
24494
  alignItems: "center",
23101
24495
  children: [
23102
- /* @__PURE__ */ jsxs16(Box28, { children: [
23103
- /* @__PURE__ */ jsx17(Text25, { bold: true, color: "cyan", children: APP_NAME }),
23104
- /* @__PURE__ */ jsxs16(Text25, { dimColor: true, children: [
24496
+ /* @__PURE__ */ jsxs17(Box29, { children: [
24497
+ /* @__PURE__ */ jsx18(Text26, { bold: true, color: "cyan", children: APP_NAME }),
24498
+ /* @__PURE__ */ jsxs17(Text26, { dimColor: true, children: [
23105
24499
  " - ",
23106
24500
  APP_DESCRIPTION
23107
24501
  ] })
23108
24502
  ] }),
23109
- /* @__PURE__ */ jsxs16(Text25, { dimColor: true, children: [
24503
+ /* @__PURE__ */ jsxs17(Text26, { dimColor: true, children: [
23110
24504
  "v",
23111
24505
  APP_VERSION
23112
24506
  ] })
23113
24507
  ]
23114
24508
  }
23115
24509
  ),
23116
- /* @__PURE__ */ jsxs16(
23117
- Box28,
24510
+ /* @__PURE__ */ jsxs17(
24511
+ Box29,
23118
24512
  {
23119
24513
  flexDirection: "row",
23120
24514
  height: availableHeight + tabsHeight,
23121
24515
  width: dimensions.width,
23122
24516
  children: [
23123
- /* @__PURE__ */ jsxs16(
23124
- Box28,
24517
+ /* @__PURE__ */ jsxs17(
24518
+ Box29,
23125
24519
  {
23126
24520
  width: serverListWidth,
23127
24521
  height: availableHeight + tabsHeight,
@@ -23133,43 +24527,43 @@ function App({
23133
24527
  flexDirection: "column",
23134
24528
  paddingX: 1,
23135
24529
  children: [
23136
- /* @__PURE__ */ jsx17(Box28, { marginTop: 1, marginBottom: 1, children: /* @__PURE__ */ jsx17(
23137
- Text25,
24530
+ /* @__PURE__ */ jsx18(Box29, { marginTop: 1, marginBottom: 1, children: /* @__PURE__ */ jsx18(
24531
+ Text26,
23138
24532
  {
23139
24533
  bold: true,
23140
24534
  backgroundColor: focus === "serverList" ? "yellow" : void 0,
23141
24535
  children: "MCP Servers"
23142
24536
  }
23143
24537
  ) }),
23144
- /* @__PURE__ */ jsx17(Box28, { flexDirection: "column", flexGrow: 1, children: serverNames.map((serverName) => {
24538
+ /* @__PURE__ */ jsx18(Box29, { flexDirection: "column", flexGrow: 1, children: serverNames.map((serverName) => {
23145
24539
  const isSelected = selectedServer === serverName;
23146
- return /* @__PURE__ */ jsx17(Box28, { paddingY: 0, children: /* @__PURE__ */ jsxs16(Text25, { children: [
24540
+ return /* @__PURE__ */ jsx18(Box29, { paddingY: 0, children: /* @__PURE__ */ jsxs17(Text26, { children: [
23147
24541
  isSelected ? "\u25B6 " : " ",
23148
24542
  serverName
23149
24543
  ] }) }, serverName);
23150
24544
  }) }),
23151
- /* @__PURE__ */ jsx17(
23152
- Box28,
24545
+ /* @__PURE__ */ jsx18(
24546
+ Box29,
23153
24547
  {
23154
24548
  flexShrink: 0,
23155
24549
  height: 1,
23156
24550
  justifyContent: "center",
23157
24551
  backgroundColor: "gray",
23158
- children: /* @__PURE__ */ jsx17(Text25, { bold: true, color: "white", children: "ESC to exit" })
24552
+ children: /* @__PURE__ */ jsx18(Text26, { bold: true, color: "white", children: "ESC to exit" })
23159
24553
  }
23160
24554
  )
23161
24555
  ]
23162
24556
  }
23163
24557
  ),
23164
- /* @__PURE__ */ jsxs16(
23165
- Box28,
24558
+ /* @__PURE__ */ jsxs17(
24559
+ Box29,
23166
24560
  {
23167
24561
  flexGrow: 1,
23168
24562
  height: availableHeight + tabsHeight,
23169
24563
  flexDirection: "column",
23170
24564
  children: [
23171
- /* @__PURE__ */ jsx17(
23172
- Box28,
24565
+ /* @__PURE__ */ jsx18(
24566
+ Box29,
23173
24567
  {
23174
24568
  width: contentWidth,
23175
24569
  borderStyle: "single",
@@ -23181,49 +24575,49 @@ function App({
23181
24575
  paddingY: 1,
23182
24576
  flexDirection: "column",
23183
24577
  flexShrink: 0,
23184
- children: /* @__PURE__ */ jsxs16(Box28, { flexDirection: "column", children: [
23185
- /* @__PURE__ */ jsxs16(
23186
- Box28,
24578
+ children: /* @__PURE__ */ jsxs17(Box29, { flexDirection: "column", children: [
24579
+ /* @__PURE__ */ jsxs17(
24580
+ Box29,
23187
24581
  {
23188
24582
  flexDirection: "row",
23189
24583
  justifyContent: "space-between",
23190
24584
  alignItems: "center",
23191
24585
  children: [
23192
- /* @__PURE__ */ jsx17(Text25, { bold: true, color: "cyan", children: selectedServer }),
23193
- /* @__PURE__ */ jsx17(Box28, { flexDirection: "row", alignItems: "center", gap: 1, children: currentServerState && /* @__PURE__ */ jsxs16(Fragment12, { children: [
23194
- /* @__PURE__ */ jsxs16(Text25, { color: getStatusColor(currentServerState.status), children: [
24586
+ /* @__PURE__ */ jsx18(Text26, { bold: true, color: "cyan", children: selectedServer }),
24587
+ /* @__PURE__ */ jsx18(Box29, { flexDirection: "row", alignItems: "center", gap: 1, children: currentServerState && /* @__PURE__ */ jsxs17(Fragment13, { children: [
24588
+ /* @__PURE__ */ jsxs17(Text26, { color: getStatusColor(currentServerState.status), children: [
23195
24589
  getStatusSymbol(currentServerState.status),
23196
24590
  " ",
23197
24591
  currentServerState.status
23198
24592
  ] }),
23199
- /* @__PURE__ */ jsx17(Text25, { children: " " }),
23200
- (currentServerState?.status === "disconnected" || currentServerState?.status === "error") && /* @__PURE__ */ jsxs16(Text25, { color: "cyan", bold: true, children: [
24593
+ /* @__PURE__ */ jsx18(Text26, { children: " " }),
24594
+ (currentServerState?.status === "disconnected" || currentServerState?.status === "error") && /* @__PURE__ */ jsxs17(Text26, { color: "cyan", bold: true, children: [
23201
24595
  "[",
23202
- /* @__PURE__ */ jsx17(Text25, { underline: true, children: "C" }),
24596
+ /* @__PURE__ */ jsx18(Text26, { underline: true, children: "C" }),
23203
24597
  "onnect]"
23204
24598
  ] }),
23205
- (currentServerState?.status === "connected" || currentServerState?.status === "connecting") && /* @__PURE__ */ jsxs16(Text25, { color: "red", bold: true, children: [
24599
+ (currentServerState?.status === "connected" || currentServerState?.status === "connecting") && /* @__PURE__ */ jsxs17(Text26, { color: "red", bold: true, children: [
23206
24600
  "[",
23207
- /* @__PURE__ */ jsx17(Text25, { underline: true, children: "D" }),
24601
+ /* @__PURE__ */ jsx18(Text26, { underline: true, children: "D" }),
23208
24602
  "isconnect]"
23209
24603
  ] })
23210
24604
  ] }) })
23211
24605
  ]
23212
24606
  }
23213
24607
  ),
23214
- oauthStatus === "authenticating" && /* @__PURE__ */ jsx17(Box28, { marginTop: 1, children: /* @__PURE__ */ jsx17(Text25, { dimColor: true, children: "OAuth: authenticating\u2026" }) }),
23215
- oauthStatus === "error" && oauthMessage && /* @__PURE__ */ jsx17(Box28, { marginTop: 1, children: /* @__PURE__ */ jsxs16(Text25, { color: "red", children: [
24608
+ oauthStatus === "authenticating" && /* @__PURE__ */ jsx18(Box29, { marginTop: 1, children: /* @__PURE__ */ jsx18(Text26, { dimColor: true, children: "OAuth: authenticating\u2026" }) }),
24609
+ oauthStatus === "error" && oauthMessage && /* @__PURE__ */ jsx18(Box29, { marginTop: 1, children: /* @__PURE__ */ jsxs17(Text26, { color: "red", children: [
23216
24610
  "OAuth: ",
23217
24611
  oauthMessage
23218
24612
  ] }) }),
23219
- disconnectError && /* @__PURE__ */ jsx17(Box28, { marginTop: 1, children: /* @__PURE__ */ jsxs16(Text25, { color: "red", children: [
24613
+ disconnectError && /* @__PURE__ */ jsx18(Box29, { marginTop: 1, children: /* @__PURE__ */ jsxs17(Text26, { color: "red", children: [
23220
24614
  "Disconnect failed: ",
23221
24615
  disconnectError
23222
24616
  ] }) })
23223
24617
  ] })
23224
24618
  }
23225
24619
  ),
23226
- /* @__PURE__ */ jsx17(
24620
+ /* @__PURE__ */ jsx18(
23227
24621
  Tabs,
23228
24622
  {
23229
24623
  activeTab,
@@ -23240,8 +24634,8 @@ function App({
23240
24634
  })() : false
23241
24635
  }
23242
24636
  ),
23243
- /* @__PURE__ */ jsxs16(
23244
- Box28,
24637
+ /* @__PURE__ */ jsxs17(
24638
+ Box29,
23245
24639
  {
23246
24640
  flexGrow: 1,
23247
24641
  minHeight: 6,
@@ -23251,7 +24645,7 @@ function App({
23251
24645
  borderRight: false,
23252
24646
  borderBottom: false,
23253
24647
  children: [
23254
- activeTab === "info" && /* @__PURE__ */ jsx17(
24648
+ activeTab === "info" && /* @__PURE__ */ jsx18(
23255
24649
  InfoTab,
23256
24650
  {
23257
24651
  serverName: selectedServer,
@@ -23263,7 +24657,7 @@ function App({
23263
24657
  focused: focus === "tabContentList" || focus === "tabContentDetails"
23264
24658
  }
23265
24659
  ),
23266
- activeTab === "auth" && selectedServer && selectedServerConfig && isOAuthCapableServerConfig(selectedServerConfig) ? /* @__PURE__ */ jsx17(
24660
+ activeTab === "auth" && selectedServer && selectedServerConfig && isOAuthCapableServerConfig(selectedServerConfig) ? /* @__PURE__ */ jsx18(
23267
24661
  AuthTab,
23268
24662
  {
23269
24663
  serverName: selectedServer,
@@ -23361,7 +24755,7 @@ function App({
23361
24755
  connectionStatus: inspectorStatus
23362
24756
  }
23363
24757
  ) : null,
23364
- activeTab === "resources" && currentServerState?.status === "connected" && selectedInspectorClient ? /* @__PURE__ */ jsx17(
24758
+ activeTab === "resources" && currentServerState?.status === "connected" && selectedInspectorClient ? /* @__PURE__ */ jsx18(
23365
24759
  ResourcesTab,
23366
24760
  {
23367
24761
  resources: currentServerState.resources,
@@ -23387,7 +24781,7 @@ function App({
23387
24781
  modalOpen: !!(toolTestModal || resourceTestModal || promptTestModal || detailsModal)
23388
24782
  },
23389
24783
  `resources-${selectedServer}`
23390
- ) : activeTab === "skills" && currentServerState?.status === "connected" && selectedInspectorClient ? /* @__PURE__ */ jsx17(
24784
+ ) : activeTab === "skills" && currentServerState?.status === "connected" && selectedInspectorClient ? /* @__PURE__ */ jsx18(
23391
24785
  SkillsTab,
23392
24786
  {
23393
24787
  skills: managedSkills,
@@ -23401,7 +24795,7 @@ function App({
23401
24795
  modalOpen: !!(toolTestModal || resourceTestModal || promptTestModal || detailsModal)
23402
24796
  },
23403
24797
  `skills-${selectedServer}`
23404
- ) : activeTab === "prompts" && currentServerState?.status === "connected" && selectedInspectorClient ? /* @__PURE__ */ jsx17(
24798
+ ) : activeTab === "prompts" && currentServerState?.status === "connected" && selectedInspectorClient ? /* @__PURE__ */ jsx18(
23405
24799
  PromptsTab,
23406
24800
  {
23407
24801
  prompts: currentServerState.prompts,
@@ -23424,7 +24818,7 @@ function App({
23424
24818
  modalOpen: !!(toolTestModal || resourceTestModal || promptTestModal || detailsModal)
23425
24819
  },
23426
24820
  `prompts-${selectedServer}`
23427
- ) : activeTab === "tools" && currentServerState?.status === "connected" && selectedInspectorClient ? /* @__PURE__ */ jsx17(
24821
+ ) : activeTab === "tools" && currentServerState?.status === "connected" && selectedInspectorClient ? /* @__PURE__ */ jsx18(
23428
24822
  ToolsTab,
23429
24823
  {
23430
24824
  tools: currentServerState.tools,
@@ -23444,7 +24838,7 @@ function App({
23444
24838
  modalOpen: !!(toolTestModal || detailsModal)
23445
24839
  },
23446
24840
  `tools-${selectedServer}`
23447
- ) : activeTab === "messages" && selectedInspectorClient ? /* @__PURE__ */ jsx17(
24841
+ ) : activeTab === "messages" && selectedInspectorClient ? /* @__PURE__ */ jsx18(
23448
24842
  HistoryTab,
23449
24843
  {
23450
24844
  serverName: selectedServer,
@@ -23462,7 +24856,7 @@ function App({
23462
24856
  });
23463
24857
  }
23464
24858
  }
23465
- ) : activeTab === "requests" && selectedInspectorClient && (inspectorStatus === "connected" || inspectorFetchRequests.length > 0) ? /* @__PURE__ */ jsx17(
24859
+ ) : activeTab === "requests" && selectedInspectorClient && (inspectorStatus === "connected" || inspectorFetchRequests.length > 0) ? /* @__PURE__ */ jsx18(
23466
24860
  RequestsTab,
23467
24861
  {
23468
24862
  serverName: selectedServer,
@@ -23479,7 +24873,7 @@ function App({
23479
24873
  });
23480
24874
  }
23481
24875
  }
23482
- ) : activeTab === "logging" && selectedInspectorClient ? /* @__PURE__ */ jsx17(
24876
+ ) : activeTab === "logging" && selectedInspectorClient ? /* @__PURE__ */ jsx18(
23483
24877
  NotificationsTab,
23484
24878
  {
23485
24879
  stderrLogs: inspectorStderrLogs,
@@ -23498,7 +24892,7 @@ function App({
23498
24892
  ]
23499
24893
  }
23500
24894
  ),
23501
- toolTestModal && /* @__PURE__ */ jsx17(
24895
+ toolTestModal && /* @__PURE__ */ jsx18(
23502
24896
  ToolTestModal,
23503
24897
  {
23504
24898
  tool: toolTestModal.tool,
@@ -23512,7 +24906,7 @@ function App({
23512
24906
  }
23513
24907
  }
23514
24908
  ),
23515
- resourceTestModal && /* @__PURE__ */ jsx17(
24909
+ resourceTestModal && /* @__PURE__ */ jsx18(
23516
24910
  ResourceTestModal,
23517
24911
  {
23518
24912
  template: resourceTestModal.template,
@@ -23526,7 +24920,7 @@ function App({
23526
24920
  }
23527
24921
  }
23528
24922
  ),
23529
- promptTestModal && /* @__PURE__ */ jsx17(
24923
+ promptTestModal && /* @__PURE__ */ jsx18(
23530
24924
  PromptTestModal,
23531
24925
  {
23532
24926
  prompt: promptTestModal.prompt,
@@ -23540,7 +24934,7 @@ function App({
23540
24934
  }
23541
24935
  }
23542
24936
  ),
23543
- detailsModal && /* @__PURE__ */ jsx17(
24937
+ detailsModal && /* @__PURE__ */ jsx18(
23544
24938
  DetailsModal,
23545
24939
  {
23546
24940
  title: detailsModal.title,
@@ -23557,7 +24951,7 @@ function App({
23557
24951
  var App_default = App;
23558
24952
 
23559
24953
  // tui.tsx
23560
- import { jsx as jsx18 } from "react/jsx-runtime";
24954
+ import { jsx as jsx19 } from "react/jsx-runtime";
23561
24955
  async function runTui(args) {
23562
24956
  const program = new Command();
23563
24957
  program.name("mcp-inspector-tui").description("Terminal UI for MCP Inspector").option(
@@ -23646,7 +25040,7 @@ async function runTui(args) {
23646
25040
  process.stdout.write("\x1B[?1049h");
23647
25041
  }
23648
25042
  const instance = render2(
23649
- /* @__PURE__ */ jsx18(
25043
+ /* @__PURE__ */ jsx19(
23650
25044
  App_default,
23651
25045
  {
23652
25046
  mcpServers,