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.
- package/bundle/goatedit-mcp.js +3472 -189
- package/package.json +1 -1
package/bundle/goatedit-mcp.js
CHANGED
|
@@ -3232,8 +3232,8 @@ var require_utils = __commonJS({
|
|
|
3232
3232
|
}
|
|
3233
3233
|
return ind;
|
|
3234
3234
|
}
|
|
3235
|
-
function removeDotSegments(
|
|
3236
|
-
let input =
|
|
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 [
|
|
3489
|
-
wsComponent.path =
|
|
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(
|
|
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
|
|
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 &&
|
|
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,
|
|
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,
|
|
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
|
|
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
|
|
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 =
|
|
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,
|
|
10815
|
-
if (!
|
|
11314
|
+
function getElementAtPath(obj, path4) {
|
|
11315
|
+
if (!path4)
|
|
10816
11316
|
return obj;
|
|
10817
|
-
return
|
|
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(
|
|
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(
|
|
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,
|
|
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 }, [...
|
|
11880
|
+
issue2.errors.map((issues) => processError({ issues }, [...path4, ...issue2.path]));
|
|
11381
11881
|
} else if (issue2.code === "invalid_key") {
|
|
11382
|
-
processError({ issues: issue2.issues }, [...
|
|
11882
|
+
processError({ issues: issue2.issues }, [...path4, ...issue2.path]);
|
|
11383
11883
|
} else if (issue2.code === "invalid_element") {
|
|
11384
|
-
processError({ issues: issue2.issues }, [...
|
|
11884
|
+
processError({ issues: issue2.issues }, [...path4, ...issue2.path]);
|
|
11385
11885
|
} else {
|
|
11386
|
-
const fullpath = [...
|
|
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
|
|
12664
|
+
const url2 = new URL(trimmed);
|
|
12164
12665
|
if (def.hostname) {
|
|
12165
12666
|
def.hostname.lastIndex = 0;
|
|
12166
|
-
if (!def.hostname.test(
|
|
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(
|
|
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 =
|
|
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
|
|
19840
|
+
import crypto2 from "crypto";
|
|
19146
19841
|
import http from "http";
|
|
19147
|
-
import
|
|
19148
|
-
import
|
|
19842
|
+
import fs3 from "fs";
|
|
19843
|
+
import path3 from "path";
|
|
19149
19844
|
import { execFileSync } from "child_process";
|
|
19150
|
-
import
|
|
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
|
-
|
|
20861
|
-
|
|
20862
|
-
|
|
20863
|
-
|
|
20864
|
-
|
|
20865
|
-
|
|
20866
|
-
|
|
20867
|
-
|
|
20868
|
-
|
|
20869
|
-
|
|
20870
|
-
|
|
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
|
-
|
|
20992
|
-
|
|
20993
|
-
|
|
20994
|
-
|
|
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
|
-
|
|
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
|
|
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
|
-
//
|
|
21007
|
-
var
|
|
21008
|
-
|
|
21009
|
-
|
|
21010
|
-
|
|
21011
|
-
|
|
21012
|
-
|
|
21013
|
-
|
|
21014
|
-
|
|
21015
|
-
|
|
21016
|
-
|
|
21017
|
-
|
|
21018
|
-
|
|
21019
|
-
|
|
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
|
-
|
|
21022
|
-
blocks.push({ type: "text", text });
|
|
21023
|
-
return blocks;
|
|
21024
|
-
}
|
|
23837
|
+
};
|
|
21025
23838
|
|
|
21026
|
-
//
|
|
21027
|
-
|
|
21028
|
-
|
|
21029
|
-
|
|
21030
|
-
|
|
21031
|
-
|
|
21032
|
-
|
|
21033
|
-
|
|
21034
|
-
|
|
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
|
-
|
|
21037
|
-
|
|
21038
|
-
|
|
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
|
-
|
|
21042
|
-
|
|
21043
|
-
|
|
21044
|
-
|
|
21045
|
-
|
|
21046
|
-
|
|
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
|
-
|
|
21054
|
-
|
|
21055
|
-
|
|
21056
|
-
|
|
21057
|
-
|
|
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
|
-
|
|
21061
|
-
|
|
21062
|
-
|
|
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
|
-
|
|
21066
|
-
|
|
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
|
-
|
|
21069
|
-
|
|
21070
|
-
|
|
21071
|
-
|
|
21072
|
-
|
|
21073
|
-
|
|
21074
|
-
|
|
21075
|
-
|
|
21076
|
-
|
|
21077
|
-
|
|
21078
|
-
|
|
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
|
-
|
|
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
|
-
|
|
21084
|
-
|
|
21085
|
-
|
|
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
|
-
|
|
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
|
-
|
|
21090
|
-
|
|
21091
|
-
|
|
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
|
-
|
|
21095
|
-
|
|
21096
|
-
|
|
21097
|
-
|
|
21098
|
-
|
|
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
|
-
|
|
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 ||
|
|
21130
|
-
var CONTROLLER_TOKEN_FILE =
|
|
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
|
-
|
|
21133
|
-
|
|
21134
|
-
|
|
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 &&
|
|
24405
|
+
return a.length === b.length && crypto2.timingSafeEqual(a, b);
|
|
21142
24406
|
}
|
|
21143
24407
|
var REQUEST_TIMEOUT_MS = 3e4;
|
|
21144
|
-
var LOCAL_ASSETS_DIR =
|
|
21145
|
-
process.env.GOATEDIT_ASSETS_DIR ||
|
|
24408
|
+
var LOCAL_ASSETS_DIR = path3.resolve(
|
|
24409
|
+
process.env.GOATEDIT_ASSETS_DIR || path3.join(os2.homedir(), "Movies")
|
|
21146
24410
|
);
|
|
21147
|
-
var FRAMES_DIR =
|
|
21148
|
-
process.env.GOATEDIT_FRAMES_DIR ||
|
|
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 =
|
|
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(
|
|
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(
|
|
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 (!
|
|
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 =
|
|
21194
|
-
if (start !== LOCAL_ASSETS_DIR && !start.startsWith(LOCAL_ASSETS_DIR +
|
|
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 =
|
|
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 =
|
|
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[
|
|
24482
|
+
const type = MEDIA_TYPES[path3.extname(entry.name).toLowerCase()];
|
|
21219
24483
|
if (!type || !entry.isFile()) continue;
|
|
21220
|
-
const rel =
|
|
24484
|
+
const rel = path3.relative(LOCAL_ASSETS_DIR, full);
|
|
21221
24485
|
let bytes = 0;
|
|
21222
24486
|
try {
|
|
21223
|
-
bytes =
|
|
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[
|
|
24503
|
+
const type = MEDIA_TYPES[path3.extname(hit).toLowerCase()];
|
|
21240
24504
|
if (!type || type.kind === "lottie") return null;
|
|
21241
|
-
const rel =
|
|
21242
|
-
return { name:
|
|
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 =
|
|
21262
|
-
|
|
21263
|
-
const scriptPath =
|
|
21264
|
-
|
|
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-${
|
|
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
|
-
|
|
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
|
-
|
|
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 =
|
|
24557
|
+
const target = path3.join(FRAMES_DIR, `${stamp}-${safe}`);
|
|
21294
24558
|
const bytes = Buffer.from(file.data, "base64");
|
|
21295
|
-
|
|
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
|
-
|
|
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 =
|
|
24572
|
+
const file = path3.join(FRAMES_DIR, `${stamp}-${safe}${frames.length > 1 ? `-${i}` : ""}.${ext}`);
|
|
21309
24573
|
const bytes = Buffer.from(f.data, "base64");
|
|
21310
|
-
|
|
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 =
|
|
21322
|
-
const type = MEDIA_TYPES[
|
|
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
|
-
|
|
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
|
-
|
|
24617
|
+
fs3.createReadStream(filePath).pipe(res);
|
|
21354
24618
|
}
|
|
21355
24619
|
var httpServer = http.createServer((req, res) => {
|
|
21356
|
-
const
|
|
21357
|
-
const 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 =
|
|
21392
|
-
const inRoot = filePath === LOCAL_ASSETS_DIR || filePath.startsWith(LOCAL_ASSETS_DIR +
|
|
21393
|
-
if (inRoot &&
|
|
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
|
|
21480
|
-
if (
|
|
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 ||
|
|
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 =
|
|
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 =
|
|
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.`));
|