goatedit-mcp 1.1.9 → 1.1.10

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 +3472 -189
  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
@@ -20855,19 +21550,147 @@ var BASE_TOOLS = [
20855
21550
  description: "Re-apply the last undone edit.",
20856
21551
  inputSchema: { type: "object", properties: {} },
20857
21552
  method: "redo"
20858
- }
20859
- ];
20860
- var SEQUENCE_EDITS = /* @__PURE__ */ new Set([
20861
- "addClip",
20862
- "addClips",
20863
- "addTextClip",
20864
- "updateTextClip",
20865
- "addShapeClip",
20866
- "addAdjustmentLayer",
20867
- "addTitleCard",
20868
- "insertRipple",
20869
- "setClipAudio",
20870
- "setClipTransform",
21553
+ },
21554
+ {
21555
+ name: "studio_tasks",
21556
+ 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.',
21557
+ inputSchema: {
21558
+ type: "object",
21559
+ properties: {
21560
+ runId: str("Only this run. Omit for every run in the project."),
21561
+ detail: bool("Include each write task's role, inputs and previous draft (default true). False lists the tasks only.")
21562
+ }
21563
+ },
21564
+ method: "getStudioTasks"
21565
+ },
21566
+ {
21567
+ name: "studio_claim",
21568
+ 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.',
21569
+ inputSchema: {
21570
+ type: "object",
21571
+ properties: {
21572
+ runId: str("The run, from studio_tasks."),
21573
+ stage: str('The stage id, from studio_tasks (e.g. "script").'),
21574
+ agent: str("Who is doing it, shown in the panel.")
21575
+ },
21576
+ required: ["runId", "stage", "agent"]
21577
+ },
21578
+ method: "studioClaim"
21579
+ },
21580
+ {
21581
+ name: "studio_submit",
21582
+ 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.",
21583
+ inputSchema: {
21584
+ type: "object",
21585
+ properties: {
21586
+ runId: str("The run, from studio_tasks."),
21587
+ stage: str("The stage id."),
21588
+ document: { type: "object", description: "The stage's document, in the shape its role card gives." },
21589
+ agent: str("Who wrote it, as in studio_claim.")
21590
+ },
21591
+ required: ["runId", "stage", "document"]
21592
+ },
21593
+ method: "studioSubmit"
21594
+ },
21595
+ {
21596
+ name: "studio_run_stage",
21597
+ 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.`,
21598
+ inputSchema: {
21599
+ type: "object",
21600
+ properties: {
21601
+ runId: str("The run, from studio_tasks."),
21602
+ stage: str("The stage id.")
21603
+ },
21604
+ required: ["runId", "stage"]
21605
+ },
21606
+ method: "studioRunStage"
21607
+ },
21608
+ {
21609
+ name: "studio_start_run",
21610
+ 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.`,
21611
+ inputSchema: {
21612
+ type: "object",
21613
+ properties: {
21614
+ title: str("What the video is, in a few words."),
21615
+ workflow: str('A workflow id or name from the Studio panel: "outside" (default), "guided", "autopilot", "hands-on", or one the user saved.')
21616
+ },
21617
+ required: ["title"]
21618
+ },
21619
+ method: "studioStartRun"
21620
+ },
21621
+ {
21622
+ name: "studio_workflows",
21623
+ 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.`,
21624
+ inputSchema: {
21625
+ type: "object",
21626
+ properties: {
21627
+ workflow: str('A workflow id or name to see stage by stage. Omit for the list, with the "outside" workflow in full.')
21628
+ }
21629
+ },
21630
+ method: "studioWorkflows"
21631
+ },
21632
+ {
21633
+ name: "studio_save_workflow",
21634
+ 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.`,
21635
+ inputSchema: {
21636
+ type: "object",
21637
+ properties: {
21638
+ workflow: {
21639
+ type: "object",
21640
+ description: "The workflow.",
21641
+ properties: {
21642
+ name: str('What the person will see, e.g. "Avatar reels".'),
21643
+ from: str('The workflow to start from, by id or name (default "outside").'),
21644
+ stages: {
21645
+ type: "object",
21646
+ 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.',
21647
+ additionalProperties: { type: "object" }
21648
+ },
21649
+ add: {
21650
+ type: "array",
21651
+ 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? }.',
21652
+ items: { type: "object" }
21653
+ }
21654
+ },
21655
+ required: ["name"]
21656
+ }
21657
+ },
21658
+ required: ["workflow"]
21659
+ },
21660
+ method: "studioSaveWorkflow"
21661
+ },
21662
+ {
21663
+ name: "studio_start_batch",
21664
+ 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.`,
21665
+ inputSchema: {
21666
+ type: "object",
21667
+ properties: {
21668
+ title: str('The series name, e.g. "Health tips".'),
21669
+ series: str("The series: brand, audience, tone, platform. Every reel's brief is written from it."),
21670
+ reels: {
21671
+ type: "array",
21672
+ description: "One per reel: { name, script (word for word), avatar? (the HeyGen avatar that speaks it) }.",
21673
+ items: { type: "object" }
21674
+ },
21675
+ text: str("Instead of reels: the scripts as the person pasted them."),
21676
+ workflow: str('A workflow id or name (default "outside"); studio_save_workflow makes one.')
21677
+ },
21678
+ required: ["title"]
21679
+ },
21680
+ method: "studioStartBatch"
21681
+ }
21682
+ ];
21683
+ var SEQUENCE_EDITS = /* @__PURE__ */ new Set([
21684
+ "addClip",
21685
+ "addClips",
21686
+ "addTextClip",
21687
+ "updateTextClip",
21688
+ "addShapeClip",
21689
+ "addAdjustmentLayer",
21690
+ "addTitleCard",
21691
+ "insertRipple",
21692
+ "setClipAudio",
21693
+ "setClipTransform",
20871
21694
  "setUltraKey",
20872
21695
  "setTrackMatte",
20873
21696
  "setShapeGradient",
@@ -20982,122 +21805,2563 @@ function typeError(key, schema, value) {
20982
21805
  if (schema.enum && !schema.enum.includes(value)) {
20983
21806
  return `Argument "${key}" must be one of: ${schema.enum.join(", ")}`;
20984
21807
  }
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}`;
21808
+ return null;
21809
+ }
21810
+ function validateArgs(tool, args) {
21811
+ for (const key of tool.inputSchema.required ?? []) {
21812
+ if (args[key] === void 0 || args[key] === null) return `Missing required argument: ${key}`;
21813
+ }
21814
+ const known = Object.keys(tool.inputSchema.properties);
21815
+ for (const [key, value] of Object.entries(args)) {
21816
+ if (value === void 0) continue;
21817
+ const schema = tool.inputSchema.properties[key];
21818
+ if (!schema) {
21819
+ 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];
21820
+ return near ? `Unknown argument "${key}" for ${tool.name}. Did you mean "${near.candidate}"?` : `Unknown argument "${key}" for ${tool.name}. Accepted: ${known.join(", ") || "(none)"}`;
21821
+ }
21822
+ if (value === null) continue;
21823
+ const problem = typeError(key, schema, value);
21824
+ if (problem) return problem;
21825
+ }
21826
+ return null;
21827
+ }
21828
+
21829
+ // ../api/_lib/mcp-content.ts
21830
+ var isImage = (v) => !!v && typeof v === "object" && typeof v.data === "string" && typeof v.mimeType === "string";
21831
+ function toContent(result) {
21832
+ if (!result || typeof result !== "object") {
21833
+ return [{ type: "text", text: JSON.stringify(result) ?? "null" }];
21834
+ }
21835
+ const { _image, _images, _file: _file2, ...rest } = result;
21836
+ 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.";
21837
+ const blocks = [];
21838
+ const captions = [];
21839
+ for (const candidate of [_image, ...Array.isArray(_images) ? _images : []]) {
21840
+ if (!isImage(candidate)) continue;
21841
+ blocks.push({ type: "image", data: candidate.data, mimeType: candidate.mimeType });
21842
+ if (typeof candidate.caption === "string") captions.push(candidate.caption);
21843
+ }
21844
+ const text = captions.length ? JSON.stringify({ ...rest, frameCaptions: captions }) : JSON.stringify(Array.isArray(result) ? result : rest);
21845
+ blocks.push({ type: "text", text });
21846
+ return blocks;
21847
+ }
21848
+
21849
+ // src/find-local-file.ts
21850
+ import fs from "fs";
21851
+ import path from "path";
21852
+ function findLocalFile(root, wanted, maxDepth) {
21853
+ const name = wanted.trim();
21854
+ if (!name || !fs.existsSync(root)) return null;
21855
+ if (name.includes("/") || name.includes(path.sep)) {
21856
+ const full = path.resolve(root, name);
21857
+ if (!full.startsWith(root + path.sep)) return null;
21858
+ try {
21859
+ return fs.statSync(full).isFile() ? full : null;
21860
+ } catch {
21861
+ return null;
21862
+ }
21863
+ }
21864
+ const target = name.toLowerCase();
21865
+ let level = [root];
21866
+ for (let depth = 0; depth <= maxDepth && level.length; depth++) {
21867
+ const hits = [];
21868
+ const next = [];
21869
+ for (const dir of level) {
21870
+ let entries;
21871
+ try {
21872
+ entries = fs.readdirSync(dir, { withFileTypes: true });
21873
+ } catch {
21874
+ continue;
21875
+ }
21876
+ for (const entry of entries) {
21877
+ if (entry.name.startsWith(".")) continue;
21878
+ const full = path.join(dir, entry.name);
21879
+ if (entry.isDirectory()) next.push(full);
21880
+ else if (entry.isFile() && entry.name.toLowerCase() === target) hits.push(full);
21881
+ }
21882
+ }
21883
+ if (hits.length > 1) {
21884
+ throw new Error(
21885
+ `Several files are named "${name}": ${hits.map((h) => path.relative(root, h)).sort().join(", ")}. Pass one of these paths as filename.`
21886
+ );
21887
+ }
21888
+ if (hits.length === 1) return hits[0];
21889
+ level = next;
21890
+ }
21891
+ return null;
21892
+ }
21893
+
21894
+ // src/run-refs.ts
21895
+ function resolveRefs(value, refs) {
21896
+ if (typeof value === "string") {
21897
+ const m = /^\$([A-Za-z_][\w-]*)((?:\.[^.]+)*)$/.exec(value);
21898
+ if (!m || !refs.has(m[1])) return value;
21899
+ let x = refs.get(m[1]);
21900
+ for (const key of m[2].split(".").slice(1)) {
21901
+ x = x && typeof x === "object" ? x[key] : void 0;
21902
+ 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)}`);
21903
+ }
21904
+ return x;
21905
+ }
21906
+ if (Array.isArray(value)) return value.map((v) => resolveRefs(v, refs));
21907
+ if (value && typeof value === "object") {
21908
+ return Object.fromEntries(Object.entries(value).map(([k, v]) => [k, resolveRefs(v, refs)]));
21909
+ }
21910
+ return value;
21911
+ }
21912
+ function withRunProject(stepArgs, projectId) {
21913
+ if (typeof projectId !== "string" || !projectId || typeof stepArgs.projectId === "string") return stepArgs;
21914
+ return { ...stepArgs, projectId };
21915
+ }
21916
+
21917
+ // src/tab-registry.ts
21918
+ function indexTabs(reports, isOpen) {
21919
+ const index = /* @__PURE__ */ new Map();
21920
+ for (const r of [...reports].sort((a, b) => a.at - b.at)) {
21921
+ if (isOpen(r.socket)) index.set(r.projectId, r);
21922
+ }
21923
+ return index;
21924
+ }
21925
+
21926
+ // node_modules/@modelcontextprotocol/sdk/dist/esm/experimental/tasks/client.js
21927
+ var ExperimentalClientTasks = class {
21928
+ constructor(_client) {
21929
+ this._client = _client;
21930
+ }
21931
+ /**
21932
+ * Calls a tool and returns an AsyncGenerator that yields response messages.
21933
+ * The generator is guaranteed to end with either a 'result' or 'error' message.
21934
+ *
21935
+ * This method provides streaming access to tool execution, allowing you to
21936
+ * observe intermediate task status updates for long-running tool calls.
21937
+ * Automatically validates structured output if the tool has an outputSchema.
21938
+ *
21939
+ * @example
21940
+ * ```typescript
21941
+ * const stream = client.experimental.tasks.callToolStream({ name: 'myTool', arguments: {} });
21942
+ * for await (const message of stream) {
21943
+ * switch (message.type) {
21944
+ * case 'taskCreated':
21945
+ * console.log('Tool execution started:', message.task.taskId);
21946
+ * break;
21947
+ * case 'taskStatus':
21948
+ * console.log('Tool status:', message.task.status);
21949
+ * break;
21950
+ * case 'result':
21951
+ * console.log('Tool result:', message.result);
21952
+ * break;
21953
+ * case 'error':
21954
+ * console.error('Tool error:', message.error);
21955
+ * break;
21956
+ * }
21957
+ * }
21958
+ * ```
21959
+ *
21960
+ * @param params - Tool call parameters (name and arguments)
21961
+ * @param resultSchema - Zod schema for validating the result (defaults to CallToolResultSchema)
21962
+ * @param options - Optional request options (timeout, signal, task creation params, etc.)
21963
+ * @returns AsyncGenerator that yields ResponseMessage objects
21964
+ *
21965
+ * @experimental
21966
+ */
21967
+ async *callToolStream(params, resultSchema = CallToolResultSchema, options) {
21968
+ const clientInternal = this._client;
21969
+ const optionsWithTask = {
21970
+ ...options,
21971
+ // We check if the tool is known to be a task during auto-configuration, but assume
21972
+ // the caller knows what they're doing if they pass this explicitly
21973
+ task: options?.task ?? (clientInternal.isToolTask(params.name) ? {} : void 0)
21974
+ };
21975
+ const stream = clientInternal.requestStream({ method: "tools/call", params }, resultSchema, optionsWithTask);
21976
+ const validator = clientInternal.getToolOutputValidator(params.name);
21977
+ for await (const message of stream) {
21978
+ if (message.type === "result" && validator) {
21979
+ const result = message.result;
21980
+ if (!result.structuredContent && !result.isError) {
21981
+ yield {
21982
+ type: "error",
21983
+ error: new McpError(ErrorCode.InvalidRequest, `Tool ${params.name} has an output schema but did not return structured content`)
21984
+ };
21985
+ return;
21986
+ }
21987
+ if (result.structuredContent) {
21988
+ try {
21989
+ const validationResult = validator(result.structuredContent);
21990
+ if (!validationResult.valid) {
21991
+ yield {
21992
+ type: "error",
21993
+ error: new McpError(ErrorCode.InvalidParams, `Structured content does not match the tool's output schema: ${validationResult.errorMessage}`)
21994
+ };
21995
+ return;
21996
+ }
21997
+ } catch (error2) {
21998
+ if (error2 instanceof McpError) {
21999
+ yield { type: "error", error: error2 };
22000
+ return;
22001
+ }
22002
+ yield {
22003
+ type: "error",
22004
+ error: new McpError(ErrorCode.InvalidParams, `Failed to validate structured content: ${error2 instanceof Error ? error2.message : String(error2)}`)
22005
+ };
22006
+ return;
22007
+ }
22008
+ }
22009
+ }
22010
+ yield message;
22011
+ }
22012
+ }
22013
+ /**
22014
+ * Gets the current status of a task.
22015
+ *
22016
+ * @param taskId - The task identifier
22017
+ * @param options - Optional request options
22018
+ * @returns The task status
22019
+ *
22020
+ * @experimental
22021
+ */
22022
+ async getTask(taskId, options) {
22023
+ return this._client.getTask({ taskId }, options);
22024
+ }
22025
+ /**
22026
+ * Retrieves the result of a completed task.
22027
+ *
22028
+ * @param taskId - The task identifier
22029
+ * @param resultSchema - Zod schema for validating the result
22030
+ * @param options - Optional request options
22031
+ * @returns The task result
22032
+ *
22033
+ * @experimental
22034
+ */
22035
+ async getTaskResult(taskId, resultSchema, options) {
22036
+ return this._client.getTaskResult({ taskId }, resultSchema, options);
22037
+ }
22038
+ /**
22039
+ * Lists tasks with optional pagination.
22040
+ *
22041
+ * @param cursor - Optional pagination cursor
22042
+ * @param options - Optional request options
22043
+ * @returns List of tasks with optional next cursor
22044
+ *
22045
+ * @experimental
22046
+ */
22047
+ async listTasks(cursor, options) {
22048
+ return this._client.listTasks(cursor ? { cursor } : void 0, options);
22049
+ }
22050
+ /**
22051
+ * Cancels a running task.
22052
+ *
22053
+ * @param taskId - The task identifier
22054
+ * @param options - Optional request options
22055
+ *
22056
+ * @experimental
22057
+ */
22058
+ async cancelTask(taskId, options) {
22059
+ return this._client.cancelTask({ taskId }, options);
22060
+ }
22061
+ /**
22062
+ * Sends a request and returns an AsyncGenerator that yields response messages.
22063
+ * The generator is guaranteed to end with either a 'result' or 'error' message.
22064
+ *
22065
+ * This method provides streaming access to request processing, allowing you to
22066
+ * observe intermediate task status updates for task-augmented requests.
22067
+ *
22068
+ * @param request - The request to send
22069
+ * @param resultSchema - Zod schema for validating the result
22070
+ * @param options - Optional request options (timeout, signal, task creation params, etc.)
22071
+ * @returns AsyncGenerator that yields ResponseMessage objects
22072
+ *
22073
+ * @experimental
22074
+ */
22075
+ requestStream(request, resultSchema, options) {
22076
+ return this._client.requestStream(request, resultSchema, options);
22077
+ }
22078
+ };
22079
+
22080
+ // node_modules/@modelcontextprotocol/sdk/dist/esm/client/index.js
22081
+ function applyElicitationDefaults(schema, data) {
22082
+ if (!schema || data === null || typeof data !== "object")
22083
+ return;
22084
+ if (schema.type === "object" && schema.properties && typeof schema.properties === "object") {
22085
+ const obj = data;
22086
+ const props = schema.properties;
22087
+ for (const key of Object.keys(props)) {
22088
+ const propSchema = props[key];
22089
+ if (obj[key] === void 0 && Object.prototype.hasOwnProperty.call(propSchema, "default")) {
22090
+ obj[key] = propSchema.default;
22091
+ }
22092
+ if (obj[key] !== void 0) {
22093
+ applyElicitationDefaults(propSchema, obj[key]);
22094
+ }
22095
+ }
22096
+ }
22097
+ if (Array.isArray(schema.anyOf)) {
22098
+ for (const sub of schema.anyOf) {
22099
+ if (typeof sub !== "boolean") {
22100
+ applyElicitationDefaults(sub, data);
22101
+ }
22102
+ }
22103
+ }
22104
+ if (Array.isArray(schema.oneOf)) {
22105
+ for (const sub of schema.oneOf) {
22106
+ if (typeof sub !== "boolean") {
22107
+ applyElicitationDefaults(sub, data);
22108
+ }
22109
+ }
22110
+ }
22111
+ }
22112
+ function getSupportedElicitationModes(capabilities) {
22113
+ if (!capabilities) {
22114
+ return { supportsFormMode: false, supportsUrlMode: false };
22115
+ }
22116
+ const hasFormCapability = capabilities.form !== void 0;
22117
+ const hasUrlCapability = capabilities.url !== void 0;
22118
+ const supportsFormMode = hasFormCapability || !hasFormCapability && !hasUrlCapability;
22119
+ const supportsUrlMode = hasUrlCapability;
22120
+ return { supportsFormMode, supportsUrlMode };
22121
+ }
22122
+ var Client = class extends Protocol {
22123
+ /**
22124
+ * Initializes this client with the given name and version information.
22125
+ */
22126
+ constructor(_clientInfo, options) {
22127
+ super(options);
22128
+ this._clientInfo = _clientInfo;
22129
+ this._cachedToolOutputValidators = /* @__PURE__ */ new Map();
22130
+ this._cachedKnownTaskTools = /* @__PURE__ */ new Set();
22131
+ this._cachedRequiredTaskTools = /* @__PURE__ */ new Set();
22132
+ this._listChangedDebounceTimers = /* @__PURE__ */ new Map();
22133
+ this._capabilities = options?.capabilities ?? {};
22134
+ this._jsonSchemaValidator = options?.jsonSchemaValidator ?? new AjvJsonSchemaValidator();
22135
+ if (options?.listChanged) {
22136
+ this._pendingListChangedConfig = options.listChanged;
22137
+ }
22138
+ }
22139
+ /**
22140
+ * Set up handlers for list changed notifications based on config and server capabilities.
22141
+ * This should only be called after initialization when server capabilities are known.
22142
+ * Handlers are silently skipped if the server doesn't advertise the corresponding listChanged capability.
22143
+ * @internal
22144
+ */
22145
+ _setupListChangedHandlers(config2) {
22146
+ if (config2.tools && this._serverCapabilities?.tools?.listChanged) {
22147
+ this._setupListChangedHandler("tools", ToolListChangedNotificationSchema, config2.tools, async () => {
22148
+ const result = await this.listTools();
22149
+ return result.tools;
22150
+ });
22151
+ }
22152
+ if (config2.prompts && this._serverCapabilities?.prompts?.listChanged) {
22153
+ this._setupListChangedHandler("prompts", PromptListChangedNotificationSchema, config2.prompts, async () => {
22154
+ const result = await this.listPrompts();
22155
+ return result.prompts;
22156
+ });
22157
+ }
22158
+ if (config2.resources && this._serverCapabilities?.resources?.listChanged) {
22159
+ this._setupListChangedHandler("resources", ResourceListChangedNotificationSchema, config2.resources, async () => {
22160
+ const result = await this.listResources();
22161
+ return result.resources;
22162
+ });
22163
+ }
22164
+ }
22165
+ /**
22166
+ * Access experimental features.
22167
+ *
22168
+ * WARNING: These APIs are experimental and may change without notice.
22169
+ *
22170
+ * @experimental
22171
+ */
22172
+ get experimental() {
22173
+ if (!this._experimental) {
22174
+ this._experimental = {
22175
+ tasks: new ExperimentalClientTasks(this)
22176
+ };
22177
+ }
22178
+ return this._experimental;
22179
+ }
22180
+ /**
22181
+ * Registers new capabilities. This can only be called before connecting to a transport.
22182
+ *
22183
+ * The new capabilities will be merged with any existing capabilities previously given (e.g., at initialization).
22184
+ */
22185
+ registerCapabilities(capabilities) {
22186
+ if (this.transport) {
22187
+ throw new Error("Cannot register capabilities after connecting to transport");
22188
+ }
22189
+ this._capabilities = mergeCapabilities(this._capabilities, capabilities);
22190
+ }
22191
+ /**
22192
+ * Override request handler registration to enforce client-side validation for elicitation.
22193
+ */
22194
+ setRequestHandler(requestSchema, handler) {
22195
+ const shape = getObjectShape(requestSchema);
22196
+ const methodSchema = shape?.method;
22197
+ if (!methodSchema) {
22198
+ throw new Error("Schema is missing a method literal");
22199
+ }
22200
+ let methodValue;
22201
+ if (isZ4Schema(methodSchema)) {
22202
+ const v4Schema = methodSchema;
22203
+ const v4Def = v4Schema._zod?.def;
22204
+ methodValue = v4Def?.value ?? v4Schema.value;
22205
+ } else {
22206
+ const v3Schema = methodSchema;
22207
+ const legacyDef = v3Schema._def;
22208
+ methodValue = legacyDef?.value ?? v3Schema.value;
22209
+ }
22210
+ if (typeof methodValue !== "string") {
22211
+ throw new Error("Schema method literal must be a string");
22212
+ }
22213
+ const method = methodValue;
22214
+ if (method === "elicitation/create") {
22215
+ const wrappedHandler = async (request, extra) => {
22216
+ const validatedRequest = safeParse2(ElicitRequestSchema, request);
22217
+ if (!validatedRequest.success) {
22218
+ const errorMessage = validatedRequest.error instanceof Error ? validatedRequest.error.message : String(validatedRequest.error);
22219
+ throw new McpError(ErrorCode.InvalidParams, `Invalid elicitation request: ${errorMessage}`);
22220
+ }
22221
+ const { params } = validatedRequest.data;
22222
+ params.mode = params.mode ?? "form";
22223
+ const { supportsFormMode, supportsUrlMode } = getSupportedElicitationModes(this._capabilities.elicitation);
22224
+ if (params.mode === "form" && !supportsFormMode) {
22225
+ throw new McpError(ErrorCode.InvalidParams, "Client does not support form-mode elicitation requests");
22226
+ }
22227
+ if (params.mode === "url" && !supportsUrlMode) {
22228
+ throw new McpError(ErrorCode.InvalidParams, "Client does not support URL-mode elicitation requests");
22229
+ }
22230
+ const result = await Promise.resolve(handler(request, extra));
22231
+ if (params.task) {
22232
+ const taskValidationResult = safeParse2(CreateTaskResultSchema, result);
22233
+ if (!taskValidationResult.success) {
22234
+ const errorMessage = taskValidationResult.error instanceof Error ? taskValidationResult.error.message : String(taskValidationResult.error);
22235
+ throw new McpError(ErrorCode.InvalidParams, `Invalid task creation result: ${errorMessage}`);
22236
+ }
22237
+ return taskValidationResult.data;
22238
+ }
22239
+ const validationResult = safeParse2(ElicitResultSchema, result);
22240
+ if (!validationResult.success) {
22241
+ const errorMessage = validationResult.error instanceof Error ? validationResult.error.message : String(validationResult.error);
22242
+ throw new McpError(ErrorCode.InvalidParams, `Invalid elicitation result: ${errorMessage}`);
22243
+ }
22244
+ const validatedResult = validationResult.data;
22245
+ const requestedSchema = params.mode === "form" ? params.requestedSchema : void 0;
22246
+ if (params.mode === "form" && validatedResult.action === "accept" && validatedResult.content && requestedSchema) {
22247
+ if (this._capabilities.elicitation?.form?.applyDefaults) {
22248
+ try {
22249
+ applyElicitationDefaults(requestedSchema, validatedResult.content);
22250
+ } catch {
22251
+ }
22252
+ }
22253
+ }
22254
+ return validatedResult;
22255
+ };
22256
+ return super.setRequestHandler(requestSchema, wrappedHandler);
22257
+ }
22258
+ if (method === "sampling/createMessage") {
22259
+ const wrappedHandler = async (request, extra) => {
22260
+ const validatedRequest = safeParse2(CreateMessageRequestSchema, request);
22261
+ if (!validatedRequest.success) {
22262
+ const errorMessage = validatedRequest.error instanceof Error ? validatedRequest.error.message : String(validatedRequest.error);
22263
+ throw new McpError(ErrorCode.InvalidParams, `Invalid sampling request: ${errorMessage}`);
22264
+ }
22265
+ const { params } = validatedRequest.data;
22266
+ const result = await Promise.resolve(handler(request, extra));
22267
+ if (params.task) {
22268
+ const taskValidationResult = safeParse2(CreateTaskResultSchema, result);
22269
+ if (!taskValidationResult.success) {
22270
+ const errorMessage = taskValidationResult.error instanceof Error ? taskValidationResult.error.message : String(taskValidationResult.error);
22271
+ throw new McpError(ErrorCode.InvalidParams, `Invalid task creation result: ${errorMessage}`);
22272
+ }
22273
+ return taskValidationResult.data;
22274
+ }
22275
+ const hasTools = params.tools || params.toolChoice;
22276
+ const resultSchema = hasTools ? CreateMessageResultWithToolsSchema : CreateMessageResultSchema;
22277
+ const validationResult = safeParse2(resultSchema, result);
22278
+ if (!validationResult.success) {
22279
+ const errorMessage = validationResult.error instanceof Error ? validationResult.error.message : String(validationResult.error);
22280
+ throw new McpError(ErrorCode.InvalidParams, `Invalid sampling result: ${errorMessage}`);
22281
+ }
22282
+ return validationResult.data;
22283
+ };
22284
+ return super.setRequestHandler(requestSchema, wrappedHandler);
22285
+ }
22286
+ return super.setRequestHandler(requestSchema, handler);
22287
+ }
22288
+ assertCapability(capability, method) {
22289
+ if (!this._serverCapabilities?.[capability]) {
22290
+ throw new Error(`Server does not support ${capability} (required for ${method})`);
22291
+ }
22292
+ }
22293
+ async connect(transport, options) {
22294
+ await super.connect(transport);
22295
+ if (transport.sessionId !== void 0) {
22296
+ return;
22297
+ }
22298
+ try {
22299
+ const result = await this.request({
22300
+ method: "initialize",
22301
+ params: {
22302
+ protocolVersion: LATEST_PROTOCOL_VERSION,
22303
+ capabilities: this._capabilities,
22304
+ clientInfo: this._clientInfo
22305
+ }
22306
+ }, InitializeResultSchema, options);
22307
+ if (result === void 0) {
22308
+ throw new Error(`Server sent invalid initialize result: ${result}`);
22309
+ }
22310
+ if (!SUPPORTED_PROTOCOL_VERSIONS.includes(result.protocolVersion)) {
22311
+ throw new Error(`Server's protocol version is not supported: ${result.protocolVersion}`);
22312
+ }
22313
+ this._serverCapabilities = result.capabilities;
22314
+ this._serverVersion = result.serverInfo;
22315
+ if (transport.setProtocolVersion) {
22316
+ transport.setProtocolVersion(result.protocolVersion);
22317
+ }
22318
+ this._instructions = result.instructions;
22319
+ await this.notification({
22320
+ method: "notifications/initialized"
22321
+ });
22322
+ if (this._pendingListChangedConfig) {
22323
+ this._setupListChangedHandlers(this._pendingListChangedConfig);
22324
+ this._pendingListChangedConfig = void 0;
22325
+ }
22326
+ } catch (error2) {
22327
+ void this.close();
22328
+ throw error2;
22329
+ }
22330
+ }
22331
+ /**
22332
+ * After initialization has completed, this will be populated with the server's reported capabilities.
22333
+ */
22334
+ getServerCapabilities() {
22335
+ return this._serverCapabilities;
22336
+ }
22337
+ /**
22338
+ * After initialization has completed, this will be populated with information about the server's name and version.
22339
+ */
22340
+ getServerVersion() {
22341
+ return this._serverVersion;
22342
+ }
22343
+ /**
22344
+ * After initialization has completed, this may be populated with information about the server's instructions.
22345
+ */
22346
+ getInstructions() {
22347
+ return this._instructions;
22348
+ }
22349
+ assertCapabilityForMethod(method) {
22350
+ switch (method) {
22351
+ case "logging/setLevel":
22352
+ if (!this._serverCapabilities?.logging) {
22353
+ throw new Error(`Server does not support logging (required for ${method})`);
22354
+ }
22355
+ break;
22356
+ case "prompts/get":
22357
+ case "prompts/list":
22358
+ if (!this._serverCapabilities?.prompts) {
22359
+ throw new Error(`Server does not support prompts (required for ${method})`);
22360
+ }
22361
+ break;
22362
+ case "resources/list":
22363
+ case "resources/templates/list":
22364
+ case "resources/read":
22365
+ case "resources/subscribe":
22366
+ case "resources/unsubscribe":
22367
+ if (!this._serverCapabilities?.resources) {
22368
+ throw new Error(`Server does not support resources (required for ${method})`);
22369
+ }
22370
+ if (method === "resources/subscribe" && !this._serverCapabilities.resources.subscribe) {
22371
+ throw new Error(`Server does not support resource subscriptions (required for ${method})`);
22372
+ }
22373
+ break;
22374
+ case "tools/call":
22375
+ case "tools/list":
22376
+ if (!this._serverCapabilities?.tools) {
22377
+ throw new Error(`Server does not support tools (required for ${method})`);
22378
+ }
22379
+ break;
22380
+ case "completion/complete":
22381
+ if (!this._serverCapabilities?.completions) {
22382
+ throw new Error(`Server does not support completions (required for ${method})`);
22383
+ }
22384
+ break;
22385
+ case "initialize":
22386
+ break;
22387
+ case "ping":
22388
+ break;
22389
+ }
22390
+ }
22391
+ assertNotificationCapability(method) {
22392
+ switch (method) {
22393
+ case "notifications/roots/list_changed":
22394
+ if (!this._capabilities.roots?.listChanged) {
22395
+ throw new Error(`Client does not support roots list changed notifications (required for ${method})`);
22396
+ }
22397
+ break;
22398
+ case "notifications/initialized":
22399
+ break;
22400
+ case "notifications/cancelled":
22401
+ break;
22402
+ case "notifications/progress":
22403
+ break;
22404
+ }
22405
+ }
22406
+ assertRequestHandlerCapability(method) {
22407
+ if (!this._capabilities) {
22408
+ return;
22409
+ }
22410
+ switch (method) {
22411
+ case "sampling/createMessage":
22412
+ if (!this._capabilities.sampling) {
22413
+ throw new Error(`Client does not support sampling capability (required for ${method})`);
22414
+ }
22415
+ break;
22416
+ case "elicitation/create":
22417
+ if (!this._capabilities.elicitation) {
22418
+ throw new Error(`Client does not support elicitation capability (required for ${method})`);
22419
+ }
22420
+ break;
22421
+ case "roots/list":
22422
+ if (!this._capabilities.roots) {
22423
+ throw new Error(`Client does not support roots capability (required for ${method})`);
22424
+ }
22425
+ break;
22426
+ case "tasks/get":
22427
+ case "tasks/list":
22428
+ case "tasks/result":
22429
+ case "tasks/cancel":
22430
+ if (!this._capabilities.tasks) {
22431
+ throw new Error(`Client does not support tasks capability (required for ${method})`);
22432
+ }
22433
+ break;
22434
+ case "ping":
22435
+ break;
22436
+ }
22437
+ }
22438
+ assertTaskCapability(method) {
22439
+ assertToolsCallTaskCapability(this._serverCapabilities?.tasks?.requests, method, "Server");
22440
+ }
22441
+ assertTaskHandlerCapability(method) {
22442
+ if (!this._capabilities) {
22443
+ return;
22444
+ }
22445
+ assertClientRequestTaskCapability(this._capabilities.tasks?.requests, method, "Client");
22446
+ }
22447
+ async ping(options) {
22448
+ return this.request({ method: "ping" }, EmptyResultSchema, options);
22449
+ }
22450
+ async complete(params, options) {
22451
+ return this.request({ method: "completion/complete", params }, CompleteResultSchema, options);
22452
+ }
22453
+ async setLoggingLevel(level, options) {
22454
+ return this.request({ method: "logging/setLevel", params: { level } }, EmptyResultSchema, options);
22455
+ }
22456
+ async getPrompt(params, options) {
22457
+ return this.request({ method: "prompts/get", params }, GetPromptResultSchema, options);
22458
+ }
22459
+ async listPrompts(params, options) {
22460
+ return this.request({ method: "prompts/list", params }, ListPromptsResultSchema, options);
22461
+ }
22462
+ async listResources(params, options) {
22463
+ return this.request({ method: "resources/list", params }, ListResourcesResultSchema, options);
22464
+ }
22465
+ async listResourceTemplates(params, options) {
22466
+ return this.request({ method: "resources/templates/list", params }, ListResourceTemplatesResultSchema, options);
22467
+ }
22468
+ async readResource(params, options) {
22469
+ return this.request({ method: "resources/read", params }, ReadResourceResultSchema, options);
22470
+ }
22471
+ async subscribeResource(params, options) {
22472
+ return this.request({ method: "resources/subscribe", params }, EmptyResultSchema, options);
22473
+ }
22474
+ async unsubscribeResource(params, options) {
22475
+ return this.request({ method: "resources/unsubscribe", params }, EmptyResultSchema, options);
22476
+ }
22477
+ /**
22478
+ * Calls a tool and waits for the result. Automatically validates structured output if the tool has an outputSchema.
22479
+ *
22480
+ * For task-based execution with streaming behavior, use client.experimental.tasks.callToolStream() instead.
22481
+ */
22482
+ async callTool(params, resultSchema = CallToolResultSchema, options) {
22483
+ if (this.isToolTaskRequired(params.name)) {
22484
+ throw new McpError(ErrorCode.InvalidRequest, `Tool "${params.name}" requires task-based execution. Use client.experimental.tasks.callToolStream() instead.`);
22485
+ }
22486
+ const result = await this.request({ method: "tools/call", params }, resultSchema, options);
22487
+ const validator = this.getToolOutputValidator(params.name);
22488
+ if (validator) {
22489
+ if (!result.structuredContent && !result.isError) {
22490
+ throw new McpError(ErrorCode.InvalidRequest, `Tool ${params.name} has an output schema but did not return structured content`);
22491
+ }
22492
+ if (result.structuredContent) {
22493
+ try {
22494
+ const validationResult = validator(result.structuredContent);
22495
+ if (!validationResult.valid) {
22496
+ throw new McpError(ErrorCode.InvalidParams, `Structured content does not match the tool's output schema: ${validationResult.errorMessage}`);
22497
+ }
22498
+ } catch (error2) {
22499
+ if (error2 instanceof McpError) {
22500
+ throw error2;
22501
+ }
22502
+ throw new McpError(ErrorCode.InvalidParams, `Failed to validate structured content: ${error2 instanceof Error ? error2.message : String(error2)}`);
22503
+ }
22504
+ }
22505
+ }
22506
+ return result;
22507
+ }
22508
+ isToolTask(toolName) {
22509
+ if (!this._serverCapabilities?.tasks?.requests?.tools?.call) {
22510
+ return false;
22511
+ }
22512
+ return this._cachedKnownTaskTools.has(toolName);
22513
+ }
22514
+ /**
22515
+ * Check if a tool requires task-based execution.
22516
+ * Unlike isToolTask which includes 'optional' tools, this only checks for 'required'.
22517
+ */
22518
+ isToolTaskRequired(toolName) {
22519
+ return this._cachedRequiredTaskTools.has(toolName);
22520
+ }
22521
+ /**
22522
+ * Cache validators for tool output schemas.
22523
+ * Called after listTools() to pre-compile validators for better performance.
22524
+ */
22525
+ cacheToolMetadata(tools) {
22526
+ this._cachedToolOutputValidators.clear();
22527
+ this._cachedKnownTaskTools.clear();
22528
+ this._cachedRequiredTaskTools.clear();
22529
+ for (const tool of tools) {
22530
+ if (tool.outputSchema) {
22531
+ const toolValidator = this._jsonSchemaValidator.getValidator(tool.outputSchema);
22532
+ this._cachedToolOutputValidators.set(tool.name, toolValidator);
22533
+ }
22534
+ const taskSupport = tool.execution?.taskSupport;
22535
+ if (taskSupport === "required" || taskSupport === "optional") {
22536
+ this._cachedKnownTaskTools.add(tool.name);
22537
+ }
22538
+ if (taskSupport === "required") {
22539
+ this._cachedRequiredTaskTools.add(tool.name);
22540
+ }
22541
+ }
22542
+ }
22543
+ /**
22544
+ * Get cached validator for a tool
22545
+ */
22546
+ getToolOutputValidator(toolName) {
22547
+ return this._cachedToolOutputValidators.get(toolName);
22548
+ }
22549
+ async listTools(params, options) {
22550
+ const result = await this.request({ method: "tools/list", params }, ListToolsResultSchema, options);
22551
+ this.cacheToolMetadata(result.tools);
22552
+ return result;
22553
+ }
22554
+ /**
22555
+ * Set up a single list changed handler.
22556
+ * @internal
22557
+ */
22558
+ _setupListChangedHandler(listType, notificationSchema, options, fetcher) {
22559
+ const parseResult = ListChangedOptionsBaseSchema.safeParse(options);
22560
+ if (!parseResult.success) {
22561
+ throw new Error(`Invalid ${listType} listChanged options: ${parseResult.error.message}`);
22562
+ }
22563
+ if (typeof options.onChanged !== "function") {
22564
+ throw new Error(`Invalid ${listType} listChanged options: onChanged must be a function`);
22565
+ }
22566
+ const { autoRefresh, debounceMs } = parseResult.data;
22567
+ const { onChanged } = options;
22568
+ const refresh = async () => {
22569
+ if (!autoRefresh) {
22570
+ onChanged(null, null);
22571
+ return;
22572
+ }
22573
+ try {
22574
+ const items = await fetcher();
22575
+ onChanged(null, items);
22576
+ } catch (e) {
22577
+ const error2 = e instanceof Error ? e : new Error(String(e));
22578
+ onChanged(error2, null);
22579
+ }
22580
+ };
22581
+ const handler = () => {
22582
+ if (debounceMs) {
22583
+ const existingTimer = this._listChangedDebounceTimers.get(listType);
22584
+ if (existingTimer) {
22585
+ clearTimeout(existingTimer);
22586
+ }
22587
+ const timer = setTimeout(refresh, debounceMs);
22588
+ this._listChangedDebounceTimers.set(listType, timer);
22589
+ } else {
22590
+ refresh();
22591
+ }
22592
+ };
22593
+ this.setNotificationHandler(notificationSchema, handler);
22594
+ }
22595
+ async sendRootsListChanged() {
22596
+ return this.notification({ method: "notifications/roots/list_changed" });
22597
+ }
22598
+ };
22599
+
22600
+ // node_modules/@modelcontextprotocol/sdk/dist/esm/client/stdio.js
22601
+ var import_cross_spawn = __toESM(require_cross_spawn(), 1);
22602
+ import process4 from "node:process";
22603
+ import { PassThrough } from "node:stream";
22604
+ var DEFAULT_INHERITED_ENV_VARS = process4.platform === "win32" ? [
22605
+ "APPDATA",
22606
+ "HOMEDRIVE",
22607
+ "HOMEPATH",
22608
+ "LOCALAPPDATA",
22609
+ "PATH",
22610
+ "PROCESSOR_ARCHITECTURE",
22611
+ "SYSTEMDRIVE",
22612
+ "SYSTEMROOT",
22613
+ "TEMP",
22614
+ "USERNAME",
22615
+ "USERPROFILE",
22616
+ "PROGRAMFILES"
22617
+ ] : (
22618
+ /* list inspired by the default env inheritance of sudo */
22619
+ ["HOME", "LOGNAME", "PATH", "SHELL", "TERM", "USER"]
22620
+ );
22621
+ function getDefaultEnvironment() {
22622
+ const env = {};
22623
+ for (const key of DEFAULT_INHERITED_ENV_VARS) {
22624
+ const value = process4.env[key];
22625
+ if (value === void 0) {
22626
+ continue;
22627
+ }
22628
+ if (value.startsWith("()")) {
22629
+ continue;
22630
+ }
22631
+ env[key] = value;
22632
+ }
22633
+ return env;
22634
+ }
22635
+ var StdioClientTransport = class {
22636
+ constructor(server2) {
22637
+ this._readBuffer = new ReadBuffer();
22638
+ this._stderrStream = null;
22639
+ this._serverParams = server2;
22640
+ if (server2.stderr === "pipe" || server2.stderr === "overlapped") {
22641
+ this._stderrStream = new PassThrough();
22642
+ }
22643
+ }
22644
+ /**
22645
+ * Starts the server process and prepares to communicate with it.
22646
+ */
22647
+ async start() {
22648
+ if (this._process) {
22649
+ throw new Error("StdioClientTransport already started! If using Client class, note that connect() calls start() automatically.");
22650
+ }
22651
+ return new Promise((resolve, reject) => {
22652
+ this._process = (0, import_cross_spawn.default)(this._serverParams.command, this._serverParams.args ?? [], {
22653
+ // merge default env with server env because mcp server needs some env vars
22654
+ env: {
22655
+ ...getDefaultEnvironment(),
22656
+ ...this._serverParams.env
22657
+ },
22658
+ stdio: ["pipe", "pipe", this._serverParams.stderr ?? "inherit"],
22659
+ shell: false,
22660
+ windowsHide: process4.platform === "win32",
22661
+ cwd: this._serverParams.cwd
22662
+ });
22663
+ this._process.on("error", (error2) => {
22664
+ reject(error2);
22665
+ this.onerror?.(error2);
22666
+ });
22667
+ this._process.on("spawn", () => {
22668
+ resolve();
22669
+ });
22670
+ this._process.on("close", (_code) => {
22671
+ this._process = void 0;
22672
+ this.onclose?.();
22673
+ });
22674
+ this._process.stdin?.on("error", (error2) => {
22675
+ this.onerror?.(error2);
22676
+ });
22677
+ this._process.stdout?.on("data", (chunk) => {
22678
+ this._readBuffer.append(chunk);
22679
+ this.processReadBuffer();
22680
+ });
22681
+ this._process.stdout?.on("error", (error2) => {
22682
+ this.onerror?.(error2);
22683
+ });
22684
+ if (this._stderrStream && this._process.stderr) {
22685
+ this._process.stderr.pipe(this._stderrStream);
22686
+ }
22687
+ });
22688
+ }
22689
+ /**
22690
+ * The stderr stream of the child process, if `StdioServerParameters.stderr` was set to "pipe" or "overlapped".
22691
+ *
22692
+ * If stderr piping was requested, a PassThrough stream is returned _immediately_, allowing callers to
22693
+ * attach listeners before the start method is invoked. This prevents loss of any early
22694
+ * error output emitted by the child process.
22695
+ */
22696
+ get stderr() {
22697
+ if (this._stderrStream) {
22698
+ return this._stderrStream;
22699
+ }
22700
+ return this._process?.stderr ?? null;
22701
+ }
22702
+ /**
22703
+ * The child process pid spawned by this transport.
22704
+ *
22705
+ * This is only available after the transport has been started.
22706
+ */
22707
+ get pid() {
22708
+ return this._process?.pid ?? null;
22709
+ }
22710
+ processReadBuffer() {
22711
+ while (true) {
22712
+ try {
22713
+ const message = this._readBuffer.readMessage();
22714
+ if (message === null) {
22715
+ break;
22716
+ }
22717
+ this.onmessage?.(message);
22718
+ } catch (error2) {
22719
+ this.onerror?.(error2);
22720
+ }
22721
+ }
22722
+ }
22723
+ async close() {
22724
+ if (this._process) {
22725
+ const processToClose = this._process;
22726
+ this._process = void 0;
22727
+ const closePromise = new Promise((resolve) => {
22728
+ processToClose.once("close", () => {
22729
+ resolve();
22730
+ });
22731
+ });
22732
+ try {
22733
+ processToClose.stdin?.end();
22734
+ } catch {
22735
+ }
22736
+ await Promise.race([closePromise, new Promise((resolve) => setTimeout(resolve, 2e3).unref())]);
22737
+ if (processToClose.exitCode === null) {
22738
+ try {
22739
+ processToClose.kill("SIGTERM");
22740
+ } catch {
22741
+ }
22742
+ await Promise.race([closePromise, new Promise((resolve) => setTimeout(resolve, 2e3).unref())]);
22743
+ }
22744
+ if (processToClose.exitCode === null) {
22745
+ try {
22746
+ processToClose.kill("SIGKILL");
22747
+ } catch {
22748
+ }
22749
+ }
22750
+ }
22751
+ this._readBuffer.clear();
22752
+ }
22753
+ send(message) {
22754
+ return new Promise((resolve) => {
22755
+ if (!this._process?.stdin) {
22756
+ throw new Error("Not connected");
22757
+ }
22758
+ const json = serializeMessage(message);
22759
+ if (this._process.stdin.write(json)) {
22760
+ resolve();
22761
+ } else {
22762
+ this._process.stdin.once("drain", resolve);
22763
+ }
22764
+ });
22765
+ }
22766
+ };
22767
+
22768
+ // node_modules/@modelcontextprotocol/sdk/dist/esm/shared/transport.js
22769
+ function normalizeHeaders(headers) {
22770
+ if (!headers)
22771
+ return {};
22772
+ if (headers instanceof Headers) {
22773
+ return Object.fromEntries(headers.entries());
22774
+ }
22775
+ if (Array.isArray(headers)) {
22776
+ return Object.fromEntries(headers);
22777
+ }
22778
+ return { ...headers };
22779
+ }
22780
+ function createFetchWithInit(baseFetch = fetch, baseInit) {
22781
+ if (!baseInit) {
22782
+ return baseFetch;
22783
+ }
22784
+ return async (url2, init) => {
22785
+ const mergedInit = {
22786
+ ...baseInit,
22787
+ ...init,
22788
+ // Headers need special handling - merge instead of replace
22789
+ headers: init?.headers ? { ...normalizeHeaders(baseInit.headers), ...normalizeHeaders(init.headers) } : baseInit.headers
22790
+ };
22791
+ return baseFetch(url2, mergedInit);
22792
+ };
22793
+ }
22794
+
22795
+ // node_modules/pkce-challenge/dist/index.node.js
22796
+ var crypto;
22797
+ crypto = globalThis.crypto?.webcrypto ?? // Node.js [18-16] REPL
22798
+ globalThis.crypto ?? // Node.js >18
22799
+ import("node:crypto").then((m) => m.webcrypto);
22800
+ async function getRandomValues(size) {
22801
+ return (await crypto).getRandomValues(new Uint8Array(size));
22802
+ }
22803
+ async function random(size) {
22804
+ const mask = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789-._~";
22805
+ const evenDistCutoff = Math.pow(2, 8) - Math.pow(2, 8) % mask.length;
22806
+ let result = "";
22807
+ while (result.length < size) {
22808
+ const randomBytes = await getRandomValues(size - result.length);
22809
+ for (const randomByte of randomBytes) {
22810
+ if (randomByte < evenDistCutoff) {
22811
+ result += mask[randomByte % mask.length];
22812
+ }
22813
+ }
22814
+ }
22815
+ return result;
22816
+ }
22817
+ async function generateVerifier(length) {
22818
+ return await random(length);
22819
+ }
22820
+ async function generateChallenge(code_verifier) {
22821
+ const buffer = await (await crypto).subtle.digest("SHA-256", new TextEncoder().encode(code_verifier));
22822
+ return btoa(String.fromCharCode(...new Uint8Array(buffer))).replace(/\//g, "_").replace(/\+/g, "-").replace(/=/g, "");
22823
+ }
22824
+ async function pkceChallenge(length) {
22825
+ if (!length)
22826
+ length = 43;
22827
+ if (length < 43 || length > 128) {
22828
+ throw `Expected a length between 43 and 128. Received ${length}.`;
22829
+ }
22830
+ const verifier = await generateVerifier(length);
22831
+ const challenge = await generateChallenge(verifier);
22832
+ return {
22833
+ code_verifier: verifier,
22834
+ code_challenge: challenge
22835
+ };
22836
+ }
22837
+
22838
+ // node_modules/@modelcontextprotocol/sdk/dist/esm/shared/auth.js
22839
+ var SafeUrlSchema = url().superRefine((val, ctx) => {
22840
+ if (!URL.canParse(val)) {
22841
+ ctx.addIssue({
22842
+ code: ZodIssueCode.custom,
22843
+ message: "URL must be parseable",
22844
+ fatal: true
22845
+ });
22846
+ return NEVER;
22847
+ }
22848
+ }).refine((url2) => {
22849
+ const u = new URL(url2);
22850
+ return u.protocol !== "javascript:" && u.protocol !== "data:" && u.protocol !== "vbscript:";
22851
+ }, { message: "URL cannot use javascript:, data:, or vbscript: scheme" });
22852
+ var OAuthProtectedResourceMetadataSchema = looseObject({
22853
+ resource: string2().url(),
22854
+ authorization_servers: array(SafeUrlSchema).optional(),
22855
+ jwks_uri: string2().url().optional(),
22856
+ scopes_supported: array(string2()).optional(),
22857
+ bearer_methods_supported: array(string2()).optional(),
22858
+ resource_signing_alg_values_supported: array(string2()).optional(),
22859
+ resource_name: string2().optional(),
22860
+ resource_documentation: string2().optional(),
22861
+ resource_policy_uri: string2().url().optional(),
22862
+ resource_tos_uri: string2().url().optional(),
22863
+ tls_client_certificate_bound_access_tokens: boolean2().optional(),
22864
+ authorization_details_types_supported: array(string2()).optional(),
22865
+ dpop_signing_alg_values_supported: array(string2()).optional(),
22866
+ dpop_bound_access_tokens_required: boolean2().optional()
22867
+ });
22868
+ var OAuthMetadataSchema = looseObject({
22869
+ issuer: string2(),
22870
+ authorization_endpoint: SafeUrlSchema,
22871
+ token_endpoint: SafeUrlSchema,
22872
+ registration_endpoint: SafeUrlSchema.optional(),
22873
+ scopes_supported: array(string2()).optional(),
22874
+ response_types_supported: array(string2()),
22875
+ response_modes_supported: array(string2()).optional(),
22876
+ grant_types_supported: array(string2()).optional(),
22877
+ token_endpoint_auth_methods_supported: array(string2()).optional(),
22878
+ token_endpoint_auth_signing_alg_values_supported: array(string2()).optional(),
22879
+ service_documentation: SafeUrlSchema.optional(),
22880
+ revocation_endpoint: SafeUrlSchema.optional(),
22881
+ revocation_endpoint_auth_methods_supported: array(string2()).optional(),
22882
+ revocation_endpoint_auth_signing_alg_values_supported: array(string2()).optional(),
22883
+ introspection_endpoint: string2().optional(),
22884
+ introspection_endpoint_auth_methods_supported: array(string2()).optional(),
22885
+ introspection_endpoint_auth_signing_alg_values_supported: array(string2()).optional(),
22886
+ code_challenge_methods_supported: array(string2()).optional(),
22887
+ client_id_metadata_document_supported: boolean2().optional()
22888
+ });
22889
+ var OpenIdProviderMetadataSchema = looseObject({
22890
+ issuer: string2(),
22891
+ authorization_endpoint: SafeUrlSchema,
22892
+ token_endpoint: SafeUrlSchema,
22893
+ userinfo_endpoint: SafeUrlSchema.optional(),
22894
+ jwks_uri: SafeUrlSchema,
22895
+ registration_endpoint: SafeUrlSchema.optional(),
22896
+ scopes_supported: array(string2()).optional(),
22897
+ response_types_supported: array(string2()),
22898
+ response_modes_supported: array(string2()).optional(),
22899
+ grant_types_supported: array(string2()).optional(),
22900
+ acr_values_supported: array(string2()).optional(),
22901
+ subject_types_supported: array(string2()),
22902
+ id_token_signing_alg_values_supported: array(string2()),
22903
+ id_token_encryption_alg_values_supported: array(string2()).optional(),
22904
+ id_token_encryption_enc_values_supported: array(string2()).optional(),
22905
+ userinfo_signing_alg_values_supported: array(string2()).optional(),
22906
+ userinfo_encryption_alg_values_supported: array(string2()).optional(),
22907
+ userinfo_encryption_enc_values_supported: array(string2()).optional(),
22908
+ request_object_signing_alg_values_supported: array(string2()).optional(),
22909
+ request_object_encryption_alg_values_supported: array(string2()).optional(),
22910
+ request_object_encryption_enc_values_supported: array(string2()).optional(),
22911
+ token_endpoint_auth_methods_supported: array(string2()).optional(),
22912
+ token_endpoint_auth_signing_alg_values_supported: array(string2()).optional(),
22913
+ display_values_supported: array(string2()).optional(),
22914
+ claim_types_supported: array(string2()).optional(),
22915
+ claims_supported: array(string2()).optional(),
22916
+ service_documentation: string2().optional(),
22917
+ claims_locales_supported: array(string2()).optional(),
22918
+ ui_locales_supported: array(string2()).optional(),
22919
+ claims_parameter_supported: boolean2().optional(),
22920
+ request_parameter_supported: boolean2().optional(),
22921
+ request_uri_parameter_supported: boolean2().optional(),
22922
+ require_request_uri_registration: boolean2().optional(),
22923
+ op_policy_uri: SafeUrlSchema.optional(),
22924
+ op_tos_uri: SafeUrlSchema.optional(),
22925
+ client_id_metadata_document_supported: boolean2().optional()
22926
+ });
22927
+ var OpenIdProviderDiscoveryMetadataSchema = object2({
22928
+ ...OpenIdProviderMetadataSchema.shape,
22929
+ ...OAuthMetadataSchema.pick({
22930
+ code_challenge_methods_supported: true
22931
+ }).shape
22932
+ });
22933
+ var OAuthTokensSchema = object2({
22934
+ access_token: string2(),
22935
+ id_token: string2().optional(),
22936
+ // Optional for OAuth 2.1, but necessary in OpenID Connect
22937
+ token_type: string2(),
22938
+ expires_in: coerce_exports.number().optional(),
22939
+ scope: string2().optional(),
22940
+ refresh_token: string2().optional()
22941
+ }).strip();
22942
+ var OAuthErrorResponseSchema = object2({
22943
+ error: string2(),
22944
+ error_description: string2().optional(),
22945
+ error_uri: string2().optional()
22946
+ });
22947
+ var OptionalSafeUrlSchema = SafeUrlSchema.optional().or(literal("").transform(() => void 0));
22948
+ var OAuthClientMetadataSchema = object2({
22949
+ redirect_uris: array(SafeUrlSchema),
22950
+ token_endpoint_auth_method: string2().optional(),
22951
+ grant_types: array(string2()).optional(),
22952
+ response_types: array(string2()).optional(),
22953
+ client_name: string2().optional(),
22954
+ client_uri: SafeUrlSchema.optional(),
22955
+ logo_uri: OptionalSafeUrlSchema,
22956
+ scope: string2().optional(),
22957
+ contacts: array(string2()).optional(),
22958
+ tos_uri: OptionalSafeUrlSchema,
22959
+ policy_uri: string2().optional(),
22960
+ jwks_uri: SafeUrlSchema.optional(),
22961
+ jwks: any().optional(),
22962
+ software_id: string2().optional(),
22963
+ software_version: string2().optional(),
22964
+ software_statement: string2().optional()
22965
+ }).strip();
22966
+ var OAuthClientInformationSchema = object2({
22967
+ client_id: string2(),
22968
+ client_secret: string2().optional(),
22969
+ client_id_issued_at: number2().optional(),
22970
+ client_secret_expires_at: number2().optional()
22971
+ }).strip();
22972
+ var OAuthClientInformationFullSchema = OAuthClientMetadataSchema.merge(OAuthClientInformationSchema);
22973
+ var OAuthClientRegistrationErrorSchema = object2({
22974
+ error: string2(),
22975
+ error_description: string2().optional()
22976
+ }).strip();
22977
+ var OAuthTokenRevocationRequestSchema = object2({
22978
+ token: string2(),
22979
+ token_type_hint: string2().optional()
22980
+ }).strip();
22981
+
22982
+ // node_modules/@modelcontextprotocol/sdk/dist/esm/shared/auth-utils.js
22983
+ function resourceUrlFromServerUrl(url2) {
22984
+ const resourceURL = typeof url2 === "string" ? new URL(url2) : new URL(url2.href);
22985
+ resourceURL.hash = "";
22986
+ return resourceURL;
22987
+ }
22988
+ function checkResourceAllowed({ requestedResource, configuredResource }) {
22989
+ const requested = typeof requestedResource === "string" ? new URL(requestedResource) : new URL(requestedResource.href);
22990
+ const configured = typeof configuredResource === "string" ? new URL(configuredResource) : new URL(configuredResource.href);
22991
+ if (requested.origin !== configured.origin) {
22992
+ return false;
22993
+ }
22994
+ if (requested.pathname.length < configured.pathname.length) {
22995
+ return false;
22996
+ }
22997
+ const requestedPath = requested.pathname.endsWith("/") ? requested.pathname : requested.pathname + "/";
22998
+ const configuredPath = configured.pathname.endsWith("/") ? configured.pathname : configured.pathname + "/";
22999
+ return requestedPath.startsWith(configuredPath);
23000
+ }
23001
+
23002
+ // node_modules/@modelcontextprotocol/sdk/dist/esm/server/auth/errors.js
23003
+ var OAuthError = class extends Error {
23004
+ constructor(message, errorUri) {
23005
+ super(message);
23006
+ this.errorUri = errorUri;
23007
+ this.name = this.constructor.name;
23008
+ }
23009
+ /**
23010
+ * Converts the error to a standard OAuth error response object
23011
+ */
23012
+ toResponseObject() {
23013
+ const response = {
23014
+ error: this.errorCode,
23015
+ error_description: this.message
23016
+ };
23017
+ if (this.errorUri) {
23018
+ response.error_uri = this.errorUri;
23019
+ }
23020
+ return response;
23021
+ }
23022
+ get errorCode() {
23023
+ return this.constructor.errorCode;
23024
+ }
23025
+ };
23026
+ var InvalidRequestError = class extends OAuthError {
23027
+ };
23028
+ InvalidRequestError.errorCode = "invalid_request";
23029
+ var InvalidClientError = class extends OAuthError {
23030
+ };
23031
+ InvalidClientError.errorCode = "invalid_client";
23032
+ var InvalidGrantError = class extends OAuthError {
23033
+ };
23034
+ InvalidGrantError.errorCode = "invalid_grant";
23035
+ var UnauthorizedClientError = class extends OAuthError {
23036
+ };
23037
+ UnauthorizedClientError.errorCode = "unauthorized_client";
23038
+ var UnsupportedGrantTypeError = class extends OAuthError {
23039
+ };
23040
+ UnsupportedGrantTypeError.errorCode = "unsupported_grant_type";
23041
+ var InvalidScopeError = class extends OAuthError {
23042
+ };
23043
+ InvalidScopeError.errorCode = "invalid_scope";
23044
+ var AccessDeniedError = class extends OAuthError {
23045
+ };
23046
+ AccessDeniedError.errorCode = "access_denied";
23047
+ var ServerError = class extends OAuthError {
23048
+ };
23049
+ ServerError.errorCode = "server_error";
23050
+ var TemporarilyUnavailableError = class extends OAuthError {
23051
+ };
23052
+ TemporarilyUnavailableError.errorCode = "temporarily_unavailable";
23053
+ var UnsupportedResponseTypeError = class extends OAuthError {
23054
+ };
23055
+ UnsupportedResponseTypeError.errorCode = "unsupported_response_type";
23056
+ var UnsupportedTokenTypeError = class extends OAuthError {
23057
+ };
23058
+ UnsupportedTokenTypeError.errorCode = "unsupported_token_type";
23059
+ var InvalidTokenError = class extends OAuthError {
23060
+ };
23061
+ InvalidTokenError.errorCode = "invalid_token";
23062
+ var MethodNotAllowedError = class extends OAuthError {
23063
+ };
23064
+ MethodNotAllowedError.errorCode = "method_not_allowed";
23065
+ var TooManyRequestsError = class extends OAuthError {
23066
+ };
23067
+ TooManyRequestsError.errorCode = "too_many_requests";
23068
+ var InvalidClientMetadataError = class extends OAuthError {
23069
+ };
23070
+ InvalidClientMetadataError.errorCode = "invalid_client_metadata";
23071
+ var InsufficientScopeError = class extends OAuthError {
23072
+ };
23073
+ InsufficientScopeError.errorCode = "insufficient_scope";
23074
+ var InvalidTargetError = class extends OAuthError {
23075
+ };
23076
+ InvalidTargetError.errorCode = "invalid_target";
23077
+ var OAUTH_ERRORS = {
23078
+ [InvalidRequestError.errorCode]: InvalidRequestError,
23079
+ [InvalidClientError.errorCode]: InvalidClientError,
23080
+ [InvalidGrantError.errorCode]: InvalidGrantError,
23081
+ [UnauthorizedClientError.errorCode]: UnauthorizedClientError,
23082
+ [UnsupportedGrantTypeError.errorCode]: UnsupportedGrantTypeError,
23083
+ [InvalidScopeError.errorCode]: InvalidScopeError,
23084
+ [AccessDeniedError.errorCode]: AccessDeniedError,
23085
+ [ServerError.errorCode]: ServerError,
23086
+ [TemporarilyUnavailableError.errorCode]: TemporarilyUnavailableError,
23087
+ [UnsupportedResponseTypeError.errorCode]: UnsupportedResponseTypeError,
23088
+ [UnsupportedTokenTypeError.errorCode]: UnsupportedTokenTypeError,
23089
+ [InvalidTokenError.errorCode]: InvalidTokenError,
23090
+ [MethodNotAllowedError.errorCode]: MethodNotAllowedError,
23091
+ [TooManyRequestsError.errorCode]: TooManyRequestsError,
23092
+ [InvalidClientMetadataError.errorCode]: InvalidClientMetadataError,
23093
+ [InsufficientScopeError.errorCode]: InsufficientScopeError,
23094
+ [InvalidTargetError.errorCode]: InvalidTargetError
23095
+ };
23096
+
23097
+ // node_modules/@modelcontextprotocol/sdk/dist/esm/client/auth.js
23098
+ var UnauthorizedError = class extends Error {
23099
+ constructor(message) {
23100
+ super(message ?? "Unauthorized");
23101
+ }
23102
+ };
23103
+ function isClientAuthMethod(method) {
23104
+ return ["client_secret_basic", "client_secret_post", "none"].includes(method);
23105
+ }
23106
+ var AUTHORIZATION_CODE_RESPONSE_TYPE = "code";
23107
+ var AUTHORIZATION_CODE_CHALLENGE_METHOD = "S256";
23108
+ function selectClientAuthMethod(clientInformation, supportedMethods) {
23109
+ const hasClientSecret = clientInformation.client_secret !== void 0;
23110
+ 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))) {
23111
+ return clientInformation.token_endpoint_auth_method;
23112
+ }
23113
+ if (supportedMethods.length === 0) {
23114
+ return hasClientSecret ? "client_secret_basic" : "none";
23115
+ }
23116
+ if (hasClientSecret && supportedMethods.includes("client_secret_basic")) {
23117
+ return "client_secret_basic";
23118
+ }
23119
+ if (hasClientSecret && supportedMethods.includes("client_secret_post")) {
23120
+ return "client_secret_post";
23121
+ }
23122
+ if (supportedMethods.includes("none")) {
23123
+ return "none";
23124
+ }
23125
+ return hasClientSecret ? "client_secret_post" : "none";
23126
+ }
23127
+ function applyClientAuthentication(method, clientInformation, headers, params) {
23128
+ const { client_id, client_secret } = clientInformation;
23129
+ switch (method) {
23130
+ case "client_secret_basic":
23131
+ applyBasicAuth(client_id, client_secret, headers);
23132
+ return;
23133
+ case "client_secret_post":
23134
+ applyPostAuth(client_id, client_secret, params);
23135
+ return;
23136
+ case "none":
23137
+ applyPublicAuth(client_id, params);
23138
+ return;
23139
+ default:
23140
+ throw new Error(`Unsupported client authentication method: ${method}`);
23141
+ }
23142
+ }
23143
+ function applyBasicAuth(clientId, clientSecret, headers) {
23144
+ if (!clientSecret) {
23145
+ throw new Error("client_secret_basic authentication requires a client_secret");
23146
+ }
23147
+ const credentials = btoa(`${clientId}:${clientSecret}`);
23148
+ headers.set("Authorization", `Basic ${credentials}`);
23149
+ }
23150
+ function applyPostAuth(clientId, clientSecret, params) {
23151
+ params.set("client_id", clientId);
23152
+ if (clientSecret) {
23153
+ params.set("client_secret", clientSecret);
23154
+ }
23155
+ }
23156
+ function applyPublicAuth(clientId, params) {
23157
+ params.set("client_id", clientId);
23158
+ }
23159
+ async function parseErrorResponse(input) {
23160
+ const statusCode = input instanceof Response ? input.status : void 0;
23161
+ const body = input instanceof Response ? await input.text() : input;
23162
+ try {
23163
+ const result = OAuthErrorResponseSchema.parse(JSON.parse(body));
23164
+ const { error: error2, error_description, error_uri } = result;
23165
+ const errorClass = OAUTH_ERRORS[error2] || ServerError;
23166
+ return new errorClass(error_description || "", error_uri);
23167
+ } catch (error2) {
23168
+ const errorMessage = `${statusCode ? `HTTP ${statusCode}: ` : ""}Invalid OAuth error response: ${error2}. Raw body: ${body}`;
23169
+ return new ServerError(errorMessage);
23170
+ }
23171
+ }
23172
+ async function auth(provider, options) {
23173
+ try {
23174
+ return await authInternal(provider, options);
23175
+ } catch (error2) {
23176
+ if (error2 instanceof InvalidClientError || error2 instanceof UnauthorizedClientError) {
23177
+ await provider.invalidateCredentials?.("all");
23178
+ return await authInternal(provider, options);
23179
+ } else if (error2 instanceof InvalidGrantError) {
23180
+ await provider.invalidateCredentials?.("tokens");
23181
+ return await authInternal(provider, options);
23182
+ }
23183
+ throw error2;
23184
+ }
23185
+ }
23186
+ async function authInternal(provider, { serverUrl, authorizationCode, scope, resourceMetadataUrl, fetchFn }) {
23187
+ const cachedState = await provider.discoveryState?.();
23188
+ let resourceMetadata;
23189
+ let authorizationServerUrl;
23190
+ let metadata;
23191
+ let effectiveResourceMetadataUrl = resourceMetadataUrl;
23192
+ if (!effectiveResourceMetadataUrl && cachedState?.resourceMetadataUrl) {
23193
+ effectiveResourceMetadataUrl = new URL(cachedState.resourceMetadataUrl);
23194
+ }
23195
+ if (cachedState?.authorizationServerUrl) {
23196
+ authorizationServerUrl = cachedState.authorizationServerUrl;
23197
+ resourceMetadata = cachedState.resourceMetadata;
23198
+ metadata = cachedState.authorizationServerMetadata ?? await discoverAuthorizationServerMetadata(authorizationServerUrl, { fetchFn });
23199
+ if (!resourceMetadata) {
23200
+ try {
23201
+ resourceMetadata = await discoverOAuthProtectedResourceMetadata(serverUrl, { resourceMetadataUrl: effectiveResourceMetadataUrl }, fetchFn);
23202
+ } catch {
23203
+ }
23204
+ }
23205
+ if (metadata !== cachedState.authorizationServerMetadata || resourceMetadata !== cachedState.resourceMetadata) {
23206
+ await provider.saveDiscoveryState?.({
23207
+ authorizationServerUrl: String(authorizationServerUrl),
23208
+ resourceMetadataUrl: effectiveResourceMetadataUrl?.toString(),
23209
+ resourceMetadata,
23210
+ authorizationServerMetadata: metadata
23211
+ });
23212
+ }
23213
+ } else {
23214
+ const serverInfo = await discoverOAuthServerInfo(serverUrl, { resourceMetadataUrl: effectiveResourceMetadataUrl, fetchFn });
23215
+ authorizationServerUrl = serverInfo.authorizationServerUrl;
23216
+ metadata = serverInfo.authorizationServerMetadata;
23217
+ resourceMetadata = serverInfo.resourceMetadata;
23218
+ await provider.saveDiscoveryState?.({
23219
+ authorizationServerUrl: String(authorizationServerUrl),
23220
+ resourceMetadataUrl: effectiveResourceMetadataUrl?.toString(),
23221
+ resourceMetadata,
23222
+ authorizationServerMetadata: metadata
23223
+ });
23224
+ }
23225
+ const resource = await selectResourceURL(serverUrl, provider, resourceMetadata);
23226
+ const resolvedScope = scope || resourceMetadata?.scopes_supported?.join(" ") || provider.clientMetadata.scope;
23227
+ let clientInformation = await Promise.resolve(provider.clientInformation());
23228
+ if (!clientInformation) {
23229
+ if (authorizationCode !== void 0) {
23230
+ throw new Error("Existing OAuth client information is required when exchanging an authorization code");
23231
+ }
23232
+ const supportsUrlBasedClientId = metadata?.client_id_metadata_document_supported === true;
23233
+ const clientMetadataUrl = provider.clientMetadataUrl;
23234
+ if (clientMetadataUrl && !isHttpsUrl(clientMetadataUrl)) {
23235
+ throw new InvalidClientMetadataError(`clientMetadataUrl must be a valid HTTPS URL with a non-root pathname, got: ${clientMetadataUrl}`);
23236
+ }
23237
+ const shouldUseUrlBasedClientId = supportsUrlBasedClientId && clientMetadataUrl;
23238
+ if (shouldUseUrlBasedClientId) {
23239
+ clientInformation = {
23240
+ client_id: clientMetadataUrl
23241
+ };
23242
+ await provider.saveClientInformation?.(clientInformation);
23243
+ } else {
23244
+ if (!provider.saveClientInformation) {
23245
+ throw new Error("OAuth client information must be saveable for dynamic registration");
23246
+ }
23247
+ const fullInformation = await registerClient(authorizationServerUrl, {
23248
+ metadata,
23249
+ clientMetadata: provider.clientMetadata,
23250
+ scope: resolvedScope,
23251
+ fetchFn
23252
+ });
23253
+ await provider.saveClientInformation(fullInformation);
23254
+ clientInformation = fullInformation;
23255
+ }
23256
+ }
23257
+ const nonInteractiveFlow = !provider.redirectUrl;
23258
+ if (authorizationCode !== void 0 || nonInteractiveFlow) {
23259
+ const tokens2 = await fetchToken(provider, authorizationServerUrl, {
23260
+ metadata,
23261
+ resource,
23262
+ authorizationCode,
23263
+ fetchFn
23264
+ });
23265
+ await provider.saveTokens(tokens2);
23266
+ return "AUTHORIZED";
23267
+ }
23268
+ const tokens = await provider.tokens();
23269
+ if (tokens?.refresh_token) {
23270
+ try {
23271
+ const newTokens = await refreshAuthorization(authorizationServerUrl, {
23272
+ metadata,
23273
+ clientInformation,
23274
+ refreshToken: tokens.refresh_token,
23275
+ resource,
23276
+ addClientAuthentication: provider.addClientAuthentication,
23277
+ fetchFn
23278
+ });
23279
+ await provider.saveTokens(newTokens);
23280
+ return "AUTHORIZED";
23281
+ } catch (error2) {
23282
+ if (!(error2 instanceof OAuthError) || error2 instanceof ServerError) {
23283
+ } else {
23284
+ throw error2;
23285
+ }
23286
+ }
23287
+ }
23288
+ const state = provider.state ? await provider.state() : void 0;
23289
+ const { authorizationUrl, codeVerifier } = await startAuthorization(authorizationServerUrl, {
23290
+ metadata,
23291
+ clientInformation,
23292
+ state,
23293
+ redirectUrl: provider.redirectUrl,
23294
+ scope: resolvedScope,
23295
+ resource
23296
+ });
23297
+ await provider.saveCodeVerifier(codeVerifier);
23298
+ await provider.redirectToAuthorization(authorizationUrl);
23299
+ return "REDIRECT";
23300
+ }
23301
+ function isHttpsUrl(value) {
23302
+ if (!value)
23303
+ return false;
23304
+ try {
23305
+ const url2 = new URL(value);
23306
+ return url2.protocol === "https:" && url2.pathname !== "/";
23307
+ } catch {
23308
+ return false;
23309
+ }
23310
+ }
23311
+ async function selectResourceURL(serverUrl, provider, resourceMetadata) {
23312
+ const defaultResource = resourceUrlFromServerUrl(serverUrl);
23313
+ if (provider.validateResourceURL) {
23314
+ return await provider.validateResourceURL(defaultResource, resourceMetadata?.resource);
23315
+ }
23316
+ if (!resourceMetadata) {
23317
+ return void 0;
23318
+ }
23319
+ if (!checkResourceAllowed({ requestedResource: defaultResource, configuredResource: resourceMetadata.resource })) {
23320
+ throw new Error(`Protected resource ${resourceMetadata.resource} does not match expected ${defaultResource} (or origin)`);
23321
+ }
23322
+ return new URL(resourceMetadata.resource);
23323
+ }
23324
+ function extractWWWAuthenticateParams(res) {
23325
+ const authenticateHeader = res.headers.get("WWW-Authenticate");
23326
+ if (!authenticateHeader) {
23327
+ return {};
23328
+ }
23329
+ const [type, scheme] = authenticateHeader.split(" ");
23330
+ if (type.toLowerCase() !== "bearer" || !scheme) {
23331
+ return {};
23332
+ }
23333
+ const resourceMetadataMatch = extractFieldFromWwwAuth(res, "resource_metadata") || void 0;
23334
+ let resourceMetadataUrl;
23335
+ if (resourceMetadataMatch) {
23336
+ try {
23337
+ resourceMetadataUrl = new URL(resourceMetadataMatch);
23338
+ } catch {
23339
+ }
23340
+ }
23341
+ const scope = extractFieldFromWwwAuth(res, "scope") || void 0;
23342
+ const error2 = extractFieldFromWwwAuth(res, "error") || void 0;
23343
+ return {
23344
+ resourceMetadataUrl,
23345
+ scope,
23346
+ error: error2
23347
+ };
23348
+ }
23349
+ function extractFieldFromWwwAuth(response, fieldName) {
23350
+ const wwwAuthHeader = response.headers.get("WWW-Authenticate");
23351
+ if (!wwwAuthHeader) {
23352
+ return null;
23353
+ }
23354
+ const pattern = new RegExp(`${fieldName}=(?:"([^"]+)"|([^\\s,]+))`);
23355
+ const match = wwwAuthHeader.match(pattern);
23356
+ if (match) {
23357
+ return match[1] || match[2];
23358
+ }
23359
+ return null;
23360
+ }
23361
+ async function discoverOAuthProtectedResourceMetadata(serverUrl, opts, fetchFn = fetch) {
23362
+ const response = await discoverMetadataWithFallback(serverUrl, "oauth-protected-resource", fetchFn, {
23363
+ protocolVersion: opts?.protocolVersion,
23364
+ metadataUrl: opts?.resourceMetadataUrl
23365
+ });
23366
+ if (!response || response.status === 404) {
23367
+ await response?.body?.cancel();
23368
+ throw new Error(`Resource server does not implement OAuth 2.0 Protected Resource Metadata.`);
23369
+ }
23370
+ if (!response.ok) {
23371
+ await response.body?.cancel();
23372
+ throw new Error(`HTTP ${response.status} trying to load well-known OAuth protected resource metadata.`);
23373
+ }
23374
+ return OAuthProtectedResourceMetadataSchema.parse(await response.json());
23375
+ }
23376
+ async function fetchWithCorsRetry(url2, headers, fetchFn = fetch) {
23377
+ try {
23378
+ return await fetchFn(url2, { headers });
23379
+ } catch (error2) {
23380
+ if (error2 instanceof TypeError) {
23381
+ if (headers) {
23382
+ return fetchWithCorsRetry(url2, void 0, fetchFn);
23383
+ } else {
23384
+ return void 0;
23385
+ }
23386
+ }
23387
+ throw error2;
23388
+ }
23389
+ }
23390
+ function buildWellKnownPath(wellKnownPrefix, pathname = "", options = {}) {
23391
+ if (pathname.endsWith("/")) {
23392
+ pathname = pathname.slice(0, -1);
23393
+ }
23394
+ return options.prependPathname ? `${pathname}/.well-known/${wellKnownPrefix}` : `/.well-known/${wellKnownPrefix}${pathname}`;
23395
+ }
23396
+ async function tryMetadataDiscovery(url2, protocolVersion, fetchFn = fetch) {
23397
+ const headers = {
23398
+ "MCP-Protocol-Version": protocolVersion
23399
+ };
23400
+ return await fetchWithCorsRetry(url2, headers, fetchFn);
23401
+ }
23402
+ function shouldAttemptFallback(response, pathname) {
23403
+ return !response || response.status >= 400 && response.status < 500 && pathname !== "/";
23404
+ }
23405
+ async function discoverMetadataWithFallback(serverUrl, wellKnownType, fetchFn, opts) {
23406
+ const issuer = new URL(serverUrl);
23407
+ const protocolVersion = opts?.protocolVersion ?? LATEST_PROTOCOL_VERSION;
23408
+ let url2;
23409
+ if (opts?.metadataUrl) {
23410
+ url2 = new URL(opts.metadataUrl);
23411
+ } else {
23412
+ const wellKnownPath = buildWellKnownPath(wellKnownType, issuer.pathname);
23413
+ url2 = new URL(wellKnownPath, opts?.metadataServerUrl ?? issuer);
23414
+ url2.search = issuer.search;
23415
+ }
23416
+ let response = await tryMetadataDiscovery(url2, protocolVersion, fetchFn);
23417
+ if (!opts?.metadataUrl && shouldAttemptFallback(response, issuer.pathname)) {
23418
+ const rootUrl = new URL(`/.well-known/${wellKnownType}`, issuer);
23419
+ response = await tryMetadataDiscovery(rootUrl, protocolVersion, fetchFn);
23420
+ }
23421
+ return response;
23422
+ }
23423
+ function buildDiscoveryUrls(authorizationServerUrl) {
23424
+ const url2 = typeof authorizationServerUrl === "string" ? new URL(authorizationServerUrl) : authorizationServerUrl;
23425
+ const hasPath = url2.pathname !== "/";
23426
+ const urlsToTry = [];
23427
+ if (!hasPath) {
23428
+ urlsToTry.push({
23429
+ url: new URL("/.well-known/oauth-authorization-server", url2.origin),
23430
+ type: "oauth"
23431
+ });
23432
+ urlsToTry.push({
23433
+ url: new URL(`/.well-known/openid-configuration`, url2.origin),
23434
+ type: "oidc"
23435
+ });
23436
+ return urlsToTry;
23437
+ }
23438
+ let pathname = url2.pathname;
23439
+ if (pathname.endsWith("/")) {
23440
+ pathname = pathname.slice(0, -1);
23441
+ }
23442
+ urlsToTry.push({
23443
+ url: new URL(`/.well-known/oauth-authorization-server${pathname}`, url2.origin),
23444
+ type: "oauth"
23445
+ });
23446
+ urlsToTry.push({
23447
+ url: new URL(`/.well-known/openid-configuration${pathname}`, url2.origin),
23448
+ type: "oidc"
23449
+ });
23450
+ urlsToTry.push({
23451
+ url: new URL(`${pathname}/.well-known/openid-configuration`, url2.origin),
23452
+ type: "oidc"
23453
+ });
23454
+ return urlsToTry;
23455
+ }
23456
+ async function discoverAuthorizationServerMetadata(authorizationServerUrl, { fetchFn = fetch, protocolVersion = LATEST_PROTOCOL_VERSION } = {}) {
23457
+ const headers = {
23458
+ "MCP-Protocol-Version": protocolVersion,
23459
+ Accept: "application/json"
23460
+ };
23461
+ const urlsToTry = buildDiscoveryUrls(authorizationServerUrl);
23462
+ for (const { url: endpointUrl, type } of urlsToTry) {
23463
+ const response = await fetchWithCorsRetry(endpointUrl, headers, fetchFn);
23464
+ if (!response) {
23465
+ continue;
23466
+ }
23467
+ if (!response.ok) {
23468
+ await response.body?.cancel();
23469
+ if (response.status >= 400 && response.status < 500) {
23470
+ continue;
23471
+ }
23472
+ throw new Error(`HTTP ${response.status} trying to load ${type === "oauth" ? "OAuth" : "OpenID provider"} metadata from ${endpointUrl}`);
23473
+ }
23474
+ if (type === "oauth") {
23475
+ return OAuthMetadataSchema.parse(await response.json());
23476
+ } else {
23477
+ return OpenIdProviderDiscoveryMetadataSchema.parse(await response.json());
23478
+ }
23479
+ }
23480
+ return void 0;
23481
+ }
23482
+ async function discoverOAuthServerInfo(serverUrl, opts) {
23483
+ let resourceMetadata;
23484
+ let authorizationServerUrl;
23485
+ try {
23486
+ resourceMetadata = await discoverOAuthProtectedResourceMetadata(serverUrl, { resourceMetadataUrl: opts?.resourceMetadataUrl }, opts?.fetchFn);
23487
+ if (resourceMetadata.authorization_servers && resourceMetadata.authorization_servers.length > 0) {
23488
+ authorizationServerUrl = resourceMetadata.authorization_servers[0];
23489
+ }
23490
+ } catch {
23491
+ }
23492
+ if (!authorizationServerUrl) {
23493
+ authorizationServerUrl = String(new URL("/", serverUrl));
23494
+ }
23495
+ const authorizationServerMetadata = await discoverAuthorizationServerMetadata(authorizationServerUrl, { fetchFn: opts?.fetchFn });
23496
+ return {
23497
+ authorizationServerUrl,
23498
+ authorizationServerMetadata,
23499
+ resourceMetadata
23500
+ };
23501
+ }
23502
+ async function startAuthorization(authorizationServerUrl, { metadata, clientInformation, redirectUrl, scope, state, resource }) {
23503
+ let authorizationUrl;
23504
+ if (metadata) {
23505
+ authorizationUrl = new URL(metadata.authorization_endpoint);
23506
+ if (!metadata.response_types_supported.includes(AUTHORIZATION_CODE_RESPONSE_TYPE)) {
23507
+ throw new Error(`Incompatible auth server: does not support response type ${AUTHORIZATION_CODE_RESPONSE_TYPE}`);
23508
+ }
23509
+ if (metadata.code_challenge_methods_supported && !metadata.code_challenge_methods_supported.includes(AUTHORIZATION_CODE_CHALLENGE_METHOD)) {
23510
+ throw new Error(`Incompatible auth server: does not support code challenge method ${AUTHORIZATION_CODE_CHALLENGE_METHOD}`);
23511
+ }
23512
+ } else {
23513
+ authorizationUrl = new URL("/authorize", authorizationServerUrl);
23514
+ }
23515
+ const challenge = await pkceChallenge();
23516
+ const codeVerifier = challenge.code_verifier;
23517
+ const codeChallenge = challenge.code_challenge;
23518
+ authorizationUrl.searchParams.set("response_type", AUTHORIZATION_CODE_RESPONSE_TYPE);
23519
+ authorizationUrl.searchParams.set("client_id", clientInformation.client_id);
23520
+ authorizationUrl.searchParams.set("code_challenge", codeChallenge);
23521
+ authorizationUrl.searchParams.set("code_challenge_method", AUTHORIZATION_CODE_CHALLENGE_METHOD);
23522
+ authorizationUrl.searchParams.set("redirect_uri", String(redirectUrl));
23523
+ if (state) {
23524
+ authorizationUrl.searchParams.set("state", state);
23525
+ }
23526
+ if (scope) {
23527
+ authorizationUrl.searchParams.set("scope", scope);
23528
+ }
23529
+ if (scope?.includes("offline_access")) {
23530
+ authorizationUrl.searchParams.append("prompt", "consent");
23531
+ }
23532
+ if (resource) {
23533
+ authorizationUrl.searchParams.set("resource", resource.href);
23534
+ }
23535
+ return { authorizationUrl, codeVerifier };
23536
+ }
23537
+ function prepareAuthorizationCodeRequest(authorizationCode, codeVerifier, redirectUri) {
23538
+ return new URLSearchParams({
23539
+ grant_type: "authorization_code",
23540
+ code: authorizationCode,
23541
+ code_verifier: codeVerifier,
23542
+ redirect_uri: String(redirectUri)
23543
+ });
23544
+ }
23545
+ async function executeTokenRequest(authorizationServerUrl, { metadata, tokenRequestParams, clientInformation, addClientAuthentication, resource, fetchFn }) {
23546
+ const tokenUrl = metadata?.token_endpoint ? new URL(metadata.token_endpoint) : new URL("/token", authorizationServerUrl);
23547
+ const headers = new Headers({
23548
+ "Content-Type": "application/x-www-form-urlencoded",
23549
+ Accept: "application/json"
23550
+ });
23551
+ if (resource) {
23552
+ tokenRequestParams.set("resource", resource.href);
23553
+ }
23554
+ if (addClientAuthentication) {
23555
+ await addClientAuthentication(headers, tokenRequestParams, tokenUrl, metadata);
23556
+ } else if (clientInformation) {
23557
+ const supportedMethods = metadata?.token_endpoint_auth_methods_supported ?? [];
23558
+ const authMethod = selectClientAuthMethod(clientInformation, supportedMethods);
23559
+ applyClientAuthentication(authMethod, clientInformation, headers, tokenRequestParams);
23560
+ }
23561
+ const response = await (fetchFn ?? fetch)(tokenUrl, {
23562
+ method: "POST",
23563
+ headers,
23564
+ body: tokenRequestParams
23565
+ });
23566
+ if (!response.ok) {
23567
+ throw await parseErrorResponse(response);
23568
+ }
23569
+ return OAuthTokensSchema.parse(await response.json());
23570
+ }
23571
+ async function refreshAuthorization(authorizationServerUrl, { metadata, clientInformation, refreshToken, resource, addClientAuthentication, fetchFn }) {
23572
+ const tokenRequestParams = new URLSearchParams({
23573
+ grant_type: "refresh_token",
23574
+ refresh_token: refreshToken
23575
+ });
23576
+ const tokens = await executeTokenRequest(authorizationServerUrl, {
23577
+ metadata,
23578
+ tokenRequestParams,
23579
+ clientInformation,
23580
+ addClientAuthentication,
23581
+ resource,
23582
+ fetchFn
23583
+ });
23584
+ return { refresh_token: refreshToken, ...tokens };
23585
+ }
23586
+ async function fetchToken(provider, authorizationServerUrl, { metadata, resource, authorizationCode, fetchFn } = {}) {
23587
+ const scope = provider.clientMetadata.scope;
23588
+ let tokenRequestParams;
23589
+ if (provider.prepareTokenRequest) {
23590
+ tokenRequestParams = await provider.prepareTokenRequest(scope);
23591
+ }
23592
+ if (!tokenRequestParams) {
23593
+ if (!authorizationCode) {
23594
+ throw new Error("Either provider.prepareTokenRequest() or authorizationCode is required");
23595
+ }
23596
+ if (!provider.redirectUrl) {
23597
+ throw new Error("redirectUrl is required for authorization_code flow");
23598
+ }
23599
+ const codeVerifier = await provider.codeVerifier();
23600
+ tokenRequestParams = prepareAuthorizationCodeRequest(authorizationCode, codeVerifier, provider.redirectUrl);
23601
+ }
23602
+ const clientInformation = await provider.clientInformation();
23603
+ return executeTokenRequest(authorizationServerUrl, {
23604
+ metadata,
23605
+ tokenRequestParams,
23606
+ clientInformation: clientInformation ?? void 0,
23607
+ addClientAuthentication: provider.addClientAuthentication,
23608
+ resource,
23609
+ fetchFn
23610
+ });
23611
+ }
23612
+ async function registerClient(authorizationServerUrl, { metadata, clientMetadata, scope, fetchFn }) {
23613
+ let registrationUrl;
23614
+ if (metadata) {
23615
+ if (!metadata.registration_endpoint) {
23616
+ throw new Error("Incompatible auth server: does not support dynamic client registration");
23617
+ }
23618
+ registrationUrl = new URL(metadata.registration_endpoint);
23619
+ } else {
23620
+ registrationUrl = new URL("/register", authorizationServerUrl);
23621
+ }
23622
+ const response = await (fetchFn ?? fetch)(registrationUrl, {
23623
+ method: "POST",
23624
+ headers: {
23625
+ "Content-Type": "application/json"
23626
+ },
23627
+ body: JSON.stringify({
23628
+ ...clientMetadata,
23629
+ ...scope !== void 0 ? { scope } : {}
23630
+ })
23631
+ });
23632
+ if (!response.ok) {
23633
+ throw await parseErrorResponse(response);
23634
+ }
23635
+ return OAuthClientInformationFullSchema.parse(await response.json());
23636
+ }
23637
+
23638
+ // node_modules/eventsource-parser/dist/index.js
23639
+ var ParseError = class extends Error {
23640
+ constructor(message, options) {
23641
+ super(message), this.name = "ParseError", this.type = options.type, this.field = options.field, this.value = options.value, this.line = options.line;
23642
+ }
23643
+ };
23644
+ var LF = 10;
23645
+ var CR = 13;
23646
+ var SPACE = 32;
23647
+ function noop(_arg) {
23648
+ }
23649
+ function createParser(config2) {
23650
+ if (typeof config2 == "function")
23651
+ throw new TypeError(
23652
+ "`config` must be an object, got a function instead. Did you mean `createParser({onEvent: fn})`?"
23653
+ );
23654
+ const { onEvent = noop, onError = noop, onRetry = noop, onComment, maxBufferSize } = config2, pendingFragments = [];
23655
+ let pendingFragmentsLength = 0, isFirstChunk = true, id, data = "", dataLines = 0, eventType, terminated = false;
23656
+ function feed(chunk) {
23657
+ if (terminated)
23658
+ throw new Error(
23659
+ "Cannot feed parser: it was terminated after exceeding the configured max buffer size. Call `reset()` to resume parsing."
23660
+ );
23661
+ if (isFirstChunk && (isFirstChunk = false, chunk.charCodeAt(0) === 239 && chunk.charCodeAt(1) === 187 && chunk.charCodeAt(2) === 191 && (chunk = chunk.slice(3))), pendingFragments.length === 0) {
23662
+ const trailing2 = processLines(chunk);
23663
+ trailing2 !== "" && (pendingFragments.push(trailing2), pendingFragmentsLength = trailing2.length), checkBufferSize();
23664
+ return;
23665
+ }
23666
+ if (chunk.indexOf(`
23667
+ `) === -1 && chunk.indexOf("\r") === -1) {
23668
+ pendingFragments.push(chunk), pendingFragmentsLength += chunk.length, checkBufferSize();
23669
+ return;
23670
+ }
23671
+ pendingFragments.push(chunk);
23672
+ const input = pendingFragments.join("");
23673
+ pendingFragments.length = 0, pendingFragmentsLength = 0;
23674
+ const trailing = processLines(input);
23675
+ trailing !== "" && (pendingFragments.push(trailing), pendingFragmentsLength = trailing.length), checkBufferSize();
23676
+ }
23677
+ function checkBufferSize() {
23678
+ maxBufferSize !== void 0 && (pendingFragmentsLength + data.length <= maxBufferSize || (terminated = true, pendingFragments.length = 0, pendingFragmentsLength = 0, id = void 0, data = "", dataLines = 0, eventType = void 0, onError(
23679
+ new ParseError(`Buffered data exceeded max buffer size of ${maxBufferSize} characters`, {
23680
+ type: "max-buffer-size-exceeded"
23681
+ })
23682
+ )));
23683
+ }
23684
+ function processLines(chunk) {
23685
+ let searchIndex = 0;
23686
+ if (chunk.indexOf("\r") === -1) {
23687
+ let lfIndex = chunk.indexOf(`
23688
+ `, searchIndex);
23689
+ for (; lfIndex !== -1; ) {
23690
+ if (searchIndex === lfIndex) {
23691
+ dataLines > 0 && onEvent({ id, event: eventType, data }), id = void 0, data = "", dataLines = 0, eventType = void 0, searchIndex = lfIndex + 1, lfIndex = chunk.indexOf(`
23692
+ `, searchIndex);
23693
+ continue;
23694
+ }
23695
+ const firstCharCode = chunk.charCodeAt(searchIndex);
23696
+ if (isDataPrefix(chunk, searchIndex, firstCharCode)) {
23697
+ const valueStart = chunk.charCodeAt(searchIndex + 5) === SPACE ? searchIndex + 6 : searchIndex + 5, value = chunk.slice(valueStart, lfIndex);
23698
+ if (dataLines === 0 && chunk.charCodeAt(lfIndex + 1) === LF) {
23699
+ onEvent({ id, event: eventType, data: value }), id = void 0, data = "", eventType = void 0, searchIndex = lfIndex + 2, lfIndex = chunk.indexOf(`
23700
+ `, searchIndex);
23701
+ continue;
23702
+ }
23703
+ data = dataLines === 0 ? value : `${data}
23704
+ ${value}`, dataLines++;
23705
+ } else isEventPrefix(chunk, searchIndex, firstCharCode) ? eventType = chunk.slice(
23706
+ chunk.charCodeAt(searchIndex + 6) === SPACE ? searchIndex + 7 : searchIndex + 6,
23707
+ lfIndex
23708
+ ) || void 0 : parseLine(chunk, searchIndex, lfIndex);
23709
+ searchIndex = lfIndex + 1, lfIndex = chunk.indexOf(`
23710
+ `, searchIndex);
23711
+ }
23712
+ return chunk.slice(searchIndex);
23713
+ }
23714
+ for (; searchIndex < chunk.length; ) {
23715
+ const crIndex = chunk.indexOf("\r", searchIndex), lfIndex = chunk.indexOf(`
23716
+ `, searchIndex);
23717
+ let lineEnd = -1;
23718
+ 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)
23719
+ break;
23720
+ parseLine(chunk, searchIndex, lineEnd), searchIndex = lineEnd + 1, chunk.charCodeAt(searchIndex - 1) === CR && chunk.charCodeAt(searchIndex) === LF && searchIndex++;
23721
+ }
23722
+ return chunk.slice(searchIndex);
23723
+ }
23724
+ function parseLine(chunk, start, end) {
23725
+ if (start === end) {
23726
+ dispatchEvent();
23727
+ return;
23728
+ }
23729
+ const firstCharCode = chunk.charCodeAt(start);
23730
+ if (isDataPrefix(chunk, start, firstCharCode)) {
23731
+ const valueStart = chunk.charCodeAt(start + 5) === SPACE ? start + 6 : start + 5, value2 = chunk.slice(valueStart, end);
23732
+ data = dataLines === 0 ? value2 : `${data}
23733
+ ${value2}`, dataLines++;
23734
+ return;
23735
+ }
23736
+ if (isEventPrefix(chunk, start, firstCharCode)) {
23737
+ eventType = chunk.slice(chunk.charCodeAt(start + 6) === SPACE ? start + 7 : start + 6, end) || void 0;
23738
+ return;
23739
+ }
23740
+ if (firstCharCode === 105 && chunk.charCodeAt(start + 1) === 100 && chunk.charCodeAt(start + 2) === 58) {
23741
+ const value2 = chunk.slice(chunk.charCodeAt(start + 3) === SPACE ? start + 4 : start + 3, end);
23742
+ id = value2.includes("\0") ? void 0 : value2;
23743
+ return;
23744
+ }
23745
+ if (firstCharCode === 58) {
23746
+ if (onComment) {
23747
+ const line2 = chunk.slice(start, end);
23748
+ onComment(line2.slice(chunk.charCodeAt(start + 1) === SPACE ? 2 : 1));
23749
+ }
23750
+ return;
23751
+ }
23752
+ const line = chunk.slice(start, end), fieldSeparatorIndex = line.indexOf(":");
23753
+ if (fieldSeparatorIndex === -1) {
23754
+ processField(line, "", line);
23755
+ return;
23756
+ }
23757
+ const field = line.slice(0, fieldSeparatorIndex), offset = line.charCodeAt(fieldSeparatorIndex + 1) === SPACE ? 2 : 1, value = line.slice(fieldSeparatorIndex + offset);
23758
+ processField(field, value, line);
23759
+ }
23760
+ function processField(field, value, line) {
23761
+ switch (field) {
23762
+ case "event":
23763
+ eventType = value || void 0;
23764
+ break;
23765
+ case "data":
23766
+ data = dataLines === 0 ? value : `${data}
23767
+ ${value}`, dataLines++;
23768
+ break;
23769
+ case "id":
23770
+ id = value.includes("\0") ? void 0 : value;
23771
+ break;
23772
+ case "retry":
23773
+ /^\d+$/.test(value) ? onRetry(parseInt(value, 10)) : onError(
23774
+ new ParseError(`Invalid \`retry\` value: "${value}"`, {
23775
+ type: "invalid-retry",
23776
+ value,
23777
+ line
23778
+ })
23779
+ );
23780
+ break;
23781
+ default:
23782
+ onError(
23783
+ new ParseError(
23784
+ `Unknown field "${field.length > 20 ? `${field.slice(0, 20)}\u2026` : field}"`,
23785
+ { type: "unknown-field", field, value, line }
23786
+ )
23787
+ );
23788
+ break;
23789
+ }
23790
+ }
23791
+ function dispatchEvent() {
23792
+ dataLines > 0 && onEvent({
23793
+ id,
23794
+ event: eventType,
23795
+ data
23796
+ }), id = void 0, data = "", dataLines = 0, eventType = void 0;
20990
23797
  }
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)"}`;
23798
+ function reset(options = {}) {
23799
+ if (options.consume && pendingFragments.length > 0) {
23800
+ const incompleteLine = pendingFragments.join("");
23801
+ parseLine(incompleteLine, 0, incompleteLine.length);
20998
23802
  }
20999
- if (value === null) continue;
21000
- const problem = typeError(key, schema, value);
21001
- if (problem) return problem;
23803
+ isFirstChunk = true, id = void 0, data = "", dataLines = 0, eventType = void 0, pendingFragments.length = 0, pendingFragmentsLength = 0, terminated = false;
21002
23804
  }
21003
- return null;
23805
+ return { feed, reset };
23806
+ }
23807
+ function isDataPrefix(chunk, i, firstCharCode) {
23808
+ return firstCharCode === 100 && chunk.charCodeAt(i + 1) === 97 && chunk.charCodeAt(i + 2) === 116 && chunk.charCodeAt(i + 3) === 97 && chunk.charCodeAt(i + 4) === 58;
23809
+ }
23810
+ function isEventPrefix(chunk, i, firstCharCode) {
23811
+ 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
23812
  }
21005
23813
 
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);
23814
+ // node_modules/eventsource-parser/dist/stream.js
23815
+ var EventSourceParserStream = class extends TransformStream {
23816
+ constructor({ onError, onRetry, onComment, maxBufferSize } = {}) {
23817
+ let parser;
23818
+ super({
23819
+ start(controller) {
23820
+ parser = createParser({
23821
+ onEvent: (event) => {
23822
+ controller.enqueue(event);
23823
+ },
23824
+ onError(error2) {
23825
+ typeof onError == "function" && onError(error2), (onError === "terminate" || error2.type === "max-buffer-size-exceeded") && controller.error(error2);
23826
+ },
23827
+ onRetry,
23828
+ onComment,
23829
+ maxBufferSize
23830
+ });
23831
+ },
23832
+ transform(chunk) {
23833
+ parser.feed(chunk);
23834
+ }
23835
+ });
21020
23836
  }
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
- }
23837
+ };
21025
23838
 
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;
23839
+ // node_modules/@modelcontextprotocol/sdk/dist/esm/client/streamableHttp.js
23840
+ var DEFAULT_STREAMABLE_HTTP_RECONNECTION_OPTIONS = {
23841
+ initialReconnectionDelay: 1e3,
23842
+ maxReconnectionDelay: 3e4,
23843
+ reconnectionDelayGrowFactor: 1.5,
23844
+ maxRetries: 2
23845
+ };
23846
+ var StreamableHTTPError = class extends Error {
23847
+ constructor(code, message) {
23848
+ super(`Streamable HTTP error: ${message}`);
23849
+ this.code = code;
23850
+ }
23851
+ };
23852
+ var StreamableHTTPClientTransport = class {
23853
+ constructor(url2, opts) {
23854
+ this._hasCompletedAuthFlow = false;
23855
+ this._url = url2;
23856
+ this._resourceMetadataUrl = void 0;
23857
+ this._scope = void 0;
23858
+ this._requestInit = opts?.requestInit;
23859
+ this._authProvider = opts?.authProvider;
23860
+ this._fetch = opts?.fetch;
23861
+ this._fetchWithInit = createFetchWithInit(opts?.fetch, opts?.requestInit);
23862
+ this._sessionId = opts?.sessionId;
23863
+ this._reconnectionOptions = opts?.reconnectionOptions ?? DEFAULT_STREAMABLE_HTTP_RECONNECTION_OPTIONS;
23864
+ }
23865
+ async _authThenStart() {
23866
+ if (!this._authProvider) {
23867
+ throw new UnauthorizedError("No auth provider");
23868
+ }
23869
+ let result;
21035
23870
  try {
21036
- return fs.statSync(full).isFile() ? full : null;
21037
- } catch {
21038
- return null;
23871
+ result = await auth(this._authProvider, {
23872
+ serverUrl: this._url,
23873
+ resourceMetadataUrl: this._resourceMetadataUrl,
23874
+ scope: this._scope,
23875
+ fetchFn: this._fetchWithInit
23876
+ });
23877
+ } catch (error2) {
23878
+ this.onerror?.(error2);
23879
+ throw error2;
23880
+ }
23881
+ if (result !== "AUTHORIZED") {
23882
+ throw new UnauthorizedError();
21039
23883
  }
23884
+ return await this._startOrAuthSse({ resumptionToken: void 0 });
21040
23885
  }
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;
23886
+ async _commonHeaders() {
23887
+ const headers = {};
23888
+ if (this._authProvider) {
23889
+ const tokens = await this._authProvider.tokens();
23890
+ if (tokens) {
23891
+ headers["Authorization"] = `Bearer ${tokens.access_token}`;
21052
23892
  }
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);
23893
+ }
23894
+ if (this._sessionId) {
23895
+ headers["mcp-session-id"] = this._sessionId;
23896
+ }
23897
+ if (this._protocolVersion) {
23898
+ headers["mcp-protocol-version"] = this._protocolVersion;
23899
+ }
23900
+ const extraHeaders = normalizeHeaders(this._requestInit?.headers);
23901
+ return new Headers({
23902
+ ...headers,
23903
+ ...extraHeaders
23904
+ });
23905
+ }
23906
+ async _startOrAuthSse(options) {
23907
+ const { resumptionToken } = options;
23908
+ try {
23909
+ const headers = await this._commonHeaders();
23910
+ headers.set("Accept", "text/event-stream");
23911
+ if (resumptionToken) {
23912
+ headers.set("last-event-id", resumptionToken);
23913
+ }
23914
+ const response = await (this._fetch ?? fetch)(this._url, {
23915
+ method: "GET",
23916
+ headers,
23917
+ signal: this._abortController?.signal
23918
+ });
23919
+ if (!response.ok) {
23920
+ await response.body?.cancel();
23921
+ if (response.status === 401 && this._authProvider) {
23922
+ return await this._authThenStart();
23923
+ }
23924
+ if (response.status === 405) {
23925
+ return;
23926
+ }
23927
+ throw new StreamableHTTPError(response.status, `Failed to open SSE stream: ${response.statusText}`);
21058
23928
  }
23929
+ this._handleSseStream(response.body, options, true);
23930
+ } catch (error2) {
23931
+ this.onerror?.(error2);
23932
+ throw error2;
21059
23933
  }
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
- );
23934
+ }
23935
+ /**
23936
+ * Calculates the next reconnection delay using backoff algorithm
23937
+ *
23938
+ * @param attempt Current reconnection attempt count for the specific stream
23939
+ * @returns Time to wait in milliseconds before next reconnection attempt
23940
+ */
23941
+ _getNextReconnectionDelay(attempt) {
23942
+ if (this._serverRetryMs !== void 0) {
23943
+ return this._serverRetryMs;
21064
23944
  }
21065
- if (hits.length === 1) return hits[0];
21066
- level = next;
23945
+ const initialDelay = this._reconnectionOptions.initialReconnectionDelay;
23946
+ const growFactor = this._reconnectionOptions.reconnectionDelayGrowFactor;
23947
+ const maxDelay = this._reconnectionOptions.maxReconnectionDelay;
23948
+ return Math.min(initialDelay * Math.pow(growFactor, attempt), maxDelay);
21067
23949
  }
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)}`);
23950
+ /**
23951
+ * Schedule a reconnection attempt using server-provided retry interval or backoff
23952
+ *
23953
+ * @param lastEventId The ID of the last received event for resumability
23954
+ * @param attemptCount Current reconnection attempt count for this specific stream
23955
+ */
23956
+ _scheduleReconnection(options, attemptCount = 0) {
23957
+ const maxRetries = this._reconnectionOptions.maxRetries;
23958
+ if (attemptCount >= maxRetries) {
23959
+ this.onerror?.(new Error(`Maximum reconnection attempts (${maxRetries}) exceeded.`));
23960
+ return;
21080
23961
  }
21081
- return x;
23962
+ const delay = this._getNextReconnectionDelay(attemptCount);
23963
+ this._reconnectionTimeout = setTimeout(() => {
23964
+ this._startOrAuthSse(options).catch((error2) => {
23965
+ this.onerror?.(new Error(`Failed to reconnect SSE stream: ${error2 instanceof Error ? error2.message : String(error2)}`));
23966
+ this._scheduleReconnection(options, attemptCount + 1);
23967
+ });
23968
+ }, delay);
21082
23969
  }
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)]));
23970
+ _handleSseStream(stream, options, isReconnectable) {
23971
+ if (!stream) {
23972
+ return;
23973
+ }
23974
+ const { onresumptiontoken, replayMessageId } = options;
23975
+ let lastEventId;
23976
+ let hasPrimingEvent = false;
23977
+ let receivedResponse = false;
23978
+ const processStream = async () => {
23979
+ try {
23980
+ const reader = stream.pipeThrough(new TextDecoderStream()).pipeThrough(new EventSourceParserStream({
23981
+ onRetry: (retryMs) => {
23982
+ this._serverRetryMs = retryMs;
23983
+ }
23984
+ })).getReader();
23985
+ while (true) {
23986
+ const { value: event, done } = await reader.read();
23987
+ if (done) {
23988
+ break;
23989
+ }
23990
+ if (event.id) {
23991
+ lastEventId = event.id;
23992
+ hasPrimingEvent = true;
23993
+ onresumptiontoken?.(event.id);
23994
+ }
23995
+ if (!event.data) {
23996
+ continue;
23997
+ }
23998
+ if (!event.event || event.event === "message") {
23999
+ try {
24000
+ const message = JSONRPCMessageSchema.parse(JSON.parse(event.data));
24001
+ if (isJSONRPCResultResponse(message)) {
24002
+ receivedResponse = true;
24003
+ if (replayMessageId !== void 0) {
24004
+ message.id = replayMessageId;
24005
+ }
24006
+ }
24007
+ this.onmessage?.(message);
24008
+ } catch (error2) {
24009
+ this.onerror?.(error2);
24010
+ }
24011
+ }
24012
+ }
24013
+ const canResume = isReconnectable || hasPrimingEvent;
24014
+ const needsReconnect = canResume && !receivedResponse;
24015
+ if (needsReconnect && this._abortController && !this._abortController.signal.aborted) {
24016
+ this._scheduleReconnection({
24017
+ resumptionToken: lastEventId,
24018
+ onresumptiontoken,
24019
+ replayMessageId
24020
+ }, 0);
24021
+ }
24022
+ } catch (error2) {
24023
+ this.onerror?.(new Error(`SSE stream disconnected: ${error2}`));
24024
+ const canResume = isReconnectable || hasPrimingEvent;
24025
+ const needsReconnect = canResume && !receivedResponse;
24026
+ if (needsReconnect && this._abortController && !this._abortController.signal.aborted) {
24027
+ try {
24028
+ this._scheduleReconnection({
24029
+ resumptionToken: lastEventId,
24030
+ onresumptiontoken,
24031
+ replayMessageId
24032
+ }, 0);
24033
+ } catch (error3) {
24034
+ this.onerror?.(new Error(`Failed to reconnect: ${error3 instanceof Error ? error3.message : String(error3)}`));
24035
+ }
24036
+ }
24037
+ }
24038
+ };
24039
+ processStream();
21086
24040
  }
21087
- return value;
24041
+ async start() {
24042
+ if (this._abortController) {
24043
+ throw new Error("StreamableHTTPClientTransport already started! If using Client class, note that connect() calls start() automatically.");
24044
+ }
24045
+ this._abortController = new AbortController();
24046
+ }
24047
+ /**
24048
+ * 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.
24049
+ */
24050
+ async finishAuth(authorizationCode) {
24051
+ if (!this._authProvider) {
24052
+ throw new UnauthorizedError("No auth provider");
24053
+ }
24054
+ const result = await auth(this._authProvider, {
24055
+ serverUrl: this._url,
24056
+ authorizationCode,
24057
+ resourceMetadataUrl: this._resourceMetadataUrl,
24058
+ scope: this._scope,
24059
+ fetchFn: this._fetchWithInit
24060
+ });
24061
+ if (result !== "AUTHORIZED") {
24062
+ throw new UnauthorizedError("Failed to authorize");
24063
+ }
24064
+ }
24065
+ async close() {
24066
+ if (this._reconnectionTimeout) {
24067
+ clearTimeout(this._reconnectionTimeout);
24068
+ this._reconnectionTimeout = void 0;
24069
+ }
24070
+ this._abortController?.abort();
24071
+ this.onclose?.();
24072
+ }
24073
+ async send(message, options) {
24074
+ try {
24075
+ const { resumptionToken, onresumptiontoken } = options || {};
24076
+ if (resumptionToken) {
24077
+ this._startOrAuthSse({ resumptionToken, replayMessageId: isJSONRPCRequest(message) ? message.id : void 0 }).catch((err) => this.onerror?.(err));
24078
+ return;
24079
+ }
24080
+ const headers = await this._commonHeaders();
24081
+ headers.set("content-type", "application/json");
24082
+ headers.set("accept", "application/json, text/event-stream");
24083
+ const init = {
24084
+ ...this._requestInit,
24085
+ method: "POST",
24086
+ headers,
24087
+ body: JSON.stringify(message),
24088
+ signal: this._abortController?.signal
24089
+ };
24090
+ const response = await (this._fetch ?? fetch)(this._url, init);
24091
+ const sessionId = response.headers.get("mcp-session-id");
24092
+ if (sessionId) {
24093
+ this._sessionId = sessionId;
24094
+ }
24095
+ if (!response.ok) {
24096
+ const text = await response.text().catch(() => null);
24097
+ if (response.status === 401 && this._authProvider) {
24098
+ if (this._hasCompletedAuthFlow) {
24099
+ throw new StreamableHTTPError(401, "Server returned 401 after successful authentication");
24100
+ }
24101
+ const { resourceMetadataUrl, scope } = extractWWWAuthenticateParams(response);
24102
+ this._resourceMetadataUrl = resourceMetadataUrl;
24103
+ this._scope = scope;
24104
+ const result = await auth(this._authProvider, {
24105
+ serverUrl: this._url,
24106
+ resourceMetadataUrl: this._resourceMetadataUrl,
24107
+ scope: this._scope,
24108
+ fetchFn: this._fetchWithInit
24109
+ });
24110
+ if (result !== "AUTHORIZED") {
24111
+ throw new UnauthorizedError();
24112
+ }
24113
+ this._hasCompletedAuthFlow = true;
24114
+ return this.send(message);
24115
+ }
24116
+ if (response.status === 403 && this._authProvider) {
24117
+ const { resourceMetadataUrl, scope, error: error2 } = extractWWWAuthenticateParams(response);
24118
+ if (error2 === "insufficient_scope") {
24119
+ const wwwAuthHeader = response.headers.get("WWW-Authenticate");
24120
+ if (this._lastUpscopingHeader === wwwAuthHeader) {
24121
+ throw new StreamableHTTPError(403, "Server returned 403 after trying upscoping");
24122
+ }
24123
+ if (scope) {
24124
+ this._scope = scope;
24125
+ }
24126
+ if (resourceMetadataUrl) {
24127
+ this._resourceMetadataUrl = resourceMetadataUrl;
24128
+ }
24129
+ this._lastUpscopingHeader = wwwAuthHeader ?? void 0;
24130
+ const result = await auth(this._authProvider, {
24131
+ serverUrl: this._url,
24132
+ resourceMetadataUrl: this._resourceMetadataUrl,
24133
+ scope: this._scope,
24134
+ fetchFn: this._fetch
24135
+ });
24136
+ if (result !== "AUTHORIZED") {
24137
+ throw new UnauthorizedError();
24138
+ }
24139
+ return this.send(message);
24140
+ }
24141
+ }
24142
+ throw new StreamableHTTPError(response.status, `Error POSTing to endpoint: ${text}`);
24143
+ }
24144
+ this._hasCompletedAuthFlow = false;
24145
+ this._lastUpscopingHeader = void 0;
24146
+ if (response.status === 202) {
24147
+ await response.body?.cancel();
24148
+ if (isInitializedNotification(message)) {
24149
+ this._startOrAuthSse({ resumptionToken: void 0 }).catch((err) => this.onerror?.(err));
24150
+ }
24151
+ return;
24152
+ }
24153
+ const messages = Array.isArray(message) ? message : [message];
24154
+ const hasRequests = messages.filter((msg) => "method" in msg && "id" in msg && msg.id !== void 0).length > 0;
24155
+ const contentType = response.headers.get("content-type");
24156
+ if (hasRequests) {
24157
+ if (contentType?.includes("text/event-stream")) {
24158
+ this._handleSseStream(response.body, { onresumptiontoken }, false);
24159
+ } else if (contentType?.includes("application/json")) {
24160
+ const data = await response.json();
24161
+ const responseMessages = Array.isArray(data) ? data.map((msg) => JSONRPCMessageSchema.parse(msg)) : [JSONRPCMessageSchema.parse(data)];
24162
+ for (const msg of responseMessages) {
24163
+ this.onmessage?.(msg);
24164
+ }
24165
+ } else {
24166
+ await response.body?.cancel();
24167
+ throw new StreamableHTTPError(-1, `Unexpected content type: ${contentType}`);
24168
+ }
24169
+ } else {
24170
+ await response.body?.cancel();
24171
+ }
24172
+ } catch (error2) {
24173
+ this.onerror?.(error2);
24174
+ throw error2;
24175
+ }
24176
+ }
24177
+ get sessionId() {
24178
+ return this._sessionId;
24179
+ }
24180
+ /**
24181
+ * Terminates the current session by sending a DELETE request to the server.
24182
+ *
24183
+ * Clients that no longer need a particular session
24184
+ * (e.g., because the user is leaving the client application) SHOULD send an
24185
+ * HTTP DELETE to the MCP endpoint with the Mcp-Session-Id header to explicitly
24186
+ * terminate the session.
24187
+ *
24188
+ * The server MAY respond with HTTP 405 Method Not Allowed, indicating that
24189
+ * the server does not allow clients to terminate sessions.
24190
+ */
24191
+ async terminateSession() {
24192
+ if (!this._sessionId) {
24193
+ return;
24194
+ }
24195
+ try {
24196
+ const headers = await this._commonHeaders();
24197
+ const init = {
24198
+ ...this._requestInit,
24199
+ method: "DELETE",
24200
+ headers,
24201
+ signal: this._abortController?.signal
24202
+ };
24203
+ const response = await (this._fetch ?? fetch)(this._url, init);
24204
+ await response.body?.cancel();
24205
+ if (!response.ok && response.status !== 405) {
24206
+ throw new StreamableHTTPError(response.status, `Failed to terminate session: ${response.statusText}`);
24207
+ }
24208
+ this._sessionId = void 0;
24209
+ } catch (error2) {
24210
+ this.onerror?.(error2);
24211
+ throw error2;
24212
+ }
24213
+ }
24214
+ setProtocolVersion(version2) {
24215
+ this._protocolVersion = version2;
24216
+ }
24217
+ get protocolVersion() {
24218
+ return this._protocolVersion;
24219
+ }
24220
+ /**
24221
+ * Resume an SSE stream from a previous event ID.
24222
+ * Opens a GET SSE connection with Last-Event-ID header to replay missed events.
24223
+ *
24224
+ * @param lastEventId The event ID to resume from
24225
+ * @param options Optional callback to receive new resumption tokens
24226
+ */
24227
+ async resumeStream(lastEventId, options) {
24228
+ await this._startOrAuthSse({
24229
+ resumptionToken: lastEventId,
24230
+ onresumptiontoken: options?.onresumptiontoken
24231
+ });
24232
+ }
24233
+ };
24234
+
24235
+ // src/services.ts
24236
+ import dns from "dns/promises";
24237
+ import fs2 from "fs";
24238
+ import net from "net";
24239
+ import os from "os";
24240
+ import path2 from "path";
24241
+ import { Readable } from "stream";
24242
+ import { pipeline } from "stream/promises";
24243
+ var SERVICES_FILE = path2.resolve(
24244
+ process.env.GOATEDIT_SERVICES_FILE || path2.join(os.homedir(), ".goatedit", "services.json")
24245
+ );
24246
+ var MAX_DOWNLOAD_BYTES = 4 * 1024 ** 3;
24247
+ var CALL_TIMEOUT_MS = 12e4;
24248
+ function readConfig() {
24249
+ let raw;
24250
+ try {
24251
+ raw = fs2.readFileSync(SERVICES_FILE, "utf8");
24252
+ } catch {
24253
+ return {};
24254
+ }
24255
+ const parsed = JSON.parse(raw);
24256
+ const servers = parsed && typeof parsed === "object" ? parsed.servers : null;
24257
+ return servers && typeof servers === "object" ? servers : {};
21088
24258
  }
21089
- function withRunProject(stepArgs, projectId) {
21090
- if (typeof projectId !== "string" || !projectId || typeof stepArgs.projectId === "string") return stepArgs;
21091
- return { ...stepArgs, projectId };
24259
+ var clients = /* @__PURE__ */ new Map();
24260
+ async function connect(name, config2) {
24261
+ const client = new Client({ name: "goatedit-studio", version: "1.0.0" });
24262
+ if ("url" in config2) {
24263
+ await client.connect(new StreamableHTTPClientTransport(new URL(config2.url), { requestInit: { headers: config2.headers ?? {} } }));
24264
+ } else {
24265
+ const env = {};
24266
+ for (const [k, v] of Object.entries(process.env)) if (typeof v === "string") env[k] = v;
24267
+ await client.connect(new StdioClientTransport({
24268
+ command: config2.command,
24269
+ args: config2.args ?? [],
24270
+ env: { ...env, ...config2.env ?? {} },
24271
+ ...config2.cwd ? { cwd: config2.cwd } : {},
24272
+ stderr: "ignore"
24273
+ }));
24274
+ }
24275
+ client.onclose = () => {
24276
+ clients.delete(name);
24277
+ };
24278
+ return client;
21092
24279
  }
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);
24280
+ function clientFor(name) {
24281
+ const config2 = readConfig()[name];
24282
+ if (!config2) throw new Error(`No service "${name}" in ${SERVICES_FILE}.`);
24283
+ let pending = clients.get(name);
24284
+ if (!pending) {
24285
+ pending = connect(name, config2);
24286
+ clients.set(name, pending);
24287
+ pending.catch(() => clients.delete(name));
24288
+ }
24289
+ return pending;
24290
+ }
24291
+ async function listServices() {
24292
+ const names = Object.keys(readConfig());
24293
+ return Promise.all(names.map(async (server2) => {
24294
+ try {
24295
+ const { tools } = await (await clientFor(server2)).listTools();
24296
+ return { server: server2, tools: tools.map((t) => ({ name: t.name, ...t.description ? { description: t.description } : {} })) };
24297
+ } catch (err) {
24298
+ return { server: server2, error: err instanceof Error ? err.message : String(err) };
24299
+ }
24300
+ }));
24301
+ }
24302
+ async function callService(server2, tool, args = {}) {
24303
+ const client = await clientFor(server2);
24304
+ const result = await client.callTool({ name: tool, arguments: args }, void 0, { timeout: CALL_TIMEOUT_MS });
24305
+ return result;
24306
+ }
24307
+ function isPrivateAddress(ip) {
24308
+ if (net.isIPv4(ip)) {
24309
+ const [a, b] = ip.split(".").map(Number);
24310
+ 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;
24311
+ }
24312
+ const v6 = ip.toLowerCase();
24313
+ if (v6.startsWith("::ffff:")) return isPrivateAddress(v6.slice(7));
24314
+ return v6 === "::1" || v6 === "::" || v6.startsWith("fc") || v6.startsWith("fd") || v6.startsWith("fe80");
24315
+ }
24316
+ async function checkUrl(raw) {
24317
+ let url2;
24318
+ try {
24319
+ url2 = new URL(raw);
24320
+ } catch {
24321
+ throw new Error("Not a URL.");
21099
24322
  }
21100
- return index;
24323
+ if (url2.protocol !== "https:") throw new Error("Only https links are downloaded.");
24324
+ const addresses = await dns.lookup(url2.hostname, { all: true });
24325
+ if (!addresses.length || addresses.some((a) => isPrivateAddress(a.address))) throw new Error(`${url2.hostname} is not a public address.`);
24326
+ return url2;
24327
+ }
24328
+ var safeName = (s) => s.replace(/[^\w.-]+/g, "_").replace(/^[._]+/, "").slice(0, 80) || "file";
24329
+ async function downloadToAssets(assetsDir, rawUrl, name) {
24330
+ let url2 = await checkUrl(rawUrl);
24331
+ let res = null;
24332
+ for (let hop = 0; hop < 5; hop++) {
24333
+ res = await fetch(url2, { redirect: "manual" });
24334
+ const next = res.status >= 300 && res.status < 400 ? res.headers.get("location") : null;
24335
+ if (!next) break;
24336
+ url2 = await checkUrl(new URL(next, url2).toString());
24337
+ res = null;
24338
+ }
24339
+ if (!res) throw new Error("Too many redirects.");
24340
+ if (!res.ok || !res.body) throw new Error(`The download failed: HTTP ${res.status}.`);
24341
+ const declared = Number(res.headers.get("content-length") || 0);
24342
+ if (declared > MAX_DOWNLOAD_BYTES) throw new Error("The file is too big.");
24343
+ const fromUrl = path2.basename(url2.pathname);
24344
+ const file = safeName(name || fromUrl);
24345
+ const ext = path2.extname(file) ? "" : path2.extname(fromUrl);
24346
+ const day = (/* @__PURE__ */ new Date()).toISOString().slice(0, 10);
24347
+ const rel = path2.join("GoatEdit Downloads", day, `${Date.now().toString(36)}-${file}${ext}`);
24348
+ const dest = path2.join(assetsDir, rel);
24349
+ fs2.mkdirSync(path2.dirname(dest), { recursive: true });
24350
+ const partial2 = `${dest}.part`;
24351
+ let bytes = 0;
24352
+ const counted = Readable.fromWeb(res.body);
24353
+ counted.on("data", (chunk) => {
24354
+ bytes += chunk.length;
24355
+ if (bytes > MAX_DOWNLOAD_BYTES) counted.destroy(new Error("The file is too big."));
24356
+ });
24357
+ try {
24358
+ await pipeline(counted, fs2.createWriteStream(partial2));
24359
+ fs2.renameSync(partial2, dest);
24360
+ } catch (err) {
24361
+ fs2.rmSync(partial2, { force: true });
24362
+ throw err;
24363
+ }
24364
+ return { rel, path: dest, bytes, contentType: res.headers.get("content-type") || "" };
21101
24365
  }
21102
24366
 
21103
24367
  // src/index.ts
@@ -21126,32 +24390,32 @@ function isLoopbackHost(host) {
21126
24390
  return false;
21127
24391
  }
21128
24392
  }
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");
24393
+ var CONTROLLER_TOKEN = process.env.GOATEDIT_CONTROLLER_TOKEN || crypto2.randomBytes(32).toString("hex");
24394
+ var CONTROLLER_TOKEN_FILE = path3.join(os2.homedir(), ".goatedit", "mcp-controller-token");
21131
24395
  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);
24396
+ fs3.mkdirSync(path3.dirname(CONTROLLER_TOKEN_FILE), { recursive: true, mode: 448 });
24397
+ fs3.writeFileSync(CONTROLLER_TOKEN_FILE, CONTROLLER_TOKEN, { mode: 384 });
24398
+ fs3.chmodSync(CONTROLLER_TOKEN_FILE, 384);
21135
24399
  }
21136
24400
  function hasControllerToken(req) {
21137
24401
  const header = req.headers.authorization || "";
21138
24402
  const presented = header.startsWith("Bearer ") ? header.slice(7) : new URL(req.url || "/", "http://localhost").searchParams.get("token") || "";
21139
24403
  const a = Buffer.from(presented);
21140
24404
  const b = Buffer.from(CONTROLLER_TOKEN);
21141
- return a.length === b.length && crypto.timingSafeEqual(a, b);
24405
+ return a.length === b.length && crypto2.timingSafeEqual(a, b);
21142
24406
  }
21143
24407
  var REQUEST_TIMEOUT_MS = 3e4;
21144
- var LOCAL_ASSETS_DIR = path2.resolve(
21145
- process.env.GOATEDIT_ASSETS_DIR || path2.join(os.homedir(), "Movies")
24408
+ var LOCAL_ASSETS_DIR = path3.resolve(
24409
+ process.env.GOATEDIT_ASSETS_DIR || path3.join(os2.homedir(), "Movies")
21146
24410
  );
21147
- var FRAMES_DIR = path2.resolve(
21148
- process.env.GOATEDIT_FRAMES_DIR || path2.join(os.homedir(), ".goatedit", "frames")
24411
+ var FRAMES_DIR = path3.resolve(
24412
+ process.env.GOATEDIT_FRAMES_DIR || path3.join(os2.homedir(), ".goatedit", "frames")
21149
24413
  );
21150
24414
  var VERSION = (() => {
21151
- const here = path2.dirname(fileURLToPath(import.meta.url));
24415
+ const here = path3.dirname(fileURLToPath(import.meta.url));
21152
24416
  for (const rel of ["../package.json", "../../../package.json"]) {
21153
24417
  try {
21154
- const pkg = JSON.parse(fs2.readFileSync(path2.join(here, rel), "utf8"));
24418
+ const pkg = JSON.parse(fs3.readFileSync(path3.join(here, rel), "utf8"));
21155
24419
  if (pkg.name === "goatedit-mcp") return String(pkg.version);
21156
24420
  } catch {
21157
24421
  }
@@ -21180,18 +24444,18 @@ var MEDIA_TYPES = {
21180
24444
  ".glb": { mime: "model/gltf-binary", kind: "model" }
21181
24445
  };
21182
24446
  function mediaUrl(rel) {
21183
- return `http://localhost:${WEBSOCKET_PORT}/media/${rel.split(path2.sep).map(encodeURIComponent).join("/")}`;
24447
+ return `http://localhost:${WEBSOCKET_PORT}/media/${rel.split(path3.sep).map(encodeURIComponent).join("/")}`;
21184
24448
  }
21185
24449
  var MAX_LISTED_ASSETS = 500;
21186
24450
  var MAX_ASSET_DEPTH = 4;
21187
24451
  async function handleListLocalAssets(args = {}) {
21188
- if (!fs2.existsSync(LOCAL_ASSETS_DIR)) {
24452
+ if (!fs3.existsSync(LOCAL_ASSETS_DIR)) {
21189
24453
  throw new Error(
21190
24454
  `Assets directory does not exist: ${LOCAL_ASSETS_DIR}. Set GOATEDIT_ASSETS_DIR to a folder of media.`
21191
24455
  );
21192
24456
  }
21193
- const start = path2.resolve(LOCAL_ASSETS_DIR, args.folder || "");
21194
- if (start !== LOCAL_ASSETS_DIR && !start.startsWith(LOCAL_ASSETS_DIR + path2.sep)) {
24457
+ const start = path3.resolve(LOCAL_ASSETS_DIR, args.folder || "");
24458
+ if (start !== LOCAL_ASSETS_DIR && !start.startsWith(LOCAL_ASSETS_DIR + path3.sep)) {
21195
24459
  throw new Error("folder must be inside the assets directory.");
21196
24460
  }
21197
24461
  const files = [];
@@ -21199,7 +24463,7 @@ async function handleListLocalAssets(args = {}) {
21199
24463
  const walk = (dir, depth) => {
21200
24464
  let entries;
21201
24465
  try {
21202
- entries = fs2.readdirSync(dir, { withFileTypes: true });
24466
+ entries = fs3.readdirSync(dir, { withFileTypes: true });
21203
24467
  } catch {
21204
24468
  return;
21205
24469
  }
@@ -21210,17 +24474,17 @@ async function handleListLocalAssets(args = {}) {
21210
24474
  return;
21211
24475
  }
21212
24476
  if (entry.name.startsWith(".")) continue;
21213
- const full = path2.join(dir, entry.name);
24477
+ const full = path3.join(dir, entry.name);
21214
24478
  if (entry.isDirectory()) {
21215
24479
  if (depth < MAX_ASSET_DEPTH) walk(full, depth + 1);
21216
24480
  continue;
21217
24481
  }
21218
- const type = MEDIA_TYPES[path2.extname(entry.name).toLowerCase()];
24482
+ const type = MEDIA_TYPES[path3.extname(entry.name).toLowerCase()];
21219
24483
  if (!type || !entry.isFile()) continue;
21220
- const rel = path2.relative(LOCAL_ASSETS_DIR, full);
24484
+ const rel = path3.relative(LOCAL_ASSETS_DIR, full);
21221
24485
  let bytes = 0;
21222
24486
  try {
21223
- bytes = fs2.statSync(full).size;
24487
+ bytes = fs3.statSync(full).size;
21224
24488
  } catch {
21225
24489
  }
21226
24490
  files.push({ name: entry.name, path: rel, type: type.kind, bytes, url: mediaUrl(rel) });
@@ -21236,10 +24500,10 @@ async function handleListLocalAssets(args = {}) {
21236
24500
  async function handleFindLocalFile(args = {}) {
21237
24501
  const hit = findLocalFile(LOCAL_ASSETS_DIR, String(args.filename ?? ""), MAX_ASSET_DEPTH);
21238
24502
  if (!hit) return null;
21239
- const type = MEDIA_TYPES[path2.extname(hit).toLowerCase()];
24503
+ const type = MEDIA_TYPES[path3.extname(hit).toLowerCase()];
21240
24504
  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 };
24505
+ const rel = path3.relative(LOCAL_ASSETS_DIR, hit);
24506
+ return { name: path3.basename(hit), path: rel, url: mediaUrl(rel), contentType: type.mime };
21243
24507
  }
21244
24508
  function audioDuration(file) {
21245
24509
  try {
@@ -21258,15 +24522,15 @@ async function handleGenerateVoiceover(text, projectId) {
21258
24522
  throw new Error("generate_voiceover needs macOS `say`. Not available on this platform.");
21259
24523
  }
21260
24524
  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");
24525
+ const filePath = path3.join(LOCAL_ASSETS_DIR, filename);
24526
+ fs3.mkdirSync(LOCAL_ASSETS_DIR, { recursive: true });
24527
+ const scriptPath = path3.join(LOCAL_ASSETS_DIR, `.voiceover_${Date.now()}.txt`);
24528
+ fs3.writeFileSync(scriptPath, text, "utf8");
21265
24529
  try {
21266
24530
  execFileSync("say", ["-o", filePath, "-f", scriptPath], { stdio: "ignore" });
21267
24531
  const duration3 = audioDuration(filePath) ?? text.split(/\s+/).length * 0.45 + 1;
21268
24532
  const audioAsset = {
21269
- id: `media-${crypto.randomUUID()}`,
24533
+ id: `media-${crypto2.randomUUID()}`,
21270
24534
  name: filename,
21271
24535
  type: "audio",
21272
24536
  duration: duration3,
@@ -21279,7 +24543,7 @@ async function handleGenerateVoiceover(text, projectId) {
21279
24543
  throw new Error(`Failed to generate voiceover: ${err.message}`);
21280
24544
  } finally {
21281
24545
  try {
21282
- fs2.unlinkSync(scriptPath);
24546
+ fs3.unlinkSync(scriptPath);
21283
24547
  } catch {
21284
24548
  }
21285
24549
  }
@@ -21287,12 +24551,12 @@ async function handleGenerateVoiceover(text, projectId) {
21287
24551
  function saveFileToDisk(result) {
21288
24552
  const file = result && typeof result === "object" ? result._file : void 0;
21289
24553
  if (!file || typeof file.data !== "string") return result;
21290
- fs2.mkdirSync(FRAMES_DIR, { recursive: true });
24554
+ fs3.mkdirSync(FRAMES_DIR, { recursive: true });
21291
24555
  const stamp = (/* @__PURE__ */ new Date()).toISOString().replace(/[:.]/g, "-");
21292
24556
  const safe = String(file.name ?? "file").replace(/[^\w.-]+/g, "_").slice(0, 80);
21293
- const target = path2.join(FRAMES_DIR, `${stamp}-${safe}`);
24557
+ const target = path3.join(FRAMES_DIR, `${stamp}-${safe}`);
21294
24558
  const bytes = Buffer.from(file.data, "base64");
21295
- fs2.writeFileSync(target, bytes);
24559
+ fs3.writeFileSync(target, bytes);
21296
24560
  const { _file: _file2, ...rest } = result;
21297
24561
  return { ...rest, savedTo: target, bytes: bytes.length };
21298
24562
  }
@@ -21300,14 +24564,14 @@ function saveFramesToDisk(result, label) {
21300
24564
  if (!result || typeof result !== "object") return result;
21301
24565
  const frames = [result._image, ...Array.isArray(result._images) ? result._images : []].filter((f) => f && typeof f.data === "string" && typeof f.mimeType === "string");
21302
24566
  if (!frames.length) return result;
21303
- fs2.mkdirSync(FRAMES_DIR, { recursive: true });
24567
+ fs3.mkdirSync(FRAMES_DIR, { recursive: true });
21304
24568
  const stamp = (/* @__PURE__ */ new Date()).toISOString().replace(/[:.]/g, "-");
21305
24569
  const safe = label.replace(/[^\w.-]+/g, "_").slice(0, 60);
21306
24570
  const saved = frames.map((f, i) => {
21307
24571
  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}`);
24572
+ const file = path3.join(FRAMES_DIR, `${stamp}-${safe}${frames.length > 1 ? `-${i}` : ""}.${ext}`);
21309
24573
  const bytes = Buffer.from(f.data, "base64");
21310
- fs2.writeFileSync(file, bytes);
24574
+ fs3.writeFileSync(file, bytes);
21311
24575
  return { path: file, bytes: bytes.length, ...f.caption ? { caption: f.caption } : {} };
21312
24576
  });
21313
24577
  const { _image, _images, ...rest } = result;
@@ -21318,8 +24582,8 @@ function saveFramesToDisk(result, label) {
21318
24582
  };
21319
24583
  }
21320
24584
  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";
24585
+ const size = fs3.statSync(filePath).size;
24586
+ const type = MEDIA_TYPES[path3.extname(filePath).toLowerCase()]?.mime ?? "application/octet-stream";
21323
24587
  const headers = { "Content-Type": type, "Accept-Ranges": "bytes" };
21324
24588
  const range = /^bytes=(\d*)-(\d*)$/.exec(req.headers.range || "");
21325
24589
  if (range && (range[1] || range[2])) {
@@ -21342,7 +24606,7 @@ function serveFile(req, res, filePath) {
21342
24606
  res.end();
21343
24607
  return;
21344
24608
  }
21345
- fs2.createReadStream(filePath, { start, end }).pipe(res);
24609
+ fs3.createReadStream(filePath, { start, end }).pipe(res);
21346
24610
  return;
21347
24611
  }
21348
24612
  res.writeHead(200, { ...headers, "Content-Length": size });
@@ -21350,11 +24614,11 @@ function serveFile(req, res, filePath) {
21350
24614
  res.end();
21351
24615
  return;
21352
24616
  }
21353
- fs2.createReadStream(filePath).pipe(res);
24617
+ fs3.createReadStream(filePath).pipe(res);
21354
24618
  }
21355
24619
  var httpServer = http.createServer((req, res) => {
21356
- const url = new URL(req.url || "/", `http://${req.headers.host}`);
21357
- const pathname = url.pathname;
24620
+ const url2 = new URL(req.url || "/", `http://${req.headers.host}`);
24621
+ const pathname = url2.pathname;
21358
24622
  if (!isLoopbackHost(req.headers.host)) {
21359
24623
  res.writeHead(403, { "Content-Type": "text/plain" });
21360
24624
  res.end("Forbidden");
@@ -21388,9 +24652,9 @@ var httpServer = http.createServer((req, res) => {
21388
24652
  res.end("Bad path");
21389
24653
  return;
21390
24654
  }
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()) {
24655
+ const filePath = path3.resolve(LOCAL_ASSETS_DIR, filename);
24656
+ const inRoot = filePath === LOCAL_ASSETS_DIR || filePath.startsWith(LOCAL_ASSETS_DIR + path3.sep);
24657
+ if (inRoot && fs3.existsSync(filePath) && fs3.statSync(filePath).isFile()) {
21394
24658
  serveFile(req, res, filePath);
21395
24659
  } else {
21396
24660
  res.writeHead(404, { "Content-Type": "text/plain" });
@@ -21475,9 +24739,24 @@ function explainTabError(error2) {
21475
24739
  function sendJson(ws, message) {
21476
24740
  if (ws.readyState === import_websocket.default.OPEN) ws.send(JSON.stringify(message));
21477
24741
  }
24742
+ async function answerService(ws, message) {
24743
+ const { id, action, params = {} } = message;
24744
+ try {
24745
+ let result;
24746
+ if (action === "list") result = await listServices();
24747
+ else if (action === "call") result = await callService(String(params.server), String(params.tool), params.args ?? {});
24748
+ else if (action === "download") {
24749
+ const saved = await downloadToAssets(LOCAL_ASSETS_DIR, String(params.url), typeof params.name === "string" ? params.name : void 0);
24750
+ result = { ...saved, mediaUrl: mediaUrl(saved.rel) };
24751
+ } else throw new Error(`Unknown service action: ${action}`);
24752
+ sendJson(ws, { type: "serviceReply", id, result });
24753
+ } catch (err) {
24754
+ sendJson(ws, { type: "serviceReply", id, error: err?.message ?? String(err) });
24755
+ }
24756
+ }
21478
24757
  wss.on("connection", (ws, req) => {
21479
- const url = req.url || "/";
21480
- if (url.startsWith("/controller")) {
24758
+ const url2 = req.url || "/";
24759
+ if (url2.startsWith("/controller")) {
21481
24760
  console.error("[GoatEdit MCP] Controller client connected");
21482
24761
  controllerSockets.add(ws);
21483
24762
  ws.on("message", async (data) => {
@@ -21527,6 +24806,10 @@ wss.on("connection", (ws, req) => {
21527
24806
  for (const controller2 of controllerSockets) sendJson(controller2, message);
21528
24807
  return;
21529
24808
  }
24809
+ if (message.type === "service") {
24810
+ void answerService(ws, message);
24811
+ return;
24812
+ }
21530
24813
  if (message.id === void 0 || message.result === void 0 && message.error === void 0) return;
21531
24814
  const key = String(message.id);
21532
24815
  const pending = pendingRequests.get(key);
@@ -21590,7 +24873,7 @@ function connectUpstream() {
21590
24873
  upstreamReady = new Promise((resolve, reject) => {
21591
24874
  let token;
21592
24875
  try {
21593
- token = process.env.GOATEDIT_CONTROLLER_TOKEN || fs2.readFileSync(CONTROLLER_TOKEN_FILE, "utf8").trim();
24876
+ token = process.env.GOATEDIT_CONTROLLER_TOKEN || fs3.readFileSync(CONTROLLER_TOKEN_FILE, "utf8").trim();
21594
24877
  } catch {
21595
24878
  reject(new Error(notConnectedMessage()));
21596
24879
  return;
@@ -21636,7 +24919,7 @@ async function ensureTransport() {
21636
24919
  }
21637
24920
  function sendUpstream(method, params, projectId) {
21638
24921
  return connectUpstream().then((ws) => new Promise((resolve, reject) => {
21639
- const id = crypto.randomUUID();
24922
+ const id = crypto2.randomUUID();
21640
24923
  const timeoutId = setTimeout(() => {
21641
24924
  upstreamPending.delete(id);
21642
24925
  reject(new Error(`Request timed out: ${method}`));
@@ -21650,7 +24933,7 @@ async function sendToBrowser(method, params = {}, projectId) {
21650
24933
  if (!ownsPort) return sendUpstream(method, params, projectId ?? chosenProjectId);
21651
24934
  const tab = resolveTab(projectId);
21652
24935
  return new Promise((resolve, reject) => {
21653
- const id = crypto.randomUUID();
24936
+ const id = crypto2.randomUUID();
21654
24937
  const timeoutId = setTimeout(() => {
21655
24938
  pendingRequests.delete(id);
21656
24939
  reject(new Error(`Request timed out after ${REQUEST_TIMEOUT_MS / 1e3}s: ${method}. Call get_timeline to see whether it landed.`));