goatedit-mcp 1.1.9 → 1.1.11

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 (2) hide show
  1. package/bundle/goatedit-mcp.js +3485 -180
  2. package/package.json +1 -1
@@ -3232,8 +3232,8 @@ var require_utils = __commonJS({
3232
3232
  }
3233
3233
  return ind;
3234
3234
  }
3235
- function removeDotSegments(path3) {
3236
- let input = path3;
3235
+ function removeDotSegments(path4) {
3236
+ let input = path4;
3237
3237
  const output = [];
3238
3238
  let nextSlash = -1;
3239
3239
  let len = 0;
@@ -3485,8 +3485,8 @@ var require_schemes = __commonJS({
3485
3485
  wsComponent.secure = void 0;
3486
3486
  }
3487
3487
  if (wsComponent.resourceName) {
3488
- const [path3, query] = wsComponent.resourceName.split("?");
3489
- wsComponent.path = path3 && path3 !== "/" ? path3 : void 0;
3488
+ const [path4, query] = wsComponent.resourceName.split("?");
3489
+ wsComponent.path = path4 && path4 !== "/" ? path4 : void 0;
3490
3490
  wsComponent.query = query;
3491
3491
  wsComponent.resourceName = void 0;
3492
3492
  }
@@ -6586,7 +6586,7 @@ var require_formats = __commonJS({
6586
6586
  }
6587
6587
  exports.fullFormats = {
6588
6588
  // date: http://tools.ietf.org/html/rfc3339#section-5.6
6589
- date: fmtDef(date3, compareDate),
6589
+ date: fmtDef(date4, compareDate),
6590
6590
  // date-time: http://tools.ietf.org/html/rfc3339#section-5.6
6591
6591
  time: fmtDef(getTime(true), compareTime),
6592
6592
  "date-time": fmtDef(getDateTime(true), compareDateTime),
@@ -6652,7 +6652,7 @@ var require_formats = __commonJS({
6652
6652
  }
6653
6653
  var DATE = /^(\d\d\d\d)-(\d\d)-(\d\d)$/;
6654
6654
  var DAYS = [0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31];
6655
- function date3(str2) {
6655
+ function date4(str2) {
6656
6656
  const matches = DATE.exec(str2);
6657
6657
  if (!matches)
6658
6658
  return false;
@@ -6721,7 +6721,7 @@ var require_formats = __commonJS({
6721
6721
  const time3 = getTime(strictTimeZone);
6722
6722
  return function date_time(str2) {
6723
6723
  const dateTime = str2.split(DATE_TIME_SEPARATOR);
6724
- return dateTime.length === 2 && date3(dateTime[0]) && time3(dateTime[1]);
6724
+ return dateTime.length === 2 && date4(dateTime[0]) && time3(dateTime[1]);
6725
6725
  };
6726
6726
  }
6727
6727
  function compareDateTime(dt1, dt2) {
@@ -6879,12 +6879,12 @@ var require_dist = __commonJS({
6879
6879
  throw new Error(`Unknown format "${name}"`);
6880
6880
  return f;
6881
6881
  };
6882
- function addFormats(ajv, list, fs3, exportName) {
6882
+ function addFormats(ajv, list, fs4, exportName) {
6883
6883
  var _a3;
6884
6884
  var _b;
6885
6885
  (_a3 = (_b = ajv.opts.code).formats) !== null && _a3 !== void 0 ? _a3 : _b.formats = (0, codegen_1._)`require("ajv-formats/dist/formats").${exportName}`;
6886
6886
  for (const f of list)
6887
- ajv.addFormat(f, fs3[f]);
6887
+ ajv.addFormat(f, fs4[f]);
6888
6888
  }
6889
6889
  module.exports = exports = formatsPlugin;
6890
6890
  Object.defineProperty(exports, "__esModule", { value: true });
@@ -9138,10 +9138,10 @@ var require_websocket = __commonJS({
9138
9138
  var EventEmitter = __require("events");
9139
9139
  var https = __require("https");
9140
9140
  var http2 = __require("http");
9141
- var net = __require("net");
9141
+ var net2 = __require("net");
9142
9142
  var tls = __require("tls");
9143
9143
  var { randomBytes, createHash } = __require("crypto");
9144
- var { Duplex, Readable } = __require("stream");
9144
+ var { Duplex, Readable: Readable2 } = __require("stream");
9145
9145
  var { URL: URL2 } = __require("url");
9146
9146
  var PerMessageDeflate2 = require_permessage_deflate();
9147
9147
  var Receiver2 = require_receiver();
@@ -9882,12 +9882,12 @@ var require_websocket = __commonJS({
9882
9882
  }
9883
9883
  function netConnect(options) {
9884
9884
  options.path = options.socketPath;
9885
- return net.connect(options);
9885
+ return net2.connect(options);
9886
9886
  }
9887
9887
  function tlsConnect(options) {
9888
9888
  options.path = void 0;
9889
9889
  if (!options.servername && options.servername !== "") {
9890
- options.servername = net.isIP(options.host) ? "" : options.host;
9890
+ options.servername = net2.isIP(options.host) ? "" : options.host;
9891
9891
  }
9892
9892
  return tls.connect(options);
9893
9893
  }
@@ -10571,8 +10571,508 @@ var require_websocket_server = __commonJS({
10571
10571
  }
10572
10572
  });
10573
10573
 
10574
+ // node_modules/isexe/windows.js
10575
+ var require_windows = __commonJS({
10576
+ "node_modules/isexe/windows.js"(exports, module) {
10577
+ module.exports = isexe;
10578
+ isexe.sync = sync;
10579
+ var fs4 = __require("fs");
10580
+ function checkPathExt(path4, options) {
10581
+ var pathext = options.pathExt !== void 0 ? options.pathExt : process.env.PATHEXT;
10582
+ if (!pathext) {
10583
+ return true;
10584
+ }
10585
+ pathext = pathext.split(";");
10586
+ if (pathext.indexOf("") !== -1) {
10587
+ return true;
10588
+ }
10589
+ for (var i = 0; i < pathext.length; i++) {
10590
+ var p = pathext[i].toLowerCase();
10591
+ if (p && path4.substr(-p.length).toLowerCase() === p) {
10592
+ return true;
10593
+ }
10594
+ }
10595
+ return false;
10596
+ }
10597
+ function checkStat(stat, path4, options) {
10598
+ if (!stat.isSymbolicLink() && !stat.isFile()) {
10599
+ return false;
10600
+ }
10601
+ return checkPathExt(path4, options);
10602
+ }
10603
+ function isexe(path4, options, cb) {
10604
+ fs4.stat(path4, function(er, stat) {
10605
+ cb(er, er ? false : checkStat(stat, path4, options));
10606
+ });
10607
+ }
10608
+ function sync(path4, options) {
10609
+ return checkStat(fs4.statSync(path4), path4, options);
10610
+ }
10611
+ }
10612
+ });
10613
+
10614
+ // node_modules/isexe/mode.js
10615
+ var require_mode = __commonJS({
10616
+ "node_modules/isexe/mode.js"(exports, module) {
10617
+ module.exports = isexe;
10618
+ isexe.sync = sync;
10619
+ var fs4 = __require("fs");
10620
+ function isexe(path4, options, cb) {
10621
+ fs4.stat(path4, function(er, stat) {
10622
+ cb(er, er ? false : checkStat(stat, options));
10623
+ });
10624
+ }
10625
+ function sync(path4, options) {
10626
+ return checkStat(fs4.statSync(path4), options);
10627
+ }
10628
+ function checkStat(stat, options) {
10629
+ return stat.isFile() && checkMode(stat, options);
10630
+ }
10631
+ function checkMode(stat, options) {
10632
+ var mod = stat.mode;
10633
+ var uid = stat.uid;
10634
+ var gid = stat.gid;
10635
+ var myUid = options.uid !== void 0 ? options.uid : process.getuid && process.getuid();
10636
+ var myGid = options.gid !== void 0 ? options.gid : process.getgid && process.getgid();
10637
+ var u = parseInt("100", 8);
10638
+ var g = parseInt("010", 8);
10639
+ var o = parseInt("001", 8);
10640
+ var ug = u | g;
10641
+ var ret = mod & o || mod & g && gid === myGid || mod & u && uid === myUid || mod & ug && myUid === 0;
10642
+ return ret;
10643
+ }
10644
+ }
10645
+ });
10646
+
10647
+ // node_modules/isexe/index.js
10648
+ var require_isexe = __commonJS({
10649
+ "node_modules/isexe/index.js"(exports, module) {
10650
+ var fs4 = __require("fs");
10651
+ var core;
10652
+ if (process.platform === "win32" || global.TESTING_WINDOWS) {
10653
+ core = require_windows();
10654
+ } else {
10655
+ core = require_mode();
10656
+ }
10657
+ module.exports = isexe;
10658
+ isexe.sync = sync;
10659
+ function isexe(path4, options, cb) {
10660
+ if (typeof options === "function") {
10661
+ cb = options;
10662
+ options = {};
10663
+ }
10664
+ if (!cb) {
10665
+ if (typeof Promise !== "function") {
10666
+ throw new TypeError("callback not provided");
10667
+ }
10668
+ return new Promise(function(resolve, reject) {
10669
+ isexe(path4, options || {}, function(er, is) {
10670
+ if (er) {
10671
+ reject(er);
10672
+ } else {
10673
+ resolve(is);
10674
+ }
10675
+ });
10676
+ });
10677
+ }
10678
+ core(path4, options || {}, function(er, is) {
10679
+ if (er) {
10680
+ if (er.code === "EACCES" || options && options.ignoreErrors) {
10681
+ er = null;
10682
+ is = false;
10683
+ }
10684
+ }
10685
+ cb(er, is);
10686
+ });
10687
+ }
10688
+ function sync(path4, options) {
10689
+ try {
10690
+ return core.sync(path4, options || {});
10691
+ } catch (er) {
10692
+ if (options && options.ignoreErrors || er.code === "EACCES") {
10693
+ return false;
10694
+ } else {
10695
+ throw er;
10696
+ }
10697
+ }
10698
+ }
10699
+ }
10700
+ });
10701
+
10702
+ // node_modules/which/which.js
10703
+ var require_which = __commonJS({
10704
+ "node_modules/which/which.js"(exports, module) {
10705
+ var isWindows = process.platform === "win32" || process.env.OSTYPE === "cygwin" || process.env.OSTYPE === "msys";
10706
+ var path4 = __require("path");
10707
+ var COLON = isWindows ? ";" : ":";
10708
+ var isexe = require_isexe();
10709
+ var getNotFoundError = (cmd) => Object.assign(new Error(`not found: ${cmd}`), { code: "ENOENT" });
10710
+ var getPathInfo = (cmd, opt) => {
10711
+ const colon = opt.colon || COLON;
10712
+ const pathEnv = cmd.match(/\//) || isWindows && cmd.match(/\\/) ? [""] : [
10713
+ // windows always checks the cwd first
10714
+ ...isWindows ? [process.cwd()] : [],
10715
+ ...(opt.path || process.env.PATH || /* istanbul ignore next: very unusual */
10716
+ "").split(colon)
10717
+ ];
10718
+ const pathExtExe = isWindows ? opt.pathExt || process.env.PATHEXT || ".EXE;.CMD;.BAT;.COM" : "";
10719
+ const pathExt = isWindows ? pathExtExe.split(colon) : [""];
10720
+ if (isWindows) {
10721
+ if (cmd.indexOf(".") !== -1 && pathExt[0] !== "")
10722
+ pathExt.unshift("");
10723
+ }
10724
+ return {
10725
+ pathEnv,
10726
+ pathExt,
10727
+ pathExtExe
10728
+ };
10729
+ };
10730
+ var which = (cmd, opt, cb) => {
10731
+ if (typeof opt === "function") {
10732
+ cb = opt;
10733
+ opt = {};
10734
+ }
10735
+ if (!opt)
10736
+ opt = {};
10737
+ const { pathEnv, pathExt, pathExtExe } = getPathInfo(cmd, opt);
10738
+ const found = [];
10739
+ const step = (i) => new Promise((resolve, reject) => {
10740
+ if (i === pathEnv.length)
10741
+ return opt.all && found.length ? resolve(found) : reject(getNotFoundError(cmd));
10742
+ const ppRaw = pathEnv[i];
10743
+ const pathPart = /^".*"$/.test(ppRaw) ? ppRaw.slice(1, -1) : ppRaw;
10744
+ const pCmd = path4.join(pathPart, cmd);
10745
+ const p = !pathPart && /^\.[\\\/]/.test(cmd) ? cmd.slice(0, 2) + pCmd : pCmd;
10746
+ resolve(subStep(p, i, 0));
10747
+ });
10748
+ const subStep = (p, i, ii) => new Promise((resolve, reject) => {
10749
+ if (ii === pathExt.length)
10750
+ return resolve(step(i + 1));
10751
+ const ext = pathExt[ii];
10752
+ isexe(p + ext, { pathExt: pathExtExe }, (er, is) => {
10753
+ if (!er && is) {
10754
+ if (opt.all)
10755
+ found.push(p + ext);
10756
+ else
10757
+ return resolve(p + ext);
10758
+ }
10759
+ return resolve(subStep(p, i, ii + 1));
10760
+ });
10761
+ });
10762
+ return cb ? step(0).then((res) => cb(null, res), cb) : step(0);
10763
+ };
10764
+ var whichSync = (cmd, opt) => {
10765
+ opt = opt || {};
10766
+ const { pathEnv, pathExt, pathExtExe } = getPathInfo(cmd, opt);
10767
+ const found = [];
10768
+ for (let i = 0; i < pathEnv.length; i++) {
10769
+ const ppRaw = pathEnv[i];
10770
+ const pathPart = /^".*"$/.test(ppRaw) ? ppRaw.slice(1, -1) : ppRaw;
10771
+ const pCmd = path4.join(pathPart, cmd);
10772
+ const p = !pathPart && /^\.[\\\/]/.test(cmd) ? cmd.slice(0, 2) + pCmd : pCmd;
10773
+ for (let j = 0; j < pathExt.length; j++) {
10774
+ const cur = p + pathExt[j];
10775
+ try {
10776
+ const is = isexe.sync(cur, { pathExt: pathExtExe });
10777
+ if (is) {
10778
+ if (opt.all)
10779
+ found.push(cur);
10780
+ else
10781
+ return cur;
10782
+ }
10783
+ } catch (ex) {
10784
+ }
10785
+ }
10786
+ }
10787
+ if (opt.all && found.length)
10788
+ return found;
10789
+ if (opt.nothrow)
10790
+ return null;
10791
+ throw getNotFoundError(cmd);
10792
+ };
10793
+ module.exports = which;
10794
+ which.sync = whichSync;
10795
+ }
10796
+ });
10797
+
10798
+ // node_modules/path-key/index.js
10799
+ var require_path_key = __commonJS({
10800
+ "node_modules/path-key/index.js"(exports, module) {
10801
+ "use strict";
10802
+ var pathKey = (options = {}) => {
10803
+ const environment = options.env || process.env;
10804
+ const platform = options.platform || process.platform;
10805
+ if (platform !== "win32") {
10806
+ return "PATH";
10807
+ }
10808
+ return Object.keys(environment).reverse().find((key) => key.toUpperCase() === "PATH") || "Path";
10809
+ };
10810
+ module.exports = pathKey;
10811
+ module.exports.default = pathKey;
10812
+ }
10813
+ });
10814
+
10815
+ // node_modules/cross-spawn/lib/util/resolveCommand.js
10816
+ var require_resolveCommand = __commonJS({
10817
+ "node_modules/cross-spawn/lib/util/resolveCommand.js"(exports, module) {
10818
+ "use strict";
10819
+ var path4 = __require("path");
10820
+ var which = require_which();
10821
+ var getPathKey = require_path_key();
10822
+ function resolveCommandAttempt(parsed, withoutPathExt) {
10823
+ const env = parsed.options.env || process.env;
10824
+ const cwd = process.cwd();
10825
+ const hasCustomCwd = parsed.options.cwd != null;
10826
+ const shouldSwitchCwd = hasCustomCwd && process.chdir !== void 0 && !process.chdir.disabled;
10827
+ if (shouldSwitchCwd) {
10828
+ try {
10829
+ process.chdir(parsed.options.cwd);
10830
+ } catch (err) {
10831
+ }
10832
+ }
10833
+ let resolved;
10834
+ try {
10835
+ resolved = which.sync(parsed.command, {
10836
+ path: env[getPathKey({ env })],
10837
+ pathExt: withoutPathExt ? path4.delimiter : void 0
10838
+ });
10839
+ } catch (e) {
10840
+ } finally {
10841
+ if (shouldSwitchCwd) {
10842
+ process.chdir(cwd);
10843
+ }
10844
+ }
10845
+ if (resolved) {
10846
+ resolved = path4.resolve(hasCustomCwd ? parsed.options.cwd : "", resolved);
10847
+ }
10848
+ return resolved;
10849
+ }
10850
+ function resolveCommand(parsed) {
10851
+ return resolveCommandAttempt(parsed) || resolveCommandAttempt(parsed, true);
10852
+ }
10853
+ module.exports = resolveCommand;
10854
+ }
10855
+ });
10856
+
10857
+ // node_modules/cross-spawn/lib/util/escape.js
10858
+ var require_escape = __commonJS({
10859
+ "node_modules/cross-spawn/lib/util/escape.js"(exports, module) {
10860
+ "use strict";
10861
+ var metaCharsRegExp = /([()\][%!^"`<>&|;, *?])/g;
10862
+ function escapeCommand(arg) {
10863
+ arg = arg.replace(metaCharsRegExp, "^$1");
10864
+ return arg;
10865
+ }
10866
+ function escapeArgument(arg, doubleEscapeMetaChars) {
10867
+ arg = `${arg}`;
10868
+ arg = arg.replace(/(?=(\\+?)?)\1"/g, '$1$1\\"');
10869
+ arg = arg.replace(/(?=(\\+?)?)\1$/, "$1$1");
10870
+ arg = `"${arg}"`;
10871
+ arg = arg.replace(metaCharsRegExp, "^$1");
10872
+ if (doubleEscapeMetaChars) {
10873
+ arg = arg.replace(metaCharsRegExp, "^$1");
10874
+ }
10875
+ return arg;
10876
+ }
10877
+ module.exports.command = escapeCommand;
10878
+ module.exports.argument = escapeArgument;
10879
+ }
10880
+ });
10881
+
10882
+ // node_modules/shebang-regex/index.js
10883
+ var require_shebang_regex = __commonJS({
10884
+ "node_modules/shebang-regex/index.js"(exports, module) {
10885
+ "use strict";
10886
+ module.exports = /^#!(.*)/;
10887
+ }
10888
+ });
10889
+
10890
+ // node_modules/shebang-command/index.js
10891
+ var require_shebang_command = __commonJS({
10892
+ "node_modules/shebang-command/index.js"(exports, module) {
10893
+ "use strict";
10894
+ var shebangRegex = require_shebang_regex();
10895
+ module.exports = (string4 = "") => {
10896
+ const match = string4.match(shebangRegex);
10897
+ if (!match) {
10898
+ return null;
10899
+ }
10900
+ const [path4, argument] = match[0].replace(/#! ?/, "").split(" ");
10901
+ const binary = path4.split("/").pop();
10902
+ if (binary === "env") {
10903
+ return argument;
10904
+ }
10905
+ return argument ? `${binary} ${argument}` : binary;
10906
+ };
10907
+ }
10908
+ });
10909
+
10910
+ // node_modules/cross-spawn/lib/util/readShebang.js
10911
+ var require_readShebang = __commonJS({
10912
+ "node_modules/cross-spawn/lib/util/readShebang.js"(exports, module) {
10913
+ "use strict";
10914
+ var fs4 = __require("fs");
10915
+ var shebangCommand = require_shebang_command();
10916
+ function readShebang(command) {
10917
+ const size = 150;
10918
+ const buffer = Buffer.alloc(size);
10919
+ let fd;
10920
+ try {
10921
+ fd = fs4.openSync(command, "r");
10922
+ fs4.readSync(fd, buffer, 0, size, 0);
10923
+ fs4.closeSync(fd);
10924
+ } catch (e) {
10925
+ }
10926
+ return shebangCommand(buffer.toString());
10927
+ }
10928
+ module.exports = readShebang;
10929
+ }
10930
+ });
10931
+
10932
+ // node_modules/cross-spawn/lib/parse.js
10933
+ var require_parse = __commonJS({
10934
+ "node_modules/cross-spawn/lib/parse.js"(exports, module) {
10935
+ "use strict";
10936
+ var path4 = __require("path");
10937
+ var resolveCommand = require_resolveCommand();
10938
+ var escape2 = require_escape();
10939
+ var readShebang = require_readShebang();
10940
+ var isWin = process.platform === "win32";
10941
+ var isExecutableRegExp = /\.(?:com|exe)$/i;
10942
+ var isCmdShimRegExp = /node_modules[\\/].bin[\\/][^\\/]+\.cmd$/i;
10943
+ function detectShebang(parsed) {
10944
+ parsed.file = resolveCommand(parsed);
10945
+ const shebang = parsed.file && readShebang(parsed.file);
10946
+ if (shebang) {
10947
+ parsed.args.unshift(parsed.file);
10948
+ parsed.command = shebang;
10949
+ return resolveCommand(parsed);
10950
+ }
10951
+ return parsed.file;
10952
+ }
10953
+ function parseNonShell(parsed) {
10954
+ if (!isWin) {
10955
+ return parsed;
10956
+ }
10957
+ const commandFile = detectShebang(parsed);
10958
+ const needsShell = !isExecutableRegExp.test(commandFile);
10959
+ if (parsed.options.forceShell || needsShell) {
10960
+ const needsDoubleEscapeMetaChars = isCmdShimRegExp.test(commandFile);
10961
+ parsed.command = path4.normalize(parsed.command);
10962
+ parsed.command = escape2.command(parsed.command);
10963
+ parsed.args = parsed.args.map((arg) => escape2.argument(arg, needsDoubleEscapeMetaChars));
10964
+ const shellCommand = [parsed.command].concat(parsed.args).join(" ");
10965
+ parsed.args = ["/d", "/s", "/c", `"${shellCommand}"`];
10966
+ parsed.command = process.env.comspec || "cmd.exe";
10967
+ parsed.options.windowsVerbatimArguments = true;
10968
+ }
10969
+ return parsed;
10970
+ }
10971
+ function parse3(command, args, options) {
10972
+ if (args && !Array.isArray(args)) {
10973
+ options = args;
10974
+ args = null;
10975
+ }
10976
+ args = args ? args.slice(0) : [];
10977
+ options = Object.assign({}, options);
10978
+ const parsed = {
10979
+ command,
10980
+ args,
10981
+ options,
10982
+ file: void 0,
10983
+ original: {
10984
+ command,
10985
+ args
10986
+ }
10987
+ };
10988
+ return options.shell ? parsed : parseNonShell(parsed);
10989
+ }
10990
+ module.exports = parse3;
10991
+ }
10992
+ });
10993
+
10994
+ // node_modules/cross-spawn/lib/enoent.js
10995
+ var require_enoent = __commonJS({
10996
+ "node_modules/cross-spawn/lib/enoent.js"(exports, module) {
10997
+ "use strict";
10998
+ var isWin = process.platform === "win32";
10999
+ function notFoundError(original, syscall) {
11000
+ return Object.assign(new Error(`${syscall} ${original.command} ENOENT`), {
11001
+ code: "ENOENT",
11002
+ errno: "ENOENT",
11003
+ syscall: `${syscall} ${original.command}`,
11004
+ path: original.command,
11005
+ spawnargs: original.args
11006
+ });
11007
+ }
11008
+ function hookChildProcess(cp, parsed) {
11009
+ if (!isWin) {
11010
+ return;
11011
+ }
11012
+ const originalEmit = cp.emit;
11013
+ cp.emit = function(name, arg1) {
11014
+ if (name === "exit") {
11015
+ const err = verifyENOENT(arg1, parsed);
11016
+ if (err) {
11017
+ return originalEmit.call(cp, "error", err);
11018
+ }
11019
+ }
11020
+ return originalEmit.apply(cp, arguments);
11021
+ };
11022
+ }
11023
+ function verifyENOENT(status, parsed) {
11024
+ if (isWin && status === 1 && !parsed.file) {
11025
+ return notFoundError(parsed.original, "spawn");
11026
+ }
11027
+ return null;
11028
+ }
11029
+ function verifyENOENTSync(status, parsed) {
11030
+ if (isWin && status === 1 && !parsed.file) {
11031
+ return notFoundError(parsed.original, "spawnSync");
11032
+ }
11033
+ return null;
11034
+ }
11035
+ module.exports = {
11036
+ hookChildProcess,
11037
+ verifyENOENT,
11038
+ verifyENOENTSync,
11039
+ notFoundError
11040
+ };
11041
+ }
11042
+ });
11043
+
11044
+ // node_modules/cross-spawn/index.js
11045
+ var require_cross_spawn = __commonJS({
11046
+ "node_modules/cross-spawn/index.js"(exports, module) {
11047
+ "use strict";
11048
+ var cp = __require("child_process");
11049
+ var parse3 = require_parse();
11050
+ var enoent = require_enoent();
11051
+ function spawn2(command, args, options) {
11052
+ const parsed = parse3(command, args, options);
11053
+ const spawned = cp.spawn(parsed.command, parsed.args, parsed.options);
11054
+ enoent.hookChildProcess(spawned, parsed);
11055
+ return spawned;
11056
+ }
11057
+ function spawnSync(command, args, options) {
11058
+ const parsed = parse3(command, args, options);
11059
+ const result = cp.spawnSync(parsed.command, parsed.args, parsed.options);
11060
+ result.error = result.error || enoent.verifyENOENTSync(result.status, parsed);
11061
+ return result;
11062
+ }
11063
+ module.exports = spawn2;
11064
+ module.exports.spawn = spawn2;
11065
+ module.exports.sync = spawnSync;
11066
+ module.exports._parse = parse3;
11067
+ module.exports._enoent = enoent;
11068
+ }
11069
+ });
11070
+
10574
11071
  // node_modules/zod/v4/core/core.js
10575
11072
  var _a;
11073
+ var NEVER = /* @__PURE__ */ Object.freeze({
11074
+ status: "aborted"
11075
+ });
10576
11076
  // @__NO_SIDE_EFFECTS__
10577
11077
  function $constructor(name, initializer3, params) {
10578
11078
  function init(inst, def) {
@@ -10811,10 +11311,10 @@ function mergeDefs(...defs) {
10811
11311
  function cloneDef(schema) {
10812
11312
  return mergeDefs(schema._zod.def);
10813
11313
  }
10814
- function getElementAtPath(obj, path3) {
10815
- if (!path3)
11314
+ function getElementAtPath(obj, path4) {
11315
+ if (!path4)
10816
11316
  return obj;
10817
- return path3.reduce((acc, key) => acc?.[key], obj);
11317
+ return path4.reduce((acc, key) => acc?.[key], obj);
10818
11318
  }
10819
11319
  function promiseAllObject(promisesObj) {
10820
11320
  const keys = Object.keys(promisesObj);
@@ -11223,11 +11723,11 @@ function explicitlyAborted(x, startIndex = 0) {
11223
11723
  }
11224
11724
  return false;
11225
11725
  }
11226
- function prefixIssues(path3, issues) {
11726
+ function prefixIssues(path4, issues) {
11227
11727
  return issues.map((iss) => {
11228
11728
  var _a3;
11229
11729
  (_a3 = iss).path ?? (_a3.path = []);
11230
- iss.path.unshift(path3);
11730
+ iss.path.unshift(path4);
11231
11731
  return iss;
11232
11732
  });
11233
11733
  }
@@ -11374,16 +11874,16 @@ function flattenError(error2, mapper = (issue2) => issue2.message) {
11374
11874
  }
11375
11875
  function formatError(error2, mapper = (issue2) => issue2.message) {
11376
11876
  const fieldErrors = { _errors: [] };
11377
- const processError = (error3, path3 = []) => {
11877
+ const processError = (error3, path4 = []) => {
11378
11878
  for (const issue2 of error3.issues) {
11379
11879
  if (issue2.code === "invalid_union" && issue2.errors.length) {
11380
- issue2.errors.map((issues) => processError({ issues }, [...path3, ...issue2.path]));
11880
+ issue2.errors.map((issues) => processError({ issues }, [...path4, ...issue2.path]));
11381
11881
  } else if (issue2.code === "invalid_key") {
11382
- processError({ issues: issue2.issues }, [...path3, ...issue2.path]);
11882
+ processError({ issues: issue2.issues }, [...path4, ...issue2.path]);
11383
11883
  } else if (issue2.code === "invalid_element") {
11384
- processError({ issues: issue2.issues }, [...path3, ...issue2.path]);
11884
+ processError({ issues: issue2.issues }, [...path4, ...issue2.path]);
11385
11885
  } else {
11386
- const fullpath = [...path3, ...issue2.path];
11886
+ const fullpath = [...path4, ...issue2.path];
11387
11887
  if (fullpath.length === 0) {
11388
11888
  fieldErrors._errors.push(mapper(issue2));
11389
11889
  } else {
@@ -11538,6 +12038,7 @@ var string = (params) => {
11538
12038
  const regex = params ? `[\\s\\S]{${params?.minimum ?? 0},${params?.maximum ?? ""}}` : `[\\s\\S]*`;
11539
12039
  return new RegExp(`^${regex}$`);
11540
12040
  };
12041
+ var bigint = /^-?\d+n?$/;
11541
12042
  var integer = /^-?\d+$/;
11542
12043
  var number = /^-?\d+(?:\.\d+)?$/;
11543
12044
  var boolean = /^(?:true|false)$/i;
@@ -12160,10 +12661,10 @@ var $ZodURL = /* @__PURE__ */ $constructor("$ZodURL", (inst, def) => {
12160
12661
  return;
12161
12662
  }
12162
12663
  }
12163
- const url = new URL(trimmed);
12664
+ const url2 = new URL(trimmed);
12164
12665
  if (def.hostname) {
12165
12666
  def.hostname.lastIndex = 0;
12166
- if (!def.hostname.test(url.hostname)) {
12667
+ if (!def.hostname.test(url2.hostname)) {
12167
12668
  payload.issues.push({
12168
12669
  code: "invalid_format",
12169
12670
  format: "url",
@@ -12177,7 +12678,7 @@ var $ZodURL = /* @__PURE__ */ $constructor("$ZodURL", (inst, def) => {
12177
12678
  }
12178
12679
  if (def.protocol) {
12179
12680
  def.protocol.lastIndex = 0;
12180
- if (!def.protocol.test(url.protocol.endsWith(":") ? url.protocol.slice(0, -1) : url.protocol)) {
12681
+ if (!def.protocol.test(url2.protocol.endsWith(":") ? url2.protocol.slice(0, -1) : url2.protocol)) {
12181
12682
  payload.issues.push({
12182
12683
  code: "invalid_format",
12183
12684
  format: "url",
@@ -12190,7 +12691,7 @@ var $ZodURL = /* @__PURE__ */ $constructor("$ZodURL", (inst, def) => {
12190
12691
  }
12191
12692
  }
12192
12693
  if (def.normalize) {
12193
- payload.value = url.href;
12694
+ payload.value = url2.href;
12194
12695
  } else {
12195
12696
  payload.value = trimmed;
12196
12697
  }
@@ -12445,6 +12946,26 @@ var $ZodBoolean = /* @__PURE__ */ $constructor("$ZodBoolean", (inst, def) => {
12445
12946
  return payload;
12446
12947
  };
12447
12948
  });
12949
+ var $ZodBigInt = /* @__PURE__ */ $constructor("$ZodBigInt", (inst, def) => {
12950
+ $ZodType.init(inst, def);
12951
+ inst._zod.pattern = bigint;
12952
+ inst._zod.parse = (payload, _ctx) => {
12953
+ if (def.coerce)
12954
+ try {
12955
+ payload.value = BigInt(payload.value);
12956
+ } catch (_) {
12957
+ }
12958
+ if (typeof payload.value === "bigint")
12959
+ return payload;
12960
+ payload.issues.push({
12961
+ expected: "bigint",
12962
+ code: "invalid_type",
12963
+ input: payload.value,
12964
+ inst
12965
+ });
12966
+ return payload;
12967
+ };
12968
+ });
12448
12969
  var $ZodNull = /* @__PURE__ */ $constructor("$ZodNull", (inst, def) => {
12449
12970
  $ZodType.init(inst, def);
12450
12971
  inst._zod.pattern = _null;
@@ -12462,6 +12983,10 @@ var $ZodNull = /* @__PURE__ */ $constructor("$ZodNull", (inst, def) => {
12462
12983
  return payload;
12463
12984
  };
12464
12985
  });
12986
+ var $ZodAny = /* @__PURE__ */ $constructor("$ZodAny", (inst, def) => {
12987
+ $ZodType.init(inst, def);
12988
+ inst._zod.parse = (payload) => payload;
12989
+ });
12465
12990
  var $ZodUnknown = /* @__PURE__ */ $constructor("$ZodUnknown", (inst, def) => {
12466
12991
  $ZodType.init(inst, def);
12467
12992
  inst._zod.parse = (payload) => payload;
@@ -12478,6 +13003,30 @@ var $ZodNever = /* @__PURE__ */ $constructor("$ZodNever", (inst, def) => {
12478
13003
  return payload;
12479
13004
  };
12480
13005
  });
13006
+ var $ZodDate = /* @__PURE__ */ $constructor("$ZodDate", (inst, def) => {
13007
+ $ZodType.init(inst, def);
13008
+ inst._zod.parse = (payload, _ctx) => {
13009
+ if (def.coerce) {
13010
+ try {
13011
+ payload.value = new Date(payload.value);
13012
+ } catch (_err) {
13013
+ }
13014
+ }
13015
+ const input = payload.value;
13016
+ const isDate = input instanceof Date;
13017
+ const isValidDate = isDate && !Number.isNaN(input.getTime());
13018
+ if (isValidDate)
13019
+ return payload;
13020
+ payload.issues.push({
13021
+ expected: "date",
13022
+ code: "invalid_type",
13023
+ input,
13024
+ ...isDate ? { received: "Invalid Date" } : {},
13025
+ inst
13026
+ });
13027
+ return payload;
13028
+ };
13029
+ });
12481
13030
  function handleArrayResult(result, final, index) {
12482
13031
  if (result.issues.length) {
12483
13032
  final.issues.push(...prefixIssues(index, result.issues));
@@ -13628,6 +14177,14 @@ function _string(Class2, params) {
13628
14177
  });
13629
14178
  }
13630
14179
  // @__NO_SIDE_EFFECTS__
14180
+ function _coercedString(Class2, params) {
14181
+ return new Class2({
14182
+ type: "string",
14183
+ coerce: true,
14184
+ ...normalizeParams(params)
14185
+ });
14186
+ }
14187
+ // @__NO_SIDE_EFFECTS__
13631
14188
  function _email(Class2, params) {
13632
14189
  return new Class2({
13633
14190
  type: "string",
@@ -13899,6 +14456,15 @@ function _number(Class2, params) {
13899
14456
  });
13900
14457
  }
13901
14458
  // @__NO_SIDE_EFFECTS__
14459
+ function _coercedNumber(Class2, params) {
14460
+ return new Class2({
14461
+ type: "number",
14462
+ coerce: true,
14463
+ checks: [],
14464
+ ...normalizeParams(params)
14465
+ });
14466
+ }
14467
+ // @__NO_SIDE_EFFECTS__
13902
14468
  function _int(Class2, params) {
13903
14469
  return new Class2({
13904
14470
  type: "number",
@@ -13916,6 +14482,22 @@ function _boolean(Class2, params) {
13916
14482
  });
13917
14483
  }
13918
14484
  // @__NO_SIDE_EFFECTS__
14485
+ function _coercedBoolean(Class2, params) {
14486
+ return new Class2({
14487
+ type: "boolean",
14488
+ coerce: true,
14489
+ ...normalizeParams(params)
14490
+ });
14491
+ }
14492
+ // @__NO_SIDE_EFFECTS__
14493
+ function _coercedBigint(Class2, params) {
14494
+ return new Class2({
14495
+ type: "bigint",
14496
+ coerce: true,
14497
+ ...normalizeParams(params)
14498
+ });
14499
+ }
14500
+ // @__NO_SIDE_EFFECTS__
13919
14501
  function _null2(Class2, params) {
13920
14502
  return new Class2({
13921
14503
  type: "null",
@@ -13923,6 +14505,12 @@ function _null2(Class2, params) {
13923
14505
  });
13924
14506
  }
13925
14507
  // @__NO_SIDE_EFFECTS__
14508
+ function _any(Class2) {
14509
+ return new Class2({
14510
+ type: "any"
14511
+ });
14512
+ }
14513
+ // @__NO_SIDE_EFFECTS__
13926
14514
  function _unknown(Class2) {
13927
14515
  return new Class2({
13928
14516
  type: "unknown"
@@ -13936,6 +14524,14 @@ function _never(Class2, params) {
13936
14524
  });
13937
14525
  }
13938
14526
  // @__NO_SIDE_EFFECTS__
14527
+ function _coercedDate(Class2, params) {
14528
+ return new Class2({
14529
+ type: "date",
14530
+ coerce: true,
14531
+ ...normalizeParams(params)
14532
+ });
14533
+ }
14534
+ // @__NO_SIDE_EFFECTS__
13939
14535
  function _lt(value, params) {
13940
14536
  return new $ZodCheckLessThan({
13941
14537
  check: "less_than",
@@ -14583,6 +15179,11 @@ var numberProcessor = (schema, ctx, _json, _params) => {
14583
15179
  var booleanProcessor = (_schema, _ctx, json, _params) => {
14584
15180
  json.type = "boolean";
14585
15181
  };
15182
+ var bigintProcessor = (_schema, ctx, _json, _params) => {
15183
+ if (ctx.unrepresentable === "throw") {
15184
+ throw new Error("BigInt cannot be represented in JSON Schema");
15185
+ }
15186
+ };
14586
15187
  var nullProcessor = (_schema, ctx, json, _params) => {
14587
15188
  if (ctx.target === "openapi-3.0") {
14588
15189
  json.type = "string";
@@ -14595,8 +15196,15 @@ var nullProcessor = (_schema, ctx, json, _params) => {
14595
15196
  var neverProcessor = (_schema, _ctx, json, _params) => {
14596
15197
  json.not = {};
14597
15198
  };
15199
+ var anyProcessor = (_schema, _ctx, _json, _params) => {
15200
+ };
14598
15201
  var unknownProcessor = (_schema, _ctx, _json, _params) => {
14599
15202
  };
15203
+ var dateProcessor = (_schema, ctx, _json, _params) => {
15204
+ if (ctx.unrepresentable === "throw") {
15205
+ throw new Error("Date cannot be represented in JSON Schema");
15206
+ }
15207
+ };
14600
15208
  var enumProcessor = (schema, _ctx, json, _params) => {
14601
15209
  const def = schema._zod.def;
14602
15210
  const values = getEnumValues(def.entries);
@@ -15273,6 +15881,9 @@ var ZodURL = /* @__PURE__ */ $constructor("ZodURL", (inst, def) => {
15273
15881
  $ZodURL.init(inst, def);
15274
15882
  ZodStringFormat.init(inst, def);
15275
15883
  });
15884
+ function url(params) {
15885
+ return _url(ZodURL, params);
15886
+ }
15276
15887
  var ZodEmoji = /* @__PURE__ */ $constructor("ZodEmoji", (inst, def) => {
15277
15888
  $ZodEmoji.init(inst, def);
15278
15889
  ZodStringFormat.init(inst, def);
@@ -15409,6 +16020,28 @@ var ZodBoolean = /* @__PURE__ */ $constructor("ZodBoolean", (inst, def) => {
15409
16020
  function boolean2(params) {
15410
16021
  return _boolean(ZodBoolean, params);
15411
16022
  }
16023
+ var ZodBigInt = /* @__PURE__ */ $constructor("ZodBigInt", (inst, def) => {
16024
+ $ZodBigInt.init(inst, def);
16025
+ ZodType.init(inst, def);
16026
+ inst._zod.processJSONSchema = (ctx, json, params) => bigintProcessor(inst, ctx, json, params);
16027
+ inst.gte = (value, params) => inst.check(_gte(value, params));
16028
+ inst.min = (value, params) => inst.check(_gte(value, params));
16029
+ inst.gt = (value, params) => inst.check(_gt(value, params));
16030
+ inst.gte = (value, params) => inst.check(_gte(value, params));
16031
+ inst.min = (value, params) => inst.check(_gte(value, params));
16032
+ inst.lt = (value, params) => inst.check(_lt(value, params));
16033
+ inst.lte = (value, params) => inst.check(_lte(value, params));
16034
+ inst.max = (value, params) => inst.check(_lte(value, params));
16035
+ inst.positive = (params) => inst.check(_gt(BigInt(0), params));
16036
+ inst.negative = (params) => inst.check(_lt(BigInt(0), params));
16037
+ inst.nonpositive = (params) => inst.check(_lte(BigInt(0), params));
16038
+ inst.nonnegative = (params) => inst.check(_gte(BigInt(0), params));
16039
+ inst.multipleOf = (value, params) => inst.check(_multipleOf(value, params));
16040
+ const bag = inst._zod.bag;
16041
+ inst.minValue = bag.minimum ?? null;
16042
+ inst.maxValue = bag.maximum ?? null;
16043
+ inst.format = bag.format ?? null;
16044
+ });
15412
16045
  var ZodNull = /* @__PURE__ */ $constructor("ZodNull", (inst, def) => {
15413
16046
  $ZodNull.init(inst, def);
15414
16047
  ZodType.init(inst, def);
@@ -15417,6 +16050,14 @@ var ZodNull = /* @__PURE__ */ $constructor("ZodNull", (inst, def) => {
15417
16050
  function _null3(params) {
15418
16051
  return _null2(ZodNull, params);
15419
16052
  }
16053
+ var ZodAny = /* @__PURE__ */ $constructor("ZodAny", (inst, def) => {
16054
+ $ZodAny.init(inst, def);
16055
+ ZodType.init(inst, def);
16056
+ inst._zod.processJSONSchema = (ctx, json, params) => anyProcessor(inst, ctx, json, params);
16057
+ });
16058
+ function any() {
16059
+ return _any(ZodAny);
16060
+ }
15420
16061
  var ZodUnknown = /* @__PURE__ */ $constructor("ZodUnknown", (inst, def) => {
15421
16062
  $ZodUnknown.init(inst, def);
15422
16063
  ZodType.init(inst, def);
@@ -15433,6 +16074,16 @@ var ZodNever = /* @__PURE__ */ $constructor("ZodNever", (inst, def) => {
15433
16074
  function never(params) {
15434
16075
  return _never(ZodNever, params);
15435
16076
  }
16077
+ var ZodDate = /* @__PURE__ */ $constructor("ZodDate", (inst, def) => {
16078
+ $ZodDate.init(inst, def);
16079
+ ZodType.init(inst, def);
16080
+ inst._zod.processJSONSchema = (ctx, json, params) => dateProcessor(inst, ctx, json, params);
16081
+ inst.min = (value, params) => inst.check(_gte(value, params));
16082
+ inst.max = (value, params) => inst.check(_lte(value, params));
16083
+ const c = inst._zod.bag;
16084
+ inst.minDate = c.minimum ? new Date(c.minimum) : null;
16085
+ inst.maxDate = c.maximum ? new Date(c.maximum) : null;
16086
+ });
15436
16087
  var ZodArray = /* @__PURE__ */ $constructor("ZodArray", (inst, def) => {
15437
16088
  $ZodArray.init(inst, def);
15438
16089
  ZodType.init(inst, def);
@@ -15838,6 +16489,49 @@ function preprocess(fn, schema) {
15838
16489
  });
15839
16490
  }
15840
16491
 
16492
+ // node_modules/zod/v4/classic/compat.js
16493
+ var ZodIssueCode = {
16494
+ invalid_type: "invalid_type",
16495
+ too_big: "too_big",
16496
+ too_small: "too_small",
16497
+ invalid_format: "invalid_format",
16498
+ not_multiple_of: "not_multiple_of",
16499
+ unrecognized_keys: "unrecognized_keys",
16500
+ invalid_union: "invalid_union",
16501
+ invalid_key: "invalid_key",
16502
+ invalid_element: "invalid_element",
16503
+ invalid_value: "invalid_value",
16504
+ custom: "custom"
16505
+ };
16506
+ var ZodFirstPartyTypeKind;
16507
+ /* @__PURE__ */ (function(ZodFirstPartyTypeKind2) {
16508
+ })(ZodFirstPartyTypeKind || (ZodFirstPartyTypeKind = {}));
16509
+
16510
+ // node_modules/zod/v4/classic/coerce.js
16511
+ var coerce_exports = {};
16512
+ __export(coerce_exports, {
16513
+ bigint: () => bigint2,
16514
+ boolean: () => boolean3,
16515
+ date: () => date3,
16516
+ number: () => number3,
16517
+ string: () => string3
16518
+ });
16519
+ function string3(params) {
16520
+ return _coercedString(ZodString, params);
16521
+ }
16522
+ function number3(params) {
16523
+ return _coercedNumber(ZodNumber, params);
16524
+ }
16525
+ function boolean3(params) {
16526
+ return _coercedBoolean(ZodBoolean, params);
16527
+ }
16528
+ function bigint2(params) {
16529
+ return _coercedBigint(ZodBigInt, params);
16530
+ }
16531
+ function date3(params) {
16532
+ return _coercedDate(ZodDate, params);
16533
+ }
16534
+
15841
16535
  // node_modules/zod/v4/classic/external.js
15842
16536
  config(en_default());
15843
16537
 
@@ -16242,6 +16936,7 @@ var InitializedNotificationSchema = NotificationSchema.extend({
16242
16936
  method: literal("notifications/initialized"),
16243
16937
  params: NotificationsParamsSchema.optional()
16244
16938
  });
16939
+ var isInitializedNotification = (value) => InitializedNotificationSchema.safeParse(value).success;
16245
16940
  var PingRequestSchema = RequestSchema.extend({
16246
16941
  method: literal("ping"),
16247
16942
  params: BaseRequestParamsSchema.optional()
@@ -19142,12 +19837,12 @@ var import_websocket = __toESM(require_websocket(), 1);
19142
19837
  var import_websocket_server = __toESM(require_websocket_server(), 1);
19143
19838
 
19144
19839
  // src/index.ts
19145
- import crypto from "crypto";
19840
+ import crypto2 from "crypto";
19146
19841
  import http from "http";
19147
- import fs2 from "fs";
19148
- import path2 from "path";
19842
+ import fs3 from "fs";
19843
+ import path3 from "path";
19149
19844
  import { execFileSync } from "child_process";
19150
- import os from "os";
19845
+ import os2 from "os";
19151
19846
  import { fileURLToPath } from "url";
19152
19847
 
19153
19848
  // ../api/_lib/mcp-tools.ts
@@ -19163,6 +19858,11 @@ var HIDE_CLIP_IDS = {
19163
19858
  items: { type: "string" },
19164
19859
  description: "Render as if these clips were not there. The timeline is not changed."
19165
19860
  };
19861
+ var TEXT_BOX_PROPS = {
19862
+ wrapWidth: num("Widest a line may run before it wraps, as a fraction of the frame width (0.05\u20131). Defaults to about 0.86. Set it to keep body copy inside a column or a card."),
19863
+ anchorX: num("Which point of the text block posX places: 0 its left edge, 0.5 its centre (default), 1 its right edge. Use 0 for left-aligned text so its left edge stays put when the words change."),
19864
+ anchorY: num("Which point of the text block posY places: 0 its top, 0.5 its middle (default), 1 its bottom.")
19865
+ };
19166
19866
  var TEXT_STYLE_PROPS = {
19167
19867
  fontSize: num("Font size in pixels, authored against a 1080p-tall frame."),
19168
19868
  fontFamily: str("Font family name."),
@@ -19190,6 +19890,8 @@ var TEXT_STYLE_PROPS = {
19190
19890
  textAccentColor: str("Colour for accent words. Mark an accent word in the text as *word*."),
19191
19891
  textAccentFontFamily: str(`Font for accent words, e.g. "'Great Vibes', cursive" for a script word inside heavy caps.`),
19192
19892
  textAccentScale: num("Size of accent words relative to the rest, e.g. 1.8."),
19893
+ textAccentFontWeight: { type: ["number", "string"], description: `Weight of accent words, 100\u2013900, "normal" or "bold". Default: bold with an accent font, else the text's own weight.` },
19894
+ textAccentFontStyle: { type: "string", enum: ["normal", "italic"], description: "Slant of accent words. Default: italic with an accent font, else the text's own style." },
19193
19895
  textAccentGradientStart: str("Gradient start colour for accent words."),
19194
19896
  textAccentGradientEnd: str("Gradient end colour for accent words."),
19195
19897
  textSwooshUnderline: bool("Hand-drawn swoosh under the last line."),
@@ -19235,7 +19937,8 @@ var BASE_TOOLS = [
19235
19937
  mediaFileId: str("Media bin file id. Omit to list every source that has a transcript."),
19236
19938
  startTime: num("Only return segments overlapping at or after this source time, in seconds."),
19237
19939
  endTime: num("Only return segments overlapping before this source time, in seconds."),
19238
- includeWords: bool("Include per-word timings. Defaults to true; set false for a much smaller payload.")
19940
+ includeWords: bool("Include per-word timings. Defaults to true; set false for a much smaller payload."),
19941
+ onTimeline: bool("Return the words as they fall on the open sequence, through every cut and trim, in timeline seconds \u2014 what to time captions and shots against after the footage is edited. mediaFileId and the time range are ignored.")
19239
19942
  }
19240
19943
  },
19241
19944
  method: "getTranscript"
@@ -19358,6 +20061,18 @@ var BASE_TOOLS = [
19358
20061
  inputSchema: { type: "object", properties: {} },
19359
20062
  method: "listSequences"
19360
20063
  },
20064
+ {
20065
+ name: "export_design",
20066
+ description: "A sequence as design JSON \u2014 the format the Designs panel saves and inserts, with every sequence nested in it. Text, HTML and shape layers travel whole; media files are listed under files and not included. Read-only.",
20067
+ inputSchema: {
20068
+ type: "object",
20069
+ properties: {
20070
+ sequenceId: str("The sequence to export. Default: the open one."),
20071
+ name: str("Name to give the design. Default: the sequence name.")
20072
+ }
20073
+ },
20074
+ method: "exportDesign"
20075
+ },
19361
20076
  {
19362
20077
  name: "create_sequence",
19363
20078
  description: "Make a new, empty sequence. It takes the project's frame size and rate unless width, height or fps say otherwise, and can be given a fixed length. By default it opens, so the edits that follow build it; pass open: false to stay where you are and place it later with add_sequence_clip. Returns its id.",
@@ -19572,7 +20287,8 @@ var BASE_TOOLS = [
19572
20287
  duration: num("How long the card stays on screen, in seconds."),
19573
20288
  startTime: num("Where it starts on the timeline, in seconds. Defaults to 0."),
19574
20289
  trackId: str("Target video track. Defaults to the topmost one that is free across the card\u2019s span, creating a new track above everything if none is free."),
19575
- ...TEXT_STYLE_PROPS
20290
+ ...TEXT_STYLE_PROPS,
20291
+ ...TEXT_BOX_PROPS
19576
20292
  },
19577
20293
  required: ["text", "duration"]
19578
20294
  },
@@ -19586,7 +20302,8 @@ var BASE_TOOLS = [
19586
20302
  properties: {
19587
20303
  clipId: CLIP_ID,
19588
20304
  text: str("New text. Omit to change only the styling."),
19589
- ...TEXT_STYLE_PROPS
20305
+ ...TEXT_STYLE_PROPS,
20306
+ ...TEXT_BOX_PROPS
19590
20307
  },
19591
20308
  required: ["clipId"]
19592
20309
  },
@@ -20855,7 +21572,135 @@ var BASE_TOOLS = [
20855
21572
  description: "Re-apply the last undone edit.",
20856
21573
  inputSchema: { type: "object", properties: {} },
20857
21574
  method: "redo"
20858
- }
21575
+ },
21576
+ {
21577
+ name: "studio_tasks",
21578
+ description: 'The work GoatEdit Studio has for you in this project. Studio makes a video in stages (brief, research, script, breakdown (the script cut into parts), moodboard, styleGuide (the design language every part follows), storyboard, edit plan, combine (the parts joined into the final edit plan), timeline, mix, QC, export, plus any the user added, whose ids start "x-" and whose document is {"notes": string, "points"?: string[]}); a stage opens once the stages it reads are approved, so several are often open at once. Each task is kind "write" (write that stage\'s JSON document: follow `role` as your system prompt, read `inputs`, follow `lessons` when present (what this user has asked for before), and if `previousDraft` is there, revise it using `note` and `problems`) or kind "run" (ask the tab to do it with studio_run_stage). Open tasks in one run do not depend on each other: hand each to its own subagent and do them side by side. When a task names an `agent`, the user wants that subagent or skill of yours on it: hand the task to the subagent with that name, or use the skill with that name. In a batch of reels each run has `batch` (reel number, name, avatar); stages listed in batch.filled are filled by Studio itself (the locked script, the pilot\'s look), so leave them. For each write task: studio_claim it first (the person sees your agent working on that stage), then studio_submit the document. The reply to a submit names the stages it opened; call studio_tasks again for them. Stages waiting for the person are listed under waitingForPerson \u2014 stop there and tell the user to approve them in the Studio panel.',
21579
+ inputSchema: {
21580
+ type: "object",
21581
+ properties: {
21582
+ runId: str("Only this run. Omit for every run in the project."),
21583
+ detail: bool("Include each write task's role, inputs and previous draft (default true). False lists the tasks only.")
21584
+ }
21585
+ },
21586
+ method: "getStudioTasks"
21587
+ },
21588
+ {
21589
+ name: "studio_claim",
21590
+ description: 'Take a Studio write task before working on it, so the Studio panel shows your agent on that stage and nobody else starts it. agent names who is doing it as the person will see it ("Claude Code \u2014 script writer"). Claiming a task you already hold is fine; one someone else holds is refused.',
21591
+ inputSchema: {
21592
+ type: "object",
21593
+ properties: {
21594
+ runId: str("The run, from studio_tasks."),
21595
+ stage: str('The stage id, from studio_tasks (e.g. "script").'),
21596
+ agent: str("Who is doing it, shown in the panel.")
21597
+ },
21598
+ required: ["runId", "stage", "agent"]
21599
+ },
21600
+ method: "studioClaim"
21601
+ },
21602
+ {
21603
+ name: "studio_submit",
21604
+ description: "Hand in the document for a Studio stage you claimed. It goes through the same checks as Studio's own agents: if it fails them the reply lists the problems and the task stays yours to fix and submit again; if it passes it waits for the person, or passes on its own when the workflow says so. The reply names the stages that opened because of it.",
21605
+ inputSchema: {
21606
+ type: "object",
21607
+ properties: {
21608
+ runId: str("The run, from studio_tasks."),
21609
+ stage: str("The stage id."),
21610
+ document: { type: "object", description: "The stage's document, in the shape its role card gives." },
21611
+ agent: str("Who wrote it, as in studio_claim.")
21612
+ },
21613
+ required: ["runId", "stage", "document"]
21614
+ },
21615
+ method: "studioSubmit"
21616
+ },
21617
+ {
21618
+ name: "studio_run_stage",
21619
+ description: `Start a Studio stage the tab does itself: "timeline" (build the edit from the approved plan) or "qc" (check it), or a stage the workflow gives to Studio's agent in the tab. Returns at once; the work goes on in the tab and the panel shows it. Poll studio_tasks to see it finish.`,
21620
+ inputSchema: {
21621
+ type: "object",
21622
+ properties: {
21623
+ runId: str("The run, from studio_tasks."),
21624
+ stage: str("The stage id.")
21625
+ },
21626
+ required: ["runId", "stage"]
21627
+ },
21628
+ method: "studioRunStage"
21629
+ },
21630
+ {
21631
+ name: "studio_start_run",
21632
+ description: `Start a new Studio run in this project, for a video the user asked you to make with Studio. workflow "outside" gives every writing stage to you (the brief first); the person still approves the brief, script, storyboard and export in the Studio panel, and on any workflow the brief, the look (moodboard, styleGuide) and the export. Refused when it would push an unfinished run out of the project's Studio history. Then call studio_tasks.`,
21633
+ inputSchema: {
21634
+ type: "object",
21635
+ properties: {
21636
+ title: str("What the video is, in a few words."),
21637
+ workflow: str('A workflow id or name from the Studio panel: "outside" (default), "guided", "autopilot", "hands-on", or one the user saved.')
21638
+ },
21639
+ required: ["title"]
21640
+ },
21641
+ method: "studioStartRun"
21642
+ },
21643
+ {
21644
+ name: "studio_workflows",
21645
+ description: `The Studio workflows the user has (built-in and saved), and one of them stage by stage: what each stage holds, which stages it waits for, who writes it ("agent" = Studio's agent in the tab on the user's key, "outside" = you over MCP, "manual" = the person, "tab" = the tab builds it), who approves it, and the agent of yours named for it. Read this before studio_save_workflow.`,
21646
+ inputSchema: {
21647
+ type: "object",
21648
+ properties: {
21649
+ workflow: str('A workflow id or name to see stage by stage. Omit for the list, with the "outside" workflow in full.')
21650
+ }
21651
+ },
21652
+ method: "studioWorkflows"
21653
+ },
21654
+ {
21655
+ name: "studio_save_workflow",
21656
+ description: `Set Studio up for the user's way of working: save a workflow that says, stage by stage, who writes it and who approves it, and names your own subagent or skill for the stages you write. Only the name is kept: your agents, skills and their files stay with you and are never sent to GoatEdit. When a stage's task comes up, studio_tasks names the agent and you hand it over. Starts from another workflow (default "outside": you write every writing stage) and changes only what you give. Stages of your own (an avatar check, a sound pass) go under add; each writes {"notes", "points"} for the stages it feeds. The brief, moodboard, design language (styleGuide) and export always stay approved by the person. The same name replaces a workflow you saved earlier, never one the person made (yours is then saved under another name). The person sees it in the Studio panel and can change it there.`,
21657
+ inputSchema: {
21658
+ type: "object",
21659
+ properties: {
21660
+ workflow: {
21661
+ type: "object",
21662
+ description: "The workflow.",
21663
+ properties: {
21664
+ name: str('What the person will see, e.g. "Avatar reels".'),
21665
+ from: str('The workflow to start from, by id or name (default "outside").'),
21666
+ stages: {
21667
+ type: "object",
21668
+ description: 'Stage id (from studio_workflows) to its settings: { enabled?, writer?: "agent" | "outside" | "manual", approver?: "person" | "auto", agent?: your subagent or skill for it (implies writer "outside"), instructions?, tier?: "fast" | "writer" | "strong", review? }. Only optional stages can be turned off.',
21669
+ additionalProperties: { type: "object" }
21670
+ },
21671
+ add: {
21672
+ type: "array",
21673
+ description: 'Stages of your own: { label, brief? (what it does), agent?, after? (stage id it waits for, default "brief"), feeds? (stage ids that wait for it), writer?, approver? }.',
21674
+ items: { type: "object" }
21675
+ }
21676
+ },
21677
+ required: ["name"]
21678
+ }
21679
+ },
21680
+ required: ["workflow"]
21681
+ },
21682
+ method: "studioSaveWorkflow"
21683
+ },
21684
+ {
21685
+ name: "studio_start_batch",
21686
+ description: `Start a batch of reels: finished scripts (up to 20), one run and one sequence each, going side by side as one series. Reel 1 is the pilot: it designs the series look (moodboard, design language), the person approves it, and every other reel takes it. Each script is final: once its brief is approved Studio cuts it into beats word for word, so do not rewrite it. The person approves the pilot's brief, the look and each export, whatever the workflow says. Refused when it would push unfinished runs out of the project's Studio history (it keeps 60 batch reels). Give reels, or text the person pasted (blocks split by "---" with Name: and Avatar: lines at the top, or a CSV with name, avatar and script columns). Then call studio_tasks.`,
21687
+ inputSchema: {
21688
+ type: "object",
21689
+ properties: {
21690
+ title: str('The series name, e.g. "Health tips".'),
21691
+ series: str("The series: brand, audience, tone, platform. Every reel's brief is written from it."),
21692
+ reels: {
21693
+ type: "array",
21694
+ description: "One per reel: { name, script (word for word), avatar? (the HeyGen avatar that speaks it) }.",
21695
+ items: { type: "object" }
21696
+ },
21697
+ text: str("Instead of reels: the scripts as the person pasted them."),
21698
+ workflow: str('A workflow id or name (default "outside"); studio_save_workflow makes one.')
21699
+ },
21700
+ required: ["title"]
21701
+ },
21702
+ method: "studioStartBatch"
21703
+ }
20859
21704
  ];
20860
21705
  var SEQUENCE_EDITS = /* @__PURE__ */ new Set([
20861
21706
  "addClip",
@@ -20982,122 +21827,2563 @@ function typeError(key, schema, value) {
20982
21827
  if (schema.enum && !schema.enum.includes(value)) {
20983
21828
  return `Argument "${key}" must be one of: ${schema.enum.join(", ")}`;
20984
21829
  }
20985
- return null;
20986
- }
20987
- function validateArgs(tool, args) {
20988
- for (const key of tool.inputSchema.required ?? []) {
20989
- if (args[key] === void 0 || args[key] === null) return `Missing required argument: ${key}`;
21830
+ return null;
21831
+ }
21832
+ function validateArgs(tool, args) {
21833
+ for (const key of tool.inputSchema.required ?? []) {
21834
+ if (args[key] === void 0 || args[key] === null) return `Missing required argument: ${key}`;
21835
+ }
21836
+ const known = Object.keys(tool.inputSchema.properties);
21837
+ for (const [key, value] of Object.entries(args)) {
21838
+ if (value === void 0) continue;
21839
+ const schema = tool.inputSchema.properties[key];
21840
+ if (!schema) {
21841
+ const near = known.map((candidate) => ({ candidate, distance: editDistance(key.toLowerCase(), candidate.toLowerCase()) })).filter(({ candidate, distance }) => distance <= (candidate.length <= 4 ? 1 : 2)).sort((a, b) => a.distance - b.distance)[0];
21842
+ return near ? `Unknown argument "${key}" for ${tool.name}. Did you mean "${near.candidate}"?` : `Unknown argument "${key}" for ${tool.name}. Accepted: ${known.join(", ") || "(none)"}`;
21843
+ }
21844
+ if (value === null) continue;
21845
+ const problem = typeError(key, schema, value);
21846
+ if (problem) return problem;
21847
+ }
21848
+ return null;
21849
+ }
21850
+
21851
+ // ../api/_lib/mcp-content.ts
21852
+ var isImage = (v) => !!v && typeof v === "object" && typeof v.data === "string" && typeof v.mimeType === "string";
21853
+ function toContent(result) {
21854
+ if (!result || typeof result !== "object") {
21855
+ return [{ type: "text", text: JSON.stringify(result) ?? "null" }];
21856
+ }
21857
+ const { _image, _images, _file: _file2, ...rest } = result;
21858
+ if (_file2) rest.fileNote = "A file was made but this connection cannot deliver it. Use the local GoatEdit MCP server, which saves it to disk.";
21859
+ const blocks = [];
21860
+ const captions = [];
21861
+ for (const candidate of [_image, ...Array.isArray(_images) ? _images : []]) {
21862
+ if (!isImage(candidate)) continue;
21863
+ blocks.push({ type: "image", data: candidate.data, mimeType: candidate.mimeType });
21864
+ if (typeof candidate.caption === "string") captions.push(candidate.caption);
21865
+ }
21866
+ const text = captions.length ? JSON.stringify({ ...rest, frameCaptions: captions }) : JSON.stringify(Array.isArray(result) ? result : rest);
21867
+ blocks.push({ type: "text", text });
21868
+ return blocks;
21869
+ }
21870
+
21871
+ // src/find-local-file.ts
21872
+ import fs from "fs";
21873
+ import path from "path";
21874
+ function findLocalFile(root, wanted, maxDepth) {
21875
+ const name = wanted.trim();
21876
+ if (!name || !fs.existsSync(root)) return null;
21877
+ if (name.includes("/") || name.includes(path.sep)) {
21878
+ const full = path.resolve(root, name);
21879
+ if (!full.startsWith(root + path.sep)) return null;
21880
+ try {
21881
+ return fs.statSync(full).isFile() ? full : null;
21882
+ } catch {
21883
+ return null;
21884
+ }
21885
+ }
21886
+ const target = name.toLowerCase();
21887
+ let level = [root];
21888
+ for (let depth = 0; depth <= maxDepth && level.length; depth++) {
21889
+ const hits = [];
21890
+ const next = [];
21891
+ for (const dir of level) {
21892
+ let entries;
21893
+ try {
21894
+ entries = fs.readdirSync(dir, { withFileTypes: true });
21895
+ } catch {
21896
+ continue;
21897
+ }
21898
+ for (const entry of entries) {
21899
+ if (entry.name.startsWith(".")) continue;
21900
+ const full = path.join(dir, entry.name);
21901
+ if (entry.isDirectory()) next.push(full);
21902
+ else if (entry.isFile() && entry.name.toLowerCase() === target) hits.push(full);
21903
+ }
21904
+ }
21905
+ if (hits.length > 1) {
21906
+ throw new Error(
21907
+ `Several files are named "${name}": ${hits.map((h) => path.relative(root, h)).sort().join(", ")}. Pass one of these paths as filename.`
21908
+ );
21909
+ }
21910
+ if (hits.length === 1) return hits[0];
21911
+ level = next;
21912
+ }
21913
+ return null;
21914
+ }
21915
+
21916
+ // src/run-refs.ts
21917
+ function resolveRefs(value, refs) {
21918
+ if (typeof value === "string") {
21919
+ const m = /^\$([A-Za-z_][\w-]*)((?:\.[^.]+)*)$/.exec(value);
21920
+ if (!m || !refs.has(m[1])) return value;
21921
+ let x = refs.get(m[1]);
21922
+ for (const key of m[2].split(".").slice(1)) {
21923
+ x = x && typeof x === "object" ? x[key] : void 0;
21924
+ if (x === void 0) throw new Error(`${value}: step "${m[1]}" has no "${m[2].slice(1)}". It returned ${JSON.stringify(refs.get(m[1])).slice(0, 300)}`);
21925
+ }
21926
+ return x;
21927
+ }
21928
+ if (Array.isArray(value)) return value.map((v) => resolveRefs(v, refs));
21929
+ if (value && typeof value === "object") {
21930
+ return Object.fromEntries(Object.entries(value).map(([k, v]) => [k, resolveRefs(v, refs)]));
21931
+ }
21932
+ return value;
21933
+ }
21934
+ function withRunProject(stepArgs, projectId) {
21935
+ if (typeof projectId !== "string" || !projectId || typeof stepArgs.projectId === "string") return stepArgs;
21936
+ return { ...stepArgs, projectId };
21937
+ }
21938
+
21939
+ // src/tab-registry.ts
21940
+ function indexTabs(reports, isOpen) {
21941
+ const index = /* @__PURE__ */ new Map();
21942
+ for (const r of [...reports].sort((a, b) => a.at - b.at)) {
21943
+ if (isOpen(r.socket)) index.set(r.projectId, r);
21944
+ }
21945
+ return index;
21946
+ }
21947
+
21948
+ // node_modules/@modelcontextprotocol/sdk/dist/esm/experimental/tasks/client.js
21949
+ var ExperimentalClientTasks = class {
21950
+ constructor(_client) {
21951
+ this._client = _client;
21952
+ }
21953
+ /**
21954
+ * Calls a tool and returns an AsyncGenerator that yields response messages.
21955
+ * The generator is guaranteed to end with either a 'result' or 'error' message.
21956
+ *
21957
+ * This method provides streaming access to tool execution, allowing you to
21958
+ * observe intermediate task status updates for long-running tool calls.
21959
+ * Automatically validates structured output if the tool has an outputSchema.
21960
+ *
21961
+ * @example
21962
+ * ```typescript
21963
+ * const stream = client.experimental.tasks.callToolStream({ name: 'myTool', arguments: {} });
21964
+ * for await (const message of stream) {
21965
+ * switch (message.type) {
21966
+ * case 'taskCreated':
21967
+ * console.log('Tool execution started:', message.task.taskId);
21968
+ * break;
21969
+ * case 'taskStatus':
21970
+ * console.log('Tool status:', message.task.status);
21971
+ * break;
21972
+ * case 'result':
21973
+ * console.log('Tool result:', message.result);
21974
+ * break;
21975
+ * case 'error':
21976
+ * console.error('Tool error:', message.error);
21977
+ * break;
21978
+ * }
21979
+ * }
21980
+ * ```
21981
+ *
21982
+ * @param params - Tool call parameters (name and arguments)
21983
+ * @param resultSchema - Zod schema for validating the result (defaults to CallToolResultSchema)
21984
+ * @param options - Optional request options (timeout, signal, task creation params, etc.)
21985
+ * @returns AsyncGenerator that yields ResponseMessage objects
21986
+ *
21987
+ * @experimental
21988
+ */
21989
+ async *callToolStream(params, resultSchema = CallToolResultSchema, options) {
21990
+ const clientInternal = this._client;
21991
+ const optionsWithTask = {
21992
+ ...options,
21993
+ // We check if the tool is known to be a task during auto-configuration, but assume
21994
+ // the caller knows what they're doing if they pass this explicitly
21995
+ task: options?.task ?? (clientInternal.isToolTask(params.name) ? {} : void 0)
21996
+ };
21997
+ const stream = clientInternal.requestStream({ method: "tools/call", params }, resultSchema, optionsWithTask);
21998
+ const validator = clientInternal.getToolOutputValidator(params.name);
21999
+ for await (const message of stream) {
22000
+ if (message.type === "result" && validator) {
22001
+ const result = message.result;
22002
+ if (!result.structuredContent && !result.isError) {
22003
+ yield {
22004
+ type: "error",
22005
+ error: new McpError(ErrorCode.InvalidRequest, `Tool ${params.name} has an output schema but did not return structured content`)
22006
+ };
22007
+ return;
22008
+ }
22009
+ if (result.structuredContent) {
22010
+ try {
22011
+ const validationResult = validator(result.structuredContent);
22012
+ if (!validationResult.valid) {
22013
+ yield {
22014
+ type: "error",
22015
+ error: new McpError(ErrorCode.InvalidParams, `Structured content does not match the tool's output schema: ${validationResult.errorMessage}`)
22016
+ };
22017
+ return;
22018
+ }
22019
+ } catch (error2) {
22020
+ if (error2 instanceof McpError) {
22021
+ yield { type: "error", error: error2 };
22022
+ return;
22023
+ }
22024
+ yield {
22025
+ type: "error",
22026
+ error: new McpError(ErrorCode.InvalidParams, `Failed to validate structured content: ${error2 instanceof Error ? error2.message : String(error2)}`)
22027
+ };
22028
+ return;
22029
+ }
22030
+ }
22031
+ }
22032
+ yield message;
22033
+ }
22034
+ }
22035
+ /**
22036
+ * Gets the current status of a task.
22037
+ *
22038
+ * @param taskId - The task identifier
22039
+ * @param options - Optional request options
22040
+ * @returns The task status
22041
+ *
22042
+ * @experimental
22043
+ */
22044
+ async getTask(taskId, options) {
22045
+ return this._client.getTask({ taskId }, options);
22046
+ }
22047
+ /**
22048
+ * Retrieves the result of a completed task.
22049
+ *
22050
+ * @param taskId - The task identifier
22051
+ * @param resultSchema - Zod schema for validating the result
22052
+ * @param options - Optional request options
22053
+ * @returns The task result
22054
+ *
22055
+ * @experimental
22056
+ */
22057
+ async getTaskResult(taskId, resultSchema, options) {
22058
+ return this._client.getTaskResult({ taskId }, resultSchema, options);
22059
+ }
22060
+ /**
22061
+ * Lists tasks with optional pagination.
22062
+ *
22063
+ * @param cursor - Optional pagination cursor
22064
+ * @param options - Optional request options
22065
+ * @returns List of tasks with optional next cursor
22066
+ *
22067
+ * @experimental
22068
+ */
22069
+ async listTasks(cursor, options) {
22070
+ return this._client.listTasks(cursor ? { cursor } : void 0, options);
22071
+ }
22072
+ /**
22073
+ * Cancels a running task.
22074
+ *
22075
+ * @param taskId - The task identifier
22076
+ * @param options - Optional request options
22077
+ *
22078
+ * @experimental
22079
+ */
22080
+ async cancelTask(taskId, options) {
22081
+ return this._client.cancelTask({ taskId }, options);
22082
+ }
22083
+ /**
22084
+ * Sends a request and returns an AsyncGenerator that yields response messages.
22085
+ * The generator is guaranteed to end with either a 'result' or 'error' message.
22086
+ *
22087
+ * This method provides streaming access to request processing, allowing you to
22088
+ * observe intermediate task status updates for task-augmented requests.
22089
+ *
22090
+ * @param request - The request to send
22091
+ * @param resultSchema - Zod schema for validating the result
22092
+ * @param options - Optional request options (timeout, signal, task creation params, etc.)
22093
+ * @returns AsyncGenerator that yields ResponseMessage objects
22094
+ *
22095
+ * @experimental
22096
+ */
22097
+ requestStream(request, resultSchema, options) {
22098
+ return this._client.requestStream(request, resultSchema, options);
22099
+ }
22100
+ };
22101
+
22102
+ // node_modules/@modelcontextprotocol/sdk/dist/esm/client/index.js
22103
+ function applyElicitationDefaults(schema, data) {
22104
+ if (!schema || data === null || typeof data !== "object")
22105
+ return;
22106
+ if (schema.type === "object" && schema.properties && typeof schema.properties === "object") {
22107
+ const obj = data;
22108
+ const props = schema.properties;
22109
+ for (const key of Object.keys(props)) {
22110
+ const propSchema = props[key];
22111
+ if (obj[key] === void 0 && Object.prototype.hasOwnProperty.call(propSchema, "default")) {
22112
+ obj[key] = propSchema.default;
22113
+ }
22114
+ if (obj[key] !== void 0) {
22115
+ applyElicitationDefaults(propSchema, obj[key]);
22116
+ }
22117
+ }
22118
+ }
22119
+ if (Array.isArray(schema.anyOf)) {
22120
+ for (const sub of schema.anyOf) {
22121
+ if (typeof sub !== "boolean") {
22122
+ applyElicitationDefaults(sub, data);
22123
+ }
22124
+ }
22125
+ }
22126
+ if (Array.isArray(schema.oneOf)) {
22127
+ for (const sub of schema.oneOf) {
22128
+ if (typeof sub !== "boolean") {
22129
+ applyElicitationDefaults(sub, data);
22130
+ }
22131
+ }
22132
+ }
22133
+ }
22134
+ function getSupportedElicitationModes(capabilities) {
22135
+ if (!capabilities) {
22136
+ return { supportsFormMode: false, supportsUrlMode: false };
22137
+ }
22138
+ const hasFormCapability = capabilities.form !== void 0;
22139
+ const hasUrlCapability = capabilities.url !== void 0;
22140
+ const supportsFormMode = hasFormCapability || !hasFormCapability && !hasUrlCapability;
22141
+ const supportsUrlMode = hasUrlCapability;
22142
+ return { supportsFormMode, supportsUrlMode };
22143
+ }
22144
+ var Client = class extends Protocol {
22145
+ /**
22146
+ * Initializes this client with the given name and version information.
22147
+ */
22148
+ constructor(_clientInfo, options) {
22149
+ super(options);
22150
+ this._clientInfo = _clientInfo;
22151
+ this._cachedToolOutputValidators = /* @__PURE__ */ new Map();
22152
+ this._cachedKnownTaskTools = /* @__PURE__ */ new Set();
22153
+ this._cachedRequiredTaskTools = /* @__PURE__ */ new Set();
22154
+ this._listChangedDebounceTimers = /* @__PURE__ */ new Map();
22155
+ this._capabilities = options?.capabilities ?? {};
22156
+ this._jsonSchemaValidator = options?.jsonSchemaValidator ?? new AjvJsonSchemaValidator();
22157
+ if (options?.listChanged) {
22158
+ this._pendingListChangedConfig = options.listChanged;
22159
+ }
22160
+ }
22161
+ /**
22162
+ * Set up handlers for list changed notifications based on config and server capabilities.
22163
+ * This should only be called after initialization when server capabilities are known.
22164
+ * Handlers are silently skipped if the server doesn't advertise the corresponding listChanged capability.
22165
+ * @internal
22166
+ */
22167
+ _setupListChangedHandlers(config2) {
22168
+ if (config2.tools && this._serverCapabilities?.tools?.listChanged) {
22169
+ this._setupListChangedHandler("tools", ToolListChangedNotificationSchema, config2.tools, async () => {
22170
+ const result = await this.listTools();
22171
+ return result.tools;
22172
+ });
22173
+ }
22174
+ if (config2.prompts && this._serverCapabilities?.prompts?.listChanged) {
22175
+ this._setupListChangedHandler("prompts", PromptListChangedNotificationSchema, config2.prompts, async () => {
22176
+ const result = await this.listPrompts();
22177
+ return result.prompts;
22178
+ });
22179
+ }
22180
+ if (config2.resources && this._serverCapabilities?.resources?.listChanged) {
22181
+ this._setupListChangedHandler("resources", ResourceListChangedNotificationSchema, config2.resources, async () => {
22182
+ const result = await this.listResources();
22183
+ return result.resources;
22184
+ });
22185
+ }
22186
+ }
22187
+ /**
22188
+ * Access experimental features.
22189
+ *
22190
+ * WARNING: These APIs are experimental and may change without notice.
22191
+ *
22192
+ * @experimental
22193
+ */
22194
+ get experimental() {
22195
+ if (!this._experimental) {
22196
+ this._experimental = {
22197
+ tasks: new ExperimentalClientTasks(this)
22198
+ };
22199
+ }
22200
+ return this._experimental;
22201
+ }
22202
+ /**
22203
+ * Registers new capabilities. This can only be called before connecting to a transport.
22204
+ *
22205
+ * The new capabilities will be merged with any existing capabilities previously given (e.g., at initialization).
22206
+ */
22207
+ registerCapabilities(capabilities) {
22208
+ if (this.transport) {
22209
+ throw new Error("Cannot register capabilities after connecting to transport");
22210
+ }
22211
+ this._capabilities = mergeCapabilities(this._capabilities, capabilities);
22212
+ }
22213
+ /**
22214
+ * Override request handler registration to enforce client-side validation for elicitation.
22215
+ */
22216
+ setRequestHandler(requestSchema, handler) {
22217
+ const shape = getObjectShape(requestSchema);
22218
+ const methodSchema = shape?.method;
22219
+ if (!methodSchema) {
22220
+ throw new Error("Schema is missing a method literal");
22221
+ }
22222
+ let methodValue;
22223
+ if (isZ4Schema(methodSchema)) {
22224
+ const v4Schema = methodSchema;
22225
+ const v4Def = v4Schema._zod?.def;
22226
+ methodValue = v4Def?.value ?? v4Schema.value;
22227
+ } else {
22228
+ const v3Schema = methodSchema;
22229
+ const legacyDef = v3Schema._def;
22230
+ methodValue = legacyDef?.value ?? v3Schema.value;
22231
+ }
22232
+ if (typeof methodValue !== "string") {
22233
+ throw new Error("Schema method literal must be a string");
22234
+ }
22235
+ const method = methodValue;
22236
+ if (method === "elicitation/create") {
22237
+ const wrappedHandler = async (request, extra) => {
22238
+ const validatedRequest = safeParse2(ElicitRequestSchema, request);
22239
+ if (!validatedRequest.success) {
22240
+ const errorMessage = validatedRequest.error instanceof Error ? validatedRequest.error.message : String(validatedRequest.error);
22241
+ throw new McpError(ErrorCode.InvalidParams, `Invalid elicitation request: ${errorMessage}`);
22242
+ }
22243
+ const { params } = validatedRequest.data;
22244
+ params.mode = params.mode ?? "form";
22245
+ const { supportsFormMode, supportsUrlMode } = getSupportedElicitationModes(this._capabilities.elicitation);
22246
+ if (params.mode === "form" && !supportsFormMode) {
22247
+ throw new McpError(ErrorCode.InvalidParams, "Client does not support form-mode elicitation requests");
22248
+ }
22249
+ if (params.mode === "url" && !supportsUrlMode) {
22250
+ throw new McpError(ErrorCode.InvalidParams, "Client does not support URL-mode elicitation requests");
22251
+ }
22252
+ const result = await Promise.resolve(handler(request, extra));
22253
+ if (params.task) {
22254
+ const taskValidationResult = safeParse2(CreateTaskResultSchema, result);
22255
+ if (!taskValidationResult.success) {
22256
+ const errorMessage = taskValidationResult.error instanceof Error ? taskValidationResult.error.message : String(taskValidationResult.error);
22257
+ throw new McpError(ErrorCode.InvalidParams, `Invalid task creation result: ${errorMessage}`);
22258
+ }
22259
+ return taskValidationResult.data;
22260
+ }
22261
+ const validationResult = safeParse2(ElicitResultSchema, result);
22262
+ if (!validationResult.success) {
22263
+ const errorMessage = validationResult.error instanceof Error ? validationResult.error.message : String(validationResult.error);
22264
+ throw new McpError(ErrorCode.InvalidParams, `Invalid elicitation result: ${errorMessage}`);
22265
+ }
22266
+ const validatedResult = validationResult.data;
22267
+ const requestedSchema = params.mode === "form" ? params.requestedSchema : void 0;
22268
+ if (params.mode === "form" && validatedResult.action === "accept" && validatedResult.content && requestedSchema) {
22269
+ if (this._capabilities.elicitation?.form?.applyDefaults) {
22270
+ try {
22271
+ applyElicitationDefaults(requestedSchema, validatedResult.content);
22272
+ } catch {
22273
+ }
22274
+ }
22275
+ }
22276
+ return validatedResult;
22277
+ };
22278
+ return super.setRequestHandler(requestSchema, wrappedHandler);
22279
+ }
22280
+ if (method === "sampling/createMessage") {
22281
+ const wrappedHandler = async (request, extra) => {
22282
+ const validatedRequest = safeParse2(CreateMessageRequestSchema, request);
22283
+ if (!validatedRequest.success) {
22284
+ const errorMessage = validatedRequest.error instanceof Error ? validatedRequest.error.message : String(validatedRequest.error);
22285
+ throw new McpError(ErrorCode.InvalidParams, `Invalid sampling request: ${errorMessage}`);
22286
+ }
22287
+ const { params } = validatedRequest.data;
22288
+ const result = await Promise.resolve(handler(request, extra));
22289
+ if (params.task) {
22290
+ const taskValidationResult = safeParse2(CreateTaskResultSchema, result);
22291
+ if (!taskValidationResult.success) {
22292
+ const errorMessage = taskValidationResult.error instanceof Error ? taskValidationResult.error.message : String(taskValidationResult.error);
22293
+ throw new McpError(ErrorCode.InvalidParams, `Invalid task creation result: ${errorMessage}`);
22294
+ }
22295
+ return taskValidationResult.data;
22296
+ }
22297
+ const hasTools = params.tools || params.toolChoice;
22298
+ const resultSchema = hasTools ? CreateMessageResultWithToolsSchema : CreateMessageResultSchema;
22299
+ const validationResult = safeParse2(resultSchema, result);
22300
+ if (!validationResult.success) {
22301
+ const errorMessage = validationResult.error instanceof Error ? validationResult.error.message : String(validationResult.error);
22302
+ throw new McpError(ErrorCode.InvalidParams, `Invalid sampling result: ${errorMessage}`);
22303
+ }
22304
+ return validationResult.data;
22305
+ };
22306
+ return super.setRequestHandler(requestSchema, wrappedHandler);
22307
+ }
22308
+ return super.setRequestHandler(requestSchema, handler);
22309
+ }
22310
+ assertCapability(capability, method) {
22311
+ if (!this._serverCapabilities?.[capability]) {
22312
+ throw new Error(`Server does not support ${capability} (required for ${method})`);
22313
+ }
22314
+ }
22315
+ async connect(transport, options) {
22316
+ await super.connect(transport);
22317
+ if (transport.sessionId !== void 0) {
22318
+ return;
22319
+ }
22320
+ try {
22321
+ const result = await this.request({
22322
+ method: "initialize",
22323
+ params: {
22324
+ protocolVersion: LATEST_PROTOCOL_VERSION,
22325
+ capabilities: this._capabilities,
22326
+ clientInfo: this._clientInfo
22327
+ }
22328
+ }, InitializeResultSchema, options);
22329
+ if (result === void 0) {
22330
+ throw new Error(`Server sent invalid initialize result: ${result}`);
22331
+ }
22332
+ if (!SUPPORTED_PROTOCOL_VERSIONS.includes(result.protocolVersion)) {
22333
+ throw new Error(`Server's protocol version is not supported: ${result.protocolVersion}`);
22334
+ }
22335
+ this._serverCapabilities = result.capabilities;
22336
+ this._serverVersion = result.serverInfo;
22337
+ if (transport.setProtocolVersion) {
22338
+ transport.setProtocolVersion(result.protocolVersion);
22339
+ }
22340
+ this._instructions = result.instructions;
22341
+ await this.notification({
22342
+ method: "notifications/initialized"
22343
+ });
22344
+ if (this._pendingListChangedConfig) {
22345
+ this._setupListChangedHandlers(this._pendingListChangedConfig);
22346
+ this._pendingListChangedConfig = void 0;
22347
+ }
22348
+ } catch (error2) {
22349
+ void this.close();
22350
+ throw error2;
22351
+ }
22352
+ }
22353
+ /**
22354
+ * After initialization has completed, this will be populated with the server's reported capabilities.
22355
+ */
22356
+ getServerCapabilities() {
22357
+ return this._serverCapabilities;
22358
+ }
22359
+ /**
22360
+ * After initialization has completed, this will be populated with information about the server's name and version.
22361
+ */
22362
+ getServerVersion() {
22363
+ return this._serverVersion;
22364
+ }
22365
+ /**
22366
+ * After initialization has completed, this may be populated with information about the server's instructions.
22367
+ */
22368
+ getInstructions() {
22369
+ return this._instructions;
22370
+ }
22371
+ assertCapabilityForMethod(method) {
22372
+ switch (method) {
22373
+ case "logging/setLevel":
22374
+ if (!this._serverCapabilities?.logging) {
22375
+ throw new Error(`Server does not support logging (required for ${method})`);
22376
+ }
22377
+ break;
22378
+ case "prompts/get":
22379
+ case "prompts/list":
22380
+ if (!this._serverCapabilities?.prompts) {
22381
+ throw new Error(`Server does not support prompts (required for ${method})`);
22382
+ }
22383
+ break;
22384
+ case "resources/list":
22385
+ case "resources/templates/list":
22386
+ case "resources/read":
22387
+ case "resources/subscribe":
22388
+ case "resources/unsubscribe":
22389
+ if (!this._serverCapabilities?.resources) {
22390
+ throw new Error(`Server does not support resources (required for ${method})`);
22391
+ }
22392
+ if (method === "resources/subscribe" && !this._serverCapabilities.resources.subscribe) {
22393
+ throw new Error(`Server does not support resource subscriptions (required for ${method})`);
22394
+ }
22395
+ break;
22396
+ case "tools/call":
22397
+ case "tools/list":
22398
+ if (!this._serverCapabilities?.tools) {
22399
+ throw new Error(`Server does not support tools (required for ${method})`);
22400
+ }
22401
+ break;
22402
+ case "completion/complete":
22403
+ if (!this._serverCapabilities?.completions) {
22404
+ throw new Error(`Server does not support completions (required for ${method})`);
22405
+ }
22406
+ break;
22407
+ case "initialize":
22408
+ break;
22409
+ case "ping":
22410
+ break;
22411
+ }
22412
+ }
22413
+ assertNotificationCapability(method) {
22414
+ switch (method) {
22415
+ case "notifications/roots/list_changed":
22416
+ if (!this._capabilities.roots?.listChanged) {
22417
+ throw new Error(`Client does not support roots list changed notifications (required for ${method})`);
22418
+ }
22419
+ break;
22420
+ case "notifications/initialized":
22421
+ break;
22422
+ case "notifications/cancelled":
22423
+ break;
22424
+ case "notifications/progress":
22425
+ break;
22426
+ }
22427
+ }
22428
+ assertRequestHandlerCapability(method) {
22429
+ if (!this._capabilities) {
22430
+ return;
22431
+ }
22432
+ switch (method) {
22433
+ case "sampling/createMessage":
22434
+ if (!this._capabilities.sampling) {
22435
+ throw new Error(`Client does not support sampling capability (required for ${method})`);
22436
+ }
22437
+ break;
22438
+ case "elicitation/create":
22439
+ if (!this._capabilities.elicitation) {
22440
+ throw new Error(`Client does not support elicitation capability (required for ${method})`);
22441
+ }
22442
+ break;
22443
+ case "roots/list":
22444
+ if (!this._capabilities.roots) {
22445
+ throw new Error(`Client does not support roots capability (required for ${method})`);
22446
+ }
22447
+ break;
22448
+ case "tasks/get":
22449
+ case "tasks/list":
22450
+ case "tasks/result":
22451
+ case "tasks/cancel":
22452
+ if (!this._capabilities.tasks) {
22453
+ throw new Error(`Client does not support tasks capability (required for ${method})`);
22454
+ }
22455
+ break;
22456
+ case "ping":
22457
+ break;
22458
+ }
22459
+ }
22460
+ assertTaskCapability(method) {
22461
+ assertToolsCallTaskCapability(this._serverCapabilities?.tasks?.requests, method, "Server");
22462
+ }
22463
+ assertTaskHandlerCapability(method) {
22464
+ if (!this._capabilities) {
22465
+ return;
22466
+ }
22467
+ assertClientRequestTaskCapability(this._capabilities.tasks?.requests, method, "Client");
22468
+ }
22469
+ async ping(options) {
22470
+ return this.request({ method: "ping" }, EmptyResultSchema, options);
22471
+ }
22472
+ async complete(params, options) {
22473
+ return this.request({ method: "completion/complete", params }, CompleteResultSchema, options);
22474
+ }
22475
+ async setLoggingLevel(level, options) {
22476
+ return this.request({ method: "logging/setLevel", params: { level } }, EmptyResultSchema, options);
22477
+ }
22478
+ async getPrompt(params, options) {
22479
+ return this.request({ method: "prompts/get", params }, GetPromptResultSchema, options);
22480
+ }
22481
+ async listPrompts(params, options) {
22482
+ return this.request({ method: "prompts/list", params }, ListPromptsResultSchema, options);
22483
+ }
22484
+ async listResources(params, options) {
22485
+ return this.request({ method: "resources/list", params }, ListResourcesResultSchema, options);
22486
+ }
22487
+ async listResourceTemplates(params, options) {
22488
+ return this.request({ method: "resources/templates/list", params }, ListResourceTemplatesResultSchema, options);
22489
+ }
22490
+ async readResource(params, options) {
22491
+ return this.request({ method: "resources/read", params }, ReadResourceResultSchema, options);
22492
+ }
22493
+ async subscribeResource(params, options) {
22494
+ return this.request({ method: "resources/subscribe", params }, EmptyResultSchema, options);
22495
+ }
22496
+ async unsubscribeResource(params, options) {
22497
+ return this.request({ method: "resources/unsubscribe", params }, EmptyResultSchema, options);
22498
+ }
22499
+ /**
22500
+ * Calls a tool and waits for the result. Automatically validates structured output if the tool has an outputSchema.
22501
+ *
22502
+ * For task-based execution with streaming behavior, use client.experimental.tasks.callToolStream() instead.
22503
+ */
22504
+ async callTool(params, resultSchema = CallToolResultSchema, options) {
22505
+ if (this.isToolTaskRequired(params.name)) {
22506
+ throw new McpError(ErrorCode.InvalidRequest, `Tool "${params.name}" requires task-based execution. Use client.experimental.tasks.callToolStream() instead.`);
22507
+ }
22508
+ const result = await this.request({ method: "tools/call", params }, resultSchema, options);
22509
+ const validator = this.getToolOutputValidator(params.name);
22510
+ if (validator) {
22511
+ if (!result.structuredContent && !result.isError) {
22512
+ throw new McpError(ErrorCode.InvalidRequest, `Tool ${params.name} has an output schema but did not return structured content`);
22513
+ }
22514
+ if (result.structuredContent) {
22515
+ try {
22516
+ const validationResult = validator(result.structuredContent);
22517
+ if (!validationResult.valid) {
22518
+ throw new McpError(ErrorCode.InvalidParams, `Structured content does not match the tool's output schema: ${validationResult.errorMessage}`);
22519
+ }
22520
+ } catch (error2) {
22521
+ if (error2 instanceof McpError) {
22522
+ throw error2;
22523
+ }
22524
+ throw new McpError(ErrorCode.InvalidParams, `Failed to validate structured content: ${error2 instanceof Error ? error2.message : String(error2)}`);
22525
+ }
22526
+ }
22527
+ }
22528
+ return result;
22529
+ }
22530
+ isToolTask(toolName) {
22531
+ if (!this._serverCapabilities?.tasks?.requests?.tools?.call) {
22532
+ return false;
22533
+ }
22534
+ return this._cachedKnownTaskTools.has(toolName);
22535
+ }
22536
+ /**
22537
+ * Check if a tool requires task-based execution.
22538
+ * Unlike isToolTask which includes 'optional' tools, this only checks for 'required'.
22539
+ */
22540
+ isToolTaskRequired(toolName) {
22541
+ return this._cachedRequiredTaskTools.has(toolName);
22542
+ }
22543
+ /**
22544
+ * Cache validators for tool output schemas.
22545
+ * Called after listTools() to pre-compile validators for better performance.
22546
+ */
22547
+ cacheToolMetadata(tools) {
22548
+ this._cachedToolOutputValidators.clear();
22549
+ this._cachedKnownTaskTools.clear();
22550
+ this._cachedRequiredTaskTools.clear();
22551
+ for (const tool of tools) {
22552
+ if (tool.outputSchema) {
22553
+ const toolValidator = this._jsonSchemaValidator.getValidator(tool.outputSchema);
22554
+ this._cachedToolOutputValidators.set(tool.name, toolValidator);
22555
+ }
22556
+ const taskSupport = tool.execution?.taskSupport;
22557
+ if (taskSupport === "required" || taskSupport === "optional") {
22558
+ this._cachedKnownTaskTools.add(tool.name);
22559
+ }
22560
+ if (taskSupport === "required") {
22561
+ this._cachedRequiredTaskTools.add(tool.name);
22562
+ }
22563
+ }
22564
+ }
22565
+ /**
22566
+ * Get cached validator for a tool
22567
+ */
22568
+ getToolOutputValidator(toolName) {
22569
+ return this._cachedToolOutputValidators.get(toolName);
22570
+ }
22571
+ async listTools(params, options) {
22572
+ const result = await this.request({ method: "tools/list", params }, ListToolsResultSchema, options);
22573
+ this.cacheToolMetadata(result.tools);
22574
+ return result;
22575
+ }
22576
+ /**
22577
+ * Set up a single list changed handler.
22578
+ * @internal
22579
+ */
22580
+ _setupListChangedHandler(listType, notificationSchema, options, fetcher) {
22581
+ const parseResult = ListChangedOptionsBaseSchema.safeParse(options);
22582
+ if (!parseResult.success) {
22583
+ throw new Error(`Invalid ${listType} listChanged options: ${parseResult.error.message}`);
22584
+ }
22585
+ if (typeof options.onChanged !== "function") {
22586
+ throw new Error(`Invalid ${listType} listChanged options: onChanged must be a function`);
22587
+ }
22588
+ const { autoRefresh, debounceMs } = parseResult.data;
22589
+ const { onChanged } = options;
22590
+ const refresh = async () => {
22591
+ if (!autoRefresh) {
22592
+ onChanged(null, null);
22593
+ return;
22594
+ }
22595
+ try {
22596
+ const items = await fetcher();
22597
+ onChanged(null, items);
22598
+ } catch (e) {
22599
+ const error2 = e instanceof Error ? e : new Error(String(e));
22600
+ onChanged(error2, null);
22601
+ }
22602
+ };
22603
+ const handler = () => {
22604
+ if (debounceMs) {
22605
+ const existingTimer = this._listChangedDebounceTimers.get(listType);
22606
+ if (existingTimer) {
22607
+ clearTimeout(existingTimer);
22608
+ }
22609
+ const timer = setTimeout(refresh, debounceMs);
22610
+ this._listChangedDebounceTimers.set(listType, timer);
22611
+ } else {
22612
+ refresh();
22613
+ }
22614
+ };
22615
+ this.setNotificationHandler(notificationSchema, handler);
22616
+ }
22617
+ async sendRootsListChanged() {
22618
+ return this.notification({ method: "notifications/roots/list_changed" });
22619
+ }
22620
+ };
22621
+
22622
+ // node_modules/@modelcontextprotocol/sdk/dist/esm/client/stdio.js
22623
+ var import_cross_spawn = __toESM(require_cross_spawn(), 1);
22624
+ import process4 from "node:process";
22625
+ import { PassThrough } from "node:stream";
22626
+ var DEFAULT_INHERITED_ENV_VARS = process4.platform === "win32" ? [
22627
+ "APPDATA",
22628
+ "HOMEDRIVE",
22629
+ "HOMEPATH",
22630
+ "LOCALAPPDATA",
22631
+ "PATH",
22632
+ "PROCESSOR_ARCHITECTURE",
22633
+ "SYSTEMDRIVE",
22634
+ "SYSTEMROOT",
22635
+ "TEMP",
22636
+ "USERNAME",
22637
+ "USERPROFILE",
22638
+ "PROGRAMFILES"
22639
+ ] : (
22640
+ /* list inspired by the default env inheritance of sudo */
22641
+ ["HOME", "LOGNAME", "PATH", "SHELL", "TERM", "USER"]
22642
+ );
22643
+ function getDefaultEnvironment() {
22644
+ const env = {};
22645
+ for (const key of DEFAULT_INHERITED_ENV_VARS) {
22646
+ const value = process4.env[key];
22647
+ if (value === void 0) {
22648
+ continue;
22649
+ }
22650
+ if (value.startsWith("()")) {
22651
+ continue;
22652
+ }
22653
+ env[key] = value;
22654
+ }
22655
+ return env;
22656
+ }
22657
+ var StdioClientTransport = class {
22658
+ constructor(server2) {
22659
+ this._readBuffer = new ReadBuffer();
22660
+ this._stderrStream = null;
22661
+ this._serverParams = server2;
22662
+ if (server2.stderr === "pipe" || server2.stderr === "overlapped") {
22663
+ this._stderrStream = new PassThrough();
22664
+ }
22665
+ }
22666
+ /**
22667
+ * Starts the server process and prepares to communicate with it.
22668
+ */
22669
+ async start() {
22670
+ if (this._process) {
22671
+ throw new Error("StdioClientTransport already started! If using Client class, note that connect() calls start() automatically.");
22672
+ }
22673
+ return new Promise((resolve, reject) => {
22674
+ this._process = (0, import_cross_spawn.default)(this._serverParams.command, this._serverParams.args ?? [], {
22675
+ // merge default env with server env because mcp server needs some env vars
22676
+ env: {
22677
+ ...getDefaultEnvironment(),
22678
+ ...this._serverParams.env
22679
+ },
22680
+ stdio: ["pipe", "pipe", this._serverParams.stderr ?? "inherit"],
22681
+ shell: false,
22682
+ windowsHide: process4.platform === "win32",
22683
+ cwd: this._serverParams.cwd
22684
+ });
22685
+ this._process.on("error", (error2) => {
22686
+ reject(error2);
22687
+ this.onerror?.(error2);
22688
+ });
22689
+ this._process.on("spawn", () => {
22690
+ resolve();
22691
+ });
22692
+ this._process.on("close", (_code) => {
22693
+ this._process = void 0;
22694
+ this.onclose?.();
22695
+ });
22696
+ this._process.stdin?.on("error", (error2) => {
22697
+ this.onerror?.(error2);
22698
+ });
22699
+ this._process.stdout?.on("data", (chunk) => {
22700
+ this._readBuffer.append(chunk);
22701
+ this.processReadBuffer();
22702
+ });
22703
+ this._process.stdout?.on("error", (error2) => {
22704
+ this.onerror?.(error2);
22705
+ });
22706
+ if (this._stderrStream && this._process.stderr) {
22707
+ this._process.stderr.pipe(this._stderrStream);
22708
+ }
22709
+ });
22710
+ }
22711
+ /**
22712
+ * The stderr stream of the child process, if `StdioServerParameters.stderr` was set to "pipe" or "overlapped".
22713
+ *
22714
+ * If stderr piping was requested, a PassThrough stream is returned _immediately_, allowing callers to
22715
+ * attach listeners before the start method is invoked. This prevents loss of any early
22716
+ * error output emitted by the child process.
22717
+ */
22718
+ get stderr() {
22719
+ if (this._stderrStream) {
22720
+ return this._stderrStream;
22721
+ }
22722
+ return this._process?.stderr ?? null;
22723
+ }
22724
+ /**
22725
+ * The child process pid spawned by this transport.
22726
+ *
22727
+ * This is only available after the transport has been started.
22728
+ */
22729
+ get pid() {
22730
+ return this._process?.pid ?? null;
22731
+ }
22732
+ processReadBuffer() {
22733
+ while (true) {
22734
+ try {
22735
+ const message = this._readBuffer.readMessage();
22736
+ if (message === null) {
22737
+ break;
22738
+ }
22739
+ this.onmessage?.(message);
22740
+ } catch (error2) {
22741
+ this.onerror?.(error2);
22742
+ }
22743
+ }
22744
+ }
22745
+ async close() {
22746
+ if (this._process) {
22747
+ const processToClose = this._process;
22748
+ this._process = void 0;
22749
+ const closePromise = new Promise((resolve) => {
22750
+ processToClose.once("close", () => {
22751
+ resolve();
22752
+ });
22753
+ });
22754
+ try {
22755
+ processToClose.stdin?.end();
22756
+ } catch {
22757
+ }
22758
+ await Promise.race([closePromise, new Promise((resolve) => setTimeout(resolve, 2e3).unref())]);
22759
+ if (processToClose.exitCode === null) {
22760
+ try {
22761
+ processToClose.kill("SIGTERM");
22762
+ } catch {
22763
+ }
22764
+ await Promise.race([closePromise, new Promise((resolve) => setTimeout(resolve, 2e3).unref())]);
22765
+ }
22766
+ if (processToClose.exitCode === null) {
22767
+ try {
22768
+ processToClose.kill("SIGKILL");
22769
+ } catch {
22770
+ }
22771
+ }
22772
+ }
22773
+ this._readBuffer.clear();
22774
+ }
22775
+ send(message) {
22776
+ return new Promise((resolve) => {
22777
+ if (!this._process?.stdin) {
22778
+ throw new Error("Not connected");
22779
+ }
22780
+ const json = serializeMessage(message);
22781
+ if (this._process.stdin.write(json)) {
22782
+ resolve();
22783
+ } else {
22784
+ this._process.stdin.once("drain", resolve);
22785
+ }
22786
+ });
22787
+ }
22788
+ };
22789
+
22790
+ // node_modules/@modelcontextprotocol/sdk/dist/esm/shared/transport.js
22791
+ function normalizeHeaders(headers) {
22792
+ if (!headers)
22793
+ return {};
22794
+ if (headers instanceof Headers) {
22795
+ return Object.fromEntries(headers.entries());
22796
+ }
22797
+ if (Array.isArray(headers)) {
22798
+ return Object.fromEntries(headers);
22799
+ }
22800
+ return { ...headers };
22801
+ }
22802
+ function createFetchWithInit(baseFetch = fetch, baseInit) {
22803
+ if (!baseInit) {
22804
+ return baseFetch;
22805
+ }
22806
+ return async (url2, init) => {
22807
+ const mergedInit = {
22808
+ ...baseInit,
22809
+ ...init,
22810
+ // Headers need special handling - merge instead of replace
22811
+ headers: init?.headers ? { ...normalizeHeaders(baseInit.headers), ...normalizeHeaders(init.headers) } : baseInit.headers
22812
+ };
22813
+ return baseFetch(url2, mergedInit);
22814
+ };
22815
+ }
22816
+
22817
+ // node_modules/pkce-challenge/dist/index.node.js
22818
+ var crypto;
22819
+ crypto = globalThis.crypto?.webcrypto ?? // Node.js [18-16] REPL
22820
+ globalThis.crypto ?? // Node.js >18
22821
+ import("node:crypto").then((m) => m.webcrypto);
22822
+ async function getRandomValues(size) {
22823
+ return (await crypto).getRandomValues(new Uint8Array(size));
22824
+ }
22825
+ async function random(size) {
22826
+ const mask = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789-._~";
22827
+ const evenDistCutoff = Math.pow(2, 8) - Math.pow(2, 8) % mask.length;
22828
+ let result = "";
22829
+ while (result.length < size) {
22830
+ const randomBytes = await getRandomValues(size - result.length);
22831
+ for (const randomByte of randomBytes) {
22832
+ if (randomByte < evenDistCutoff) {
22833
+ result += mask[randomByte % mask.length];
22834
+ }
22835
+ }
22836
+ }
22837
+ return result;
22838
+ }
22839
+ async function generateVerifier(length) {
22840
+ return await random(length);
22841
+ }
22842
+ async function generateChallenge(code_verifier) {
22843
+ const buffer = await (await crypto).subtle.digest("SHA-256", new TextEncoder().encode(code_verifier));
22844
+ return btoa(String.fromCharCode(...new Uint8Array(buffer))).replace(/\//g, "_").replace(/\+/g, "-").replace(/=/g, "");
22845
+ }
22846
+ async function pkceChallenge(length) {
22847
+ if (!length)
22848
+ length = 43;
22849
+ if (length < 43 || length > 128) {
22850
+ throw `Expected a length between 43 and 128. Received ${length}.`;
22851
+ }
22852
+ const verifier = await generateVerifier(length);
22853
+ const challenge = await generateChallenge(verifier);
22854
+ return {
22855
+ code_verifier: verifier,
22856
+ code_challenge: challenge
22857
+ };
22858
+ }
22859
+
22860
+ // node_modules/@modelcontextprotocol/sdk/dist/esm/shared/auth.js
22861
+ var SafeUrlSchema = url().superRefine((val, ctx) => {
22862
+ if (!URL.canParse(val)) {
22863
+ ctx.addIssue({
22864
+ code: ZodIssueCode.custom,
22865
+ message: "URL must be parseable",
22866
+ fatal: true
22867
+ });
22868
+ return NEVER;
22869
+ }
22870
+ }).refine((url2) => {
22871
+ const u = new URL(url2);
22872
+ return u.protocol !== "javascript:" && u.protocol !== "data:" && u.protocol !== "vbscript:";
22873
+ }, { message: "URL cannot use javascript:, data:, or vbscript: scheme" });
22874
+ var OAuthProtectedResourceMetadataSchema = looseObject({
22875
+ resource: string2().url(),
22876
+ authorization_servers: array(SafeUrlSchema).optional(),
22877
+ jwks_uri: string2().url().optional(),
22878
+ scopes_supported: array(string2()).optional(),
22879
+ bearer_methods_supported: array(string2()).optional(),
22880
+ resource_signing_alg_values_supported: array(string2()).optional(),
22881
+ resource_name: string2().optional(),
22882
+ resource_documentation: string2().optional(),
22883
+ resource_policy_uri: string2().url().optional(),
22884
+ resource_tos_uri: string2().url().optional(),
22885
+ tls_client_certificate_bound_access_tokens: boolean2().optional(),
22886
+ authorization_details_types_supported: array(string2()).optional(),
22887
+ dpop_signing_alg_values_supported: array(string2()).optional(),
22888
+ dpop_bound_access_tokens_required: boolean2().optional()
22889
+ });
22890
+ var OAuthMetadataSchema = looseObject({
22891
+ issuer: string2(),
22892
+ authorization_endpoint: SafeUrlSchema,
22893
+ token_endpoint: SafeUrlSchema,
22894
+ registration_endpoint: SafeUrlSchema.optional(),
22895
+ scopes_supported: array(string2()).optional(),
22896
+ response_types_supported: array(string2()),
22897
+ response_modes_supported: array(string2()).optional(),
22898
+ grant_types_supported: array(string2()).optional(),
22899
+ token_endpoint_auth_methods_supported: array(string2()).optional(),
22900
+ token_endpoint_auth_signing_alg_values_supported: array(string2()).optional(),
22901
+ service_documentation: SafeUrlSchema.optional(),
22902
+ revocation_endpoint: SafeUrlSchema.optional(),
22903
+ revocation_endpoint_auth_methods_supported: array(string2()).optional(),
22904
+ revocation_endpoint_auth_signing_alg_values_supported: array(string2()).optional(),
22905
+ introspection_endpoint: string2().optional(),
22906
+ introspection_endpoint_auth_methods_supported: array(string2()).optional(),
22907
+ introspection_endpoint_auth_signing_alg_values_supported: array(string2()).optional(),
22908
+ code_challenge_methods_supported: array(string2()).optional(),
22909
+ client_id_metadata_document_supported: boolean2().optional()
22910
+ });
22911
+ var OpenIdProviderMetadataSchema = looseObject({
22912
+ issuer: string2(),
22913
+ authorization_endpoint: SafeUrlSchema,
22914
+ token_endpoint: SafeUrlSchema,
22915
+ userinfo_endpoint: SafeUrlSchema.optional(),
22916
+ jwks_uri: SafeUrlSchema,
22917
+ registration_endpoint: SafeUrlSchema.optional(),
22918
+ scopes_supported: array(string2()).optional(),
22919
+ response_types_supported: array(string2()),
22920
+ response_modes_supported: array(string2()).optional(),
22921
+ grant_types_supported: array(string2()).optional(),
22922
+ acr_values_supported: array(string2()).optional(),
22923
+ subject_types_supported: array(string2()),
22924
+ id_token_signing_alg_values_supported: array(string2()),
22925
+ id_token_encryption_alg_values_supported: array(string2()).optional(),
22926
+ id_token_encryption_enc_values_supported: array(string2()).optional(),
22927
+ userinfo_signing_alg_values_supported: array(string2()).optional(),
22928
+ userinfo_encryption_alg_values_supported: array(string2()).optional(),
22929
+ userinfo_encryption_enc_values_supported: array(string2()).optional(),
22930
+ request_object_signing_alg_values_supported: array(string2()).optional(),
22931
+ request_object_encryption_alg_values_supported: array(string2()).optional(),
22932
+ request_object_encryption_enc_values_supported: array(string2()).optional(),
22933
+ token_endpoint_auth_methods_supported: array(string2()).optional(),
22934
+ token_endpoint_auth_signing_alg_values_supported: array(string2()).optional(),
22935
+ display_values_supported: array(string2()).optional(),
22936
+ claim_types_supported: array(string2()).optional(),
22937
+ claims_supported: array(string2()).optional(),
22938
+ service_documentation: string2().optional(),
22939
+ claims_locales_supported: array(string2()).optional(),
22940
+ ui_locales_supported: array(string2()).optional(),
22941
+ claims_parameter_supported: boolean2().optional(),
22942
+ request_parameter_supported: boolean2().optional(),
22943
+ request_uri_parameter_supported: boolean2().optional(),
22944
+ require_request_uri_registration: boolean2().optional(),
22945
+ op_policy_uri: SafeUrlSchema.optional(),
22946
+ op_tos_uri: SafeUrlSchema.optional(),
22947
+ client_id_metadata_document_supported: boolean2().optional()
22948
+ });
22949
+ var OpenIdProviderDiscoveryMetadataSchema = object2({
22950
+ ...OpenIdProviderMetadataSchema.shape,
22951
+ ...OAuthMetadataSchema.pick({
22952
+ code_challenge_methods_supported: true
22953
+ }).shape
22954
+ });
22955
+ var OAuthTokensSchema = object2({
22956
+ access_token: string2(),
22957
+ id_token: string2().optional(),
22958
+ // Optional for OAuth 2.1, but necessary in OpenID Connect
22959
+ token_type: string2(),
22960
+ expires_in: coerce_exports.number().optional(),
22961
+ scope: string2().optional(),
22962
+ refresh_token: string2().optional()
22963
+ }).strip();
22964
+ var OAuthErrorResponseSchema = object2({
22965
+ error: string2(),
22966
+ error_description: string2().optional(),
22967
+ error_uri: string2().optional()
22968
+ });
22969
+ var OptionalSafeUrlSchema = SafeUrlSchema.optional().or(literal("").transform(() => void 0));
22970
+ var OAuthClientMetadataSchema = object2({
22971
+ redirect_uris: array(SafeUrlSchema),
22972
+ token_endpoint_auth_method: string2().optional(),
22973
+ grant_types: array(string2()).optional(),
22974
+ response_types: array(string2()).optional(),
22975
+ client_name: string2().optional(),
22976
+ client_uri: SafeUrlSchema.optional(),
22977
+ logo_uri: OptionalSafeUrlSchema,
22978
+ scope: string2().optional(),
22979
+ contacts: array(string2()).optional(),
22980
+ tos_uri: OptionalSafeUrlSchema,
22981
+ policy_uri: string2().optional(),
22982
+ jwks_uri: SafeUrlSchema.optional(),
22983
+ jwks: any().optional(),
22984
+ software_id: string2().optional(),
22985
+ software_version: string2().optional(),
22986
+ software_statement: string2().optional()
22987
+ }).strip();
22988
+ var OAuthClientInformationSchema = object2({
22989
+ client_id: string2(),
22990
+ client_secret: string2().optional(),
22991
+ client_id_issued_at: number2().optional(),
22992
+ client_secret_expires_at: number2().optional()
22993
+ }).strip();
22994
+ var OAuthClientInformationFullSchema = OAuthClientMetadataSchema.merge(OAuthClientInformationSchema);
22995
+ var OAuthClientRegistrationErrorSchema = object2({
22996
+ error: string2(),
22997
+ error_description: string2().optional()
22998
+ }).strip();
22999
+ var OAuthTokenRevocationRequestSchema = object2({
23000
+ token: string2(),
23001
+ token_type_hint: string2().optional()
23002
+ }).strip();
23003
+
23004
+ // node_modules/@modelcontextprotocol/sdk/dist/esm/shared/auth-utils.js
23005
+ function resourceUrlFromServerUrl(url2) {
23006
+ const resourceURL = typeof url2 === "string" ? new URL(url2) : new URL(url2.href);
23007
+ resourceURL.hash = "";
23008
+ return resourceURL;
23009
+ }
23010
+ function checkResourceAllowed({ requestedResource, configuredResource }) {
23011
+ const requested = typeof requestedResource === "string" ? new URL(requestedResource) : new URL(requestedResource.href);
23012
+ const configured = typeof configuredResource === "string" ? new URL(configuredResource) : new URL(configuredResource.href);
23013
+ if (requested.origin !== configured.origin) {
23014
+ return false;
23015
+ }
23016
+ if (requested.pathname.length < configured.pathname.length) {
23017
+ return false;
23018
+ }
23019
+ const requestedPath = requested.pathname.endsWith("/") ? requested.pathname : requested.pathname + "/";
23020
+ const configuredPath = configured.pathname.endsWith("/") ? configured.pathname : configured.pathname + "/";
23021
+ return requestedPath.startsWith(configuredPath);
23022
+ }
23023
+
23024
+ // node_modules/@modelcontextprotocol/sdk/dist/esm/server/auth/errors.js
23025
+ var OAuthError = class extends Error {
23026
+ constructor(message, errorUri) {
23027
+ super(message);
23028
+ this.errorUri = errorUri;
23029
+ this.name = this.constructor.name;
23030
+ }
23031
+ /**
23032
+ * Converts the error to a standard OAuth error response object
23033
+ */
23034
+ toResponseObject() {
23035
+ const response = {
23036
+ error: this.errorCode,
23037
+ error_description: this.message
23038
+ };
23039
+ if (this.errorUri) {
23040
+ response.error_uri = this.errorUri;
23041
+ }
23042
+ return response;
23043
+ }
23044
+ get errorCode() {
23045
+ return this.constructor.errorCode;
23046
+ }
23047
+ };
23048
+ var InvalidRequestError = class extends OAuthError {
23049
+ };
23050
+ InvalidRequestError.errorCode = "invalid_request";
23051
+ var InvalidClientError = class extends OAuthError {
23052
+ };
23053
+ InvalidClientError.errorCode = "invalid_client";
23054
+ var InvalidGrantError = class extends OAuthError {
23055
+ };
23056
+ InvalidGrantError.errorCode = "invalid_grant";
23057
+ var UnauthorizedClientError = class extends OAuthError {
23058
+ };
23059
+ UnauthorizedClientError.errorCode = "unauthorized_client";
23060
+ var UnsupportedGrantTypeError = class extends OAuthError {
23061
+ };
23062
+ UnsupportedGrantTypeError.errorCode = "unsupported_grant_type";
23063
+ var InvalidScopeError = class extends OAuthError {
23064
+ };
23065
+ InvalidScopeError.errorCode = "invalid_scope";
23066
+ var AccessDeniedError = class extends OAuthError {
23067
+ };
23068
+ AccessDeniedError.errorCode = "access_denied";
23069
+ var ServerError = class extends OAuthError {
23070
+ };
23071
+ ServerError.errorCode = "server_error";
23072
+ var TemporarilyUnavailableError = class extends OAuthError {
23073
+ };
23074
+ TemporarilyUnavailableError.errorCode = "temporarily_unavailable";
23075
+ var UnsupportedResponseTypeError = class extends OAuthError {
23076
+ };
23077
+ UnsupportedResponseTypeError.errorCode = "unsupported_response_type";
23078
+ var UnsupportedTokenTypeError = class extends OAuthError {
23079
+ };
23080
+ UnsupportedTokenTypeError.errorCode = "unsupported_token_type";
23081
+ var InvalidTokenError = class extends OAuthError {
23082
+ };
23083
+ InvalidTokenError.errorCode = "invalid_token";
23084
+ var MethodNotAllowedError = class extends OAuthError {
23085
+ };
23086
+ MethodNotAllowedError.errorCode = "method_not_allowed";
23087
+ var TooManyRequestsError = class extends OAuthError {
23088
+ };
23089
+ TooManyRequestsError.errorCode = "too_many_requests";
23090
+ var InvalidClientMetadataError = class extends OAuthError {
23091
+ };
23092
+ InvalidClientMetadataError.errorCode = "invalid_client_metadata";
23093
+ var InsufficientScopeError = class extends OAuthError {
23094
+ };
23095
+ InsufficientScopeError.errorCode = "insufficient_scope";
23096
+ var InvalidTargetError = class extends OAuthError {
23097
+ };
23098
+ InvalidTargetError.errorCode = "invalid_target";
23099
+ var OAUTH_ERRORS = {
23100
+ [InvalidRequestError.errorCode]: InvalidRequestError,
23101
+ [InvalidClientError.errorCode]: InvalidClientError,
23102
+ [InvalidGrantError.errorCode]: InvalidGrantError,
23103
+ [UnauthorizedClientError.errorCode]: UnauthorizedClientError,
23104
+ [UnsupportedGrantTypeError.errorCode]: UnsupportedGrantTypeError,
23105
+ [InvalidScopeError.errorCode]: InvalidScopeError,
23106
+ [AccessDeniedError.errorCode]: AccessDeniedError,
23107
+ [ServerError.errorCode]: ServerError,
23108
+ [TemporarilyUnavailableError.errorCode]: TemporarilyUnavailableError,
23109
+ [UnsupportedResponseTypeError.errorCode]: UnsupportedResponseTypeError,
23110
+ [UnsupportedTokenTypeError.errorCode]: UnsupportedTokenTypeError,
23111
+ [InvalidTokenError.errorCode]: InvalidTokenError,
23112
+ [MethodNotAllowedError.errorCode]: MethodNotAllowedError,
23113
+ [TooManyRequestsError.errorCode]: TooManyRequestsError,
23114
+ [InvalidClientMetadataError.errorCode]: InvalidClientMetadataError,
23115
+ [InsufficientScopeError.errorCode]: InsufficientScopeError,
23116
+ [InvalidTargetError.errorCode]: InvalidTargetError
23117
+ };
23118
+
23119
+ // node_modules/@modelcontextprotocol/sdk/dist/esm/client/auth.js
23120
+ var UnauthorizedError = class extends Error {
23121
+ constructor(message) {
23122
+ super(message ?? "Unauthorized");
23123
+ }
23124
+ };
23125
+ function isClientAuthMethod(method) {
23126
+ return ["client_secret_basic", "client_secret_post", "none"].includes(method);
23127
+ }
23128
+ var AUTHORIZATION_CODE_RESPONSE_TYPE = "code";
23129
+ var AUTHORIZATION_CODE_CHALLENGE_METHOD = "S256";
23130
+ function selectClientAuthMethod(clientInformation, supportedMethods) {
23131
+ const hasClientSecret = clientInformation.client_secret !== void 0;
23132
+ if ("token_endpoint_auth_method" in clientInformation && clientInformation.token_endpoint_auth_method && isClientAuthMethod(clientInformation.token_endpoint_auth_method) && (supportedMethods.length === 0 || supportedMethods.includes(clientInformation.token_endpoint_auth_method))) {
23133
+ return clientInformation.token_endpoint_auth_method;
23134
+ }
23135
+ if (supportedMethods.length === 0) {
23136
+ return hasClientSecret ? "client_secret_basic" : "none";
23137
+ }
23138
+ if (hasClientSecret && supportedMethods.includes("client_secret_basic")) {
23139
+ return "client_secret_basic";
23140
+ }
23141
+ if (hasClientSecret && supportedMethods.includes("client_secret_post")) {
23142
+ return "client_secret_post";
23143
+ }
23144
+ if (supportedMethods.includes("none")) {
23145
+ return "none";
23146
+ }
23147
+ return hasClientSecret ? "client_secret_post" : "none";
23148
+ }
23149
+ function applyClientAuthentication(method, clientInformation, headers, params) {
23150
+ const { client_id, client_secret } = clientInformation;
23151
+ switch (method) {
23152
+ case "client_secret_basic":
23153
+ applyBasicAuth(client_id, client_secret, headers);
23154
+ return;
23155
+ case "client_secret_post":
23156
+ applyPostAuth(client_id, client_secret, params);
23157
+ return;
23158
+ case "none":
23159
+ applyPublicAuth(client_id, params);
23160
+ return;
23161
+ default:
23162
+ throw new Error(`Unsupported client authentication method: ${method}`);
23163
+ }
23164
+ }
23165
+ function applyBasicAuth(clientId, clientSecret, headers) {
23166
+ if (!clientSecret) {
23167
+ throw new Error("client_secret_basic authentication requires a client_secret");
23168
+ }
23169
+ const credentials = btoa(`${clientId}:${clientSecret}`);
23170
+ headers.set("Authorization", `Basic ${credentials}`);
23171
+ }
23172
+ function applyPostAuth(clientId, clientSecret, params) {
23173
+ params.set("client_id", clientId);
23174
+ if (clientSecret) {
23175
+ params.set("client_secret", clientSecret);
23176
+ }
23177
+ }
23178
+ function applyPublicAuth(clientId, params) {
23179
+ params.set("client_id", clientId);
23180
+ }
23181
+ async function parseErrorResponse(input) {
23182
+ const statusCode = input instanceof Response ? input.status : void 0;
23183
+ const body = input instanceof Response ? await input.text() : input;
23184
+ try {
23185
+ const result = OAuthErrorResponseSchema.parse(JSON.parse(body));
23186
+ const { error: error2, error_description, error_uri } = result;
23187
+ const errorClass = OAUTH_ERRORS[error2] || ServerError;
23188
+ return new errorClass(error_description || "", error_uri);
23189
+ } catch (error2) {
23190
+ const errorMessage = `${statusCode ? `HTTP ${statusCode}: ` : ""}Invalid OAuth error response: ${error2}. Raw body: ${body}`;
23191
+ return new ServerError(errorMessage);
23192
+ }
23193
+ }
23194
+ async function auth(provider, options) {
23195
+ try {
23196
+ return await authInternal(provider, options);
23197
+ } catch (error2) {
23198
+ if (error2 instanceof InvalidClientError || error2 instanceof UnauthorizedClientError) {
23199
+ await provider.invalidateCredentials?.("all");
23200
+ return await authInternal(provider, options);
23201
+ } else if (error2 instanceof InvalidGrantError) {
23202
+ await provider.invalidateCredentials?.("tokens");
23203
+ return await authInternal(provider, options);
23204
+ }
23205
+ throw error2;
23206
+ }
23207
+ }
23208
+ async function authInternal(provider, { serverUrl, authorizationCode, scope, resourceMetadataUrl, fetchFn }) {
23209
+ const cachedState = await provider.discoveryState?.();
23210
+ let resourceMetadata;
23211
+ let authorizationServerUrl;
23212
+ let metadata;
23213
+ let effectiveResourceMetadataUrl = resourceMetadataUrl;
23214
+ if (!effectiveResourceMetadataUrl && cachedState?.resourceMetadataUrl) {
23215
+ effectiveResourceMetadataUrl = new URL(cachedState.resourceMetadataUrl);
23216
+ }
23217
+ if (cachedState?.authorizationServerUrl) {
23218
+ authorizationServerUrl = cachedState.authorizationServerUrl;
23219
+ resourceMetadata = cachedState.resourceMetadata;
23220
+ metadata = cachedState.authorizationServerMetadata ?? await discoverAuthorizationServerMetadata(authorizationServerUrl, { fetchFn });
23221
+ if (!resourceMetadata) {
23222
+ try {
23223
+ resourceMetadata = await discoverOAuthProtectedResourceMetadata(serverUrl, { resourceMetadataUrl: effectiveResourceMetadataUrl }, fetchFn);
23224
+ } catch {
23225
+ }
23226
+ }
23227
+ if (metadata !== cachedState.authorizationServerMetadata || resourceMetadata !== cachedState.resourceMetadata) {
23228
+ await provider.saveDiscoveryState?.({
23229
+ authorizationServerUrl: String(authorizationServerUrl),
23230
+ resourceMetadataUrl: effectiveResourceMetadataUrl?.toString(),
23231
+ resourceMetadata,
23232
+ authorizationServerMetadata: metadata
23233
+ });
23234
+ }
23235
+ } else {
23236
+ const serverInfo = await discoverOAuthServerInfo(serverUrl, { resourceMetadataUrl: effectiveResourceMetadataUrl, fetchFn });
23237
+ authorizationServerUrl = serverInfo.authorizationServerUrl;
23238
+ metadata = serverInfo.authorizationServerMetadata;
23239
+ resourceMetadata = serverInfo.resourceMetadata;
23240
+ await provider.saveDiscoveryState?.({
23241
+ authorizationServerUrl: String(authorizationServerUrl),
23242
+ resourceMetadataUrl: effectiveResourceMetadataUrl?.toString(),
23243
+ resourceMetadata,
23244
+ authorizationServerMetadata: metadata
23245
+ });
23246
+ }
23247
+ const resource = await selectResourceURL(serverUrl, provider, resourceMetadata);
23248
+ const resolvedScope = scope || resourceMetadata?.scopes_supported?.join(" ") || provider.clientMetadata.scope;
23249
+ let clientInformation = await Promise.resolve(provider.clientInformation());
23250
+ if (!clientInformation) {
23251
+ if (authorizationCode !== void 0) {
23252
+ throw new Error("Existing OAuth client information is required when exchanging an authorization code");
23253
+ }
23254
+ const supportsUrlBasedClientId = metadata?.client_id_metadata_document_supported === true;
23255
+ const clientMetadataUrl = provider.clientMetadataUrl;
23256
+ if (clientMetadataUrl && !isHttpsUrl(clientMetadataUrl)) {
23257
+ throw new InvalidClientMetadataError(`clientMetadataUrl must be a valid HTTPS URL with a non-root pathname, got: ${clientMetadataUrl}`);
23258
+ }
23259
+ const shouldUseUrlBasedClientId = supportsUrlBasedClientId && clientMetadataUrl;
23260
+ if (shouldUseUrlBasedClientId) {
23261
+ clientInformation = {
23262
+ client_id: clientMetadataUrl
23263
+ };
23264
+ await provider.saveClientInformation?.(clientInformation);
23265
+ } else {
23266
+ if (!provider.saveClientInformation) {
23267
+ throw new Error("OAuth client information must be saveable for dynamic registration");
23268
+ }
23269
+ const fullInformation = await registerClient(authorizationServerUrl, {
23270
+ metadata,
23271
+ clientMetadata: provider.clientMetadata,
23272
+ scope: resolvedScope,
23273
+ fetchFn
23274
+ });
23275
+ await provider.saveClientInformation(fullInformation);
23276
+ clientInformation = fullInformation;
23277
+ }
23278
+ }
23279
+ const nonInteractiveFlow = !provider.redirectUrl;
23280
+ if (authorizationCode !== void 0 || nonInteractiveFlow) {
23281
+ const tokens2 = await fetchToken(provider, authorizationServerUrl, {
23282
+ metadata,
23283
+ resource,
23284
+ authorizationCode,
23285
+ fetchFn
23286
+ });
23287
+ await provider.saveTokens(tokens2);
23288
+ return "AUTHORIZED";
23289
+ }
23290
+ const tokens = await provider.tokens();
23291
+ if (tokens?.refresh_token) {
23292
+ try {
23293
+ const newTokens = await refreshAuthorization(authorizationServerUrl, {
23294
+ metadata,
23295
+ clientInformation,
23296
+ refreshToken: tokens.refresh_token,
23297
+ resource,
23298
+ addClientAuthentication: provider.addClientAuthentication,
23299
+ fetchFn
23300
+ });
23301
+ await provider.saveTokens(newTokens);
23302
+ return "AUTHORIZED";
23303
+ } catch (error2) {
23304
+ if (!(error2 instanceof OAuthError) || error2 instanceof ServerError) {
23305
+ } else {
23306
+ throw error2;
23307
+ }
23308
+ }
23309
+ }
23310
+ const state = provider.state ? await provider.state() : void 0;
23311
+ const { authorizationUrl, codeVerifier } = await startAuthorization(authorizationServerUrl, {
23312
+ metadata,
23313
+ clientInformation,
23314
+ state,
23315
+ redirectUrl: provider.redirectUrl,
23316
+ scope: resolvedScope,
23317
+ resource
23318
+ });
23319
+ await provider.saveCodeVerifier(codeVerifier);
23320
+ await provider.redirectToAuthorization(authorizationUrl);
23321
+ return "REDIRECT";
23322
+ }
23323
+ function isHttpsUrl(value) {
23324
+ if (!value)
23325
+ return false;
23326
+ try {
23327
+ const url2 = new URL(value);
23328
+ return url2.protocol === "https:" && url2.pathname !== "/";
23329
+ } catch {
23330
+ return false;
23331
+ }
23332
+ }
23333
+ async function selectResourceURL(serverUrl, provider, resourceMetadata) {
23334
+ const defaultResource = resourceUrlFromServerUrl(serverUrl);
23335
+ if (provider.validateResourceURL) {
23336
+ return await provider.validateResourceURL(defaultResource, resourceMetadata?.resource);
23337
+ }
23338
+ if (!resourceMetadata) {
23339
+ return void 0;
23340
+ }
23341
+ if (!checkResourceAllowed({ requestedResource: defaultResource, configuredResource: resourceMetadata.resource })) {
23342
+ throw new Error(`Protected resource ${resourceMetadata.resource} does not match expected ${defaultResource} (or origin)`);
23343
+ }
23344
+ return new URL(resourceMetadata.resource);
23345
+ }
23346
+ function extractWWWAuthenticateParams(res) {
23347
+ const authenticateHeader = res.headers.get("WWW-Authenticate");
23348
+ if (!authenticateHeader) {
23349
+ return {};
23350
+ }
23351
+ const [type, scheme] = authenticateHeader.split(" ");
23352
+ if (type.toLowerCase() !== "bearer" || !scheme) {
23353
+ return {};
23354
+ }
23355
+ const resourceMetadataMatch = extractFieldFromWwwAuth(res, "resource_metadata") || void 0;
23356
+ let resourceMetadataUrl;
23357
+ if (resourceMetadataMatch) {
23358
+ try {
23359
+ resourceMetadataUrl = new URL(resourceMetadataMatch);
23360
+ } catch {
23361
+ }
23362
+ }
23363
+ const scope = extractFieldFromWwwAuth(res, "scope") || void 0;
23364
+ const error2 = extractFieldFromWwwAuth(res, "error") || void 0;
23365
+ return {
23366
+ resourceMetadataUrl,
23367
+ scope,
23368
+ error: error2
23369
+ };
23370
+ }
23371
+ function extractFieldFromWwwAuth(response, fieldName) {
23372
+ const wwwAuthHeader = response.headers.get("WWW-Authenticate");
23373
+ if (!wwwAuthHeader) {
23374
+ return null;
23375
+ }
23376
+ const pattern = new RegExp(`${fieldName}=(?:"([^"]+)"|([^\\s,]+))`);
23377
+ const match = wwwAuthHeader.match(pattern);
23378
+ if (match) {
23379
+ return match[1] || match[2];
23380
+ }
23381
+ return null;
23382
+ }
23383
+ async function discoverOAuthProtectedResourceMetadata(serverUrl, opts, fetchFn = fetch) {
23384
+ const response = await discoverMetadataWithFallback(serverUrl, "oauth-protected-resource", fetchFn, {
23385
+ protocolVersion: opts?.protocolVersion,
23386
+ metadataUrl: opts?.resourceMetadataUrl
23387
+ });
23388
+ if (!response || response.status === 404) {
23389
+ await response?.body?.cancel();
23390
+ throw new Error(`Resource server does not implement OAuth 2.0 Protected Resource Metadata.`);
23391
+ }
23392
+ if (!response.ok) {
23393
+ await response.body?.cancel();
23394
+ throw new Error(`HTTP ${response.status} trying to load well-known OAuth protected resource metadata.`);
23395
+ }
23396
+ return OAuthProtectedResourceMetadataSchema.parse(await response.json());
23397
+ }
23398
+ async function fetchWithCorsRetry(url2, headers, fetchFn = fetch) {
23399
+ try {
23400
+ return await fetchFn(url2, { headers });
23401
+ } catch (error2) {
23402
+ if (error2 instanceof TypeError) {
23403
+ if (headers) {
23404
+ return fetchWithCorsRetry(url2, void 0, fetchFn);
23405
+ } else {
23406
+ return void 0;
23407
+ }
23408
+ }
23409
+ throw error2;
23410
+ }
23411
+ }
23412
+ function buildWellKnownPath(wellKnownPrefix, pathname = "", options = {}) {
23413
+ if (pathname.endsWith("/")) {
23414
+ pathname = pathname.slice(0, -1);
23415
+ }
23416
+ return options.prependPathname ? `${pathname}/.well-known/${wellKnownPrefix}` : `/.well-known/${wellKnownPrefix}${pathname}`;
23417
+ }
23418
+ async function tryMetadataDiscovery(url2, protocolVersion, fetchFn = fetch) {
23419
+ const headers = {
23420
+ "MCP-Protocol-Version": protocolVersion
23421
+ };
23422
+ return await fetchWithCorsRetry(url2, headers, fetchFn);
23423
+ }
23424
+ function shouldAttemptFallback(response, pathname) {
23425
+ return !response || response.status >= 400 && response.status < 500 && pathname !== "/";
23426
+ }
23427
+ async function discoverMetadataWithFallback(serverUrl, wellKnownType, fetchFn, opts) {
23428
+ const issuer = new URL(serverUrl);
23429
+ const protocolVersion = opts?.protocolVersion ?? LATEST_PROTOCOL_VERSION;
23430
+ let url2;
23431
+ if (opts?.metadataUrl) {
23432
+ url2 = new URL(opts.metadataUrl);
23433
+ } else {
23434
+ const wellKnownPath = buildWellKnownPath(wellKnownType, issuer.pathname);
23435
+ url2 = new URL(wellKnownPath, opts?.metadataServerUrl ?? issuer);
23436
+ url2.search = issuer.search;
23437
+ }
23438
+ let response = await tryMetadataDiscovery(url2, protocolVersion, fetchFn);
23439
+ if (!opts?.metadataUrl && shouldAttemptFallback(response, issuer.pathname)) {
23440
+ const rootUrl = new URL(`/.well-known/${wellKnownType}`, issuer);
23441
+ response = await tryMetadataDiscovery(rootUrl, protocolVersion, fetchFn);
23442
+ }
23443
+ return response;
23444
+ }
23445
+ function buildDiscoveryUrls(authorizationServerUrl) {
23446
+ const url2 = typeof authorizationServerUrl === "string" ? new URL(authorizationServerUrl) : authorizationServerUrl;
23447
+ const hasPath = url2.pathname !== "/";
23448
+ const urlsToTry = [];
23449
+ if (!hasPath) {
23450
+ urlsToTry.push({
23451
+ url: new URL("/.well-known/oauth-authorization-server", url2.origin),
23452
+ type: "oauth"
23453
+ });
23454
+ urlsToTry.push({
23455
+ url: new URL(`/.well-known/openid-configuration`, url2.origin),
23456
+ type: "oidc"
23457
+ });
23458
+ return urlsToTry;
23459
+ }
23460
+ let pathname = url2.pathname;
23461
+ if (pathname.endsWith("/")) {
23462
+ pathname = pathname.slice(0, -1);
23463
+ }
23464
+ urlsToTry.push({
23465
+ url: new URL(`/.well-known/oauth-authorization-server${pathname}`, url2.origin),
23466
+ type: "oauth"
23467
+ });
23468
+ urlsToTry.push({
23469
+ url: new URL(`/.well-known/openid-configuration${pathname}`, url2.origin),
23470
+ type: "oidc"
23471
+ });
23472
+ urlsToTry.push({
23473
+ url: new URL(`${pathname}/.well-known/openid-configuration`, url2.origin),
23474
+ type: "oidc"
23475
+ });
23476
+ return urlsToTry;
23477
+ }
23478
+ async function discoverAuthorizationServerMetadata(authorizationServerUrl, { fetchFn = fetch, protocolVersion = LATEST_PROTOCOL_VERSION } = {}) {
23479
+ const headers = {
23480
+ "MCP-Protocol-Version": protocolVersion,
23481
+ Accept: "application/json"
23482
+ };
23483
+ const urlsToTry = buildDiscoveryUrls(authorizationServerUrl);
23484
+ for (const { url: endpointUrl, type } of urlsToTry) {
23485
+ const response = await fetchWithCorsRetry(endpointUrl, headers, fetchFn);
23486
+ if (!response) {
23487
+ continue;
23488
+ }
23489
+ if (!response.ok) {
23490
+ await response.body?.cancel();
23491
+ if (response.status >= 400 && response.status < 500) {
23492
+ continue;
23493
+ }
23494
+ throw new Error(`HTTP ${response.status} trying to load ${type === "oauth" ? "OAuth" : "OpenID provider"} metadata from ${endpointUrl}`);
23495
+ }
23496
+ if (type === "oauth") {
23497
+ return OAuthMetadataSchema.parse(await response.json());
23498
+ } else {
23499
+ return OpenIdProviderDiscoveryMetadataSchema.parse(await response.json());
23500
+ }
23501
+ }
23502
+ return void 0;
23503
+ }
23504
+ async function discoverOAuthServerInfo(serverUrl, opts) {
23505
+ let resourceMetadata;
23506
+ let authorizationServerUrl;
23507
+ try {
23508
+ resourceMetadata = await discoverOAuthProtectedResourceMetadata(serverUrl, { resourceMetadataUrl: opts?.resourceMetadataUrl }, opts?.fetchFn);
23509
+ if (resourceMetadata.authorization_servers && resourceMetadata.authorization_servers.length > 0) {
23510
+ authorizationServerUrl = resourceMetadata.authorization_servers[0];
23511
+ }
23512
+ } catch {
23513
+ }
23514
+ if (!authorizationServerUrl) {
23515
+ authorizationServerUrl = String(new URL("/", serverUrl));
23516
+ }
23517
+ const authorizationServerMetadata = await discoverAuthorizationServerMetadata(authorizationServerUrl, { fetchFn: opts?.fetchFn });
23518
+ return {
23519
+ authorizationServerUrl,
23520
+ authorizationServerMetadata,
23521
+ resourceMetadata
23522
+ };
23523
+ }
23524
+ async function startAuthorization(authorizationServerUrl, { metadata, clientInformation, redirectUrl, scope, state, resource }) {
23525
+ let authorizationUrl;
23526
+ if (metadata) {
23527
+ authorizationUrl = new URL(metadata.authorization_endpoint);
23528
+ if (!metadata.response_types_supported.includes(AUTHORIZATION_CODE_RESPONSE_TYPE)) {
23529
+ throw new Error(`Incompatible auth server: does not support response type ${AUTHORIZATION_CODE_RESPONSE_TYPE}`);
23530
+ }
23531
+ if (metadata.code_challenge_methods_supported && !metadata.code_challenge_methods_supported.includes(AUTHORIZATION_CODE_CHALLENGE_METHOD)) {
23532
+ throw new Error(`Incompatible auth server: does not support code challenge method ${AUTHORIZATION_CODE_CHALLENGE_METHOD}`);
23533
+ }
23534
+ } else {
23535
+ authorizationUrl = new URL("/authorize", authorizationServerUrl);
23536
+ }
23537
+ const challenge = await pkceChallenge();
23538
+ const codeVerifier = challenge.code_verifier;
23539
+ const codeChallenge = challenge.code_challenge;
23540
+ authorizationUrl.searchParams.set("response_type", AUTHORIZATION_CODE_RESPONSE_TYPE);
23541
+ authorizationUrl.searchParams.set("client_id", clientInformation.client_id);
23542
+ authorizationUrl.searchParams.set("code_challenge", codeChallenge);
23543
+ authorizationUrl.searchParams.set("code_challenge_method", AUTHORIZATION_CODE_CHALLENGE_METHOD);
23544
+ authorizationUrl.searchParams.set("redirect_uri", String(redirectUrl));
23545
+ if (state) {
23546
+ authorizationUrl.searchParams.set("state", state);
23547
+ }
23548
+ if (scope) {
23549
+ authorizationUrl.searchParams.set("scope", scope);
23550
+ }
23551
+ if (scope?.includes("offline_access")) {
23552
+ authorizationUrl.searchParams.append("prompt", "consent");
23553
+ }
23554
+ if (resource) {
23555
+ authorizationUrl.searchParams.set("resource", resource.href);
23556
+ }
23557
+ return { authorizationUrl, codeVerifier };
23558
+ }
23559
+ function prepareAuthorizationCodeRequest(authorizationCode, codeVerifier, redirectUri) {
23560
+ return new URLSearchParams({
23561
+ grant_type: "authorization_code",
23562
+ code: authorizationCode,
23563
+ code_verifier: codeVerifier,
23564
+ redirect_uri: String(redirectUri)
23565
+ });
23566
+ }
23567
+ async function executeTokenRequest(authorizationServerUrl, { metadata, tokenRequestParams, clientInformation, addClientAuthentication, resource, fetchFn }) {
23568
+ const tokenUrl = metadata?.token_endpoint ? new URL(metadata.token_endpoint) : new URL("/token", authorizationServerUrl);
23569
+ const headers = new Headers({
23570
+ "Content-Type": "application/x-www-form-urlencoded",
23571
+ Accept: "application/json"
23572
+ });
23573
+ if (resource) {
23574
+ tokenRequestParams.set("resource", resource.href);
23575
+ }
23576
+ if (addClientAuthentication) {
23577
+ await addClientAuthentication(headers, tokenRequestParams, tokenUrl, metadata);
23578
+ } else if (clientInformation) {
23579
+ const supportedMethods = metadata?.token_endpoint_auth_methods_supported ?? [];
23580
+ const authMethod = selectClientAuthMethod(clientInformation, supportedMethods);
23581
+ applyClientAuthentication(authMethod, clientInformation, headers, tokenRequestParams);
23582
+ }
23583
+ const response = await (fetchFn ?? fetch)(tokenUrl, {
23584
+ method: "POST",
23585
+ headers,
23586
+ body: tokenRequestParams
23587
+ });
23588
+ if (!response.ok) {
23589
+ throw await parseErrorResponse(response);
23590
+ }
23591
+ return OAuthTokensSchema.parse(await response.json());
23592
+ }
23593
+ async function refreshAuthorization(authorizationServerUrl, { metadata, clientInformation, refreshToken, resource, addClientAuthentication, fetchFn }) {
23594
+ const tokenRequestParams = new URLSearchParams({
23595
+ grant_type: "refresh_token",
23596
+ refresh_token: refreshToken
23597
+ });
23598
+ const tokens = await executeTokenRequest(authorizationServerUrl, {
23599
+ metadata,
23600
+ tokenRequestParams,
23601
+ clientInformation,
23602
+ addClientAuthentication,
23603
+ resource,
23604
+ fetchFn
23605
+ });
23606
+ return { refresh_token: refreshToken, ...tokens };
23607
+ }
23608
+ async function fetchToken(provider, authorizationServerUrl, { metadata, resource, authorizationCode, fetchFn } = {}) {
23609
+ const scope = provider.clientMetadata.scope;
23610
+ let tokenRequestParams;
23611
+ if (provider.prepareTokenRequest) {
23612
+ tokenRequestParams = await provider.prepareTokenRequest(scope);
23613
+ }
23614
+ if (!tokenRequestParams) {
23615
+ if (!authorizationCode) {
23616
+ throw new Error("Either provider.prepareTokenRequest() or authorizationCode is required");
23617
+ }
23618
+ if (!provider.redirectUrl) {
23619
+ throw new Error("redirectUrl is required for authorization_code flow");
23620
+ }
23621
+ const codeVerifier = await provider.codeVerifier();
23622
+ tokenRequestParams = prepareAuthorizationCodeRequest(authorizationCode, codeVerifier, provider.redirectUrl);
23623
+ }
23624
+ const clientInformation = await provider.clientInformation();
23625
+ return executeTokenRequest(authorizationServerUrl, {
23626
+ metadata,
23627
+ tokenRequestParams,
23628
+ clientInformation: clientInformation ?? void 0,
23629
+ addClientAuthentication: provider.addClientAuthentication,
23630
+ resource,
23631
+ fetchFn
23632
+ });
23633
+ }
23634
+ async function registerClient(authorizationServerUrl, { metadata, clientMetadata, scope, fetchFn }) {
23635
+ let registrationUrl;
23636
+ if (metadata) {
23637
+ if (!metadata.registration_endpoint) {
23638
+ throw new Error("Incompatible auth server: does not support dynamic client registration");
23639
+ }
23640
+ registrationUrl = new URL(metadata.registration_endpoint);
23641
+ } else {
23642
+ registrationUrl = new URL("/register", authorizationServerUrl);
23643
+ }
23644
+ const response = await (fetchFn ?? fetch)(registrationUrl, {
23645
+ method: "POST",
23646
+ headers: {
23647
+ "Content-Type": "application/json"
23648
+ },
23649
+ body: JSON.stringify({
23650
+ ...clientMetadata,
23651
+ ...scope !== void 0 ? { scope } : {}
23652
+ })
23653
+ });
23654
+ if (!response.ok) {
23655
+ throw await parseErrorResponse(response);
23656
+ }
23657
+ return OAuthClientInformationFullSchema.parse(await response.json());
23658
+ }
23659
+
23660
+ // node_modules/eventsource-parser/dist/index.js
23661
+ var ParseError = class extends Error {
23662
+ constructor(message, options) {
23663
+ super(message), this.name = "ParseError", this.type = options.type, this.field = options.field, this.value = options.value, this.line = options.line;
23664
+ }
23665
+ };
23666
+ var LF = 10;
23667
+ var CR = 13;
23668
+ var SPACE = 32;
23669
+ function noop(_arg) {
23670
+ }
23671
+ function createParser(config2) {
23672
+ if (typeof config2 == "function")
23673
+ throw new TypeError(
23674
+ "`config` must be an object, got a function instead. Did you mean `createParser({onEvent: fn})`?"
23675
+ );
23676
+ const { onEvent = noop, onError = noop, onRetry = noop, onComment, maxBufferSize } = config2, pendingFragments = [];
23677
+ let pendingFragmentsLength = 0, isFirstChunk = true, id, data = "", dataLines = 0, eventType, terminated = false;
23678
+ function feed(chunk) {
23679
+ if (terminated)
23680
+ throw new Error(
23681
+ "Cannot feed parser: it was terminated after exceeding the configured max buffer size. Call `reset()` to resume parsing."
23682
+ );
23683
+ if (isFirstChunk && (isFirstChunk = false, chunk.charCodeAt(0) === 239 && chunk.charCodeAt(1) === 187 && chunk.charCodeAt(2) === 191 && (chunk = chunk.slice(3))), pendingFragments.length === 0) {
23684
+ const trailing2 = processLines(chunk);
23685
+ trailing2 !== "" && (pendingFragments.push(trailing2), pendingFragmentsLength = trailing2.length), checkBufferSize();
23686
+ return;
23687
+ }
23688
+ if (chunk.indexOf(`
23689
+ `) === -1 && chunk.indexOf("\r") === -1) {
23690
+ pendingFragments.push(chunk), pendingFragmentsLength += chunk.length, checkBufferSize();
23691
+ return;
23692
+ }
23693
+ pendingFragments.push(chunk);
23694
+ const input = pendingFragments.join("");
23695
+ pendingFragments.length = 0, pendingFragmentsLength = 0;
23696
+ const trailing = processLines(input);
23697
+ trailing !== "" && (pendingFragments.push(trailing), pendingFragmentsLength = trailing.length), checkBufferSize();
23698
+ }
23699
+ function checkBufferSize() {
23700
+ maxBufferSize !== void 0 && (pendingFragmentsLength + data.length <= maxBufferSize || (terminated = true, pendingFragments.length = 0, pendingFragmentsLength = 0, id = void 0, data = "", dataLines = 0, eventType = void 0, onError(
23701
+ new ParseError(`Buffered data exceeded max buffer size of ${maxBufferSize} characters`, {
23702
+ type: "max-buffer-size-exceeded"
23703
+ })
23704
+ )));
23705
+ }
23706
+ function processLines(chunk) {
23707
+ let searchIndex = 0;
23708
+ if (chunk.indexOf("\r") === -1) {
23709
+ let lfIndex = chunk.indexOf(`
23710
+ `, searchIndex);
23711
+ for (; lfIndex !== -1; ) {
23712
+ if (searchIndex === lfIndex) {
23713
+ dataLines > 0 && onEvent({ id, event: eventType, data }), id = void 0, data = "", dataLines = 0, eventType = void 0, searchIndex = lfIndex + 1, lfIndex = chunk.indexOf(`
23714
+ `, searchIndex);
23715
+ continue;
23716
+ }
23717
+ const firstCharCode = chunk.charCodeAt(searchIndex);
23718
+ if (isDataPrefix(chunk, searchIndex, firstCharCode)) {
23719
+ const valueStart = chunk.charCodeAt(searchIndex + 5) === SPACE ? searchIndex + 6 : searchIndex + 5, value = chunk.slice(valueStart, lfIndex);
23720
+ if (dataLines === 0 && chunk.charCodeAt(lfIndex + 1) === LF) {
23721
+ onEvent({ id, event: eventType, data: value }), id = void 0, data = "", eventType = void 0, searchIndex = lfIndex + 2, lfIndex = chunk.indexOf(`
23722
+ `, searchIndex);
23723
+ continue;
23724
+ }
23725
+ data = dataLines === 0 ? value : `${data}
23726
+ ${value}`, dataLines++;
23727
+ } else isEventPrefix(chunk, searchIndex, firstCharCode) ? eventType = chunk.slice(
23728
+ chunk.charCodeAt(searchIndex + 6) === SPACE ? searchIndex + 7 : searchIndex + 6,
23729
+ lfIndex
23730
+ ) || void 0 : parseLine(chunk, searchIndex, lfIndex);
23731
+ searchIndex = lfIndex + 1, lfIndex = chunk.indexOf(`
23732
+ `, searchIndex);
23733
+ }
23734
+ return chunk.slice(searchIndex);
23735
+ }
23736
+ for (; searchIndex < chunk.length; ) {
23737
+ const crIndex = chunk.indexOf("\r", searchIndex), lfIndex = chunk.indexOf(`
23738
+ `, searchIndex);
23739
+ let lineEnd = -1;
23740
+ if (crIndex !== -1 && lfIndex !== -1 ? lineEnd = crIndex < lfIndex ? crIndex : lfIndex : crIndex !== -1 ? crIndex === chunk.length - 1 ? lineEnd = -1 : lineEnd = crIndex : lfIndex !== -1 && (lineEnd = lfIndex), lineEnd === -1)
23741
+ break;
23742
+ parseLine(chunk, searchIndex, lineEnd), searchIndex = lineEnd + 1, chunk.charCodeAt(searchIndex - 1) === CR && chunk.charCodeAt(searchIndex) === LF && searchIndex++;
23743
+ }
23744
+ return chunk.slice(searchIndex);
23745
+ }
23746
+ function parseLine(chunk, start, end) {
23747
+ if (start === end) {
23748
+ dispatchEvent();
23749
+ return;
23750
+ }
23751
+ const firstCharCode = chunk.charCodeAt(start);
23752
+ if (isDataPrefix(chunk, start, firstCharCode)) {
23753
+ const valueStart = chunk.charCodeAt(start + 5) === SPACE ? start + 6 : start + 5, value2 = chunk.slice(valueStart, end);
23754
+ data = dataLines === 0 ? value2 : `${data}
23755
+ ${value2}`, dataLines++;
23756
+ return;
23757
+ }
23758
+ if (isEventPrefix(chunk, start, firstCharCode)) {
23759
+ eventType = chunk.slice(chunk.charCodeAt(start + 6) === SPACE ? start + 7 : start + 6, end) || void 0;
23760
+ return;
23761
+ }
23762
+ if (firstCharCode === 105 && chunk.charCodeAt(start + 1) === 100 && chunk.charCodeAt(start + 2) === 58) {
23763
+ const value2 = chunk.slice(chunk.charCodeAt(start + 3) === SPACE ? start + 4 : start + 3, end);
23764
+ id = value2.includes("\0") ? void 0 : value2;
23765
+ return;
23766
+ }
23767
+ if (firstCharCode === 58) {
23768
+ if (onComment) {
23769
+ const line2 = chunk.slice(start, end);
23770
+ onComment(line2.slice(chunk.charCodeAt(start + 1) === SPACE ? 2 : 1));
23771
+ }
23772
+ return;
23773
+ }
23774
+ const line = chunk.slice(start, end), fieldSeparatorIndex = line.indexOf(":");
23775
+ if (fieldSeparatorIndex === -1) {
23776
+ processField(line, "", line);
23777
+ return;
23778
+ }
23779
+ const field = line.slice(0, fieldSeparatorIndex), offset = line.charCodeAt(fieldSeparatorIndex + 1) === SPACE ? 2 : 1, value = line.slice(fieldSeparatorIndex + offset);
23780
+ processField(field, value, line);
23781
+ }
23782
+ function processField(field, value, line) {
23783
+ switch (field) {
23784
+ case "event":
23785
+ eventType = value || void 0;
23786
+ break;
23787
+ case "data":
23788
+ data = dataLines === 0 ? value : `${data}
23789
+ ${value}`, dataLines++;
23790
+ break;
23791
+ case "id":
23792
+ id = value.includes("\0") ? void 0 : value;
23793
+ break;
23794
+ case "retry":
23795
+ /^\d+$/.test(value) ? onRetry(parseInt(value, 10)) : onError(
23796
+ new ParseError(`Invalid \`retry\` value: "${value}"`, {
23797
+ type: "invalid-retry",
23798
+ value,
23799
+ line
23800
+ })
23801
+ );
23802
+ break;
23803
+ default:
23804
+ onError(
23805
+ new ParseError(
23806
+ `Unknown field "${field.length > 20 ? `${field.slice(0, 20)}\u2026` : field}"`,
23807
+ { type: "unknown-field", field, value, line }
23808
+ )
23809
+ );
23810
+ break;
23811
+ }
23812
+ }
23813
+ function dispatchEvent() {
23814
+ dataLines > 0 && onEvent({
23815
+ id,
23816
+ event: eventType,
23817
+ data
23818
+ }), id = void 0, data = "", dataLines = 0, eventType = void 0;
20990
23819
  }
20991
- const known = Object.keys(tool.inputSchema.properties);
20992
- for (const [key, value] of Object.entries(args)) {
20993
- if (value === void 0) continue;
20994
- const schema = tool.inputSchema.properties[key];
20995
- if (!schema) {
20996
- const near = known.map((candidate) => ({ candidate, distance: editDistance(key.toLowerCase(), candidate.toLowerCase()) })).filter(({ candidate, distance }) => distance <= (candidate.length <= 4 ? 1 : 2)).sort((a, b) => a.distance - b.distance)[0];
20997
- return near ? `Unknown argument "${key}" for ${tool.name}. Did you mean "${near.candidate}"?` : `Unknown argument "${key}" for ${tool.name}. Accepted: ${known.join(", ") || "(none)"}`;
23820
+ function reset(options = {}) {
23821
+ if (options.consume && pendingFragments.length > 0) {
23822
+ const incompleteLine = pendingFragments.join("");
23823
+ parseLine(incompleteLine, 0, incompleteLine.length);
20998
23824
  }
20999
- if (value === null) continue;
21000
- const problem = typeError(key, schema, value);
21001
- if (problem) return problem;
23825
+ isFirstChunk = true, id = void 0, data = "", dataLines = 0, eventType = void 0, pendingFragments.length = 0, pendingFragmentsLength = 0, terminated = false;
21002
23826
  }
21003
- return null;
23827
+ return { feed, reset };
23828
+ }
23829
+ function isDataPrefix(chunk, i, firstCharCode) {
23830
+ return firstCharCode === 100 && chunk.charCodeAt(i + 1) === 97 && chunk.charCodeAt(i + 2) === 116 && chunk.charCodeAt(i + 3) === 97 && chunk.charCodeAt(i + 4) === 58;
23831
+ }
23832
+ function isEventPrefix(chunk, i, firstCharCode) {
23833
+ return firstCharCode === 101 && chunk.charCodeAt(i + 1) === 118 && chunk.charCodeAt(i + 2) === 101 && chunk.charCodeAt(i + 3) === 110 && chunk.charCodeAt(i + 4) === 116 && chunk.charCodeAt(i + 5) === 58;
21004
23834
  }
21005
23835
 
21006
- // ../api/_lib/mcp-content.ts
21007
- var isImage = (v) => !!v && typeof v === "object" && typeof v.data === "string" && typeof v.mimeType === "string";
21008
- function toContent(result) {
21009
- if (!result || typeof result !== "object") {
21010
- return [{ type: "text", text: JSON.stringify(result) ?? "null" }];
21011
- }
21012
- const { _image, _images, _file: _file2, ...rest } = result;
21013
- if (_file2) rest.fileNote = "A file was made but this connection cannot deliver it. Use the local GoatEdit MCP server, which saves it to disk.";
21014
- const blocks = [];
21015
- const captions = [];
21016
- for (const candidate of [_image, ...Array.isArray(_images) ? _images : []]) {
21017
- if (!isImage(candidate)) continue;
21018
- blocks.push({ type: "image", data: candidate.data, mimeType: candidate.mimeType });
21019
- if (typeof candidate.caption === "string") captions.push(candidate.caption);
23836
+ // node_modules/eventsource-parser/dist/stream.js
23837
+ var EventSourceParserStream = class extends TransformStream {
23838
+ constructor({ onError, onRetry, onComment, maxBufferSize } = {}) {
23839
+ let parser;
23840
+ super({
23841
+ start(controller) {
23842
+ parser = createParser({
23843
+ onEvent: (event) => {
23844
+ controller.enqueue(event);
23845
+ },
23846
+ onError(error2) {
23847
+ typeof onError == "function" && onError(error2), (onError === "terminate" || error2.type === "max-buffer-size-exceeded") && controller.error(error2);
23848
+ },
23849
+ onRetry,
23850
+ onComment,
23851
+ maxBufferSize
23852
+ });
23853
+ },
23854
+ transform(chunk) {
23855
+ parser.feed(chunk);
23856
+ }
23857
+ });
21020
23858
  }
21021
- const text = captions.length ? JSON.stringify({ ...rest, frameCaptions: captions }) : JSON.stringify(Array.isArray(result) ? result : rest);
21022
- blocks.push({ type: "text", text });
21023
- return blocks;
21024
- }
23859
+ };
21025
23860
 
21026
- // src/find-local-file.ts
21027
- import fs from "fs";
21028
- import path from "path";
21029
- function findLocalFile(root, wanted, maxDepth) {
21030
- const name = wanted.trim();
21031
- if (!name || !fs.existsSync(root)) return null;
21032
- if (name.includes("/") || name.includes(path.sep)) {
21033
- const full = path.resolve(root, name);
21034
- if (!full.startsWith(root + path.sep)) return null;
23861
+ // node_modules/@modelcontextprotocol/sdk/dist/esm/client/streamableHttp.js
23862
+ var DEFAULT_STREAMABLE_HTTP_RECONNECTION_OPTIONS = {
23863
+ initialReconnectionDelay: 1e3,
23864
+ maxReconnectionDelay: 3e4,
23865
+ reconnectionDelayGrowFactor: 1.5,
23866
+ maxRetries: 2
23867
+ };
23868
+ var StreamableHTTPError = class extends Error {
23869
+ constructor(code, message) {
23870
+ super(`Streamable HTTP error: ${message}`);
23871
+ this.code = code;
23872
+ }
23873
+ };
23874
+ var StreamableHTTPClientTransport = class {
23875
+ constructor(url2, opts) {
23876
+ this._hasCompletedAuthFlow = false;
23877
+ this._url = url2;
23878
+ this._resourceMetadataUrl = void 0;
23879
+ this._scope = void 0;
23880
+ this._requestInit = opts?.requestInit;
23881
+ this._authProvider = opts?.authProvider;
23882
+ this._fetch = opts?.fetch;
23883
+ this._fetchWithInit = createFetchWithInit(opts?.fetch, opts?.requestInit);
23884
+ this._sessionId = opts?.sessionId;
23885
+ this._reconnectionOptions = opts?.reconnectionOptions ?? DEFAULT_STREAMABLE_HTTP_RECONNECTION_OPTIONS;
23886
+ }
23887
+ async _authThenStart() {
23888
+ if (!this._authProvider) {
23889
+ throw new UnauthorizedError("No auth provider");
23890
+ }
23891
+ let result;
21035
23892
  try {
21036
- return fs.statSync(full).isFile() ? full : null;
21037
- } catch {
21038
- return null;
23893
+ result = await auth(this._authProvider, {
23894
+ serverUrl: this._url,
23895
+ resourceMetadataUrl: this._resourceMetadataUrl,
23896
+ scope: this._scope,
23897
+ fetchFn: this._fetchWithInit
23898
+ });
23899
+ } catch (error2) {
23900
+ this.onerror?.(error2);
23901
+ throw error2;
23902
+ }
23903
+ if (result !== "AUTHORIZED") {
23904
+ throw new UnauthorizedError();
21039
23905
  }
23906
+ return await this._startOrAuthSse({ resumptionToken: void 0 });
21040
23907
  }
21041
- const target = name.toLowerCase();
21042
- let level = [root];
21043
- for (let depth = 0; depth <= maxDepth && level.length; depth++) {
21044
- const hits = [];
21045
- const next = [];
21046
- for (const dir of level) {
21047
- let entries;
21048
- try {
21049
- entries = fs.readdirSync(dir, { withFileTypes: true });
21050
- } catch {
21051
- continue;
23908
+ async _commonHeaders() {
23909
+ const headers = {};
23910
+ if (this._authProvider) {
23911
+ const tokens = await this._authProvider.tokens();
23912
+ if (tokens) {
23913
+ headers["Authorization"] = `Bearer ${tokens.access_token}`;
21052
23914
  }
21053
- for (const entry of entries) {
21054
- if (entry.name.startsWith(".")) continue;
21055
- const full = path.join(dir, entry.name);
21056
- if (entry.isDirectory()) next.push(full);
21057
- else if (entry.isFile() && entry.name.toLowerCase() === target) hits.push(full);
23915
+ }
23916
+ if (this._sessionId) {
23917
+ headers["mcp-session-id"] = this._sessionId;
23918
+ }
23919
+ if (this._protocolVersion) {
23920
+ headers["mcp-protocol-version"] = this._protocolVersion;
23921
+ }
23922
+ const extraHeaders = normalizeHeaders(this._requestInit?.headers);
23923
+ return new Headers({
23924
+ ...headers,
23925
+ ...extraHeaders
23926
+ });
23927
+ }
23928
+ async _startOrAuthSse(options) {
23929
+ const { resumptionToken } = options;
23930
+ try {
23931
+ const headers = await this._commonHeaders();
23932
+ headers.set("Accept", "text/event-stream");
23933
+ if (resumptionToken) {
23934
+ headers.set("last-event-id", resumptionToken);
23935
+ }
23936
+ const response = await (this._fetch ?? fetch)(this._url, {
23937
+ method: "GET",
23938
+ headers,
23939
+ signal: this._abortController?.signal
23940
+ });
23941
+ if (!response.ok) {
23942
+ await response.body?.cancel();
23943
+ if (response.status === 401 && this._authProvider) {
23944
+ return await this._authThenStart();
23945
+ }
23946
+ if (response.status === 405) {
23947
+ return;
23948
+ }
23949
+ throw new StreamableHTTPError(response.status, `Failed to open SSE stream: ${response.statusText}`);
21058
23950
  }
23951
+ this._handleSseStream(response.body, options, true);
23952
+ } catch (error2) {
23953
+ this.onerror?.(error2);
23954
+ throw error2;
21059
23955
  }
21060
- if (hits.length > 1) {
21061
- throw new Error(
21062
- `Several files are named "${name}": ${hits.map((h) => path.relative(root, h)).sort().join(", ")}. Pass one of these paths as filename.`
21063
- );
23956
+ }
23957
+ /**
23958
+ * Calculates the next reconnection delay using backoff algorithm
23959
+ *
23960
+ * @param attempt Current reconnection attempt count for the specific stream
23961
+ * @returns Time to wait in milliseconds before next reconnection attempt
23962
+ */
23963
+ _getNextReconnectionDelay(attempt) {
23964
+ if (this._serverRetryMs !== void 0) {
23965
+ return this._serverRetryMs;
21064
23966
  }
21065
- if (hits.length === 1) return hits[0];
21066
- level = next;
23967
+ const initialDelay = this._reconnectionOptions.initialReconnectionDelay;
23968
+ const growFactor = this._reconnectionOptions.reconnectionDelayGrowFactor;
23969
+ const maxDelay = this._reconnectionOptions.maxReconnectionDelay;
23970
+ return Math.min(initialDelay * Math.pow(growFactor, attempt), maxDelay);
21067
23971
  }
21068
- return null;
21069
- }
21070
-
21071
- // src/run-refs.ts
21072
- function resolveRefs(value, refs) {
21073
- if (typeof value === "string") {
21074
- const m = /^\$([A-Za-z_][\w-]*)((?:\.[^.]+)*)$/.exec(value);
21075
- if (!m || !refs.has(m[1])) return value;
21076
- let x = refs.get(m[1]);
21077
- for (const key of m[2].split(".").slice(1)) {
21078
- x = x && typeof x === "object" ? x[key] : void 0;
21079
- if (x === void 0) throw new Error(`${value}: step "${m[1]}" has no "${m[2].slice(1)}". It returned ${JSON.stringify(refs.get(m[1])).slice(0, 300)}`);
23972
+ /**
23973
+ * Schedule a reconnection attempt using server-provided retry interval or backoff
23974
+ *
23975
+ * @param lastEventId The ID of the last received event for resumability
23976
+ * @param attemptCount Current reconnection attempt count for this specific stream
23977
+ */
23978
+ _scheduleReconnection(options, attemptCount = 0) {
23979
+ const maxRetries = this._reconnectionOptions.maxRetries;
23980
+ if (attemptCount >= maxRetries) {
23981
+ this.onerror?.(new Error(`Maximum reconnection attempts (${maxRetries}) exceeded.`));
23982
+ return;
21080
23983
  }
21081
- return x;
23984
+ const delay = this._getNextReconnectionDelay(attemptCount);
23985
+ this._reconnectionTimeout = setTimeout(() => {
23986
+ this._startOrAuthSse(options).catch((error2) => {
23987
+ this.onerror?.(new Error(`Failed to reconnect SSE stream: ${error2 instanceof Error ? error2.message : String(error2)}`));
23988
+ this._scheduleReconnection(options, attemptCount + 1);
23989
+ });
23990
+ }, delay);
21082
23991
  }
21083
- if (Array.isArray(value)) return value.map((v) => resolveRefs(v, refs));
21084
- if (value && typeof value === "object") {
21085
- return Object.fromEntries(Object.entries(value).map(([k, v]) => [k, resolveRefs(v, refs)]));
23992
+ _handleSseStream(stream, options, isReconnectable) {
23993
+ if (!stream) {
23994
+ return;
23995
+ }
23996
+ const { onresumptiontoken, replayMessageId } = options;
23997
+ let lastEventId;
23998
+ let hasPrimingEvent = false;
23999
+ let receivedResponse = false;
24000
+ const processStream = async () => {
24001
+ try {
24002
+ const reader = stream.pipeThrough(new TextDecoderStream()).pipeThrough(new EventSourceParserStream({
24003
+ onRetry: (retryMs) => {
24004
+ this._serverRetryMs = retryMs;
24005
+ }
24006
+ })).getReader();
24007
+ while (true) {
24008
+ const { value: event, done } = await reader.read();
24009
+ if (done) {
24010
+ break;
24011
+ }
24012
+ if (event.id) {
24013
+ lastEventId = event.id;
24014
+ hasPrimingEvent = true;
24015
+ onresumptiontoken?.(event.id);
24016
+ }
24017
+ if (!event.data) {
24018
+ continue;
24019
+ }
24020
+ if (!event.event || event.event === "message") {
24021
+ try {
24022
+ const message = JSONRPCMessageSchema.parse(JSON.parse(event.data));
24023
+ if (isJSONRPCResultResponse(message)) {
24024
+ receivedResponse = true;
24025
+ if (replayMessageId !== void 0) {
24026
+ message.id = replayMessageId;
24027
+ }
24028
+ }
24029
+ this.onmessage?.(message);
24030
+ } catch (error2) {
24031
+ this.onerror?.(error2);
24032
+ }
24033
+ }
24034
+ }
24035
+ const canResume = isReconnectable || hasPrimingEvent;
24036
+ const needsReconnect = canResume && !receivedResponse;
24037
+ if (needsReconnect && this._abortController && !this._abortController.signal.aborted) {
24038
+ this._scheduleReconnection({
24039
+ resumptionToken: lastEventId,
24040
+ onresumptiontoken,
24041
+ replayMessageId
24042
+ }, 0);
24043
+ }
24044
+ } catch (error2) {
24045
+ this.onerror?.(new Error(`SSE stream disconnected: ${error2}`));
24046
+ const canResume = isReconnectable || hasPrimingEvent;
24047
+ const needsReconnect = canResume && !receivedResponse;
24048
+ if (needsReconnect && this._abortController && !this._abortController.signal.aborted) {
24049
+ try {
24050
+ this._scheduleReconnection({
24051
+ resumptionToken: lastEventId,
24052
+ onresumptiontoken,
24053
+ replayMessageId
24054
+ }, 0);
24055
+ } catch (error3) {
24056
+ this.onerror?.(new Error(`Failed to reconnect: ${error3 instanceof Error ? error3.message : String(error3)}`));
24057
+ }
24058
+ }
24059
+ }
24060
+ };
24061
+ processStream();
21086
24062
  }
21087
- return value;
24063
+ async start() {
24064
+ if (this._abortController) {
24065
+ throw new Error("StreamableHTTPClientTransport already started! If using Client class, note that connect() calls start() automatically.");
24066
+ }
24067
+ this._abortController = new AbortController();
24068
+ }
24069
+ /**
24070
+ * Call this method after the user has finished authorizing via their user agent and is redirected back to the MCP client application. This will exchange the authorization code for an access token, enabling the next connection attempt to successfully auth.
24071
+ */
24072
+ async finishAuth(authorizationCode) {
24073
+ if (!this._authProvider) {
24074
+ throw new UnauthorizedError("No auth provider");
24075
+ }
24076
+ const result = await auth(this._authProvider, {
24077
+ serverUrl: this._url,
24078
+ authorizationCode,
24079
+ resourceMetadataUrl: this._resourceMetadataUrl,
24080
+ scope: this._scope,
24081
+ fetchFn: this._fetchWithInit
24082
+ });
24083
+ if (result !== "AUTHORIZED") {
24084
+ throw new UnauthorizedError("Failed to authorize");
24085
+ }
24086
+ }
24087
+ async close() {
24088
+ if (this._reconnectionTimeout) {
24089
+ clearTimeout(this._reconnectionTimeout);
24090
+ this._reconnectionTimeout = void 0;
24091
+ }
24092
+ this._abortController?.abort();
24093
+ this.onclose?.();
24094
+ }
24095
+ async send(message, options) {
24096
+ try {
24097
+ const { resumptionToken, onresumptiontoken } = options || {};
24098
+ if (resumptionToken) {
24099
+ this._startOrAuthSse({ resumptionToken, replayMessageId: isJSONRPCRequest(message) ? message.id : void 0 }).catch((err) => this.onerror?.(err));
24100
+ return;
24101
+ }
24102
+ const headers = await this._commonHeaders();
24103
+ headers.set("content-type", "application/json");
24104
+ headers.set("accept", "application/json, text/event-stream");
24105
+ const init = {
24106
+ ...this._requestInit,
24107
+ method: "POST",
24108
+ headers,
24109
+ body: JSON.stringify(message),
24110
+ signal: this._abortController?.signal
24111
+ };
24112
+ const response = await (this._fetch ?? fetch)(this._url, init);
24113
+ const sessionId = response.headers.get("mcp-session-id");
24114
+ if (sessionId) {
24115
+ this._sessionId = sessionId;
24116
+ }
24117
+ if (!response.ok) {
24118
+ const text = await response.text().catch(() => null);
24119
+ if (response.status === 401 && this._authProvider) {
24120
+ if (this._hasCompletedAuthFlow) {
24121
+ throw new StreamableHTTPError(401, "Server returned 401 after successful authentication");
24122
+ }
24123
+ const { resourceMetadataUrl, scope } = extractWWWAuthenticateParams(response);
24124
+ this._resourceMetadataUrl = resourceMetadataUrl;
24125
+ this._scope = scope;
24126
+ const result = await auth(this._authProvider, {
24127
+ serverUrl: this._url,
24128
+ resourceMetadataUrl: this._resourceMetadataUrl,
24129
+ scope: this._scope,
24130
+ fetchFn: this._fetchWithInit
24131
+ });
24132
+ if (result !== "AUTHORIZED") {
24133
+ throw new UnauthorizedError();
24134
+ }
24135
+ this._hasCompletedAuthFlow = true;
24136
+ return this.send(message);
24137
+ }
24138
+ if (response.status === 403 && this._authProvider) {
24139
+ const { resourceMetadataUrl, scope, error: error2 } = extractWWWAuthenticateParams(response);
24140
+ if (error2 === "insufficient_scope") {
24141
+ const wwwAuthHeader = response.headers.get("WWW-Authenticate");
24142
+ if (this._lastUpscopingHeader === wwwAuthHeader) {
24143
+ throw new StreamableHTTPError(403, "Server returned 403 after trying upscoping");
24144
+ }
24145
+ if (scope) {
24146
+ this._scope = scope;
24147
+ }
24148
+ if (resourceMetadataUrl) {
24149
+ this._resourceMetadataUrl = resourceMetadataUrl;
24150
+ }
24151
+ this._lastUpscopingHeader = wwwAuthHeader ?? void 0;
24152
+ const result = await auth(this._authProvider, {
24153
+ serverUrl: this._url,
24154
+ resourceMetadataUrl: this._resourceMetadataUrl,
24155
+ scope: this._scope,
24156
+ fetchFn: this._fetch
24157
+ });
24158
+ if (result !== "AUTHORIZED") {
24159
+ throw new UnauthorizedError();
24160
+ }
24161
+ return this.send(message);
24162
+ }
24163
+ }
24164
+ throw new StreamableHTTPError(response.status, `Error POSTing to endpoint: ${text}`);
24165
+ }
24166
+ this._hasCompletedAuthFlow = false;
24167
+ this._lastUpscopingHeader = void 0;
24168
+ if (response.status === 202) {
24169
+ await response.body?.cancel();
24170
+ if (isInitializedNotification(message)) {
24171
+ this._startOrAuthSse({ resumptionToken: void 0 }).catch((err) => this.onerror?.(err));
24172
+ }
24173
+ return;
24174
+ }
24175
+ const messages = Array.isArray(message) ? message : [message];
24176
+ const hasRequests = messages.filter((msg) => "method" in msg && "id" in msg && msg.id !== void 0).length > 0;
24177
+ const contentType = response.headers.get("content-type");
24178
+ if (hasRequests) {
24179
+ if (contentType?.includes("text/event-stream")) {
24180
+ this._handleSseStream(response.body, { onresumptiontoken }, false);
24181
+ } else if (contentType?.includes("application/json")) {
24182
+ const data = await response.json();
24183
+ const responseMessages = Array.isArray(data) ? data.map((msg) => JSONRPCMessageSchema.parse(msg)) : [JSONRPCMessageSchema.parse(data)];
24184
+ for (const msg of responseMessages) {
24185
+ this.onmessage?.(msg);
24186
+ }
24187
+ } else {
24188
+ await response.body?.cancel();
24189
+ throw new StreamableHTTPError(-1, `Unexpected content type: ${contentType}`);
24190
+ }
24191
+ } else {
24192
+ await response.body?.cancel();
24193
+ }
24194
+ } catch (error2) {
24195
+ this.onerror?.(error2);
24196
+ throw error2;
24197
+ }
24198
+ }
24199
+ get sessionId() {
24200
+ return this._sessionId;
24201
+ }
24202
+ /**
24203
+ * Terminates the current session by sending a DELETE request to the server.
24204
+ *
24205
+ * Clients that no longer need a particular session
24206
+ * (e.g., because the user is leaving the client application) SHOULD send an
24207
+ * HTTP DELETE to the MCP endpoint with the Mcp-Session-Id header to explicitly
24208
+ * terminate the session.
24209
+ *
24210
+ * The server MAY respond with HTTP 405 Method Not Allowed, indicating that
24211
+ * the server does not allow clients to terminate sessions.
24212
+ */
24213
+ async terminateSession() {
24214
+ if (!this._sessionId) {
24215
+ return;
24216
+ }
24217
+ try {
24218
+ const headers = await this._commonHeaders();
24219
+ const init = {
24220
+ ...this._requestInit,
24221
+ method: "DELETE",
24222
+ headers,
24223
+ signal: this._abortController?.signal
24224
+ };
24225
+ const response = await (this._fetch ?? fetch)(this._url, init);
24226
+ await response.body?.cancel();
24227
+ if (!response.ok && response.status !== 405) {
24228
+ throw new StreamableHTTPError(response.status, `Failed to terminate session: ${response.statusText}`);
24229
+ }
24230
+ this._sessionId = void 0;
24231
+ } catch (error2) {
24232
+ this.onerror?.(error2);
24233
+ throw error2;
24234
+ }
24235
+ }
24236
+ setProtocolVersion(version2) {
24237
+ this._protocolVersion = version2;
24238
+ }
24239
+ get protocolVersion() {
24240
+ return this._protocolVersion;
24241
+ }
24242
+ /**
24243
+ * Resume an SSE stream from a previous event ID.
24244
+ * Opens a GET SSE connection with Last-Event-ID header to replay missed events.
24245
+ *
24246
+ * @param lastEventId The event ID to resume from
24247
+ * @param options Optional callback to receive new resumption tokens
24248
+ */
24249
+ async resumeStream(lastEventId, options) {
24250
+ await this._startOrAuthSse({
24251
+ resumptionToken: lastEventId,
24252
+ onresumptiontoken: options?.onresumptiontoken
24253
+ });
24254
+ }
24255
+ };
24256
+
24257
+ // src/services.ts
24258
+ import dns from "dns/promises";
24259
+ import fs2 from "fs";
24260
+ import net from "net";
24261
+ import os from "os";
24262
+ import path2 from "path";
24263
+ import { Readable } from "stream";
24264
+ import { pipeline } from "stream/promises";
24265
+ var SERVICES_FILE = path2.resolve(
24266
+ process.env.GOATEDIT_SERVICES_FILE || path2.join(os.homedir(), ".goatedit", "services.json")
24267
+ );
24268
+ var MAX_DOWNLOAD_BYTES = 4 * 1024 ** 3;
24269
+ var CALL_TIMEOUT_MS = 12e4;
24270
+ function readConfig() {
24271
+ let raw;
24272
+ try {
24273
+ raw = fs2.readFileSync(SERVICES_FILE, "utf8");
24274
+ } catch {
24275
+ return {};
24276
+ }
24277
+ const parsed = JSON.parse(raw);
24278
+ const servers = parsed && typeof parsed === "object" ? parsed.servers : null;
24279
+ return servers && typeof servers === "object" ? servers : {};
21088
24280
  }
21089
- function withRunProject(stepArgs, projectId) {
21090
- if (typeof projectId !== "string" || !projectId || typeof stepArgs.projectId === "string") return stepArgs;
21091
- return { ...stepArgs, projectId };
24281
+ var clients = /* @__PURE__ */ new Map();
24282
+ async function connect(name, config2) {
24283
+ const client = new Client({ name: "goatedit-studio", version: "1.0.0" });
24284
+ if ("url" in config2) {
24285
+ await client.connect(new StreamableHTTPClientTransport(new URL(config2.url), { requestInit: { headers: config2.headers ?? {} } }));
24286
+ } else {
24287
+ const env = {};
24288
+ for (const [k, v] of Object.entries(process.env)) if (typeof v === "string") env[k] = v;
24289
+ await client.connect(new StdioClientTransport({
24290
+ command: config2.command,
24291
+ args: config2.args ?? [],
24292
+ env: { ...env, ...config2.env ?? {} },
24293
+ ...config2.cwd ? { cwd: config2.cwd } : {},
24294
+ stderr: "ignore"
24295
+ }));
24296
+ }
24297
+ client.onclose = () => {
24298
+ clients.delete(name);
24299
+ };
24300
+ return client;
21092
24301
  }
21093
-
21094
- // src/tab-registry.ts
21095
- function indexTabs(reports, isOpen) {
21096
- const index = /* @__PURE__ */ new Map();
21097
- for (const r of [...reports].sort((a, b) => a.at - b.at)) {
21098
- if (isOpen(r.socket)) index.set(r.projectId, r);
24302
+ function clientFor(name) {
24303
+ const config2 = readConfig()[name];
24304
+ if (!config2) throw new Error(`No service "${name}" in ${SERVICES_FILE}.`);
24305
+ let pending = clients.get(name);
24306
+ if (!pending) {
24307
+ pending = connect(name, config2);
24308
+ clients.set(name, pending);
24309
+ pending.catch(() => clients.delete(name));
24310
+ }
24311
+ return pending;
24312
+ }
24313
+ async function listServices() {
24314
+ const names = Object.keys(readConfig());
24315
+ return Promise.all(names.map(async (server2) => {
24316
+ try {
24317
+ const { tools } = await (await clientFor(server2)).listTools();
24318
+ return { server: server2, tools: tools.map((t) => ({ name: t.name, ...t.description ? { description: t.description } : {} })) };
24319
+ } catch (err) {
24320
+ return { server: server2, error: err instanceof Error ? err.message : String(err) };
24321
+ }
24322
+ }));
24323
+ }
24324
+ async function callService(server2, tool, args = {}) {
24325
+ const client = await clientFor(server2);
24326
+ const result = await client.callTool({ name: tool, arguments: args }, void 0, { timeout: CALL_TIMEOUT_MS });
24327
+ return result;
24328
+ }
24329
+ function isPrivateAddress(ip) {
24330
+ if (net.isIPv4(ip)) {
24331
+ const [a, b] = ip.split(".").map(Number);
24332
+ return a === 10 || a === 127 || a === 0 || a === 169 && b === 254 || a === 172 && b >= 16 && b <= 31 || a === 192 && b === 168 || a === 100 && b >= 64 && b <= 127;
24333
+ }
24334
+ const v6 = ip.toLowerCase();
24335
+ if (v6.startsWith("::ffff:")) return isPrivateAddress(v6.slice(7));
24336
+ return v6 === "::1" || v6 === "::" || v6.startsWith("fc") || v6.startsWith("fd") || v6.startsWith("fe80");
24337
+ }
24338
+ async function checkUrl(raw) {
24339
+ let url2;
24340
+ try {
24341
+ url2 = new URL(raw);
24342
+ } catch {
24343
+ throw new Error("Not a URL.");
21099
24344
  }
21100
- return index;
24345
+ if (url2.protocol !== "https:") throw new Error("Only https links are downloaded.");
24346
+ const addresses = await dns.lookup(url2.hostname, { all: true });
24347
+ if (!addresses.length || addresses.some((a) => isPrivateAddress(a.address))) throw new Error(`${url2.hostname} is not a public address.`);
24348
+ return url2;
24349
+ }
24350
+ var safeName = (s) => s.replace(/[^\w.-]+/g, "_").replace(/^[._]+/, "").slice(0, 80) || "file";
24351
+ async function downloadToAssets(assetsDir, rawUrl, name) {
24352
+ let url2 = await checkUrl(rawUrl);
24353
+ let res = null;
24354
+ for (let hop = 0; hop < 5; hop++) {
24355
+ res = await fetch(url2, { redirect: "manual" });
24356
+ const next = res.status >= 300 && res.status < 400 ? res.headers.get("location") : null;
24357
+ if (!next) break;
24358
+ url2 = await checkUrl(new URL(next, url2).toString());
24359
+ res = null;
24360
+ }
24361
+ if (!res) throw new Error("Too many redirects.");
24362
+ if (!res.ok || !res.body) throw new Error(`The download failed: HTTP ${res.status}.`);
24363
+ const declared = Number(res.headers.get("content-length") || 0);
24364
+ if (declared > MAX_DOWNLOAD_BYTES) throw new Error("The file is too big.");
24365
+ const fromUrl = path2.basename(url2.pathname);
24366
+ const file = safeName(name || fromUrl);
24367
+ const ext = path2.extname(file) ? "" : path2.extname(fromUrl);
24368
+ const day = (/* @__PURE__ */ new Date()).toISOString().slice(0, 10);
24369
+ const rel = path2.join("GoatEdit Downloads", day, `${Date.now().toString(36)}-${file}${ext}`);
24370
+ const dest = path2.join(assetsDir, rel);
24371
+ fs2.mkdirSync(path2.dirname(dest), { recursive: true });
24372
+ const partial2 = `${dest}.part`;
24373
+ let bytes = 0;
24374
+ const counted = Readable.fromWeb(res.body);
24375
+ counted.on("data", (chunk) => {
24376
+ bytes += chunk.length;
24377
+ if (bytes > MAX_DOWNLOAD_BYTES) counted.destroy(new Error("The file is too big."));
24378
+ });
24379
+ try {
24380
+ await pipeline(counted, fs2.createWriteStream(partial2));
24381
+ fs2.renameSync(partial2, dest);
24382
+ } catch (err) {
24383
+ fs2.rmSync(partial2, { force: true });
24384
+ throw err;
24385
+ }
24386
+ return { rel, path: dest, bytes, contentType: res.headers.get("content-type") || "" };
21101
24387
  }
21102
24388
 
21103
24389
  // src/index.ts
@@ -21126,32 +24412,32 @@ function isLoopbackHost(host) {
21126
24412
  return false;
21127
24413
  }
21128
24414
  }
21129
- var CONTROLLER_TOKEN = process.env.GOATEDIT_CONTROLLER_TOKEN || crypto.randomBytes(32).toString("hex");
21130
- var CONTROLLER_TOKEN_FILE = path2.join(os.homedir(), ".goatedit", "mcp-controller-token");
24415
+ var CONTROLLER_TOKEN = process.env.GOATEDIT_CONTROLLER_TOKEN || crypto2.randomBytes(32).toString("hex");
24416
+ var CONTROLLER_TOKEN_FILE = path3.join(os2.homedir(), ".goatedit", "mcp-controller-token");
21131
24417
  function writeControllerToken() {
21132
- fs2.mkdirSync(path2.dirname(CONTROLLER_TOKEN_FILE), { recursive: true, mode: 448 });
21133
- fs2.writeFileSync(CONTROLLER_TOKEN_FILE, CONTROLLER_TOKEN, { mode: 384 });
21134
- fs2.chmodSync(CONTROLLER_TOKEN_FILE, 384);
24418
+ fs3.mkdirSync(path3.dirname(CONTROLLER_TOKEN_FILE), { recursive: true, mode: 448 });
24419
+ fs3.writeFileSync(CONTROLLER_TOKEN_FILE, CONTROLLER_TOKEN, { mode: 384 });
24420
+ fs3.chmodSync(CONTROLLER_TOKEN_FILE, 384);
21135
24421
  }
21136
24422
  function hasControllerToken(req) {
21137
24423
  const header = req.headers.authorization || "";
21138
24424
  const presented = header.startsWith("Bearer ") ? header.slice(7) : new URL(req.url || "/", "http://localhost").searchParams.get("token") || "";
21139
24425
  const a = Buffer.from(presented);
21140
24426
  const b = Buffer.from(CONTROLLER_TOKEN);
21141
- return a.length === b.length && crypto.timingSafeEqual(a, b);
24427
+ return a.length === b.length && crypto2.timingSafeEqual(a, b);
21142
24428
  }
21143
24429
  var REQUEST_TIMEOUT_MS = 3e4;
21144
- var LOCAL_ASSETS_DIR = path2.resolve(
21145
- process.env.GOATEDIT_ASSETS_DIR || path2.join(os.homedir(), "Movies")
24430
+ var LOCAL_ASSETS_DIR = path3.resolve(
24431
+ process.env.GOATEDIT_ASSETS_DIR || path3.join(os2.homedir(), "Movies")
21146
24432
  );
21147
- var FRAMES_DIR = path2.resolve(
21148
- process.env.GOATEDIT_FRAMES_DIR || path2.join(os.homedir(), ".goatedit", "frames")
24433
+ var FRAMES_DIR = path3.resolve(
24434
+ process.env.GOATEDIT_FRAMES_DIR || path3.join(os2.homedir(), ".goatedit", "frames")
21149
24435
  );
21150
24436
  var VERSION = (() => {
21151
- const here = path2.dirname(fileURLToPath(import.meta.url));
24437
+ const here = path3.dirname(fileURLToPath(import.meta.url));
21152
24438
  for (const rel of ["../package.json", "../../../package.json"]) {
21153
24439
  try {
21154
- const pkg = JSON.parse(fs2.readFileSync(path2.join(here, rel), "utf8"));
24440
+ const pkg = JSON.parse(fs3.readFileSync(path3.join(here, rel), "utf8"));
21155
24441
  if (pkg.name === "goatedit-mcp") return String(pkg.version);
21156
24442
  } catch {
21157
24443
  }
@@ -21180,18 +24466,18 @@ var MEDIA_TYPES = {
21180
24466
  ".glb": { mime: "model/gltf-binary", kind: "model" }
21181
24467
  };
21182
24468
  function mediaUrl(rel) {
21183
- return `http://localhost:${WEBSOCKET_PORT}/media/${rel.split(path2.sep).map(encodeURIComponent).join("/")}`;
24469
+ return `http://localhost:${WEBSOCKET_PORT}/media/${rel.split(path3.sep).map(encodeURIComponent).join("/")}`;
21184
24470
  }
21185
24471
  var MAX_LISTED_ASSETS = 500;
21186
24472
  var MAX_ASSET_DEPTH = 4;
21187
24473
  async function handleListLocalAssets(args = {}) {
21188
- if (!fs2.existsSync(LOCAL_ASSETS_DIR)) {
24474
+ if (!fs3.existsSync(LOCAL_ASSETS_DIR)) {
21189
24475
  throw new Error(
21190
24476
  `Assets directory does not exist: ${LOCAL_ASSETS_DIR}. Set GOATEDIT_ASSETS_DIR to a folder of media.`
21191
24477
  );
21192
24478
  }
21193
- const start = path2.resolve(LOCAL_ASSETS_DIR, args.folder || "");
21194
- if (start !== LOCAL_ASSETS_DIR && !start.startsWith(LOCAL_ASSETS_DIR + path2.sep)) {
24479
+ const start = path3.resolve(LOCAL_ASSETS_DIR, args.folder || "");
24480
+ if (start !== LOCAL_ASSETS_DIR && !start.startsWith(LOCAL_ASSETS_DIR + path3.sep)) {
21195
24481
  throw new Error("folder must be inside the assets directory.");
21196
24482
  }
21197
24483
  const files = [];
@@ -21199,7 +24485,7 @@ async function handleListLocalAssets(args = {}) {
21199
24485
  const walk = (dir, depth) => {
21200
24486
  let entries;
21201
24487
  try {
21202
- entries = fs2.readdirSync(dir, { withFileTypes: true });
24488
+ entries = fs3.readdirSync(dir, { withFileTypes: true });
21203
24489
  } catch {
21204
24490
  return;
21205
24491
  }
@@ -21210,17 +24496,17 @@ async function handleListLocalAssets(args = {}) {
21210
24496
  return;
21211
24497
  }
21212
24498
  if (entry.name.startsWith(".")) continue;
21213
- const full = path2.join(dir, entry.name);
24499
+ const full = path3.join(dir, entry.name);
21214
24500
  if (entry.isDirectory()) {
21215
24501
  if (depth < MAX_ASSET_DEPTH) walk(full, depth + 1);
21216
24502
  continue;
21217
24503
  }
21218
- const type = MEDIA_TYPES[path2.extname(entry.name).toLowerCase()];
24504
+ const type = MEDIA_TYPES[path3.extname(entry.name).toLowerCase()];
21219
24505
  if (!type || !entry.isFile()) continue;
21220
- const rel = path2.relative(LOCAL_ASSETS_DIR, full);
24506
+ const rel = path3.relative(LOCAL_ASSETS_DIR, full);
21221
24507
  let bytes = 0;
21222
24508
  try {
21223
- bytes = fs2.statSync(full).size;
24509
+ bytes = fs3.statSync(full).size;
21224
24510
  } catch {
21225
24511
  }
21226
24512
  files.push({ name: entry.name, path: rel, type: type.kind, bytes, url: mediaUrl(rel) });
@@ -21236,10 +24522,10 @@ async function handleListLocalAssets(args = {}) {
21236
24522
  async function handleFindLocalFile(args = {}) {
21237
24523
  const hit = findLocalFile(LOCAL_ASSETS_DIR, String(args.filename ?? ""), MAX_ASSET_DEPTH);
21238
24524
  if (!hit) return null;
21239
- const type = MEDIA_TYPES[path2.extname(hit).toLowerCase()];
24525
+ const type = MEDIA_TYPES[path3.extname(hit).toLowerCase()];
21240
24526
  if (!type || type.kind === "lottie") return null;
21241
- const rel = path2.relative(LOCAL_ASSETS_DIR, hit);
21242
- return { name: path2.basename(hit), path: rel, url: mediaUrl(rel), contentType: type.mime };
24527
+ const rel = path3.relative(LOCAL_ASSETS_DIR, hit);
24528
+ return { name: path3.basename(hit), path: rel, url: mediaUrl(rel), contentType: type.mime };
21243
24529
  }
21244
24530
  function audioDuration(file) {
21245
24531
  try {
@@ -21258,15 +24544,15 @@ async function handleGenerateVoiceover(text, projectId) {
21258
24544
  throw new Error("generate_voiceover needs macOS `say`. Not available on this platform.");
21259
24545
  }
21260
24546
  const filename = `voiceover_${Date.now()}.wav`;
21261
- const filePath = path2.join(LOCAL_ASSETS_DIR, filename);
21262
- fs2.mkdirSync(LOCAL_ASSETS_DIR, { recursive: true });
21263
- const scriptPath = path2.join(LOCAL_ASSETS_DIR, `.voiceover_${Date.now()}.txt`);
21264
- fs2.writeFileSync(scriptPath, text, "utf8");
24547
+ const filePath = path3.join(LOCAL_ASSETS_DIR, filename);
24548
+ fs3.mkdirSync(LOCAL_ASSETS_DIR, { recursive: true });
24549
+ const scriptPath = path3.join(LOCAL_ASSETS_DIR, `.voiceover_${Date.now()}.txt`);
24550
+ fs3.writeFileSync(scriptPath, text, "utf8");
21265
24551
  try {
21266
24552
  execFileSync("say", ["-o", filePath, "-f", scriptPath], { stdio: "ignore" });
21267
24553
  const duration3 = audioDuration(filePath) ?? text.split(/\s+/).length * 0.45 + 1;
21268
24554
  const audioAsset = {
21269
- id: `media-${crypto.randomUUID()}`,
24555
+ id: `media-${crypto2.randomUUID()}`,
21270
24556
  name: filename,
21271
24557
  type: "audio",
21272
24558
  duration: duration3,
@@ -21279,7 +24565,7 @@ async function handleGenerateVoiceover(text, projectId) {
21279
24565
  throw new Error(`Failed to generate voiceover: ${err.message}`);
21280
24566
  } finally {
21281
24567
  try {
21282
- fs2.unlinkSync(scriptPath);
24568
+ fs3.unlinkSync(scriptPath);
21283
24569
  } catch {
21284
24570
  }
21285
24571
  }
@@ -21287,12 +24573,12 @@ async function handleGenerateVoiceover(text, projectId) {
21287
24573
  function saveFileToDisk(result) {
21288
24574
  const file = result && typeof result === "object" ? result._file : void 0;
21289
24575
  if (!file || typeof file.data !== "string") return result;
21290
- fs2.mkdirSync(FRAMES_DIR, { recursive: true });
24576
+ fs3.mkdirSync(FRAMES_DIR, { recursive: true });
21291
24577
  const stamp = (/* @__PURE__ */ new Date()).toISOString().replace(/[:.]/g, "-");
21292
24578
  const safe = String(file.name ?? "file").replace(/[^\w.-]+/g, "_").slice(0, 80);
21293
- const target = path2.join(FRAMES_DIR, `${stamp}-${safe}`);
24579
+ const target = path3.join(FRAMES_DIR, `${stamp}-${safe}`);
21294
24580
  const bytes = Buffer.from(file.data, "base64");
21295
- fs2.writeFileSync(target, bytes);
24581
+ fs3.writeFileSync(target, bytes);
21296
24582
  const { _file: _file2, ...rest } = result;
21297
24583
  return { ...rest, savedTo: target, bytes: bytes.length };
21298
24584
  }
@@ -21300,14 +24586,14 @@ function saveFramesToDisk(result, label) {
21300
24586
  if (!result || typeof result !== "object") return result;
21301
24587
  const frames = [result._image, ...Array.isArray(result._images) ? result._images : []].filter((f) => f && typeof f.data === "string" && typeof f.mimeType === "string");
21302
24588
  if (!frames.length) return result;
21303
- fs2.mkdirSync(FRAMES_DIR, { recursive: true });
24589
+ fs3.mkdirSync(FRAMES_DIR, { recursive: true });
21304
24590
  const stamp = (/* @__PURE__ */ new Date()).toISOString().replace(/[:.]/g, "-");
21305
24591
  const safe = label.replace(/[^\w.-]+/g, "_").slice(0, 60);
21306
24592
  const saved = frames.map((f, i) => {
21307
24593
  const ext = f.mimeType === "image/png" ? "png" : f.mimeType === "image/webp" ? "webp" : "jpg";
21308
- const file = path2.join(FRAMES_DIR, `${stamp}-${safe}${frames.length > 1 ? `-${i}` : ""}.${ext}`);
24594
+ const file = path3.join(FRAMES_DIR, `${stamp}-${safe}${frames.length > 1 ? `-${i}` : ""}.${ext}`);
21309
24595
  const bytes = Buffer.from(f.data, "base64");
21310
- fs2.writeFileSync(file, bytes);
24596
+ fs3.writeFileSync(file, bytes);
21311
24597
  return { path: file, bytes: bytes.length, ...f.caption ? { caption: f.caption } : {} };
21312
24598
  });
21313
24599
  const { _image, _images, ...rest } = result;
@@ -21318,8 +24604,8 @@ function saveFramesToDisk(result, label) {
21318
24604
  };
21319
24605
  }
21320
24606
  function serveFile(req, res, filePath) {
21321
- const size = fs2.statSync(filePath).size;
21322
- const type = MEDIA_TYPES[path2.extname(filePath).toLowerCase()]?.mime ?? "application/octet-stream";
24607
+ const size = fs3.statSync(filePath).size;
24608
+ const type = MEDIA_TYPES[path3.extname(filePath).toLowerCase()]?.mime ?? "application/octet-stream";
21323
24609
  const headers = { "Content-Type": type, "Accept-Ranges": "bytes" };
21324
24610
  const range = /^bytes=(\d*)-(\d*)$/.exec(req.headers.range || "");
21325
24611
  if (range && (range[1] || range[2])) {
@@ -21342,7 +24628,7 @@ function serveFile(req, res, filePath) {
21342
24628
  res.end();
21343
24629
  return;
21344
24630
  }
21345
- fs2.createReadStream(filePath, { start, end }).pipe(res);
24631
+ fs3.createReadStream(filePath, { start, end }).pipe(res);
21346
24632
  return;
21347
24633
  }
21348
24634
  res.writeHead(200, { ...headers, "Content-Length": size });
@@ -21350,11 +24636,11 @@ function serveFile(req, res, filePath) {
21350
24636
  res.end();
21351
24637
  return;
21352
24638
  }
21353
- fs2.createReadStream(filePath).pipe(res);
24639
+ fs3.createReadStream(filePath).pipe(res);
21354
24640
  }
21355
24641
  var httpServer = http.createServer((req, res) => {
21356
- const url = new URL(req.url || "/", `http://${req.headers.host}`);
21357
- const pathname = url.pathname;
24642
+ const url2 = new URL(req.url || "/", `http://${req.headers.host}`);
24643
+ const pathname = url2.pathname;
21358
24644
  if (!isLoopbackHost(req.headers.host)) {
21359
24645
  res.writeHead(403, { "Content-Type": "text/plain" });
21360
24646
  res.end("Forbidden");
@@ -21388,9 +24674,9 @@ var httpServer = http.createServer((req, res) => {
21388
24674
  res.end("Bad path");
21389
24675
  return;
21390
24676
  }
21391
- const filePath = path2.resolve(LOCAL_ASSETS_DIR, filename);
21392
- const inRoot = filePath === LOCAL_ASSETS_DIR || filePath.startsWith(LOCAL_ASSETS_DIR + path2.sep);
21393
- if (inRoot && fs2.existsSync(filePath) && fs2.statSync(filePath).isFile()) {
24677
+ const filePath = path3.resolve(LOCAL_ASSETS_DIR, filename);
24678
+ const inRoot = filePath === LOCAL_ASSETS_DIR || filePath.startsWith(LOCAL_ASSETS_DIR + path3.sep);
24679
+ if (inRoot && fs3.existsSync(filePath) && fs3.statSync(filePath).isFile()) {
21394
24680
  serveFile(req, res, filePath);
21395
24681
  } else {
21396
24682
  res.writeHead(404, { "Content-Type": "text/plain" });
@@ -21475,9 +24761,24 @@ function explainTabError(error2) {
21475
24761
  function sendJson(ws, message) {
21476
24762
  if (ws.readyState === import_websocket.default.OPEN) ws.send(JSON.stringify(message));
21477
24763
  }
24764
+ async function answerService(ws, message) {
24765
+ const { id, action, params = {} } = message;
24766
+ try {
24767
+ let result;
24768
+ if (action === "list") result = await listServices();
24769
+ else if (action === "call") result = await callService(String(params.server), String(params.tool), params.args ?? {});
24770
+ else if (action === "download") {
24771
+ const saved = await downloadToAssets(LOCAL_ASSETS_DIR, String(params.url), typeof params.name === "string" ? params.name : void 0);
24772
+ result = { ...saved, mediaUrl: mediaUrl(saved.rel) };
24773
+ } else throw new Error(`Unknown service action: ${action}`);
24774
+ sendJson(ws, { type: "serviceReply", id, result });
24775
+ } catch (err) {
24776
+ sendJson(ws, { type: "serviceReply", id, error: err?.message ?? String(err) });
24777
+ }
24778
+ }
21478
24779
  wss.on("connection", (ws, req) => {
21479
- const url = req.url || "/";
21480
- if (url.startsWith("/controller")) {
24780
+ const url2 = req.url || "/";
24781
+ if (url2.startsWith("/controller")) {
21481
24782
  console.error("[GoatEdit MCP] Controller client connected");
21482
24783
  controllerSockets.add(ws);
21483
24784
  ws.on("message", async (data) => {
@@ -21527,6 +24828,10 @@ wss.on("connection", (ws, req) => {
21527
24828
  for (const controller2 of controllerSockets) sendJson(controller2, message);
21528
24829
  return;
21529
24830
  }
24831
+ if (message.type === "service") {
24832
+ void answerService(ws, message);
24833
+ return;
24834
+ }
21530
24835
  if (message.id === void 0 || message.result === void 0 && message.error === void 0) return;
21531
24836
  const key = String(message.id);
21532
24837
  const pending = pendingRequests.get(key);
@@ -21590,7 +24895,7 @@ function connectUpstream() {
21590
24895
  upstreamReady = new Promise((resolve, reject) => {
21591
24896
  let token;
21592
24897
  try {
21593
- token = process.env.GOATEDIT_CONTROLLER_TOKEN || fs2.readFileSync(CONTROLLER_TOKEN_FILE, "utf8").trim();
24898
+ token = process.env.GOATEDIT_CONTROLLER_TOKEN || fs3.readFileSync(CONTROLLER_TOKEN_FILE, "utf8").trim();
21594
24899
  } catch {
21595
24900
  reject(new Error(notConnectedMessage()));
21596
24901
  return;
@@ -21636,7 +24941,7 @@ async function ensureTransport() {
21636
24941
  }
21637
24942
  function sendUpstream(method, params, projectId) {
21638
24943
  return connectUpstream().then((ws) => new Promise((resolve, reject) => {
21639
- const id = crypto.randomUUID();
24944
+ const id = crypto2.randomUUID();
21640
24945
  const timeoutId = setTimeout(() => {
21641
24946
  upstreamPending.delete(id);
21642
24947
  reject(new Error(`Request timed out: ${method}`));
@@ -21650,7 +24955,7 @@ async function sendToBrowser(method, params = {}, projectId) {
21650
24955
  if (!ownsPort) return sendUpstream(method, params, projectId ?? chosenProjectId);
21651
24956
  const tab = resolveTab(projectId);
21652
24957
  return new Promise((resolve, reject) => {
21653
- const id = crypto.randomUUID();
24958
+ const id = crypto2.randomUUID();
21654
24959
  const timeoutId = setTimeout(() => {
21655
24960
  pendingRequests.delete(id);
21656
24961
  reject(new Error(`Request timed out after ${REQUEST_TIMEOUT_MS / 1e3}s: ${method}. Call get_timeline to see whether it landed.`));