@shortcut/mcp 0.4.0 → 0.5.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.js +548 -87
- package/package.json +11 -5
package/dist/index.js
CHANGED
|
@@ -14651,6 +14651,11 @@ class ShortcutClientWrapper {
|
|
|
14651
14651
|
await this.loadMembers();
|
|
14652
14652
|
return userIds.map((id) => this.userCache.get(id)).filter((user) => user !== null);
|
|
14653
14653
|
}
|
|
14654
|
+
async listMembers() {
|
|
14655
|
+
await this.loadMembers();
|
|
14656
|
+
const members = Array.from(this.userCache.values());
|
|
14657
|
+
return members;
|
|
14658
|
+
}
|
|
14654
14659
|
async getWorkflowMap(workflowIds) {
|
|
14655
14660
|
await this.loadWorkflows();
|
|
14656
14661
|
return new Map(workflowIds.map((id) => [id, this.workflowCache.get(id)]).filter((workflow) => workflow[1] !== null));
|
|
@@ -14782,6 +14787,49 @@ class ShortcutClientWrapper {
|
|
|
14782
14787
|
throw new Error(`Failed to create the epic: ${response.status}`);
|
|
14783
14788
|
return epic;
|
|
14784
14789
|
}
|
|
14790
|
+
async addTaskToStory(storyPublicId, taskParams) {
|
|
14791
|
+
const { description, ownerIds } = taskParams;
|
|
14792
|
+
const params = {
|
|
14793
|
+
description,
|
|
14794
|
+
owner_ids: ownerIds
|
|
14795
|
+
};
|
|
14796
|
+
const response = await this.client.createTask(storyPublicId, params);
|
|
14797
|
+
const task = response?.data ?? null;
|
|
14798
|
+
if (!task)
|
|
14799
|
+
throw new Error(`Failed to create the task: ${response.status}`);
|
|
14800
|
+
return task;
|
|
14801
|
+
}
|
|
14802
|
+
async addRelationToStory(storyPublicId, linkedStoryId) {
|
|
14803
|
+
const response = await this.client.createStoryLink({
|
|
14804
|
+
object_id: linkedStoryId,
|
|
14805
|
+
subject_id: storyPublicId,
|
|
14806
|
+
verb: "relates to"
|
|
14807
|
+
});
|
|
14808
|
+
const storyLink = response?.data ?? null;
|
|
14809
|
+
if (!storyLink)
|
|
14810
|
+
throw new Error(`Failed to create the story links: ${response.status}`);
|
|
14811
|
+
return storyLink;
|
|
14812
|
+
}
|
|
14813
|
+
async getTask(storyPublicId, taskPublicId) {
|
|
14814
|
+
const response = await this.client.getTask(storyPublicId, taskPublicId);
|
|
14815
|
+
const task = response?.data ?? null;
|
|
14816
|
+
if (!task)
|
|
14817
|
+
throw new Error(`Failed to get the task: ${response.status}`);
|
|
14818
|
+
return task;
|
|
14819
|
+
}
|
|
14820
|
+
async updateTask(storyPublicId, taskPublicId, taskParams) {
|
|
14821
|
+
const { description, ownerIds } = taskParams;
|
|
14822
|
+
const params = {
|
|
14823
|
+
description,
|
|
14824
|
+
owner_ids: ownerIds,
|
|
14825
|
+
complete: taskParams.isCompleted
|
|
14826
|
+
};
|
|
14827
|
+
const response = await this.client.updateTask(storyPublicId, taskPublicId, params);
|
|
14828
|
+
const task = response?.data ?? null;
|
|
14829
|
+
if (!task)
|
|
14830
|
+
throw new Error(`Failed to update the task: ${response.status}`);
|
|
14831
|
+
return task;
|
|
14832
|
+
}
|
|
14785
14833
|
}
|
|
14786
14834
|
|
|
14787
14835
|
// node_modules/zod/lib/index.mjs
|
|
@@ -15631,13 +15679,14 @@ var base64urlRegex = /^([0-9a-zA-Z-_]{4})*(([0-9a-zA-Z-_]{2}(==)?)|([0-9a-zA-Z-_
|
|
|
15631
15679
|
var dateRegexSource = `((\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-((0[13578]|1[02])-(0[1-9]|[12]\\d|3[01])|(0[469]|11)-(0[1-9]|[12]\\d|30)|(02)-(0[1-9]|1\\d|2[0-8])))`;
|
|
15632
15680
|
var dateRegex = new RegExp(`^${dateRegexSource}$`);
|
|
15633
15681
|
function timeRegexSource(args) {
|
|
15634
|
-
let
|
|
15682
|
+
let secondsRegexSource = `[0-5]\\d`;
|
|
15635
15683
|
if (args.precision) {
|
|
15636
|
-
|
|
15684
|
+
secondsRegexSource = `${secondsRegexSource}\\.\\d{${args.precision}}`;
|
|
15637
15685
|
} else if (args.precision == null) {
|
|
15638
|
-
|
|
15686
|
+
secondsRegexSource = `${secondsRegexSource}(\\.\\d+)?`;
|
|
15639
15687
|
}
|
|
15640
|
-
|
|
15688
|
+
const secondsQuantifier = args.precision ? "+" : "?";
|
|
15689
|
+
return `([01]\\d|2[0-3]):[0-5]\\d(:${secondsRegexSource})${secondsQuantifier}`;
|
|
15641
15690
|
}
|
|
15642
15691
|
function timeRegex(args) {
|
|
15643
15692
|
return new RegExp(`^${timeRegexSource(args)}$`);
|
|
@@ -18790,18 +18839,20 @@ var z = /* @__PURE__ */ Object.freeze({
|
|
|
18790
18839
|
});
|
|
18791
18840
|
|
|
18792
18841
|
// node_modules/@modelcontextprotocol/sdk/dist/esm/types.js
|
|
18793
|
-
var LATEST_PROTOCOL_VERSION = "
|
|
18842
|
+
var LATEST_PROTOCOL_VERSION = "2025-03-26";
|
|
18794
18843
|
var SUPPORTED_PROTOCOL_VERSIONS = [
|
|
18795
18844
|
LATEST_PROTOCOL_VERSION,
|
|
18845
|
+
"2024-11-05",
|
|
18796
18846
|
"2024-10-07"
|
|
18797
18847
|
];
|
|
18798
18848
|
var JSONRPC_VERSION = "2.0";
|
|
18799
18849
|
var ProgressTokenSchema = z.union([z.string(), z.number().int()]);
|
|
18800
18850
|
var CursorSchema = z.string();
|
|
18851
|
+
var RequestMetaSchema = z.object({
|
|
18852
|
+
progressToken: z.optional(ProgressTokenSchema)
|
|
18853
|
+
}).passthrough();
|
|
18801
18854
|
var BaseRequestParamsSchema = z.object({
|
|
18802
|
-
_meta: z.optional(
|
|
18803
|
-
progressToken: z.optional(ProgressTokenSchema)
|
|
18804
|
-
}).passthrough())
|
|
18855
|
+
_meta: z.optional(RequestMetaSchema)
|
|
18805
18856
|
}).passthrough();
|
|
18806
18857
|
var RequestSchema = z.object({
|
|
18807
18858
|
method: z.string(),
|
|
@@ -18822,14 +18873,17 @@ var JSONRPCRequestSchema = z.object({
|
|
|
18822
18873
|
jsonrpc: z.literal(JSONRPC_VERSION),
|
|
18823
18874
|
id: RequestIdSchema
|
|
18824
18875
|
}).merge(RequestSchema).strict();
|
|
18876
|
+
var isJSONRPCRequest = (value) => JSONRPCRequestSchema.safeParse(value).success;
|
|
18825
18877
|
var JSONRPCNotificationSchema = z.object({
|
|
18826
18878
|
jsonrpc: z.literal(JSONRPC_VERSION)
|
|
18827
18879
|
}).merge(NotificationSchema).strict();
|
|
18880
|
+
var isJSONRPCNotification = (value) => JSONRPCNotificationSchema.safeParse(value).success;
|
|
18828
18881
|
var JSONRPCResponseSchema = z.object({
|
|
18829
18882
|
jsonrpc: z.literal(JSONRPC_VERSION),
|
|
18830
18883
|
id: RequestIdSchema,
|
|
18831
18884
|
result: ResultSchema
|
|
18832
18885
|
}).strict();
|
|
18886
|
+
var isJSONRPCResponse = (value) => JSONRPCResponseSchema.safeParse(value).success;
|
|
18833
18887
|
var ErrorCode;
|
|
18834
18888
|
(function(ErrorCode2) {
|
|
18835
18889
|
ErrorCode2[ErrorCode2["ConnectionClosed"] = -32000] = "ConnectionClosed";
|
|
@@ -18849,6 +18903,7 @@ var JSONRPCErrorSchema = z.object({
|
|
|
18849
18903
|
data: z.optional(z.unknown())
|
|
18850
18904
|
})
|
|
18851
18905
|
}).strict();
|
|
18906
|
+
var isJSONRPCError = (value) => JSONRPCErrorSchema.safeParse(value).success;
|
|
18852
18907
|
var JSONRPCMessageSchema = z.union([
|
|
18853
18908
|
JSONRPCRequestSchema,
|
|
18854
18909
|
JSONRPCNotificationSchema,
|
|
@@ -18885,6 +18940,7 @@ var InitializeRequestSchema = RequestSchema.extend({
|
|
|
18885
18940
|
var ServerCapabilitiesSchema = z.object({
|
|
18886
18941
|
experimental: z.optional(z.object({}).passthrough()),
|
|
18887
18942
|
logging: z.optional(z.object({}).passthrough()),
|
|
18943
|
+
completions: z.optional(z.object({}).passthrough()),
|
|
18888
18944
|
prompts: z.optional(z.object({
|
|
18889
18945
|
listChanged: z.optional(z.boolean())
|
|
18890
18946
|
}).passthrough()),
|
|
@@ -19022,6 +19078,11 @@ var ImageContentSchema = z.object({
|
|
|
19022
19078
|
data: z.string().base64(),
|
|
19023
19079
|
mimeType: z.string()
|
|
19024
19080
|
}).passthrough();
|
|
19081
|
+
var AudioContentSchema = z.object({
|
|
19082
|
+
type: z.literal("audio"),
|
|
19083
|
+
data: z.string().base64(),
|
|
19084
|
+
mimeType: z.string()
|
|
19085
|
+
}).passthrough();
|
|
19025
19086
|
var EmbeddedResourceSchema = z.object({
|
|
19026
19087
|
type: z.literal("resource"),
|
|
19027
19088
|
resource: z.union([TextResourceContentsSchema, BlobResourceContentsSchema])
|
|
@@ -19031,6 +19092,7 @@ var PromptMessageSchema = z.object({
|
|
|
19031
19092
|
content: z.union([
|
|
19032
19093
|
TextContentSchema,
|
|
19033
19094
|
ImageContentSchema,
|
|
19095
|
+
AudioContentSchema,
|
|
19034
19096
|
EmbeddedResourceSchema
|
|
19035
19097
|
])
|
|
19036
19098
|
}).passthrough();
|
|
@@ -19041,13 +19103,21 @@ var GetPromptResultSchema = ResultSchema.extend({
|
|
|
19041
19103
|
var PromptListChangedNotificationSchema = NotificationSchema.extend({
|
|
19042
19104
|
method: z.literal("notifications/prompts/list_changed")
|
|
19043
19105
|
});
|
|
19106
|
+
var ToolAnnotationsSchema = z.object({
|
|
19107
|
+
title: z.optional(z.string()),
|
|
19108
|
+
readOnlyHint: z.optional(z.boolean()),
|
|
19109
|
+
destructiveHint: z.optional(z.boolean()),
|
|
19110
|
+
idempotentHint: z.optional(z.boolean()),
|
|
19111
|
+
openWorldHint: z.optional(z.boolean())
|
|
19112
|
+
}).passthrough();
|
|
19044
19113
|
var ToolSchema = z.object({
|
|
19045
19114
|
name: z.string(),
|
|
19046
19115
|
description: z.optional(z.string()),
|
|
19047
19116
|
inputSchema: z.object({
|
|
19048
19117
|
type: z.literal("object"),
|
|
19049
19118
|
properties: z.optional(z.object({}).passthrough())
|
|
19050
|
-
}).passthrough()
|
|
19119
|
+
}).passthrough(),
|
|
19120
|
+
annotations: z.optional(ToolAnnotationsSchema)
|
|
19051
19121
|
}).passthrough();
|
|
19052
19122
|
var ListToolsRequestSchema = PaginatedRequestSchema.extend({
|
|
19053
19123
|
method: z.literal("tools/list")
|
|
@@ -19056,7 +19126,7 @@ var ListToolsResultSchema = PaginatedResultSchema.extend({
|
|
|
19056
19126
|
tools: z.array(ToolSchema)
|
|
19057
19127
|
});
|
|
19058
19128
|
var CallToolResultSchema = ResultSchema.extend({
|
|
19059
|
-
content: z.array(z.union([TextContentSchema, ImageContentSchema, EmbeddedResourceSchema])),
|
|
19129
|
+
content: z.array(z.union([TextContentSchema, ImageContentSchema, AudioContentSchema, EmbeddedResourceSchema])),
|
|
19060
19130
|
isError: z.boolean().default(false).optional()
|
|
19061
19131
|
});
|
|
19062
19132
|
var CompatibilityCallToolResultSchema = CallToolResultSchema.or(ResultSchema.extend({
|
|
@@ -19107,7 +19177,7 @@ var ModelPreferencesSchema = z.object({
|
|
|
19107
19177
|
}).passthrough();
|
|
19108
19178
|
var SamplingMessageSchema = z.object({
|
|
19109
19179
|
role: z.enum(["user", "assistant"]),
|
|
19110
|
-
content: z.union([TextContentSchema, ImageContentSchema])
|
|
19180
|
+
content: z.union([TextContentSchema, ImageContentSchema, AudioContentSchema])
|
|
19111
19181
|
}).passthrough();
|
|
19112
19182
|
var CreateMessageRequestSchema = RequestSchema.extend({
|
|
19113
19183
|
method: z.literal("sampling/createMessage"),
|
|
@@ -19128,7 +19198,8 @@ var CreateMessageResultSchema = ResultSchema.extend({
|
|
|
19128
19198
|
role: z.enum(["user", "assistant"]),
|
|
19129
19199
|
content: z.discriminatedUnion("type", [
|
|
19130
19200
|
TextContentSchema,
|
|
19131
|
-
ImageContentSchema
|
|
19201
|
+
ImageContentSchema,
|
|
19202
|
+
AudioContentSchema
|
|
19132
19203
|
])
|
|
19133
19204
|
});
|
|
19134
19205
|
var ResourceReferenceSchema = z.object({
|
|
@@ -19253,12 +19324,13 @@ class Protocol {
|
|
|
19253
19324
|
});
|
|
19254
19325
|
this.setRequestHandler(PingRequestSchema, (_request) => ({}));
|
|
19255
19326
|
}
|
|
19256
|
-
_setupTimeout(messageId, timeout, maxTotalTimeout, onTimeout) {
|
|
19327
|
+
_setupTimeout(messageId, timeout, maxTotalTimeout, onTimeout, resetTimeoutOnProgress = false) {
|
|
19257
19328
|
this._timeoutInfo.set(messageId, {
|
|
19258
19329
|
timeoutId: setTimeout(onTimeout, timeout),
|
|
19259
19330
|
startTime: Date.now(),
|
|
19260
19331
|
timeout,
|
|
19261
19332
|
maxTotalTimeout,
|
|
19333
|
+
resetTimeoutOnProgress,
|
|
19262
19334
|
onTimeout
|
|
19263
19335
|
});
|
|
19264
19336
|
}
|
|
@@ -19290,13 +19362,15 @@ class Protocol {
|
|
|
19290
19362
|
this._transport.onerror = (error) => {
|
|
19291
19363
|
this._onerror(error);
|
|
19292
19364
|
};
|
|
19293
|
-
this._transport.onmessage = (message) => {
|
|
19294
|
-
if (
|
|
19365
|
+
this._transport.onmessage = (message, extra) => {
|
|
19366
|
+
if (isJSONRPCResponse(message) || isJSONRPCError(message)) {
|
|
19295
19367
|
this._onresponse(message);
|
|
19296
|
-
} else if (
|
|
19297
|
-
this._onrequest(message);
|
|
19298
|
-
} else {
|
|
19368
|
+
} else if (isJSONRPCRequest(message)) {
|
|
19369
|
+
this._onrequest(message, extra);
|
|
19370
|
+
} else if (isJSONRPCNotification(message)) {
|
|
19299
19371
|
this._onnotification(message);
|
|
19372
|
+
} else {
|
|
19373
|
+
this._onerror(new Error(`Unknown message type: ${JSON.stringify(message)}`));
|
|
19300
19374
|
}
|
|
19301
19375
|
};
|
|
19302
19376
|
await this._transport.start();
|
|
@@ -19325,8 +19399,8 @@ class Protocol {
|
|
|
19325
19399
|
}
|
|
19326
19400
|
Promise.resolve().then(() => handler(notification)).catch((error) => this._onerror(new Error(`Uncaught error in notification handler: ${error}`)));
|
|
19327
19401
|
}
|
|
19328
|
-
_onrequest(request) {
|
|
19329
|
-
var _a, _b;
|
|
19402
|
+
_onrequest(request, extra) {
|
|
19403
|
+
var _a, _b, _c, _d;
|
|
19330
19404
|
const handler = (_a = this._requestHandlers.get(request.method)) !== null && _a !== undefined ? _a : this.fallbackRequestHandler;
|
|
19331
19405
|
if (handler === undefined) {
|
|
19332
19406
|
(_b = this._transport) === null || _b === undefined || _b.send({
|
|
@@ -19341,7 +19415,16 @@ class Protocol {
|
|
|
19341
19415
|
}
|
|
19342
19416
|
const abortController = new AbortController;
|
|
19343
19417
|
this._requestHandlerAbortControllers.set(request.id, abortController);
|
|
19344
|
-
|
|
19418
|
+
const fullExtra = {
|
|
19419
|
+
signal: abortController.signal,
|
|
19420
|
+
sessionId: (_c = this._transport) === null || _c === undefined ? undefined : _c.sessionId,
|
|
19421
|
+
_meta: (_d = request.params) === null || _d === undefined ? undefined : _d._meta,
|
|
19422
|
+
sendNotification: (notification) => this.notification(notification, { relatedRequestId: request.id }),
|
|
19423
|
+
sendRequest: (r, resultSchema, options) => this.request(r, resultSchema, { ...options, relatedRequestId: request.id }),
|
|
19424
|
+
authInfo: extra === null || extra === undefined ? undefined : extra.authInfo,
|
|
19425
|
+
requestId: request.id
|
|
19426
|
+
};
|
|
19427
|
+
Promise.resolve().then(() => handler(request, fullExtra)).then((result) => {
|
|
19345
19428
|
var _a2;
|
|
19346
19429
|
if (abortController.signal.aborted) {
|
|
19347
19430
|
return;
|
|
@@ -19377,7 +19460,8 @@ class Protocol {
|
|
|
19377
19460
|
return;
|
|
19378
19461
|
}
|
|
19379
19462
|
const responseHandler = this._responseHandlers.get(messageId);
|
|
19380
|
-
|
|
19463
|
+
const timeoutInfo = this._timeoutInfo.get(messageId);
|
|
19464
|
+
if (timeoutInfo && responseHandler && timeoutInfo.resetTimeoutOnProgress) {
|
|
19381
19465
|
try {
|
|
19382
19466
|
this._resetTimeout(messageId);
|
|
19383
19467
|
} catch (error) {
|
|
@@ -19397,7 +19481,7 @@ class Protocol {
|
|
|
19397
19481
|
this._responseHandlers.delete(messageId);
|
|
19398
19482
|
this._progressHandlers.delete(messageId);
|
|
19399
19483
|
this._cleanupTimeout(messageId);
|
|
19400
|
-
if (
|
|
19484
|
+
if (isJSONRPCResponse(response)) {
|
|
19401
19485
|
handler(response);
|
|
19402
19486
|
} else {
|
|
19403
19487
|
const error = new McpError(response.error.code, response.error.message, response.error.data);
|
|
@@ -19412,8 +19496,9 @@ class Protocol {
|
|
|
19412
19496
|
await ((_a = this._transport) === null || _a === undefined ? undefined : _a.close());
|
|
19413
19497
|
}
|
|
19414
19498
|
request(request, resultSchema, options) {
|
|
19499
|
+
const { relatedRequestId, resumptionToken, onresumptiontoken } = options !== null && options !== undefined ? options : {};
|
|
19415
19500
|
return new Promise((resolve, reject) => {
|
|
19416
|
-
var _a, _b, _c, _d;
|
|
19501
|
+
var _a, _b, _c, _d, _e;
|
|
19417
19502
|
if (!this._transport) {
|
|
19418
19503
|
reject(new Error("Not connected"));
|
|
19419
19504
|
return;
|
|
@@ -19447,7 +19532,7 @@ class Protocol {
|
|
|
19447
19532
|
requestId: messageId,
|
|
19448
19533
|
reason: String(reason)
|
|
19449
19534
|
}
|
|
19450
|
-
}).catch((error) => this._onerror(new Error(`Failed to send cancellation: ${error}`)));
|
|
19535
|
+
}, { relatedRequestId, resumptionToken, onresumptiontoken }).catch((error) => this._onerror(new Error(`Failed to send cancellation: ${error}`)));
|
|
19451
19536
|
reject(reason);
|
|
19452
19537
|
};
|
|
19453
19538
|
this._responseHandlers.set(messageId, (response) => {
|
|
@@ -19471,14 +19556,14 @@ class Protocol {
|
|
|
19471
19556
|
});
|
|
19472
19557
|
const timeout = (_d = options === null || options === undefined ? undefined : options.timeout) !== null && _d !== undefined ? _d : DEFAULT_REQUEST_TIMEOUT_MSEC;
|
|
19473
19558
|
const timeoutHandler = () => cancel(new McpError(ErrorCode.RequestTimeout, "Request timed out", { timeout }));
|
|
19474
|
-
this._setupTimeout(messageId, timeout, options === null || options === undefined ? undefined : options.maxTotalTimeout, timeoutHandler);
|
|
19475
|
-
this._transport.send(jsonrpcRequest).catch((error) => {
|
|
19559
|
+
this._setupTimeout(messageId, timeout, options === null || options === undefined ? undefined : options.maxTotalTimeout, timeoutHandler, (_e = options === null || options === undefined ? undefined : options.resetTimeoutOnProgress) !== null && _e !== undefined ? _e : false);
|
|
19560
|
+
this._transport.send(jsonrpcRequest, { relatedRequestId, resumptionToken, onresumptiontoken }).catch((error) => {
|
|
19476
19561
|
this._cleanupTimeout(messageId);
|
|
19477
19562
|
reject(error);
|
|
19478
19563
|
});
|
|
19479
19564
|
});
|
|
19480
19565
|
}
|
|
19481
|
-
async notification(notification) {
|
|
19566
|
+
async notification(notification, options) {
|
|
19482
19567
|
if (!this._transport) {
|
|
19483
19568
|
throw new Error("Not connected");
|
|
19484
19569
|
}
|
|
@@ -19487,12 +19572,14 @@ class Protocol {
|
|
|
19487
19572
|
...notification,
|
|
19488
19573
|
jsonrpc: "2.0"
|
|
19489
19574
|
};
|
|
19490
|
-
await this._transport.send(jsonrpcNotification);
|
|
19575
|
+
await this._transport.send(jsonrpcNotification, options);
|
|
19491
19576
|
}
|
|
19492
19577
|
setRequestHandler(requestSchema, handler) {
|
|
19493
19578
|
const method = requestSchema.shape.method.value;
|
|
19494
19579
|
this.assertRequestHandlerCapability(method);
|
|
19495
|
-
this._requestHandlers.set(method, (request, extra) =>
|
|
19580
|
+
this._requestHandlers.set(method, (request, extra) => {
|
|
19581
|
+
return Promise.resolve(handler(requestSchema.parse(request), extra));
|
|
19582
|
+
});
|
|
19496
19583
|
}
|
|
19497
19584
|
removeRequestHandler(method) {
|
|
19498
19585
|
this._requestHandlers.delete(method);
|
|
@@ -20932,16 +21019,19 @@ class McpServer {
|
|
|
20932
21019
|
this.server.assertCanSetRequestHandler(ListToolsRequestSchema.shape.method.value);
|
|
20933
21020
|
this.server.assertCanSetRequestHandler(CallToolRequestSchema.shape.method.value);
|
|
20934
21021
|
this.server.registerCapabilities({
|
|
20935
|
-
tools: {
|
|
21022
|
+
tools: {
|
|
21023
|
+
listChanged: true
|
|
21024
|
+
}
|
|
20936
21025
|
});
|
|
20937
21026
|
this.server.setRequestHandler(ListToolsRequestSchema, () => ({
|
|
20938
|
-
tools: Object.entries(this._registeredTools).map(([name, tool]) => {
|
|
21027
|
+
tools: Object.entries(this._registeredTools).filter(([, tool]) => tool.enabled).map(([name, tool]) => {
|
|
20939
21028
|
return {
|
|
20940
21029
|
name,
|
|
20941
21030
|
description: tool.description,
|
|
20942
21031
|
inputSchema: tool.inputSchema ? zodToJsonSchema(tool.inputSchema, {
|
|
20943
21032
|
strictUnions: true
|
|
20944
|
-
}) : EMPTY_OBJECT_JSON_SCHEMA
|
|
21033
|
+
}) : EMPTY_OBJECT_JSON_SCHEMA,
|
|
21034
|
+
annotations: tool.annotations
|
|
20945
21035
|
};
|
|
20946
21036
|
})
|
|
20947
21037
|
}));
|
|
@@ -20950,6 +21040,9 @@ class McpServer {
|
|
|
20950
21040
|
if (!tool) {
|
|
20951
21041
|
throw new McpError(ErrorCode.InvalidParams, `Tool ${request.params.name} not found`);
|
|
20952
21042
|
}
|
|
21043
|
+
if (!tool.enabled) {
|
|
21044
|
+
throw new McpError(ErrorCode.InvalidParams, `Tool ${request.params.name} disabled`);
|
|
21045
|
+
}
|
|
20953
21046
|
if (tool.inputSchema) {
|
|
20954
21047
|
const parseResult = await tool.inputSchema.safeParseAsync(request.params.arguments);
|
|
20955
21048
|
if (!parseResult.success) {
|
|
@@ -21009,7 +21102,10 @@ class McpServer {
|
|
|
21009
21102
|
async handlePromptCompletion(request, ref) {
|
|
21010
21103
|
const prompt = this._registeredPrompts[ref.name];
|
|
21011
21104
|
if (!prompt) {
|
|
21012
|
-
throw new McpError(ErrorCode.InvalidParams, `Prompt ${
|
|
21105
|
+
throw new McpError(ErrorCode.InvalidParams, `Prompt ${ref.name} not found`);
|
|
21106
|
+
}
|
|
21107
|
+
if (!prompt.enabled) {
|
|
21108
|
+
throw new McpError(ErrorCode.InvalidParams, `Prompt ${ref.name} disabled`);
|
|
21013
21109
|
}
|
|
21014
21110
|
if (!prompt.argsSchema) {
|
|
21015
21111
|
return EMPTY_COMPLETION_RESULT;
|
|
@@ -21045,10 +21141,12 @@ class McpServer {
|
|
|
21045
21141
|
this.server.assertCanSetRequestHandler(ListResourceTemplatesRequestSchema.shape.method.value);
|
|
21046
21142
|
this.server.assertCanSetRequestHandler(ReadResourceRequestSchema.shape.method.value);
|
|
21047
21143
|
this.server.registerCapabilities({
|
|
21048
|
-
resources: {
|
|
21144
|
+
resources: {
|
|
21145
|
+
listChanged: true
|
|
21146
|
+
}
|
|
21049
21147
|
});
|
|
21050
21148
|
this.server.setRequestHandler(ListResourcesRequestSchema, async (request, extra) => {
|
|
21051
|
-
const resources = Object.entries(this._registeredResources).map(([uri, resource]) => ({
|
|
21149
|
+
const resources = Object.entries(this._registeredResources).filter(([_, resource]) => resource.enabled).map(([uri, resource]) => ({
|
|
21052
21150
|
uri,
|
|
21053
21151
|
name: resource.name,
|
|
21054
21152
|
...resource.metadata
|
|
@@ -21080,6 +21178,9 @@ class McpServer {
|
|
|
21080
21178
|
const uri = new URL(request.params.uri);
|
|
21081
21179
|
const resource = this._registeredResources[uri.toString()];
|
|
21082
21180
|
if (resource) {
|
|
21181
|
+
if (!resource.enabled) {
|
|
21182
|
+
throw new McpError(ErrorCode.InvalidParams, `Resource ${uri} disabled`);
|
|
21183
|
+
}
|
|
21083
21184
|
return resource.readCallback(uri, extra);
|
|
21084
21185
|
}
|
|
21085
21186
|
for (const template of Object.values(this._registeredResourceTemplates)) {
|
|
@@ -21100,10 +21201,12 @@ class McpServer {
|
|
|
21100
21201
|
this.server.assertCanSetRequestHandler(ListPromptsRequestSchema.shape.method.value);
|
|
21101
21202
|
this.server.assertCanSetRequestHandler(GetPromptRequestSchema.shape.method.value);
|
|
21102
21203
|
this.server.registerCapabilities({
|
|
21103
|
-
prompts: {
|
|
21204
|
+
prompts: {
|
|
21205
|
+
listChanged: true
|
|
21206
|
+
}
|
|
21104
21207
|
});
|
|
21105
21208
|
this.server.setRequestHandler(ListPromptsRequestSchema, () => ({
|
|
21106
|
-
prompts: Object.entries(this._registeredPrompts).map(([name, prompt]) => {
|
|
21209
|
+
prompts: Object.entries(this._registeredPrompts).filter(([, prompt]) => prompt.enabled).map(([name, prompt]) => {
|
|
21107
21210
|
return {
|
|
21108
21211
|
name,
|
|
21109
21212
|
description: prompt.description,
|
|
@@ -21116,6 +21219,9 @@ class McpServer {
|
|
|
21116
21219
|
if (!prompt) {
|
|
21117
21220
|
throw new McpError(ErrorCode.InvalidParams, `Prompt ${request.params.name} not found`);
|
|
21118
21221
|
}
|
|
21222
|
+
if (!prompt.enabled) {
|
|
21223
|
+
throw new McpError(ErrorCode.InvalidParams, `Prompt ${request.params.name} disabled`);
|
|
21224
|
+
}
|
|
21119
21225
|
if (prompt.argsSchema) {
|
|
21120
21226
|
const parseResult = await prompt.argsSchema.safeParseAsync(request.params.arguments);
|
|
21121
21227
|
if (!parseResult.success) {
|
|
@@ -21142,22 +21248,69 @@ class McpServer {
|
|
|
21142
21248
|
if (this._registeredResources[uriOrTemplate]) {
|
|
21143
21249
|
throw new Error(`Resource ${uriOrTemplate} is already registered`);
|
|
21144
21250
|
}
|
|
21145
|
-
|
|
21251
|
+
const registeredResource = {
|
|
21146
21252
|
name,
|
|
21147
21253
|
metadata,
|
|
21148
|
-
readCallback
|
|
21254
|
+
readCallback,
|
|
21255
|
+
enabled: true,
|
|
21256
|
+
disable: () => registeredResource.update({ enabled: false }),
|
|
21257
|
+
enable: () => registeredResource.update({ enabled: true }),
|
|
21258
|
+
remove: () => registeredResource.update({ uri: null }),
|
|
21259
|
+
update: (updates) => {
|
|
21260
|
+
if (typeof updates.uri !== "undefined" && updates.uri !== uriOrTemplate) {
|
|
21261
|
+
delete this._registeredResources[uriOrTemplate];
|
|
21262
|
+
if (updates.uri)
|
|
21263
|
+
this._registeredResources[updates.uri] = registeredResource;
|
|
21264
|
+
}
|
|
21265
|
+
if (typeof updates.name !== "undefined")
|
|
21266
|
+
registeredResource.name = updates.name;
|
|
21267
|
+
if (typeof updates.metadata !== "undefined")
|
|
21268
|
+
registeredResource.metadata = updates.metadata;
|
|
21269
|
+
if (typeof updates.callback !== "undefined")
|
|
21270
|
+
registeredResource.readCallback = updates.callback;
|
|
21271
|
+
if (typeof updates.enabled !== "undefined")
|
|
21272
|
+
registeredResource.enabled = updates.enabled;
|
|
21273
|
+
this.sendResourceListChanged();
|
|
21274
|
+
}
|
|
21149
21275
|
};
|
|
21276
|
+
this._registeredResources[uriOrTemplate] = registeredResource;
|
|
21277
|
+
this.setResourceRequestHandlers();
|
|
21278
|
+
this.sendResourceListChanged();
|
|
21279
|
+
return registeredResource;
|
|
21150
21280
|
} else {
|
|
21151
21281
|
if (this._registeredResourceTemplates[name]) {
|
|
21152
21282
|
throw new Error(`Resource template ${name} is already registered`);
|
|
21153
21283
|
}
|
|
21154
|
-
|
|
21284
|
+
const registeredResourceTemplate = {
|
|
21155
21285
|
resourceTemplate: uriOrTemplate,
|
|
21156
21286
|
metadata,
|
|
21157
|
-
readCallback
|
|
21287
|
+
readCallback,
|
|
21288
|
+
enabled: true,
|
|
21289
|
+
disable: () => registeredResourceTemplate.update({ enabled: false }),
|
|
21290
|
+
enable: () => registeredResourceTemplate.update({ enabled: true }),
|
|
21291
|
+
remove: () => registeredResourceTemplate.update({ name: null }),
|
|
21292
|
+
update: (updates) => {
|
|
21293
|
+
if (typeof updates.name !== "undefined" && updates.name !== name) {
|
|
21294
|
+
delete this._registeredResourceTemplates[name];
|
|
21295
|
+
if (updates.name)
|
|
21296
|
+
this._registeredResourceTemplates[updates.name] = registeredResourceTemplate;
|
|
21297
|
+
}
|
|
21298
|
+
if (typeof updates.template !== "undefined")
|
|
21299
|
+
registeredResourceTemplate.resourceTemplate = updates.template;
|
|
21300
|
+
if (typeof updates.metadata !== "undefined")
|
|
21301
|
+
registeredResourceTemplate.metadata = updates.metadata;
|
|
21302
|
+
if (typeof updates.callback !== "undefined")
|
|
21303
|
+
registeredResourceTemplate.readCallback = updates.callback;
|
|
21304
|
+
if (typeof updates.enabled !== "undefined")
|
|
21305
|
+
registeredResourceTemplate.enabled = updates.enabled;
|
|
21306
|
+
this.sendResourceListChanged();
|
|
21307
|
+
}
|
|
21158
21308
|
};
|
|
21309
|
+
this._registeredResourceTemplates[name] = registeredResourceTemplate;
|
|
21310
|
+
this.setResourceRequestHandlers();
|
|
21311
|
+
this.sendResourceListChanged();
|
|
21312
|
+
return registeredResourceTemplate;
|
|
21159
21313
|
}
|
|
21160
|
-
this.setResourceRequestHandlers();
|
|
21161
21314
|
}
|
|
21162
21315
|
tool(name, ...rest) {
|
|
21163
21316
|
if (this._registeredTools[name]) {
|
|
@@ -21168,16 +21321,51 @@ class McpServer {
|
|
|
21168
21321
|
description = rest.shift();
|
|
21169
21322
|
}
|
|
21170
21323
|
let paramsSchema;
|
|
21324
|
+
let annotations;
|
|
21171
21325
|
if (rest.length > 1) {
|
|
21172
|
-
|
|
21326
|
+
const firstArg = rest[0];
|
|
21327
|
+
if (isZodRawShape(firstArg)) {
|
|
21328
|
+
paramsSchema = rest.shift();
|
|
21329
|
+
if (rest.length > 1 && typeof rest[0] === "object" && rest[0] !== null && !isZodRawShape(rest[0])) {
|
|
21330
|
+
annotations = rest.shift();
|
|
21331
|
+
}
|
|
21332
|
+
} else if (typeof firstArg === "object" && firstArg !== null) {
|
|
21333
|
+
annotations = rest.shift();
|
|
21334
|
+
}
|
|
21173
21335
|
}
|
|
21174
21336
|
const cb = rest[0];
|
|
21175
|
-
|
|
21337
|
+
const registeredTool = {
|
|
21176
21338
|
description,
|
|
21177
21339
|
inputSchema: paramsSchema === undefined ? undefined : z.object(paramsSchema),
|
|
21178
|
-
|
|
21340
|
+
annotations,
|
|
21341
|
+
callback: cb,
|
|
21342
|
+
enabled: true,
|
|
21343
|
+
disable: () => registeredTool.update({ enabled: false }),
|
|
21344
|
+
enable: () => registeredTool.update({ enabled: true }),
|
|
21345
|
+
remove: () => registeredTool.update({ name: null }),
|
|
21346
|
+
update: (updates) => {
|
|
21347
|
+
if (typeof updates.name !== "undefined" && updates.name !== name) {
|
|
21348
|
+
delete this._registeredTools[name];
|
|
21349
|
+
if (updates.name)
|
|
21350
|
+
this._registeredTools[updates.name] = registeredTool;
|
|
21351
|
+
}
|
|
21352
|
+
if (typeof updates.description !== "undefined")
|
|
21353
|
+
registeredTool.description = updates.description;
|
|
21354
|
+
if (typeof updates.paramsSchema !== "undefined")
|
|
21355
|
+
registeredTool.inputSchema = z.object(updates.paramsSchema);
|
|
21356
|
+
if (typeof updates.callback !== "undefined")
|
|
21357
|
+
registeredTool.callback = updates.callback;
|
|
21358
|
+
if (typeof updates.annotations !== "undefined")
|
|
21359
|
+
registeredTool.annotations = updates.annotations;
|
|
21360
|
+
if (typeof updates.enabled !== "undefined")
|
|
21361
|
+
registeredTool.enabled = updates.enabled;
|
|
21362
|
+
this.sendToolListChanged();
|
|
21363
|
+
}
|
|
21179
21364
|
};
|
|
21365
|
+
this._registeredTools[name] = registeredTool;
|
|
21180
21366
|
this.setToolRequestHandlers();
|
|
21367
|
+
this.sendToolListChanged();
|
|
21368
|
+
return registeredTool;
|
|
21181
21369
|
}
|
|
21182
21370
|
prompt(name, ...rest) {
|
|
21183
21371
|
if (this._registeredPrompts[name]) {
|
|
@@ -21192,17 +21380,67 @@ class McpServer {
|
|
|
21192
21380
|
argsSchema = rest.shift();
|
|
21193
21381
|
}
|
|
21194
21382
|
const cb = rest[0];
|
|
21195
|
-
|
|
21383
|
+
const registeredPrompt = {
|
|
21196
21384
|
description,
|
|
21197
21385
|
argsSchema: argsSchema === undefined ? undefined : z.object(argsSchema),
|
|
21198
|
-
callback: cb
|
|
21386
|
+
callback: cb,
|
|
21387
|
+
enabled: true,
|
|
21388
|
+
disable: () => registeredPrompt.update({ enabled: false }),
|
|
21389
|
+
enable: () => registeredPrompt.update({ enabled: true }),
|
|
21390
|
+
remove: () => registeredPrompt.update({ name: null }),
|
|
21391
|
+
update: (updates) => {
|
|
21392
|
+
if (typeof updates.name !== "undefined" && updates.name !== name) {
|
|
21393
|
+
delete this._registeredPrompts[name];
|
|
21394
|
+
if (updates.name)
|
|
21395
|
+
this._registeredPrompts[updates.name] = registeredPrompt;
|
|
21396
|
+
}
|
|
21397
|
+
if (typeof updates.description !== "undefined")
|
|
21398
|
+
registeredPrompt.description = updates.description;
|
|
21399
|
+
if (typeof updates.argsSchema !== "undefined")
|
|
21400
|
+
registeredPrompt.argsSchema = z.object(updates.argsSchema);
|
|
21401
|
+
if (typeof updates.callback !== "undefined")
|
|
21402
|
+
registeredPrompt.callback = updates.callback;
|
|
21403
|
+
if (typeof updates.enabled !== "undefined")
|
|
21404
|
+
registeredPrompt.enabled = updates.enabled;
|
|
21405
|
+
this.sendPromptListChanged();
|
|
21406
|
+
}
|
|
21199
21407
|
};
|
|
21408
|
+
this._registeredPrompts[name] = registeredPrompt;
|
|
21200
21409
|
this.setPromptRequestHandlers();
|
|
21410
|
+
this.sendPromptListChanged();
|
|
21411
|
+
return registeredPrompt;
|
|
21412
|
+
}
|
|
21413
|
+
isConnected() {
|
|
21414
|
+
return this.server.transport !== undefined;
|
|
21415
|
+
}
|
|
21416
|
+
sendResourceListChanged() {
|
|
21417
|
+
if (this.isConnected()) {
|
|
21418
|
+
this.server.sendResourceListChanged();
|
|
21419
|
+
}
|
|
21420
|
+
}
|
|
21421
|
+
sendToolListChanged() {
|
|
21422
|
+
if (this.isConnected()) {
|
|
21423
|
+
this.server.sendToolListChanged();
|
|
21424
|
+
}
|
|
21425
|
+
}
|
|
21426
|
+
sendPromptListChanged() {
|
|
21427
|
+
if (this.isConnected()) {
|
|
21428
|
+
this.server.sendPromptListChanged();
|
|
21429
|
+
}
|
|
21201
21430
|
}
|
|
21202
21431
|
}
|
|
21203
21432
|
var EMPTY_OBJECT_JSON_SCHEMA = {
|
|
21204
21433
|
type: "object"
|
|
21205
21434
|
};
|
|
21435
|
+
function isZodRawShape(obj) {
|
|
21436
|
+
if (typeof obj !== "object" || obj === null)
|
|
21437
|
+
return false;
|
|
21438
|
+
const isEmptyObject = Object.keys(obj).length === 0;
|
|
21439
|
+
return isEmptyObject || Object.values(obj).some(isZodTypeLike);
|
|
21440
|
+
}
|
|
21441
|
+
function isZodTypeLike(value) {
|
|
21442
|
+
return value !== null && typeof value === "object" && "parse" in value && typeof value.parse === "function" && "safeParse" in value && typeof value.safeParse === "function";
|
|
21443
|
+
}
|
|
21206
21444
|
function promptArgumentsFromSchema(schema) {
|
|
21207
21445
|
return Object.entries(schema.shape).map(([name, field]) => ({
|
|
21208
21446
|
name,
|
|
@@ -21243,7 +21481,7 @@ class ReadBuffer {
|
|
|
21243
21481
|
if (index === -1) {
|
|
21244
21482
|
return null;
|
|
21245
21483
|
}
|
|
21246
|
-
const line = this._buffer.toString("utf8", 0, index);
|
|
21484
|
+
const line = this._buffer.toString("utf8", 0, index).replace(/\r$/, "");
|
|
21247
21485
|
this._buffer = this._buffer.subarray(index + 1);
|
|
21248
21486
|
return deserializeMessage(line);
|
|
21249
21487
|
}
|
|
@@ -21325,7 +21563,7 @@ var import_client = __toESM(require_lib(), 1);
|
|
|
21325
21563
|
|
|
21326
21564
|
// package.json
|
|
21327
21565
|
var name = "@shortcut/mcp";
|
|
21328
|
-
var version = "0.
|
|
21566
|
+
var version = "0.5.0";
|
|
21329
21567
|
|
|
21330
21568
|
// src/tools/base.ts
|
|
21331
21569
|
class BaseTools {
|
|
@@ -21339,13 +21577,98 @@ class BaseTools {
|
|
|
21339
21577
|
}
|
|
21340
21578
|
|
|
21341
21579
|
// src/tools/utils/format.ts
|
|
21580
|
+
function jsonToText(data, options = {}) {
|
|
21581
|
+
const indent = options.indent || "";
|
|
21582
|
+
if (data === null || data === undefined)
|
|
21583
|
+
return "";
|
|
21584
|
+
if (Array.isArray(data))
|
|
21585
|
+
return formatArray(data, { ...options, indent });
|
|
21586
|
+
if (typeof data === "object")
|
|
21587
|
+
return formatObject(data, { ...options, indent });
|
|
21588
|
+
return formatPrimitive(data);
|
|
21589
|
+
}
|
|
21590
|
+
function formatPrimitive(value) {
|
|
21591
|
+
if (typeof value === "boolean")
|
|
21592
|
+
return value ? "Yes" : "No";
|
|
21593
|
+
return String(value);
|
|
21594
|
+
}
|
|
21595
|
+
function formatArray(arr, options = {}) {
|
|
21596
|
+
if (arr.length === 0)
|
|
21597
|
+
return "(empty)";
|
|
21598
|
+
const indent = options.indent || "";
|
|
21599
|
+
const nextIndent = `${indent} `;
|
|
21600
|
+
return arr.map((item) => {
|
|
21601
|
+
let formattedItem;
|
|
21602
|
+
if (typeof item === "object" && item !== null) {
|
|
21603
|
+
formattedItem = jsonToText(item, {
|
|
21604
|
+
...options,
|
|
21605
|
+
indent: nextIndent,
|
|
21606
|
+
depth: options.depth !== undefined ? options.depth - 1 : undefined
|
|
21607
|
+
});
|
|
21608
|
+
if (formattedItem.includes(`
|
|
21609
|
+
`))
|
|
21610
|
+
return `${indent}-
|
|
21611
|
+
${formattedItem}`;
|
|
21612
|
+
} else
|
|
21613
|
+
formattedItem = formatPrimitive(item);
|
|
21614
|
+
return `${indent}- ${formattedItem}`;
|
|
21615
|
+
}).join(`
|
|
21616
|
+
`);
|
|
21617
|
+
}
|
|
21618
|
+
function formatObject(obj, options = {}) {
|
|
21619
|
+
const indent = options.indent || "";
|
|
21620
|
+
const nextIndent = `${indent} `;
|
|
21621
|
+
if (options.depth !== undefined && options.depth <= 0)
|
|
21622
|
+
return `${indent}[Object]`;
|
|
21623
|
+
if (Object.keys(obj).length === 0)
|
|
21624
|
+
return `${indent}(empty)`;
|
|
21625
|
+
let keys;
|
|
21626
|
+
if (!options.include) {
|
|
21627
|
+
keys = Object.keys(obj);
|
|
21628
|
+
} else if (Array.isArray(options.include)) {
|
|
21629
|
+
const arr = options.include;
|
|
21630
|
+
keys = Object.keys(obj).filter((key) => arr.includes(key));
|
|
21631
|
+
} else {
|
|
21632
|
+
keys = Object.keys(obj).filter((key) => {
|
|
21633
|
+
const include = options.include;
|
|
21634
|
+
return key in include;
|
|
21635
|
+
});
|
|
21636
|
+
}
|
|
21637
|
+
return keys.map((key) => {
|
|
21638
|
+
const value = obj[key];
|
|
21639
|
+
const formattedKey = formatKey(key);
|
|
21640
|
+
let nestedInclude;
|
|
21641
|
+
if (options.include && !Array.isArray(options.include)) {
|
|
21642
|
+
const includeValue = options.include[key];
|
|
21643
|
+
if (includeValue === true)
|
|
21644
|
+
nestedInclude = undefined;
|
|
21645
|
+
else
|
|
21646
|
+
nestedInclude = includeValue;
|
|
21647
|
+
}
|
|
21648
|
+
const formattedValue = jsonToText(value, {
|
|
21649
|
+
...options,
|
|
21650
|
+
include: nestedInclude,
|
|
21651
|
+
indent: nextIndent,
|
|
21652
|
+
depth: options.depth !== undefined ? options.depth - 1 : undefined
|
|
21653
|
+
});
|
|
21654
|
+
if (!formattedValue.includes(`
|
|
21655
|
+
`)) {
|
|
21656
|
+
return `${indent}${formattedKey}: ${formattedValue}`;
|
|
21657
|
+
}
|
|
21658
|
+
return `${indent}${formattedKey}:
|
|
21659
|
+
${formattedValue}`;
|
|
21660
|
+
}).join(`
|
|
21661
|
+
`);
|
|
21662
|
+
}
|
|
21663
|
+
function formatKey(key) {
|
|
21664
|
+
return key.replace(/([A-Z])/g, " $1").replace(/_/g, " ").trim().split(" ").map((word) => word.charAt(0).toUpperCase() + word.slice(1).toLowerCase()).join(" ");
|
|
21665
|
+
}
|
|
21342
21666
|
var formatAsUnorderedList = (items, label) => {
|
|
21343
21667
|
return `${label ? `${label}:` : ""}${items?.length ? `${label ? `
|
|
21344
|
-
` : ""}${items
|
|
21345
|
-
`)}` : `${label ? " " : ""}[None]`}`;
|
|
21668
|
+
` : ""}${formatArray(items)}` : `${label ? " " : ""}(none)`}`;
|
|
21346
21669
|
};
|
|
21347
21670
|
var formatStoryList = (stories, users, label) => {
|
|
21348
|
-
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}` : "
|
|
21671
|
+
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);
|
|
21349
21672
|
};
|
|
21350
21673
|
var formatMemberList = (ids, users, label = "Members") => {
|
|
21351
21674
|
return formatAsUnorderedList((ids || []).map((id) => {
|
|
@@ -21382,6 +21705,9 @@ var formatStats = (stats, showPoints) => {
|
|
|
21382
21705
|
- (${stats.num_stories_unestimated} of the stories are unestimated)`;
|
|
21383
21706
|
return statsString;
|
|
21384
21707
|
};
|
|
21708
|
+
var formatUsersList = (users) => {
|
|
21709
|
+
return formatAsUnorderedList(users.map((user) => `id=${user.id} ${user?.profile?.mention_name ? `@${user.profile.mention_name}` : ""} : ""}`));
|
|
21710
|
+
};
|
|
21385
21711
|
|
|
21386
21712
|
// src/tools/utils/search.ts
|
|
21387
21713
|
var getKey = (prop) => {
|
|
@@ -21394,8 +21720,11 @@ var getKey = (prop) => {
|
|
|
21394
21720
|
var buildSearchQuery = async (params, currentUser) => {
|
|
21395
21721
|
const query = Object.entries(params).map(([key, value]) => {
|
|
21396
21722
|
const q = getKey(key);
|
|
21397
|
-
if (
|
|
21398
|
-
|
|
21723
|
+
if (key === "owner" || key === "requester") {
|
|
21724
|
+
if (value === "me")
|
|
21725
|
+
return `${q}:${currentUser?.mention_name || value}`;
|
|
21726
|
+
return `${q}:${String(value || "").replace(/^@/, "")}`;
|
|
21727
|
+
}
|
|
21399
21728
|
if (typeof value === "boolean")
|
|
21400
21729
|
return value ? q : `!${q}`;
|
|
21401
21730
|
if (typeof value === "number")
|
|
@@ -21429,9 +21758,9 @@ var variations = [
|
|
|
21429
21758
|
range({ f: dateformat, t: dateformat })
|
|
21430
21759
|
];
|
|
21431
21760
|
var DATE_REGEXP = new RegExp(`^(${variations.join("|")})$`);
|
|
21432
|
-
var date2 = z.string().regex(DATE_REGEXP).optional().describe('The date in "YYYY-MM-DD" format, or one of the keywords: "yesterday", "today", "tomorrow", or a date range in the format "YYYY-MM-DD..YYYY-MM-DD". The date range can also be open ended by using "*" for one of the bounds.
|
|
21761
|
+
var date2 = z.string().regex(DATE_REGEXP).optional().describe('The date in "YYYY-MM-DD" format, or one of the keywords: "yesterday", "today", "tomorrow", or a date range in the format "YYYY-MM-DD..YYYY-MM-DD". The date range can also be open ended by using "*" for one of the bounds. Examples: "2023-01-01", "today", "2023-01-01..*" (from Jan 1, 2023 to any future date), "*.2023-01-31" (any date up to Jan 31, 2023), "today..*" (from today onwards), "*.yesterday" (any date up to yesterday). The keywords cannot be used to calculate relative dates (e.g. the following are not valid: "today-1" or "tomorrow+1").');
|
|
21433
21762
|
var is = (field) => z.boolean().optional().describe(`Find only entities that are ${field} when true, or only entities that are not ${field} when false.`);
|
|
21434
|
-
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.`);
|
|
21763
|
+
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. Example: hasOwner: true will find stories with an owner, hasOwner: false will find stories without an owner.`);
|
|
21435
21764
|
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.`);
|
|
21436
21765
|
|
|
21437
21766
|
// src/tools/epics.ts
|
|
@@ -21465,8 +21794,9 @@ class EpicTools extends BaseTools {
|
|
|
21465
21794
|
}, async (params) => await tools.searchEpics(params));
|
|
21466
21795
|
server.tool("create-epic", "Create a new Shortcut epic.", {
|
|
21467
21796
|
name: z.string().describe("The name of the epic"),
|
|
21468
|
-
|
|
21469
|
-
description: z.string().optional().describe("
|
|
21797
|
+
owner: z.string().optional().describe("The user ID of the owner of the epic"),
|
|
21798
|
+
description: z.string().optional().describe("A description of the epic"),
|
|
21799
|
+
teamId: z.string().optional().describe("The ID of a team to assign the epic to")
|
|
21470
21800
|
}, async (params) => await tools.createEpic(params));
|
|
21471
21801
|
return tools;
|
|
21472
21802
|
}
|
|
@@ -21494,8 +21824,8 @@ Archived: ${epic.archived ? "Yes" : "No"}
|
|
|
21494
21824
|
Completed: ${epic.completed ? "Yes" : "No"}
|
|
21495
21825
|
Started: ${epic.started ? "Yes" : "No"}
|
|
21496
21826
|
Due date: ${epic.deadline ? epic.deadline : "[Not set]"}
|
|
21497
|
-
Team: ${epic.group_id ? `${epic.group_id}` : "
|
|
21498
|
-
Objective: ${epic.milestone_id ? `${epic.milestone_id}` : "
|
|
21827
|
+
Team: ${epic.group_id ? `${epic.group_id}` : "(none)"}
|
|
21828
|
+
Objective: ${epic.milestone_id ? `${epic.milestone_id}` : "(none)"}
|
|
21499
21829
|
|
|
21500
21830
|
${formatStats(epic.stats, showPoints)}
|
|
21501
21831
|
|
|
@@ -21504,15 +21834,16 @@ ${epic.description}`);
|
|
|
21504
21834
|
}
|
|
21505
21835
|
async createEpic({
|
|
21506
21836
|
name: name2,
|
|
21507
|
-
|
|
21837
|
+
owner,
|
|
21838
|
+
teamId: group_id,
|
|
21508
21839
|
description
|
|
21509
21840
|
}) {
|
|
21510
|
-
|
|
21511
|
-
|
|
21512
|
-
|
|
21513
|
-
|
|
21514
|
-
|
|
21515
|
-
|
|
21841
|
+
const epic = await this.client.createEpic({
|
|
21842
|
+
name: name2,
|
|
21843
|
+
group_id,
|
|
21844
|
+
owner_ids: owner ? [owner] : undefined,
|
|
21845
|
+
description
|
|
21846
|
+
});
|
|
21516
21847
|
return this.toResult(`Epic created with ID: ${epic.id}.`);
|
|
21517
21848
|
}
|
|
21518
21849
|
}
|
|
@@ -21530,7 +21861,7 @@ class IterationTools extends BaseTools {
|
|
|
21530
21861
|
name: z.string().optional().describe("Find only iterations matching the specified name"),
|
|
21531
21862
|
description: z.string().optional().describe("Find only iterations matching the specified description"),
|
|
21532
21863
|
state: z.enum(["started", "unstarted", "done"]).optional().describe("Find only iterations matching the specified state"),
|
|
21533
|
-
team: z.string().optional().describe("Find only iterations matching the specified team.
|
|
21864
|
+
team: z.string().optional().describe("Find only iterations matching the specified team. This can be a team ID or mention name."),
|
|
21534
21865
|
created: date2,
|
|
21535
21866
|
updated: date2,
|
|
21536
21867
|
startDate: date2,
|
|
@@ -21538,10 +21869,10 @@ class IterationTools extends BaseTools {
|
|
|
21538
21869
|
}, async (params) => await tools.searchIterations(params));
|
|
21539
21870
|
server.tool("create-iteration", "Create a new Shortcut iteration", {
|
|
21540
21871
|
name: z.string().describe("The name of the iteration"),
|
|
21541
|
-
|
|
21542
|
-
|
|
21543
|
-
|
|
21544
|
-
|
|
21872
|
+
startDate: z.string().describe("The start date of the iteration in YYYY-MM-DD format"),
|
|
21873
|
+
endDate: z.string().describe("The end date of the iteration in YYYY-MM-DD format"),
|
|
21874
|
+
teamId: z.string().optional().describe("The ID of a team to assign the iteration to"),
|
|
21875
|
+
description: z.string().optional().describe("A description of the iteration")
|
|
21545
21876
|
}, async (params) => await tools.createIteration(params));
|
|
21546
21877
|
return tools;
|
|
21547
21878
|
}
|
|
@@ -21577,7 +21908,7 @@ Start date: ${iteration.start_date}
|
|
|
21577
21908
|
End date: ${iteration.end_date}
|
|
21578
21909
|
Completed: ${iteration.status === "completed" ? "Yes" : "No"}
|
|
21579
21910
|
Started: ${iteration.status === "started" ? "Yes" : "No"}
|
|
21580
|
-
Team: ${iteration.group_ids?.length ? `${iteration.group_ids.join(", ")}` : "
|
|
21911
|
+
Team: ${iteration.group_ids?.length ? `${iteration.group_ids.join(", ")}` : "(none)"}
|
|
21581
21912
|
|
|
21582
21913
|
${formatStats(iteration.stats, showPoints)}
|
|
21583
21914
|
|
|
@@ -21591,11 +21922,6 @@ ${iteration.description}`);
|
|
|
21591
21922
|
teamId,
|
|
21592
21923
|
description
|
|
21593
21924
|
}) {
|
|
21594
|
-
if (teamId) {
|
|
21595
|
-
const team = await this.client.getTeam(teamId);
|
|
21596
|
-
if (!team)
|
|
21597
|
-
throw new Error(`Team with ID ${teamId} not found`);
|
|
21598
|
-
}
|
|
21599
21925
|
const iteration = await this.client.createIteration({
|
|
21600
21926
|
name: name2,
|
|
21601
21927
|
start_date: startDate,
|
|
@@ -21666,7 +21992,7 @@ ${objective.description}`);
|
|
|
21666
21992
|
class StoryTools extends BaseTools {
|
|
21667
21993
|
static create(client, server) {
|
|
21668
21994
|
const tools = new StoryTools(client);
|
|
21669
|
-
server.tool("get-story-branch-name",
|
|
21995
|
+
server.tool("get-story-branch-name", "Get a valid branch name for a specific story.", {
|
|
21670
21996
|
storyPublicId: z.number().positive().describe("The public Id of the story")
|
|
21671
21997
|
}, async ({ storyPublicId }) => await tools.getStoryBranchName(storyPublicId));
|
|
21672
21998
|
server.tool("get-story", "Get a Shortcut story by public ID", {
|
|
@@ -21719,7 +22045,9 @@ class StoryTools extends BaseTools {
|
|
|
21719
22045
|
due: date2
|
|
21720
22046
|
}, async (params) => await tools.searchStories(params));
|
|
21721
22047
|
server.tool("create-story", `Create a new Shortcut story.
|
|
21722
|
-
Name
|
|
22048
|
+
Name is required, and either a Team or Workflow must be specified:
|
|
22049
|
+
- If only Team is specified, we will use the default workflow for that team.
|
|
22050
|
+
- If Workflow is specified, it will be used regardless of Team.
|
|
21723
22051
|
The story will be added to the default state for the workflow.
|
|
21724
22052
|
`, {
|
|
21725
22053
|
name: z.string().min(1).max(512).describe("The name of the story. Required."),
|
|
@@ -21727,8 +22055,8 @@ The story will be added to the default state for the workflow.
|
|
|
21727
22055
|
type: z.enum(["feature", "bug", "chore"]).default("feature").describe("The type of the story"),
|
|
21728
22056
|
owner: z.string().optional().describe("The user id of the owner of the story"),
|
|
21729
22057
|
epic: z.number().optional().describe("The epic id of the epic the story belongs to"),
|
|
21730
|
-
team: z.string().optional().describe("The team
|
|
21731
|
-
workflow: z.number().optional().describe("The workflow to add the story to. Required unless a team is specified.")
|
|
22058
|
+
team: z.string().optional().describe("The team ID or mention name of the team the story belongs to. Required unless a workflow is specified."),
|
|
22059
|
+
workflow: z.number().optional().describe("The workflow ID to add the story to. Required unless a team is specified.")
|
|
21732
22060
|
}, async ({ name: name2, description, type, owner, epic, team, workflow }) => await tools.createStory({
|
|
21733
22061
|
name: name2,
|
|
21734
22062
|
description,
|
|
@@ -21738,6 +22066,21 @@ The story will be added to the default state for the workflow.
|
|
|
21738
22066
|
team,
|
|
21739
22067
|
workflow
|
|
21740
22068
|
}));
|
|
22069
|
+
server.tool("update-story", "Update an existing Shortcut story. Only provide fields you want to update. The story public ID will always be included in updates.", {
|
|
22070
|
+
storyPublicId: z.number().positive().describe("The public ID of the story to update"),
|
|
22071
|
+
name: z.string().max(512).optional().describe("The name of the story"),
|
|
22072
|
+
description: z.string().max(1e4).optional().describe("The description of the story"),
|
|
22073
|
+
type: z.enum(["feature", "bug", "chore"]).optional().describe("The type of the story"),
|
|
22074
|
+
epic: z.number().nullable().optional().describe("The epic id of the epic the story belongs to, or null to unset"),
|
|
22075
|
+
estimate: z.number().nullable().optional().describe("The point estimate of the story, or null to unset"),
|
|
22076
|
+
owner_ids: z.array(z.string()).optional().describe("Array of user UUIDs to assign as owners of the story"),
|
|
22077
|
+
workflow_state_id: z.number().optional().describe("The workflow state ID to move the story to"),
|
|
22078
|
+
labels: z.array(z.object({
|
|
22079
|
+
name: z.string().describe("The name of the label"),
|
|
22080
|
+
color: z.string().optional().describe("The color of the label"),
|
|
22081
|
+
description: z.string().optional().describe("The description of the label")
|
|
22082
|
+
})).optional().describe("Labels to assign to the story")
|
|
22083
|
+
}, async (params) => await tools.updateStory(params));
|
|
21741
22084
|
server.tool("assign-current-user-as-owner", "Assign the current user as the owner of a story", {
|
|
21742
22085
|
storyPublicId: z.number().positive().describe("The public ID of the story")
|
|
21743
22086
|
}, async ({ storyPublicId }) => await tools.assignCurrentUserAsOwner(storyPublicId));
|
|
@@ -21748,6 +22091,22 @@ The story will be added to the default state for the workflow.
|
|
|
21748
22091
|
storyPublicId: z.number().positive().describe("The public ID of the story"),
|
|
21749
22092
|
text: z.string().min(1).describe("The text of the comment")
|
|
21750
22093
|
}, async (params) => await tools.createStoryComment(params));
|
|
22094
|
+
server.tool("add-task-to-story", "Add a task to a story", {
|
|
22095
|
+
storyPublicId: z.number().positive().describe("The public ID of the story"),
|
|
22096
|
+
taskDescription: z.string().min(1).describe("The description of the task"),
|
|
22097
|
+
taskOwnerIds: z.array(z.string()).optional().describe("Array of user IDs to assign as owners of the task")
|
|
22098
|
+
}, async (params) => await tools.addTaskToStory(params));
|
|
22099
|
+
server.tool("add-relation-to-story", "Add a relation to a story", {
|
|
22100
|
+
storyPublicId: z.number().positive().describe("The public ID of the story"),
|
|
22101
|
+
relatedStoryPublicId: z.number().positive().describe("The public ID of the related story")
|
|
22102
|
+
}, async (params) => await tools.addRelationToStory(params));
|
|
22103
|
+
server.tool("update-task", "Update a task in a story", {
|
|
22104
|
+
storyPublicId: z.number().positive().describe("The public ID of the story"),
|
|
22105
|
+
taskPublicId: z.number().positive().describe("The public ID of the task"),
|
|
22106
|
+
taskDescription: z.string().optional().describe("The description of the task"),
|
|
22107
|
+
taskOwnerIds: z.array(z.string()).optional().describe("Array of user IDs to assign as owners of the task"),
|
|
22108
|
+
isCompleted: z.boolean().optional().describe("Whether the task is completed or not")
|
|
22109
|
+
}, async (params) => await tools.updateTask(params));
|
|
21751
22110
|
return tools;
|
|
21752
22111
|
}
|
|
21753
22112
|
async assignCurrentUserAsOwner(storyPublicId) {
|
|
@@ -21852,11 +22211,11 @@ Completed: ${story.completed ? "Yes" : "No"}
|
|
|
21852
22211
|
Started: ${story.started ? "Yes" : "No"}
|
|
21853
22212
|
Blocked: ${story.blocked ? "Yes" : "No"}
|
|
21854
22213
|
Blocking: ${story.blocker ? "Yes" : "No"}
|
|
21855
|
-
Due date: ${story.deadline ? story.deadline : "
|
|
21856
|
-
Team: ${story.group_id ? `${story.group_id}` : "
|
|
22214
|
+
Due date: ${story.deadline ? story.deadline : "(none)"}
|
|
22215
|
+
Team: ${story.group_id ? `${story.group_id}` : "(none)"}
|
|
21857
22216
|
${formatMemberList(story.owner_ids, users, "Owners")}
|
|
21858
|
-
Epic: ${story.epic_id ? `${story.epic_id}` : "
|
|
21859
|
-
Iteration: ${story.iteration_id ? `${story.iteration_id}` : "
|
|
22217
|
+
Epic: ${story.epic_id ? `${story.epic_id}` : "(none)"}
|
|
22218
|
+
Iteration: ${story.iteration_id ? `${story.iteration_id}` : "(none)"}
|
|
21860
22219
|
|
|
21861
22220
|
Description:
|
|
21862
22221
|
${story.description}
|
|
@@ -21890,6 +22249,103 @@ ${comment.text || ""}`;
|
|
|
21890
22249
|
const storyComment = await this.client.createStoryComment(storyPublicId, { text });
|
|
21891
22250
|
return this.toResult(`Created comment on story sc-${storyPublicId}. Comment URL: ${storyComment.app_url}.`);
|
|
21892
22251
|
}
|
|
22252
|
+
async updateStory({
|
|
22253
|
+
storyPublicId,
|
|
22254
|
+
...updates
|
|
22255
|
+
}) {
|
|
22256
|
+
if (!storyPublicId)
|
|
22257
|
+
throw new Error("Story public ID is required");
|
|
22258
|
+
const story = await this.client.getStory(storyPublicId);
|
|
22259
|
+
if (!story)
|
|
22260
|
+
throw new Error(`Failed to retrieve Shortcut story with public ID: ${storyPublicId}`);
|
|
22261
|
+
const updateParams = {};
|
|
22262
|
+
if (updates.name !== undefined)
|
|
22263
|
+
updateParams.name = updates.name;
|
|
22264
|
+
if (updates.description !== undefined)
|
|
22265
|
+
updateParams.description = updates.description;
|
|
22266
|
+
if (updates.type !== undefined)
|
|
22267
|
+
updateParams.story_type = updates.type;
|
|
22268
|
+
if (updates.epic !== undefined)
|
|
22269
|
+
updateParams.epic_id = updates.epic;
|
|
22270
|
+
if (updates.estimate !== undefined)
|
|
22271
|
+
updateParams.estimate = updates.estimate;
|
|
22272
|
+
if (updates.owner_ids !== undefined)
|
|
22273
|
+
updateParams.owner_ids = updates.owner_ids;
|
|
22274
|
+
if (updates.workflow_state_id !== undefined)
|
|
22275
|
+
updateParams.workflow_state_id = updates.workflow_state_id;
|
|
22276
|
+
if (updates.labels !== undefined)
|
|
22277
|
+
updateParams.labels = updates.labels;
|
|
22278
|
+
const updatedStory = await this.client.updateStory(storyPublicId, updateParams);
|
|
22279
|
+
return this.toResult(`Updated story sc-${storyPublicId}. Story URL: ${updatedStory.app_url}`);
|
|
22280
|
+
}
|
|
22281
|
+
async addTaskToStory({
|
|
22282
|
+
storyPublicId,
|
|
22283
|
+
taskDescription,
|
|
22284
|
+
taskOwnerIds
|
|
22285
|
+
}) {
|
|
22286
|
+
if (!storyPublicId)
|
|
22287
|
+
throw new Error("Story public ID is required");
|
|
22288
|
+
if (!taskDescription)
|
|
22289
|
+
throw new Error("Task description is required");
|
|
22290
|
+
const story = await this.client.getStory(storyPublicId);
|
|
22291
|
+
if (!story)
|
|
22292
|
+
throw new Error(`Failed to retrieve Shortcut story with public ID: ${storyPublicId}`);
|
|
22293
|
+
if (taskOwnerIds?.length) {
|
|
22294
|
+
const owners = await this.client.getUserMap(taskOwnerIds);
|
|
22295
|
+
if (!owners)
|
|
22296
|
+
throw new Error(`Failed to retrieve users with IDs: ${taskOwnerIds.join(", ")}`);
|
|
22297
|
+
}
|
|
22298
|
+
const task = await this.client.addTaskToStory(storyPublicId, {
|
|
22299
|
+
description: taskDescription,
|
|
22300
|
+
ownerIds: taskOwnerIds
|
|
22301
|
+
});
|
|
22302
|
+
return this.toResult(`Created task for story sc-${storyPublicId}. Task ID: ${task.id}.`);
|
|
22303
|
+
}
|
|
22304
|
+
async updateTask({
|
|
22305
|
+
storyPublicId,
|
|
22306
|
+
taskPublicId,
|
|
22307
|
+
taskDescription,
|
|
22308
|
+
taskOwnerIds,
|
|
22309
|
+
isCompleted
|
|
22310
|
+
}) {
|
|
22311
|
+
if (!storyPublicId)
|
|
22312
|
+
throw new Error("Story public ID is required");
|
|
22313
|
+
if (!taskPublicId)
|
|
22314
|
+
throw new Error("Task public ID is required");
|
|
22315
|
+
const story = await this.client.getStory(storyPublicId);
|
|
22316
|
+
if (!story)
|
|
22317
|
+
throw new Error(`Failed to retrieve Shortcut story with public ID: ${storyPublicId}`);
|
|
22318
|
+
const task = await this.client.getTask(storyPublicId, taskPublicId);
|
|
22319
|
+
if (!task)
|
|
22320
|
+
throw new Error(`Failed to retrieve Shortcut task with public ID: ${taskPublicId}`);
|
|
22321
|
+
const updatedTask = await this.client.updateTask(storyPublicId, taskPublicId, {
|
|
22322
|
+
description: taskDescription,
|
|
22323
|
+
ownerIds: taskOwnerIds,
|
|
22324
|
+
isCompleted
|
|
22325
|
+
});
|
|
22326
|
+
let message = `Updated task for story sc-${storyPublicId}. Task ID: ${updatedTask.id}.`;
|
|
22327
|
+
if (isCompleted) {
|
|
22328
|
+
message = `Completed task for story sc-${storyPublicId}. Task ID: ${updatedTask.id}.`;
|
|
22329
|
+
}
|
|
22330
|
+
return this.toResult(message);
|
|
22331
|
+
}
|
|
22332
|
+
async addRelationToStory({
|
|
22333
|
+
storyPublicId,
|
|
22334
|
+
relatedStoryPublicId
|
|
22335
|
+
}) {
|
|
22336
|
+
if (!storyPublicId)
|
|
22337
|
+
throw new Error("Story public ID is required");
|
|
22338
|
+
if (!relatedStoryPublicId)
|
|
22339
|
+
throw new Error("Related story public ID is required");
|
|
22340
|
+
const story = await this.client.getStory(storyPublicId);
|
|
22341
|
+
if (!story)
|
|
22342
|
+
throw new Error(`Failed to retrieve Shortcut story with public ID: ${storyPublicId}`);
|
|
22343
|
+
const relatedStory = await this.client.getStory(relatedStoryPublicId);
|
|
22344
|
+
if (!relatedStory)
|
|
22345
|
+
throw new Error(`Failed to retrieve Shortcut story with public ID: ${relatedStoryPublicId}`);
|
|
22346
|
+
await this.client.addRelationToStory(storyPublicId, relatedStoryPublicId);
|
|
22347
|
+
return this.toResult(`Added relation between stories sc-${storyPublicId} and sc-${relatedStoryPublicId}.`);
|
|
22348
|
+
}
|
|
21893
22349
|
}
|
|
21894
22350
|
|
|
21895
22351
|
// src/tools/teams.ts
|
|
@@ -21933,6 +22389,7 @@ class UserTools extends BaseTools {
|
|
|
21933
22389
|
static create(client, server) {
|
|
21934
22390
|
const tools = new UserTools(client);
|
|
21935
22391
|
server.tool("get-current-user", "Get the current user", async () => await tools.getCurrentUser());
|
|
22392
|
+
server.tool("list-members", "Get all members", async () => await tools.listMembers());
|
|
21936
22393
|
return tools;
|
|
21937
22394
|
}
|
|
21938
22395
|
async getCurrentUser() {
|
|
@@ -21944,6 +22401,10 @@ Id: ${user2.id}
|
|
|
21944
22401
|
Mention name: @${user2.mention_name}
|
|
21945
22402
|
Full name: ${user2.name}`);
|
|
21946
22403
|
}
|
|
22404
|
+
async listMembers() {
|
|
22405
|
+
const members = await this.client.listMembers();
|
|
22406
|
+
return this.toResult(`Found ${members.length} members, ${formatUsersList(members)}`);
|
|
22407
|
+
}
|
|
21947
22408
|
}
|
|
21948
22409
|
|
|
21949
22410
|
// src/tools/workflows.ts
|
package/package.json
CHANGED
|
@@ -6,15 +6,21 @@
|
|
|
6
6
|
"type": "git",
|
|
7
7
|
"url": "https://github.com/useshortcut/mcp-server-shortcut.git"
|
|
8
8
|
},
|
|
9
|
-
"keywords": [
|
|
9
|
+
"keywords": [
|
|
10
|
+
"shortcut",
|
|
11
|
+
"mcp",
|
|
12
|
+
"modelcontextprotocol"
|
|
13
|
+
],
|
|
10
14
|
"license": "MIT",
|
|
11
|
-
"version": "0.
|
|
15
|
+
"version": "0.5.0",
|
|
12
16
|
"type": "module",
|
|
13
17
|
"main": "dist/index.js",
|
|
14
18
|
"bin": {
|
|
15
19
|
"mcp-server-shortcut": "dist/index.js"
|
|
16
20
|
},
|
|
17
|
-
"files": [
|
|
21
|
+
"files": [
|
|
22
|
+
"dist"
|
|
23
|
+
],
|
|
18
24
|
"devDependencies": {
|
|
19
25
|
"@biomejs/biome": "^1.9.4",
|
|
20
26
|
"@types/bun": "latest",
|
|
@@ -26,9 +32,9 @@
|
|
|
26
32
|
"typescript": "^5"
|
|
27
33
|
},
|
|
28
34
|
"dependencies": {
|
|
29
|
-
"@modelcontextprotocol/sdk": "^1.
|
|
35
|
+
"@modelcontextprotocol/sdk": "^1.11.3",
|
|
30
36
|
"@shortcut/client": "^1.1.0",
|
|
31
|
-
"zod": "^3.24.
|
|
37
|
+
"zod": "^3.24.4"
|
|
32
38
|
},
|
|
33
39
|
"scripts": {
|
|
34
40
|
"test": "bun test",
|