@modelcontextprotocol/inspector 2.8.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
  );
@@ -2208,6 +2212,19 @@ import { readFileSync as readFileSync2, statSync as statSync2 } from "fs";
2208
2212
  import * as fs3 from "fs/promises";
2209
2213
  import * as path3 from "path";
2210
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
+
2211
2228
  // ../../core/auth/node/file-lock.ts
2212
2229
  import nodeFs, { statSync, rmdirSync } from "fs";
2213
2230
  import * as fs2 from "fs/promises";
@@ -2266,6 +2283,12 @@ var SecretStoreUnavailableError = class extends Error {
2266
2283
  this.name = "SecretStoreUnavailableError";
2267
2284
  }
2268
2285
  };
2286
+ var SecretFileLockHeldError = class extends SecretStoreUnavailableError {
2287
+ constructor(message, options) {
2288
+ super(message, options);
2289
+ this.name = "SecretFileLockHeldError";
2290
+ }
2291
+ };
2269
2292
  var KeychainUnavailableError = class extends SecretStoreUnavailableError {
2270
2293
  constructor(cause) {
2271
2294
  const message = cause instanceof Error ? cause.message : String(cause);
@@ -2296,6 +2319,7 @@ async function probeKeyringAvailable() {
2296
2319
  try {
2297
2320
  const entry = new keyring.mod.AsyncEntry(SERVICE_NAME, PROBE_ACCOUNT);
2298
2321
  await entry.getPassword();
2322
+ await keyring.mod.findCredentialsAsync(SERVICE_NAME);
2299
2323
  return { available: true };
2300
2324
  } catch (err) {
2301
2325
  return {
@@ -2305,6 +2329,7 @@ async function probeKeyringAvailable() {
2305
2329
  }
2306
2330
  }
2307
2331
  var PROBE_ACCOUNT = "__inspector:probe";
2332
+ var isNoEntryError = (err) => err instanceof Error && /no (matching )?entry/i.test(err.message);
2308
2333
  var KeyringSecretStore = class {
2309
2334
  /**
2310
2335
  * The intolerant read. Same lookup as {@link get}, minus the catch — a
@@ -2356,23 +2381,27 @@ var KeyringSecretStore = class {
2356
2381
  async delete(serverId, field) {
2357
2382
  try {
2358
2383
  const keyring = await loadKeyring();
2359
- if (!keyring.ok) return;
2384
+ if (!keyring.ok) throw new KeychainUnavailableError(keyring.err);
2360
2385
  const entry = new keyring.mod.AsyncEntry(
2361
2386
  SERVICE_NAME,
2362
2387
  buildAccount(serverId, field)
2363
2388
  );
2364
2389
  await entry.deleteCredential();
2365
- } catch {
2390
+ } catch (err) {
2391
+ if (isNoEntryError(err)) return;
2392
+ if (err instanceof KeychainUnavailableError) throw err;
2393
+ throw new KeychainUnavailableError(err);
2366
2394
  }
2367
2395
  }
2368
2396
  async deleteAllForServer(serverId) {
2369
2397
  let creds;
2370
2398
  try {
2371
2399
  const keyring = await loadKeyring();
2372
- if (!keyring.ok) return;
2400
+ if (!keyring.ok) throw new KeychainUnavailableError(keyring.err);
2373
2401
  creds = await keyring.mod.findCredentialsAsync(SERVICE_NAME);
2374
- } catch {
2375
- return;
2402
+ } catch (err) {
2403
+ if (err instanceof KeychainUnavailableError) throw err;
2404
+ throw new KeychainUnavailableError(err);
2376
2405
  }
2377
2406
  const prefix = `${serverId}:`;
2378
2407
  for (const c of creds) {
@@ -2386,6 +2415,25 @@ var KeyringSecretStore = class {
2386
2415
  async function secretStoreGetStrict(store, serverId, field) {
2387
2416
  return store.getStrict ? store.getStrict(serverId, field) : store.get(serverId, field);
2388
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
+ }
2389
2437
  async function secretStoreGetMany(store, requests) {
2390
2438
  if (store.getMany) return store.getMany(requests);
2391
2439
  const out = {};
@@ -2398,16 +2446,44 @@ async function secretStoreGetMany(store, requests) {
2398
2446
  );
2399
2447
  const found = {};
2400
2448
  for (const [field, value] of entries) {
2401
- 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);
2402
2472
  }
2403
- out[serverId] = found;
2473
+ setOwnEntry(out, serverId, found);
2404
2474
  })
2405
2475
  );
2406
2476
  return out;
2407
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
+ }
2408
2484
  async function secretStoreSetMany(store, serverId, values) {
2409
2485
  if (store.setMany) return store.setMany(serverId, values);
2410
- await Promise.all(
2486
+ await settleStoreMutations(
2411
2487
  Object.entries(values).map(
2412
2488
  ([field, value]) => store.set(serverId, field, value)
2413
2489
  )
@@ -2576,7 +2652,7 @@ async function openSecretFileLock(filePath) {
2576
2652
  });
2577
2653
  } catch (err) {
2578
2654
  if (isStuckOrHeld(err, lockPathOf(target))) {
2579
- throw new SecretStoreUnavailableError(
2655
+ throw new SecretFileLockHeldError(
2580
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.`
2581
2657
  );
2582
2658
  }
@@ -2685,6 +2761,13 @@ function resolveSecretPassphrase(env2 = process.env, secretFilePath) {
2685
2761
  return { passphrase };
2686
2762
  }
2687
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
+ }
2688
2771
  function asSecretMap(value, filePath) {
2689
2772
  if (typeof value !== "object" || value === null || Array.isArray(value)) {
2690
2773
  throw new SecretStoreUnavailableError(
@@ -2943,7 +3026,9 @@ var FileSecretStore = class {
2943
3026
  let plain;
2944
3027
  try {
2945
3028
  const key = await this.deriveKey(parsed.kdf);
2946
- const decipher = crypto2.createDecipheriv(CIPHER, key, parts.iv);
3029
+ const decipher = crypto2.createDecipheriv(CIPHER, key, parts.iv, {
3030
+ authTagLength: GCM_TAG_BYTES
3031
+ });
2947
3032
  decipher.setAuthTag(parts.tag);
2948
3033
  plain = Buffer.concat([
2949
3034
  decipher.update(parts.body),
@@ -2977,7 +3062,9 @@ var FileSecretStore = class {
2977
3062
  };
2978
3063
  const key = await this.deriveKey(kdf);
2979
3064
  const iv = crypto2.randomBytes(IV_BYTES);
2980
- const cipher = crypto2.createCipheriv(CIPHER, key, iv);
3065
+ const cipher = crypto2.createCipheriv(CIPHER, key, iv, {
3066
+ authTagLength: GCM_TAG_BYTES
3067
+ });
2981
3068
  const body = Buffer.concat([
2982
3069
  cipher.update(JSON.stringify(map), "utf-8"),
2983
3070
  cipher.final()
@@ -3142,9 +3229,36 @@ var FileSecretStore = class {
3142
3229
  const found = {};
3143
3230
  for (const field of fields) {
3144
3231
  const value = map?.[buildAccount2(serverId, field)];
3145
- if (value !== void 0) found[field] = value;
3232
+ if (value !== void 0) setOwnEntry(found, field, value);
3233
+ }
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);
3146
3260
  }
3147
- out[serverId] = found;
3261
+ setOwnEntry(out, serverId, found);
3148
3262
  }
3149
3263
  return out;
3150
3264
  }
@@ -3188,6 +3302,9 @@ var FileSecretStore = class {
3188
3302
  */
3189
3303
  async setMany(serverId, values) {
3190
3304
  if (Object.keys(values).length === 0) return;
3305
+ for (const [field, value] of Object.entries(values)) {
3306
+ assertSecretString(field, value);
3307
+ }
3191
3308
  await this.serialize(
3192
3309
  () => this.mutate((map) => {
3193
3310
  const next = { ...map };
@@ -3199,6 +3316,7 @@ var FileSecretStore = class {
3199
3316
  );
3200
3317
  }
3201
3318
  async set(serverId, field, value) {
3319
+ assertSecretString(field, value);
3202
3320
  await this.serialize(
3203
3321
  () => this.mutate((map) => ({
3204
3322
  ...map,
@@ -3214,9 +3332,11 @@ var FileSecretStore = class {
3214
3332
  await this.deleteWhere((key) => key.startsWith(prefix));
3215
3333
  }
3216
3334
  /**
3217
- * Shared delete body. Silent on every failure, matching the keyring store:
3218
- * every reason a delete can fail collapses to "the entry isn't there
3219
- * 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.
3220
3340
  */
3221
3341
  async deleteWhere(match) {
3222
3342
  try {
@@ -3229,7 +3349,12 @@ var FileSecretStore = class {
3229
3349
  return next;
3230
3350
  })
3231
3351
  );
3232
- } 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
+ );
3233
3358
  }
3234
3359
  }
3235
3360
  };
@@ -3605,6 +3730,9 @@ var DeferredSecretStore = class {
3605
3730
  async getMany(requests) {
3606
3731
  return secretStoreGetMany(await this.target(), requests);
3607
3732
  }
3733
+ async getManyStrict(requests) {
3734
+ return secretStoreGetManyStrict(await this.target(), requests);
3735
+ }
3608
3736
  async get(serverId, field) {
3609
3737
  return (await this.target()).get(serverId, field);
3610
3738
  }
@@ -3822,12 +3950,31 @@ function redactJsonValue(value) {
3822
3950
  }
3823
3951
  return value;
3824
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
+ }
3825
3972
  function redactBody(body, contentType) {
3826
3973
  if (!body) return body;
3827
3974
  const type = (contentType ?? "").toLowerCase();
3828
3975
  if (type.includes("application/x-www-form-urlencoded")) {
3829
3976
  try {
3830
- const params = new URLSearchParams(body);
3977
+ const params = new URLSearchParams(joinSensitiveContinuations(body));
3831
3978
  let changed = false;
3832
3979
  for (const key of new Set(params.keys())) {
3833
3980
  if (isSensitiveField(key)) {
@@ -4861,6 +5008,23 @@ function mergeSecretsIntoClientConfig(config, secrets) {
4861
5008
  }
4862
5009
 
4863
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
+ }
4864
5028
  async function readIdpSecretFromKeychain(secretStore) {
4865
5029
  const secret = await secretStore.get(
4866
5030
  CLIENT_KEYCHAIN_ID,
@@ -4870,29 +5034,39 @@ async function readIdpSecretFromKeychain(secretStore) {
4870
5034
  return { [SECRET_FIELD_IDP_CLIENT_SECRET]: secret };
4871
5035
  }
4872
5036
  async function migrateClientPlaintextSecret(filePath, config, secretStore) {
4873
- const { stripped, secrets } = extractSecretsFromClientConfig(config);
4874
- const value = secrets[SECRET_FIELD_IDP_CLIENT_SECRET];
4875
- if (!value) return config;
4876
5037
  try {
4877
- const existing = await secretStoreGetStrict(
4878
- secretStore,
4879
- CLIENT_KEYCHAIN_ID,
4880
- SECRET_FIELD_IDP_CLIENT_SECRET
4881
- );
4882
- if (existing === null) {
4883
- await secretStore.set(
4884
- CLIENT_KEYCHAIN_ID,
4885
- SECRET_FIELD_IDP_CLIENT_SECRET,
4886
- value
4887
- );
4888
- }
4889
- if (!await secretStoreIsDurable(secretStore)) return config;
4890
- await writeStoreFile(filePath, serializeStore(stripped));
4891
- 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
+ });
4892
5068
  } catch (err) {
4893
- if (err instanceof SecretStoreUnavailableError) {
4894
- return config;
4895
- }
5069
+ if (err instanceof SecretFileLockHeldError) return config;
4896
5070
  throw err;
4897
5071
  }
4898
5072
  }
@@ -5095,7 +5269,7 @@ import {
5095
5269
  useCallback as useCallback14,
5096
5270
  useRef as useRef15
5097
5271
  } from "react";
5098
- 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";
5099
5273
 
5100
5274
  // ../../core/mcp/inspectorClient.ts
5101
5275
  import { Client } from "@modelcontextprotocol/client";
@@ -5486,10 +5660,13 @@ var ADVERTISABLE_EXTENSIONS = [
5486
5660
  {
5487
5661
  key: UI_EXTENSION_KEY,
5488
5662
  label: "MCP Apps UI (io.modelcontextprotocol/ui)",
5489
- // The MCP Apps UI extension. The Inspector always renders App tools, so it
5490
- // advertises this by default with the App resource MIME type it supports —
5491
- // 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).
5492
5668
  defaultAdvertised: true,
5669
+ requiresAppRenderer: true,
5493
5670
  advertisement: { mimeTypes: [MCP_APP_MIME_TYPE] }
5494
5671
  },
5495
5672
  {
@@ -5505,10 +5682,13 @@ var ADVERTISABLE_EXTENSIONS = [
5505
5682
  defaultAdvertised: true
5506
5683
  }
5507
5684
  ];
5685
+ function isAdvertisedByDefault(ext, rendersApps) {
5686
+ return ext.defaultAdvertised && (!ext.requiresAppRenderer || rendersApps);
5687
+ }
5508
5688
  function buildClientExtensions(input) {
5509
5689
  const map = {};
5510
5690
  for (const ext of ADVERTISABLE_EXTENSIONS) {
5511
- const advertised = input.advertised?.[ext.key] ?? ext.defaultAdvertised;
5691
+ const advertised = input.advertised?.[ext.key] ?? isAdvertisedByDefault(ext, input.rendersApps === true);
5512
5692
  if (advertised) {
5513
5693
  map[ext.key] = ext.advertisement ? structuredClone(ext.advertisement) : {};
5514
5694
  }
@@ -6498,6 +6678,14 @@ function exemptMcpEndpoint(getServerUrl, negotiatesEndpoint) {
6498
6678
  };
6499
6679
  }
6500
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
+ }
6501
6689
  function requestHeadersOf(input, init) {
6502
6690
  if (init?.headers) return new Headers(init.headers);
6503
6691
  if (typeof input !== "string" && !(input instanceof URL)) {
@@ -6555,7 +6743,7 @@ function withOAuthRequestTimeout(fetchFn, timeoutMs = DEFAULT_OAUTH_REQUEST_TIME
6555
6743
  }
6556
6744
  });
6557
6745
  const nextInit = { ...init, signal };
6558
- REQUEST_DEADLINES.set(nextInit, budget);
6746
+ stampRequestDeadline(nextInit, budget);
6559
6747
  let settled;
6560
6748
  let drainReader;
6561
6749
  try {
@@ -7482,7 +7670,7 @@ async function collectGrants(snapshot) {
7482
7670
  return { grants, failures };
7483
7671
  }
7484
7672
  async function parseTokens(raw) {
7485
- 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);
7486
7674
  }
7487
7675
  async function parseClient(raw) {
7488
7676
  return raw === void 0 || raw === null ? void 0 : await OAuthClientInformationSchema.parseAsync(raw);
@@ -9263,6 +9451,14 @@ function progressTokenOf(message) {
9263
9451
  }
9264
9452
  return void 0;
9265
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
+ }
9266
9462
 
9267
9463
  // ../../core/mcp/remote/remoteClientTransport.ts
9268
9464
  var DEFAULT_SSE_RESPONSE_TIMEOUT_MS = 6e4;
@@ -9739,8 +9935,8 @@ var RemoteClientTransport = class {
9739
9935
  });
9740
9936
  }
9741
9937
  /** Re-arm a pending request's SSE wait timeout on a matching progress note. */
9742
- resetSseResponseWait(requestId) {
9743
- this.sseResponseWaits.get(requestId)?.resetTimeout();
9938
+ resetSseResponseWait(progressToken) {
9939
+ waitForProgressToken(this.sseResponseWaits, progressToken)?.resetTimeout();
9744
9940
  }
9745
9941
  async postSend(message, options, retryCount) {
9746
9942
  const requestId = requestIdForMessage(message);
@@ -9945,6 +10141,11 @@ var InspectorClient = class _InspectorClient extends InspectorClientEventTarget
9945
10141
  requestTimeout;
9946
10142
  defaultMetadata;
9947
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;
9948
10149
  versionNegotiation;
9949
10150
  status = "disconnected";
9950
10151
  // True only while an explicit disconnect() owns the teardown. close() can
@@ -10299,6 +10500,10 @@ var InspectorClient = class _InspectorClient extends InspectorClientEventTarget
10299
10500
  const advertisedExtensions = buildClientExtensions({
10300
10501
  enterpriseManaged: options.oauth?.enterpriseManaged ?? false,
10301
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,
10302
10507
  // Read off the built `capabilities.elicitation.form` rather than
10303
10508
  // re-deriving from `options.elicit`: the nested MCP Apps `elicitation`
10304
10509
  // setting must never be advertised without the core form capability it
@@ -10724,6 +10929,7 @@ var InspectorClient = class _InspectorClient extends InspectorClientEventTarget
10724
10929
  }
10725
10930
  this.baseTransport = null;
10726
10931
  this.transport = null;
10932
+ this.transportSettings = void 0;
10727
10933
  this.transportHasAuthProvider = false;
10728
10934
  }
10729
10935
  /**
@@ -11197,6 +11403,7 @@ var InspectorClient = class _InspectorClient extends InspectorClientEventTarget
11197
11403
  transportOptions
11198
11404
  );
11199
11405
  this.baseTransport = baseTransport;
11406
+ this.transportSettings = transportOptions.settings;
11200
11407
  if (this.directAuthRecovery) {
11201
11408
  this.directAuthRecoveryActive = !(baseTransport instanceof RemoteClientTransport);
11202
11409
  }
@@ -11398,6 +11605,7 @@ var InspectorClient = class _InspectorClient extends InspectorClientEventTarget
11398
11605
  }
11399
11606
  this.baseTransport = null;
11400
11607
  this.transport = null;
11608
+ this.transportSettings = void 0;
11401
11609
  this.transportHasAuthProvider = false;
11402
11610
  this.clearPendingPeerRequests();
11403
11611
  if (this.status !== "disconnected") {
@@ -12130,6 +12338,13 @@ var InspectorClient = class _InspectorClient extends InspectorClientEventTarget
12130
12338
  getClientCapabilities() {
12131
12339
  return this.clientCapabilities;
12132
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
+ }
12133
12348
  /**
12134
12349
  * Get server info (name, version)
12135
12350
  */
@@ -12181,6 +12396,16 @@ var InspectorClient = class _InspectorClient extends InspectorClientEventTarget
12181
12396
  getServerSettings() {
12182
12397
  return this.serverSettings;
12183
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
+ }
12184
12409
  /**
12185
12410
  * Replace the in-memory per-server settings on a live client. Lets a settings
12186
12411
  * edit (e.g. toggling auto-refresh-on-list-changed) take effect on the
@@ -13702,10 +13927,9 @@ var InspectorClient = class _InspectorClient extends InspectorClientEventTarget
13702
13927
  * removes it before the result gets here (#2373).
13703
13928
  *
13704
13929
  * Separate from {@link getSkill} because the callers differ: the UIs want the
13705
- * entry, while the CLI prints the result and must not reshape it. SEP-2640
13706
- * explicitly leaves open whether this result carries `ttlMs` / `cacheScope`,
13707
- * so a server may send them — and unwrapping to the entry discards exactly
13708
- * 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).
13709
13933
  */
13710
13934
  async getSkillResult(uri, metadata) {
13711
13935
  if (!this.client) {
@@ -13716,11 +13940,12 @@ var InspectorClient = class _InspectorClient extends InspectorClientEventTarget
13716
13940
  uri,
13717
13941
  ...effectiveMeta ? { _meta: effectiveMeta } : {}
13718
13942
  };
13943
+ const resultSchema = this.isModernEra() ? ModernGetSkillEnvelopeSchema : GetSkillEnvelopeSchema;
13719
13944
  try {
13720
13945
  return await this.invokeMcpClient(
13721
13946
  () => this.client.request(
13722
13947
  { method: SKILLS_GET_METHOD, params },
13723
- GetSkillEnvelopeSchema,
13948
+ resultSchema,
13724
13949
  this.getRequestOptions(this.progressTokenOf(metadata))
13725
13950
  ),
13726
13951
  { method: SKILLS_GET_METHOD }
@@ -16051,42 +16276,57 @@ import {
16051
16276
  function withIssuer(value, issuer) {
16052
16277
  return issuer === void 0 ? value : { ...value, issuer };
16053
16278
  }
16054
- var OAuthStorageBase = class {
16279
+ var OAuthStorageCoordination = class {
16055
16280
  loaded = false;
16056
16281
  loadPromise;
16057
16282
  /** Serializes persist writes so concurrent mutators cannot reorder POSTs. */
16058
16283
  persistQueue = Promise.resolve();
16284
+ };
16285
+ var OAuthStorageBase = class {
16286
+ coordination;
16059
16287
  memory;
16060
16288
  backend;
16061
- constructor(memory, backend) {
16289
+ constructor(memory, backend, coordination = new OAuthStorageCoordination()) {
16062
16290
  this.memory = memory;
16063
16291
  this.backend = backend;
16292
+ this.coordination = coordination;
16064
16293
  }
16065
16294
  load() {
16066
- if (!this.loadPromise) {
16067
- 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
+ });
16068
16301
  }
16069
- return this.loadPromise;
16302
+ return coordination.loadPromise;
16070
16303
  }
16071
16304
  async doLoad() {
16072
- if (this.loaded) {
16305
+ if (this.coordination.loaded) {
16073
16306
  return;
16074
16307
  }
16075
16308
  const snapshot = await this.backend.read();
16076
16309
  if (snapshot) {
16077
16310
  this.memory.replace(snapshot);
16078
16311
  }
16079
- this.loaded = true;
16312
+ this.coordination.loaded = true;
16080
16313
  }
16081
16314
  async ensureLoaded() {
16082
16315
  await this.load();
16083
16316
  }
16084
- async persist() {
16085
- const snapshot = this.memory.snapshot();
16086
- 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;
16087
16327
  const tracked = prior.catch(() => {
16088
- }).then(() => this.backend.write(snapshot));
16089
- this.persistQueue = tracked;
16328
+ }).then(() => this.backend.write(this.memory.snapshot(), sections));
16329
+ this.coordination.persistQueue = tracked;
16090
16330
  await tracked;
16091
16331
  }
16092
16332
  /**
@@ -16100,7 +16340,7 @@ var OAuthStorageBase = class {
16100
16340
  /** Read the issuer-bound slot for a read, if one exists. */
16101
16341
  issuerSlot(state, issuer) {
16102
16342
  const key = this.resolveReadIssuer(state, issuer);
16103
- return key ? state.byIssuer?.[key] : void 0;
16343
+ return key ? getOwnEntry(state.byIssuer, key) : void 0;
16104
16344
  }
16105
16345
  /**
16106
16346
  * Read-modify-write the `byIssuer[issuer]` slot, set `activeIssuer`, and clear
@@ -16111,7 +16351,9 @@ var OAuthStorageBase = class {
16111
16351
  const state = this.memory.getState().getServerState(serverUrl);
16112
16352
  const byIssuer = {
16113
16353
  ...state.byIssuer,
16114
- [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 }
16115
16357
  };
16116
16358
  this.memory.getState().setServerState(serverUrl, {
16117
16359
  byIssuer,
@@ -16123,7 +16365,7 @@ var OAuthStorageBase = class {
16123
16365
  mapIssuerSlots(state, fn) {
16124
16366
  const byIssuer = {};
16125
16367
  for (const [key, slot] of Object.entries(state.byIssuer ?? {})) {
16126
- byIssuer[key] = { ...slot, ...fn(slot) };
16368
+ setOwnEntry(byIssuer, key, { ...slot, ...fn(slot) });
16127
16369
  }
16128
16370
  return byIssuer;
16129
16371
  }
@@ -16169,7 +16411,7 @@ var OAuthStorageBase = class {
16169
16411
  clientRegistrationKind: options.registrationKind
16170
16412
  });
16171
16413
  }
16172
- await this.persist();
16414
+ await this.persist({ servers: [serverUrl] });
16173
16415
  }
16174
16416
  async savePreregisteredClientInformation(serverUrl, clientInformation) {
16175
16417
  await this.ensureLoaded();
@@ -16177,7 +16419,7 @@ var OAuthStorageBase = class {
16177
16419
  preregisteredClientInformation: clientInformation,
16178
16420
  clientRegistrationKind: "static"
16179
16421
  });
16180
- await this.persist();
16422
+ await this.persist({ servers: [serverUrl] });
16181
16423
  }
16182
16424
  async clearClientInformation(serverUrl, isPreregistered, issuer) {
16183
16425
  await this.ensureLoaded();
@@ -16185,7 +16427,7 @@ var OAuthStorageBase = class {
16185
16427
  this.memory.getState().setServerState(serverUrl, {
16186
16428
  preregisteredClientInformation: void 0
16187
16429
  });
16188
- await this.persist();
16430
+ await this.persist({ servers: [serverUrl] });
16189
16431
  return;
16190
16432
  }
16191
16433
  if (issuer !== void 0) {
@@ -16208,7 +16450,7 @@ var OAuthStorageBase = class {
16208
16450
  clientRegistrationKind: void 0
16209
16451
  });
16210
16452
  }
16211
- await this.persist();
16453
+ await this.persist({ servers: [serverUrl] });
16212
16454
  }
16213
16455
  async getTokens(serverUrl, issuer) {
16214
16456
  await this.ensureLoaded();
@@ -16219,9 +16461,12 @@ var OAuthStorageBase = class {
16219
16461
  if (!tokens) {
16220
16462
  return void 0;
16221
16463
  }
16222
- const parsed = await OAuthTokensSchema3.parseAsync(tokens);
16464
+ const result = await OAuthTokensSchema3.safeParseAsync(tokens);
16465
+ if (!result.success) {
16466
+ return void 0;
16467
+ }
16223
16468
  return withIssuer(
16224
- parsed,
16469
+ result.data,
16225
16470
  fromSlot ? this.resolveReadIssuer(state, issuer) : void 0
16226
16471
  );
16227
16472
  }
@@ -16245,7 +16490,7 @@ var OAuthStorageBase = class {
16245
16490
  ...options?.enterpriseManaged === true && { enterpriseManaged: true }
16246
16491
  });
16247
16492
  }
16248
- await this.persist();
16493
+ await this.persist({ servers: [serverUrl] });
16249
16494
  }
16250
16495
  async clearTokens(serverUrl, issuer) {
16251
16496
  await this.ensureLoaded();
@@ -16264,7 +16509,7 @@ var OAuthStorageBase = class {
16264
16509
  }));
16265
16510
  this.memory.getState().setServerState(serverUrl, { byIssuer, tokens: void 0 });
16266
16511
  }
16267
- await this.persist();
16512
+ await this.persist({ servers: [serverUrl] });
16268
16513
  }
16269
16514
  async getCodeVerifier(serverUrl) {
16270
16515
  await this.ensureLoaded();
@@ -16274,12 +16519,12 @@ var OAuthStorageBase = class {
16274
16519
  async saveCodeVerifier(serverUrl, codeVerifier) {
16275
16520
  await this.ensureLoaded();
16276
16521
  this.memory.getState().setServerState(serverUrl, { codeVerifier });
16277
- await this.persist();
16522
+ await this.persist({ servers: [serverUrl] });
16278
16523
  }
16279
16524
  async clearCodeVerifier(serverUrl) {
16280
16525
  await this.ensureLoaded();
16281
16526
  this.memory.getState().setServerState(serverUrl, { codeVerifier: void 0 });
16282
- await this.persist();
16527
+ await this.persist({ servers: [serverUrl] });
16283
16528
  }
16284
16529
  async getScope(serverUrl) {
16285
16530
  await this.ensureLoaded();
@@ -16289,12 +16534,12 @@ var OAuthStorageBase = class {
16289
16534
  async saveScope(serverUrl, scope) {
16290
16535
  await this.ensureLoaded();
16291
16536
  this.memory.getState().setServerState(serverUrl, { scope });
16292
- await this.persist();
16537
+ await this.persist({ servers: [serverUrl] });
16293
16538
  }
16294
16539
  async clearScope(serverUrl) {
16295
16540
  await this.ensureLoaded();
16296
16541
  this.memory.getState().setServerState(serverUrl, { scope: void 0 });
16297
- await this.persist();
16542
+ await this.persist({ servers: [serverUrl] });
16298
16543
  }
16299
16544
  async getServerMetadata(serverUrl) {
16300
16545
  await this.ensureLoaded();
@@ -16304,12 +16549,12 @@ var OAuthStorageBase = class {
16304
16549
  async saveServerMetadata(serverUrl, metadata) {
16305
16550
  await this.ensureLoaded();
16306
16551
  this.memory.getState().setServerState(serverUrl, { serverMetadata: metadata });
16307
- await this.persist();
16552
+ await this.persist({ servers: [serverUrl] });
16308
16553
  }
16309
16554
  async clearServerMetadata(serverUrl) {
16310
16555
  await this.ensureLoaded();
16311
16556
  this.memory.getState().setServerState(serverUrl, { serverMetadata: void 0 });
16312
- await this.persist();
16557
+ await this.persist({ servers: [serverUrl] });
16313
16558
  }
16314
16559
  async getDiscoveryState(serverUrl) {
16315
16560
  await this.ensureLoaded();
@@ -16318,12 +16563,12 @@ var OAuthStorageBase = class {
16318
16563
  async saveDiscoveryState(serverUrl, state) {
16319
16564
  await this.ensureLoaded();
16320
16565
  this.memory.getState().setServerState(serverUrl, { discoveryState: state });
16321
- await this.persist();
16566
+ await this.persist({ servers: [serverUrl] });
16322
16567
  }
16323
16568
  async clearDiscoveryState(serverUrl) {
16324
16569
  await this.ensureLoaded();
16325
16570
  this.memory.getState().setServerState(serverUrl, { discoveryState: void 0 });
16326
- await this.persist();
16571
+ await this.persist({ servers: [serverUrl] });
16327
16572
  }
16328
16573
  async takeRevocationSnapshot(serverUrl) {
16329
16574
  await this.ensureLoaded();
@@ -16341,13 +16586,13 @@ var OAuthStorageBase = class {
16341
16586
  serverMetadata: state.serverMetadata
16342
16587
  };
16343
16588
  this.memory.getState().clearServerState(serverUrl);
16344
- await this.persist();
16589
+ await this.persist({ servers: [serverUrl] });
16345
16590
  return snapshot;
16346
16591
  }
16347
16592
  async clear(serverUrl) {
16348
16593
  await this.ensureLoaded();
16349
16594
  this.memory.getState().clearServerState(serverUrl);
16350
- await this.persist();
16595
+ await this.persist({ servers: [serverUrl] });
16351
16596
  }
16352
16597
  async getIdpSession(issuer) {
16353
16598
  await this.ensureLoaded();
@@ -16360,17 +16605,18 @@ var OAuthStorageBase = class {
16360
16605
  async saveIdpSession(issuer, session) {
16361
16606
  await this.ensureLoaded();
16362
16607
  this.memory.getState().setIdpSession(issuer, session);
16363
- await this.persist();
16608
+ await this.persist({ idpSessions: [issuer] });
16364
16609
  }
16365
16610
  async clearIdpSession(issuer) {
16366
16611
  await this.ensureLoaded();
16367
16612
  this.memory.getState().clearIdpSession(issuer);
16368
- await this.persist();
16613
+ await this.persist({ idpSessions: [issuer] });
16369
16614
  }
16370
16615
  async clearEnterpriseManagedResourceServers() {
16371
16616
  await this.ensureLoaded();
16617
+ const servers = Object.entries(this.memory.getState().servers).filter(([, state]) => state.enterpriseManaged === true).map(([url]) => url);
16372
16618
  this.memory.getState().clearEnterpriseManagedResourceServers();
16373
- await this.persist();
16619
+ await this.persist({ servers });
16374
16620
  }
16375
16621
  };
16376
16622
 
@@ -16388,13 +16634,15 @@ var OAuthMemoryStore = class {
16388
16634
  servers: this.servers,
16389
16635
  idpSessions: this.idpSessions,
16390
16636
  getServerState: (serverUrl) => {
16391
- return this.servers[serverUrl] || {};
16637
+ return getOwnEntry(this.servers, serverUrl) || {};
16392
16638
  },
16393
16639
  setServerState: (serverUrl, updates) => {
16394
16640
  this.servers = {
16395
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.
16396
16644
  [serverUrl]: {
16397
- ...this.servers[serverUrl],
16645
+ ...getOwnEntry(this.servers, serverUrl),
16398
16646
  ...updates
16399
16647
  }
16400
16648
  };
@@ -16405,13 +16653,13 @@ var OAuthMemoryStore = class {
16405
16653
  this.servers = rest;
16406
16654
  },
16407
16655
  getIdpSession: (issuer) => {
16408
- return this.idpSessions[issuer] || {};
16656
+ return getOwnEntry(this.idpSessions, issuer) || {};
16409
16657
  },
16410
16658
  setIdpSession: (issuer, updates) => {
16411
16659
  this.idpSessions = {
16412
16660
  ...this.idpSessions,
16413
16661
  [issuer]: {
16414
- ...this.idpSessions[issuer],
16662
+ ...getOwnEntry(this.idpSessions, issuer),
16415
16663
  ...updates
16416
16664
  }
16417
16665
  };
@@ -16445,13 +16693,70 @@ var OAuthMemoryStore = class {
16445
16693
  };
16446
16694
 
16447
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
+ }
16448
16720
  function isRecord4(value) {
16449
16721
  return typeof value === "object" && value !== null && !Array.isArray(value);
16450
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
+ }
16451
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;
16452
16757
  return {
16453
- servers: payload.servers ?? {},
16454
- idpSessions: payload.idpSessions ?? {}
16758
+ servers,
16759
+ idpSessions
16455
16760
  };
16456
16761
  }
16457
16762
  function parseOAuthPersistBlob(raw) {
@@ -16474,92 +16779,853 @@ function serializeOAuthPersistBlob(snapshot) {
16474
16779
  return serializeStore(snapshot);
16475
16780
  }
16476
16781
 
16477
- // ../../core/auth/node/oauth-persist-file.ts
16478
- function createFileOAuthPersistBackend(options) {
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
+ }
16479
16851
  return {
16480
- async read() {
16481
- const raw = await readStoreFile(options.filePath);
16482
- return parseOAuthPersistBlob(raw);
16483
- },
16484
- async write(snapshot) {
16485
- await writeStoreFile(
16486
- options.filePath,
16487
- serializeOAuthPersistBlob(snapshot)
16488
- );
16489
- },
16490
- async remove() {
16491
- await deleteStoreFile(options.filePath);
16852
+ ...info,
16853
+ ...clientSecret !== void 0 && { client_secret: clientSecret },
16854
+ ...registrationToken !== void 0 && {
16855
+ registration_access_token: registrationToken
16492
16856
  }
16493
16857
  };
16494
16858
  }
16495
-
16496
- // ../../core/auth/node/storage-node.ts
16497
- var DEFAULT_STATE_PATH = getStoreFilePath(getDefaultStorageDir(), "oauth");
16498
- function getStateFilePath(customPath) {
16499
- if (customPath) return customPath;
16500
- if (process.env.MCP_INSPECTOR_OAUTH_STATE_PATH) {
16501
- return process.env.MCP_INSPECTOR_OAUTH_STATE_PATH;
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;
16502
16896
  }
16503
- if (process.env.MCP_STORAGE_DIR) {
16504
- return getStoreFilePath(process.env.MCP_STORAGE_DIR, "oauth");
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;
16505
16904
  }
16506
- return DEFAULT_STATE_PATH;
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 };
16507
16920
  }
16508
- var memoryCache = /* @__PURE__ */ new Map();
16509
- function getSharedMemory(stateFilePath) {
16510
- const key = getStateFilePath(stateFilePath);
16511
- let memory = memoryCache.get(key);
16512
- if (!memory) {
16513
- memory = new OAuthMemoryStore();
16514
- memoryCache.set(key, memory);
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 {
16515
16928
  }
16516
- return memory;
16929
+ return void 0;
16517
16930
  }
16518
- var NodeOAuthStorage = class extends OAuthStorageBase {
16519
- /**
16520
- * @param storagePath - Optional path to state file. Default: ~/.mcp-inspector/storage/oauth.json
16521
- */
16522
- constructor(storagePath) {
16523
- const filePath = getStateFilePath(storagePath);
16524
- super(
16525
- getSharedMemory(storagePath),
16526
- createFileOAuthPersistBackend({ filePath })
16527
- );
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 {
16528
16943
  }
16529
- };
16530
-
16531
- // ../../core/auth/node/oauth-callback-server.ts
16532
- import { createServer } from "http";
16533
- var DEFAULT_HOSTNAME = "127.0.0.1";
16534
- var DEFAULT_CALLBACK_PATH = "/oauth/callback";
16535
- var SUCCESS_HTML = `<!DOCTYPE html>
16536
- <html>
16537
- <head><meta charset="utf-8"><title>OAuth complete</title></head>
16538
- <body><p>OAuth complete. You can close this window.</p></body>
16539
- </html>`;
16540
- function errorHtml(message) {
16541
- return `<!DOCTYPE html>
16542
- <html>
16543
- <head><meta charset="utf-8"><title>OAuth error</title></head>
16544
- <body><p>OAuth failed: ${escapeHtml(message)}</p></body>
16545
- </html>`;
16944
+ return void 0;
16546
16945
  }
16547
- function escapeHtml(s) {
16548
- return s.replace(/&/g, "&amp;").replace(/</g, "&lt;").replace(/>/g, "&gt;").replace(/"/g, "&quot;");
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;
16549
16954
  }
16550
- var OAuthCallbackServer = class {
16551
- server = null;
16552
- port = 0;
16553
- callbackPath = DEFAULT_CALLBACK_PATH;
16554
- handled = false;
16555
- onCallback;
16556
- onError;
16557
- /**
16558
- * Start the server. Port defaults to 0 (random) when omitted; TUI/CLI callers
16559
- * pass the resolved port from {@link parseRunnerOAuthCallbackUrl} (6276 by default).
16560
- * Returns port and redirectUrl for use as oauth.redirectUrl.
16561
- */
16562
- async start(options = {}) {
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;
17400
+ }
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
+ });
17424
+ }
17425
+ for (const issuer of Object.keys(snapshot.idpSessions)) {
17426
+ requests.push({
17427
+ serverId: oauthIdpSecretServerId(issuer),
17428
+ fields: [IDP_SESSION_FIELD]
17429
+ });
17430
+ }
17431
+ return requests;
17432
+ }
17433
+ async function joinSnapshot(snapshot, secretStore) {
17434
+ const requests = secretRequestsFor(snapshot);
17435
+ const values = requests.length > 0 ? await secretStoreGetManyStrict(secretStore, requests) : {};
17436
+ return {
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
+ )
17449
+ };
17450
+ }
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
+ });
17497
+ }
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
+ });
17533
+ }
17534
+ function createFileOAuthPersistBackend(options) {
17535
+ const secretStore = options.secretStore ?? defaultSecretStore();
17536
+ return {
17537
+ async read() {
17538
+ return readOAuthStore(options.filePath, secretStore);
17539
+ },
17540
+ async write(snapshot, sections) {
17541
+ await writeOAuthSections(
17542
+ options.filePath,
17543
+ snapshot,
17544
+ sections,
17545
+ secretStore
17546
+ );
17547
+ },
17548
+ async remove() {
17549
+ await removeOAuthStore(options.filePath, secretStore);
17550
+ }
17551
+ };
17552
+ }
17553
+
17554
+ // ../../core/auth/node/storage-node.ts
17555
+ var DEFAULT_STATE_PATH = getStoreFilePath(getDefaultStorageDir(), "oauth");
17556
+ function getStateFilePath(customPath) {
17557
+ if (customPath) return customPath;
17558
+ if (process.env.MCP_INSPECTOR_OAUTH_STATE_PATH) {
17559
+ return process.env.MCP_INSPECTOR_OAUTH_STATE_PATH;
17560
+ }
17561
+ if (process.env.MCP_STORAGE_DIR) {
17562
+ return getStoreFilePath(process.env.MCP_STORAGE_DIR, "oauth");
17563
+ }
17564
+ return DEFAULT_STATE_PATH;
17565
+ }
17566
+ var sharedStateCache = /* @__PURE__ */ new Map();
17567
+ function getSharedState(stateFilePath) {
17568
+ const key = getStateFilePath(stateFilePath);
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);
17576
+ }
17577
+ return shared;
17578
+ }
17579
+ var NodeOAuthStorage = class extends OAuthStorageBase {
17580
+ /**
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.
17585
+ */
17586
+ constructor(storagePath, secretStore) {
17587
+ const filePath = getStateFilePath(storagePath);
17588
+ const shared = getSharedState(storagePath);
17589
+ super(
17590
+ shared.memory,
17591
+ createFileOAuthPersistBackend({ filePath, secretStore }),
17592
+ shared.coordination
17593
+ );
17594
+ }
17595
+ };
17596
+
17597
+ // ../../core/auth/node/oauth-callback-server.ts
17598
+ import { createServer } from "http";
17599
+ var DEFAULT_HOSTNAME = "127.0.0.1";
17600
+ var DEFAULT_CALLBACK_PATH = "/oauth/callback";
17601
+ var SUCCESS_HTML = `<!DOCTYPE html>
17602
+ <html>
17603
+ <head><meta charset="utf-8"><title>OAuth complete</title></head>
17604
+ <body><p>OAuth complete. You can close this window.</p></body>
17605
+ </html>`;
17606
+ function errorHtml(message) {
17607
+ return `<!DOCTYPE html>
17608
+ <html>
17609
+ <head><meta charset="utf-8"><title>OAuth error</title></head>
17610
+ <body><p>OAuth failed: ${escapeHtml(message)}</p></body>
17611
+ </html>`;
17612
+ }
17613
+ function escapeHtml(s) {
17614
+ return s.replace(/&/g, "&amp;").replace(/</g, "&lt;").replace(/>/g, "&gt;").replace(/"/g, "&quot;");
17615
+ }
17616
+ var OAuthCallbackServer = class {
17617
+ server = null;
17618
+ port = 0;
17619
+ callbackPath = DEFAULT_CALLBACK_PATH;
17620
+ handled = false;
17621
+ onCallback;
17622
+ onError;
17623
+ /**
17624
+ * Start the server. Port defaults to 0 (random) when omitted; TUI/CLI callers
17625
+ * pass the resolved port from {@link parseRunnerOAuthCallbackUrl} (6276 by default).
17626
+ * Returns port and redirectUrl for use as oauth.redirectUrl.
17627
+ */
17628
+ async start(options = {}) {
16563
17629
  const {
16564
17630
  port = 0,
16565
17631
  hostname = DEFAULT_HOSTNAME,
@@ -18458,7 +19524,11 @@ async function verifySkills(client, entries, metadata) {
18458
19524
  files,
18459
19525
  ...incomplete ? { incomplete } : {},
18460
19526
  ok: !hasError && !fileFailed,
18461
- 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"
18462
19532
  });
18463
19533
  }
18464
19534
  return reports;
@@ -18490,6 +19560,7 @@ var FILE_COLOR = {
18490
19560
  };
18491
19561
  var VERIFY_STATUS = {
18492
19562
  verified: "[Verified \u2014 Enter to re-verify]",
19563
+ unverifiable: "[UNVERIFIABLE \u2014 Enter to re-verify]",
18493
19564
  incomplete: "[Verification INCOMPLETE \u2014 Enter to re-verify]",
18494
19565
  failed: "[Verification FAILED \u2014 Enter to re-verify]"
18495
19566
  };
@@ -19573,8 +20644,64 @@ function HistoryTab({
19573
20644
 
19574
20645
  // src/components/RequestsTab.tsx
19575
20646
  import React9, { useEffect as useEffect10, useRef as useRef12 } from "react";
19576
- 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
19577
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";
19578
20705
  function RequestsTab({
19579
20706
  requests,
19580
20707
  width,
@@ -19642,9 +20769,9 @@ function RequestsTab({
19642
20769
  if (status >= 400) return "red";
19643
20770
  return "gray";
19644
20771
  };
19645
- return /* @__PURE__ */ jsxs11(Box12, { flexDirection: "row", width, height, children: [
19646
- /* @__PURE__ */ jsxs11(
19647
- Box12,
20772
+ return /* @__PURE__ */ jsxs12(Box13, { flexDirection: "row", width, height, children: [
20773
+ /* @__PURE__ */ jsxs12(
20774
+ Box13,
19648
20775
  {
19649
20776
  width: listWidth,
19650
20777
  height,
@@ -19656,8 +20783,8 @@ function RequestsTab({
19656
20783
  flexDirection: "column",
19657
20784
  paddingX: 1,
19658
20785
  children: [
19659
- /* @__PURE__ */ jsx12(Box12, { paddingY: 1, flexShrink: 0, children: /* @__PURE__ */ jsxs11(
19660
- Text11,
20786
+ /* @__PURE__ */ jsx13(Box13, { paddingY: 1, flexShrink: 0, children: /* @__PURE__ */ jsxs12(
20787
+ Text12,
19661
20788
  {
19662
20789
  bold: true,
19663
20790
  backgroundColor: focusedPane === "requests" ? "yellow" : void 0,
@@ -19668,8 +20795,8 @@ function RequestsTab({
19668
20795
  ]
19669
20796
  }
19670
20797
  ) }),
19671
- requests.length === 0 ? /* @__PURE__ */ jsx12(Box12, { paddingY: 1, children: /* @__PURE__ */ jsx12(Text11, { dimColor: true, children: "No requests" }) }) : /* @__PURE__ */ jsx12(
19672
- Box12,
20798
+ requests.length === 0 ? /* @__PURE__ */ jsx13(Box13, { paddingY: 1, children: /* @__PURE__ */ jsx13(Text12, { dimColor: true, children: "No requests" }) }) : /* @__PURE__ */ jsx13(
20799
+ Box13,
19673
20800
  {
19674
20801
  flexDirection: "column",
19675
20802
  height: visibleCount,
@@ -19682,14 +20809,14 @@ function RequestsTab({
19682
20809
  const statusText = req.responseStatus ? `${req.responseStatus}` : req.error ? "ERROR" : "...";
19683
20810
  const categoryLabel = req.category === "auth" ? "AUTH" : "MCP ";
19684
20811
  const methodPadded = req.method === "GET" ? "GET " : req.method;
19685
- 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: [
19686
20813
  isSelected ? "\u25B6 " : " ",
19687
- /* @__PURE__ */ jsx12(Text11, { children: categoryLabel }),
20814
+ /* @__PURE__ */ jsx13(Text12, { children: categoryLabel }),
19688
20815
  " ",
19689
- /* @__PURE__ */ jsx12(Text11, { color: statusColor, children: methodPadded }),
20816
+ /* @__PURE__ */ jsx13(Text12, { color: statusColor, children: methodPadded }),
19690
20817
  " ",
19691
- /* @__PURE__ */ jsx12(Text11, { dimColor: true, children: statusText }),
19692
- 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: [
19693
20820
  " ",
19694
20821
  req.duration,
19695
20822
  "ms"
@@ -19701,8 +20828,8 @@ function RequestsTab({
19701
20828
  ]
19702
20829
  }
19703
20830
  ),
19704
- /* @__PURE__ */ jsx12(
19705
- Box12,
20831
+ /* @__PURE__ */ jsx13(
20832
+ Box13,
19706
20833
  {
19707
20834
  width: detailWidth,
19708
20835
  height,
@@ -19714,9 +20841,9 @@ function RequestsTab({
19714
20841
  borderBottom: false,
19715
20842
  borderLeft: false,
19716
20843
  borderRight: false,
19717
- children: selectedRequest ? /* @__PURE__ */ jsxs11(Fragment8, { children: [
19718
- /* @__PURE__ */ jsx12(Box12, { flexShrink: 0, paddingTop: 1, children: /* @__PURE__ */ jsxs11(
19719
- Text11,
20844
+ children: selectedRequest ? /* @__PURE__ */ jsxs12(Fragment9, { children: [
20845
+ /* @__PURE__ */ jsx13(Box13, { flexShrink: 0, paddingTop: 1, children: /* @__PURE__ */ jsxs12(
20846
+ Text12,
19720
20847
  {
19721
20848
  bold: true,
19722
20849
  backgroundColor: focusedPane === "details" ? "yellow" : void 0,
@@ -19728,17 +20855,17 @@ function RequestsTab({
19728
20855
  ]
19729
20856
  }
19730
20857
  ) }),
19731
- /* @__PURE__ */ jsxs11(ScrollView, { ref: scrollViewRef, height: height - 5, children: [
19732
- /* @__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: [
19733
20860
  "Category:",
19734
20861
  " ",
19735
- /* @__PURE__ */ jsx12(Text11, { children: selectedRequest.category === "auth" ? "auth" : "transport" })
20862
+ /* @__PURE__ */ jsx13(Text12, { children: selectedRequest.category === "auth" ? "auth" : "transport" })
19736
20863
  ] }) }),
19737
- 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: [
19738
20865
  "Status:",
19739
20866
  " ",
19740
- /* @__PURE__ */ jsxs11(
19741
- Text11,
20867
+ /* @__PURE__ */ jsxs12(
20868
+ Text12,
19742
20869
  {
19743
20870
  color: getStatusColor(selectedRequest.responseStatus),
19744
20871
  children: [
@@ -19748,54 +20875,44 @@ function RequestsTab({
19748
20875
  ]
19749
20876
  }
19750
20877
  )
19751
- ] }) }) : 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: [
19752
20879
  "Error: ",
19753
20880
  selectedRequest.error
19754
- ] }) }) : /* @__PURE__ */ jsx12(Box12, { marginTop: 1, flexShrink: 0, children: /* @__PURE__ */ jsx12(Text11, { dimColor: true, italic: true, children: "Request in progress..." }) }),
19755
- 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: [
19756
20883
  selectedRequest.timestamp.toLocaleTimeString(),
19757
20884
  " (",
19758
20885
  selectedRequest.duration,
19759
20886
  "ms)"
19760
20887
  ] }) }),
19761
- /* @__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:" }) }),
19762
20889
  Object.entries(selectedRequest.requestHeaders).map(
19763
- ([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: [
19764
20891
  key,
19765
20892
  ": ",
19766
20893
  value
19767
20894
  ] }) }, key)
19768
20895
  ),
19769
- selectedRequest.requestBody && /* @__PURE__ */ jsxs11(Fragment8, { children: [
19770
- /* @__PURE__ */ jsx12(Box12, { marginTop: 1, flexShrink: 0, children: /* @__PURE__ */ jsx12(Text11, { bold: true, children: "Request Body:" }) }),
19771
- (() => {
19772
- try {
19773
- const parsed = JSON.parse(selectedRequest.requestBody);
19774
- return JSON.stringify(parsed, null, 2).split("\n").map((line, idx) => /* @__PURE__ */ jsx12(
19775
- Box12,
19776
- {
19777
- marginTop: idx === 0 ? 1 : 0,
19778
- paddingLeft: 2,
19779
- flexShrink: 0,
19780
- children: /* @__PURE__ */ jsx12(Text11, { dimColor: true, children: line })
19781
- },
19782
- `req-body-${idx}`
19783
- ));
19784
- } catch {
19785
- 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"
19786
20903
  }
19787
- })()
20904
+ )
19788
20905
  ] }),
19789
- selectedRequest.responseHeaders && Object.keys(selectedRequest.responseHeaders).length > 0 && /* @__PURE__ */ jsxs11(Fragment8, { children: [
19790
- /* @__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:" }) }),
19791
20908
  Object.entries(selectedRequest.responseHeaders).map(
19792
- ([key, value]) => /* @__PURE__ */ jsx12(
19793
- Box12,
20909
+ ([key, value]) => /* @__PURE__ */ jsx13(
20910
+ Box13,
19794
20911
  {
19795
20912
  marginTop: 0,
19796
20913
  paddingLeft: 2,
19797
20914
  flexShrink: 0,
19798
- children: /* @__PURE__ */ jsxs11(Text11, { dimColor: true, children: [
20915
+ children: /* @__PURE__ */ jsxs12(Text12, { dimColor: true, children: [
19799
20916
  key,
19800
20917
  ": ",
19801
20918
  value
@@ -19805,38 +20922,28 @@ function RequestsTab({
19805
20922
  )
19806
20923
  )
19807
20924
  ] }),
19808
- selectedRequest.responseBody && /* @__PURE__ */ jsxs11(Fragment8, { children: [
19809
- /* @__PURE__ */ jsx12(Box12, { marginTop: 1, flexShrink: 0, children: /* @__PURE__ */ jsx12(Text11, { bold: true, children: "Response Body:" }) }),
19810
- (() => {
19811
- try {
19812
- const parsed = JSON.parse(selectedRequest.responseBody);
19813
- return JSON.stringify(parsed, null, 2).split("\n").map((line, idx) => /* @__PURE__ */ jsx12(
19814
- Box12,
19815
- {
19816
- marginTop: idx === 0 ? 1 : 0,
19817
- paddingLeft: 2,
19818
- flexShrink: 0,
19819
- children: /* @__PURE__ */ jsx12(Text11, { dimColor: true, children: line })
19820
- },
19821
- `resp-body-${idx}`
19822
- ));
19823
- } catch {
19824
- 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"
19825
20932
  }
19826
- })()
20933
+ )
19827
20934
  ] })
19828
20935
  ] }),
19829
- focusedPane === "details" && /* @__PURE__ */ jsx12(
19830
- Box12,
20936
+ focusedPane === "details" && /* @__PURE__ */ jsx13(
20937
+ Box13,
19831
20938
  {
19832
20939
  flexShrink: 0,
19833
20940
  height: 1,
19834
20941
  justifyContent: "center",
19835
20942
  backgroundColor: "gray",
19836
- 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" })
19837
20944
  }
19838
20945
  )
19839
- ] }) : /* @__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" }) })
19840
20947
  }
19841
20948
  )
19842
20949
  ] });
@@ -19844,16 +20951,16 @@ function RequestsTab({
19844
20951
 
19845
20952
  // src/components/ToolTestModal.tsx
19846
20953
  import React26, { useState as useState14 } from "react";
19847
- 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";
19848
20955
 
19849
20956
  // node_modules/ink-form/lib/Form.js
19850
- import { Box as Box23, useFocusManager, useInput as useInput17 } from "ink";
20957
+ import { Box as Box24, useFocusManager, useInput as useInput17 } from "ink";
19851
20958
  import { useEffect as useEffect13, useMemo as useMemo3, useState as useState13 } from "react";
19852
20959
  import * as React24 from "react";
19853
20960
 
19854
20961
  // node_modules/ink-form/lib/FormHeader.js
19855
20962
  import * as React10 from "react";
19856
- 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";
19857
20964
  var FormHeader = (props) => {
19858
20965
  const sections = props.form.sections;
19859
20966
  useInput10((input, key) => {
@@ -19870,42 +20977,42 @@ var FormHeader = (props) => {
19870
20977
  }
19871
20978
  }, { isActive: !props.editingField });
19872
20979
  return React10.createElement(
19873
- Box13,
20980
+ Box14,
19874
20981
  { borderStyle: "double", width: "100%", flexDirection: "column" },
19875
20982
  React10.createElement(
19876
- Box13,
20983
+ Box14,
19877
20984
  { width: "100%" },
19878
20985
  React10.createElement(
19879
- Box13,
20986
+ Box14,
19880
20987
  { flexGrow: 1 },
19881
- React10.createElement(Text12, { bold: true }, props.form.title)
20988
+ React10.createElement(Text13, { bold: true }, props.form.title)
19882
20989
  ),
19883
20990
  React10.createElement(
19884
- Box13,
20991
+ Box14,
19885
20992
  null,
19886
- 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")
19887
20994
  )
19888
20995
  ),
19889
20996
  React10.createElement(
19890
- Box13,
20997
+ Box14,
19891
20998
  { width: "100%" },
19892
- React10.createElement(Box13, null, !props.editingField ? sections.map((section, id) => React10.createElement(
19893
- Box13,
20999
+ React10.createElement(Box14, null, !props.editingField ? sections.map((section, id) => React10.createElement(
21000
+ Box14,
19894
21001
  { key: section.title },
19895
21002
  React10.createElement(
19896
- Text12,
21003
+ Text13,
19897
21004
  { color: "gray" },
19898
21005
  "[",
19899
21006
  id + 1,
19900
21007
  "] "
19901
21008
  ),
19902
- React10.createElement(Text12, { color: props.currentTab === id ? "blue" : void 0, underline: props.currentTab === id }, section.title),
19903
- 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, " ")
19904
21011
  )) : React10.createElement(
19905
- Box13,
21012
+ Box14,
19906
21013
  null,
19907
21014
  React10.createElement(
19908
- Text12,
21015
+ Text13,
19909
21016
  null,
19910
21017
  "Editing ",
19911
21018
  props.editingField
@@ -19917,18 +21024,18 @@ var FormHeader = (props) => {
19917
21024
 
19918
21025
  // node_modules/ink-form/lib/FormFieldRenderer.js
19919
21026
  import React22, { useState as useState12 } from "react";
19920
- 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";
19921
21028
 
19922
21029
  // node_modules/ink-form/lib/managers/FloatFormFieldManager.js
19923
21030
  import React13 from "react";
19924
21031
 
19925
21032
  // node_modules/ink-form/lib/NumberFieldRenderer.js
19926
21033
  import React12 from "react";
19927
- 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";
19928
21035
 
19929
21036
  // node_modules/ink-text-input/build/index.js
19930
21037
  import React11, { useState as useState10, useEffect as useEffect11 } from "react";
19931
- import { Text as Text13, useInput as useInput11 } from "ink";
21038
+ import { Text as Text14, useInput as useInput11 } from "ink";
19932
21039
 
19933
21040
  // node_modules/chalk/source/vendor/ansi-styles/index.js
19934
21041
  var ANSI_BACKGROUND_OFFSET = 10;
@@ -20510,7 +21617,7 @@ function TextInput({ value: originalValue, placeholder = "", focus = true, mask,
20510
21617
  onChange(nextValue);
20511
21618
  }
20512
21619
  }, { isActive: focus });
20513
- 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);
20514
21621
  }
20515
21622
  var build_default = TextInput;
20516
21623
 
@@ -20554,10 +21661,10 @@ var NumberFieldRenderer = (props) => {
20554
21661
  }
20555
21662
  });
20556
21663
  return React12.createElement(
20557
- Box14,
21664
+ Box15,
20558
21665
  { borderStyle: "round", width: "100%", flexDirection: "column" },
20559
21666
  React12.createElement(
20560
- Box14,
21667
+ Box15,
20561
21668
  null,
20562
21669
  React12.createElement(build_default, { value: "" + (props.value ?? ""), onChange: (value) => {
20563
21670
  if (regex.test(value)) {
@@ -20570,9 +21677,9 @@ var NumberFieldRenderer = (props) => {
20570
21677
  }, placeholder: props.field.placeholder, onSubmit: () => props.onSetEditingField(void 0) })
20571
21678
  ),
20572
21679
  React12.createElement(
20573
- Box14,
21680
+ Box15,
20574
21681
  null,
20575
- 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.")
20576
21683
  )
20577
21684
  );
20578
21685
  };
@@ -20594,11 +21701,11 @@ var IntegerFormFieldManager = class {
20594
21701
 
20595
21702
  // node_modules/ink-form/lib/managers/SelectFormFieldManager.js
20596
21703
  import React18 from "react";
20597
- import { Box as Box17 } from "ink";
21704
+ import { Box as Box18 } from "ink";
20598
21705
 
20599
21706
  // node_modules/ink-select-input/build/Indicator.js
20600
21707
  import React15 from "react";
20601
- import { Box as Box15, Text as Text15 } from "ink";
21708
+ import { Box as Box16, Text as Text16 } from "ink";
20602
21709
 
20603
21710
  // node_modules/is-unicode-supported/index.js
20604
21711
  import process3 from "process";
@@ -20889,15 +21996,15 @@ var replacements = Object.entries(specialMainSymbols);
20889
21996
 
20890
21997
  // node_modules/ink-select-input/build/Indicator.js
20891
21998
  function Indicator({ isSelected = false }) {
20892
- 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, " "));
20893
22000
  }
20894
22001
  var Indicator_default = Indicator;
20895
22002
 
20896
22003
  // node_modules/ink-select-input/build/Item.js
20897
22004
  import * as React16 from "react";
20898
- import { Text as Text16 } from "ink";
22005
+ import { Text as Text17 } from "ink";
20899
22006
  function Item({ isSelected = false, label }) {
20900
- return React16.createElement(Text16, { color: isSelected ? "blue" : void 0 }, label);
22007
+ return React16.createElement(Text17, { color: isSelected ? "blue" : void 0 }, label);
20901
22008
  }
20902
22009
  var Item_default = Item;
20903
22010
 
@@ -20928,7 +22035,7 @@ function toRotated(array, steps) {
20928
22035
  }
20929
22036
 
20930
22037
  // node_modules/ink-select-input/build/SelectInput.js
20931
- import { Box as Box16, useInput as useInput13 } from "ink";
22038
+ import { Box as Box17, useInput as useInput13 } from "ink";
20932
22039
  function SelectInput({ items = [], isFocused = true, initialIndex = 0, indicatorComponent = Indicator_default, itemComponent = Item_default, limit: customLimit, onSelect, onHighlight }) {
20933
22040
  const hasLimit = typeof customLimit === "number" && items.length > customLimit;
20934
22041
  const limit = hasLimit ? Math.min(customLimit, items.length) : items.length;
@@ -20995,12 +22102,12 @@ function SelectInput({ items = [], isFocused = true, initialIndex = 0, indicator
20995
22102
  onHighlight
20996
22103
  ]), { isActive: isFocused });
20997
22104
  const slicedItems = hasLimit ? toRotated(items, rotateIndex).slice(0, limit) : items;
20998
- return React17.createElement(Box16, { flexDirection: "column" }, slicedItems.map((item, index) => {
22105
+ return React17.createElement(Box17, { flexDirection: "column" }, slicedItems.map((item, index) => {
20999
22106
  const isSelected = index === selectedIndex;
21000
22107
  return (
21001
22108
  // @ts-expect-error - `key` can't be optional but `item.value` is generic T
21002
22109
  React17.createElement(
21003
- Box16,
22110
+ Box17,
21004
22111
  { key: item.key ?? item.value },
21005
22112
  React17.createElement(indicatorComponent, { isSelected }),
21006
22113
  React17.createElement(itemComponent, { ...item, isSelected })
@@ -21014,7 +22121,7 @@ var SelectInput_default = SelectInput;
21014
22121
  var SelectFormFieldManager = class {
21015
22122
  type = "select";
21016
22123
  renderField = (props) => React18.createElement(
21017
- Box17,
22124
+ Box18,
21018
22125
  { borderStyle: "round", width: "100%" },
21019
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 })
21020
22127
  );
@@ -21023,11 +22130,11 @@ var SelectFormFieldManager = class {
21023
22130
 
21024
22131
  // node_modules/ink-form/lib/managers/StringFormFieldManager.js
21025
22132
  import React19 from "react";
21026
- import { Box as Box18, Transform } from "ink";
22133
+ import { Box as Box19, Transform } from "ink";
21027
22134
  var StringFormFieldManager = class {
21028
22135
  type = "string";
21029
22136
  renderField = (props) => React19.createElement(
21030
- Box18,
22137
+ Box19,
21031
22138
  { borderStyle: "round", width: "100%" },
21032
22139
  React19.createElement(build_default, { value: props.value ?? "", onChange: (value) => {
21033
22140
  props.onChange(value);
@@ -21043,7 +22150,7 @@ var StringFormFieldManager = class {
21043
22150
 
21044
22151
  // node_modules/ink-form/lib/managers/BooleanFormFieldManager.js
21045
22152
  import React20 from "react";
21046
- 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";
21047
22154
  var BooleanFormFieldManager = class {
21048
22155
  type = "boolean";
21049
22156
  renderField = (props) => {
@@ -21053,21 +22160,21 @@ var BooleanFormFieldManager = class {
21053
22160
  }
21054
22161
  });
21055
22162
  return React20.createElement(
21056
- Box19,
22163
+ Box20,
21057
22164
  { width: "100%", borderStyle: "round", borderColor: props.value ? "green" : "gray", marginBottom: 2 },
21058
22165
  React20.createElement(
21059
- Box19,
22166
+ Box20,
21060
22167
  { marginRight: 2 },
21061
- 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]")
21062
22169
  ),
21063
22170
  React20.createElement(
21064
- Box19,
22171
+ Box20,
21065
22172
  { flexGrow: 1 },
21066
- React20.createElement(Text17, null, "Press Space to toggle value")
22173
+ React20.createElement(Text18, null, "Press Space to toggle value")
21067
22174
  )
21068
22175
  );
21069
22176
  };
21070
- 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]");
21071
22178
  };
21072
22179
 
21073
22180
  // node_modules/ink-form/lib/managers/managers.js
@@ -21084,20 +22191,20 @@ var getManager = (formFieldType, customManagers = []) => {
21084
22191
 
21085
22192
  // node_modules/ink-form/lib/DescriptionRenderer.js
21086
22193
  import React21 from "react";
21087
- import { Box as Box20, Text as Text18 } from "ink";
22194
+ import { Box as Box21, Text as Text19 } from "ink";
21088
22195
  var DescriptionRenderer = (props) => {
21089
22196
  if (!props.description) {
21090
22197
  return null;
21091
22198
  } else if (props.description.type) {
21092
22199
  return props.description;
21093
22200
  } else if (Array.isArray(props.description)) {
21094
- return React21.createElement(Box20, { flexDirection: "column" }, props.description.map((line) => React21.createElement(
21095
- Box20,
22201
+ return React21.createElement(Box21, { flexDirection: "column" }, props.description.map((line) => React21.createElement(
22202
+ Box21,
21096
22203
  { key: line, width: "100%", marginBottom: 1 },
21097
- React21.createElement(Text18, null, line)
22204
+ React21.createElement(Text19, null, line)
21098
22205
  )));
21099
22206
  } else {
21100
- return React21.createElement(Text18, null, props.description);
22207
+ return React21.createElement(Text19, null, props.description);
21101
22208
  }
21102
22209
  };
21103
22210
 
@@ -21140,24 +22247,24 @@ var FormFieldRenderer = (props) => {
21140
22247
  if (!isEditing) {
21141
22248
  const RenderValue = manager?.renderValue ?? (() => React22.createElement(React22.Fragment, null, props.value));
21142
22249
  return React22.createElement(
21143
- Box21,
22250
+ Box22,
21144
22251
  { marginX: 2, paddingX: 1, borderStyle: "round", borderColor: isFocused ? "blue" : void 0 },
21145
22252
  React22.createElement(
21146
- Box21,
22253
+ Box22,
21147
22254
  { flexGrow: 1 },
21148
- React22.createElement(Text19, { underline: isFocused, color: isFocused ? "blue" : void 0 }, props.field.label ?? props.field.name),
21149
- props.field.required && React22.createElement(Text19, { color: "red" }, "*"),
21150
- 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, ": "),
21151
22258
  React22.createElement(
21152
- Text19,
22259
+ Text20,
21153
22260
  { dimColor: true },
21154
22261
  React22.createElement(RenderValue, { value: props.value, field: props.field })
21155
22262
  )
21156
22263
  ),
21157
22264
  isFocused && React22.createElement(
21158
- Box21,
22265
+ Box22,
21159
22266
  null,
21160
- React22.createElement(Text19, null, "Press enter to edit")
22267
+ React22.createElement(Text20, null, "Press enter to edit")
21161
22268
  )
21162
22269
  );
21163
22270
  } else {
@@ -21174,7 +22281,7 @@ var FormFieldRenderer = (props) => {
21174
22281
  };
21175
22282
  if (!manager) {
21176
22283
  component = React22.createElement(
21177
- Text19,
22284
+ Text20,
21178
22285
  { color: "red" },
21179
22286
  "No formfield manager for form field of type ",
21180
22287
  props.field.type,
@@ -21185,39 +22292,39 @@ var FormFieldRenderer = (props) => {
21185
22292
  component = React22.createElement(Field, { ...rendererProps });
21186
22293
  }
21187
22294
  return React22.createElement(
21188
- Box21,
22295
+ Box22,
21189
22296
  { paddingX: 3, paddingY: 1, flexDirection: "column" },
21190
22297
  React22.createElement(
21191
- Box21,
22298
+ Box22,
21192
22299
  null,
21193
- React22.createElement(Text19, null, props.field.label ?? props.field.name),
21194
- props.field.required && React22.createElement(Text19, { color: "red" }, "*"),
21195
- 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, ": ")
21196
22303
  ),
21197
- React22.createElement(Box21, null, component),
22304
+ React22.createElement(Box22, null, component),
21198
22305
  props.field.description && React22.createElement(
21199
- Box21,
22306
+ Box22,
21200
22307
  null,
21201
22308
  React22.createElement(
21202
- Text19,
22309
+ Text20,
21203
22310
  { dimColor: true },
21204
22311
  React22.createElement(DescriptionRenderer, { description: props.field.description })
21205
22312
  )
21206
22313
  ),
21207
22314
  error && React22.createElement(
21208
- Box21,
22315
+ Box22,
21209
22316
  null,
21210
22317
  React22.createElement(
21211
- Text19,
22318
+ Text20,
21212
22319
  { color: "red" },
21213
22320
  "Error: ",
21214
22321
  error
21215
22322
  )
21216
22323
  ),
21217
22324
  React22.createElement(
21218
- Box21,
22325
+ Box22,
21219
22326
  { marginTop: 2 },
21220
- 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(
21221
22328
  React22.Fragment,
21222
22329
  null,
21223
22330
  "Press ",
@@ -21236,7 +22343,7 @@ var canSubmit = (form, value) => {
21236
22343
 
21237
22344
  // node_modules/ink-form/lib/SubmitButton.js
21238
22345
  import React23 from "react";
21239
- 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";
21240
22347
  var SubmitButton = (props) => {
21241
22348
  const { isFocused } = useFocus2({ isActive: props.canSubmit });
21242
22349
  useInput16((input, key) => {
@@ -21245,17 +22352,17 @@ var SubmitButton = (props) => {
21245
22352
  }
21246
22353
  });
21247
22354
  return React23.createElement(
21248
- Box22,
22355
+ Box23,
21249
22356
  { marginRight: 2 },
21250
22357
  React23.createElement(
21251
- Box22,
22358
+ Box23,
21252
22359
  { marginRight: 2, paddingY: 1 },
21253
- 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.")
21254
22361
  ),
21255
22362
  React23.createElement(
21256
- Box22,
22363
+ Box23,
21257
22364
  { borderStyle: "round", borderColor: !props.canSubmit ? "gray" : isFocused ? "blue" : "white", paddingX: 2 },
21258
- 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")
21259
22366
  )
21260
22367
  );
21261
22368
  };
@@ -21296,17 +22403,17 @@ var Form = (props) => {
21296
22403
  }
21297
22404
  }, { isActive: !editingField });
21298
22405
  return React24.createElement(
21299
- Box23,
22406
+ Box24,
21300
22407
  { width: "100%", height: "100%", flexDirection: "column" },
21301
22408
  React24.createElement(FormHeader, { ...props, currentTab, onChangeTab: setCurrentTab, editingField }),
21302
22409
  !editingField && props.form.sections[currentTab].description && React24.createElement(
21303
- Box23,
22410
+ Box24,
21304
22411
  { marginX: 4 },
21305
22412
  React24.createElement(DescriptionRenderer, { description: props.form.sections[currentTab].description })
21306
22413
  ),
21307
- 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 }))),
21308
22415
  !editingField && React24.createElement(
21309
- Box23,
22416
+ Box24,
21310
22417
  { flexDirection: "row-reverse" },
21311
22418
  React24.createElement(SubmitButton, { canSubmit: canSubmitForm, onSubmit: () => props.onSubmit?.(value) })
21312
22419
  )
@@ -21578,7 +22685,7 @@ function missingRequiredFields(schema, decoded, rawValues = {}) {
21578
22685
  }
21579
22686
 
21580
22687
  // src/components/ToolTestModal.tsx
21581
- 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";
21582
22689
  function ToolTestModal({
21583
22690
  tool,
21584
22691
  inspectorClient,
@@ -21704,8 +22811,8 @@ function ToolTestModal({
21704
22811
  };
21705
22812
  const modalWidth = terminalDimensions.width - 2;
21706
22813
  const modalHeight = terminalDimensions.height - 2;
21707
- return /* @__PURE__ */ jsx13(
21708
- Box24,
22814
+ return /* @__PURE__ */ jsx14(
22815
+ Box25,
21709
22816
  {
21710
22817
  position: "absolute",
21711
22818
  width: terminalDimensions.width,
@@ -21713,8 +22820,8 @@ function ToolTestModal({
21713
22820
  flexDirection: "column",
21714
22821
  justifyContent: "center",
21715
22822
  alignItems: "center",
21716
- children: /* @__PURE__ */ jsxs12(
21717
- Box24,
22823
+ children: /* @__PURE__ */ jsxs13(
22824
+ Box25,
21718
22825
  {
21719
22826
  width: modalWidth,
21720
22827
  height: modalHeight,
@@ -21725,40 +22832,40 @@ function ToolTestModal({
21725
22832
  paddingY: 1,
21726
22833
  backgroundColor: "black",
21727
22834
  children: [
21728
- /* @__PURE__ */ jsxs12(Box24, { flexShrink: 0, marginBottom: 1, children: [
21729
- /* @__PURE__ */ jsx13(Text21, { bold: true, color: "cyan", children: formStructure.title }),
21730
- /* @__PURE__ */ jsx13(Text21, { children: " " }),
21731
- /* @__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)" })
21732
22839
  ] }),
21733
- /* @__PURE__ */ jsxs12(Box24, { flexGrow: 1, flexDirection: "column", overflow: "hidden", children: [
21734
- 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(
21735
22842
  Form,
21736
22843
  {
21737
22844
  form: formStructure,
21738
22845
  onSubmit: (value) => void handleFormSubmit(value)
21739
22846
  }
21740
22847
  ) }),
21741
- state === "loading" && /* @__PURE__ */ jsx13(Box24, { flexGrow: 1, justifyContent: "center", alignItems: "center", children: /* @__PURE__ */ jsx13(Text21, { color: "yellow", children: "Calling tool..." }) }),
21742
- state === "results" && result && /* @__PURE__ */ jsx13(Box24, { flexGrow: 1, flexDirection: "column", overflow: "hidden", children: /* @__PURE__ */ jsxs12(ScrollView, { ref: scrollViewRef, children: [
21743
- /* @__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: [
21744
22851
  "Duration: ",
21745
22852
  result.duration,
21746
22853
  "ms"
21747
22854
  ] }) }),
21748
- /* @__PURE__ */ jsxs12(Box24, { marginBottom: 1, flexShrink: 0, flexDirection: "column", children: [
21749
- /* @__PURE__ */ jsx13(Text21, { bold: true, color: "cyan", children: "Input:" }),
21750
- /* @__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) }) })
21751
22858
  ] }),
21752
- result.error ? /* @__PURE__ */ jsxs12(Box24, { flexShrink: 0, flexDirection: "column", children: [
21753
- /* @__PURE__ */ jsx13(Text21, { bold: true, color: "red", children: "Error:" }),
21754
- /* @__PURE__ */ jsx13(Box24, { paddingLeft: 2, children: /* @__PURE__ */ jsx13(Text21, { color: "red", children: String(result.error) }) }),
21755
- result.errorDetails != null ? /* @__PURE__ */ jsxs12(Fragment9, { children: [
21756
- /* @__PURE__ */ jsx13(Box24, { marginTop: 1, children: /* @__PURE__ */ jsx13(Text21, { bold: true, color: "red", dimColor: true, children: "Error Details:" }) }),
21757
- /* @__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) }) })
21758
22865
  ] }) : null
21759
- ] }) : /* @__PURE__ */ jsxs12(Box24, { flexShrink: 0, flexDirection: "column", children: [
21760
- /* @__PURE__ */ jsx13(Text21, { bold: true, color: "green", children: "Output:" }),
21761
- /* @__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) }) })
21762
22869
  ] })
21763
22870
  ] }) })
21764
22871
  ] })
@@ -21771,7 +22878,7 @@ function ToolTestModal({
21771
22878
 
21772
22879
  // src/components/ResourceTestModal.tsx
21773
22880
  import React27, { useState as useState15 } from "react";
21774
- 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";
21775
22882
 
21776
22883
  // src/utils/uriTemplateToForm.ts
21777
22884
  import { UriTemplate as UriTemplate2 } from "@modelcontextprotocol/client";
@@ -21804,7 +22911,7 @@ function uriTemplateToForm(uriTemplate, templateName) {
21804
22911
  }
21805
22912
 
21806
22913
  // src/components/ResourceTestModal.tsx
21807
- 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";
21808
22915
  function getErrorMessage(error) {
21809
22916
  if (error instanceof Error) {
21810
22917
  return error.message;
@@ -21953,8 +23060,8 @@ function ResourceTestModal({
21953
23060
  };
21954
23061
  const modalWidth = terminalDimensions.width - 2;
21955
23062
  const modalHeight = terminalDimensions.height - 2;
21956
- return /* @__PURE__ */ jsx14(
21957
- Box25,
23063
+ return /* @__PURE__ */ jsx15(
23064
+ Box26,
21958
23065
  {
21959
23066
  position: "absolute",
21960
23067
  width: terminalDimensions.width,
@@ -21962,8 +23069,8 @@ function ResourceTestModal({
21962
23069
  flexDirection: "column",
21963
23070
  justifyContent: "center",
21964
23071
  alignItems: "center",
21965
- children: /* @__PURE__ */ jsxs13(
21966
- Box25,
23072
+ children: /* @__PURE__ */ jsxs14(
23073
+ Box26,
21967
23074
  {
21968
23075
  width: modalWidth,
21969
23076
  height: modalHeight,
@@ -21974,15 +23081,15 @@ function ResourceTestModal({
21974
23081
  paddingY: 1,
21975
23082
  backgroundColor: "black",
21976
23083
  children: [
21977
- /* @__PURE__ */ jsxs13(Box25, { flexShrink: 0, marginBottom: 1, children: [
21978
- /* @__PURE__ */ jsx14(Text22, { bold: true, color: "cyan", children: formStructure.title }),
21979
- /* @__PURE__ */ jsx14(Text22, { children: " " }),
21980
- /* @__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)" })
21981
23088
  ] }),
21982
- /* @__PURE__ */ jsxs13(Box25, { flexGrow: 1, flexDirection: "column", overflow: "hidden", children: [
21983
- state === "form" && /* @__PURE__ */ jsxs13(Box25, { flexGrow: 1, flexDirection: "column", children: [
21984
- template.description && /* @__PURE__ */ jsx14(Box25, { marginBottom: 1, flexShrink: 0, children: /* @__PURE__ */ jsx14(Text22, { dimColor: true, children: template.description }) }),
21985
- /* @__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(
21986
23093
  Form,
21987
23094
  {
21988
23095
  form: formStructure,
@@ -21990,34 +23097,34 @@ function ResourceTestModal({
21990
23097
  }
21991
23098
  )
21992
23099
  ] }),
21993
- state === "loading" && /* @__PURE__ */ jsx14(Box25, { flexGrow: 1, justifyContent: "center", alignItems: "center", children: /* @__PURE__ */ jsx14(Text22, { color: "yellow", children: "Reading resource..." }) }),
21994
- state === "results" && result && /* @__PURE__ */ jsx14(Box25, { flexGrow: 1, flexDirection: "column", overflow: "hidden", children: /* @__PURE__ */ jsxs13(ScrollView, { ref: scrollViewRef, children: [
21995
- /* @__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: [
21996
23103
  "Duration: ",
21997
23104
  result.duration,
21998
23105
  "ms"
21999
23106
  ] }) }),
22000
- /* @__PURE__ */ jsxs13(Box25, { marginBottom: 1, flexShrink: 0, children: [
22001
- /* @__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: [
22002
23109
  "URI:",
22003
23110
  " "
22004
23111
  ] }),
22005
- /* @__PURE__ */ jsx14(Text22, { dimColor: true, children: result.uri })
23112
+ /* @__PURE__ */ jsx15(Text23, { dimColor: true, children: result.uri })
22006
23113
  ] }),
22007
- /* @__PURE__ */ jsxs13(Box25, { marginBottom: 1, flexShrink: 0, flexDirection: "column", children: [
22008
- /* @__PURE__ */ jsx14(Text22, { bold: true, color: "cyan", children: "Template Values:" }),
22009
- /* @__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) }) })
22010
23117
  ] }),
22011
- result.error ? /* @__PURE__ */ jsxs13(Box25, { flexShrink: 0, flexDirection: "column", children: [
22012
- /* @__PURE__ */ jsx14(Box25, { marginTop: 1, flexShrink: 0, children: /* @__PURE__ */ jsx14(Text22, { bold: true, color: "red", children: "Error:" }) }),
22013
- /* @__PURE__ */ jsx14(Box25, { marginTop: 1, paddingLeft: 2, flexShrink: 0, children: /* @__PURE__ */ jsx14(Text22, { color: "red", children: String(result.error) }) }),
22014
- result.errorDetails != null ? /* @__PURE__ */ jsxs13(Fragment10, { children: [
22015
- /* @__PURE__ */ jsx14(Box25, { marginTop: 1, flexShrink: 0, children: /* @__PURE__ */ jsx14(Text22, { bold: true, color: "red", dimColor: true, children: "Error Details:" }) }),
22016
- /* @__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) }) })
22017
23124
  ] }) : null
22018
- ] }) : /* @__PURE__ */ jsxs13(Box25, { flexShrink: 0, flexDirection: "column", children: [
22019
- /* @__PURE__ */ jsx14(Text22, { bold: true, color: "green", children: "Resource Content:" }),
22020
- /* @__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) }) })
22021
23128
  ] })
22022
23129
  ] }) })
22023
23130
  ] })
@@ -22030,7 +23137,7 @@ function ResourceTestModal({
22030
23137
 
22031
23138
  // src/components/PromptTestModal.tsx
22032
23139
  import React28, { useState as useState16 } from "react";
22033
- 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";
22034
23141
 
22035
23142
  // src/utils/promptArgsToForm.ts
22036
23143
  function promptArgsToForm(promptArguments, promptName) {
@@ -22066,7 +23173,7 @@ function promptArgsToForm(promptArguments, promptName) {
22066
23173
  }
22067
23174
 
22068
23175
  // src/components/PromptTestModal.tsx
22069
- 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";
22070
23177
  function getErrorMessage2(error) {
22071
23178
  if (error instanceof Error) {
22072
23179
  return error.message;
@@ -22188,8 +23295,8 @@ function PromptTestModal({
22188
23295
  };
22189
23296
  const modalWidth = terminalDimensions.width - 2;
22190
23297
  const modalHeight = terminalDimensions.height - 2;
22191
- return /* @__PURE__ */ jsx15(
22192
- Box26,
23298
+ return /* @__PURE__ */ jsx16(
23299
+ Box27,
22193
23300
  {
22194
23301
  position: "absolute",
22195
23302
  width: terminalDimensions.width,
@@ -22197,8 +23304,8 @@ function PromptTestModal({
22197
23304
  flexDirection: "column",
22198
23305
  justifyContent: "center",
22199
23306
  alignItems: "center",
22200
- children: /* @__PURE__ */ jsxs14(
22201
- Box26,
23307
+ children: /* @__PURE__ */ jsxs15(
23308
+ Box27,
22202
23309
  {
22203
23310
  width: modalWidth,
22204
23311
  height: modalHeight,
@@ -22209,15 +23316,15 @@ function PromptTestModal({
22209
23316
  paddingY: 1,
22210
23317
  backgroundColor: "black",
22211
23318
  children: [
22212
- /* @__PURE__ */ jsxs14(Box26, { flexShrink: 0, marginBottom: 1, children: [
22213
- /* @__PURE__ */ jsx15(Text23, { bold: true, color: "cyan", children: formStructure.title }),
22214
- /* @__PURE__ */ jsx15(Text23, { children: " " }),
22215
- /* @__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)" })
22216
23323
  ] }),
22217
- /* @__PURE__ */ jsxs14(Box26, { flexGrow: 1, flexDirection: "column", overflow: "hidden", children: [
22218
- state === "form" && /* @__PURE__ */ jsxs14(Box26, { flexGrow: 1, flexDirection: "column", children: [
22219
- prompt.description && /* @__PURE__ */ jsx15(Box26, { marginBottom: 1, flexShrink: 0, children: /* @__PURE__ */ jsx15(Text23, { dimColor: true, children: prompt.description }) }),
22220
- /* @__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(
22221
23328
  Form,
22222
23329
  {
22223
23330
  form: formStructure,
@@ -22225,27 +23332,27 @@ function PromptTestModal({
22225
23332
  }
22226
23333
  )
22227
23334
  ] }),
22228
- state === "loading" && /* @__PURE__ */ jsx15(Box26, { flexGrow: 1, justifyContent: "center", alignItems: "center", children: /* @__PURE__ */ jsx15(Text23, { color: "yellow", children: "Getting prompt..." }) }),
22229
- state === "results" && result && /* @__PURE__ */ jsx15(Box26, { flexGrow: 1, flexDirection: "column", overflow: "hidden", children: /* @__PURE__ */ jsxs14(ScrollView, { ref: scrollViewRef, children: [
22230
- /* @__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: [
22231
23338
  "Duration: ",
22232
23339
  result.duration,
22233
23340
  "ms"
22234
23341
  ] }) }),
22235
- Object.keys(result.input).length > 0 && /* @__PURE__ */ jsxs14(Box26, { marginBottom: 1, flexShrink: 0, flexDirection: "column", children: [
22236
- /* @__PURE__ */ jsx15(Text23, { bold: true, color: "cyan", children: "Arguments:" }),
22237
- /* @__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) }) })
22238
23345
  ] }),
22239
- result.error ? /* @__PURE__ */ jsxs14(Box26, { flexShrink: 0, flexDirection: "column", children: [
22240
- /* @__PURE__ */ jsx15(Box26, { marginTop: 1, flexShrink: 0, children: /* @__PURE__ */ jsx15(Text23, { bold: true, color: "red", children: "Error:" }) }),
22241
- /* @__PURE__ */ jsx15(Box26, { marginTop: 1, paddingLeft: 2, flexShrink: 0, children: /* @__PURE__ */ jsx15(Text23, { color: "red", children: String(result.error) }) }),
22242
- result.errorDetails != null ? /* @__PURE__ */ jsxs14(Fragment11, { children: [
22243
- /* @__PURE__ */ jsx15(Box26, { marginTop: 1, flexShrink: 0, children: /* @__PURE__ */ jsx15(Text23, { bold: true, color: "red", dimColor: true, children: "Error Details:" }) }),
22244
- /* @__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) }) })
22245
23352
  ] }) : null
22246
- ] }) : /* @__PURE__ */ jsxs14(Box26, { flexShrink: 0, flexDirection: "column", children: [
22247
- /* @__PURE__ */ jsx15(Text23, { bold: true, color: "green", children: "Prompt Messages:" }),
22248
- /* @__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) }) })
22249
23356
  ] })
22250
23357
  ] }) })
22251
23358
  ] })
@@ -22258,8 +23365,8 @@ function PromptTestModal({
22258
23365
 
22259
23366
  // src/components/DetailsModal.tsx
22260
23367
  import React29, { useRef as useRef14 } from "react";
22261
- import { Box as Box27, Text as Text24, useInput as useInput21 } from "ink";
22262
- 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";
22263
23370
  function DetailsModal({
22264
23371
  title,
22265
23372
  content,
@@ -22305,8 +23412,8 @@ function DetailsModal({
22305
23412
  );
22306
23413
  const modalWidth = terminalDimensions.width - 2;
22307
23414
  const modalHeight = terminalDimensions.height - 2;
22308
- return /* @__PURE__ */ jsx16(
22309
- Box27,
23415
+ return /* @__PURE__ */ jsx17(
23416
+ Box28,
22310
23417
  {
22311
23418
  position: "absolute",
22312
23419
  width: terminalDimensions.width,
@@ -22314,8 +23421,8 @@ function DetailsModal({
22314
23421
  flexDirection: "column",
22315
23422
  justifyContent: "center",
22316
23423
  alignItems: "center",
22317
- children: /* @__PURE__ */ jsxs15(
22318
- Box27,
23424
+ children: /* @__PURE__ */ jsxs16(
23425
+ Box28,
22319
23426
  {
22320
23427
  width: modalWidth,
22321
23428
  height: modalHeight,
@@ -22326,12 +23433,12 @@ function DetailsModal({
22326
23433
  paddingY: 1,
22327
23434
  backgroundColor: "black",
22328
23435
  children: [
22329
- /* @__PURE__ */ jsxs15(Box27, { flexShrink: 0, marginBottom: 1, children: [
22330
- /* @__PURE__ */ jsx16(Text24, { bold: true, color: "cyan", children: title }),
22331
- /* @__PURE__ */ jsx16(Text24, { children: " " }),
22332
- /* @__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)" })
22333
23440
  ] }),
22334
- /* @__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 }) })
22335
23442
  ]
22336
23443
  }
22337
23444
  )
@@ -22340,7 +23447,7 @@ function DetailsModal({
22340
23447
  }
22341
23448
 
22342
23449
  // src/App.tsx
22343
- 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";
22344
23451
  var APP_NAME = "MCP Inspector TUI";
22345
23452
  var APP_DESCRIPTION = "Terminal User Interface for the Model Context Protocol Inspector";
22346
23453
  var APP_VERSION = readInspectorVersion(import.meta.url);
@@ -23028,48 +24135,48 @@ function App({
23028
24135
  managedTools,
23029
24136
  inspectorStderrLogs
23030
24137
  ]);
23031
- const renderResourceDetails = (resource) => /* @__PURE__ */ jsxs16(Fragment12, { children: [
23032
- "uri" in resource && resource.description && /* @__PURE__ */ jsx17(Fragment12, { children: resource.description.split("\n").map((line, idx) => /* @__PURE__ */ jsx17(
23033
- 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,
23034
24141
  {
23035
24142
  marginTop: idx === 0 ? 0 : 0,
23036
24143
  flexShrink: 0,
23037
- children: /* @__PURE__ */ jsx17(Text25, { dimColor: true, children: line })
24144
+ children: /* @__PURE__ */ jsx18(Text26, { dimColor: true, children: line })
23038
24145
  },
23039
24146
  `desc-${idx}`
23040
24147
  )) }),
23041
- "uri" in resource && resource.uri && /* @__PURE__ */ jsxs16(Box28, { marginTop: 1, flexShrink: 0, children: [
23042
- /* @__PURE__ */ jsx17(Text25, { bold: true, children: "URI:" }),
23043
- /* @__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 }) })
23044
24151
  ] }),
23045
- "mimeType" in resource && resource.mimeType && /* @__PURE__ */ jsxs16(Box28, { marginTop: 1, flexShrink: 0, children: [
23046
- /* @__PURE__ */ jsx17(Text25, { bold: true, children: "MIME Type:" }),
23047
- /* @__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 }) })
23048
24155
  ] }),
23049
- /* @__PURE__ */ jsxs16(Box28, { marginTop: 1, flexShrink: 0, flexDirection: "column", children: [
23050
- /* @__PURE__ */ jsx17(Text25, { bold: true, children: "Full JSON:" }),
23051
- /* @__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) }) })
23052
24159
  ] })
23053
24160
  ] });
23054
- const renderPromptDetails = (prompt) => /* @__PURE__ */ jsxs16(Fragment12, { children: [
23055
- prompt.description && /* @__PURE__ */ jsx17(Fragment12, { children: prompt.description.split("\n").map((line, idx) => /* @__PURE__ */ jsx17(
23056
- 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,
23057
24164
  {
23058
24165
  marginTop: idx === 0 ? 0 : 0,
23059
24166
  flexShrink: 0,
23060
- children: /* @__PURE__ */ jsx17(Text25, { dimColor: true, children: line })
24167
+ children: /* @__PURE__ */ jsx18(Text26, { dimColor: true, children: line })
23061
24168
  },
23062
24169
  `desc-${idx}`
23063
24170
  )) }),
23064
- prompt.arguments && prompt.arguments.length > 0 && /* @__PURE__ */ jsxs16(Fragment12, { children: [
23065
- /* @__PURE__ */ jsx17(Box28, { marginTop: 1, flexShrink: 0, children: /* @__PURE__ */ jsx17(Text25, { bold: true, children: "Arguments:" }) }),
23066
- prompt.arguments.map((arg, idx) => /* @__PURE__ */ jsx17(
23067
- 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,
23068
24175
  {
23069
24176
  marginTop: 1,
23070
24177
  paddingLeft: 2,
23071
24178
  flexShrink: 0,
23072
- children: /* @__PURE__ */ jsxs16(Text25, { dimColor: true, children: [
24179
+ children: /* @__PURE__ */ jsxs17(Text26, { dimColor: true, children: [
23073
24180
  "- ",
23074
24181
  arg.name,
23075
24182
  ":",
@@ -23080,134 +24187,102 @@ function App({
23080
24187
  `arg-${idx}`
23081
24188
  ))
23082
24189
  ] }),
23083
- /* @__PURE__ */ jsxs16(Box28, { marginTop: 1, flexShrink: 0, flexDirection: "column", children: [
23084
- /* @__PURE__ */ jsx17(Text25, { bold: true, children: "Full JSON:" }),
23085
- /* @__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) }) })
23086
24193
  ] })
23087
24194
  ] });
23088
- const renderToolDetails = (tool) => /* @__PURE__ */ jsxs16(Fragment12, { children: [
23089
- tool.description && /* @__PURE__ */ jsx17(Fragment12, { children: tool.description.split("\n").map((line, idx) => /* @__PURE__ */ jsx17(
23090
- 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,
23091
24198
  {
23092
24199
  marginTop: idx === 0 ? 0 : 0,
23093
24200
  flexShrink: 0,
23094
- children: /* @__PURE__ */ jsx17(Text25, { dimColor: true, children: line })
24201
+ children: /* @__PURE__ */ jsx18(Text26, { dimColor: true, children: line })
23095
24202
  },
23096
24203
  `desc-${idx}`
23097
24204
  )) }),
23098
- tool.inputSchema && /* @__PURE__ */ jsxs16(Box28, { marginTop: 1, flexShrink: 0, flexDirection: "column", children: [
23099
- /* @__PURE__ */ jsx17(Text25, { bold: true, children: "Input Schema:" }),
23100
- /* @__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) }) })
23101
24208
  ] }),
23102
- /* @__PURE__ */ jsxs16(Box28, { marginTop: 1, flexShrink: 0, flexDirection: "column", children: [
23103
- /* @__PURE__ */ jsx17(Text25, { bold: true, children: "Full JSON:" }),
23104
- /* @__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) }) })
23105
24212
  ] })
23106
24213
  ] });
23107
- const renderRequestDetails = (request) => /* @__PURE__ */ jsxs16(Fragment12, { children: [
23108
- /* @__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: [
23109
24216
  request.method,
23110
24217
  " ",
23111
24218
  request.url
23112
24219
  ] }) }),
23113
- /* @__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: [
23114
24221
  "Category:",
23115
24222
  " ",
23116
- /* @__PURE__ */ jsx17(Text25, { children: request.category === "auth" ? "auth" : "transport" })
24223
+ /* @__PURE__ */ jsx18(Text26, { children: request.category === "auth" ? "auth" : "transport" })
23117
24224
  ] }) }),
23118
- 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: [
23119
24226
  "Status: ",
23120
24227
  request.responseStatus,
23121
24228
  " ",
23122
24229
  request.responseStatusText || ""
23123
- ] }) }) : 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: [
23124
24231
  "Error: ",
23125
24232
  request.error
23126
24233
  ] }) }) : null,
23127
- 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: [
23128
24235
  request.timestamp.toLocaleTimeString(),
23129
24236
  " (",
23130
24237
  request.duration,
23131
24238
  "ms)"
23132
24239
  ] }) }),
23133
- /* @__PURE__ */ jsxs16(Box28, { marginTop: 1, flexShrink: 0, children: [
23134
- /* @__PURE__ */ jsx17(Text25, { bold: true, children: "Request Headers:" }),
23135
- 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: [
23136
24243
  key,
23137
24244
  ": ",
23138
24245
  value
23139
24246
  ] }) }, key))
23140
24247
  ] }),
23141
- request.requestBody && /* @__PURE__ */ jsxs16(Fragment12, { children: [
23142
- /* @__PURE__ */ jsx17(Box28, { marginTop: 1, flexShrink: 0, children: /* @__PURE__ */ jsx17(Text25, { bold: true, children: "Request Body:" }) }),
23143
- (() => {
23144
- try {
23145
- const parsed = JSON.parse(request.requestBody);
23146
- return JSON.stringify(parsed, null, 2).split("\n").map((line, idx) => /* @__PURE__ */ jsx17(
23147
- Box28,
23148
- {
23149
- marginTop: idx === 0 ? 1 : 0,
23150
- paddingLeft: 2,
23151
- flexShrink: 0,
23152
- children: /* @__PURE__ */ jsx17(Text25, { dimColor: true, children: line })
23153
- },
23154
- `req-body-${idx}`
23155
- ));
23156
- } catch {
23157
- return /* @__PURE__ */ jsx17(Box28, { marginTop: 1, paddingLeft: 2, flexShrink: 0, children: /* @__PURE__ */ jsx17(Text25, { dimColor: true, children: request.requestBody }) });
23158
- }
23159
- })()
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" })
23160
24251
  ] }),
23161
- request.responseHeaders && Object.keys(request.responseHeaders).length > 0 && /* @__PURE__ */ jsxs16(Fragment12, { children: [
23162
- /* @__PURE__ */ jsx17(Box28, { marginTop: 1, flexShrink: 0, children: /* @__PURE__ */ jsx17(Text25, { bold: true, children: "Response Headers:" }) }),
23163
- 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: [
23164
24255
  key,
23165
24256
  ": ",
23166
24257
  value
23167
24258
  ] }) }, key))
23168
24259
  ] }),
23169
- request.responseBody && /* @__PURE__ */ jsxs16(Fragment12, { children: [
23170
- /* @__PURE__ */ jsx17(Box28, { marginTop: 1, flexShrink: 0, children: /* @__PURE__ */ jsx17(Text25, { bold: true, children: "Response Body:" }) }),
23171
- (() => {
23172
- try {
23173
- const parsed = JSON.parse(request.responseBody);
23174
- return JSON.stringify(parsed, null, 2).split("\n").map((line, idx) => /* @__PURE__ */ jsx17(
23175
- Box28,
23176
- {
23177
- marginTop: idx === 0 ? 1 : 0,
23178
- paddingLeft: 2,
23179
- flexShrink: 0,
23180
- children: /* @__PURE__ */ jsx17(Text25, { dimColor: true, children: line })
23181
- },
23182
- `resp-body-${idx}`
23183
- ));
23184
- } catch {
23185
- return /* @__PURE__ */ jsx17(Box28, { marginTop: 1, paddingLeft: 2, flexShrink: 0, children: /* @__PURE__ */ jsx17(Text25, { dimColor: true, children: request.responseBody }) });
23186
- }
23187
- })()
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" })
23188
24263
  ] })
23189
24264
  ] });
23190
- const renderMessageDetails = (message) => /* @__PURE__ */ jsxs16(Fragment12, { children: [
23191
- /* @__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: [
23192
24267
  "Direction: ",
23193
24268
  message.direction
23194
24269
  ] }) }),
23195
- /* @__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: [
23196
24271
  message.timestamp.toLocaleTimeString(),
23197
24272
  message.duration !== void 0 && ` (${message.duration}ms)`
23198
24273
  ] }) }),
23199
- message.direction === "request" ? /* @__PURE__ */ jsxs16(Fragment12, { children: [
23200
- /* @__PURE__ */ jsxs16(Box28, { marginTop: 1, flexShrink: 0, flexDirection: "column", children: [
23201
- /* @__PURE__ */ jsx17(Text25, { bold: true, children: "Request:" }),
23202
- /* @__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) }) })
23203
24278
  ] }),
23204
- message.response && /* @__PURE__ */ jsxs16(Box28, { marginTop: 1, flexShrink: 0, flexDirection: "column", children: [
23205
- /* @__PURE__ */ jsx17(Text25, { bold: true, children: "Response:" }),
23206
- /* @__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) }) })
23207
24282
  ] })
23208
- ] }) : /* @__PURE__ */ jsxs16(Box28, { marginTop: 1, flexShrink: 0, flexDirection: "column", children: [
23209
- /* @__PURE__ */ jsx17(Text25, { bold: true, children: message.direction === "response" ? "Response:" : "Notification:" }),
23210
- /* @__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) }) })
23211
24286
  ] })
23212
24287
  ] });
23213
24288
  useEffect14(() => {
@@ -23398,15 +24473,15 @@ function App({
23398
24473
  return "\u25CB";
23399
24474
  }
23400
24475
  };
23401
- return /* @__PURE__ */ jsxs16(
23402
- Box28,
24476
+ return /* @__PURE__ */ jsxs17(
24477
+ Box29,
23403
24478
  {
23404
24479
  flexDirection: "column",
23405
24480
  width: dimensions.width,
23406
24481
  height: dimensions.height,
23407
24482
  children: [
23408
- /* @__PURE__ */ jsxs16(
23409
- Box28,
24483
+ /* @__PURE__ */ jsxs17(
24484
+ Box29,
23410
24485
  {
23411
24486
  width: dimensions.width,
23412
24487
  height: headerHeight,
@@ -23418,29 +24493,29 @@ function App({
23418
24493
  justifyContent: "space-between",
23419
24494
  alignItems: "center",
23420
24495
  children: [
23421
- /* @__PURE__ */ jsxs16(Box28, { children: [
23422
- /* @__PURE__ */ jsx17(Text25, { bold: true, color: "cyan", children: APP_NAME }),
23423
- /* @__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: [
23424
24499
  " - ",
23425
24500
  APP_DESCRIPTION
23426
24501
  ] })
23427
24502
  ] }),
23428
- /* @__PURE__ */ jsxs16(Text25, { dimColor: true, children: [
24503
+ /* @__PURE__ */ jsxs17(Text26, { dimColor: true, children: [
23429
24504
  "v",
23430
24505
  APP_VERSION
23431
24506
  ] })
23432
24507
  ]
23433
24508
  }
23434
24509
  ),
23435
- /* @__PURE__ */ jsxs16(
23436
- Box28,
24510
+ /* @__PURE__ */ jsxs17(
24511
+ Box29,
23437
24512
  {
23438
24513
  flexDirection: "row",
23439
24514
  height: availableHeight + tabsHeight,
23440
24515
  width: dimensions.width,
23441
24516
  children: [
23442
- /* @__PURE__ */ jsxs16(
23443
- Box28,
24517
+ /* @__PURE__ */ jsxs17(
24518
+ Box29,
23444
24519
  {
23445
24520
  width: serverListWidth,
23446
24521
  height: availableHeight + tabsHeight,
@@ -23452,43 +24527,43 @@ function App({
23452
24527
  flexDirection: "column",
23453
24528
  paddingX: 1,
23454
24529
  children: [
23455
- /* @__PURE__ */ jsx17(Box28, { marginTop: 1, marginBottom: 1, children: /* @__PURE__ */ jsx17(
23456
- Text25,
24530
+ /* @__PURE__ */ jsx18(Box29, { marginTop: 1, marginBottom: 1, children: /* @__PURE__ */ jsx18(
24531
+ Text26,
23457
24532
  {
23458
24533
  bold: true,
23459
24534
  backgroundColor: focus === "serverList" ? "yellow" : void 0,
23460
24535
  children: "MCP Servers"
23461
24536
  }
23462
24537
  ) }),
23463
- /* @__PURE__ */ jsx17(Box28, { flexDirection: "column", flexGrow: 1, children: serverNames.map((serverName) => {
24538
+ /* @__PURE__ */ jsx18(Box29, { flexDirection: "column", flexGrow: 1, children: serverNames.map((serverName) => {
23464
24539
  const isSelected = selectedServer === serverName;
23465
- return /* @__PURE__ */ jsx17(Box28, { paddingY: 0, children: /* @__PURE__ */ jsxs16(Text25, { children: [
24540
+ return /* @__PURE__ */ jsx18(Box29, { paddingY: 0, children: /* @__PURE__ */ jsxs17(Text26, { children: [
23466
24541
  isSelected ? "\u25B6 " : " ",
23467
24542
  serverName
23468
24543
  ] }) }, serverName);
23469
24544
  }) }),
23470
- /* @__PURE__ */ jsx17(
23471
- Box28,
24545
+ /* @__PURE__ */ jsx18(
24546
+ Box29,
23472
24547
  {
23473
24548
  flexShrink: 0,
23474
24549
  height: 1,
23475
24550
  justifyContent: "center",
23476
24551
  backgroundColor: "gray",
23477
- 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" })
23478
24553
  }
23479
24554
  )
23480
24555
  ]
23481
24556
  }
23482
24557
  ),
23483
- /* @__PURE__ */ jsxs16(
23484
- Box28,
24558
+ /* @__PURE__ */ jsxs17(
24559
+ Box29,
23485
24560
  {
23486
24561
  flexGrow: 1,
23487
24562
  height: availableHeight + tabsHeight,
23488
24563
  flexDirection: "column",
23489
24564
  children: [
23490
- /* @__PURE__ */ jsx17(
23491
- Box28,
24565
+ /* @__PURE__ */ jsx18(
24566
+ Box29,
23492
24567
  {
23493
24568
  width: contentWidth,
23494
24569
  borderStyle: "single",
@@ -23500,49 +24575,49 @@ function App({
23500
24575
  paddingY: 1,
23501
24576
  flexDirection: "column",
23502
24577
  flexShrink: 0,
23503
- children: /* @__PURE__ */ jsxs16(Box28, { flexDirection: "column", children: [
23504
- /* @__PURE__ */ jsxs16(
23505
- Box28,
24578
+ children: /* @__PURE__ */ jsxs17(Box29, { flexDirection: "column", children: [
24579
+ /* @__PURE__ */ jsxs17(
24580
+ Box29,
23506
24581
  {
23507
24582
  flexDirection: "row",
23508
24583
  justifyContent: "space-between",
23509
24584
  alignItems: "center",
23510
24585
  children: [
23511
- /* @__PURE__ */ jsx17(Text25, { bold: true, color: "cyan", children: selectedServer }),
23512
- /* @__PURE__ */ jsx17(Box28, { flexDirection: "row", alignItems: "center", gap: 1, children: currentServerState && /* @__PURE__ */ jsxs16(Fragment12, { children: [
23513
- /* @__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: [
23514
24589
  getStatusSymbol(currentServerState.status),
23515
24590
  " ",
23516
24591
  currentServerState.status
23517
24592
  ] }),
23518
- /* @__PURE__ */ jsx17(Text25, { children: " " }),
23519
- (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: [
23520
24595
  "[",
23521
- /* @__PURE__ */ jsx17(Text25, { underline: true, children: "C" }),
24596
+ /* @__PURE__ */ jsx18(Text26, { underline: true, children: "C" }),
23522
24597
  "onnect]"
23523
24598
  ] }),
23524
- (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: [
23525
24600
  "[",
23526
- /* @__PURE__ */ jsx17(Text25, { underline: true, children: "D" }),
24601
+ /* @__PURE__ */ jsx18(Text26, { underline: true, children: "D" }),
23527
24602
  "isconnect]"
23528
24603
  ] })
23529
24604
  ] }) })
23530
24605
  ]
23531
24606
  }
23532
24607
  ),
23533
- oauthStatus === "authenticating" && /* @__PURE__ */ jsx17(Box28, { marginTop: 1, children: /* @__PURE__ */ jsx17(Text25, { dimColor: true, children: "OAuth: authenticating\u2026" }) }),
23534
- 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: [
23535
24610
  "OAuth: ",
23536
24611
  oauthMessage
23537
24612
  ] }) }),
23538
- 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: [
23539
24614
  "Disconnect failed: ",
23540
24615
  disconnectError
23541
24616
  ] }) })
23542
24617
  ] })
23543
24618
  }
23544
24619
  ),
23545
- /* @__PURE__ */ jsx17(
24620
+ /* @__PURE__ */ jsx18(
23546
24621
  Tabs,
23547
24622
  {
23548
24623
  activeTab,
@@ -23559,8 +24634,8 @@ function App({
23559
24634
  })() : false
23560
24635
  }
23561
24636
  ),
23562
- /* @__PURE__ */ jsxs16(
23563
- Box28,
24637
+ /* @__PURE__ */ jsxs17(
24638
+ Box29,
23564
24639
  {
23565
24640
  flexGrow: 1,
23566
24641
  minHeight: 6,
@@ -23570,7 +24645,7 @@ function App({
23570
24645
  borderRight: false,
23571
24646
  borderBottom: false,
23572
24647
  children: [
23573
- activeTab === "info" && /* @__PURE__ */ jsx17(
24648
+ activeTab === "info" && /* @__PURE__ */ jsx18(
23574
24649
  InfoTab,
23575
24650
  {
23576
24651
  serverName: selectedServer,
@@ -23582,7 +24657,7 @@ function App({
23582
24657
  focused: focus === "tabContentList" || focus === "tabContentDetails"
23583
24658
  }
23584
24659
  ),
23585
- activeTab === "auth" && selectedServer && selectedServerConfig && isOAuthCapableServerConfig(selectedServerConfig) ? /* @__PURE__ */ jsx17(
24660
+ activeTab === "auth" && selectedServer && selectedServerConfig && isOAuthCapableServerConfig(selectedServerConfig) ? /* @__PURE__ */ jsx18(
23586
24661
  AuthTab,
23587
24662
  {
23588
24663
  serverName: selectedServer,
@@ -23680,7 +24755,7 @@ function App({
23680
24755
  connectionStatus: inspectorStatus
23681
24756
  }
23682
24757
  ) : null,
23683
- activeTab === "resources" && currentServerState?.status === "connected" && selectedInspectorClient ? /* @__PURE__ */ jsx17(
24758
+ activeTab === "resources" && currentServerState?.status === "connected" && selectedInspectorClient ? /* @__PURE__ */ jsx18(
23684
24759
  ResourcesTab,
23685
24760
  {
23686
24761
  resources: currentServerState.resources,
@@ -23706,7 +24781,7 @@ function App({
23706
24781
  modalOpen: !!(toolTestModal || resourceTestModal || promptTestModal || detailsModal)
23707
24782
  },
23708
24783
  `resources-${selectedServer}`
23709
- ) : activeTab === "skills" && currentServerState?.status === "connected" && selectedInspectorClient ? /* @__PURE__ */ jsx17(
24784
+ ) : activeTab === "skills" && currentServerState?.status === "connected" && selectedInspectorClient ? /* @__PURE__ */ jsx18(
23710
24785
  SkillsTab,
23711
24786
  {
23712
24787
  skills: managedSkills,
@@ -23720,7 +24795,7 @@ function App({
23720
24795
  modalOpen: !!(toolTestModal || resourceTestModal || promptTestModal || detailsModal)
23721
24796
  },
23722
24797
  `skills-${selectedServer}`
23723
- ) : activeTab === "prompts" && currentServerState?.status === "connected" && selectedInspectorClient ? /* @__PURE__ */ jsx17(
24798
+ ) : activeTab === "prompts" && currentServerState?.status === "connected" && selectedInspectorClient ? /* @__PURE__ */ jsx18(
23724
24799
  PromptsTab,
23725
24800
  {
23726
24801
  prompts: currentServerState.prompts,
@@ -23743,7 +24818,7 @@ function App({
23743
24818
  modalOpen: !!(toolTestModal || resourceTestModal || promptTestModal || detailsModal)
23744
24819
  },
23745
24820
  `prompts-${selectedServer}`
23746
- ) : activeTab === "tools" && currentServerState?.status === "connected" && selectedInspectorClient ? /* @__PURE__ */ jsx17(
24821
+ ) : activeTab === "tools" && currentServerState?.status === "connected" && selectedInspectorClient ? /* @__PURE__ */ jsx18(
23747
24822
  ToolsTab,
23748
24823
  {
23749
24824
  tools: currentServerState.tools,
@@ -23763,7 +24838,7 @@ function App({
23763
24838
  modalOpen: !!(toolTestModal || detailsModal)
23764
24839
  },
23765
24840
  `tools-${selectedServer}`
23766
- ) : activeTab === "messages" && selectedInspectorClient ? /* @__PURE__ */ jsx17(
24841
+ ) : activeTab === "messages" && selectedInspectorClient ? /* @__PURE__ */ jsx18(
23767
24842
  HistoryTab,
23768
24843
  {
23769
24844
  serverName: selectedServer,
@@ -23781,7 +24856,7 @@ function App({
23781
24856
  });
23782
24857
  }
23783
24858
  }
23784
- ) : activeTab === "requests" && selectedInspectorClient && (inspectorStatus === "connected" || inspectorFetchRequests.length > 0) ? /* @__PURE__ */ jsx17(
24859
+ ) : activeTab === "requests" && selectedInspectorClient && (inspectorStatus === "connected" || inspectorFetchRequests.length > 0) ? /* @__PURE__ */ jsx18(
23785
24860
  RequestsTab,
23786
24861
  {
23787
24862
  serverName: selectedServer,
@@ -23798,7 +24873,7 @@ function App({
23798
24873
  });
23799
24874
  }
23800
24875
  }
23801
- ) : activeTab === "logging" && selectedInspectorClient ? /* @__PURE__ */ jsx17(
24876
+ ) : activeTab === "logging" && selectedInspectorClient ? /* @__PURE__ */ jsx18(
23802
24877
  NotificationsTab,
23803
24878
  {
23804
24879
  stderrLogs: inspectorStderrLogs,
@@ -23817,7 +24892,7 @@ function App({
23817
24892
  ]
23818
24893
  }
23819
24894
  ),
23820
- toolTestModal && /* @__PURE__ */ jsx17(
24895
+ toolTestModal && /* @__PURE__ */ jsx18(
23821
24896
  ToolTestModal,
23822
24897
  {
23823
24898
  tool: toolTestModal.tool,
@@ -23831,7 +24906,7 @@ function App({
23831
24906
  }
23832
24907
  }
23833
24908
  ),
23834
- resourceTestModal && /* @__PURE__ */ jsx17(
24909
+ resourceTestModal && /* @__PURE__ */ jsx18(
23835
24910
  ResourceTestModal,
23836
24911
  {
23837
24912
  template: resourceTestModal.template,
@@ -23845,7 +24920,7 @@ function App({
23845
24920
  }
23846
24921
  }
23847
24922
  ),
23848
- promptTestModal && /* @__PURE__ */ jsx17(
24923
+ promptTestModal && /* @__PURE__ */ jsx18(
23849
24924
  PromptTestModal,
23850
24925
  {
23851
24926
  prompt: promptTestModal.prompt,
@@ -23859,7 +24934,7 @@ function App({
23859
24934
  }
23860
24935
  }
23861
24936
  ),
23862
- detailsModal && /* @__PURE__ */ jsx17(
24937
+ detailsModal && /* @__PURE__ */ jsx18(
23863
24938
  DetailsModal,
23864
24939
  {
23865
24940
  title: detailsModal.title,
@@ -23876,7 +24951,7 @@ function App({
23876
24951
  var App_default = App;
23877
24952
 
23878
24953
  // tui.tsx
23879
- import { jsx as jsx18 } from "react/jsx-runtime";
24954
+ import { jsx as jsx19 } from "react/jsx-runtime";
23880
24955
  async function runTui(args) {
23881
24956
  const program = new Command();
23882
24957
  program.name("mcp-inspector-tui").description("Terminal UI for MCP Inspector").option(
@@ -23965,7 +25040,7 @@ async function runTui(args) {
23965
25040
  process.stdout.write("\x1B[?1049h");
23966
25041
  }
23967
25042
  const instance = render2(
23968
- /* @__PURE__ */ jsx18(
25043
+ /* @__PURE__ */ jsx19(
23969
25044
  App_default,
23970
25045
  {
23971
25046
  mcpServers,