@shortcut/mcp 0.1.5 → 0.2.1
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/README.md +52 -3
- package/dist/index.js +573 -550
- package/package.json +4 -4
package/dist/index.js
CHANGED
|
@@ -9589,26 +9589,26 @@ var require_get_intrinsic = __commonJS((exports, module) => {
|
|
|
9589
9589
|
}
|
|
9590
9590
|
}
|
|
9591
9591
|
var errorProto;
|
|
9592
|
-
var doEval = function doEval(
|
|
9592
|
+
var doEval = function doEval(name) {
|
|
9593
9593
|
var value;
|
|
9594
|
-
if (
|
|
9594
|
+
if (name === "%AsyncFunction%") {
|
|
9595
9595
|
value = getEvalledConstructor("async function () {}");
|
|
9596
|
-
} else if (
|
|
9596
|
+
} else if (name === "%GeneratorFunction%") {
|
|
9597
9597
|
value = getEvalledConstructor("function* () {}");
|
|
9598
|
-
} else if (
|
|
9598
|
+
} else if (name === "%AsyncGeneratorFunction%") {
|
|
9599
9599
|
value = getEvalledConstructor("async function* () {}");
|
|
9600
|
-
} else if (
|
|
9600
|
+
} else if (name === "%AsyncGenerator%") {
|
|
9601
9601
|
var fn = doEval("%AsyncGeneratorFunction%");
|
|
9602
9602
|
if (fn) {
|
|
9603
9603
|
value = fn.prototype;
|
|
9604
9604
|
}
|
|
9605
|
-
} else if (
|
|
9605
|
+
} else if (name === "%AsyncIteratorPrototype%") {
|
|
9606
9606
|
var gen = doEval("%AsyncGenerator%");
|
|
9607
9607
|
if (gen && getProto) {
|
|
9608
9608
|
value = getProto(gen.prototype);
|
|
9609
9609
|
}
|
|
9610
9610
|
}
|
|
9611
|
-
INTRINSICS[
|
|
9611
|
+
INTRINSICS[name] = value;
|
|
9612
9612
|
return value;
|
|
9613
9613
|
};
|
|
9614
9614
|
var LEGACY_ALIASES = {
|
|
@@ -9688,8 +9688,8 @@ var require_get_intrinsic = __commonJS((exports, module) => {
|
|
|
9688
9688
|
});
|
|
9689
9689
|
return result;
|
|
9690
9690
|
};
|
|
9691
|
-
var getBaseIntrinsic = function getBaseIntrinsic(
|
|
9692
|
-
var intrinsicName =
|
|
9691
|
+
var getBaseIntrinsic = function getBaseIntrinsic(name, allowMissing) {
|
|
9692
|
+
var intrinsicName = name;
|
|
9693
9693
|
var alias;
|
|
9694
9694
|
if (hasOwn(LEGACY_ALIASES, intrinsicName)) {
|
|
9695
9695
|
alias = LEGACY_ALIASES[intrinsicName];
|
|
@@ -9701,7 +9701,7 @@ var require_get_intrinsic = __commonJS((exports, module) => {
|
|
|
9701
9701
|
value = doEval(intrinsicName);
|
|
9702
9702
|
}
|
|
9703
9703
|
if (typeof value === "undefined" && !allowMissing) {
|
|
9704
|
-
throw new $TypeError("intrinsic " +
|
|
9704
|
+
throw new $TypeError("intrinsic " + name + " exists, but is not available. Please file an issue!");
|
|
9705
9705
|
}
|
|
9706
9706
|
return {
|
|
9707
9707
|
alias,
|
|
@@ -9709,19 +9709,19 @@ var require_get_intrinsic = __commonJS((exports, module) => {
|
|
|
9709
9709
|
value
|
|
9710
9710
|
};
|
|
9711
9711
|
}
|
|
9712
|
-
throw new $SyntaxError("intrinsic " +
|
|
9712
|
+
throw new $SyntaxError("intrinsic " + name + " does not exist!");
|
|
9713
9713
|
};
|
|
9714
|
-
module.exports = function GetIntrinsic(
|
|
9715
|
-
if (typeof
|
|
9714
|
+
module.exports = function GetIntrinsic(name, allowMissing) {
|
|
9715
|
+
if (typeof name !== "string" || name.length === 0) {
|
|
9716
9716
|
throw new $TypeError("intrinsic name must be a non-empty string");
|
|
9717
9717
|
}
|
|
9718
9718
|
if (arguments.length > 1 && typeof allowMissing !== "boolean") {
|
|
9719
9719
|
throw new $TypeError('"allowMissing" argument must be a boolean');
|
|
9720
9720
|
}
|
|
9721
|
-
if ($exec(/^%?[^%]*%?$/,
|
|
9721
|
+
if ($exec(/^%?[^%]*%?$/, name) === null) {
|
|
9722
9722
|
throw new $SyntaxError("`%` may not be present anywhere but at the beginning and end of the intrinsic name");
|
|
9723
9723
|
}
|
|
9724
|
-
var parts = stringToPath(
|
|
9724
|
+
var parts = stringToPath(name);
|
|
9725
9725
|
var intrinsicBaseName = parts.length > 0 ? parts[0] : "";
|
|
9726
9726
|
var intrinsic = getBaseIntrinsic("%" + intrinsicBaseName + "%", allowMissing);
|
|
9727
9727
|
var intrinsicRealName = intrinsic.name;
|
|
@@ -9749,7 +9749,7 @@ var require_get_intrinsic = __commonJS((exports, module) => {
|
|
|
9749
9749
|
} else if (value != null) {
|
|
9750
9750
|
if (!(part in value)) {
|
|
9751
9751
|
if (!allowMissing) {
|
|
9752
|
-
throw new $TypeError("base intrinsic for " +
|
|
9752
|
+
throw new $TypeError("base intrinsic for " + name + " exists, but the property is not available.");
|
|
9753
9753
|
}
|
|
9754
9754
|
return;
|
|
9755
9755
|
}
|
|
@@ -10306,9 +10306,9 @@ var require_ms = __commonJS((exports, module) => {
|
|
|
10306
10306
|
}
|
|
10307
10307
|
return ms + " ms";
|
|
10308
10308
|
}
|
|
10309
|
-
function plural(ms, msAbs, n,
|
|
10309
|
+
function plural(ms, msAbs, n, name) {
|
|
10310
10310
|
var isPlural = msAbs >= n * 1.5;
|
|
10311
|
-
return Math.round(ms / n) + " " +
|
|
10311
|
+
return Math.round(ms / n) + " " + name + (isPlural ? "s" : "");
|
|
10312
10312
|
}
|
|
10313
10313
|
});
|
|
10314
10314
|
|
|
@@ -10437,19 +10437,19 @@ var require_common = __commonJS((exports, module) => {
|
|
|
10437
10437
|
createDebug.enable("");
|
|
10438
10438
|
return namespaces;
|
|
10439
10439
|
}
|
|
10440
|
-
function enabled(
|
|
10441
|
-
if (
|
|
10440
|
+
function enabled(name) {
|
|
10441
|
+
if (name[name.length - 1] === "*") {
|
|
10442
10442
|
return true;
|
|
10443
10443
|
}
|
|
10444
10444
|
let i;
|
|
10445
10445
|
let len;
|
|
10446
10446
|
for (i = 0, len = createDebug.skips.length;i < len; i++) {
|
|
10447
|
-
if (createDebug.skips[i].test(
|
|
10447
|
+
if (createDebug.skips[i].test(name)) {
|
|
10448
10448
|
return false;
|
|
10449
10449
|
}
|
|
10450
10450
|
}
|
|
10451
10451
|
for (i = 0, len = createDebug.names.length;i < len; i++) {
|
|
10452
|
-
if (createDebug.names[i].test(
|
|
10452
|
+
if (createDebug.names[i].test(name)) {
|
|
10453
10453
|
return true;
|
|
10454
10454
|
}
|
|
10455
10455
|
}
|
|
@@ -10751,17 +10751,17 @@ var require_node = __commonJS((exports, module) => {
|
|
|
10751
10751
|
return "colors" in exports.inspectOpts ? Boolean(exports.inspectOpts.colors) : tty.isatty(process.stderr.fd);
|
|
10752
10752
|
}
|
|
10753
10753
|
function formatArgs(args) {
|
|
10754
|
-
const { namespace:
|
|
10754
|
+
const { namespace: name, useColors: useColors2 } = this;
|
|
10755
10755
|
if (useColors2) {
|
|
10756
10756
|
const c = this.color;
|
|
10757
10757
|
const colorCode = "\x1B[3" + (c < 8 ? c : "8;5;" + c);
|
|
10758
|
-
const prefix = ` ${colorCode};1m${
|
|
10758
|
+
const prefix = ` ${colorCode};1m${name} \x1B[0m`;
|
|
10759
10759
|
args[0] = prefix + args[0].split(`
|
|
10760
10760
|
`).join(`
|
|
10761
10761
|
` + prefix);
|
|
10762
10762
|
args.push(colorCode + "m+" + module.exports.humanize(this.diff) + "\x1B[0m");
|
|
10763
10763
|
} else {
|
|
10764
|
-
args[0] = getDate() +
|
|
10764
|
+
args[0] = getDate() + name + " " + args[0];
|
|
10765
10765
|
}
|
|
10766
10766
|
}
|
|
10767
10767
|
function getDate() {
|
|
@@ -10959,13 +10959,13 @@ var require_follow_redirects = __commonJS((exports, module) => {
|
|
|
10959
10959
|
this._ending = true;
|
|
10960
10960
|
}
|
|
10961
10961
|
};
|
|
10962
|
-
RedirectableRequest.prototype.setHeader = function(
|
|
10963
|
-
this._options.headers[
|
|
10964
|
-
this._currentRequest.setHeader(
|
|
10962
|
+
RedirectableRequest.prototype.setHeader = function(name, value) {
|
|
10963
|
+
this._options.headers[name] = value;
|
|
10964
|
+
this._currentRequest.setHeader(name, value);
|
|
10965
10965
|
};
|
|
10966
|
-
RedirectableRequest.prototype.removeHeader = function(
|
|
10967
|
-
delete this._options.headers[
|
|
10968
|
-
this._currentRequest.removeHeader(
|
|
10966
|
+
RedirectableRequest.prototype.removeHeader = function(name) {
|
|
10967
|
+
delete this._options.headers[name];
|
|
10968
|
+
this._currentRequest.removeHeader(name);
|
|
10969
10969
|
};
|
|
10970
10970
|
RedirectableRequest.prototype.setTimeout = function(msecs, callback) {
|
|
10971
10971
|
var self2 = this;
|
|
@@ -11542,20 +11542,20 @@ var require_axios = __commonJS((exports, module) => {
|
|
|
11542
11542
|
var reduceDescriptors = (obj, reducer) => {
|
|
11543
11543
|
const descriptors2 = Object.getOwnPropertyDescriptors(obj);
|
|
11544
11544
|
const reducedDescriptors = {};
|
|
11545
|
-
forEach(descriptors2, (descriptor,
|
|
11545
|
+
forEach(descriptors2, (descriptor, name) => {
|
|
11546
11546
|
let ret;
|
|
11547
|
-
if ((ret = reducer(descriptor,
|
|
11548
|
-
reducedDescriptors[
|
|
11547
|
+
if ((ret = reducer(descriptor, name, obj)) !== false) {
|
|
11548
|
+
reducedDescriptors[name] = ret || descriptor;
|
|
11549
11549
|
}
|
|
11550
11550
|
});
|
|
11551
11551
|
Object.defineProperties(obj, reducedDescriptors);
|
|
11552
11552
|
};
|
|
11553
11553
|
var freezeMethods = (obj) => {
|
|
11554
|
-
reduceDescriptors(obj, (descriptor,
|
|
11555
|
-
if (isFunction(obj) && ["arguments", "caller", "callee"].indexOf(
|
|
11554
|
+
reduceDescriptors(obj, (descriptor, name) => {
|
|
11555
|
+
if (isFunction(obj) && ["arguments", "caller", "callee"].indexOf(name) !== -1) {
|
|
11556
11556
|
return false;
|
|
11557
11557
|
}
|
|
11558
|
-
const value = obj[
|
|
11558
|
+
const value = obj[name];
|
|
11559
11559
|
if (!isFunction(value))
|
|
11560
11560
|
return;
|
|
11561
11561
|
descriptor.enumerable = false;
|
|
@@ -11565,7 +11565,7 @@ var require_axios = __commonJS((exports, module) => {
|
|
|
11565
11565
|
}
|
|
11566
11566
|
if (!descriptor.set) {
|
|
11567
11567
|
descriptor.set = () => {
|
|
11568
|
-
throw Error("Can not rewrite read-only method '" +
|
|
11568
|
+
throw Error("Can not rewrite read-only method '" + name + "'");
|
|
11569
11569
|
};
|
|
11570
11570
|
}
|
|
11571
11571
|
});
|
|
@@ -11873,8 +11873,8 @@ var require_axios = __commonJS((exports, module) => {
|
|
|
11873
11873
|
params && toFormData(params, this, options);
|
|
11874
11874
|
}
|
|
11875
11875
|
var prototype = AxiosURLSearchParams.prototype;
|
|
11876
|
-
prototype.append = function append(
|
|
11877
|
-
this._pairs.push([
|
|
11876
|
+
prototype.append = function append(name, value) {
|
|
11877
|
+
this._pairs.push([name, value]);
|
|
11878
11878
|
};
|
|
11879
11879
|
prototype.toString = function toString(encoder) {
|
|
11880
11880
|
const _encode = encoder ? function(value) {
|
|
@@ -12010,8 +12010,8 @@ var require_axios = __commonJS((exports, module) => {
|
|
|
12010
12010
|
}
|
|
12011
12011
|
}, options));
|
|
12012
12012
|
}
|
|
12013
|
-
function parsePropPath(
|
|
12014
|
-
return utils$1.matchAll(/\w+|\[(\w*)]/g,
|
|
12013
|
+
function parsePropPath(name) {
|
|
12014
|
+
return utils$1.matchAll(/\w+|\[(\w*)]/g, name).map((match) => {
|
|
12015
12015
|
return match[0] === "[]" ? "" : match[1] || match[0];
|
|
12016
12016
|
});
|
|
12017
12017
|
}
|
|
@@ -12029,33 +12029,33 @@ var require_axios = __commonJS((exports, module) => {
|
|
|
12029
12029
|
}
|
|
12030
12030
|
function formDataToJSON(formData) {
|
|
12031
12031
|
function buildPath(path, value, target, index) {
|
|
12032
|
-
let
|
|
12033
|
-
if (
|
|
12032
|
+
let name = path[index++];
|
|
12033
|
+
if (name === "__proto__")
|
|
12034
12034
|
return true;
|
|
12035
|
-
const isNumericKey = Number.isFinite(+
|
|
12035
|
+
const isNumericKey = Number.isFinite(+name);
|
|
12036
12036
|
const isLast = index >= path.length;
|
|
12037
|
-
|
|
12037
|
+
name = !name && utils$1.isArray(target) ? target.length : name;
|
|
12038
12038
|
if (isLast) {
|
|
12039
|
-
if (utils$1.hasOwnProp(target,
|
|
12040
|
-
target[
|
|
12039
|
+
if (utils$1.hasOwnProp(target, name)) {
|
|
12040
|
+
target[name] = [target[name], value];
|
|
12041
12041
|
} else {
|
|
12042
|
-
target[
|
|
12042
|
+
target[name] = value;
|
|
12043
12043
|
}
|
|
12044
12044
|
return !isNumericKey;
|
|
12045
12045
|
}
|
|
12046
|
-
if (!target[
|
|
12047
|
-
target[
|
|
12046
|
+
if (!target[name] || !utils$1.isObject(target[name])) {
|
|
12047
|
+
target[name] = [];
|
|
12048
12048
|
}
|
|
12049
|
-
const result = buildPath(path, value, target[
|
|
12050
|
-
if (result && utils$1.isArray(target[
|
|
12051
|
-
target[
|
|
12049
|
+
const result = buildPath(path, value, target[name], index);
|
|
12050
|
+
if (result && utils$1.isArray(target[name])) {
|
|
12051
|
+
target[name] = arrayToObject(target[name]);
|
|
12052
12052
|
}
|
|
12053
12053
|
return !isNumericKey;
|
|
12054
12054
|
}
|
|
12055
12055
|
if (utils$1.isFormData(formData) && utils$1.isFunction(formData.entries)) {
|
|
12056
12056
|
const obj = {};
|
|
12057
|
-
utils$1.forEachEntry(formData, (
|
|
12058
|
-
buildPath(parsePropPath(
|
|
12057
|
+
utils$1.forEachEntry(formData, (name, value) => {
|
|
12058
|
+
buildPath(parsePropPath(name), value, obj, 0);
|
|
12059
12059
|
});
|
|
12060
12060
|
return obj;
|
|
12061
12061
|
}
|
|
@@ -12634,10 +12634,10 @@ var require_axios = __commonJS((exports, module) => {
|
|
|
12634
12634
|
var CRLF_BYTES_COUNT = 2;
|
|
12635
12635
|
|
|
12636
12636
|
class FormDataPart {
|
|
12637
|
-
constructor(
|
|
12637
|
+
constructor(name, value) {
|
|
12638
12638
|
const { escapeName } = this.constructor;
|
|
12639
12639
|
const isStringValue = utils$1.isString(value);
|
|
12640
|
-
let headers = `Content-Disposition: form-data; name="${escapeName(
|
|
12640
|
+
let headers = `Content-Disposition: form-data; name="${escapeName(name)}"${!isStringValue && value.name ? `; filename="${escapeName(value.name)}"` : ""}${CRLF}`;
|
|
12641
12641
|
if (isStringValue) {
|
|
12642
12642
|
value = textEncoder.encode(String(value).replace(/\r?\n|\r\n?/g, CRLF));
|
|
12643
12643
|
} else {
|
|
@@ -12646,7 +12646,7 @@ var require_axios = __commonJS((exports, module) => {
|
|
|
12646
12646
|
this.headers = textEncoder.encode(headers + CRLF);
|
|
12647
12647
|
this.contentLength = isStringValue ? value.byteLength : value.size;
|
|
12648
12648
|
this.size = this.headers.byteLength + this.contentLength + CRLF_BYTES_COUNT;
|
|
12649
|
-
this.name =
|
|
12649
|
+
this.name = name;
|
|
12650
12650
|
this.value = value;
|
|
12651
12651
|
}
|
|
12652
12652
|
async* encode() {
|
|
@@ -12659,8 +12659,8 @@ var require_axios = __commonJS((exports, module) => {
|
|
|
12659
12659
|
}
|
|
12660
12660
|
yield CRLF_BYTES;
|
|
12661
12661
|
}
|
|
12662
|
-
static escapeName(
|
|
12663
|
-
return String(
|
|
12662
|
+
static escapeName(name) {
|
|
12663
|
+
return String(name).replace(/[\r\n"]/g, (match) => ({
|
|
12664
12664
|
"\r": "%0D",
|
|
12665
12665
|
"\n": "%0A",
|
|
12666
12666
|
'"': "%22"
|
|
@@ -12682,8 +12682,8 @@ var require_axios = __commonJS((exports, module) => {
|
|
|
12682
12682
|
const boundaryBytes = textEncoder.encode("--" + boundary + CRLF);
|
|
12683
12683
|
const footerBytes = textEncoder.encode("--" + boundary + "--" + CRLF + CRLF);
|
|
12684
12684
|
let contentLength = footerBytes.byteLength;
|
|
12685
|
-
const parts = Array.from(form.entries()).map(([
|
|
12686
|
-
const part = new FormDataPart(
|
|
12685
|
+
const parts = Array.from(form.entries()).map(([name, value]) => {
|
|
12686
|
+
const part = new FormDataPart(name, value);
|
|
12687
12687
|
contentLength += part.size;
|
|
12688
12688
|
return part;
|
|
12689
12689
|
});
|
|
@@ -13291,20 +13291,20 @@ var require_axios = __commonJS((exports, module) => {
|
|
|
13291
13291
|
return origin2.protocol === url2.protocol && origin2.host === url2.host && (isMSIE || origin2.port === url2.port);
|
|
13292
13292
|
})(new URL(platform.origin), platform.navigator && /(msie|trident)/i.test(platform.navigator.userAgent)) : () => true;
|
|
13293
13293
|
var cookies = platform.hasStandardBrowserEnv ? {
|
|
13294
|
-
write(
|
|
13295
|
-
const cookie = [
|
|
13294
|
+
write(name, value, expires, path, domain, secure) {
|
|
13295
|
+
const cookie = [name + "=" + encodeURIComponent(value)];
|
|
13296
13296
|
utils$1.isNumber(expires) && cookie.push("expires=" + new Date(expires).toGMTString());
|
|
13297
13297
|
utils$1.isString(path) && cookie.push("path=" + path);
|
|
13298
13298
|
utils$1.isString(domain) && cookie.push("domain=" + domain);
|
|
13299
13299
|
secure === true && cookie.push("secure");
|
|
13300
13300
|
document.cookie = cookie.join("; ");
|
|
13301
13301
|
},
|
|
13302
|
-
read(
|
|
13303
|
-
const match = document.cookie.match(new RegExp("(^|;\\s*)(" +
|
|
13302
|
+
read(name) {
|
|
13303
|
+
const match = document.cookie.match(new RegExp("(^|;\\s*)(" + name + ")=([^;]*)"));
|
|
13304
13304
|
return match ? decodeURIComponent(match[3]) : null;
|
|
13305
13305
|
},
|
|
13306
|
-
remove(
|
|
13307
|
-
this.write(
|
|
13306
|
+
remove(name) {
|
|
13307
|
+
this.write(name, "", Date.now() - 86400000);
|
|
13308
13308
|
}
|
|
13309
13309
|
} : {
|
|
13310
13310
|
write() {},
|
|
@@ -13883,17 +13883,17 @@ var require_axios = __commonJS((exports, module) => {
|
|
|
13883
13883
|
};
|
|
13884
13884
|
});
|
|
13885
13885
|
var deprecatedWarnings = {};
|
|
13886
|
-
validators$1.transitional = function transitional(validator2,
|
|
13886
|
+
validators$1.transitional = function transitional(validator2, version, message) {
|
|
13887
13887
|
function formatMessage(opt, desc) {
|
|
13888
13888
|
return "[Axios v" + VERSION + "] Transitional option '" + opt + "'" + desc + (message ? ". " + message : "");
|
|
13889
13889
|
}
|
|
13890
13890
|
return (value, opt, opts) => {
|
|
13891
13891
|
if (validator2 === false) {
|
|
13892
|
-
throw new AxiosError(formatMessage(opt, " has been removed" + (
|
|
13892
|
+
throw new AxiosError(formatMessage(opt, " has been removed" + (version ? " in " + version : "")), AxiosError.ERR_DEPRECATED);
|
|
13893
13893
|
}
|
|
13894
|
-
if (
|
|
13894
|
+
if (version && !deprecatedWarnings[opt]) {
|
|
13895
13895
|
deprecatedWarnings[opt] = true;
|
|
13896
|
-
console.warn(formatMessage(opt, " has been deprecated since v" +
|
|
13896
|
+
console.warn(formatMessage(opt, " has been deprecated since v" + version + " and will be removed in the near future"));
|
|
13897
13897
|
}
|
|
13898
13898
|
return validator2 ? validator2(value, opt, opts) : true;
|
|
13899
13899
|
};
|
|
@@ -14567,9 +14567,201 @@ var require_lib = __commonJS((exports) => {
|
|
|
14567
14567
|
__exportStar(require_data_contracts(), exports);
|
|
14568
14568
|
});
|
|
14569
14569
|
|
|
14570
|
-
//
|
|
14571
|
-
|
|
14572
|
-
|
|
14570
|
+
// src/client/cache.ts
|
|
14571
|
+
class Cache {
|
|
14572
|
+
cache;
|
|
14573
|
+
age;
|
|
14574
|
+
constructor() {
|
|
14575
|
+
this.cache = new Map;
|
|
14576
|
+
this.age = 0;
|
|
14577
|
+
}
|
|
14578
|
+
get(key) {
|
|
14579
|
+
return this.cache.get(key) ?? null;
|
|
14580
|
+
}
|
|
14581
|
+
values() {
|
|
14582
|
+
return Array.from(this.cache.values());
|
|
14583
|
+
}
|
|
14584
|
+
setMany(values) {
|
|
14585
|
+
this.cache.clear();
|
|
14586
|
+
for (const [key, value] of values) {
|
|
14587
|
+
this.cache.set(key, value);
|
|
14588
|
+
}
|
|
14589
|
+
this.age = Date.now();
|
|
14590
|
+
}
|
|
14591
|
+
clear() {
|
|
14592
|
+
this.cache.clear();
|
|
14593
|
+
this.age = 0;
|
|
14594
|
+
}
|
|
14595
|
+
get isStale() {
|
|
14596
|
+
return Date.now() - this.age > 1000 * 60 * 5;
|
|
14597
|
+
}
|
|
14598
|
+
}
|
|
14599
|
+
|
|
14600
|
+
// src/client/shortcut.ts
|
|
14601
|
+
class ShortcutClientWrapper {
|
|
14602
|
+
client;
|
|
14603
|
+
currentUser = null;
|
|
14604
|
+
userCache;
|
|
14605
|
+
workflowCache;
|
|
14606
|
+
constructor(client) {
|
|
14607
|
+
this.client = client;
|
|
14608
|
+
this.userCache = new Cache;
|
|
14609
|
+
this.workflowCache = new Cache;
|
|
14610
|
+
}
|
|
14611
|
+
async loadMembers() {
|
|
14612
|
+
if (this.userCache.isStale) {
|
|
14613
|
+
const response = await this.client.listMembers({});
|
|
14614
|
+
const members = response?.data ?? null;
|
|
14615
|
+
if (members) {
|
|
14616
|
+
this.userCache.setMany(members.map((member) => [member.id, member]));
|
|
14617
|
+
}
|
|
14618
|
+
}
|
|
14619
|
+
}
|
|
14620
|
+
async loadWorkflows() {
|
|
14621
|
+
if (this.workflowCache.isStale) {
|
|
14622
|
+
const response = await this.client.listWorkflows();
|
|
14623
|
+
const workflows = response?.data ?? null;
|
|
14624
|
+
if (workflows) {
|
|
14625
|
+
this.workflowCache.setMany(workflows.map((workflow) => [workflow.id, workflow]));
|
|
14626
|
+
}
|
|
14627
|
+
}
|
|
14628
|
+
}
|
|
14629
|
+
async getCurrentUser() {
|
|
14630
|
+
if (this.currentUser)
|
|
14631
|
+
return this.currentUser;
|
|
14632
|
+
const response = await this.client.getCurrentMemberInfo();
|
|
14633
|
+
const user = response?.data;
|
|
14634
|
+
if (!user)
|
|
14635
|
+
return null;
|
|
14636
|
+
this.currentUser = user;
|
|
14637
|
+
return user;
|
|
14638
|
+
}
|
|
14639
|
+
async getUser(userId) {
|
|
14640
|
+
const response = await this.client.getMember(userId, {});
|
|
14641
|
+
const user = response?.data;
|
|
14642
|
+
if (!user)
|
|
14643
|
+
return null;
|
|
14644
|
+
return user;
|
|
14645
|
+
}
|
|
14646
|
+
async getUserMap(userIds) {
|
|
14647
|
+
await this.loadMembers();
|
|
14648
|
+
return new Map(userIds.map((id) => [id, this.userCache.get(id)]).filter((user) => user[1] !== null));
|
|
14649
|
+
}
|
|
14650
|
+
async getUsers(userIds) {
|
|
14651
|
+
await this.loadMembers();
|
|
14652
|
+
return userIds.map((id) => this.userCache.get(id)).filter((user) => user !== null);
|
|
14653
|
+
}
|
|
14654
|
+
async getWorkflowMap(workflowIds) {
|
|
14655
|
+
await this.loadWorkflows();
|
|
14656
|
+
return new Map(workflowIds.map((id) => [id, this.workflowCache.get(id)]).filter((workflow) => workflow[1] !== null));
|
|
14657
|
+
}
|
|
14658
|
+
async getWorkflows() {
|
|
14659
|
+
await this.loadWorkflows();
|
|
14660
|
+
return Array.from(this.workflowCache.values());
|
|
14661
|
+
}
|
|
14662
|
+
async getWorkflow(workflowPublicId) {
|
|
14663
|
+
const response = await this.client.getWorkflow(workflowPublicId);
|
|
14664
|
+
const workflow = response?.data;
|
|
14665
|
+
if (!workflow)
|
|
14666
|
+
return null;
|
|
14667
|
+
return workflow;
|
|
14668
|
+
}
|
|
14669
|
+
async getTeams() {
|
|
14670
|
+
const response = await this.client.listGroups();
|
|
14671
|
+
const groups = response?.data ?? [];
|
|
14672
|
+
return groups;
|
|
14673
|
+
}
|
|
14674
|
+
async getTeam(teamPublicId) {
|
|
14675
|
+
const response = await this.client.getGroup(teamPublicId);
|
|
14676
|
+
const group = response?.data;
|
|
14677
|
+
if (!group)
|
|
14678
|
+
return null;
|
|
14679
|
+
return group;
|
|
14680
|
+
}
|
|
14681
|
+
async createStory(params) {
|
|
14682
|
+
const response = await this.client.createStory(params);
|
|
14683
|
+
const story = response?.data ?? null;
|
|
14684
|
+
if (!story)
|
|
14685
|
+
throw new Error(`Failed to create the story: ${response.status}`);
|
|
14686
|
+
return story;
|
|
14687
|
+
}
|
|
14688
|
+
async updateStory(storyPublicId, params) {
|
|
14689
|
+
const response = await this.client.updateStory(storyPublicId, params);
|
|
14690
|
+
const story = response?.data ?? null;
|
|
14691
|
+
if (!story)
|
|
14692
|
+
throw new Error(`Failed to update the story: ${response.status}`);
|
|
14693
|
+
return story;
|
|
14694
|
+
}
|
|
14695
|
+
async getStory(storyPublicId) {
|
|
14696
|
+
const response = await this.client.getStory(storyPublicId);
|
|
14697
|
+
const story = response?.data ?? null;
|
|
14698
|
+
if (!story)
|
|
14699
|
+
return null;
|
|
14700
|
+
return story;
|
|
14701
|
+
}
|
|
14702
|
+
async getEpic(epicPublicId) {
|
|
14703
|
+
const response = await this.client.getEpic(epicPublicId);
|
|
14704
|
+
const epic = response?.data ?? null;
|
|
14705
|
+
if (!epic)
|
|
14706
|
+
return null;
|
|
14707
|
+
return epic;
|
|
14708
|
+
}
|
|
14709
|
+
async getIteration(iterationPublicId) {
|
|
14710
|
+
const response = await this.client.getIteration(iterationPublicId);
|
|
14711
|
+
const iteration = response?.data ?? null;
|
|
14712
|
+
if (!iteration)
|
|
14713
|
+
return null;
|
|
14714
|
+
return iteration;
|
|
14715
|
+
}
|
|
14716
|
+
async getMilestone(milestonePublicId) {
|
|
14717
|
+
const response = await this.client.getMilestone(milestonePublicId);
|
|
14718
|
+
const milestone = response?.data ?? null;
|
|
14719
|
+
if (!milestone)
|
|
14720
|
+
return null;
|
|
14721
|
+
return milestone;
|
|
14722
|
+
}
|
|
14723
|
+
async searchStories(query) {
|
|
14724
|
+
const response = await this.client.searchStories({ query, page_size: 25, detail: "slim" });
|
|
14725
|
+
const stories = response?.data?.data;
|
|
14726
|
+
const total = response?.data?.total;
|
|
14727
|
+
if (!stories)
|
|
14728
|
+
return { stories: null, total: null };
|
|
14729
|
+
return { stories, total };
|
|
14730
|
+
}
|
|
14731
|
+
async searchIterations(query) {
|
|
14732
|
+
const response = await this.client.searchIterations({ query, page_size: 25, detail: "slim" });
|
|
14733
|
+
const iterations = response?.data?.data;
|
|
14734
|
+
const total = response?.data?.total;
|
|
14735
|
+
if (!iterations)
|
|
14736
|
+
return { iterations: null, total: null };
|
|
14737
|
+
return { iterations, total };
|
|
14738
|
+
}
|
|
14739
|
+
async searchEpics(query) {
|
|
14740
|
+
const response = await this.client.searchEpics({ query, page_size: 25, detail: "slim" });
|
|
14741
|
+
const epics = response?.data?.data;
|
|
14742
|
+
const total = response?.data?.total;
|
|
14743
|
+
if (!epics)
|
|
14744
|
+
return { epics: null, total: null };
|
|
14745
|
+
return { epics, total };
|
|
14746
|
+
}
|
|
14747
|
+
async searchMilestones(query) {
|
|
14748
|
+
const response = await this.client.searchMilestones({ query, page_size: 25, detail: "slim" });
|
|
14749
|
+
const milestones = response?.data?.data;
|
|
14750
|
+
const total = response?.data?.total;
|
|
14751
|
+
if (!milestones)
|
|
14752
|
+
return { milestones: null, total: null };
|
|
14753
|
+
return { milestones, total };
|
|
14754
|
+
}
|
|
14755
|
+
async listIterationStories(iterationPublicId) {
|
|
14756
|
+
const response = await this.client.listIterationStories(iterationPublicId, {
|
|
14757
|
+
includes_description: false
|
|
14758
|
+
});
|
|
14759
|
+
const stories = response?.data;
|
|
14760
|
+
if (!stories)
|
|
14761
|
+
return { stories: null, total: null };
|
|
14762
|
+
return { stories, total: stories.length };
|
|
14763
|
+
}
|
|
14764
|
+
}
|
|
14573
14765
|
|
|
14574
14766
|
// node_modules/zod/lib/index.mjs
|
|
14575
14767
|
var util;
|
|
@@ -15438,11 +15630,11 @@ function datetimeRegex(args) {
|
|
|
15438
15630
|
regex = `${regex}(${opts.join("|")})`;
|
|
15439
15631
|
return new RegExp(`^${regex}$`);
|
|
15440
15632
|
}
|
|
15441
|
-
function isValidIP(ip,
|
|
15442
|
-
if ((
|
|
15633
|
+
function isValidIP(ip, version) {
|
|
15634
|
+
if ((version === "v4" || !version) && ipv4Regex.test(ip)) {
|
|
15443
15635
|
return true;
|
|
15444
15636
|
}
|
|
15445
|
-
if ((
|
|
15637
|
+
if ((version === "v6" || !version) && ipv6Regex.test(ip)) {
|
|
15446
15638
|
return true;
|
|
15447
15639
|
}
|
|
15448
15640
|
return false;
|
|
@@ -15465,11 +15657,11 @@ function isValidJWT(jwt, alg) {
|
|
|
15465
15657
|
return false;
|
|
15466
15658
|
}
|
|
15467
15659
|
}
|
|
15468
|
-
function isValidCidr(ip,
|
|
15469
|
-
if ((
|
|
15660
|
+
function isValidCidr(ip, version) {
|
|
15661
|
+
if ((version === "v4" || !version) && ipv4CidrRegex.test(ip)) {
|
|
15470
15662
|
return true;
|
|
15471
15663
|
}
|
|
15472
|
-
if ((
|
|
15664
|
+
if ((version === "v6" || !version) && ipv6CidrRegex.test(ip)) {
|
|
15473
15665
|
return true;
|
|
15474
15666
|
}
|
|
15475
15667
|
return false;
|
|
@@ -19498,11 +19690,11 @@ var getRefs = (options) => {
|
|
|
19498
19690
|
..._options,
|
|
19499
19691
|
currentPath,
|
|
19500
19692
|
propertyPath: undefined,
|
|
19501
|
-
seen: new Map(Object.entries(_options.definitions).map(([
|
|
19693
|
+
seen: new Map(Object.entries(_options.definitions).map(([name, def]) => [
|
|
19502
19694
|
def._def,
|
|
19503
19695
|
{
|
|
19504
19696
|
def: def._def,
|
|
19505
|
-
path: [..._options.basePath, _options.definitionPath,
|
|
19697
|
+
path: [..._options.basePath, _options.definitionPath, name],
|
|
19506
19698
|
jsonSchema: undefined
|
|
19507
19699
|
}
|
|
19508
19700
|
]))
|
|
@@ -20600,34 +20792,34 @@ var addMeta = (def, refs, jsonSchema) => {
|
|
|
20600
20792
|
// node_modules/zod-to-json-schema/dist/esm/zodToJsonSchema.js
|
|
20601
20793
|
var zodToJsonSchema = (schema, options) => {
|
|
20602
20794
|
const refs = getRefs(options);
|
|
20603
|
-
const definitions = typeof options === "object" && options.definitions ? Object.entries(options.definitions).reduce((acc, [
|
|
20795
|
+
const definitions = typeof options === "object" && options.definitions ? Object.entries(options.definitions).reduce((acc, [name2, schema2]) => ({
|
|
20604
20796
|
...acc,
|
|
20605
|
-
[
|
|
20797
|
+
[name2]: parseDef(schema2._def, {
|
|
20606
20798
|
...refs,
|
|
20607
|
-
currentPath: [...refs.basePath, refs.definitionPath,
|
|
20799
|
+
currentPath: [...refs.basePath, refs.definitionPath, name2]
|
|
20608
20800
|
}, true) ?? {}
|
|
20609
20801
|
}), {}) : undefined;
|
|
20610
|
-
const
|
|
20611
|
-
const main = parseDef(schema._def,
|
|
20802
|
+
const name = typeof options === "string" ? options : options?.nameStrategy === "title" ? undefined : options?.name;
|
|
20803
|
+
const main = parseDef(schema._def, name === undefined ? refs : {
|
|
20612
20804
|
...refs,
|
|
20613
|
-
currentPath: [...refs.basePath, refs.definitionPath,
|
|
20805
|
+
currentPath: [...refs.basePath, refs.definitionPath, name]
|
|
20614
20806
|
}, false) ?? {};
|
|
20615
20807
|
const title = typeof options === "object" && options.name !== undefined && options.nameStrategy === "title" ? options.name : undefined;
|
|
20616
20808
|
if (title !== undefined) {
|
|
20617
20809
|
main.title = title;
|
|
20618
20810
|
}
|
|
20619
|
-
const combined =
|
|
20811
|
+
const combined = name === undefined ? definitions ? {
|
|
20620
20812
|
...main,
|
|
20621
20813
|
[refs.definitionPath]: definitions
|
|
20622
20814
|
} : main : {
|
|
20623
20815
|
$ref: [
|
|
20624
20816
|
...refs.$refStrategy === "relative" ? [] : refs.basePath,
|
|
20625
20817
|
refs.definitionPath,
|
|
20626
|
-
|
|
20818
|
+
name
|
|
20627
20819
|
].join("/"),
|
|
20628
20820
|
[refs.definitionPath]: {
|
|
20629
20821
|
...definitions,
|
|
20630
|
-
[
|
|
20822
|
+
[name]: main
|
|
20631
20823
|
}
|
|
20632
20824
|
};
|
|
20633
20825
|
if (refs.target === "jsonSchema7") {
|
|
@@ -20722,9 +20914,9 @@ class McpServer {
|
|
|
20722
20914
|
tools: {}
|
|
20723
20915
|
});
|
|
20724
20916
|
this.server.setRequestHandler(ListToolsRequestSchema, () => ({
|
|
20725
|
-
tools: Object.entries(this._registeredTools).map(([
|
|
20917
|
+
tools: Object.entries(this._registeredTools).map(([name, tool]) => {
|
|
20726
20918
|
return {
|
|
20727
|
-
name
|
|
20919
|
+
name,
|
|
20728
20920
|
description: tool.description,
|
|
20729
20921
|
inputSchema: tool.inputSchema ? zodToJsonSchema(tool.inputSchema, {
|
|
20730
20922
|
strictUnions: true
|
|
@@ -20856,8 +21048,8 @@ class McpServer {
|
|
|
20856
21048
|
return { resources: [...resources, ...templateResources] };
|
|
20857
21049
|
});
|
|
20858
21050
|
this.server.setRequestHandler(ListResourceTemplatesRequestSchema, async () => {
|
|
20859
|
-
const resourceTemplates = Object.entries(this._registeredResourceTemplates).map(([
|
|
20860
|
-
name
|
|
21051
|
+
const resourceTemplates = Object.entries(this._registeredResourceTemplates).map(([name, template]) => ({
|
|
21052
|
+
name,
|
|
20861
21053
|
uriTemplate: template.resourceTemplate.uriTemplate.toString(),
|
|
20862
21054
|
...template.metadata
|
|
20863
21055
|
}));
|
|
@@ -20890,9 +21082,9 @@ class McpServer {
|
|
|
20890
21082
|
prompts: {}
|
|
20891
21083
|
});
|
|
20892
21084
|
this.server.setRequestHandler(ListPromptsRequestSchema, () => ({
|
|
20893
|
-
prompts: Object.entries(this._registeredPrompts).map(([
|
|
21085
|
+
prompts: Object.entries(this._registeredPrompts).map(([name, prompt]) => {
|
|
20894
21086
|
return {
|
|
20895
|
-
name
|
|
21087
|
+
name,
|
|
20896
21088
|
description: prompt.description,
|
|
20897
21089
|
arguments: prompt.argsSchema ? promptArgumentsFromSchema(prompt.argsSchema) : undefined
|
|
20898
21090
|
};
|
|
@@ -20919,7 +21111,7 @@ class McpServer {
|
|
|
20919
21111
|
this.setCompletionRequestHandler();
|
|
20920
21112
|
this._promptHandlersInitialized = true;
|
|
20921
21113
|
}
|
|
20922
|
-
resource(
|
|
21114
|
+
resource(name, uriOrTemplate, ...rest) {
|
|
20923
21115
|
let metadata;
|
|
20924
21116
|
if (typeof rest[0] === "object") {
|
|
20925
21117
|
metadata = rest.shift();
|
|
@@ -20930,15 +21122,15 @@ class McpServer {
|
|
|
20930
21122
|
throw new Error(`Resource ${uriOrTemplate} is already registered`);
|
|
20931
21123
|
}
|
|
20932
21124
|
this._registeredResources[uriOrTemplate] = {
|
|
20933
|
-
name
|
|
21125
|
+
name,
|
|
20934
21126
|
metadata,
|
|
20935
21127
|
readCallback
|
|
20936
21128
|
};
|
|
20937
21129
|
} else {
|
|
20938
|
-
if (this._registeredResourceTemplates[
|
|
20939
|
-
throw new Error(`Resource template ${
|
|
21130
|
+
if (this._registeredResourceTemplates[name]) {
|
|
21131
|
+
throw new Error(`Resource template ${name} is already registered`);
|
|
20940
21132
|
}
|
|
20941
|
-
this._registeredResourceTemplates[
|
|
21133
|
+
this._registeredResourceTemplates[name] = {
|
|
20942
21134
|
resourceTemplate: uriOrTemplate,
|
|
20943
21135
|
metadata,
|
|
20944
21136
|
readCallback
|
|
@@ -20946,9 +21138,9 @@ class McpServer {
|
|
|
20946
21138
|
}
|
|
20947
21139
|
this.setResourceRequestHandlers();
|
|
20948
21140
|
}
|
|
20949
|
-
tool(
|
|
20950
|
-
if (this._registeredTools[
|
|
20951
|
-
throw new Error(`Tool ${
|
|
21141
|
+
tool(name, ...rest) {
|
|
21142
|
+
if (this._registeredTools[name]) {
|
|
21143
|
+
throw new Error(`Tool ${name} is already registered`);
|
|
20952
21144
|
}
|
|
20953
21145
|
let description;
|
|
20954
21146
|
if (typeof rest[0] === "string") {
|
|
@@ -20959,16 +21151,16 @@ class McpServer {
|
|
|
20959
21151
|
paramsSchema = rest.shift();
|
|
20960
21152
|
}
|
|
20961
21153
|
const cb = rest[0];
|
|
20962
|
-
this._registeredTools[
|
|
21154
|
+
this._registeredTools[name] = {
|
|
20963
21155
|
description,
|
|
20964
21156
|
inputSchema: paramsSchema === undefined ? undefined : z.object(paramsSchema),
|
|
20965
21157
|
callback: cb
|
|
20966
21158
|
};
|
|
20967
21159
|
this.setToolRequestHandlers();
|
|
20968
21160
|
}
|
|
20969
|
-
prompt(
|
|
20970
|
-
if (this._registeredPrompts[
|
|
20971
|
-
throw new Error(`Prompt ${
|
|
21161
|
+
prompt(name, ...rest) {
|
|
21162
|
+
if (this._registeredPrompts[name]) {
|
|
21163
|
+
throw new Error(`Prompt ${name} is already registered`);
|
|
20972
21164
|
}
|
|
20973
21165
|
let description;
|
|
20974
21166
|
if (typeof rest[0] === "string") {
|
|
@@ -20979,7 +21171,7 @@ class McpServer {
|
|
|
20979
21171
|
argsSchema = rest.shift();
|
|
20980
21172
|
}
|
|
20981
21173
|
const cb = rest[0];
|
|
20982
|
-
this._registeredPrompts[
|
|
21174
|
+
this._registeredPrompts[name] = {
|
|
20983
21175
|
description,
|
|
20984
21176
|
argsSchema: argsSchema === undefined ? undefined : z.object(argsSchema),
|
|
20985
21177
|
callback: cb
|
|
@@ -20991,8 +21183,8 @@ var EMPTY_OBJECT_JSON_SCHEMA = {
|
|
|
20991
21183
|
type: "object"
|
|
20992
21184
|
};
|
|
20993
21185
|
function promptArgumentsFromSchema(schema) {
|
|
20994
|
-
return Object.entries(schema.shape).map(([
|
|
20995
|
-
name
|
|
21186
|
+
return Object.entries(schema.shape).map(([name, field]) => ({
|
|
21187
|
+
name,
|
|
20996
21188
|
description: field.description,
|
|
20997
21189
|
required: !field.isOptional()
|
|
20998
21190
|
}));
|
|
@@ -21110,220 +21302,71 @@ class StdioServerTransport {
|
|
|
21110
21302
|
// src/server.ts
|
|
21111
21303
|
var import_client = __toESM(require_lib(), 1);
|
|
21112
21304
|
|
|
21113
|
-
//
|
|
21114
|
-
|
|
21115
|
-
|
|
21116
|
-
age;
|
|
21117
|
-
constructor() {
|
|
21118
|
-
this.cache = new Map;
|
|
21119
|
-
this.age = 0;
|
|
21120
|
-
}
|
|
21121
|
-
get(key) {
|
|
21122
|
-
return this.cache.get(key) ?? null;
|
|
21123
|
-
}
|
|
21124
|
-
values() {
|
|
21125
|
-
return Array.from(this.cache.values());
|
|
21126
|
-
}
|
|
21127
|
-
setMany(values) {
|
|
21128
|
-
this.cache.clear();
|
|
21129
|
-
for (const [key, value] of values) {
|
|
21130
|
-
this.cache.set(key, value);
|
|
21131
|
-
}
|
|
21132
|
-
this.age = Date.now();
|
|
21133
|
-
}
|
|
21134
|
-
clear() {
|
|
21135
|
-
this.cache.clear();
|
|
21136
|
-
this.age = 0;
|
|
21137
|
-
}
|
|
21138
|
-
get isStale() {
|
|
21139
|
-
return Date.now() - this.age > 1000 * 60 * 5;
|
|
21140
|
-
}
|
|
21141
|
-
}
|
|
21305
|
+
// package.json
|
|
21306
|
+
var name = "@shortcut/mcp";
|
|
21307
|
+
var version = "0.2.1";
|
|
21142
21308
|
|
|
21143
|
-
// src/
|
|
21144
|
-
class
|
|
21309
|
+
// src/tools/base.ts
|
|
21310
|
+
class BaseTools {
|
|
21145
21311
|
client;
|
|
21146
|
-
currentUser = null;
|
|
21147
|
-
userCache;
|
|
21148
|
-
workflowCache;
|
|
21149
21312
|
constructor(client) {
|
|
21150
21313
|
this.client = client;
|
|
21151
|
-
this.userCache = new Cache;
|
|
21152
|
-
this.workflowCache = new Cache;
|
|
21153
21314
|
}
|
|
21154
|
-
|
|
21155
|
-
|
|
21156
|
-
const response = await this.client.listMembers({});
|
|
21157
|
-
const members = response?.data ?? null;
|
|
21158
|
-
if (members) {
|
|
21159
|
-
this.userCache.setMany(members.map((member) => [member.id, member]));
|
|
21160
|
-
}
|
|
21161
|
-
}
|
|
21162
|
-
}
|
|
21163
|
-
async loadWorkflows() {
|
|
21164
|
-
if (this.workflowCache.isStale) {
|
|
21165
|
-
const response = await this.client.listWorkflows();
|
|
21166
|
-
const workflows = response?.data ?? null;
|
|
21167
|
-
if (workflows) {
|
|
21168
|
-
this.workflowCache.setMany(workflows.map((workflow) => [workflow.id, workflow]));
|
|
21169
|
-
}
|
|
21170
|
-
}
|
|
21171
|
-
}
|
|
21172
|
-
async getCurrentUser() {
|
|
21173
|
-
if (this.currentUser)
|
|
21174
|
-
return this.currentUser;
|
|
21175
|
-
const response = await this.client.getCurrentMemberInfo();
|
|
21176
|
-
const user = response?.data;
|
|
21177
|
-
if (!user)
|
|
21178
|
-
return null;
|
|
21179
|
-
this.currentUser = user;
|
|
21180
|
-
return user;
|
|
21181
|
-
}
|
|
21182
|
-
async getUser(userId) {
|
|
21183
|
-
const response = await this.client.getMember(userId, {});
|
|
21184
|
-
const user = response?.data;
|
|
21185
|
-
if (!user)
|
|
21186
|
-
return null;
|
|
21187
|
-
return user;
|
|
21188
|
-
}
|
|
21189
|
-
async getUserMap(userIds) {
|
|
21190
|
-
await this.loadMembers();
|
|
21191
|
-
return new Map(userIds.map((id) => [id, this.userCache.get(id)]).filter((user) => user[1] !== null));
|
|
21192
|
-
}
|
|
21193
|
-
async getUsers(userIds) {
|
|
21194
|
-
await this.loadMembers();
|
|
21195
|
-
return userIds.map((id) => this.userCache.get(id)).filter((user) => user !== null);
|
|
21196
|
-
}
|
|
21197
|
-
async getWorkflowMap(workflowIds) {
|
|
21198
|
-
await this.loadWorkflows();
|
|
21199
|
-
return new Map(workflowIds.map((id) => [id, this.workflowCache.get(id)]).filter((workflow) => workflow[1] !== null));
|
|
21200
|
-
}
|
|
21201
|
-
async getWorkflows() {
|
|
21202
|
-
await this.loadWorkflows();
|
|
21203
|
-
return Array.from(this.workflowCache.values());
|
|
21204
|
-
}
|
|
21205
|
-
async getWorkflow(workflowPublicId) {
|
|
21206
|
-
const response = await this.client.getWorkflow(workflowPublicId);
|
|
21207
|
-
const workflow = response?.data;
|
|
21208
|
-
if (!workflow)
|
|
21209
|
-
return null;
|
|
21210
|
-
return workflow;
|
|
21211
|
-
}
|
|
21212
|
-
async getTeams() {
|
|
21213
|
-
const response = await this.client.listGroups();
|
|
21214
|
-
const groups = response?.data ?? [];
|
|
21215
|
-
return groups;
|
|
21216
|
-
}
|
|
21217
|
-
async getTeam(teamPublicId) {
|
|
21218
|
-
const response = await this.client.getGroup(teamPublicId);
|
|
21219
|
-
const group = response?.data;
|
|
21220
|
-
if (!group)
|
|
21221
|
-
return null;
|
|
21222
|
-
return group;
|
|
21223
|
-
}
|
|
21224
|
-
async createStory(params) {
|
|
21225
|
-
const response = await this.client.createStory(params);
|
|
21226
|
-
const story = response?.data ?? null;
|
|
21227
|
-
if (!story)
|
|
21228
|
-
throw new Error(`Failed to create the story: ${response.status}`);
|
|
21229
|
-
return story;
|
|
21230
|
-
}
|
|
21231
|
-
async updateStory(storyPublicId, params) {
|
|
21232
|
-
const response = await this.client.updateStory(storyPublicId, params);
|
|
21233
|
-
const story = response?.data ?? null;
|
|
21234
|
-
if (!story)
|
|
21235
|
-
throw new Error(`Failed to update the story: ${response.status}`);
|
|
21236
|
-
return story;
|
|
21237
|
-
}
|
|
21238
|
-
async getStory(storyPublicId) {
|
|
21239
|
-
const response = await this.client.getStory(storyPublicId);
|
|
21240
|
-
const story = response?.data ?? null;
|
|
21241
|
-
if (!story)
|
|
21242
|
-
return null;
|
|
21243
|
-
return story;
|
|
21244
|
-
}
|
|
21245
|
-
async getEpic(epicPublicId) {
|
|
21246
|
-
const response = await this.client.getEpic(epicPublicId);
|
|
21247
|
-
const epic = response?.data ?? null;
|
|
21248
|
-
if (!epic)
|
|
21249
|
-
return null;
|
|
21250
|
-
return epic;
|
|
21251
|
-
}
|
|
21252
|
-
async getIteration(iterationPublicId) {
|
|
21253
|
-
const response = await this.client.getIteration(iterationPublicId);
|
|
21254
|
-
const iteration = response?.data ?? null;
|
|
21255
|
-
if (!iteration)
|
|
21256
|
-
return null;
|
|
21257
|
-
return iteration;
|
|
21258
|
-
}
|
|
21259
|
-
async getMilestone(milestonePublicId) {
|
|
21260
|
-
const response = await this.client.getMilestone(milestonePublicId);
|
|
21261
|
-
const milestone = response?.data ?? null;
|
|
21262
|
-
if (!milestone)
|
|
21263
|
-
return null;
|
|
21264
|
-
return milestone;
|
|
21265
|
-
}
|
|
21266
|
-
async searchStories(query) {
|
|
21267
|
-
const response = await this.client.searchStories({ query, page_size: 25, detail: "slim" });
|
|
21268
|
-
const stories = response?.data?.data;
|
|
21269
|
-
const total = response?.data?.total;
|
|
21270
|
-
if (!stories)
|
|
21271
|
-
return { stories: null, total: null };
|
|
21272
|
-
return { stories, total };
|
|
21273
|
-
}
|
|
21274
|
-
async searchIterations(query) {
|
|
21275
|
-
const response = await this.client.searchIterations({ query, page_size: 25, detail: "slim" });
|
|
21276
|
-
const iterations = response?.data?.data;
|
|
21277
|
-
const total = response?.data?.total;
|
|
21278
|
-
if (!iterations)
|
|
21279
|
-
return { iterations: null, total: null };
|
|
21280
|
-
return { iterations, total };
|
|
21281
|
-
}
|
|
21282
|
-
async searchEpics(query) {
|
|
21283
|
-
const response = await this.client.searchEpics({ query, page_size: 25, detail: "slim" });
|
|
21284
|
-
const epics = response?.data?.data;
|
|
21285
|
-
const total = response?.data?.total;
|
|
21286
|
-
if (!epics)
|
|
21287
|
-
return { epics: null, total: null };
|
|
21288
|
-
return { epics, total };
|
|
21289
|
-
}
|
|
21290
|
-
async searchMilestones(query) {
|
|
21291
|
-
const response = await this.client.searchMilestones({ query, page_size: 25, detail: "slim" });
|
|
21292
|
-
const milestones = response?.data?.data;
|
|
21293
|
-
const total = response?.data?.total;
|
|
21294
|
-
if (!milestones)
|
|
21295
|
-
return { milestones: null, total: null };
|
|
21296
|
-
return { milestones, total };
|
|
21297
|
-
}
|
|
21298
|
-
async listIterationStories(iterationPublicId) {
|
|
21299
|
-
const response = await this.client.listIterationStories(iterationPublicId, {
|
|
21300
|
-
includes_description: false
|
|
21301
|
-
});
|
|
21302
|
-
const stories = response?.data;
|
|
21303
|
-
if (!stories)
|
|
21304
|
-
return { stories: null, total: null };
|
|
21305
|
-
return { stories, total: stories.length };
|
|
21315
|
+
toResult(content) {
|
|
21316
|
+
return { content: [{ type: "text", text: content }] };
|
|
21306
21317
|
}
|
|
21307
21318
|
}
|
|
21308
21319
|
|
|
21309
21320
|
// src/tools/utils/format.ts
|
|
21310
|
-
var
|
|
21311
|
-
return
|
|
21312
|
-
`)
|
|
21321
|
+
var formatAsUnorderedList = (items, label) => {
|
|
21322
|
+
return `${label ? `${label}:` : ""}${items?.length ? `${label ? `
|
|
21323
|
+
` : ""}${items.map((item) => `- ${item}`).join(`
|
|
21324
|
+
`)}` : `${label ? " " : ""}[None]`}`;
|
|
21325
|
+
};
|
|
21326
|
+
var formatStoryList = (stories, users, label) => {
|
|
21327
|
+
return formatAsUnorderedList(stories.map((story) => `sc-${story.id}: ${story.name} (Type: ${story.story_type}, State: ${story.completed ? "Completed" : story.started ? "In Progress" : "Not Started"}, Team: ${story.group_id ? `${story.group_id}` : "[None]"}, Epic: ${story.epic_id ? `${story.epic_id}` : "[None]"}, Iteration: ${story.iteration_id ? `${story.iteration_id}` : "[None]"}, Owners: ${story.owner_ids.map((ownerId) => users.get(ownerId)).filter((owner) => owner !== null).map((owner) => `@${owner.profile.mention_name}`).join(", ") || "[None]"})`), label);
|
|
21313
21328
|
};
|
|
21314
|
-
var formatMemberList = (ids, users) => {
|
|
21315
|
-
return ids.map((id) => {
|
|
21329
|
+
var formatMemberList = (ids, users, label = "Members") => {
|
|
21330
|
+
return formatAsUnorderedList((ids || []).map((id) => {
|
|
21316
21331
|
const user = users.get(id);
|
|
21317
|
-
return user ?
|
|
21318
|
-
})
|
|
21319
|
-
`);
|
|
21332
|
+
return user ? `id=${user.id} @${user.profile.mention_name}` : `id=${id} [Unknown]`;
|
|
21333
|
+
}), label);
|
|
21320
21334
|
};
|
|
21321
21335
|
var formatWorkflowList = (ids, workflows) => {
|
|
21322
|
-
return ids.map((id) => workflows.get(id)).filter((workflow) => !!workflow).map((workflow) => {
|
|
21336
|
+
return formatAsUnorderedList((ids || []).map((id) => workflows.get(id)).filter((workflow) => !!workflow).map((workflow) => {
|
|
21323
21337
|
const defaultState = workflow.states.find((state) => state.id === workflow.default_state_id);
|
|
21324
|
-
return
|
|
21325
|
-
})
|
|
21326
|
-
|
|
21338
|
+
return `id=${workflow.id} name=${workflow.name}. Default state: ${defaultState ? `id=${defaultState.id} name=${defaultState.name}` : "[Unknown]"}`;
|
|
21339
|
+
}), "Workflows");
|
|
21340
|
+
};
|
|
21341
|
+
var formatPullRequestList = (branches) => {
|
|
21342
|
+
return formatAsUnorderedList((branches || []).flatMap((branch) => branch.pull_requests || []).map((pr) => `Title: ${pr.title}, Merged: ${pr.merged ? "Yes" : "No"}, URL: ${pr.url}`), "Pull Requests");
|
|
21343
|
+
};
|
|
21344
|
+
var formatTaskList = (tasks) => {
|
|
21345
|
+
return formatAsUnorderedList((tasks || []).map((task) => `[${task.complete ? "X" : " "}] ${task.description}`), "Tasks");
|
|
21346
|
+
};
|
|
21347
|
+
|
|
21348
|
+
// src/tools/utils/search.ts
|
|
21349
|
+
var getKey = (prop) => {
|
|
21350
|
+
if (prop.startsWith("is"))
|
|
21351
|
+
return `is:${prop.slice(2).toLowerCase()}`;
|
|
21352
|
+
if (prop.startsWith("has"))
|
|
21353
|
+
return `has:${prop.slice(3).toLowerCase()}`;
|
|
21354
|
+
return prop;
|
|
21355
|
+
};
|
|
21356
|
+
var buildSearchQuery = async (params, currentUser) => {
|
|
21357
|
+
const query = Object.entries(params).map(([key, value]) => {
|
|
21358
|
+
const q = getKey(key);
|
|
21359
|
+
if ((key === "owner" || key === "requester") && value === "me")
|
|
21360
|
+
return `${q}:${currentUser?.mention_name || value}`;
|
|
21361
|
+
if (typeof value === "boolean")
|
|
21362
|
+
return value ? q : `!${q}`;
|
|
21363
|
+
if (typeof value === "number")
|
|
21364
|
+
return `${q}:${value}`;
|
|
21365
|
+
if (typeof value === "string" && value.includes(" "))
|
|
21366
|
+
return `${q}:"${value}"`;
|
|
21367
|
+
return `${q}:${value}`;
|
|
21368
|
+
}).join(" ");
|
|
21369
|
+
return query;
|
|
21327
21370
|
};
|
|
21328
21371
|
|
|
21329
21372
|
// src/tools/utils/validation.ts
|
|
@@ -21353,38 +21396,175 @@ var is = (field) => z.boolean().optional().describe(`Find only entities that are
|
|
|
21353
21396
|
var has = (field) => z.boolean().optional().describe(`Find only entities that have ${field} when true, or only entities that do not have ${field} when false.`);
|
|
21354
21397
|
var user = (field) => z.string().optional().describe(`Find entities where the ${field} match the specified user. This must either be the user's mention name or the keyword "me" for the current user.`);
|
|
21355
21398
|
|
|
21356
|
-
// src/tools/
|
|
21357
|
-
|
|
21358
|
-
|
|
21359
|
-
|
|
21360
|
-
|
|
21361
|
-
|
|
21362
|
-
|
|
21363
|
-
|
|
21364
|
-
|
|
21365
|
-
|
|
21366
|
-
|
|
21367
|
-
|
|
21368
|
-
|
|
21369
|
-
|
|
21370
|
-
|
|
21371
|
-
|
|
21372
|
-
|
|
21373
|
-
|
|
21374
|
-
|
|
21375
|
-
|
|
21376
|
-
|
|
21377
|
-
|
|
21378
|
-
|
|
21399
|
+
// src/tools/epics.ts
|
|
21400
|
+
class EpicTools extends BaseTools {
|
|
21401
|
+
static create(client, server) {
|
|
21402
|
+
const tools = new EpicTools(client);
|
|
21403
|
+
server.tool("get-epic", "Get a Shortcut epic by public ID", { epicPublicId: z.number().positive().describe("The public ID of the epic to get") }, async ({ epicPublicId }) => await tools.getEpic(epicPublicId));
|
|
21404
|
+
server.tool("search-epics", "Find Shortcut epics.", {
|
|
21405
|
+
id: z.number().optional().describe("Find only epics with the specified public ID"),
|
|
21406
|
+
name: z.string().optional().describe("Find only epics matching the specified name"),
|
|
21407
|
+
description: z.string().optional().describe("Find only epics matching the specified description"),
|
|
21408
|
+
state: z.enum(["unstarted", "started", "done"]).optional().describe("Find only epics matching the specified state"),
|
|
21409
|
+
objective: z.number().optional().describe("Find only epics matching the specified objective"),
|
|
21410
|
+
owner: user("owner"),
|
|
21411
|
+
requester: user("requester"),
|
|
21412
|
+
team: z.string().optional().describe("Find only epics matching the specified team. Should be a team's mention name."),
|
|
21413
|
+
comment: z.string().optional().describe("Find only epics matching the specified comment"),
|
|
21414
|
+
isUnstarted: is("unstarted"),
|
|
21415
|
+
isStarted: is("started"),
|
|
21416
|
+
isDone: is("completed"),
|
|
21417
|
+
isArchived: is("archived").default(false),
|
|
21418
|
+
isOverdue: is("overdue"),
|
|
21419
|
+
hasOwner: has("an owner"),
|
|
21420
|
+
hasComment: has("a comment"),
|
|
21421
|
+
hasDeadline: has("a deadline"),
|
|
21422
|
+
hasLabel: has("a label"),
|
|
21423
|
+
created: date2,
|
|
21424
|
+
updated: date2,
|
|
21425
|
+
completed: date2,
|
|
21426
|
+
due: date2
|
|
21427
|
+
}, async (params) => await tools.searchEpics(params));
|
|
21428
|
+
return tools;
|
|
21429
|
+
}
|
|
21430
|
+
async searchEpics(params) {
|
|
21431
|
+
const currentUser = await this.client.getCurrentUser();
|
|
21432
|
+
const query = await buildSearchQuery(params, currentUser);
|
|
21433
|
+
const { epics, total } = await this.client.searchEpics(query);
|
|
21434
|
+
if (!epics)
|
|
21435
|
+
throw new Error(`Failed to search for epics matching your query: "${query}"`);
|
|
21436
|
+
if (!epics.length)
|
|
21437
|
+
return this.toResult(`Result: No epics found.`);
|
|
21438
|
+
return this.toResult(`Result (first ${epics.length} shown of ${total} total epics found):
|
|
21439
|
+
${formatAsUnorderedList(epics.map((epic) => `${epic.id}: ${epic.name}`))}`);
|
|
21440
|
+
}
|
|
21441
|
+
async getEpic(epicPublicId) {
|
|
21442
|
+
const epic = await this.client.getEpic(epicPublicId);
|
|
21443
|
+
if (!epic)
|
|
21444
|
+
throw new Error(`Failed to retrieve Shortcut epic with public ID: ${epicPublicId}`);
|
|
21445
|
+
return this.toResult(`Epic: ${epicPublicId}
|
|
21446
|
+
URL: ${epic.app_url}
|
|
21447
|
+
Name: ${epic.name}
|
|
21448
|
+
Archived: ${epic.archived ? "Yes" : "No"}
|
|
21449
|
+
Completed: ${epic.completed ? "Yes" : "No"}
|
|
21450
|
+
Started: ${epic.started ? "Yes" : "No"}
|
|
21451
|
+
Due date: ${epic.deadline ? epic.deadline : "[Not set]"}
|
|
21452
|
+
Team: ${epic.group_id ? `${epic.group_id}` : "[None]"}
|
|
21453
|
+
Objective: ${epic.milestone_id ? `${epic.milestone_id}` : "[None]"}
|
|
21379
21454
|
|
|
21380
|
-
|
|
21381
|
-
|
|
21382
|
-
|
|
21383
|
-
|
|
21384
|
-
|
|
21455
|
+
Description:
|
|
21456
|
+
${epic.description}`);
|
|
21457
|
+
}
|
|
21458
|
+
}
|
|
21459
|
+
|
|
21460
|
+
// src/tools/iterations.ts
|
|
21461
|
+
class IterationTools extends BaseTools {
|
|
21462
|
+
static create(client, server) {
|
|
21463
|
+
const tools = new IterationTools(client);
|
|
21464
|
+
server.tool("get-iteration-stories", "Get stories in a specific iteration by iteration public ID", { iterationPublicId: z.number().positive().describe("The public ID of the iteration") }, async ({ iterationPublicId }) => await tools.getIterationStories(iterationPublicId));
|
|
21465
|
+
server.tool("get-iteration", "Get a Shortcut iteration by public ID", {
|
|
21466
|
+
iterationPublicId: z.number().positive().describe("The public ID of the iteration to get")
|
|
21467
|
+
}, async ({ iterationPublicId }) => await tools.getIteration(iterationPublicId));
|
|
21468
|
+
server.tool("search-iterations", "Find Shortcut iterations.", {
|
|
21469
|
+
id: z.number().optional().describe("Find only iterations with the specified public ID"),
|
|
21470
|
+
name: z.string().optional().describe("Find only iterations matching the specified name"),
|
|
21471
|
+
description: z.string().optional().describe("Find only iterations matching the specified description"),
|
|
21472
|
+
state: z.enum(["started", "unstarted", "done"]).optional().describe("Find only iterations matching the specified state"),
|
|
21473
|
+
team: z.string().optional().describe("Find only iterations matching the specified team. Should be a team mention name."),
|
|
21474
|
+
created: date2,
|
|
21475
|
+
updated: date2,
|
|
21476
|
+
startDate: date2,
|
|
21477
|
+
endDate: date2
|
|
21478
|
+
}, async (params) => await tools.searchIterations(params));
|
|
21479
|
+
return tools;
|
|
21480
|
+
}
|
|
21481
|
+
async getIterationStories(iterationPublicId) {
|
|
21482
|
+
const { stories } = await this.client.listIterationStories(iterationPublicId);
|
|
21483
|
+
if (!stories)
|
|
21484
|
+
throw new Error(`Failed to retrieve Shortcut stories in iteration with public ID: ${iterationPublicId}.`);
|
|
21485
|
+
const owners = await this.client.getUserMap(stories.flatMap((story) => story.owner_ids));
|
|
21486
|
+
return this.toResult(`Result (${stories.length} stories found):
|
|
21487
|
+
${formatStoryList(stories, owners)}`);
|
|
21488
|
+
}
|
|
21489
|
+
async searchIterations(params) {
|
|
21490
|
+
const currentUser = await this.client.getCurrentUser();
|
|
21491
|
+
const query = await buildSearchQuery(params, currentUser);
|
|
21492
|
+
const { iterations, total } = await this.client.searchIterations(query);
|
|
21493
|
+
if (!iterations)
|
|
21494
|
+
throw new Error(`Failed to search for iterations matching your query: "${query}".`);
|
|
21495
|
+
if (!iterations.length)
|
|
21496
|
+
return this.toResult(`Result: No iterations found.`);
|
|
21497
|
+
return this.toResult(`Result (first ${iterations.length} shown of ${total} total iterations found):
|
|
21498
|
+
${formatAsUnorderedList(iterations.map((iteration) => `${iteration.id}: ${iteration.name} (Start date: ${iteration.start_date}, End date: ${iteration.end_date})`))}`);
|
|
21499
|
+
}
|
|
21500
|
+
async getIteration(iterationPublicId) {
|
|
21501
|
+
const iteration = await this.client.getIteration(iterationPublicId);
|
|
21502
|
+
if (!iteration)
|
|
21503
|
+
throw new Error(`Failed to retrieve Shortcut iteration with public ID: ${iterationPublicId}.`);
|
|
21504
|
+
return this.toResult(`Iteration: ${iterationPublicId}
|
|
21505
|
+
Url: ${iteration.app_url}
|
|
21506
|
+
Name: ${iteration.name}
|
|
21507
|
+
Start date: ${iteration.start_date}
|
|
21508
|
+
End date: ${iteration.end_date}
|
|
21509
|
+
Completed: ${iteration.status === "completed" ? "Yes" : "No"}
|
|
21510
|
+
Started: ${iteration.status === "started" ? "Yes" : "No"}
|
|
21511
|
+
Team: ${iteration.group_ids?.length ? `${iteration.group_ids.join(", ")}` : "[None]"}
|
|
21512
|
+
|
|
21513
|
+
Description:
|
|
21514
|
+
${iteration.description}`);
|
|
21515
|
+
}
|
|
21516
|
+
}
|
|
21517
|
+
|
|
21518
|
+
// src/tools/objectives.ts
|
|
21519
|
+
class ObjectiveTools extends BaseTools {
|
|
21520
|
+
static create(client, server) {
|
|
21521
|
+
const tools = new ObjectiveTools(client);
|
|
21522
|
+
server.tool("get-objective", "Get a Shortcut objective by public ID", {
|
|
21523
|
+
objectivePublicId: z.number().positive().describe("The public ID of the objective to get")
|
|
21524
|
+
}, async ({ objectivePublicId }) => await tools.getObjective(objectivePublicId));
|
|
21525
|
+
server.tool("search-objectives", "Find Shortcut objectives.", {
|
|
21526
|
+
id: z.number().optional().describe("Find objectives matching the specified id"),
|
|
21527
|
+
name: z.string().optional().describe("Find objectives matching the specified name"),
|
|
21528
|
+
description: z.string().optional().describe("Find objectives matching the specified description"),
|
|
21529
|
+
state: z.enum(["unstarted", "started", "done"]).optional().describe("Find objectives matching the specified state"),
|
|
21530
|
+
owner: user("owner"),
|
|
21531
|
+
requester: user("requester"),
|
|
21532
|
+
team: z.string().optional().describe("Find objectives matching the specified team. Should be a team mention name."),
|
|
21533
|
+
isUnstarted: is("unstarted"),
|
|
21534
|
+
isStarted: is("started"),
|
|
21535
|
+
isDone: is("completed"),
|
|
21536
|
+
isArchived: is("archived"),
|
|
21537
|
+
hasOwner: has("an owner"),
|
|
21538
|
+
created: date2,
|
|
21539
|
+
updated: date2,
|
|
21540
|
+
completed: date2
|
|
21541
|
+
}, async (params) => await tools.searchObjectives(params));
|
|
21542
|
+
return tools;
|
|
21385
21543
|
}
|
|
21386
|
-
|
|
21387
|
-
|
|
21544
|
+
async searchObjectives(params) {
|
|
21545
|
+
const currentUser = await this.client.getCurrentUser();
|
|
21546
|
+
const query = await buildSearchQuery(params, currentUser);
|
|
21547
|
+
const { milestones, total } = await this.client.searchMilestones(query);
|
|
21548
|
+
if (!milestones)
|
|
21549
|
+
throw new Error(`Failed to search for milestones matching your query: "${query}"`);
|
|
21550
|
+
if (!milestones.length)
|
|
21551
|
+
return this.toResult(`Result: No milestones found.`);
|
|
21552
|
+
return this.toResult(`Result (first ${milestones.length} shown of ${total} total milestones found):
|
|
21553
|
+
${formatAsUnorderedList(milestones.map((milestone) => `${milestone.id}: ${milestone.name}`))}`);
|
|
21554
|
+
}
|
|
21555
|
+
async getObjective(objectivePublicId) {
|
|
21556
|
+
const objective = await this.client.getMilestone(objectivePublicId);
|
|
21557
|
+
if (!objective)
|
|
21558
|
+
throw new Error(`Failed to retrieve Shortcut objective with public ID: ${objectivePublicId}`);
|
|
21559
|
+
return this.toResult(`Objective: ${objectivePublicId}
|
|
21560
|
+
Url: ${objective.app_url}
|
|
21561
|
+
Name: ${objective.name}
|
|
21562
|
+
Archived: ${objective.archived ? "Yes" : "No"}
|
|
21563
|
+
Completed: ${objective.completed ? "Yes" : "No"}
|
|
21564
|
+
Started: ${objective.started ? "Yes" : "No"}
|
|
21565
|
+
|
|
21566
|
+
Description:
|
|
21567
|
+
${objective.description}`);
|
|
21388
21568
|
}
|
|
21389
21569
|
}
|
|
21390
21570
|
|
|
@@ -21392,8 +21572,12 @@ class BaseTools {
|
|
|
21392
21572
|
class StoryTools extends BaseTools {
|
|
21393
21573
|
static create(client, server) {
|
|
21394
21574
|
const tools = new StoryTools(client);
|
|
21395
|
-
server.tool("get-story-branch-name", 'Get a valid branch name for a specific story. The branch name is a combination of story ID, owner, and story name in the format "[owner]/sc-[id]/[name]". The story name will be truncated if the total length of the branch name exceeds 50 characters.', {
|
|
21396
|
-
|
|
21575
|
+
server.tool("get-story-branch-name", 'Get a valid branch name for a specific story. The branch name is a combination of story ID, owner, and story name in the format "[owner]/sc-[id]/[name]". The story name will be truncated if the total length of the branch name exceeds 50 characters.', {
|
|
21576
|
+
storyPublicId: z.number().positive().describe("The public Id of the story")
|
|
21577
|
+
}, async ({ storyPublicId }) => await tools.getStoryBranchName(storyPublicId));
|
|
21578
|
+
server.tool("get-story", "Get a Shortcut story by public ID", {
|
|
21579
|
+
storyPublicId: z.number().positive().describe("The public ID of the story to get")
|
|
21580
|
+
}, async ({ storyPublicId }) => await tools.getStory(storyPublicId));
|
|
21397
21581
|
server.tool("search-stories", "Find Shortcut stories.", {
|
|
21398
21582
|
id: z.number().optional().describe("Find only stories with the specified public ID"),
|
|
21399
21583
|
name: z.string().optional().describe("Find only stories matching the specified name"),
|
|
@@ -21451,9 +21635,21 @@ The story will be added to the default state for the workflow.
|
|
|
21451
21635
|
epic: z.number().optional().describe("The epic id of the epic the story belongs to"),
|
|
21452
21636
|
team: z.string().optional().describe("The team id of the team the story belongs to. Required unless a workflow is specified."),
|
|
21453
21637
|
workflow: z.number().optional().describe("The workflow to add the story to. Required unless a team is specified.")
|
|
21454
|
-
}, async ({ name: name2, description, type, owner, epic, team, workflow }) => await tools.createStory({
|
|
21455
|
-
|
|
21456
|
-
|
|
21638
|
+
}, async ({ name: name2, description, type, owner, epic, team, workflow }) => await tools.createStory({
|
|
21639
|
+
name: name2,
|
|
21640
|
+
description,
|
|
21641
|
+
type,
|
|
21642
|
+
owner,
|
|
21643
|
+
epic,
|
|
21644
|
+
team,
|
|
21645
|
+
workflow
|
|
21646
|
+
}));
|
|
21647
|
+
server.tool("assign-current-user-as-owner", "Assign the current user as the owner of a story", {
|
|
21648
|
+
storyPublicId: z.number().positive().describe("The public ID of the story")
|
|
21649
|
+
}, async ({ storyPublicId }) => await tools.assignCurrentUserAsOwner(storyPublicId));
|
|
21650
|
+
server.tool("unassign-current-user-as-owner", "Unassign the current user as the owner of a story", {
|
|
21651
|
+
storyPublicId: z.number().positive().describe("The public ID of the story")
|
|
21652
|
+
}, async ({ storyPublicId }) => await tools.unassignCurrentUserAsOwner(storyPublicId));
|
|
21457
21653
|
return tools;
|
|
21458
21654
|
}
|
|
21459
21655
|
async assignCurrentUserAsOwner(storyPublicId) {
|
|
@@ -21560,14 +21756,19 @@ Blocked: ${story.blocked ? "Yes" : "No"}
|
|
|
21560
21756
|
Blocking: ${story.blocker ? "Yes" : "No"}
|
|
21561
21757
|
Due date: ${story.deadline ? story.deadline : "[None]"}
|
|
21562
21758
|
Team: ${story.group_id ? `${story.group_id}` : "[None]"}
|
|
21563
|
-
|
|
21564
|
-
${formatMemberList(story.owner_ids, users)}` : " [None]"}
|
|
21759
|
+
${formatMemberList(story.owner_ids, users, "Owners")}
|
|
21565
21760
|
Epic: ${story.epic_id ? `${story.epic_id}` : "[None]"}
|
|
21566
21761
|
Iteration: ${story.iteration_id ? `${story.iteration_id}` : "[None]"}
|
|
21567
21762
|
|
|
21568
21763
|
Description:
|
|
21569
21764
|
${story.description}
|
|
21570
21765
|
|
|
21766
|
+
${formatAsUnorderedList(story.external_links, "External Links")}
|
|
21767
|
+
|
|
21768
|
+
${formatPullRequestList(story.branches)}
|
|
21769
|
+
|
|
21770
|
+
${formatTaskList(story.tasks)}
|
|
21771
|
+
|
|
21571
21772
|
Comments:
|
|
21572
21773
|
${(story.comments || []).map((comment) => {
|
|
21573
21774
|
const mentionName = comment.author_id ? users.get(comment.author_id)?.profile?.mention_name : null;
|
|
@@ -21579,199 +21780,6 @@ ${comment.text || ""}`;
|
|
|
21579
21780
|
}
|
|
21580
21781
|
}
|
|
21581
21782
|
|
|
21582
|
-
// src/tools/user.ts
|
|
21583
|
-
class UserTools extends BaseTools {
|
|
21584
|
-
static create(client, server) {
|
|
21585
|
-
const tools = new UserTools(client);
|
|
21586
|
-
server.tool("get-current-user", "Get the current user", async () => await tools.getCurrentUser());
|
|
21587
|
-
return tools;
|
|
21588
|
-
}
|
|
21589
|
-
async getCurrentUser() {
|
|
21590
|
-
const user2 = await this.client.getCurrentUser();
|
|
21591
|
-
if (!user2)
|
|
21592
|
-
throw new Error("Failed to retrieve current user.");
|
|
21593
|
-
return this.toResult(`Current user:
|
|
21594
|
-
Id: ${user2.id}
|
|
21595
|
-
Mention name: @${user2.mention_name}
|
|
21596
|
-
Full name: ${user2.name}`);
|
|
21597
|
-
}
|
|
21598
|
-
}
|
|
21599
|
-
|
|
21600
|
-
// src/tools/epics.ts
|
|
21601
|
-
class EpicTools extends BaseTools {
|
|
21602
|
-
static create(client, server) {
|
|
21603
|
-
const tools = new EpicTools(client);
|
|
21604
|
-
server.tool("get-epic", "Get a Shortcut epic by public ID", { epicPublicId: z.number().positive().describe("The public ID of the epic to get") }, async ({ epicPublicId }) => await tools.getEpic(epicPublicId));
|
|
21605
|
-
server.tool("search-epics", "Find Shortcut epics.", {
|
|
21606
|
-
id: z.number().optional().describe("Find only epics with the specified public ID"),
|
|
21607
|
-
name: z.string().optional().describe("Find only epics matching the specified name"),
|
|
21608
|
-
description: z.string().optional().describe("Find only epics matching the specified description"),
|
|
21609
|
-
state: z.enum(["unstarted", "started", "done"]).optional().describe("Find only epics matching the specified state"),
|
|
21610
|
-
objective: z.number().optional().describe("Find only epics matching the specified objective"),
|
|
21611
|
-
owner: user("owner"),
|
|
21612
|
-
requester: user("requester"),
|
|
21613
|
-
team: z.string().optional().describe("Find only epics matching the specified team. Should be a team's mention name."),
|
|
21614
|
-
comment: z.string().optional().describe("Find only epics matching the specified comment"),
|
|
21615
|
-
isUnstarted: is("unstarted"),
|
|
21616
|
-
isStarted: is("started"),
|
|
21617
|
-
isDone: is("completed"),
|
|
21618
|
-
isArchived: is("archived").default(false),
|
|
21619
|
-
isOverdue: is("overdue"),
|
|
21620
|
-
hasOwner: has("an owner"),
|
|
21621
|
-
hasComment: has("a comment"),
|
|
21622
|
-
hasDeadline: has("a deadline"),
|
|
21623
|
-
hasLabel: has("a label"),
|
|
21624
|
-
created: date2,
|
|
21625
|
-
updated: date2,
|
|
21626
|
-
completed: date2,
|
|
21627
|
-
due: date2
|
|
21628
|
-
}, async (params) => await tools.searchEpics(params));
|
|
21629
|
-
return tools;
|
|
21630
|
-
}
|
|
21631
|
-
async searchEpics(params) {
|
|
21632
|
-
const currentUser = await this.client.getCurrentUser();
|
|
21633
|
-
const query = await buildSearchQuery(params, currentUser);
|
|
21634
|
-
const { epics, total } = await this.client.searchEpics(query);
|
|
21635
|
-
if (!epics)
|
|
21636
|
-
throw new Error(`Failed to search for epics matching your query: "${query}"`);
|
|
21637
|
-
if (!epics.length)
|
|
21638
|
-
return this.toResult(`Result: No epics found.`);
|
|
21639
|
-
return this.toResult(`Result (first ${epics.length} shown of ${total} total epics found):
|
|
21640
|
-
${epics.map((epic) => `- ${epic.id}: ${epic.name}`).join(`
|
|
21641
|
-
`)}`);
|
|
21642
|
-
}
|
|
21643
|
-
async getEpic(epicPublicId) {
|
|
21644
|
-
const epic = await this.client.getEpic(epicPublicId);
|
|
21645
|
-
if (!epic)
|
|
21646
|
-
throw new Error(`Failed to retrieve Shortcut epic with public ID: ${epicPublicId}`);
|
|
21647
|
-
return this.toResult(`Epic: ${epicPublicId}
|
|
21648
|
-
URL: ${epic.app_url}
|
|
21649
|
-
Name: ${epic.name}
|
|
21650
|
-
Archived: ${epic.archived ? "Yes" : "No"}
|
|
21651
|
-
Completed: ${epic.completed ? "Yes" : "No"}
|
|
21652
|
-
Started: ${epic.started ? "Yes" : "No"}
|
|
21653
|
-
Due date: ${epic.deadline ? epic.deadline : "[Not set]"}
|
|
21654
|
-
Team: ${epic.group_id ? `${epic.group_id}` : "[None]"}
|
|
21655
|
-
Objective: ${epic.milestone_id ? `${epic.milestone_id}` : "[None]"}
|
|
21656
|
-
|
|
21657
|
-
Description:
|
|
21658
|
-
${epic.description}`);
|
|
21659
|
-
}
|
|
21660
|
-
}
|
|
21661
|
-
|
|
21662
|
-
// src/tools/objectives.ts
|
|
21663
|
-
class ObjectiveTools extends BaseTools {
|
|
21664
|
-
static create(client, server) {
|
|
21665
|
-
const tools = new ObjectiveTools(client);
|
|
21666
|
-
server.tool("get-objective", "Get a Shortcut objective by public ID", {
|
|
21667
|
-
objectivePublicId: z.number().positive().describe("The public ID of the objective to get")
|
|
21668
|
-
}, async ({ objectivePublicId }) => await tools.getObjective(objectivePublicId));
|
|
21669
|
-
server.tool("search-objectives", "Find Shortcut objectives.", {
|
|
21670
|
-
id: z.number().optional().describe("Find objectives matching the specified id"),
|
|
21671
|
-
name: z.string().optional().describe("Find objectives matching the specified name"),
|
|
21672
|
-
description: z.string().optional().describe("Find objectives matching the specified description"),
|
|
21673
|
-
state: z.enum(["unstarted", "started", "done"]).optional().describe("Find objectives matching the specified state"),
|
|
21674
|
-
owner: user("owner"),
|
|
21675
|
-
requester: user("requester"),
|
|
21676
|
-
team: z.string().optional().describe("Find objectives matching the specified team. Should be a team mention name."),
|
|
21677
|
-
isUnstarted: is("unstarted"),
|
|
21678
|
-
isStarted: is("started"),
|
|
21679
|
-
isDone: is("completed"),
|
|
21680
|
-
isArchived: is("archived"),
|
|
21681
|
-
hasOwner: has("an owner"),
|
|
21682
|
-
created: date2,
|
|
21683
|
-
updated: date2,
|
|
21684
|
-
completed: date2
|
|
21685
|
-
}, async (params) => await tools.searchObjectives(params));
|
|
21686
|
-
return tools;
|
|
21687
|
-
}
|
|
21688
|
-
async searchObjectives(params) {
|
|
21689
|
-
const currentUser = await this.client.getCurrentUser();
|
|
21690
|
-
const query = await buildSearchQuery(params, currentUser);
|
|
21691
|
-
const { milestones, total } = await this.client.searchMilestones(query);
|
|
21692
|
-
if (!milestones)
|
|
21693
|
-
throw new Error(`Failed to search for milestones matching your query: "${query}"`);
|
|
21694
|
-
if (!milestones.length)
|
|
21695
|
-
return this.toResult(`Result: No milestones found.`);
|
|
21696
|
-
return this.toResult(`Result (first ${milestones.length} shown of ${total} total milestones found):
|
|
21697
|
-
${milestones.map((milestone) => `- ${milestone.id}: ${milestone.name}`).join(`
|
|
21698
|
-
`)}`);
|
|
21699
|
-
}
|
|
21700
|
-
async getObjective(objectivePublicId) {
|
|
21701
|
-
const objective = await this.client.getMilestone(objectivePublicId);
|
|
21702
|
-
if (!objective)
|
|
21703
|
-
throw new Error(`Failed to retrieve Shortcut objective with public ID: ${objectivePublicId}`);
|
|
21704
|
-
return this.toResult(`Objective: ${objectivePublicId}
|
|
21705
|
-
Url: ${objective.app_url}
|
|
21706
|
-
Name: ${objective.name}
|
|
21707
|
-
Archived: ${objective.archived ? "Yes" : "No"}
|
|
21708
|
-
Completed: ${objective.completed ? "Yes" : "No"}
|
|
21709
|
-
Started: ${objective.started ? "Yes" : "No"}
|
|
21710
|
-
|
|
21711
|
-
Description:
|
|
21712
|
-
${objective.description}`);
|
|
21713
|
-
}
|
|
21714
|
-
}
|
|
21715
|
-
|
|
21716
|
-
// src/tools/iterations.ts
|
|
21717
|
-
class IterationTools extends BaseTools {
|
|
21718
|
-
static create(client, server) {
|
|
21719
|
-
const tools = new IterationTools(client);
|
|
21720
|
-
server.tool("get-iteration-stories", "Get stories in a specific iteration by iteration public ID", { iterationPublicId: z.number().positive().describe("The public ID of the iteration") }, async ({ iterationPublicId }) => await tools.getIterationStories(iterationPublicId));
|
|
21721
|
-
server.tool("get-iteration", "Get a Shortcut iteration by public ID", {
|
|
21722
|
-
iterationPublicId: z.number().positive().describe("The public ID of the iteration to get")
|
|
21723
|
-
}, async ({ iterationPublicId }) => await tools.getIteration(iterationPublicId));
|
|
21724
|
-
server.tool("search-iterations", "Find Shortcut iterations.", {
|
|
21725
|
-
id: z.number().optional().describe("Find only iterations with the specified public ID"),
|
|
21726
|
-
name: z.string().optional().describe("Find only iterations matching the specified name"),
|
|
21727
|
-
description: z.string().optional().describe("Find only iterations matching the specified description"),
|
|
21728
|
-
state: z.enum(["started", "unstarted", "done"]).optional().describe("Find only iterations matching the specified state"),
|
|
21729
|
-
team: z.string().optional().describe("Find only iterations matching the specified team. Should be a team mention name."),
|
|
21730
|
-
created: date2,
|
|
21731
|
-
updated: date2,
|
|
21732
|
-
startDate: date2,
|
|
21733
|
-
endDate: date2
|
|
21734
|
-
}, async (params) => await tools.searchIterations(params));
|
|
21735
|
-
return tools;
|
|
21736
|
-
}
|
|
21737
|
-
async getIterationStories(iterationPublicId) {
|
|
21738
|
-
const { stories } = await this.client.listIterationStories(iterationPublicId);
|
|
21739
|
-
if (!stories)
|
|
21740
|
-
throw new Error(`Failed to retrieve Shortcut stories in iteration with public ID: ${iterationPublicId}.`);
|
|
21741
|
-
const owners = await this.client.getUserMap(stories.flatMap((story) => story.owner_ids));
|
|
21742
|
-
return this.toResult(`Result (${stories.length} stories found):
|
|
21743
|
-
${formatStoryList(stories, owners)}`);
|
|
21744
|
-
}
|
|
21745
|
-
async searchIterations(params) {
|
|
21746
|
-
const currentUser = await this.client.getCurrentUser();
|
|
21747
|
-
const query = await buildSearchQuery(params, currentUser);
|
|
21748
|
-
const { iterations, total } = await this.client.searchIterations(query);
|
|
21749
|
-
if (!iterations)
|
|
21750
|
-
throw new Error(`Failed to search for iterations matching your query: "${query}".`);
|
|
21751
|
-
if (!iterations.length)
|
|
21752
|
-
return this.toResult(`Result: No iterations found.`);
|
|
21753
|
-
return this.toResult(`Result (first ${iterations.length} shown of ${total} total iterations found):
|
|
21754
|
-
${iterations.map((iteration) => `- ${iteration.id}: ${iteration.name} (Start date: ${iteration.start_date}, End date: ${iteration.end_date})`).join(`
|
|
21755
|
-
`)}`);
|
|
21756
|
-
}
|
|
21757
|
-
async getIteration(iterationPublicId) {
|
|
21758
|
-
const iteration = await this.client.getIteration(iterationPublicId);
|
|
21759
|
-
if (!iteration)
|
|
21760
|
-
throw new Error(`Failed to retrieve Shortcut iteration with public ID: ${iterationPublicId}.`);
|
|
21761
|
-
return this.toResult(`Iteration: ${iterationPublicId}
|
|
21762
|
-
Url: ${iteration.app_url}
|
|
21763
|
-
Name: ${iteration.name}
|
|
21764
|
-
Start date: ${iteration.start_date}
|
|
21765
|
-
End date: ${iteration.end_date}
|
|
21766
|
-
Completed: ${iteration.status === "completed" ? "Yes" : "No"}
|
|
21767
|
-
Started: ${iteration.status === "started" ? "Yes" : "No"}
|
|
21768
|
-
Team: ${iteration.group_ids?.length ? `${iteration.group_ids.join(", ")}` : "[None]"}
|
|
21769
|
-
|
|
21770
|
-
Description:
|
|
21771
|
-
${iteration.description}`);
|
|
21772
|
-
}
|
|
21773
|
-
}
|
|
21774
|
-
|
|
21775
21783
|
// src/tools/teams.ts
|
|
21776
21784
|
class TeamTools extends BaseTools {
|
|
21777
21785
|
static create(client, server) {
|
|
@@ -21789,8 +21797,7 @@ class TeamTools extends BaseTools {
|
|
|
21789
21797
|
Name: ${team.name}
|
|
21790
21798
|
Mention name: ${team.mention_name}
|
|
21791
21799
|
Description: ${team.description}
|
|
21792
|
-
|
|
21793
|
-
${formatMemberList(team.member_ids, users)}` : " [None]"}`);
|
|
21800
|
+
${formatMemberList(team.member_ids, users)}`);
|
|
21794
21801
|
}
|
|
21795
21802
|
async getTeams() {
|
|
21796
21803
|
const teams = await this.client.getTeams();
|
|
@@ -21803,13 +21810,30 @@ ${teams.map((team) => `Id: ${team.id}
|
|
|
21803
21810
|
Name: ${team.name}
|
|
21804
21811
|
Description: ${team.description}
|
|
21805
21812
|
Number of Members: ${team.member_ids.length}
|
|
21806
|
-
|
|
21807
|
-
${formatWorkflowList(team.workflow_ids, workflows)}` : "[None]"}`).join(`
|
|
21813
|
+
${formatWorkflowList(team.workflow_ids, workflows)}`).join(`
|
|
21808
21814
|
|
|
21809
21815
|
`)}`);
|
|
21810
21816
|
}
|
|
21811
21817
|
}
|
|
21812
21818
|
|
|
21819
|
+
// src/tools/user.ts
|
|
21820
|
+
class UserTools extends BaseTools {
|
|
21821
|
+
static create(client, server) {
|
|
21822
|
+
const tools = new UserTools(client);
|
|
21823
|
+
server.tool("get-current-user", "Get the current user", async () => await tools.getCurrentUser());
|
|
21824
|
+
return tools;
|
|
21825
|
+
}
|
|
21826
|
+
async getCurrentUser() {
|
|
21827
|
+
const user2 = await this.client.getCurrentUser();
|
|
21828
|
+
if (!user2)
|
|
21829
|
+
throw new Error("Failed to retrieve current user.");
|
|
21830
|
+
return this.toResult(`Current user:
|
|
21831
|
+
Id: ${user2.id}
|
|
21832
|
+
Mention name: @${user2.mention_name}
|
|
21833
|
+
Full name: ${user2.name}`);
|
|
21834
|
+
}
|
|
21835
|
+
}
|
|
21836
|
+
|
|
21813
21837
|
// src/tools/workflows.ts
|
|
21814
21838
|
class WorkflowTools extends BaseTools {
|
|
21815
21839
|
static create(client, server) {
|
|
@@ -21826,8 +21850,7 @@ class WorkflowTools extends BaseTools {
|
|
|
21826
21850
|
Name: ${workflow.name}
|
|
21827
21851
|
Description: ${workflow.description}
|
|
21828
21852
|
States:
|
|
21829
|
-
${workflow.states.map((state) =>
|
|
21830
|
-
`)}`);
|
|
21853
|
+
${formatAsUnorderedList(workflow.states.map((state) => `id=${state.id} name=${state.name} (default: ${state.id === workflow.default_state_id ? "yes" : "no"}, type: ${state.type})`))}`);
|
|
21831
21854
|
}
|
|
21832
21855
|
async listWorkflows() {
|
|
21833
21856
|
const workflows = await this.client.getWorkflows();
|