wolfpack-mcp 1.0.97 → 1.0.99
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/client.js +7 -0
- package/dist/index.js +141 -0
- package/package.json +1 -1
package/dist/client.js
CHANGED
|
@@ -240,6 +240,13 @@ export class WolfpackClient {
|
|
|
240
240
|
throw error;
|
|
241
241
|
}
|
|
242
242
|
}
|
|
243
|
+
// Dependency methods (#2331)
|
|
244
|
+
async setWorkItemDependencies(workItemId, dependsOnRefIds, teamSlug) {
|
|
245
|
+
return this.api.put(this.withTeamSlug(`/work-items/${workItemId}/dependencies`, teamSlug), { dependsOnRefIds });
|
|
246
|
+
}
|
|
247
|
+
async getWorkItemDependencyGraph(workItemId, teamSlug) {
|
|
248
|
+
return this.api.get(this.withTeamSlug(`/work-items/${workItemId}/dependency-graph`, teamSlug));
|
|
249
|
+
}
|
|
243
250
|
// Review check methods
|
|
244
251
|
async listWorkItemChecks(filter, teamSlug) {
|
|
245
252
|
const params = new URLSearchParams();
|
package/dist/index.js
CHANGED
|
@@ -216,6 +216,29 @@ const SubmitWorkItemFormSchema = z.object({
|
|
|
216
216
|
.optional()
|
|
217
217
|
.describe('Project slug (required for multi-project users, use list_projects to get slugs)'),
|
|
218
218
|
});
|
|
219
|
+
// #2331 — reference numbers, accepted as numbers or as "#2322" the way agents
|
|
220
|
+
// write them, so an ordered plan can be transcribed without reformatting.
|
|
221
|
+
const dependsOnRefIds = () => z
|
|
222
|
+
.array(z.union([z.number(), z.string()]))
|
|
223
|
+
.transform((refs) => refs.map((ref) => Number(String(ref).replace(/^#/, ''))))
|
|
224
|
+
.refine((refs) => refs.every(Number.isInteger), {
|
|
225
|
+
message: 'depends_on must be work item reference numbers, e.g. [2322] or ["#2322"]',
|
|
226
|
+
});
|
|
227
|
+
const SetWorkItemDependenciesSchema = z.object({
|
|
228
|
+
work_item_id: refIdString().describe('The refId of the work item that follows the others'),
|
|
229
|
+
depends_on: dependsOnRefIds().describe('Reference numbers of the prerequisites. Replaces the whole set; pass [] to clear.'),
|
|
230
|
+
project_slug: z
|
|
231
|
+
.string()
|
|
232
|
+
.optional()
|
|
233
|
+
.describe('Project slug (required for multi-project users, use list_projects to get slugs)'),
|
|
234
|
+
});
|
|
235
|
+
const GetWorkItemDependencyGraphSchema = z.object({
|
|
236
|
+
work_item_id: refIdString().describe('The refId of the work item'),
|
|
237
|
+
project_slug: z
|
|
238
|
+
.string()
|
|
239
|
+
.optional()
|
|
240
|
+
.describe('Project slug (required for multi-project users, use list_projects to get slugs)'),
|
|
241
|
+
});
|
|
219
242
|
const WorkPoolMemberSchema = z.object({
|
|
220
243
|
work_pool: z.string().describe('Work pool id or name'),
|
|
221
244
|
user_id: z.string().describe('The user id to add or remove'),
|
|
@@ -369,6 +392,9 @@ const CreateWorkItemSchema = z.object({
|
|
|
369
392
|
.string()
|
|
370
393
|
.optional()
|
|
371
394
|
.describe('Link to a radar/initiative item. Accepts refId ("5" or "#r5") or UUID.'),
|
|
395
|
+
depends_on: dependsOnRefIds()
|
|
396
|
+
.optional()
|
|
397
|
+
.describe('Reference numbers of work items that must finish before this one starts'),
|
|
372
398
|
});
|
|
373
399
|
const CreateIssueSchema = z.object({
|
|
374
400
|
project_slug: z
|
|
@@ -411,6 +437,10 @@ const UpdateIssueSchema = z.object({
|
|
|
411
437
|
steps_to_reproduce: z.string().optional().describe('Steps to reproduce'),
|
|
412
438
|
expected_behavior: z.string().optional().describe('Expected behavior'),
|
|
413
439
|
actual_behavior: z.string().optional().describe('Actual behavior'),
|
|
440
|
+
tags: z
|
|
441
|
+
.array(z.string())
|
|
442
|
+
.optional()
|
|
443
|
+
.describe('Tag names to apply (replaces existing tags). Use list_tags to see available tags.'),
|
|
414
444
|
project_slug: z
|
|
415
445
|
.string()
|
|
416
446
|
.optional()
|
|
@@ -1269,6 +1299,56 @@ class WolfpackMCPServer {
|
|
|
1269
1299
|
required: ['work_item_id', 'check_id', 'status'],
|
|
1270
1300
|
},
|
|
1271
1301
|
},
|
|
1302
|
+
{
|
|
1303
|
+
name: 'set_work_item_dependencies',
|
|
1304
|
+
description: 'Record which work items must finish before this one can start, so the board knows the order ' +
|
|
1305
|
+
'and the pickup gate enforces it. Use this when you file or plan a set of ordered items, instead ' +
|
|
1306
|
+
'of writing "Follows #2322" into a description — a description is prose nothing enforces. ' +
|
|
1307
|
+
'A bare #N is a WORK ITEM refId, and depends_on takes those reference numbers. ' +
|
|
1308
|
+
'REPLACES the whole set: pass every prerequisite you want the item to have, and [] to clear it. ' +
|
|
1309
|
+
'An item may not depend on itself, nor on anything that already depends on it — either would leave ' +
|
|
1310
|
+
'it permanently blocked, and both are refused with 400 naming the item. ' +
|
|
1311
|
+
'Requires the mcp:work_items:manage_dependencies permission, which is separate from ' +
|
|
1312
|
+
"mcp:work_items:update: updating your own item does not let you order other people's work. " +
|
|
1313
|
+
'Returns what the item now depends on, what follows it, and which prerequisites are still unfinished.',
|
|
1314
|
+
inputSchema: {
|
|
1315
|
+
type: 'object',
|
|
1316
|
+
properties: {
|
|
1317
|
+
work_item_id: {
|
|
1318
|
+
type: 'string',
|
|
1319
|
+
description: 'The refId of the work item that follows the others',
|
|
1320
|
+
},
|
|
1321
|
+
depends_on: {
|
|
1322
|
+
type: 'array',
|
|
1323
|
+
items: { type: ['number', 'string'] },
|
|
1324
|
+
description: 'Reference numbers of the prerequisites, as 2322 or "#2322". Replaces the whole set; pass [] to clear.',
|
|
1325
|
+
},
|
|
1326
|
+
project_slug: {
|
|
1327
|
+
type: 'string',
|
|
1328
|
+
description: 'Project slug (required for multi-project users, use list_projects to get slugs)',
|
|
1329
|
+
},
|
|
1330
|
+
},
|
|
1331
|
+
required: ['work_item_id', 'depends_on'],
|
|
1332
|
+
},
|
|
1333
|
+
},
|
|
1334
|
+
{
|
|
1335
|
+
name: 'get_work_item_dependency_graph',
|
|
1336
|
+
description: 'The whole chain of ordered work around one work item — the prerequisites above it and the work ' +
|
|
1337
|
+
'that follows below — as nodes and edges, each item appearing exactly once. An edge runs from the ' +
|
|
1338
|
+
"item that must finish to the item that waits on it. Use it to see a plan's shape; " +
|
|
1339
|
+
"get_work_item already gives one item's own dependsOn, nextItems and blockedBy.",
|
|
1340
|
+
inputSchema: {
|
|
1341
|
+
type: 'object',
|
|
1342
|
+
properties: {
|
|
1343
|
+
work_item_id: { type: 'string', description: 'The refId of the work item' },
|
|
1344
|
+
project_slug: {
|
|
1345
|
+
type: 'string',
|
|
1346
|
+
description: 'Project slug (required for multi-project users, use list_projects to get slugs)',
|
|
1347
|
+
},
|
|
1348
|
+
},
|
|
1349
|
+
required: ['work_item_id'],
|
|
1350
|
+
},
|
|
1351
|
+
},
|
|
1272
1352
|
// Radar Item (Initiative/Roadmap) tools
|
|
1273
1353
|
{
|
|
1274
1354
|
name: 'list_radar_items',
|
|
@@ -1459,6 +1539,9 @@ class WolfpackMCPServer {
|
|
|
1459
1539
|
name: 'create_work_item',
|
|
1460
1540
|
description: 'Create a new work item in your current project (auto-selected for single-project users, or use list_projects first for multi-project). Requires mcp:work_items:create permission. ' +
|
|
1461
1541
|
'Agents: work you file lands unassigned in the backlog, whatever status you ask for, and waits there for the Delivery Lead to approve and assign it. ' +
|
|
1542
|
+
'ORDERED WORK: when you file a set of items that must happen in order, give each one depends_on ' +
|
|
1543
|
+
'naming the reference numbers it follows, rather than writing "Follows #2322" into the description — ' +
|
|
1544
|
+
'that way the board knows the order and the pickup gate enforces it. ' +
|
|
1462
1545
|
CONTENT_LINKING_HELP,
|
|
1463
1546
|
inputSchema: {
|
|
1464
1547
|
type: 'object',
|
|
@@ -1508,6 +1591,11 @@ class WolfpackMCPServer {
|
|
|
1508
1591
|
type: 'string',
|
|
1509
1592
|
description: 'Link to a radar/initiative item. Accepts refId (e.g. "5" or "#r5") or UUID.',
|
|
1510
1593
|
},
|
|
1594
|
+
depends_on: {
|
|
1595
|
+
type: 'array',
|
|
1596
|
+
items: { type: ['number', 'string'] },
|
|
1597
|
+
description: 'Reference numbers of work items that must finish before this one starts, as 2322 or "#2322". Filing an ordered set one call each needs mcp:work_items:manage_dependencies.',
|
|
1598
|
+
},
|
|
1511
1599
|
},
|
|
1512
1600
|
required: ['title'],
|
|
1513
1601
|
},
|
|
@@ -1553,6 +1641,10 @@ class WolfpackMCPServer {
|
|
|
1553
1641
|
{
|
|
1554
1642
|
name: 'update_issue',
|
|
1555
1643
|
description: 'Update an existing issue. Requires mcp:issues:update permission. ' +
|
|
1644
|
+
'TAGS: pass `tags` (names from list_tags) to replace the whole tag set; an ' +
|
|
1645
|
+
'empty array clears it. Tagging an issue that is not assigned to you needs ' +
|
|
1646
|
+
'mcp:issues:tag_all, and that scope allows a tags-only update — send any other ' +
|
|
1647
|
+
'field alongside and the usual assignment rule applies. ' +
|
|
1556
1648
|
CONTENT_LINKING_HELP,
|
|
1557
1649
|
inputSchema: {
|
|
1558
1650
|
type: 'object',
|
|
@@ -1592,6 +1684,11 @@ class WolfpackMCPServer {
|
|
|
1592
1684
|
steps_to_reproduce: { type: 'string', description: 'Steps to reproduce' },
|
|
1593
1685
|
expected_behavior: { type: 'string', description: 'Expected behavior' },
|
|
1594
1686
|
actual_behavior: { type: 'string', description: 'Actual behavior' },
|
|
1687
|
+
tags: {
|
|
1688
|
+
type: 'array',
|
|
1689
|
+
items: { type: 'string' },
|
|
1690
|
+
description: 'Tag names to apply (replaces existing tags). Use list_tags to see available tags.',
|
|
1691
|
+
},
|
|
1595
1692
|
project_slug: {
|
|
1596
1693
|
type: 'string',
|
|
1597
1694
|
description: 'Project slug (required for multi-project users, use list_projects to get slugs)',
|
|
@@ -2787,6 +2884,48 @@ class WolfpackMCPServer {
|
|
|
2787
2884
|
],
|
|
2788
2885
|
};
|
|
2789
2886
|
}
|
|
2887
|
+
case 'set_work_item_dependencies': {
|
|
2888
|
+
const parsed = SetWorkItemDependenciesSchema.parse(args);
|
|
2889
|
+
const teamSlug = parsed.project_slug || this.client.getProjectSlug() || undefined;
|
|
2890
|
+
const dependencies = await this.client.setWorkItemDependencies(parsed.work_item_id, parsed.depends_on, teamSlug);
|
|
2891
|
+
const name = (items) => items.map((item) => `#${item.refId} "${item.title}"`).join(', ');
|
|
2892
|
+
const summary = dependencies.dependsOn.length === 0
|
|
2893
|
+
? `#${parsed.work_item_id} now depends on nothing`
|
|
2894
|
+
: `#${parsed.work_item_id} now depends on ${name(dependencies.dependsOn)}` +
|
|
2895
|
+
(dependencies.blockedBy.length > 0
|
|
2896
|
+
? `, and cannot start until ${name(dependencies.blockedBy)} finishes`
|
|
2897
|
+
: ', all of which have finished');
|
|
2898
|
+
return {
|
|
2899
|
+
content: [
|
|
2900
|
+
{
|
|
2901
|
+
type: 'text',
|
|
2902
|
+
text: `${summary}\n\n${JSON.stringify(stripUuids(dependencies), null, 2)}`,
|
|
2903
|
+
},
|
|
2904
|
+
],
|
|
2905
|
+
};
|
|
2906
|
+
}
|
|
2907
|
+
case 'get_work_item_dependency_graph': {
|
|
2908
|
+
const parsed = GetWorkItemDependencyGraphSchema.parse(args);
|
|
2909
|
+
const teamSlug = parsed.project_slug || this.client.getProjectSlug() || undefined;
|
|
2910
|
+
const graph = await this.client.getWorkItemDependencyGraph(parsed.work_item_id, teamSlug);
|
|
2911
|
+
// Edges name nodes by UUID, which agents never see, so they are
|
|
2912
|
+
// rewritten as reference numbers before the UUIDs are stripped —
|
|
2913
|
+
// dropping them would leave a list of items and no order at all
|
|
2914
|
+
const byId = new Map(graph.nodes.map((node) => [node.id, node.refId]));
|
|
2915
|
+
return {
|
|
2916
|
+
content: [
|
|
2917
|
+
{
|
|
2918
|
+
type: 'text',
|
|
2919
|
+
text: JSON.stringify({
|
|
2920
|
+
root: `#${byId.get(graph.rootId)}`,
|
|
2921
|
+
items: stripUuids(graph.nodes),
|
|
2922
|
+
// Each entry reads "A must finish before B can start"
|
|
2923
|
+
mustFinishBefore: graph.edges.map((edge) => `#${byId.get(edge.from)} → #${byId.get(edge.to)}`),
|
|
2924
|
+
}, null, 2),
|
|
2925
|
+
},
|
|
2926
|
+
],
|
|
2927
|
+
};
|
|
2928
|
+
}
|
|
2790
2929
|
// Radar Item handlers
|
|
2791
2930
|
case 'list_radar_items': {
|
|
2792
2931
|
const parsed = ListRadarItemsSchema.parse(args);
|
|
@@ -2906,6 +3045,7 @@ class WolfpackMCPServer {
|
|
|
2906
3045
|
leadingUserId: parsed.leading_user_id,
|
|
2907
3046
|
categoryId: parsed.category_id,
|
|
2908
3047
|
radarItemId,
|
|
3048
|
+
dependsOnRefIds: parsed.depends_on,
|
|
2909
3049
|
teamSlug,
|
|
2910
3050
|
});
|
|
2911
3051
|
return {
|
|
@@ -2959,6 +3099,7 @@ class WolfpackMCPServer {
|
|
|
2959
3099
|
stepsToReproduce: parsed.steps_to_reproduce,
|
|
2960
3100
|
expectedBehavior: parsed.expected_behavior,
|
|
2961
3101
|
actualBehavior: parsed.actual_behavior,
|
|
3102
|
+
tags: parsed.tags,
|
|
2962
3103
|
}, teamSlug);
|
|
2963
3104
|
return {
|
|
2964
3105
|
content: [
|