@modelcontextprotocol/inspector 2.13.0 → 2.14.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.
Files changed (32) hide show
  1. package/README.md +1 -1
  2. package/clients/cli/build/index.js +1013 -80
  3. package/clients/mcpdo/build/mcp-bin.js +50 -22
  4. package/clients/mcpdo/build/mcpdod.js +1 -1
  5. package/clients/mcpdo/build/{server-BHuKGkMj.js → server-Dv339Ejx.js} +886 -48
  6. package/clients/tui/build/index.js +781 -46
  7. package/clients/web/build/index.js +223 -124
  8. package/clients/web/dist/assets/fredoka-normal-hebrew-CjvktpUN.woff2 +0 -0
  9. package/clients/web/dist/assets/fredoka-normal-latin-DOQG_Jwn.woff2 +0 -0
  10. package/clients/web/dist/assets/fredoka-normal-latin-ext-tYNUQHO6.woff2 +0 -0
  11. package/clients/web/dist/assets/index-BCud2uMC.js +1594 -0
  12. package/clients/web/dist/assets/{index-dqp8Sd8W.css → index-Dval2a7I.css} +1 -1
  13. package/clients/web/dist/assets/{prism-light-BIhJtJkv.js → prism-light-CoVRM9R2.js} +1 -1
  14. package/clients/web/dist/assets/roboto-mono-italic-cyrillic-C1E63de8.woff2 +0 -0
  15. package/clients/web/dist/assets/roboto-mono-italic-cyrillic-ext-DR9ovEqT.woff2 +0 -0
  16. package/clients/web/dist/assets/roboto-mono-italic-greek-Cs2u2nVh.woff2 +0 -0
  17. package/clients/web/dist/assets/roboto-mono-italic-latin-D_P-kX1t.woff2 +0 -0
  18. package/clients/web/dist/assets/roboto-mono-italic-latin-ext-CErTcBzw.woff2 +0 -0
  19. package/clients/web/dist/assets/roboto-mono-italic-vietnamese-D4UvzJMM.woff2 +0 -0
  20. package/clients/web/dist/assets/roboto-mono-normal-cyrillic-DfzWIUPd.woff2 +0 -0
  21. package/clients/web/dist/assets/roboto-mono-normal-cyrillic-ext-D8QBEkUe.woff2 +0 -0
  22. package/clients/web/dist/assets/roboto-mono-normal-greek-DlC4X1lQ.woff2 +0 -0
  23. package/clients/web/dist/assets/roboto-mono-normal-latin-BAKpfWyj.woff2 +0 -0
  24. package/clients/web/dist/assets/roboto-mono-normal-latin-ext-CSSVNFqV.woff2 +0 -0
  25. package/clients/web/dist/assets/roboto-mono-normal-vietnamese-DFkHeOHB.woff2 +0 -0
  26. package/clients/web/dist/fonts/Fredoka-OFL.txt +93 -0
  27. package/clients/web/dist/fonts/RobotoMono-OFL.txt +93 -0
  28. package/clients/web/dist/index.html +2 -5
  29. package/clients/web/static/sandbox_proxy.html +177 -6
  30. package/package.json +5 -4
  31. package/skills/mcpdo/SKILL.md +14 -0
  32. package/clients/web/dist/assets/index-BqEbhCDX.js +0 -1587
@@ -31,7 +31,10 @@ import { runtimeCodecFromStandardSchema, taskId, toJsonValue } from "@modelconte
31
31
  import { CallToolResultSchema, ElicitResultSchema, EmptyResultSchema, GetPromptResultSchema, ListPromptsResultSchema, ListResourceTemplatesResultSchema, ListResourcesResultSchema, ListToolsResultSchema, NotificationSchema, OAuthClientInformationSchema, OAuthMetadataSchema, OAuthTokensSchema, OpenIdProviderDiscoveryMetadataSchema, ProgressTokenSchema, PromptSchema, ReadResourceResultSchema, RequestMetaSchema, ResourceSchema, ResourceTemplateSchema, TaskStatusNotificationSchema, ToolSchema } from "@modelcontextprotocol/core";
32
32
  import { TASKS_EXTENSION_ID_V2 as TASKS_EXTENSION_KEY } from "@modelcontextprotocol/ext-tasks/core/v2";
33
33
  import { RESOURCE_MIME_TYPE } from "@modelcontextprotocol/ext-apps/app-bridge";
34
- import { AjvJsonSchemaValidator } from "@modelcontextprotocol/client/validators/ajv";
34
+ import Ajv from "ajv";
35
+ import { Ajv2019 } from "ajv/dist/2019.js";
36
+ import { Ajv2020 } from "ajv/dist/2020.js";
37
+ import { addFormats } from "@modelcontextprotocol/client/validators/ajv";
35
38
  import { createServer } from "node:http";
36
39
  import pino from "pino";
37
40
  import open from "open";
@@ -1607,6 +1610,14 @@ function expectedSecretFields(stored) {
1607
1610
  if (isStdioStored(stored) && stored.env) for (const k of Object.keys(stored.env)) fields.push(envSecretField(k));
1608
1611
  return fields;
1609
1612
  }
1613
+ function adHocServerName(config) {
1614
+ if (config.type === "sse" || config.type === "streamable-http") try {
1615
+ return new URL(config.url).host || "server";
1616
+ } catch {
1617
+ return "server";
1618
+ }
1619
+ return config.command?.split(/[\\/]/).pop() || "server";
1620
+ }
1610
1621
  //#endregion
1611
1622
  //#region ../../core/storage/own-entry.ts
1612
1623
  function setOwnEntry(map, key, value) {
@@ -2996,8 +3007,9 @@ async function loadServerEntries(serverOptions) {
2996
3007
  }
2997
3008
  const configs = resolveServerConfigs(serverOptions, "multi");
2998
3009
  if (configs.length === 0) throw new Error("At least one server is required. Use --catalog/--config <path> or an ad-hoc target (command/URL).");
2999
- return { default: {
3000
- config: configs[0],
3010
+ const config = configs[0];
3011
+ return { [adHocServerName(config)]: {
3012
+ config,
3001
3013
  settings: mergeSettings(void 0, serverOptions)
3002
3014
  } };
3003
3015
  }
@@ -5182,6 +5194,627 @@ function validateToolOutput(provider, tool, result) {
5182
5194
  return;
5183
5195
  }
5184
5196
  }
5197
+ //#endregion
5198
+ //#region ../../core/json/linearRegExp.ts
5199
+ var CharMatcher = class {
5200
+ re;
5201
+ ascii = /* @__PURE__ */ new Uint8Array(128);
5202
+ constructor(source, unicode) {
5203
+ this.re = new RegExp(`^(?:${source})$`, unicode ? "u" : "");
5204
+ }
5205
+ matches(cp, unicode) {
5206
+ if (cp < 128) {
5207
+ const memo = this.ascii[cp];
5208
+ if (memo !== 0) return memo === 1;
5209
+ const result = this.re.test(String.fromCharCode(cp));
5210
+ this.ascii[cp] = result ? 1 : 2;
5211
+ return result;
5212
+ }
5213
+ return this.re.test(unicode ? String.fromCodePoint(cp) : String.fromCharCode(cp));
5214
+ }
5215
+ };
5216
+ var Unsupported = class extends Error {};
5217
+ const MAX_GROUP_DEPTH = 64;
5218
+ const MAX_PROGRAM_SIZE = 1e4;
5219
+ const MAX_COMPILE_STEPS = 10 * MAX_PROGRAM_SIZE;
5220
+ const MAX_PATTERN_LENGTH = 8192;
5221
+ const COMPILE_BUDGET_EXHAUSTED = "the patterns together exceed the compilation budget";
5222
+ function isCompileBudgetExhausted(budget) {
5223
+ return budget.steps < 0 || budget.size < 0;
5224
+ }
5225
+ const QUANTIFIER_BRACES = /\{(\d+)(?:(,)(\d*))?\}/y;
5226
+ const HEX4 = /^[0-9a-fA-F]{4}$/;
5227
+ const HEX2 = /^[0-9a-fA-F]{2}$/;
5228
+ var Parser = class {
5229
+ pos = 0;
5230
+ src;
5231
+ unicode;
5232
+ constructor(src, unicode) {
5233
+ this.src = src;
5234
+ this.unicode = unicode;
5235
+ }
5236
+ parse() {
5237
+ const node = this.parseAlternation(0);
5238
+ /* v8 ignore next -- the native RegExp constructor rejects an unbalanced `)` first */
5239
+ if (this.pos !== this.src.length) throw new Unsupported("unbalanced group");
5240
+ return node;
5241
+ }
5242
+ parseAlternation(depth) {
5243
+ const options = [this.parseSequence(depth)];
5244
+ while (this.src[this.pos] === "|") {
5245
+ this.pos++;
5246
+ options.push(this.parseSequence(depth));
5247
+ }
5248
+ return options.length === 1 ? options[0] : {
5249
+ kind: "alt",
5250
+ options
5251
+ };
5252
+ }
5253
+ parseSequence(depth) {
5254
+ const items = [];
5255
+ while (this.pos < this.src.length && this.src[this.pos] !== "|" && this.src[this.pos] !== ")") items.push(this.parseTerm(depth));
5256
+ return items.length === 1 ? items[0] : {
5257
+ kind: "seq",
5258
+ items
5259
+ };
5260
+ }
5261
+ parseTerm(depth) {
5262
+ const atom = this.parseAtom(depth);
5263
+ const quantifier = this.readQuantifier();
5264
+ if (!quantifier) return atom;
5265
+ if (this.src[this.pos] === "?") this.pos++;
5266
+ return {
5267
+ kind: "repeat",
5268
+ body: atom,
5269
+ ...quantifier
5270
+ };
5271
+ }
5272
+ readQuantifier() {
5273
+ const c = this.src[this.pos];
5274
+ if (c === "*") {
5275
+ this.pos++;
5276
+ return {
5277
+ min: 0,
5278
+ max: Infinity
5279
+ };
5280
+ }
5281
+ if (c === "+") {
5282
+ this.pos++;
5283
+ return {
5284
+ min: 1,
5285
+ max: Infinity
5286
+ };
5287
+ }
5288
+ if (c === "?") {
5289
+ this.pos++;
5290
+ return {
5291
+ min: 0,
5292
+ max: 1
5293
+ };
5294
+ }
5295
+ if (c === "{") {
5296
+ QUANTIFIER_BRACES.lastIndex = this.pos;
5297
+ const m = QUANTIFIER_BRACES.exec(this.src);
5298
+ if (!m) return void 0;
5299
+ this.pos += m[0].length;
5300
+ const min = Number(m[1]);
5301
+ return {
5302
+ min,
5303
+ max: m[2] === void 0 ? min : m[3] ? Number(m[3]) : Infinity
5304
+ };
5305
+ }
5306
+ }
5307
+ parseAtom(depth) {
5308
+ switch (this.src[this.pos]) {
5309
+ case "(": return this.parseGroup(depth);
5310
+ case "[": return this.parseClass();
5311
+ case "\\": return this.parseEscape();
5312
+ case ".":
5313
+ this.pos++;
5314
+ return {
5315
+ kind: "char",
5316
+ source: "."
5317
+ };
5318
+ case "^":
5319
+ this.pos++;
5320
+ return {
5321
+ kind: "assert",
5322
+ assertion: "start"
5323
+ };
5324
+ case "$":
5325
+ this.pos++;
5326
+ return {
5327
+ kind: "assert",
5328
+ assertion: "end"
5329
+ };
5330
+ case "*":
5331
+ case "+":
5332
+ case "?":
5333
+ /* v8 ignore next -- "nothing to repeat" is a native syntax error */
5334
+ throw new Unsupported("nothing to repeat");
5335
+ case "{":
5336
+ QUANTIFIER_BRACES.lastIndex = this.pos;
5337
+ if (QUANTIFIER_BRACES.test(this.src))
5338
+ /* v8 ignore next -- rejected by the native RegExp constructor first */
5339
+ throw new Unsupported("nothing to repeat");
5340
+ this.pos++;
5341
+ return {
5342
+ kind: "char",
5343
+ source: "\\{"
5344
+ };
5345
+ default: {
5346
+ const width = this.codePointWidth(this.pos);
5347
+ const source = this.src.slice(this.pos, this.pos + width);
5348
+ this.pos += width;
5349
+ return {
5350
+ kind: "char",
5351
+ source
5352
+ };
5353
+ }
5354
+ }
5355
+ }
5356
+ codePointWidth(at) {
5357
+ if (!this.unicode) return 1;
5358
+ return this.src.codePointAt(at) > 65535 ? 2 : 1;
5359
+ }
5360
+ parseGroup(depth) {
5361
+ if (depth >= MAX_GROUP_DEPTH) throw new Unsupported("groups nested too deeply");
5362
+ this.pos++;
5363
+ if (this.src.startsWith("?:", this.pos)) this.pos += 2;
5364
+ else if (this.src.startsWith("?<", this.pos) && this.src[this.pos + 2] !== "=" && this.src[this.pos + 2] !== "!") {
5365
+ const close = this.src.indexOf(">", this.pos);
5366
+ /* v8 ignore next -- an unterminated group name is a native syntax error */
5367
+ if (close < 0) throw new Unsupported("unterminated group name");
5368
+ this.pos = close + 1;
5369
+ } else if (this.src[this.pos] === "?") throw new Unsupported("lookaround or group modifier");
5370
+ const body = this.parseAlternation(depth + 1);
5371
+ /* v8 ignore next -- an unterminated group is a native syntax error */
5372
+ if (this.src[this.pos] !== ")") throw new Unsupported("unterminated group");
5373
+ this.pos++;
5374
+ return body;
5375
+ }
5376
+ parseClass() {
5377
+ const start = this.pos;
5378
+ this.pos++;
5379
+ while (this.pos < this.src.length && this.src[this.pos] !== "]") this.pos += this.src[this.pos] === "\\" ? 2 : 1;
5380
+ /* v8 ignore next -- an unterminated class is a native syntax error */
5381
+ if (this.pos >= this.src.length) throw new Unsupported("unterminated class");
5382
+ this.pos++;
5383
+ return {
5384
+ kind: "char",
5385
+ source: this.src.slice(start, this.pos)
5386
+ };
5387
+ }
5388
+ parseEscape() {
5389
+ const next = this.src[this.pos + 1];
5390
+ /* v8 ignore next -- a trailing backslash is a native syntax error */
5391
+ if (next === void 0) throw new Unsupported("trailing backslash");
5392
+ switch (next) {
5393
+ case "b":
5394
+ this.pos += 2;
5395
+ return {
5396
+ kind: "assert",
5397
+ assertion: "wordBoundary"
5398
+ };
5399
+ case "B":
5400
+ this.pos += 2;
5401
+ return {
5402
+ kind: "assert",
5403
+ assertion: "notWordBoundary"
5404
+ };
5405
+ case "1":
5406
+ case "2":
5407
+ case "3":
5408
+ case "4":
5409
+ case "5":
5410
+ case "6":
5411
+ case "7":
5412
+ case "8":
5413
+ case "9":
5414
+ case "k": throw new Unsupported("backreference");
5415
+ case "0":
5416
+ if (/[0-9]/.test(this.src[this.pos + 2] ?? "")) throw new Unsupported("octal escape");
5417
+ return this.takeChar(2);
5418
+ case "c":
5419
+ if (!/[a-zA-Z]/.test(this.src[this.pos + 2] ?? "")) throw new Unsupported("incomplete control escape");
5420
+ return this.takeChar(3);
5421
+ case "p":
5422
+ case "P":
5423
+ if (this.unicode && this.src[this.pos + 2] === "{") return this.takeThrough("}");
5424
+ return this.takeChar(2);
5425
+ case "x": return this.takeChar(HEX2.test(this.src.slice(this.pos + 2, this.pos + 4)) ? 4 : 2);
5426
+ case "u": return this.parseUnicodeEscape();
5427
+ default: return this.takeChar(1 + this.codePointWidth(this.pos + 1));
5428
+ }
5429
+ }
5430
+ parseUnicodeEscape() {
5431
+ if (this.unicode && this.src[this.pos + 2] === "{") return this.takeThrough("}");
5432
+ const hex = this.src.slice(this.pos + 2, this.pos + 6);
5433
+ if (!HEX4.test(hex)) return this.takeChar(2);
5434
+ const unit = parseInt(hex, 16);
5435
+ if (this.unicode && unit >= 55296 && unit <= 56319 && this.src.startsWith("\\u", this.pos + 6)) {
5436
+ const low = this.src.slice(this.pos + 8, this.pos + 12);
5437
+ if (HEX4.test(low)) {
5438
+ const lowUnit = parseInt(low, 16);
5439
+ if (lowUnit >= 56320 && lowUnit <= 57343) return this.takeChar(12);
5440
+ }
5441
+ }
5442
+ return this.takeChar(6);
5443
+ }
5444
+ takeChar(length) {
5445
+ const source = this.src.slice(this.pos, this.pos + length);
5446
+ this.pos += length;
5447
+ return {
5448
+ kind: "char",
5449
+ source
5450
+ };
5451
+ }
5452
+ takeThrough(terminator) {
5453
+ const end = this.src.indexOf(terminator, this.pos);
5454
+ /* v8 ignore next -- an unterminated `\p{` / `\u{` is a native syntax error */
5455
+ if (end < 0) throw new Unsupported("unterminated escape");
5456
+ return this.takeChar(end + 1 - this.pos);
5457
+ }
5458
+ };
5459
+ var Compiler = class {
5460
+ prog = [];
5461
+ matchers = /* @__PURE__ */ new Map();
5462
+ unicode;
5463
+ budget;
5464
+ steps = 0;
5465
+ constructor(unicode, budget) {
5466
+ this.unicode = unicode;
5467
+ this.budget = budget;
5468
+ }
5469
+ emit(inst) {
5470
+ if (this.prog.length >= 1e4) throw new Unsupported("pattern too complex");
5471
+ if (this.budget && --this.budget.size < 0) throw new Unsupported(COMPILE_BUDGET_EXHAUSTED);
5472
+ this.prog.push(inst);
5473
+ return this.prog.length - 1;
5474
+ }
5475
+ matcher(source) {
5476
+ let matcher = this.matchers.get(source);
5477
+ if (!matcher) {
5478
+ try {
5479
+ matcher = new CharMatcher(source, this.unicode);
5480
+ } catch {
5481
+ /* v8 ignore start -- defensive: each atom is a slice the native constructor already accepted in context */
5482
+ throw new Unsupported("unrecognized character syntax");
5483
+ }
5484
+ this.matchers.set(source, matcher);
5485
+ }
5486
+ return matcher;
5487
+ }
5488
+ compile(node) {
5489
+ if (++this.steps > 1e5) throw new Unsupported("pattern too complex");
5490
+ if (this.budget && --this.budget.steps < 0) throw new Unsupported(COMPILE_BUDGET_EXHAUSTED);
5491
+ switch (node.kind) {
5492
+ case "char":
5493
+ this.emit({
5494
+ op: "char",
5495
+ matcher: this.matcher(node.source)
5496
+ });
5497
+ return;
5498
+ case "assert":
5499
+ this.emit({
5500
+ op: "assert",
5501
+ assertion: node.assertion
5502
+ });
5503
+ return;
5504
+ case "seq":
5505
+ for (const item of node.items) this.compile(item);
5506
+ return;
5507
+ case "alt":
5508
+ this.compileAlternation(node.options);
5509
+ return;
5510
+ case "repeat":
5511
+ this.compileRepeat(node.body, node.min, node.max);
5512
+ return;
5513
+ }
5514
+ }
5515
+ compileAlternation(options) {
5516
+ const jumps = [];
5517
+ for (let i = 0; i < options.length - 1; i++) {
5518
+ const split = this.emit({
5519
+ op: "split",
5520
+ a: 0,
5521
+ b: 0
5522
+ });
5523
+ this.patchSplit(split, split + 1, -1);
5524
+ this.compile(options[i]);
5525
+ jumps.push(this.emit({
5526
+ op: "jmp",
5527
+ to: 0
5528
+ }));
5529
+ this.patchSplit(split, -1, this.prog.length);
5530
+ }
5531
+ this.compile(options[options.length - 1]);
5532
+ for (const jump of jumps) this.patchJump(jump, this.prog.length);
5533
+ }
5534
+ compileRepeat(body, min, max) {
5535
+ for (let i = 0; i < min; i++) {
5536
+ const before = this.prog.length;
5537
+ this.compile(body);
5538
+ if (this.prog.length === before) return;
5539
+ }
5540
+ if (max === Infinity) {
5541
+ const split = this.emit({
5542
+ op: "split",
5543
+ a: 0,
5544
+ b: 0
5545
+ });
5546
+ this.compile(body);
5547
+ this.emit({
5548
+ op: "jmp",
5549
+ to: split
5550
+ });
5551
+ this.patchSplit(split, split + 1, this.prog.length);
5552
+ return;
5553
+ }
5554
+ const splits = [];
5555
+ for (let i = min; i < max; i++) {
5556
+ const split = this.emit({
5557
+ op: "split",
5558
+ a: 0,
5559
+ b: 0
5560
+ });
5561
+ this.patchSplit(split, split + 1, -1);
5562
+ splits.push(split);
5563
+ this.compile(body);
5564
+ }
5565
+ for (const split of splits) this.patchSplit(split, -1, this.prog.length);
5566
+ }
5567
+ patchSplit(at, a, b) {
5568
+ const inst = this.prog[at];
5569
+ if (a >= 0) inst.a = a;
5570
+ if (b >= 0) inst.b = b;
5571
+ }
5572
+ patchJump(at, to) {
5573
+ this.prog[at].to = to;
5574
+ }
5575
+ };
5576
+ function isWordUnit(unit) {
5577
+ return unit >= 48 && unit <= 57 || unit >= 65 && unit <= 90 || unit >= 97 && unit <= 122 || unit === 95;
5578
+ }
5579
+ var LinearRegExp = class {
5580
+ anchoredStart;
5581
+ prog;
5582
+ unicode;
5583
+ constructor(prog, unicode) {
5584
+ this.prog = prog;
5585
+ this.unicode = unicode;
5586
+ const first = prog[0];
5587
+ this.anchoredStart = first !== void 0 && first.op === "assert" && first.assertion === "start";
5588
+ }
5589
+ get size() {
5590
+ return this.prog.length;
5591
+ }
5592
+ cost(input) {
5593
+ return (input.length + 1) * this.prog.length;
5594
+ }
5595
+ search(input, budget) {
5596
+ if (this.cost(input) > budget) return void 0;
5597
+ const prog = this.prog;
5598
+ const size = prog.length;
5599
+ const mark = new Int32Array(size).fill(-1);
5600
+ const stack = [];
5601
+ let clist = new Int32Array(size);
5602
+ let nlist = new Int32Array(size);
5603
+ const add = (list, count, start, pos, generation) => {
5604
+ stack.push(start);
5605
+ while (stack.length > 0) {
5606
+ const pc = stack.pop();
5607
+ if (mark[pc] === generation) continue;
5608
+ mark[pc] = generation;
5609
+ const inst = prog[pc];
5610
+ switch (inst.op) {
5611
+ case "match":
5612
+ stack.length = 0;
5613
+ return -1;
5614
+ case "jmp":
5615
+ stack.push(inst.to);
5616
+ break;
5617
+ case "split":
5618
+ stack.push(inst.b, inst.a);
5619
+ break;
5620
+ case "assert":
5621
+ if (this.holds(inst.assertion, input, pos)) stack.push(pc + 1);
5622
+ break;
5623
+ case "char": list[count++] = pc;
5624
+ }
5625
+ }
5626
+ return count;
5627
+ };
5628
+ let pos = 0;
5629
+ let generation = 0;
5630
+ let clen = add(clist, 0, 0, pos, generation);
5631
+ if (clen < 0) return true;
5632
+ while (pos < input.length) {
5633
+ if (this.anchoredStart && clen === 0) return false;
5634
+ const cp = this.unicode ? input.codePointAt(pos) : input.charCodeAt(pos);
5635
+ const next = pos + (this.unicode && cp > 65535 ? 2 : 1);
5636
+ generation++;
5637
+ let nlen = 0;
5638
+ for (let i = 0; i < clen; i++) {
5639
+ const pc = clist[i];
5640
+ if (prog[pc].matcher.matches(cp, this.unicode)) {
5641
+ nlen = add(nlist, nlen, pc + 1, next, generation);
5642
+ if (nlen < 0) return true;
5643
+ }
5644
+ }
5645
+ nlen = add(nlist, nlen, 0, next, generation);
5646
+ if (nlen < 0) return true;
5647
+ [clist, nlist] = [nlist, clist];
5648
+ clen = nlen;
5649
+ pos = next;
5650
+ }
5651
+ return false;
5652
+ }
5653
+ holds(assertion, input, pos) {
5654
+ switch (assertion) {
5655
+ case "start": return pos === 0;
5656
+ case "end": return pos === input.length;
5657
+ case "wordBoundary":
5658
+ case "notWordBoundary": return (pos > 0 && isWordUnit(input.charCodeAt(pos - 1))) !== (pos < input.length && isWordUnit(input.charCodeAt(pos))) === (assertion === "wordBoundary");
5659
+ }
5660
+ }
5661
+ };
5662
+ function compileLinearRegExp(pattern, unicode, budget) {
5663
+ if (pattern.length > 8192) return {
5664
+ ok: false,
5665
+ reason: `pattern longer than ${MAX_PATTERN_LENGTH} characters`
5666
+ };
5667
+ if (budget) {
5668
+ budget.steps -= pattern.length;
5669
+ if (isCompileBudgetExhausted(budget)) return {
5670
+ ok: false,
5671
+ reason: COMPILE_BUDGET_EXHAUSTED
5672
+ };
5673
+ }
5674
+ new RegExp(pattern, unicode ? "u" : "");
5675
+ try {
5676
+ const ast = new Parser(pattern, unicode).parse();
5677
+ const compiler = new Compiler(unicode, budget);
5678
+ compiler.compile(ast);
5679
+ compiler.prog.push({ op: "match" });
5680
+ return {
5681
+ ok: true,
5682
+ regExp: new LinearRegExp(compiler.prog, unicode)
5683
+ };
5684
+ } catch (error) {
5685
+ /* v8 ignore next -- every throw inside the parser/compiler is an Unsupported */
5686
+ if (!(error instanceof Unsupported)) throw error;
5687
+ return {
5688
+ ok: false,
5689
+ reason: error.message
5690
+ };
5691
+ }
5692
+ }
5693
+ //#endregion
5694
+ //#region ../../core/mcp/linearPatternValidator.ts
5695
+ const PATTERN_EVALUATION_BUDGET = 2e7;
5696
+ const SCHEMA_COMPILE_BUDGET = {
5697
+ steps: 10 * MAX_COMPILE_STEPS,
5698
+ size: 10 * MAX_PROGRAM_SIZE
5699
+ };
5700
+ const MAX_QUOTED_PATTERN = 120;
5701
+ const DRAFT_2020_12 = /* @__PURE__ */ new Set(["https://json-schema.org/draft/2020-12/schema", "http://json-schema.org/draft/2020-12/schema"]);
5702
+ const DRAFT_2019_09 = /* @__PURE__ */ new Set(["https://json-schema.org/draft/2019-09/schema", "http://json-schema.org/draft/2019-09/schema"]);
5703
+ const DRAFT_07_OR_06 = /* @__PURE__ */ new Set([
5704
+ "https://json-schema.org/draft-07/schema",
5705
+ "http://json-schema.org/draft-07/schema",
5706
+ "https://json-schema.org/draft-06/schema",
5707
+ "http://json-schema.org/draft-06/schema"
5708
+ ]);
5709
+ function declaredDialect(schema) {
5710
+ const declared = schema.$schema;
5711
+ if (typeof declared !== "string") return "2020-12";
5712
+ const uri = declared.replace(/#$/, "");
5713
+ if (DRAFT_2020_12.has(uri)) return "2020-12";
5714
+ if (DRAFT_2019_09.has(uri)) return "2019-09";
5715
+ if (DRAFT_07_OR_06.has(uri)) return "draft-7";
5716
+ throw new Error(`JSON Schema declares an unsupported dialect ("$schema": "${declared.slice(0, 200)}"). Supported: JSON Schema 2020-12, 2019-09, draft-07, and draft-06.`);
5717
+ }
5718
+ function quote(pattern) {
5719
+ return pattern.length > MAX_QUOTED_PATTERN ? `${pattern.slice(0, MAX_QUOTED_PATTERN)}…` : pattern;
5720
+ }
5721
+ var PatternLedger = class {
5722
+ remaining = PATTERN_EVALUATION_BUDGET;
5723
+ unevaluated = /* @__PURE__ */ new Set();
5724
+ reset() {
5725
+ this.remaining = PATTERN_EVALUATION_BUDGET;
5726
+ this.unevaluated.clear();
5727
+ }
5728
+ };
5729
+ var LinearPattern = class {
5730
+ source;
5731
+ flags;
5732
+ compiled;
5733
+ ledger;
5734
+ constructor(source, flags, compiled, ledger) {
5735
+ this.source = source;
5736
+ this.flags = flags;
5737
+ this.compiled = compiled;
5738
+ this.ledger = ledger;
5739
+ }
5740
+ test(input) {
5741
+ if (!this.compiled.ok) return this.skip(this.compiled.reason);
5742
+ const { regExp } = this.compiled;
5743
+ const cost = regExp.cost(input);
5744
+ if (cost > this.ledger.remaining) return this.skip(`checking a ${input.length}-character value would exceed the evaluation budget`);
5745
+ this.ledger.remaining -= cost;
5746
+ return regExp.search(input, cost) === true;
5747
+ }
5748
+ skip(reason) {
5749
+ this.ledger.unevaluated.add(`pattern "${quote(this.source)}" was not evaluated (${reason})`);
5750
+ return true;
5751
+ }
5752
+ toString() {
5753
+ return `/${this.source}/${this.flags}`;
5754
+ }
5755
+ };
5756
+ function createRegExpEngine(ledger, budget) {
5757
+ const engine = (pattern, flags) => new LinearPattern(pattern, flags, compileLinearRegExp(pattern, flags.includes("u"), budget()), ledger);
5758
+ return Object.assign(engine, { code: "linearRegExp" });
5759
+ }
5760
+ var LinearPatternJsonSchemaValidator = class {
5761
+ ledger = new PatternLedger();
5762
+ engines = /* @__PURE__ */ new Map();
5763
+ compileBudget = { ...SCHEMA_COMPILE_BUDGET };
5764
+ overBudget = /* @__PURE__ */ new WeakSet();
5765
+ engineFor(dialect) {
5766
+ let engine = this.engines.get(dialect);
5767
+ if (!engine) {
5768
+ const options = {
5769
+ strict: false,
5770
+ validateFormats: true,
5771
+ validateSchema: false,
5772
+ allErrors: true,
5773
+ code: { regExp: createRegExpEngine(this.ledger, () => this.compileBudget) }
5774
+ };
5775
+ engine = dialect === "2020-12" ? new Ajv2020(options) : dialect === "2019-09" ? new Ajv2019(options) : new Ajv(options);
5776
+ addFormats(engine);
5777
+ this.engines.set(dialect, engine);
5778
+ }
5779
+ return engine;
5780
+ }
5781
+ getValidator(schema) {
5782
+ const engine = this.engineFor(declaredDialect(schema));
5783
+ const id = schema.$id;
5784
+ const validate = this.tracked(() => (typeof id === "string" ? engine.getSchema(id) : void 0) ?? engine.compile(schema));
5785
+ const overBudget = this.overBudget.has(validate);
5786
+ return (input) => {
5787
+ this.ledger.reset();
5788
+ const valid = validate(input);
5789
+ const unevaluated = [...this.ledger.unevaluated];
5790
+ if (overBudget) unevaluated.unshift("the schema's patterns exceed the compilation budget");
5791
+ if (valid && unevaluated.length === 0) return {
5792
+ valid: true,
5793
+ data: input,
5794
+ errorMessage: void 0
5795
+ };
5796
+ const messages = valid ? [] : [engine.errorsText(validate.errors)];
5797
+ if (unevaluated.length > 0) messages.push(`${unevaluated.join("; ")}, so the value could not be verified against the schema`);
5798
+ return {
5799
+ valid: false,
5800
+ data: void 0,
5801
+ errorMessage: messages.join("; ")
5802
+ };
5803
+ };
5804
+ }
5805
+ tracked(run) {
5806
+ const outer = this.compileBudget;
5807
+ const budget = { ...SCHEMA_COMPILE_BUDGET };
5808
+ this.compileBudget = budget;
5809
+ try {
5810
+ const validate = run();
5811
+ if (isCompileBudgetExhausted(budget)) this.overBudget.add(validate);
5812
+ return validate;
5813
+ } finally {
5814
+ this.compileBudget = outer;
5815
+ }
5816
+ }
5817
+ };
5185
5818
  function listPaginationExceeded(method) {
5186
5819
  return /* @__PURE__ */ new Error(`Salvage walk for ${method} exceeded 64 pages without the server's pagination converging`);
5187
5820
  }
@@ -8333,6 +8966,16 @@ var RemoteClientTransport = class {
8333
8966
  }
8334
8967
  return await res.json();
8335
8968
  }
8969
+ releaseOnPageHide() {
8970
+ if (!this._sessionId) return false;
8971
+ this.fetchFn(`${this.baseUrl}/api/mcp/disconnect`, {
8972
+ method: "POST",
8973
+ headers: this.headers,
8974
+ body: JSON.stringify({ sessionId: this._sessionId }),
8975
+ keepalive: true
8976
+ }).catch(() => {});
8977
+ return true;
8978
+ }
8336
8979
  async close() {
8337
8980
  if (this.closed) return;
8338
8981
  this.closed = true;
@@ -9270,7 +9913,7 @@ var InspectorClient = class InspectorClient extends InspectorClientEventTarget {
9270
9913
  params: request.params,
9271
9914
  signal: controller.signal
9272
9915
  });
9273
- this.outputValidator ??= new AjvJsonSchemaValidator();
9916
+ this.outputValidator ??= new LinearPatternJsonSchemaValidator();
9274
9917
  const invalid = validateAppElicitResult(this.outputValidator, request.params, result);
9275
9918
  if (invalid) {
9276
9919
  this.logger.warn({
@@ -9869,7 +10512,7 @@ var InspectorClient = class InspectorClient extends InspectorClientEventTarget {
9869
10512
  });
9870
10513
  }
9871
10514
  validateToolOutput(tool, result) {
9872
- this.outputValidator ??= new AjvJsonSchemaValidator();
10515
+ this.outputValidator ??= new LinearPatternJsonSchemaValidator();
9873
10516
  return validateToolOutput(this.outputValidator, tool, result);
9874
10517
  }
9875
10518
  cancelPendingTaskInput(taskId) {
@@ -10716,6 +11359,10 @@ var InspectorClient = class InspectorClient extends InspectorClientEventTarget {
10716
11359
  getRemoteBackendSessionId() {
10717
11360
  if (this.baseTransport instanceof RemoteClientTransport) return this.baseTransport.getRemoteBackendSessionId();
10718
11361
  }
11362
+ releaseRemoteSessionOnPageHide() {
11363
+ if (this.baseTransport instanceof RemoteClientTransport) return this.baseTransport.releaseOnPageHide();
11364
+ return false;
11365
+ }
10719
11366
  async resumeAfterOAuth(authorizationCode, options) {
10720
11367
  await this.completeOAuthFlow(authorizationCode, options?.iss, options?.state);
10721
11368
  const remoteSessionId = options?.remoteSessionId;
@@ -11757,6 +12404,18 @@ function useManagedTools(client, managedToolsState) {
11757
12404
  };
11758
12405
  }
11759
12406
  //#endregion
12407
+ //#region ../../core/mcp/toolOrder.ts
12408
+ const toolLabelCollator = new Intl.Collator(void 0, {
12409
+ sensitivity: "base",
12410
+ numeric: true
12411
+ });
12412
+ function compareToolLabels(a, b) {
12413
+ return toolLabelCollator.compare(a, b);
12414
+ }
12415
+ function compareToolsByName(a, b) {
12416
+ return compareToolLabels(a.name, b.name);
12417
+ }
12418
+ //#endregion
11760
12419
  //#region ../../core/react/useManagedResources.ts
11761
12420
  const NO_RESOURCES = [];
11762
12421
  const readResources = (state) => state.getResources();
@@ -13449,21 +14108,38 @@ var NodeOAuthStorage = class extends OAuthStorageBase {
13449
14108
  //#region ../../core/auth/node/oauth-callback-server.ts
13450
14109
  const DEFAULT_HOSTNAME = "127.0.0.1";
13451
14110
  const DEFAULT_CALLBACK_PATH = "/oauth/callback";
13452
- const SUCCESS_HTML = `<!DOCTYPE html>
13453
- <html>
13454
- <head><meta charset="utf-8"><title>OAuth complete</title></head>
13455
- <body><p>OAuth complete. You can close this window.</p></body>
13456
- </html>`;
13457
- function errorHtml(message) {
14111
+ const SUCCESS_HTML = page("OAuth complete", "OAuth complete. You can close this window.");
14112
+ const NOT_CALLBACK_HTML = page("Not the OAuth callback", "This address is not the OAuth callback the Inspector is waiting for. Sign-in has not finished; return to the Inspector to continue.");
14113
+ const STATE_MISMATCH_HTML = page("OAuth callback ignored", "This callback does not belong to the sign-in in progress and was ignored. Sign-in has not finished; the Inspector is still waiting for the authorization server.");
14114
+ const ALREADY_HANDLED_HTML = page("OAuth callback already received", "This sign-in has already received its callback. You can close this window.");
14115
+ const STOPPED_HTML = page("OAuth callback not expected", "The Inspector is no longer waiting for this sign-in. Start sign-in again from the Inspector.");
14116
+ function errorHtml(serverText) {
14117
+ return page("OAuth error", `OAuth failed. The authorization server said: ${serverText}`);
14118
+ }
14119
+ function exchangeErrorHtml(message) {
14120
+ return page("OAuth error", `OAuth failed: ${message}`);
14121
+ }
14122
+ function page(title, text) {
13458
14123
  return `<!DOCTYPE html>
13459
14124
  <html>
13460
- <head><meta charset="utf-8"><title>OAuth error</title></head>
13461
- <body><p>OAuth failed: ${escapeHtml(message)}</p></body>
14125
+ <head><meta charset="utf-8"><title>${escapeHtml(title)}</title></head>
14126
+ <body><p>${escapeHtml(text)}</p></body>
13462
14127
  </html>`;
13463
14128
  }
13464
14129
  function escapeHtml(s) {
13465
14130
  return s.replace(/&/g, "&amp;").replace(/</g, "&lt;").replace(/>/g, "&gt;").replace(/"/g, "&quot;");
13466
14131
  }
14132
+ const ANY_STATE = Symbol("any-state");
14133
+ const STOPPED = Symbol("stopped");
14134
+ function createStopSignal() {
14135
+ let fire;
14136
+ return {
14137
+ stopped: new Promise((resolve) => {
14138
+ fire = () => resolve(STOPPED);
14139
+ }),
14140
+ fire
14141
+ };
14142
+ }
13467
14143
  var OAuthCallbackServer = class {
13468
14144
  server = null;
13469
14145
  port = 0;
@@ -13471,6 +14147,8 @@ var OAuthCallbackServer = class {
13471
14147
  handled = false;
13472
14148
  onCallback;
13473
14149
  onError;
14150
+ expectedState = Promise.resolve(ANY_STATE);
14151
+ stopSignal = createStopSignal();
13474
14152
  async start(options = {}) {
13475
14153
  const { port = 0, hostname = DEFAULT_HOSTNAME, path = DEFAULT_CALLBACK_PATH, onCallback, onError } = options;
13476
14154
  if (!path.startsWith("/")) return Promise.reject(/* @__PURE__ */ new Error("Callback path must start with '/' (absolute path)"));
@@ -13478,6 +14156,8 @@ var OAuthCallbackServer = class {
13478
14156
  this.onError = onError;
13479
14157
  this.handled = false;
13480
14158
  this.callbackPath = path;
14159
+ this.stopSignal = createStopSignal();
14160
+ this.expectedState = "expectedState" in options ? Promise.race([Promise.resolve(options.expectedState).catch(() => STOPPED), this.stopSignal.stopped]) : Promise.resolve(ANY_STATE);
13481
14161
  return new Promise((resolve, reject) => {
13482
14162
  this.server = createServer((req, res) => this.handleRequest(req, res));
13483
14163
  this.server.on("error", reject);
@@ -13501,6 +14181,7 @@ var OAuthCallbackServer = class {
13501
14181
  }
13502
14182
  async stop() {
13503
14183
  if (!this.server) return;
14184
+ this.stopSignal.fire();
13504
14185
  await new Promise((resolve) => {
13505
14186
  this.server.close(() => resolve());
13506
14187
  });
@@ -13509,11 +14190,14 @@ var OAuthCallbackServer = class {
13509
14190
  handleRequest(req, res) {
13510
14191
  const needJson = req.headers["accept"]?.includes("application/json");
13511
14192
  const send = (status, body, contentType = "text/html; charset=utf-8") => {
13512
- res.writeHead(status, { "Content-Type": contentType });
14193
+ res.writeHead(status, {
14194
+ "Content-Type": contentType,
14195
+ Connection: "close"
14196
+ });
13513
14197
  res.end(body);
13514
14198
  };
13515
14199
  if (req.method !== "GET") {
13516
- send(405, needJson ? "{\"error\":\"Method Not Allowed\"}" : SUCCESS_HTML);
14200
+ send(405, needJson ? "{\"error\":\"Method Not Allowed\"}" : NOT_CALLBACK_HTML);
13517
14201
  return;
13518
14202
  }
13519
14203
  let pathname;
@@ -13530,15 +14214,26 @@ var OAuthCallbackServer = class {
13530
14214
  search = u.search;
13531
14215
  state = u.searchParams.get("state") ?? void 0;
13532
14216
  } catch {
13533
- send(400, needJson ? "{\"error\":\"Bad Request\"}" : SUCCESS_HTML);
14217
+ send(400, needJson ? "{\"error\":\"Bad Request\"}" : NOT_CALLBACK_HTML);
13534
14218
  return;
13535
14219
  }
13536
14220
  if (pathname !== this.callbackPath) {
13537
- send(404, needJson ? "{\"error\":\"Not Found\"}" : SUCCESS_HTML);
14221
+ send(404, needJson ? "{\"error\":\"Not Found\"}" : NOT_CALLBACK_HTML);
14222
+ return;
14223
+ }
14224
+ this.expectedState.then((expected) => this.handleCallback(expected, state, search, needJson, send));
14225
+ }
14226
+ handleCallback(expected, state, search, needJson, send) {
14227
+ if (expected === STOPPED) {
14228
+ send(503, needJson ? "{\"error\":\"Not waiting for a callback\"}" : STOPPED_HTML);
14229
+ return;
14230
+ }
14231
+ if (expected !== ANY_STATE && state !== expected) {
14232
+ send(400, needJson ? "{\"error\":\"State mismatch\"}" : STATE_MISMATCH_HTML);
13538
14233
  return;
13539
14234
  }
13540
14235
  if (this.handled) {
13541
- send(409, needJson ? "{\"error\":\"Callback already handled\"}" : SUCCESS_HTML);
14236
+ send(409, needJson ? "{\"error\":\"Callback already handled\"}" : ALREADY_HANDLED_HTML);
13542
14237
  return;
13543
14238
  }
13544
14239
  const params = parseOAuthCallbackParams(search);
@@ -13556,9 +14251,10 @@ var OAuthCallbackServer = class {
13556
14251
  const msg = err instanceof Error ? err.message : String(err);
13557
14252
  this.onError?.({
13558
14253
  error: "callback_error",
13559
- error_description: msg
14254
+ error_description: msg,
14255
+ source: "callback"
13560
14256
  });
13561
- send(500, errorHtml(msg));
14257
+ send(500, exchangeErrorHtml(msg));
13562
14258
  this.stop();
13563
14259
  });
13564
14260
  else {
@@ -13571,7 +14267,8 @@ var OAuthCallbackServer = class {
13571
14267
  const msg = generateOAuthErrorDescription(params);
13572
14268
  this.onError?.({
13573
14269
  error: params.error,
13574
- error_description: params.error_description ?? void 0
14270
+ error_description: params.error_description ?? void 0,
14271
+ source: "redirect"
13575
14272
  });
13576
14273
  send(400, errorHtml(msg));
13577
14274
  }
@@ -13590,6 +14287,14 @@ function toRunnerOAuthError(err) {
13590
14287
  }
13591
14288
  return err instanceof Error ? err : new Error(String(err));
13592
14289
  }
14290
+ function stateOf(authorizationUrl) {
14291
+ return authorizationUrl.searchParams.get("state") ?? void 0;
14292
+ }
14293
+ function callbackErrorMessage(params) {
14294
+ if (params.source === "callback") return params.error_description ?? "OAuth callback failed";
14295
+ if (!params.error && !params.error_description) return "OAuth error";
14296
+ return `OAuth authorization failed. The authorization server said: ${params.error_description ? `${params.error_description} (${params.error})` : params.error}`;
14297
+ }
13593
14298
  async function runRunnerInteractiveOAuth(options) {
13594
14299
  const server = (options.createCallbackServer ?? createOAuthCallbackServer)();
13595
14300
  let flowResolve;
@@ -13619,11 +14324,16 @@ async function runRunnerInteractiveOAuth(options) {
13619
14324
  process.on("SIGTERM", onSignal);
13620
14325
  }
13621
14326
  let timeoutId;
14327
+ let resolveExpectedState;
14328
+ const expectedState = new Promise((resolve) => {
14329
+ resolveExpectedState = resolve;
14330
+ });
13622
14331
  try {
13623
14332
  const { redirectUrl } = await racingSignals(server.start({
13624
14333
  hostname: options.callbackListen.hostname,
13625
14334
  port: options.callbackListen.port,
13626
14335
  path: options.callbackListen.pathname,
14336
+ expectedState,
13627
14337
  onCallback: async (params) => {
13628
14338
  try {
13629
14339
  await options.client.completeOAuthFlow(params.code, params.iss, params.state);
@@ -13633,10 +14343,7 @@ async function runRunnerInteractiveOAuth(options) {
13633
14343
  }
13634
14344
  },
13635
14345
  onError: (params) => {
13636
- flowReject(new Error(
13637
- /* v8 ignore next -- params.error is a required non-null string, so the "OAuth error" fallback is unreachable */
13638
- params.error_description ?? params.error ?? "OAuth error"
13639
- ));
14346
+ flowReject(new Error(callbackErrorMessage(params)));
13640
14347
  }
13641
14348
  }));
13642
14349
  options.onCallbackServer?.(server);
@@ -13652,10 +14359,16 @@ async function runRunnerInteractiveOAuth(options) {
13652
14359
  })]);
13653
14360
  waitForCallback.catch(() => {});
13654
14361
  if (options.authorizationUrl) {
14362
+ resolveExpectedState(stateOf(options.authorizationUrl));
13655
14363
  await racingSignals(options.client.beginInteractiveAuthorization(options.authorizationUrl));
13656
14364
  await waitForCallback;
13657
- } else if (await racingSignals(options.client.authenticate()) !== void 0) await waitForCallback;
13658
- else return { kind: "already_authorized" };
14365
+ } else {
14366
+ const authUrl = await racingSignals(options.client.authenticate());
14367
+ if (authUrl !== void 0) {
14368
+ resolveExpectedState(stateOf(authUrl));
14369
+ await waitForCallback;
14370
+ } else return { kind: "already_authorized" };
14371
+ }
13659
14372
  if (options.authChallenge) {
13660
14373
  if (!await racingSignals(options.client.checkAuthChallengeSatisfied(options.authChallenge, { scopeOnly: true }))) return {
13661
14374
  kind: "insufficient_scope",
@@ -14965,7 +15678,7 @@ function useSelectableList(itemCount, visibleCount, options) {
14965
15678
  ]);
14966
15679
  return {
14967
15680
  selectedIndex,
14968
- firstVisible,
15681
+ firstVisible: clampFirstVisible(firstVisible, selectedIndex, visibleCount),
14969
15682
  setSelection
14970
15683
  };
14971
15684
  }
@@ -15277,7 +15990,10 @@ function ResourcesTab({ resources, resourceTemplates = [], inspectorClient, widt
15277
15990
  return /* @__PURE__ */ jsx(Box, {
15278
15991
  paddingY: 0,
15279
15992
  flexShrink: 0,
15280
- children: /* @__PURE__ */ jsxs(Text, { children: [isSelected ? "▶ " : " ", label] })
15993
+ children: /* @__PURE__ */ jsxs(Text, {
15994
+ wrap: "truncate-end",
15995
+ children: [isSelected ? "▶ " : " ", label]
15996
+ })
15281
15997
  }, key);
15282
15998
  })
15283
15999
  })
@@ -15561,7 +16277,10 @@ function PromptsTab({ prompts, inspectorClient, width, height, focusedPane = nul
15561
16277
  return /* @__PURE__ */ jsx(Box, {
15562
16278
  paddingY: 0,
15563
16279
  flexShrink: 0,
15564
- children: /* @__PURE__ */ jsxs(Text, { children: [isSelected ? "▶ " : " ", prompt.name || `Prompt ${ordinal + 1}`] })
16280
+ children: /* @__PURE__ */ jsxs(Text, {
16281
+ wrap: "truncate-end",
16282
+ children: [isSelected ? "▶ " : " ", prompt.name || `Prompt ${ordinal + 1}`]
16283
+ })
15565
16284
  }, `${ordinal}:${prompt.name}`);
15566
16285
  })
15567
16286
  })
@@ -16603,17 +17322,19 @@ function ToolsTab({ tools, isConnected, width, height, focusedPane = null, onTes
16603
17322
  const isSelected = index === selectedIndex;
16604
17323
  const marker = schemaMarker(findingsByTool.get(tool));
16605
17324
  const ordinal = filter.indices[index];
16606
- return /* @__PURE__ */ jsx(Box, {
17325
+ return /* @__PURE__ */ jsxs(Box, {
16607
17326
  paddingY: 0,
16608
17327
  flexShrink: 0,
16609
- children: /* @__PURE__ */ jsxs(Text, { children: [
16610
- isSelected ? "▶ " : " ",
16611
- tool.name || `Tool ${ordinal + 1}`,
16612
- marker && /* @__PURE__ */ jsxs(Text, {
17328
+ children: [/* @__PURE__ */ jsxs(Text, {
17329
+ wrap: "truncate-end",
17330
+ children: [isSelected ? "▶ " : " ", tool.name || `Tool ${ordinal + 1}`]
17331
+ }), marker && /* @__PURE__ */ jsx(Box, {
17332
+ flexShrink: 0,
17333
+ children: /* @__PURE__ */ jsxs(Text, {
16613
17334
  color: marker.color,
16614
17335
  children: [" ", marker.glyph]
16615
17336
  })
16616
- ] })
17337
+ })]
16617
17338
  }, `${ordinal}:${tool.name}`);
16618
17339
  })
16619
17340
  })
@@ -16628,18 +17349,23 @@ function ToolsTab({ tools, isConnected, width, height, focusedPane = null, onTes
16628
17349
  /* @__PURE__ */ jsxs(Box, {
16629
17350
  flexShrink: 0,
16630
17351
  flexDirection: "row",
17352
+ flexWrap: "wrap",
16631
17353
  justifyContent: "space-between",
17354
+ columnGap: 1,
16632
17355
  paddingTop: 1,
16633
17356
  children: [/* @__PURE__ */ jsx(Text, {
16634
17357
  bold: true,
16635
17358
  backgroundColor: focusedPane === "details" ? "yellow" : void 0,
16636
17359
  ...focusedPane === "details" ? {} : { color: "cyan" },
16637
17360
  children: selectedTool.name
16638
- }), isConnected && /* @__PURE__ */ jsx(Text, { children: /* @__PURE__ */ jsx(Text, {
16639
- color: "cyan",
16640
- bold: true,
16641
- children: "[Enter to Test]"
16642
- }) })]
17361
+ }), isConnected && /* @__PURE__ */ jsx(Box, {
17362
+ flexShrink: 0,
17363
+ children: /* @__PURE__ */ jsx(Text, {
17364
+ color: "cyan",
17365
+ bold: true,
17366
+ children: "[Enter to Test]"
17367
+ })
17368
+ })]
16643
17369
  }),
16644
17370
  /* @__PURE__ */ jsxs(ScrollView, {
16645
17371
  ref: scrollViewRef,
@@ -18739,6 +19465,14 @@ function missingRequiredFields(schema, decoded, rawValues = {}) {
18739
19465
  });
18740
19466
  }
18741
19467
  //#endregion
19468
+ //#region src/utils/formHeader.ts
19469
+ function untitledForm(form) {
19470
+ return {
19471
+ ...form,
19472
+ title: void 0
19473
+ };
19474
+ }
19475
+ //#endregion
18742
19476
  //#region ../../core/mcp/resultFile.ts
18743
19477
  var RawResultUnavailableError = class extends Error {
18744
19478
  method;
@@ -19116,7 +19850,7 @@ function ToolTestModal({ tool, inspectorClient, width, height, onClose, onAuthRe
19116
19850
  flexGrow: 1,
19117
19851
  width: "100%",
19118
19852
  children: /* @__PURE__ */ jsx(Form, {
19119
- form: formStructure,
19853
+ form: untitledForm(formStructure),
19120
19854
  onSubmit: (value) => void handleFormSubmit(value)
19121
19855
  })
19122
19856
  }),
@@ -19408,7 +20142,7 @@ function ResourceTestModal({ template, inspectorClient, width, height, onClose,
19408
20142
  children: template.description
19409
20143
  })
19410
20144
  }), /* @__PURE__ */ jsx(Form, {
19411
- form: formStructure,
20145
+ form: untitledForm(formStructure),
19412
20146
  onSubmit: (values) => handleFormSubmit(values)
19413
20147
  })]
19414
20148
  }),
@@ -19705,7 +20439,7 @@ function PromptTestModal({ prompt, inspectorClient, width, height, onClose, onAu
19705
20439
  children: prompt.description
19706
20440
  })
19707
20441
  }), /* @__PURE__ */ jsx(Form, {
19708
- form: formStructure,
20442
+ form: untitledForm(formStructure),
19709
20443
  onSubmit: (values) => handleFormSubmit(values)
19710
20444
  })]
19711
20445
  }),
@@ -21341,6 +22075,7 @@ function App({ mcpServers, clientConfig, clientId, clientSecret, clientMetadataU
21341
22075
  const { fetchRequests: inspectorFetchRequests } = useFetchRequestLog(selectedFetchRequestLogState);
21342
22076
  const { stderrLogs: inspectorStderrLogs } = useStderrLog(selectedStderrLogState);
21343
22077
  const { tools: managedTools } = useManagedTools(selectedInspectorClient, useMemo(() => selectedServer && managedToolsStates[selectedServer] ? managedToolsStates[selectedServer] : null, [selectedServer, managedToolsStates]));
22078
+ const sortedTools = useMemo(() => [...managedTools].sort(compareToolsByName), [managedTools]);
21344
22079
  const selectedManagedResourcesState = useMemo(() => selectedServer && managedResourcesStates[selectedServer] ? managedResourcesStates[selectedServer] : null, [selectedServer, managedResourcesStates]);
21345
22080
  const selectedManagedResourceTemplatesState = useMemo(() => selectedServer && managedResourceTemplatesStates[selectedServer] ? managedResourceTemplatesStates[selectedServer] : null, [selectedServer, managedResourceTemplatesStates]);
21346
22081
  const selectedManagedPromptsState = useMemo(() => selectedServer && managedPromptsStates[selectedServer] ? managedPromptsStates[selectedServer] : null, [selectedServer, managedPromptsStates]);
@@ -21640,7 +22375,7 @@ function App({ mcpServers, clientConfig, clientId, clientSecret, clientMetadataU
21640
22375
  resources: managedResources,
21641
22376
  resourceTemplates: managedResourceTemplates,
21642
22377
  prompts: managedPrompts,
21643
- tools: managedTools,
22378
+ tools: sortedTools,
21644
22379
  stderrLogs: inspectorStderrLogs
21645
22380
  };
21646
22381
  }, [
@@ -21654,7 +22389,7 @@ function App({ mcpServers, clientConfig, clientId, clientSecret, clientMetadataU
21654
22389
  managedResources,
21655
22390
  managedResourceTemplates,
21656
22391
  managedPrompts,
21657
- managedTools,
22392
+ sortedTools,
21658
22393
  inspectorStderrLogs
21659
22394
  ]);
21660
22395
  const renderResourceDetails = (resource) => /* @__PURE__ */ jsxs(Fragment, { children: [