wolfpack-mcp 1.0.37 → 1.0.39
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/apiClient.js +16 -6
- package/dist/client.js +74 -12
- package/dist/index.js +321 -73
- package/package.json +1 -1
package/dist/apiClient.js
CHANGED
|
@@ -8,6 +8,16 @@ export class ApiError extends Error {
|
|
|
8
8
|
this.name = 'ApiError';
|
|
9
9
|
}
|
|
10
10
|
}
|
|
11
|
+
function formatError(error) {
|
|
12
|
+
if (error instanceof Error) {
|
|
13
|
+
const code = error.code;
|
|
14
|
+
if (code)
|
|
15
|
+
return `${error.message} (${code})`;
|
|
16
|
+
if (error.message)
|
|
17
|
+
return error.message;
|
|
18
|
+
}
|
|
19
|
+
return String(error) || 'unknown error';
|
|
20
|
+
}
|
|
11
21
|
export class ApiClient {
|
|
12
22
|
headers = {
|
|
13
23
|
Authorization: `Bearer ${config.apiKey}`,
|
|
@@ -30,7 +40,7 @@ export class ApiClient {
|
|
|
30
40
|
if (error instanceof ApiError) {
|
|
31
41
|
throw error;
|
|
32
42
|
}
|
|
33
|
-
throw new Error(`Failed to GET ${path}: ${error}`);
|
|
43
|
+
throw new Error(`Failed to GET ${path}: ${formatError(error)}`);
|
|
34
44
|
}
|
|
35
45
|
}
|
|
36
46
|
async post(path, body) {
|
|
@@ -51,7 +61,7 @@ export class ApiClient {
|
|
|
51
61
|
if (error instanceof ApiError) {
|
|
52
62
|
throw error;
|
|
53
63
|
}
|
|
54
|
-
throw new Error(`Failed to POST ${path}: ${error}`);
|
|
64
|
+
throw new Error(`Failed to POST ${path}: ${formatError(error)}`);
|
|
55
65
|
}
|
|
56
66
|
}
|
|
57
67
|
async put(path, body) {
|
|
@@ -72,7 +82,7 @@ export class ApiClient {
|
|
|
72
82
|
if (error instanceof ApiError) {
|
|
73
83
|
throw error;
|
|
74
84
|
}
|
|
75
|
-
throw new Error(`Failed to PUT ${path}: ${error}`);
|
|
85
|
+
throw new Error(`Failed to PUT ${path}: ${formatError(error)}`);
|
|
76
86
|
}
|
|
77
87
|
}
|
|
78
88
|
async patch(path, body) {
|
|
@@ -93,7 +103,7 @@ export class ApiClient {
|
|
|
93
103
|
if (error instanceof ApiError) {
|
|
94
104
|
throw error;
|
|
95
105
|
}
|
|
96
|
-
throw new Error(`Failed to PATCH ${path}: ${error}`);
|
|
106
|
+
throw new Error(`Failed to PATCH ${path}: ${formatError(error)}`);
|
|
97
107
|
}
|
|
98
108
|
}
|
|
99
109
|
async getBuffer(path) {
|
|
@@ -119,7 +129,7 @@ export class ApiClient {
|
|
|
119
129
|
if (error instanceof ApiError) {
|
|
120
130
|
throw error;
|
|
121
131
|
}
|
|
122
|
-
throw new Error(`Failed to GET buffer ${path}: ${error}`);
|
|
132
|
+
throw new Error(`Failed to GET buffer ${path}: ${formatError(error)}`);
|
|
123
133
|
}
|
|
124
134
|
}
|
|
125
135
|
async postMultipart(path, buffer, filename, mimeType) {
|
|
@@ -166,7 +176,7 @@ export class ApiClient {
|
|
|
166
176
|
if (error instanceof ApiError) {
|
|
167
177
|
throw error;
|
|
168
178
|
}
|
|
169
|
-
throw new Error(`Failed to DELETE ${path}: ${error}`);
|
|
179
|
+
throw new Error(`Failed to DELETE ${path}: ${formatError(error)}`);
|
|
170
180
|
}
|
|
171
181
|
}
|
|
172
182
|
}
|
package/dist/client.js
CHANGED
|
@@ -9,6 +9,14 @@ export class WolfpackClient {
|
|
|
9
9
|
constructor() {
|
|
10
10
|
this.api = new ApiClient();
|
|
11
11
|
}
|
|
12
|
+
/** Build a URL path with optional teamSlug query parameter. */
|
|
13
|
+
withTeamSlug(path, teamSlug) {
|
|
14
|
+
const slug = teamSlug || this.projectSlug;
|
|
15
|
+
if (!slug)
|
|
16
|
+
return path;
|
|
17
|
+
const sep = path.includes('?') ? '&' : '?';
|
|
18
|
+
return `${path}${sep}teamSlug=${encodeURIComponent(slug)}`;
|
|
19
|
+
}
|
|
12
20
|
/**
|
|
13
21
|
* Fetch and cache the project slug by verifying it exists.
|
|
14
22
|
* Uses the MCP team endpoint to validate the slug.
|
|
@@ -158,7 +166,7 @@ export class WolfpackClient {
|
|
|
158
166
|
}
|
|
159
167
|
async updateWorkProgress(workItemId, description) {
|
|
160
168
|
try {
|
|
161
|
-
return await this.api.put(`/work-items/${workItemId}/progress
|
|
169
|
+
return await this.api.put(this.withTeamSlug(`/work-items/${workItemId}/progress`), {
|
|
162
170
|
description,
|
|
163
171
|
});
|
|
164
172
|
}
|
|
@@ -171,7 +179,9 @@ export class WolfpackClient {
|
|
|
171
179
|
}
|
|
172
180
|
async updateWorkItemStatus(workItemId, status) {
|
|
173
181
|
try {
|
|
174
|
-
return await this.api.put(`/work-items/${workItemId}/status
|
|
182
|
+
return await this.api.put(this.withTeamSlug(`/work-items/${workItemId}/status`), {
|
|
183
|
+
status,
|
|
184
|
+
});
|
|
175
185
|
}
|
|
176
186
|
catch (error) {
|
|
177
187
|
if (error && typeof error === 'object' && 'status' in error && error.status === 404) {
|
|
@@ -182,7 +192,7 @@ export class WolfpackClient {
|
|
|
182
192
|
}
|
|
183
193
|
async updateWorkItemAssignee(workItemId, data) {
|
|
184
194
|
try {
|
|
185
|
-
return await this.api.put(`/work-items/${workItemId}/assignee
|
|
195
|
+
return await this.api.put(this.withTeamSlug(`/work-items/${workItemId}/assignee`), data);
|
|
186
196
|
}
|
|
187
197
|
catch (error) {
|
|
188
198
|
if (error && typeof error === 'object' && 'status' in error && error.status === 404) {
|
|
@@ -193,7 +203,20 @@ export class WolfpackClient {
|
|
|
193
203
|
}
|
|
194
204
|
async updateWorkItemTitle(workItemId, title) {
|
|
195
205
|
try {
|
|
196
|
-
return await this.api.put(`/work-items/${workItemId}/title
|
|
206
|
+
return await this.api.put(this.withTeamSlug(`/work-items/${workItemId}/title`), {
|
|
207
|
+
title,
|
|
208
|
+
});
|
|
209
|
+
}
|
|
210
|
+
catch (error) {
|
|
211
|
+
if (error && typeof error === 'object' && 'status' in error && error.status === 404) {
|
|
212
|
+
return null;
|
|
213
|
+
}
|
|
214
|
+
throw error;
|
|
215
|
+
}
|
|
216
|
+
}
|
|
217
|
+
async updateWorkItemInitiative(workItemId, radarItemId) {
|
|
218
|
+
try {
|
|
219
|
+
return await this.api.put(this.withTeamSlug(`/work-items/${workItemId}/initiative`), { radarItemId });
|
|
197
220
|
}
|
|
198
221
|
catch (error) {
|
|
199
222
|
if (error && typeof error === 'object' && 'status' in error && error.status === 404) {
|
|
@@ -204,7 +227,20 @@ export class WolfpackClient {
|
|
|
204
227
|
}
|
|
205
228
|
async pullWorkItem(workItemId, data) {
|
|
206
229
|
try {
|
|
207
|
-
return await this.api.post(`/work-items/${workItemId}/pull
|
|
230
|
+
return await this.api.post(this.withTeamSlug(`/work-items/${workItemId}/pull`), data || {});
|
|
231
|
+
}
|
|
232
|
+
catch (error) {
|
|
233
|
+
if (error && typeof error === 'object' && 'status' in error && error.status === 404) {
|
|
234
|
+
return null;
|
|
235
|
+
}
|
|
236
|
+
throw error;
|
|
237
|
+
}
|
|
238
|
+
}
|
|
239
|
+
async submitWorkItemForm(workItemId, formValues) {
|
|
240
|
+
try {
|
|
241
|
+
return await this.api.put(this.withTeamSlug(`/work-items/${workItemId}/form`), {
|
|
242
|
+
formValues,
|
|
243
|
+
});
|
|
208
244
|
}
|
|
209
245
|
catch (error) {
|
|
210
246
|
if (error && typeof error === 'object' && 'status' in error && error.status === 404) {
|
|
@@ -325,7 +361,7 @@ export class WolfpackClient {
|
|
|
325
361
|
return this.api.post('/issues', { ...rest, teamSlug });
|
|
326
362
|
}
|
|
327
363
|
async updateIssue(issueId, data) {
|
|
328
|
-
return this.api.patch(`/issues/${issueId}
|
|
364
|
+
return this.api.patch(this.withTeamSlug(`/issues/${issueId}`), data);
|
|
329
365
|
}
|
|
330
366
|
// Wiki Page methods
|
|
331
367
|
async listWikiPages(options) {
|
|
@@ -374,7 +410,7 @@ export class WolfpackClient {
|
|
|
374
410
|
return this.api.post('/wiki-pages', { ...rest, teamSlug });
|
|
375
411
|
}
|
|
376
412
|
async updateWikiPage(pageId, data) {
|
|
377
|
-
return this.api.patch(`/wiki-pages/${pageId}
|
|
413
|
+
return this.api.patch(this.withTeamSlug(`/wiki-pages/${pageId}`), data);
|
|
378
414
|
}
|
|
379
415
|
// Journal Entry methods
|
|
380
416
|
async listJournalEntries(options) {
|
|
@@ -423,20 +459,20 @@ export class WolfpackClient {
|
|
|
423
459
|
return this.api.post('/journal-entries', { ...rest, teamSlug });
|
|
424
460
|
}
|
|
425
461
|
async updateJournalEntry(entryId, data) {
|
|
426
|
-
return this.api.patch(`/journal-entries/${entryId}
|
|
462
|
+
return this.api.patch(this.withTeamSlug(`/journal-entries/${entryId}`), data);
|
|
427
463
|
}
|
|
428
464
|
// Comment methods
|
|
429
465
|
async listWorkItemComments(workItemId) {
|
|
430
|
-
return this.api.get(`/work-items/${workItemId}/comments`);
|
|
466
|
+
return this.api.get(this.withTeamSlug(`/work-items/${workItemId}/comments`));
|
|
431
467
|
}
|
|
432
468
|
async listIssueComments(issueId) {
|
|
433
|
-
return this.api.get(`/issues/${issueId}/comments`);
|
|
469
|
+
return this.api.get(this.withTeamSlug(`/issues/${issueId}/comments`));
|
|
434
470
|
}
|
|
435
471
|
async createWorkItemComment(workItemId, data) {
|
|
436
|
-
return this.api.post(`/work-items/${workItemId}/comments
|
|
472
|
+
return this.api.post(this.withTeamSlug(`/work-items/${workItemId}/comments`), data);
|
|
437
473
|
}
|
|
438
474
|
async createIssueComment(issueId, data) {
|
|
439
|
-
return this.api.post(`/issues/${issueId}/comments
|
|
475
|
+
return this.api.post(this.withTeamSlug(`/issues/${issueId}/comments`), data);
|
|
440
476
|
}
|
|
441
477
|
/**
|
|
442
478
|
* Upload an image and get back a URL that can be used in markdown content.
|
|
@@ -452,6 +488,32 @@ export class WolfpackClient {
|
|
|
452
488
|
const { buffer, contentType } = await this.api.getBuffer(`/images/${team}/${filename}`);
|
|
453
489
|
return { base64: buffer.toString('base64'), mimeType: contentType };
|
|
454
490
|
}
|
|
491
|
+
// Skill methods (progressive disclosure)
|
|
492
|
+
async listSkills() {
|
|
493
|
+
return this.api.get('/skills');
|
|
494
|
+
}
|
|
495
|
+
async getSkill(name) {
|
|
496
|
+
try {
|
|
497
|
+
return await this.api.get(`/skills/${encodeURIComponent(name)}`);
|
|
498
|
+
}
|
|
499
|
+
catch (error) {
|
|
500
|
+
if (error && typeof error === 'object' && 'status' in error && error.status === 404) {
|
|
501
|
+
return null;
|
|
502
|
+
}
|
|
503
|
+
throw error;
|
|
504
|
+
}
|
|
505
|
+
}
|
|
506
|
+
async getSkillResource(skillName, resourceName) {
|
|
507
|
+
try {
|
|
508
|
+
return await this.api.get(`/skills/${encodeURIComponent(skillName)}/resources/${encodeURIComponent(resourceName)}`);
|
|
509
|
+
}
|
|
510
|
+
catch (error) {
|
|
511
|
+
if (error && typeof error === 'object' && 'status' in error && error.status === 404) {
|
|
512
|
+
return null;
|
|
513
|
+
}
|
|
514
|
+
throw error;
|
|
515
|
+
}
|
|
516
|
+
}
|
|
455
517
|
close() {
|
|
456
518
|
// No cleanup needed for API client
|
|
457
519
|
}
|
package/dist/index.js
CHANGED
|
@@ -43,6 +43,12 @@ async function checkForUpdates() {
|
|
|
43
43
|
}
|
|
44
44
|
return null;
|
|
45
45
|
}
|
|
46
|
+
// Cross-reference syntax for linking between content items in markdown fields
|
|
47
|
+
const CONTENT_LINKING_HELP = 'CROSS-REFERENCES: In any markdown content, you can link to other items using these patterns: ' +
|
|
48
|
+
'#123 or #w123 for work items, #i123 for issues, #r123 for initiatives/roadmap, ' +
|
|
49
|
+
'#j123 for journal entries, #c123 for cases, #p123 for procedures. ' +
|
|
50
|
+
'Use @username to mention team members (triggers notifications). ' +
|
|
51
|
+
'Standard markdown links also work: [link text](/project/{slug}/work-items/123).';
|
|
46
52
|
// Work Item schemas
|
|
47
53
|
// Use z.coerce.string() to handle any type coercion issues from MCP args
|
|
48
54
|
const ListWorkItemsSchema = z.object({
|
|
@@ -84,7 +90,7 @@ const ListWorkItemsSchema = z.object({
|
|
|
84
90
|
offset: z.number().optional().describe('Number of items to skip'),
|
|
85
91
|
});
|
|
86
92
|
const GetWorkItemSchema = z.object({
|
|
87
|
-
work_item_id: z.string().describe('The
|
|
93
|
+
work_item_id: z.string().describe('The refId (number) of the work item'),
|
|
88
94
|
project_slug: z.string().optional().describe('Project slug (required when looking up by refId)'),
|
|
89
95
|
});
|
|
90
96
|
const UpdateWorkProgressSchema = z.object({
|
|
@@ -117,6 +123,13 @@ const UpdateWorkItemTitleSchema = z.object({
|
|
|
117
123
|
work_item_id: z.string().describe('The ID of the work item'),
|
|
118
124
|
title: z.string().describe('New title for the work item'),
|
|
119
125
|
});
|
|
126
|
+
const UpdateWorkItemInitiativeSchema = z.object({
|
|
127
|
+
work_item_id: z.string().describe('The ID of the work item'),
|
|
128
|
+
radar_item_id: z
|
|
129
|
+
.string()
|
|
130
|
+
.nullable()
|
|
131
|
+
.describe('Radar/initiative item ID to link to, or null to unlink'),
|
|
132
|
+
});
|
|
120
133
|
const PullWorkItemSchema = z.object({
|
|
121
134
|
work_item_id: z.string().describe('The ID of the work item to pull from backlog'),
|
|
122
135
|
leading_user_id: z
|
|
@@ -124,6 +137,10 @@ const PullWorkItemSchema = z.object({
|
|
|
124
137
|
.optional()
|
|
125
138
|
.describe('User ID to assign as leading user (defaults to API key owner)'),
|
|
126
139
|
});
|
|
140
|
+
const SubmitWorkItemFormSchema = z.object({
|
|
141
|
+
work_item_id: z.string().describe('The ID of the work item'),
|
|
142
|
+
form_values: z.record(z.any()).describe('Key-value pairs matching formDefinition field names'),
|
|
143
|
+
});
|
|
127
144
|
// Radar Item (Initiative/Roadmap) schemas
|
|
128
145
|
const ListRadarItemsSchema = z.object({
|
|
129
146
|
project_slug: z.string().optional().describe('Project slug to filter radar items'),
|
|
@@ -136,7 +153,7 @@ const ListRadarItemsSchema = z.object({
|
|
|
136
153
|
offset: z.number().optional().describe('Number of items to skip'),
|
|
137
154
|
});
|
|
138
155
|
const GetRadarItemSchema = z.object({
|
|
139
|
-
item_id: z.string().describe('The
|
|
156
|
+
item_id: z.string().describe('The refId (number) of the radar item'),
|
|
140
157
|
project_slug: z.string().optional().describe('Project slug (required when looking up by refId)'),
|
|
141
158
|
});
|
|
142
159
|
// Issue schemas
|
|
@@ -173,7 +190,7 @@ const ListIssuesSchema = z.object({
|
|
|
173
190
|
offset: z.number().optional().describe('Number of items to skip'),
|
|
174
191
|
});
|
|
175
192
|
const GetIssueSchema = z.object({
|
|
176
|
-
issue_id: z.string().describe('The
|
|
193
|
+
issue_id: z.string().describe('The refId (number) of the issue'),
|
|
177
194
|
project_slug: z.string().optional().describe('Project slug (required when looking up by refId)'),
|
|
178
195
|
});
|
|
179
196
|
// Create schemas
|
|
@@ -189,6 +206,10 @@ const CreateWorkItemSchema = z.object({
|
|
|
189
206
|
.optional()
|
|
190
207
|
.describe('Initial status: "pending" (backlog), "new" (to do), "doing", "review", "ready", "blocked", "completed". Defaults to "new".'),
|
|
191
208
|
priority: z.number().optional().describe('Priority level (0-4, higher is more important)'),
|
|
209
|
+
size: z
|
|
210
|
+
.enum(['S', 'M', 'L'])
|
|
211
|
+
.optional()
|
|
212
|
+
.describe('Size estimate: "S" (small), "M" (medium), "L" (large)'),
|
|
192
213
|
leading_user_id: z.string().optional().describe('User ID to assign as leading user'),
|
|
193
214
|
category_id: z.string().optional().describe('Category ID to organize the work item'),
|
|
194
215
|
radar_item_id: z.string().optional().describe('Radar/initiative item ID to link to'),
|
|
@@ -214,7 +235,7 @@ const CreateIssueSchema = z.object({
|
|
|
214
235
|
actual_behavior: z.string().optional().describe('Actual behavior observed'),
|
|
215
236
|
});
|
|
216
237
|
const UpdateIssueSchema = z.object({
|
|
217
|
-
issue_id: z.string().describe('The
|
|
238
|
+
issue_id: z.string().describe('The refId (number) of the issue to update'),
|
|
218
239
|
title: z.string().optional().describe('Updated title'),
|
|
219
240
|
description: z.string().optional().describe('Updated description'),
|
|
220
241
|
status: z
|
|
@@ -241,7 +262,7 @@ const ListWikiPagesSchema = z.object({
|
|
|
241
262
|
offset: z.number().optional().describe('Number of pages to skip'),
|
|
242
263
|
});
|
|
243
264
|
const GetWikiPageSchema = z.object({
|
|
244
|
-
page_id: z.string().describe('The page
|
|
265
|
+
page_id: z.string().describe('The page slug'),
|
|
245
266
|
});
|
|
246
267
|
const CreateWikiPageSchema = z.object({
|
|
247
268
|
project_slug: z
|
|
@@ -260,7 +281,7 @@ const CreateWikiPageSchema = z.object({
|
|
|
260
281
|
content: z.string().describe('Page content (markdown)'),
|
|
261
282
|
});
|
|
262
283
|
const UpdateWikiPageSchema = z.object({
|
|
263
|
-
page_id: z.string().describe('The page
|
|
284
|
+
page_id: z.string().describe('The page slug'),
|
|
264
285
|
title: z.string().optional().describe('Updated title'),
|
|
265
286
|
content: z.string().optional().describe('Updated content (markdown)'),
|
|
266
287
|
});
|
|
@@ -280,8 +301,8 @@ const ListJournalEntriesSchema = z.object({
|
|
|
280
301
|
offset: z.number().optional().describe('Number of entries to skip'),
|
|
281
302
|
});
|
|
282
303
|
const GetJournalEntrySchema = z.object({
|
|
283
|
-
entry_id: z.string().describe('The entry
|
|
284
|
-
project_slug: z.string().optional().describe('Project slug (required
|
|
304
|
+
entry_id: z.string().describe('The entry refId (number)'),
|
|
305
|
+
project_slug: z.string().optional().describe('Project slug (required for refId lookup)'),
|
|
285
306
|
});
|
|
286
307
|
const CreateJournalEntrySchema = z.object({
|
|
287
308
|
project_slug: z
|
|
@@ -290,26 +311,25 @@ const CreateJournalEntrySchema = z.object({
|
|
|
290
311
|
.describe('Project slug (required for multi-project users, use list_projects to get slugs)'),
|
|
291
312
|
title: z.string().describe('Entry title'),
|
|
292
313
|
content: z.string().describe('Entry content (markdown)'),
|
|
293
|
-
date: z.string().optional().describe('Entry date (ISO format, defaults to now)'),
|
|
294
314
|
});
|
|
295
315
|
const UpdateJournalEntrySchema = z.object({
|
|
296
|
-
entry_id: z.string().describe('The entry
|
|
316
|
+
entry_id: z.string().describe('The entry refId (number)'),
|
|
297
317
|
title: z.string().optional().describe('Updated title'),
|
|
298
318
|
content: z.string().optional().describe('Updated content (markdown)'),
|
|
299
319
|
});
|
|
300
320
|
// Comment schemas
|
|
301
321
|
const ListWorkItemCommentsSchema = z.object({
|
|
302
|
-
work_item_id: z.string().describe('The work item
|
|
322
|
+
work_item_id: z.string().describe('The work item refId (number)'),
|
|
303
323
|
});
|
|
304
324
|
const ListIssueCommentsSchema = z.object({
|
|
305
|
-
issue_id: z.string().describe('The issue
|
|
325
|
+
issue_id: z.string().describe('The issue refId (number)'),
|
|
306
326
|
});
|
|
307
327
|
const CreateWorkItemCommentSchema = z.object({
|
|
308
|
-
work_item_id: z.string().describe('The work item
|
|
328
|
+
work_item_id: z.string().describe('The work item refId (number)'),
|
|
309
329
|
content: z.string().describe('Comment content (markdown)'),
|
|
310
330
|
});
|
|
311
331
|
const CreateIssueCommentSchema = z.object({
|
|
312
|
-
issue_id: z.string().describe('The issue
|
|
332
|
+
issue_id: z.string().describe('The issue refId (number)'),
|
|
313
333
|
content: z.string().describe('Comment content (markdown)'),
|
|
314
334
|
});
|
|
315
335
|
// Image upload schema
|
|
@@ -328,6 +348,54 @@ const DownloadImageSchema = z.object({
|
|
|
328
348
|
.string()
|
|
329
349
|
.describe('The image URL path found in content fields (e.g. "/api/files/images/{team}/{filename}").'),
|
|
330
350
|
});
|
|
351
|
+
// Skill schemas
|
|
352
|
+
const GetSkillSchema = z.object({
|
|
353
|
+
skill_name: z.string().describe('The name of the skill to load (e.g. "deploy-app")'),
|
|
354
|
+
});
|
|
355
|
+
const GetSkillResourceSchema = z.object({
|
|
356
|
+
skill_name: z.string().describe('The name of the skill'),
|
|
357
|
+
resource_name: z.string().describe('The name of the resource file'),
|
|
358
|
+
});
|
|
359
|
+
// UUID v4 field names to remove from responses.
|
|
360
|
+
// These are internal database IDs that agents should not use.
|
|
361
|
+
// Agents should use refId (sequential int) or slug instead.
|
|
362
|
+
const UUID_FIELDS_TO_STRIP = new Set([
|
|
363
|
+
'id', // Main entity UUID - replaced by refId or slug
|
|
364
|
+
'teamId', // Internal team UUID - noise for agents
|
|
365
|
+
'workItemId', // Cross-reference UUID on Issues - noise
|
|
366
|
+
]);
|
|
367
|
+
// Fields containing user-defined data that should never be recursively processed.
|
|
368
|
+
const PASSTHROUGH_FIELDS = new Set(['formDefinition', 'formValues']);
|
|
369
|
+
// Strip UUID v4 fields from response objects so agents use refId/slug instead.
|
|
370
|
+
// Preserves Clerk user IDs (user_xxx format) and operational fields (categoryId, radarItemId).
|
|
371
|
+
function stripUuids(obj) {
|
|
372
|
+
if (obj === null || obj === undefined)
|
|
373
|
+
return obj;
|
|
374
|
+
if (Array.isArray(obj))
|
|
375
|
+
return obj.map(stripUuids);
|
|
376
|
+
if (typeof obj !== 'object')
|
|
377
|
+
return obj;
|
|
378
|
+
const record = obj;
|
|
379
|
+
const result = {};
|
|
380
|
+
for (const [key, value] of Object.entries(record)) {
|
|
381
|
+
// Skip UUID fields
|
|
382
|
+
if (UUID_FIELDS_TO_STRIP.has(key))
|
|
383
|
+
continue;
|
|
384
|
+
// Preserve user-defined data fields as-is (no recursive stripping)
|
|
385
|
+
if (PASSTHROUGH_FIELDS.has(key)) {
|
|
386
|
+
result[key] = value;
|
|
387
|
+
continue;
|
|
388
|
+
}
|
|
389
|
+
// Recurse into nested objects/arrays
|
|
390
|
+
if (typeof value === 'object' && value !== null) {
|
|
391
|
+
result[key] = stripUuids(value);
|
|
392
|
+
}
|
|
393
|
+
else {
|
|
394
|
+
result[key] = value;
|
|
395
|
+
}
|
|
396
|
+
}
|
|
397
|
+
return result;
|
|
398
|
+
}
|
|
331
399
|
// Helper to detect if a work item description contains a plan
|
|
332
400
|
function hasPlan(description) {
|
|
333
401
|
if (!description)
|
|
@@ -443,22 +511,23 @@ class WolfpackMCPServer {
|
|
|
443
511
|
},
|
|
444
512
|
{
|
|
445
513
|
name: 'get_work_item',
|
|
446
|
-
description: 'Get a specific work item/task by
|
|
514
|
+
description: 'Get a specific work item/task by reference number. Returns full details including description (markdown notes). ' +
|
|
447
515
|
'Call this before updating to see current content. ' +
|
|
448
516
|
'WORKFLOW: When asked to work on an item, check its status and follow the required state transitions ' +
|
|
449
517
|
'(pending→pull first, new→doing, blocked/ready/completed/closed→new→doing, then review when done). ' +
|
|
450
518
|
'PLANNING: Check if the description contains a plan (markdown checklist). If not, APPEND one using update_work_progress - preserve all original description text and add your plan below a "---" separator. ' +
|
|
519
|
+
'FORMS: Procedure-created work items may include formDefinition (field definitions with name, label, type, required, options) and formValues (current values). Use submit_work_item_form to fill in form values. ' +
|
|
451
520
|
'IMAGES: Image references in the description (e.g. ``) can be viewed using the download_image tool.',
|
|
452
521
|
inputSchema: {
|
|
453
522
|
type: 'object',
|
|
454
523
|
properties: {
|
|
455
524
|
work_item_id: {
|
|
456
525
|
type: 'string',
|
|
457
|
-
description: 'The
|
|
526
|
+
description: 'The refId (number) of the work item',
|
|
458
527
|
},
|
|
459
528
|
project_slug: {
|
|
460
529
|
type: 'string',
|
|
461
|
-
description: 'Project slug (required
|
|
530
|
+
description: 'Project slug (required for refId lookup)',
|
|
462
531
|
},
|
|
463
532
|
},
|
|
464
533
|
required: ['work_item_id'],
|
|
@@ -468,7 +537,8 @@ class WolfpackMCPServer {
|
|
|
468
537
|
name: 'update_work_progress',
|
|
469
538
|
description: 'Update work item description/notes with your progress. WORKFLOW: 1) get_work_item to read current notes 2) Modify the markdown description with new findings/progress 3) Call this with the complete updated description. The full description replaces the existing one. ' +
|
|
470
539
|
'CRITICAL: NEVER overwrite or remove the original description text. Preserve all existing content exactly as-is. Append your plan below a "---" separator. You may only modify content you previously added (your plan section). ' +
|
|
471
|
-
'BEST PRACTICE: Append a plan with markdown checkboxes (- [ ] task). Check off completed tasks (- [x] task) as you progress. Include sections for: Plan (checklist), Approach (strategy), and Notes (discoveries/decisions).'
|
|
540
|
+
'BEST PRACTICE: Append a plan with markdown checkboxes (- [ ] task). Check off completed tasks (- [x] task) as you progress. Include sections for: Plan (checklist), Approach (strategy), and Notes (discoveries/decisions). ' +
|
|
541
|
+
CONTENT_LINKING_HELP,
|
|
472
542
|
inputSchema: {
|
|
473
543
|
type: 'object',
|
|
474
544
|
properties: {
|
|
@@ -557,6 +627,25 @@ class WolfpackMCPServer {
|
|
|
557
627
|
required: ['work_item_id', 'title'],
|
|
558
628
|
},
|
|
559
629
|
},
|
|
630
|
+
{
|
|
631
|
+
name: 'update_work_item_initiative',
|
|
632
|
+
description: 'Link or unlink a work item to/from a radar item (initiative). ' +
|
|
633
|
+
'Pass a radar_item_id to link, or null to remove the initiative link.',
|
|
634
|
+
inputSchema: {
|
|
635
|
+
type: 'object',
|
|
636
|
+
properties: {
|
|
637
|
+
work_item_id: {
|
|
638
|
+
type: 'string',
|
|
639
|
+
description: 'The ID of the work item',
|
|
640
|
+
},
|
|
641
|
+
radar_item_id: {
|
|
642
|
+
type: ['string', 'null'],
|
|
643
|
+
description: 'Radar/initiative item ID to link to, or null to unlink',
|
|
644
|
+
},
|
|
645
|
+
},
|
|
646
|
+
required: ['work_item_id', 'radar_item_id'],
|
|
647
|
+
},
|
|
648
|
+
},
|
|
560
649
|
{
|
|
561
650
|
name: 'pull_work_item',
|
|
562
651
|
description: 'Pull a specific work item from the backlog to the board. ' +
|
|
@@ -580,6 +669,26 @@ class WolfpackMCPServer {
|
|
|
580
669
|
required: ['work_item_id'],
|
|
581
670
|
},
|
|
582
671
|
},
|
|
672
|
+
{
|
|
673
|
+
name: 'submit_work_item_form',
|
|
674
|
+
description: 'Submit form values for a procedure-created work item. ' +
|
|
675
|
+
'Use get_work_item first to see formDefinition (field names, types, required) and current formValues. ' +
|
|
676
|
+
'Then call this with form_values mapping field names to values.',
|
|
677
|
+
inputSchema: {
|
|
678
|
+
type: 'object',
|
|
679
|
+
properties: {
|
|
680
|
+
work_item_id: {
|
|
681
|
+
type: 'string',
|
|
682
|
+
description: 'The ID of the work item',
|
|
683
|
+
},
|
|
684
|
+
form_values: {
|
|
685
|
+
type: 'object',
|
|
686
|
+
description: 'Key-value pairs matching formDefinition field names',
|
|
687
|
+
},
|
|
688
|
+
},
|
|
689
|
+
required: ['work_item_id', 'form_values'],
|
|
690
|
+
},
|
|
691
|
+
},
|
|
583
692
|
// Radar Item (Initiative/Roadmap) tools
|
|
584
693
|
{
|
|
585
694
|
name: 'list_radar_items',
|
|
@@ -607,18 +716,18 @@ class WolfpackMCPServer {
|
|
|
607
716
|
},
|
|
608
717
|
{
|
|
609
718
|
name: 'get_radar_item',
|
|
610
|
-
description: 'Get a specific radar item (initiative) by
|
|
719
|
+
description: 'Get a specific radar item (initiative) by reference number, including its work items and participants. ' +
|
|
611
720
|
'IMAGES: Image references in the description (e.g. ``) can be viewed using the download_image tool.',
|
|
612
721
|
inputSchema: {
|
|
613
722
|
type: 'object',
|
|
614
723
|
properties: {
|
|
615
724
|
item_id: {
|
|
616
725
|
type: 'string',
|
|
617
|
-
description: 'The
|
|
726
|
+
description: 'The refId (number) of the radar item',
|
|
618
727
|
},
|
|
619
728
|
project_slug: {
|
|
620
729
|
type: 'string',
|
|
621
|
-
description: 'Project slug (required
|
|
730
|
+
description: 'Project slug (required for refId lookup)',
|
|
622
731
|
},
|
|
623
732
|
},
|
|
624
733
|
required: ['item_id'],
|
|
@@ -685,18 +794,18 @@ class WolfpackMCPServer {
|
|
|
685
794
|
},
|
|
686
795
|
{
|
|
687
796
|
name: 'get_issue',
|
|
688
|
-
description: 'Get a specific issue by
|
|
797
|
+
description: 'Get a specific issue by reference number, including comment and attachment counts. ' +
|
|
689
798
|
'IMAGES: Image references in the description (e.g. ``) can be viewed using the download_image tool.',
|
|
690
799
|
inputSchema: {
|
|
691
800
|
type: 'object',
|
|
692
801
|
properties: {
|
|
693
802
|
issue_id: {
|
|
694
803
|
type: 'string',
|
|
695
|
-
description: 'The
|
|
804
|
+
description: 'The refId (number) of the issue',
|
|
696
805
|
},
|
|
697
806
|
project_slug: {
|
|
698
807
|
type: 'string',
|
|
699
|
-
description: 'Project slug (required
|
|
808
|
+
description: 'Project slug (required for refId lookup)',
|
|
700
809
|
},
|
|
701
810
|
},
|
|
702
811
|
required: ['issue_id'],
|
|
@@ -705,7 +814,8 @@ class WolfpackMCPServer {
|
|
|
705
814
|
// Create/Update tools
|
|
706
815
|
{
|
|
707
816
|
name: 'create_work_item',
|
|
708
|
-
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.'
|
|
817
|
+
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. ' +
|
|
818
|
+
CONTENT_LINKING_HELP,
|
|
709
819
|
inputSchema: {
|
|
710
820
|
type: 'object',
|
|
711
821
|
properties: {
|
|
@@ -737,6 +847,11 @@ class WolfpackMCPServer {
|
|
|
737
847
|
type: 'number',
|
|
738
848
|
description: 'Priority level (0-4, higher is more important)',
|
|
739
849
|
},
|
|
850
|
+
size: {
|
|
851
|
+
type: 'string',
|
|
852
|
+
enum: ['S', 'M', 'L'],
|
|
853
|
+
description: 'Size estimate: "S" (small), "M" (medium), "L" (large)',
|
|
854
|
+
},
|
|
740
855
|
leading_user_id: {
|
|
741
856
|
type: 'string',
|
|
742
857
|
description: 'User ID to assign as leading user',
|
|
@@ -755,7 +870,8 @@ class WolfpackMCPServer {
|
|
|
755
870
|
},
|
|
756
871
|
{
|
|
757
872
|
name: 'create_issue',
|
|
758
|
-
description: 'Create a new issue in your current project (auto-selected for single-project users, or use list_projects first for multi-project). Requires mcp:issues:create permission.'
|
|
873
|
+
description: 'Create a new issue in your current project (auto-selected for single-project users, or use list_projects first for multi-project). Requires mcp:issues:create permission. ' +
|
|
874
|
+
CONTENT_LINKING_HELP,
|
|
759
875
|
inputSchema: {
|
|
760
876
|
type: 'object',
|
|
761
877
|
properties: {
|
|
@@ -788,11 +904,15 @@ class WolfpackMCPServer {
|
|
|
788
904
|
},
|
|
789
905
|
{
|
|
790
906
|
name: 'update_issue',
|
|
791
|
-
description: 'Update an existing issue. Requires mcp:issues:update permission.'
|
|
907
|
+
description: 'Update an existing issue. Requires mcp:issues:update permission. ' +
|
|
908
|
+
CONTENT_LINKING_HELP,
|
|
792
909
|
inputSchema: {
|
|
793
910
|
type: 'object',
|
|
794
911
|
properties: {
|
|
795
|
-
issue_id: {
|
|
912
|
+
issue_id: {
|
|
913
|
+
type: 'string',
|
|
914
|
+
description: 'The refId (number) of the issue to update',
|
|
915
|
+
},
|
|
796
916
|
title: { type: 'string', description: 'Updated title' },
|
|
797
917
|
description: { type: 'string', description: 'Updated description' },
|
|
798
918
|
status: {
|
|
@@ -844,14 +964,14 @@ class WolfpackMCPServer {
|
|
|
844
964
|
},
|
|
845
965
|
{
|
|
846
966
|
name: 'get_wiki_page',
|
|
847
|
-
description: 'Get a specific wiki/documentation page by
|
|
967
|
+
description: 'Get a specific wiki/documentation page by slug (URL path). Returns full content in markdown. ' +
|
|
848
968
|
'IMAGES: Image references in the content (e.g. ``) can be viewed using the download_image tool.',
|
|
849
969
|
inputSchema: {
|
|
850
970
|
type: 'object',
|
|
851
971
|
properties: {
|
|
852
972
|
page_id: {
|
|
853
973
|
type: 'string',
|
|
854
|
-
description: 'The page
|
|
974
|
+
description: 'The page slug (URL path like "getting-started")',
|
|
855
975
|
},
|
|
856
976
|
},
|
|
857
977
|
required: ['page_id'],
|
|
@@ -859,7 +979,8 @@ class WolfpackMCPServer {
|
|
|
859
979
|
},
|
|
860
980
|
{
|
|
861
981
|
name: 'create_wiki_page',
|
|
862
|
-
description: 'Create a new wiki/documentation page. Use when user wants to "add docs", "create documentation", or "write a guide".'
|
|
982
|
+
description: 'Create a new wiki/documentation page. Use when user wants to "add docs", "create documentation", or "write a guide". ' +
|
|
983
|
+
CONTENT_LINKING_HELP,
|
|
863
984
|
inputSchema: {
|
|
864
985
|
type: 'object',
|
|
865
986
|
properties: {
|
|
@@ -882,11 +1003,12 @@ class WolfpackMCPServer {
|
|
|
882
1003
|
},
|
|
883
1004
|
{
|
|
884
1005
|
name: 'update_wiki_page',
|
|
885
|
-
description: 'Update an existing wiki page. Requires mcp:wiki:update permission.'
|
|
1006
|
+
description: 'Update an existing wiki page. Requires mcp:wiki:update permission. ' +
|
|
1007
|
+
CONTENT_LINKING_HELP,
|
|
886
1008
|
inputSchema: {
|
|
887
1009
|
type: 'object',
|
|
888
1010
|
properties: {
|
|
889
|
-
page_id: { type: 'string', description: 'The page
|
|
1011
|
+
page_id: { type: 'string', description: 'The page slug' },
|
|
890
1012
|
title: { type: 'string', description: 'Updated title' },
|
|
891
1013
|
content: {
|
|
892
1014
|
type: 'string',
|
|
@@ -926,15 +1048,15 @@ class WolfpackMCPServer {
|
|
|
926
1048
|
},
|
|
927
1049
|
{
|
|
928
1050
|
name: 'get_journal_entry',
|
|
929
|
-
description: 'Get a specific journal/log entry by
|
|
1051
|
+
description: 'Get a specific journal/log entry by reference number. Returns full content. ' +
|
|
930
1052
|
'IMAGES: Image references in the content (e.g. ``) can be viewed using the download_image tool.',
|
|
931
1053
|
inputSchema: {
|
|
932
1054
|
type: 'object',
|
|
933
1055
|
properties: {
|
|
934
|
-
entry_id: { type: 'string', description: 'The entry
|
|
1056
|
+
entry_id: { type: 'string', description: 'The entry refId (number)' },
|
|
935
1057
|
project_slug: {
|
|
936
1058
|
type: 'string',
|
|
937
|
-
description: 'Project slug (required
|
|
1059
|
+
description: 'Project slug (required for refId lookup)',
|
|
938
1060
|
},
|
|
939
1061
|
},
|
|
940
1062
|
required: ['entry_id'],
|
|
@@ -942,7 +1064,8 @@ class WolfpackMCPServer {
|
|
|
942
1064
|
},
|
|
943
1065
|
{
|
|
944
1066
|
name: 'create_journal_entry',
|
|
945
|
-
description: 'Create a new journal entry (daily log, standup note, progress update). Use when user wants to "log progress", "write a standup", "add a journal entry", or "record what I did".'
|
|
1067
|
+
description: 'Create a new journal entry (daily log, standup note, progress update). Use when user wants to "log progress", "write a standup", "add a journal entry", or "record what I did". ' +
|
|
1068
|
+
CONTENT_LINKING_HELP,
|
|
946
1069
|
inputSchema: {
|
|
947
1070
|
type: 'object',
|
|
948
1071
|
properties: {
|
|
@@ -955,18 +1078,18 @@ class WolfpackMCPServer {
|
|
|
955
1078
|
type: 'string',
|
|
956
1079
|
description: 'Entry content (markdown)',
|
|
957
1080
|
},
|
|
958
|
-
date: { type: 'string', description: 'Entry date (ISO format, defaults to now)' },
|
|
959
1081
|
},
|
|
960
1082
|
required: ['title', 'content'],
|
|
961
1083
|
},
|
|
962
1084
|
},
|
|
963
1085
|
{
|
|
964
1086
|
name: 'update_journal_entry',
|
|
965
|
-
description: 'Update an existing journal entry. Requires mcp:journal:update permission.'
|
|
1087
|
+
description: 'Update an existing journal entry. Requires mcp:journal:update permission. ' +
|
|
1088
|
+
CONTENT_LINKING_HELP,
|
|
966
1089
|
inputSchema: {
|
|
967
1090
|
type: 'object',
|
|
968
1091
|
properties: {
|
|
969
|
-
entry_id: { type: 'string', description: 'The entry
|
|
1092
|
+
entry_id: { type: 'string', description: 'The entry refId (number)' },
|
|
970
1093
|
title: { type: 'string', description: 'Updated title' },
|
|
971
1094
|
content: {
|
|
972
1095
|
type: 'string',
|
|
@@ -984,7 +1107,7 @@ class WolfpackMCPServer {
|
|
|
984
1107
|
inputSchema: {
|
|
985
1108
|
type: 'object',
|
|
986
1109
|
properties: {
|
|
987
|
-
work_item_id: { type: 'string', description: 'The work item
|
|
1110
|
+
work_item_id: { type: 'string', description: 'The work item refId (number)' },
|
|
988
1111
|
},
|
|
989
1112
|
required: ['work_item_id'],
|
|
990
1113
|
},
|
|
@@ -996,7 +1119,7 @@ class WolfpackMCPServer {
|
|
|
996
1119
|
inputSchema: {
|
|
997
1120
|
type: 'object',
|
|
998
1121
|
properties: {
|
|
999
|
-
issue_id: { type: 'string', description: 'The issue
|
|
1122
|
+
issue_id: { type: 'string', description: 'The issue refId (number)' },
|
|
1000
1123
|
},
|
|
1001
1124
|
required: ['issue_id'],
|
|
1002
1125
|
},
|
|
@@ -1008,11 +1131,12 @@ class WolfpackMCPServer {
|
|
|
1008
1131
|
'2) Completion summaries when moving to "review" (what was done, files changed, testing notes). ' +
|
|
1009
1132
|
'3) Important observations or decisions that should be visible in the activity history. ' +
|
|
1010
1133
|
'USE DESCRIPTION (update_work_progress) FOR: Plans, checklists, and progress tracking that need to be updated over time. ' +
|
|
1011
|
-
'Comments are typically not used in personal projects.'
|
|
1134
|
+
'Comments are typically not used in personal projects. ' +
|
|
1135
|
+
CONTENT_LINKING_HELP,
|
|
1012
1136
|
inputSchema: {
|
|
1013
1137
|
type: 'object',
|
|
1014
1138
|
properties: {
|
|
1015
|
-
work_item_id: { type: 'string', description: 'The work item
|
|
1139
|
+
work_item_id: { type: 'string', description: 'The work item refId (number)' },
|
|
1016
1140
|
content: {
|
|
1017
1141
|
type: 'string',
|
|
1018
1142
|
description: 'Comment content (markdown)',
|
|
@@ -1023,11 +1147,12 @@ class WolfpackMCPServer {
|
|
|
1023
1147
|
},
|
|
1024
1148
|
{
|
|
1025
1149
|
name: 'create_issue_comment',
|
|
1026
|
-
description: 'Add a comment to an issue. Requires mcp:comments:create permission.'
|
|
1150
|
+
description: 'Add a comment to an issue. Requires mcp:comments:create permission. ' +
|
|
1151
|
+
CONTENT_LINKING_HELP,
|
|
1027
1152
|
inputSchema: {
|
|
1028
1153
|
type: 'object',
|
|
1029
1154
|
properties: {
|
|
1030
|
-
issue_id: { type: 'string', description: 'The issue
|
|
1155
|
+
issue_id: { type: 'string', description: 'The issue refId (number)' },
|
|
1031
1156
|
content: {
|
|
1032
1157
|
type: 'string',
|
|
1033
1158
|
description: 'Comment content (markdown)',
|
|
@@ -1078,6 +1203,51 @@ class WolfpackMCPServer {
|
|
|
1078
1203
|
required: ['image_url'],
|
|
1079
1204
|
},
|
|
1080
1205
|
},
|
|
1206
|
+
// Skill tools (progressive disclosure)
|
|
1207
|
+
{
|
|
1208
|
+
name: 'list_skills',
|
|
1209
|
+
description: 'List all skills available to the current agent. Returns lean metadata (name + description) for each skill. ' +
|
|
1210
|
+
'Use get_skill to load the full instructions for a specific skill when needed.',
|
|
1211
|
+
inputSchema: {
|
|
1212
|
+
type: 'object',
|
|
1213
|
+
properties: {},
|
|
1214
|
+
},
|
|
1215
|
+
},
|
|
1216
|
+
{
|
|
1217
|
+
name: 'get_skill',
|
|
1218
|
+
description: 'Load the full instruction content for a specific skill by name. ' +
|
|
1219
|
+
"Call this when a task matches a skill's description to get detailed instructions before proceeding. " +
|
|
1220
|
+
'Also returns a list of available resources (scripts, references, assets).',
|
|
1221
|
+
inputSchema: {
|
|
1222
|
+
type: 'object',
|
|
1223
|
+
properties: {
|
|
1224
|
+
skill_name: {
|
|
1225
|
+
type: 'string',
|
|
1226
|
+
description: 'The name of the skill to load (e.g. "deploy-app")',
|
|
1227
|
+
},
|
|
1228
|
+
},
|
|
1229
|
+
required: ['skill_name'],
|
|
1230
|
+
},
|
|
1231
|
+
},
|
|
1232
|
+
{
|
|
1233
|
+
name: 'get_skill_resource',
|
|
1234
|
+
description: 'Get a specific resource file attached to a skill. ' +
|
|
1235
|
+
'Resources can be scripts, reference documents, or assets that supplement the skill instructions.',
|
|
1236
|
+
inputSchema: {
|
|
1237
|
+
type: 'object',
|
|
1238
|
+
properties: {
|
|
1239
|
+
skill_name: {
|
|
1240
|
+
type: 'string',
|
|
1241
|
+
description: 'The name of the skill',
|
|
1242
|
+
},
|
|
1243
|
+
resource_name: {
|
|
1244
|
+
type: 'string',
|
|
1245
|
+
description: 'The name of the resource file',
|
|
1246
|
+
},
|
|
1247
|
+
},
|
|
1248
|
+
required: ['skill_name', 'resource_name'],
|
|
1249
|
+
},
|
|
1250
|
+
},
|
|
1081
1251
|
],
|
|
1082
1252
|
}));
|
|
1083
1253
|
this.server.setRequestHandler(CallToolRequestSchema, async (request) => {
|
|
@@ -1123,7 +1293,7 @@ class WolfpackMCPServer {
|
|
|
1123
1293
|
limit: parsed.limit,
|
|
1124
1294
|
offset: parsed.offset,
|
|
1125
1295
|
});
|
|
1126
|
-
let text = JSON.stringify(result.items, null, 2);
|
|
1296
|
+
let text = JSON.stringify(stripUuids(result.items), null, 2);
|
|
1127
1297
|
if (result.truncated) {
|
|
1128
1298
|
text = `Note: Results truncated. Showing ${result.items.length} of ${result.total} items. Use filters or limit/offset for pagination.\n\n${text}`;
|
|
1129
1299
|
}
|
|
@@ -1135,7 +1305,7 @@ class WolfpackMCPServer {
|
|
|
1135
1305
|
const parsed = GetWorkItemSchema.parse(args);
|
|
1136
1306
|
const workItem = await this.client.getWorkItem(parsed.work_item_id, parsed.project_slug || this.client.getProjectSlug() || undefined);
|
|
1137
1307
|
if (workItem) {
|
|
1138
|
-
let text = JSON.stringify(workItem, null, 2);
|
|
1308
|
+
let text = JSON.stringify(stripUuids(workItem), null, 2);
|
|
1139
1309
|
// Add hint if no plan detected in description
|
|
1140
1310
|
if (!hasPlan(workItem.description)) {
|
|
1141
1311
|
text =
|
|
@@ -1158,7 +1328,7 @@ class WolfpackMCPServer {
|
|
|
1158
1328
|
content: [
|
|
1159
1329
|
{
|
|
1160
1330
|
type: 'text',
|
|
1161
|
-
text: `Updated description on: ${workItem.title}\n\n${JSON.stringify(workItem, null, 2)}`,
|
|
1331
|
+
text: `Updated description on: ${workItem.title}\n\n${JSON.stringify(stripUuids(workItem), null, 2)}`,
|
|
1162
1332
|
},
|
|
1163
1333
|
],
|
|
1164
1334
|
};
|
|
@@ -1175,7 +1345,7 @@ class WolfpackMCPServer {
|
|
|
1175
1345
|
content: [
|
|
1176
1346
|
{
|
|
1177
1347
|
type: 'text',
|
|
1178
|
-
text: `Updated status of "${workItem.title}" to ${parsed.status}\n\n${JSON.stringify(workItem, null, 2)}`,
|
|
1348
|
+
text: `Updated status of "${workItem.title}" to ${parsed.status}\n\n${JSON.stringify(stripUuids(workItem), null, 2)}`,
|
|
1179
1349
|
},
|
|
1180
1350
|
],
|
|
1181
1351
|
};
|
|
@@ -1197,7 +1367,7 @@ class WolfpackMCPServer {
|
|
|
1197
1367
|
content: [
|
|
1198
1368
|
{
|
|
1199
1369
|
type: 'text',
|
|
1200
|
-
text: `Updated "${workItem.title}" - now ${assigneeText}\n\n${JSON.stringify(workItem, null, 2)}`,
|
|
1370
|
+
text: `Updated "${workItem.title}" - now ${assigneeText}\n\n${JSON.stringify(stripUuids(workItem), null, 2)}`,
|
|
1201
1371
|
},
|
|
1202
1372
|
],
|
|
1203
1373
|
};
|
|
@@ -1214,7 +1384,27 @@ class WolfpackMCPServer {
|
|
|
1214
1384
|
content: [
|
|
1215
1385
|
{
|
|
1216
1386
|
type: 'text',
|
|
1217
|
-
text: `Updated title to "${workItem.title}"\n\n${JSON.stringify(workItem, null, 2)}`,
|
|
1387
|
+
text: `Updated title to "${workItem.title}"\n\n${JSON.stringify(stripUuids(workItem), null, 2)}`,
|
|
1388
|
+
},
|
|
1389
|
+
],
|
|
1390
|
+
};
|
|
1391
|
+
}
|
|
1392
|
+
return {
|
|
1393
|
+
content: [{ type: 'text', text: 'Work item not found' }],
|
|
1394
|
+
};
|
|
1395
|
+
}
|
|
1396
|
+
case 'update_work_item_initiative': {
|
|
1397
|
+
const parsed = UpdateWorkItemInitiativeSchema.parse(args);
|
|
1398
|
+
const workItem = await this.client.updateWorkItemInitiative(parsed.work_item_id, parsed.radar_item_id);
|
|
1399
|
+
if (workItem) {
|
|
1400
|
+
const initiativeText = parsed.radar_item_id
|
|
1401
|
+
? `linked to initiative ${parsed.radar_item_id}`
|
|
1402
|
+
: 'unlinked from initiative';
|
|
1403
|
+
return {
|
|
1404
|
+
content: [
|
|
1405
|
+
{
|
|
1406
|
+
type: 'text',
|
|
1407
|
+
text: `Updated "${workItem.title}" - ${initiativeText}\n\n${JSON.stringify(stripUuids(workItem), null, 2)}`,
|
|
1218
1408
|
},
|
|
1219
1409
|
],
|
|
1220
1410
|
};
|
|
@@ -1233,7 +1423,24 @@ class WolfpackMCPServer {
|
|
|
1233
1423
|
content: [
|
|
1234
1424
|
{
|
|
1235
1425
|
type: 'text',
|
|
1236
|
-
text: `Pulled "${workItem.title}" from backlog to board (status: new)\n\n${JSON.stringify(workItem, null, 2)}`,
|
|
1426
|
+
text: `Pulled "${workItem.title}" from backlog to board (status: new)\n\n${JSON.stringify(stripUuids(workItem), null, 2)}`,
|
|
1427
|
+
},
|
|
1428
|
+
],
|
|
1429
|
+
};
|
|
1430
|
+
}
|
|
1431
|
+
return {
|
|
1432
|
+
content: [{ type: 'text', text: 'Work item not found' }],
|
|
1433
|
+
};
|
|
1434
|
+
}
|
|
1435
|
+
case 'submit_work_item_form': {
|
|
1436
|
+
const parsed = SubmitWorkItemFormSchema.parse(args);
|
|
1437
|
+
const workItem = await this.client.submitWorkItemForm(parsed.work_item_id, parsed.form_values);
|
|
1438
|
+
if (workItem) {
|
|
1439
|
+
return {
|
|
1440
|
+
content: [
|
|
1441
|
+
{
|
|
1442
|
+
type: 'text',
|
|
1443
|
+
text: `Submitted form values for "${workItem.title}"\n\n${JSON.stringify(stripUuids(workItem), null, 2)}`,
|
|
1237
1444
|
},
|
|
1238
1445
|
],
|
|
1239
1446
|
};
|
|
@@ -1252,7 +1459,7 @@ class WolfpackMCPServer {
|
|
|
1252
1459
|
limit: parsed.limit,
|
|
1253
1460
|
offset: parsed.offset,
|
|
1254
1461
|
});
|
|
1255
|
-
let text = JSON.stringify(result.items, null, 2);
|
|
1462
|
+
let text = JSON.stringify(stripUuids(result.items), null, 2);
|
|
1256
1463
|
if (result.truncated) {
|
|
1257
1464
|
text = `Note: Results truncated. Showing ${result.items.length} of ${result.total} items. Use stage filter or limit/offset for pagination.\n\n${text}`;
|
|
1258
1465
|
}
|
|
@@ -1265,7 +1472,7 @@ class WolfpackMCPServer {
|
|
|
1265
1472
|
const radarItem = await this.client.getRadarItem(parsed.item_id, parsed.project_slug);
|
|
1266
1473
|
if (radarItem) {
|
|
1267
1474
|
return {
|
|
1268
|
-
content: [{ type: 'text', text: JSON.stringify(radarItem, null, 2) }],
|
|
1475
|
+
content: [{ type: 'text', text: JSON.stringify(stripUuids(radarItem), null, 2) }],
|
|
1269
1476
|
};
|
|
1270
1477
|
}
|
|
1271
1478
|
return {
|
|
@@ -1289,7 +1496,7 @@ class WolfpackMCPServer {
|
|
|
1289
1496
|
limit: parsed.limit,
|
|
1290
1497
|
offset: parsed.offset,
|
|
1291
1498
|
});
|
|
1292
|
-
let text = JSON.stringify(result.items, null, 2);
|
|
1499
|
+
let text = JSON.stringify(stripUuids(result.items), null, 2);
|
|
1293
1500
|
if (result.truncated) {
|
|
1294
1501
|
text = `Note: Results truncated. Showing ${result.items.length} of ${result.total} items. Use filters or limit/offset for pagination.\n\n${text}`;
|
|
1295
1502
|
}
|
|
@@ -1302,7 +1509,7 @@ class WolfpackMCPServer {
|
|
|
1302
1509
|
const issue = await this.client.getIssue(parsed.issue_id, parsed.project_slug);
|
|
1303
1510
|
if (issue) {
|
|
1304
1511
|
return {
|
|
1305
|
-
content: [{ type: 'text', text: JSON.stringify(issue, null, 2) }],
|
|
1512
|
+
content: [{ type: 'text', text: JSON.stringify(stripUuids(issue), null, 2) }],
|
|
1306
1513
|
};
|
|
1307
1514
|
}
|
|
1308
1515
|
return {
|
|
@@ -1317,6 +1524,7 @@ class WolfpackMCPServer {
|
|
|
1317
1524
|
description: parsed.description,
|
|
1318
1525
|
status: parsed.status,
|
|
1319
1526
|
priority: parsed.priority,
|
|
1527
|
+
size: parsed.size,
|
|
1320
1528
|
leadingUserId: parsed.leading_user_id,
|
|
1321
1529
|
categoryId: parsed.category_id,
|
|
1322
1530
|
radarItemId: parsed.radar_item_id,
|
|
@@ -1326,7 +1534,7 @@ class WolfpackMCPServer {
|
|
|
1326
1534
|
content: [
|
|
1327
1535
|
{
|
|
1328
1536
|
type: 'text',
|
|
1329
|
-
text: `Created work item #${workItem.refId}: ${workItem.title}\n\n${JSON.stringify(workItem, null, 2)}`,
|
|
1537
|
+
text: `Created work item #${workItem.refId}: ${workItem.title}\n\n${JSON.stringify(stripUuids(workItem), null, 2)}`,
|
|
1330
1538
|
},
|
|
1331
1539
|
],
|
|
1332
1540
|
};
|
|
@@ -1351,7 +1559,7 @@ class WolfpackMCPServer {
|
|
|
1351
1559
|
content: [
|
|
1352
1560
|
{
|
|
1353
1561
|
type: 'text',
|
|
1354
|
-
text: `Created issue #${issue.refId}: ${issue.title}\n\n${JSON.stringify(issue, null, 2)}`,
|
|
1562
|
+
text: `Created issue #${issue.refId}: ${issue.title}\n\n${JSON.stringify(stripUuids(issue), null, 2)}`,
|
|
1355
1563
|
},
|
|
1356
1564
|
],
|
|
1357
1565
|
};
|
|
@@ -1370,7 +1578,7 @@ class WolfpackMCPServer {
|
|
|
1370
1578
|
content: [
|
|
1371
1579
|
{
|
|
1372
1580
|
type: 'text',
|
|
1373
|
-
text: `Updated issue #${issue.refId}: ${issue.title}\n\n${JSON.stringify(issue, null, 2)}`,
|
|
1581
|
+
text: `Updated issue #${issue.refId}: ${issue.title}\n\n${JSON.stringify(stripUuids(issue), null, 2)}`,
|
|
1374
1582
|
},
|
|
1375
1583
|
],
|
|
1376
1584
|
};
|
|
@@ -1386,7 +1594,7 @@ class WolfpackMCPServer {
|
|
|
1386
1594
|
limit: parsed.limit,
|
|
1387
1595
|
offset: parsed.offset,
|
|
1388
1596
|
});
|
|
1389
|
-
let text = JSON.stringify(result.items, null, 2);
|
|
1597
|
+
let text = JSON.stringify(stripUuids(result.items), null, 2);
|
|
1390
1598
|
if (result.truncated) {
|
|
1391
1599
|
text = `Note: Results truncated. Showing ${result.items.length} of ${result.total} pages. Use limit/offset for pagination.\n\n${text}`;
|
|
1392
1600
|
}
|
|
@@ -1399,7 +1607,7 @@ class WolfpackMCPServer {
|
|
|
1399
1607
|
const page = await this.client.getWikiPage(parsed.page_id);
|
|
1400
1608
|
if (page) {
|
|
1401
1609
|
return {
|
|
1402
|
-
content: [{ type: 'text', text: JSON.stringify(page, null, 2) }],
|
|
1610
|
+
content: [{ type: 'text', text: JSON.stringify(stripUuids(page), null, 2) }],
|
|
1403
1611
|
};
|
|
1404
1612
|
}
|
|
1405
1613
|
return {
|
|
@@ -1418,7 +1626,7 @@ class WolfpackMCPServer {
|
|
|
1418
1626
|
content: [
|
|
1419
1627
|
{
|
|
1420
1628
|
type: 'text',
|
|
1421
|
-
text: `Created wiki page: ${page.title}\n\n${JSON.stringify(page, null, 2)}`,
|
|
1629
|
+
text: `Created wiki page: ${page.title}\n\n${JSON.stringify(stripUuids(page), null, 2)}`,
|
|
1422
1630
|
},
|
|
1423
1631
|
],
|
|
1424
1632
|
};
|
|
@@ -1433,7 +1641,7 @@ class WolfpackMCPServer {
|
|
|
1433
1641
|
content: [
|
|
1434
1642
|
{
|
|
1435
1643
|
type: 'text',
|
|
1436
|
-
text: `Updated wiki page: ${page.title}\n\n${JSON.stringify(page, null, 2)}`,
|
|
1644
|
+
text: `Updated wiki page: ${page.title}\n\n${JSON.stringify(stripUuids(page), null, 2)}`,
|
|
1437
1645
|
},
|
|
1438
1646
|
],
|
|
1439
1647
|
};
|
|
@@ -1449,7 +1657,7 @@ class WolfpackMCPServer {
|
|
|
1449
1657
|
limit: parsed.limit,
|
|
1450
1658
|
offset: parsed.offset,
|
|
1451
1659
|
});
|
|
1452
|
-
let text = JSON.stringify(result.items, null, 2);
|
|
1660
|
+
let text = JSON.stringify(stripUuids(result.items), null, 2);
|
|
1453
1661
|
if (result.truncated) {
|
|
1454
1662
|
text = `Note: Results truncated. Showing ${result.items.length} of ${result.total} entries. Use limit/offset for pagination.\n\n${text}`;
|
|
1455
1663
|
}
|
|
@@ -1462,7 +1670,7 @@ class WolfpackMCPServer {
|
|
|
1462
1670
|
const entry = await this.client.getJournalEntry(parsed.entry_id, parsed.project_slug);
|
|
1463
1671
|
if (entry) {
|
|
1464
1672
|
return {
|
|
1465
|
-
content: [{ type: 'text', text: JSON.stringify(entry, null, 2) }],
|
|
1673
|
+
content: [{ type: 'text', text: JSON.stringify(stripUuids(entry), null, 2) }],
|
|
1466
1674
|
};
|
|
1467
1675
|
}
|
|
1468
1676
|
return {
|
|
@@ -1474,14 +1682,13 @@ class WolfpackMCPServer {
|
|
|
1474
1682
|
const entry = await this.client.createJournalEntry({
|
|
1475
1683
|
title: parsed.title,
|
|
1476
1684
|
content: parsed.content,
|
|
1477
|
-
date: parsed.date,
|
|
1478
1685
|
teamSlug: parsed.project_slug || this.client.getProjectSlug() || undefined,
|
|
1479
1686
|
});
|
|
1480
1687
|
return {
|
|
1481
1688
|
content: [
|
|
1482
1689
|
{
|
|
1483
1690
|
type: 'text',
|
|
1484
|
-
text: `Created journal entry #${entry.refId}: ${entry.title}\n\n${JSON.stringify(entry, null, 2)}`,
|
|
1691
|
+
text: `Created journal entry #${entry.refId}: ${entry.title}\n\n${JSON.stringify(stripUuids(entry), null, 2)}`,
|
|
1485
1692
|
},
|
|
1486
1693
|
],
|
|
1487
1694
|
};
|
|
@@ -1496,7 +1703,7 @@ class WolfpackMCPServer {
|
|
|
1496
1703
|
content: [
|
|
1497
1704
|
{
|
|
1498
1705
|
type: 'text',
|
|
1499
|
-
text: `Updated journal entry #${entry.refId}: ${entry.title}\n\n${JSON.stringify(entry, null, 2)}`,
|
|
1706
|
+
text: `Updated journal entry #${entry.refId}: ${entry.title}\n\n${JSON.stringify(stripUuids(entry), null, 2)}`,
|
|
1500
1707
|
},
|
|
1501
1708
|
],
|
|
1502
1709
|
};
|
|
@@ -1506,14 +1713,14 @@ class WolfpackMCPServer {
|
|
|
1506
1713
|
const parsed = ListWorkItemCommentsSchema.parse(args);
|
|
1507
1714
|
const comments = await this.client.listWorkItemComments(parsed.work_item_id);
|
|
1508
1715
|
return {
|
|
1509
|
-
content: [{ type: 'text', text: JSON.stringify(comments, null, 2) }],
|
|
1716
|
+
content: [{ type: 'text', text: JSON.stringify(stripUuids(comments), null, 2) }],
|
|
1510
1717
|
};
|
|
1511
1718
|
}
|
|
1512
1719
|
case 'list_issue_comments': {
|
|
1513
1720
|
const parsed = ListIssueCommentsSchema.parse(args);
|
|
1514
1721
|
const comments = await this.client.listIssueComments(parsed.issue_id);
|
|
1515
1722
|
return {
|
|
1516
|
-
content: [{ type: 'text', text: JSON.stringify(comments, null, 2) }],
|
|
1723
|
+
content: [{ type: 'text', text: JSON.stringify(stripUuids(comments), null, 2) }],
|
|
1517
1724
|
};
|
|
1518
1725
|
}
|
|
1519
1726
|
case 'create_work_item_comment': {
|
|
@@ -1525,7 +1732,7 @@ class WolfpackMCPServer {
|
|
|
1525
1732
|
content: [
|
|
1526
1733
|
{
|
|
1527
1734
|
type: 'text',
|
|
1528
|
-
text: `Added comment to work item\n\n${JSON.stringify(comment, null, 2)}`,
|
|
1735
|
+
text: `Added comment to work item\n\n${JSON.stringify(stripUuids(comment), null, 2)}`,
|
|
1529
1736
|
},
|
|
1530
1737
|
],
|
|
1531
1738
|
};
|
|
@@ -1539,7 +1746,7 @@ class WolfpackMCPServer {
|
|
|
1539
1746
|
content: [
|
|
1540
1747
|
{
|
|
1541
1748
|
type: 'text',
|
|
1542
|
-
text: `Added comment to issue\n\n${JSON.stringify(comment, null, 2)}`,
|
|
1749
|
+
text: `Added comment to issue\n\n${JSON.stringify(stripUuids(comment), null, 2)}`,
|
|
1543
1750
|
},
|
|
1544
1751
|
],
|
|
1545
1752
|
};
|
|
@@ -1601,6 +1808,47 @@ class WolfpackMCPServer {
|
|
|
1601
1808
|
],
|
|
1602
1809
|
};
|
|
1603
1810
|
}
|
|
1811
|
+
// Skill handlers
|
|
1812
|
+
case 'list_skills': {
|
|
1813
|
+
const skills = await this.client.listSkills();
|
|
1814
|
+
return {
|
|
1815
|
+
content: [{ type: 'text', text: JSON.stringify(skills, null, 2) }],
|
|
1816
|
+
};
|
|
1817
|
+
}
|
|
1818
|
+
case 'get_skill': {
|
|
1819
|
+
const parsed = GetSkillSchema.parse(args);
|
|
1820
|
+
const skill = await this.client.getSkill(parsed.skill_name);
|
|
1821
|
+
if (skill) {
|
|
1822
|
+
return {
|
|
1823
|
+
content: [{ type: 'text', text: JSON.stringify(skill, null, 2) }],
|
|
1824
|
+
};
|
|
1825
|
+
}
|
|
1826
|
+
return {
|
|
1827
|
+
content: [
|
|
1828
|
+
{
|
|
1829
|
+
type: 'text',
|
|
1830
|
+
text: `Skill '${parsed.skill_name}' not found. Use list_skills to see available skills.`,
|
|
1831
|
+
},
|
|
1832
|
+
],
|
|
1833
|
+
};
|
|
1834
|
+
}
|
|
1835
|
+
case 'get_skill_resource': {
|
|
1836
|
+
const parsed = GetSkillResourceSchema.parse(args);
|
|
1837
|
+
const resource = await this.client.getSkillResource(parsed.skill_name, parsed.resource_name);
|
|
1838
|
+
if (resource) {
|
|
1839
|
+
return {
|
|
1840
|
+
content: [{ type: 'text', text: JSON.stringify(resource, null, 2) }],
|
|
1841
|
+
};
|
|
1842
|
+
}
|
|
1843
|
+
return {
|
|
1844
|
+
content: [
|
|
1845
|
+
{
|
|
1846
|
+
type: 'text',
|
|
1847
|
+
text: `Resource '${parsed.resource_name}' not found in skill '${parsed.skill_name}'.`,
|
|
1848
|
+
},
|
|
1849
|
+
],
|
|
1850
|
+
};
|
|
1851
|
+
}
|
|
1604
1852
|
default:
|
|
1605
1853
|
throw new Error(`Unknown tool: ${name}`);
|
|
1606
1854
|
}
|