wolfpack-mcp 1.0.38 → 1.0.40

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 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.
@@ -156,11 +164,9 @@ export class WolfpackClient {
156
164
  throw error;
157
165
  }
158
166
  }
159
- async updateWorkProgress(workItemId, description) {
167
+ async updateWorkProgress(workItemId, description, teamSlug) {
160
168
  try {
161
- return await this.api.put(`/work-items/${workItemId}/progress`, {
162
- description,
163
- });
169
+ return await this.api.put(this.withTeamSlug(`/work-items/${workItemId}/progress`, teamSlug), { description });
164
170
  }
165
171
  catch (error) {
166
172
  if (error && typeof error === 'object' && 'status' in error && error.status === 404) {
@@ -169,9 +175,9 @@ export class WolfpackClient {
169
175
  throw error;
170
176
  }
171
177
  }
172
- async updateWorkItemStatus(workItemId, status) {
178
+ async updateWorkItemStatus(workItemId, status, teamSlug) {
173
179
  try {
174
- return await this.api.put(`/work-items/${workItemId}/status`, { status });
180
+ return await this.api.put(this.withTeamSlug(`/work-items/${workItemId}/status`, teamSlug), { status });
175
181
  }
176
182
  catch (error) {
177
183
  if (error && typeof error === 'object' && 'status' in error && error.status === 404) {
@@ -180,9 +186,9 @@ export class WolfpackClient {
180
186
  throw error;
181
187
  }
182
188
  }
183
- async updateWorkItemAssignee(workItemId, data) {
189
+ async updateWorkItemAssignee(workItemId, data, teamSlug) {
184
190
  try {
185
- return await this.api.put(`/work-items/${workItemId}/assignee`, data);
191
+ return await this.api.put(this.withTeamSlug(`/work-items/${workItemId}/assignee`, teamSlug), data);
186
192
  }
187
193
  catch (error) {
188
194
  if (error && typeof error === 'object' && 'status' in error && error.status === 404) {
@@ -191,9 +197,9 @@ export class WolfpackClient {
191
197
  throw error;
192
198
  }
193
199
  }
194
- async updateWorkItemTitle(workItemId, title) {
200
+ async updateWorkItemTitle(workItemId, title, teamSlug) {
195
201
  try {
196
- return await this.api.put(`/work-items/${workItemId}/title`, { title });
202
+ return await this.api.put(this.withTeamSlug(`/work-items/${workItemId}/title`, teamSlug), { title });
197
203
  }
198
204
  catch (error) {
199
205
  if (error && typeof error === 'object' && 'status' in error && error.status === 404) {
@@ -202,9 +208,9 @@ export class WolfpackClient {
202
208
  throw error;
203
209
  }
204
210
  }
205
- async updateWorkItemInitiative(workItemId, radarItemId) {
211
+ async updateWorkItemInitiative(workItemId, radarItemId, teamSlug) {
206
212
  try {
207
- return await this.api.put(`/work-items/${workItemId}/initiative`, { radarItemId });
213
+ return await this.api.put(this.withTeamSlug(`/work-items/${workItemId}/initiative`, teamSlug), { radarItemId });
208
214
  }
209
215
  catch (error) {
210
216
  if (error && typeof error === 'object' && 'status' in error && error.status === 404) {
@@ -213,9 +219,9 @@ export class WolfpackClient {
213
219
  throw error;
214
220
  }
215
221
  }
216
- async pullWorkItem(workItemId, data) {
222
+ async pullWorkItem(workItemId, data, teamSlug) {
217
223
  try {
218
- return await this.api.post(`/work-items/${workItemId}/pull`, data || {});
224
+ return await this.api.post(this.withTeamSlug(`/work-items/${workItemId}/pull`, teamSlug), data || {});
219
225
  }
220
226
  catch (error) {
221
227
  if (error && typeof error === 'object' && 'status' in error && error.status === 404) {
@@ -224,11 +230,9 @@ export class WolfpackClient {
224
230
  throw error;
225
231
  }
226
232
  }
227
- async submitWorkItemForm(workItemId, formValues) {
233
+ async submitWorkItemForm(workItemId, formValues, teamSlug) {
228
234
  try {
229
- return await this.api.put(`/work-items/${workItemId}/form`, {
230
- formValues,
231
- });
235
+ return await this.api.put(this.withTeamSlug(`/work-items/${workItemId}/form`, teamSlug), { formValues });
232
236
  }
233
237
  catch (error) {
234
238
  if (error && typeof error === 'object' && 'status' in error && error.status === 404) {
@@ -348,8 +352,8 @@ export class WolfpackClient {
348
352
  const { teamSlug, ...rest } = data;
349
353
  return this.api.post('/issues', { ...rest, teamSlug });
350
354
  }
351
- async updateIssue(issueId, data) {
352
- return this.api.patch(`/issues/${issueId}`, data);
355
+ async updateIssue(issueId, data, teamSlug) {
356
+ return this.api.patch(this.withTeamSlug(`/issues/${issueId}`, teamSlug), data);
353
357
  }
354
358
  // Wiki Page methods
355
359
  async listWikiPages(options) {
@@ -397,8 +401,8 @@ export class WolfpackClient {
397
401
  const { teamSlug, ...rest } = data;
398
402
  return this.api.post('/wiki-pages', { ...rest, teamSlug });
399
403
  }
400
- async updateWikiPage(pageId, data) {
401
- return this.api.patch(`/wiki-pages/${pageId}`, data);
404
+ async updateWikiPage(pageId, data, teamSlug) {
405
+ return this.api.patch(this.withTeamSlug(`/wiki-pages/${pageId}`, teamSlug), data);
402
406
  }
403
407
  // Journal Entry methods
404
408
  async listJournalEntries(options) {
@@ -446,21 +450,21 @@ export class WolfpackClient {
446
450
  const { teamSlug, ...rest } = data;
447
451
  return this.api.post('/journal-entries', { ...rest, teamSlug });
448
452
  }
449
- async updateJournalEntry(entryId, data) {
450
- return this.api.patch(`/journal-entries/${entryId}`, data);
453
+ async updateJournalEntry(entryId, data, teamSlug) {
454
+ return this.api.patch(this.withTeamSlug(`/journal-entries/${entryId}`, teamSlug), data);
451
455
  }
452
456
  // Comment methods
453
- async listWorkItemComments(workItemId) {
454
- return this.api.get(`/work-items/${workItemId}/comments`);
457
+ async listWorkItemComments(workItemId, teamSlug) {
458
+ return this.api.get(this.withTeamSlug(`/work-items/${workItemId}/comments`, teamSlug));
455
459
  }
456
- async listIssueComments(issueId) {
457
- return this.api.get(`/issues/${issueId}/comments`);
460
+ async listIssueComments(issueId, teamSlug) {
461
+ return this.api.get(this.withTeamSlug(`/issues/${issueId}/comments`, teamSlug));
458
462
  }
459
- async createWorkItemComment(workItemId, data) {
460
- return this.api.post(`/work-items/${workItemId}/comments`, data);
463
+ async createWorkItemComment(workItemId, data, teamSlug) {
464
+ return this.api.post(this.withTeamSlug(`/work-items/${workItemId}/comments`, teamSlug), data);
461
465
  }
462
- async createIssueComment(issueId, data) {
463
- return this.api.post(`/issues/${issueId}/comments`, data);
466
+ async createIssueComment(issueId, data, teamSlug) {
467
+ return this.api.post(this.withTeamSlug(`/issues/${issueId}/comments`, teamSlug), data);
464
468
  }
465
469
  /**
466
470
  * Upload an image and get back a URL that can be used in markdown content.
@@ -476,6 +480,32 @@ export class WolfpackClient {
476
480
  const { buffer, contentType } = await this.api.getBuffer(`/images/${team}/${filename}`);
477
481
  return { base64: buffer.toString('base64'), mimeType: contentType };
478
482
  }
483
+ // Skill methods (progressive disclosure)
484
+ async listSkills() {
485
+ return this.api.get('/skills');
486
+ }
487
+ async getSkill(name) {
488
+ try {
489
+ return await this.api.get(`/skills/${encodeURIComponent(name)}`);
490
+ }
491
+ catch (error) {
492
+ if (error && typeof error === 'object' && 'status' in error && error.status === 404) {
493
+ return null;
494
+ }
495
+ throw error;
496
+ }
497
+ }
498
+ async getSkillResource(skillName, resourceName) {
499
+ try {
500
+ return await this.api.get(`/skills/${encodeURIComponent(skillName)}/resources/${encodeURIComponent(resourceName)}`);
501
+ }
502
+ catch (error) {
503
+ if (error && typeof error === 'object' && 'status' in error && error.status === 404) {
504
+ return null;
505
+ }
506
+ throw error;
507
+ }
508
+ }
479
509
  close() {
480
510
  // No cleanup needed for API client
481
511
  }
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,12 +90,16 @@ 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 ID (UUID) or refId (number) of the work item'),
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({
91
97
  work_item_id: z.string().describe('The ID of the work item'),
92
98
  description: z.string().describe('Updated description/notes for the work item'),
99
+ project_slug: z
100
+ .string()
101
+ .optional()
102
+ .describe('Project slug (required for multi-project users, use list_projects to get slugs)'),
93
103
  });
94
104
  const VALID_STATUSES = [
95
105
  'pending',
@@ -105,6 +115,10 @@ const VALID_STATUSES = [
105
115
  const UpdateWorkItemStatusSchema = z.object({
106
116
  work_item_id: z.string().describe('The ID of the work item'),
107
117
  status: z.enum(VALID_STATUSES).describe('New status'),
118
+ project_slug: z
119
+ .string()
120
+ .optional()
121
+ .describe('Project slug (required for multi-project users, use list_projects to get slugs)'),
108
122
  });
109
123
  const UpdateWorkItemAssigneeSchema = z.object({
110
124
  work_item_id: z.string().describe('The ID of the work item'),
@@ -112,10 +126,18 @@ const UpdateWorkItemAssigneeSchema = z.object({
112
126
  .string()
113
127
  .nullable()
114
128
  .describe('User ID to assign as leading user, or null to unassign'),
129
+ project_slug: z
130
+ .string()
131
+ .optional()
132
+ .describe('Project slug (required for multi-project users, use list_projects to get slugs)'),
115
133
  });
116
134
  const UpdateWorkItemTitleSchema = z.object({
117
135
  work_item_id: z.string().describe('The ID of the work item'),
118
136
  title: z.string().describe('New title for the work item'),
137
+ project_slug: z
138
+ .string()
139
+ .optional()
140
+ .describe('Project slug (required for multi-project users, use list_projects to get slugs)'),
119
141
  });
120
142
  const UpdateWorkItemInitiativeSchema = z.object({
121
143
  work_item_id: z.string().describe('The ID of the work item'),
@@ -123,6 +145,10 @@ const UpdateWorkItemInitiativeSchema = z.object({
123
145
  .string()
124
146
  .nullable()
125
147
  .describe('Radar/initiative item ID to link to, or null to unlink'),
148
+ project_slug: z
149
+ .string()
150
+ .optional()
151
+ .describe('Project slug (required for multi-project users, use list_projects to get slugs)'),
126
152
  });
127
153
  const PullWorkItemSchema = z.object({
128
154
  work_item_id: z.string().describe('The ID of the work item to pull from backlog'),
@@ -130,10 +156,18 @@ const PullWorkItemSchema = z.object({
130
156
  .string()
131
157
  .optional()
132
158
  .describe('User ID to assign as leading user (defaults to API key owner)'),
159
+ project_slug: z
160
+ .string()
161
+ .optional()
162
+ .describe('Project slug (required for multi-project users, use list_projects to get slugs)'),
133
163
  });
134
164
  const SubmitWorkItemFormSchema = z.object({
135
165
  work_item_id: z.string().describe('The ID of the work item'),
136
166
  form_values: z.record(z.any()).describe('Key-value pairs matching formDefinition field names'),
167
+ project_slug: z
168
+ .string()
169
+ .optional()
170
+ .describe('Project slug (required for multi-project users, use list_projects to get slugs)'),
137
171
  });
138
172
  // Radar Item (Initiative/Roadmap) schemas
139
173
  const ListRadarItemsSchema = z.object({
@@ -147,7 +181,7 @@ const ListRadarItemsSchema = z.object({
147
181
  offset: z.number().optional().describe('Number of items to skip'),
148
182
  });
149
183
  const GetRadarItemSchema = z.object({
150
- item_id: z.string().describe('The ID (UUID) or refId (number) of the radar item'),
184
+ item_id: z.string().describe('The refId (number) of the radar item'),
151
185
  project_slug: z.string().optional().describe('Project slug (required when looking up by refId)'),
152
186
  });
153
187
  // Issue schemas
@@ -184,7 +218,7 @@ const ListIssuesSchema = z.object({
184
218
  offset: z.number().optional().describe('Number of items to skip'),
185
219
  });
186
220
  const GetIssueSchema = z.object({
187
- issue_id: z.string().describe('The ID (UUID) or refId (number) of the issue'),
221
+ issue_id: z.string().describe('The refId (number) of the issue'),
188
222
  project_slug: z.string().optional().describe('Project slug (required when looking up by refId)'),
189
223
  });
190
224
  // Create schemas
@@ -229,7 +263,7 @@ const CreateIssueSchema = z.object({
229
263
  actual_behavior: z.string().optional().describe('Actual behavior observed'),
230
264
  });
231
265
  const UpdateIssueSchema = z.object({
232
- issue_id: z.string().describe('The ID (UUID) of the issue to update'),
266
+ issue_id: z.string().describe('The refId (number) of the issue to update'),
233
267
  title: z.string().optional().describe('Updated title'),
234
268
  description: z.string().optional().describe('Updated description'),
235
269
  status: z
@@ -239,6 +273,10 @@ const UpdateIssueSchema = z.object({
239
273
  severity: z.enum(['low', 'medium', 'high', 'critical']).optional().describe('Updated severity'),
240
274
  assigned_to_id: z.string().optional().describe('Updated assignee'),
241
275
  closing_note: z.string().optional().describe('Closing note (when closing the issue)'),
276
+ project_slug: z
277
+ .string()
278
+ .optional()
279
+ .describe('Project slug (required for multi-project users, use list_projects to get slugs)'),
242
280
  });
243
281
  // Wiki Page schemas
244
282
  const ListWikiPagesSchema = z.object({
@@ -256,7 +294,7 @@ const ListWikiPagesSchema = z.object({
256
294
  offset: z.number().optional().describe('Number of pages to skip'),
257
295
  });
258
296
  const GetWikiPageSchema = z.object({
259
- page_id: z.string().describe('The page UUID or slug'),
297
+ page_id: z.string().describe('The page slug'),
260
298
  });
261
299
  const CreateWikiPageSchema = z.object({
262
300
  project_slug: z
@@ -275,9 +313,13 @@ const CreateWikiPageSchema = z.object({
275
313
  content: z.string().describe('Page content (markdown)'),
276
314
  });
277
315
  const UpdateWikiPageSchema = z.object({
278
- page_id: z.string().describe('The page UUID'),
316
+ page_id: z.string().describe('The page slug'),
279
317
  title: z.string().optional().describe('Updated title'),
280
318
  content: z.string().optional().describe('Updated content (markdown)'),
319
+ project_slug: z
320
+ .string()
321
+ .optional()
322
+ .describe('Project slug (required for multi-project users, use list_projects to get slugs)'),
281
323
  });
282
324
  // Journal Entry schemas
283
325
  const ListJournalEntriesSchema = z.object({
@@ -295,8 +337,8 @@ const ListJournalEntriesSchema = z.object({
295
337
  offset: z.number().optional().describe('Number of entries to skip'),
296
338
  });
297
339
  const GetJournalEntrySchema = z.object({
298
- entry_id: z.string().describe('The entry UUID or refId'),
299
- project_slug: z.string().optional().describe('Project slug (required when looking up by refId)'),
340
+ entry_id: z.string().describe('The entry refId (number)'),
341
+ project_slug: z.string().optional().describe('Project slug (required for refId lookup)'),
300
342
  });
301
343
  const CreateJournalEntrySchema = z.object({
302
344
  project_slug: z
@@ -305,27 +347,46 @@ const CreateJournalEntrySchema = z.object({
305
347
  .describe('Project slug (required for multi-project users, use list_projects to get slugs)'),
306
348
  title: z.string().describe('Entry title'),
307
349
  content: z.string().describe('Entry content (markdown)'),
308
- date: z.string().optional().describe('Entry date (ISO format, defaults to now)'),
309
350
  });
310
351
  const UpdateJournalEntrySchema = z.object({
311
- entry_id: z.string().describe('The entry UUID'),
352
+ entry_id: z.string().describe('The entry refId (number)'),
312
353
  title: z.string().optional().describe('Updated title'),
313
354
  content: z.string().optional().describe('Updated content (markdown)'),
355
+ project_slug: z
356
+ .string()
357
+ .optional()
358
+ .describe('Project slug (required for multi-project users, use list_projects to get slugs)'),
314
359
  });
315
360
  // Comment schemas
316
361
  const ListWorkItemCommentsSchema = z.object({
317
- work_item_id: z.string().describe('The work item UUID'),
362
+ work_item_id: z.string().describe('The work item refId (number)'),
363
+ project_slug: z
364
+ .string()
365
+ .optional()
366
+ .describe('Project slug (required for multi-project users, use list_projects to get slugs)'),
318
367
  });
319
368
  const ListIssueCommentsSchema = z.object({
320
- issue_id: z.string().describe('The issue UUID'),
369
+ issue_id: z.string().describe('The issue refId (number)'),
370
+ project_slug: z
371
+ .string()
372
+ .optional()
373
+ .describe('Project slug (required for multi-project users, use list_projects to get slugs)'),
321
374
  });
322
375
  const CreateWorkItemCommentSchema = z.object({
323
- work_item_id: z.string().describe('The work item UUID'),
376
+ work_item_id: z.string().describe('The work item refId (number)'),
324
377
  content: z.string().describe('Comment content (markdown)'),
378
+ project_slug: z
379
+ .string()
380
+ .optional()
381
+ .describe('Project slug (required for multi-project users, use list_projects to get slugs)'),
325
382
  });
326
383
  const CreateIssueCommentSchema = z.object({
327
- issue_id: z.string().describe('The issue UUID'),
384
+ issue_id: z.string().describe('The issue refId (number)'),
328
385
  content: z.string().describe('Comment content (markdown)'),
386
+ project_slug: z
387
+ .string()
388
+ .optional()
389
+ .describe('Project slug (required for multi-project users, use list_projects to get slugs)'),
329
390
  });
330
391
  // Image upload schema
331
392
  const UploadImageSchema = z.object({
@@ -343,6 +404,54 @@ const DownloadImageSchema = z.object({
343
404
  .string()
344
405
  .describe('The image URL path found in content fields (e.g. "/api/files/images/{team}/{filename}").'),
345
406
  });
407
+ // Skill schemas
408
+ const GetSkillSchema = z.object({
409
+ skill_name: z.string().describe('The name of the skill to load (e.g. "deploy-app")'),
410
+ });
411
+ const GetSkillResourceSchema = z.object({
412
+ skill_name: z.string().describe('The name of the skill'),
413
+ resource_name: z.string().describe('The name of the resource file'),
414
+ });
415
+ // UUID v4 field names to remove from responses.
416
+ // These are internal database IDs that agents should not use.
417
+ // Agents should use refId (sequential int) or slug instead.
418
+ const UUID_FIELDS_TO_STRIP = new Set([
419
+ 'id', // Main entity UUID - replaced by refId or slug
420
+ 'teamId', // Internal team UUID - noise for agents
421
+ 'workItemId', // Cross-reference UUID on Issues - noise
422
+ ]);
423
+ // Fields containing user-defined data that should never be recursively processed.
424
+ const PASSTHROUGH_FIELDS = new Set(['formDefinition', 'formValues']);
425
+ // Strip UUID v4 fields from response objects so agents use refId/slug instead.
426
+ // Preserves Clerk user IDs (user_xxx format) and operational fields (categoryId, radarItemId).
427
+ function stripUuids(obj) {
428
+ if (obj === null || obj === undefined)
429
+ return obj;
430
+ if (Array.isArray(obj))
431
+ return obj.map(stripUuids);
432
+ if (typeof obj !== 'object')
433
+ return obj;
434
+ const record = obj;
435
+ const result = {};
436
+ for (const [key, value] of Object.entries(record)) {
437
+ // Skip UUID fields
438
+ if (UUID_FIELDS_TO_STRIP.has(key))
439
+ continue;
440
+ // Preserve user-defined data fields as-is (no recursive stripping)
441
+ if (PASSTHROUGH_FIELDS.has(key)) {
442
+ result[key] = value;
443
+ continue;
444
+ }
445
+ // Recurse into nested objects/arrays
446
+ if (typeof value === 'object' && value !== null) {
447
+ result[key] = stripUuids(value);
448
+ }
449
+ else {
450
+ result[key] = value;
451
+ }
452
+ }
453
+ return result;
454
+ }
346
455
  // Helper to detect if a work item description contains a plan
347
456
  function hasPlan(description) {
348
457
  if (!description)
@@ -458,7 +567,7 @@ class WolfpackMCPServer {
458
567
  },
459
568
  {
460
569
  name: 'get_work_item',
461
- description: 'Get a specific work item/task by ID or reference number. Returns full details including description (markdown notes). ' +
570
+ description: 'Get a specific work item/task by reference number. Returns full details including description (markdown notes). ' +
462
571
  'Call this before updating to see current content. ' +
463
572
  'WORKFLOW: When asked to work on an item, check its status and follow the required state transitions ' +
464
573
  '(pending→pull first, new→doing, blocked/ready/completed/closed→new→doing, then review when done). ' +
@@ -470,11 +579,11 @@ class WolfpackMCPServer {
470
579
  properties: {
471
580
  work_item_id: {
472
581
  type: 'string',
473
- description: 'The ID (UUID) or refId (number) of the work item',
582
+ description: 'The refId (number) of the work item',
474
583
  },
475
584
  project_slug: {
476
585
  type: 'string',
477
- description: 'Project slug (required when looking up by refId)',
586
+ description: 'Project slug (required for refId lookup)',
478
587
  },
479
588
  },
480
589
  required: ['work_item_id'],
@@ -484,7 +593,8 @@ class WolfpackMCPServer {
484
593
  name: 'update_work_progress',
485
594
  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. ' +
486
595
  '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). ' +
487
- '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).',
596
+ '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). ' +
597
+ CONTENT_LINKING_HELP,
488
598
  inputSchema: {
489
599
  type: 'object',
490
600
  properties: {
@@ -662,18 +772,18 @@ class WolfpackMCPServer {
662
772
  },
663
773
  {
664
774
  name: 'get_radar_item',
665
- description: 'Get a specific radar item (initiative) by ID or refId, including its work items and participants. ' +
775
+ description: 'Get a specific radar item (initiative) by reference number, including its work items and participants. ' +
666
776
  'IMAGES: Image references in the description (e.g. `![alt](/api/files/images/...)`) can be viewed using the download_image tool.',
667
777
  inputSchema: {
668
778
  type: 'object',
669
779
  properties: {
670
780
  item_id: {
671
781
  type: 'string',
672
- description: 'The ID (UUID) or refId (number) of the radar item',
782
+ description: 'The refId (number) of the radar item',
673
783
  },
674
784
  project_slug: {
675
785
  type: 'string',
676
- description: 'Project slug (required when looking up by refId)',
786
+ description: 'Project slug (required for refId lookup)',
677
787
  },
678
788
  },
679
789
  required: ['item_id'],
@@ -740,18 +850,18 @@ class WolfpackMCPServer {
740
850
  },
741
851
  {
742
852
  name: 'get_issue',
743
- description: 'Get a specific issue by ID or refId, including comment and attachment counts. ' +
853
+ description: 'Get a specific issue by reference number, including comment and attachment counts. ' +
744
854
  'IMAGES: Image references in the description (e.g. `![alt](/api/files/images/...)`) can be viewed using the download_image tool.',
745
855
  inputSchema: {
746
856
  type: 'object',
747
857
  properties: {
748
858
  issue_id: {
749
859
  type: 'string',
750
- description: 'The ID (UUID) or refId (number) of the issue',
860
+ description: 'The refId (number) of the issue',
751
861
  },
752
862
  project_slug: {
753
863
  type: 'string',
754
- description: 'Project slug (required when looking up by refId)',
864
+ description: 'Project slug (required for refId lookup)',
755
865
  },
756
866
  },
757
867
  required: ['issue_id'],
@@ -760,7 +870,8 @@ class WolfpackMCPServer {
760
870
  // Create/Update tools
761
871
  {
762
872
  name: 'create_work_item',
763
- 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.',
873
+ 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. ' +
874
+ CONTENT_LINKING_HELP,
764
875
  inputSchema: {
765
876
  type: 'object',
766
877
  properties: {
@@ -815,7 +926,8 @@ class WolfpackMCPServer {
815
926
  },
816
927
  {
817
928
  name: 'create_issue',
818
- 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.',
929
+ 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. ' +
930
+ CONTENT_LINKING_HELP,
819
931
  inputSchema: {
820
932
  type: 'object',
821
933
  properties: {
@@ -848,11 +960,15 @@ class WolfpackMCPServer {
848
960
  },
849
961
  {
850
962
  name: 'update_issue',
851
- description: 'Update an existing issue. Requires mcp:issues:update permission.',
963
+ description: 'Update an existing issue. Requires mcp:issues:update permission. ' +
964
+ CONTENT_LINKING_HELP,
852
965
  inputSchema: {
853
966
  type: 'object',
854
967
  properties: {
855
- issue_id: { type: 'string', description: 'The ID (UUID) of the issue to update' },
968
+ issue_id: {
969
+ type: 'string',
970
+ description: 'The refId (number) of the issue to update',
971
+ },
856
972
  title: { type: 'string', description: 'Updated title' },
857
973
  description: { type: 'string', description: 'Updated description' },
858
974
  status: {
@@ -904,14 +1020,14 @@ class WolfpackMCPServer {
904
1020
  },
905
1021
  {
906
1022
  name: 'get_wiki_page',
907
- description: 'Get a specific wiki/documentation page by ID or slug (URL path). Returns full content in markdown. ' +
1023
+ description: 'Get a specific wiki/documentation page by slug (URL path). Returns full content in markdown. ' +
908
1024
  'IMAGES: Image references in the content (e.g. `![alt](/api/files/images/...)`) can be viewed using the download_image tool.',
909
1025
  inputSchema: {
910
1026
  type: 'object',
911
1027
  properties: {
912
1028
  page_id: {
913
1029
  type: 'string',
914
- description: 'The page UUID or slug (URL path like "getting-started")',
1030
+ description: 'The page slug (URL path like "getting-started")',
915
1031
  },
916
1032
  },
917
1033
  required: ['page_id'],
@@ -919,7 +1035,8 @@ class WolfpackMCPServer {
919
1035
  },
920
1036
  {
921
1037
  name: 'create_wiki_page',
922
- description: 'Create a new wiki/documentation page. Use when user wants to "add docs", "create documentation", or "write a guide".',
1038
+ description: 'Create a new wiki/documentation page. Use when user wants to "add docs", "create documentation", or "write a guide". ' +
1039
+ CONTENT_LINKING_HELP,
923
1040
  inputSchema: {
924
1041
  type: 'object',
925
1042
  properties: {
@@ -942,11 +1059,12 @@ class WolfpackMCPServer {
942
1059
  },
943
1060
  {
944
1061
  name: 'update_wiki_page',
945
- description: 'Update an existing wiki page. Requires mcp:wiki:update permission.',
1062
+ description: 'Update an existing wiki page. Requires mcp:wiki:update permission. ' +
1063
+ CONTENT_LINKING_HELP,
946
1064
  inputSchema: {
947
1065
  type: 'object',
948
1066
  properties: {
949
- page_id: { type: 'string', description: 'The page UUID' },
1067
+ page_id: { type: 'string', description: 'The page slug' },
950
1068
  title: { type: 'string', description: 'Updated title' },
951
1069
  content: {
952
1070
  type: 'string',
@@ -986,15 +1104,15 @@ class WolfpackMCPServer {
986
1104
  },
987
1105
  {
988
1106
  name: 'get_journal_entry',
989
- description: 'Get a specific journal/log entry by ID or reference number. Returns full content. ' +
1107
+ description: 'Get a specific journal/log entry by reference number. Returns full content. ' +
990
1108
  'IMAGES: Image references in the content (e.g. `![alt](/api/files/images/...)`) can be viewed using the download_image tool.',
991
1109
  inputSchema: {
992
1110
  type: 'object',
993
1111
  properties: {
994
- entry_id: { type: 'string', description: 'The entry UUID or refId' },
1112
+ entry_id: { type: 'string', description: 'The entry refId (number)' },
995
1113
  project_slug: {
996
1114
  type: 'string',
997
- description: 'Project slug (required when looking up by refId)',
1115
+ description: 'Project slug (required for refId lookup)',
998
1116
  },
999
1117
  },
1000
1118
  required: ['entry_id'],
@@ -1002,7 +1120,8 @@ class WolfpackMCPServer {
1002
1120
  },
1003
1121
  {
1004
1122
  name: 'create_journal_entry',
1005
- 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".',
1123
+ 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". ' +
1124
+ CONTENT_LINKING_HELP,
1006
1125
  inputSchema: {
1007
1126
  type: 'object',
1008
1127
  properties: {
@@ -1015,18 +1134,18 @@ class WolfpackMCPServer {
1015
1134
  type: 'string',
1016
1135
  description: 'Entry content (markdown)',
1017
1136
  },
1018
- date: { type: 'string', description: 'Entry date (ISO format, defaults to now)' },
1019
1137
  },
1020
1138
  required: ['title', 'content'],
1021
1139
  },
1022
1140
  },
1023
1141
  {
1024
1142
  name: 'update_journal_entry',
1025
- description: 'Update an existing journal entry. Requires mcp:journal:update permission.',
1143
+ description: 'Update an existing journal entry. Requires mcp:journal:update permission. ' +
1144
+ CONTENT_LINKING_HELP,
1026
1145
  inputSchema: {
1027
1146
  type: 'object',
1028
1147
  properties: {
1029
- entry_id: { type: 'string', description: 'The entry UUID' },
1148
+ entry_id: { type: 'string', description: 'The entry refId (number)' },
1030
1149
  title: { type: 'string', description: 'Updated title' },
1031
1150
  content: {
1032
1151
  type: 'string',
@@ -1044,7 +1163,7 @@ class WolfpackMCPServer {
1044
1163
  inputSchema: {
1045
1164
  type: 'object',
1046
1165
  properties: {
1047
- work_item_id: { type: 'string', description: 'The work item UUID' },
1166
+ work_item_id: { type: 'string', description: 'The work item refId (number)' },
1048
1167
  },
1049
1168
  required: ['work_item_id'],
1050
1169
  },
@@ -1056,7 +1175,7 @@ class WolfpackMCPServer {
1056
1175
  inputSchema: {
1057
1176
  type: 'object',
1058
1177
  properties: {
1059
- issue_id: { type: 'string', description: 'The issue UUID' },
1178
+ issue_id: { type: 'string', description: 'The issue refId (number)' },
1060
1179
  },
1061
1180
  required: ['issue_id'],
1062
1181
  },
@@ -1068,11 +1187,12 @@ class WolfpackMCPServer {
1068
1187
  '2) Completion summaries when moving to "review" (what was done, files changed, testing notes). ' +
1069
1188
  '3) Important observations or decisions that should be visible in the activity history. ' +
1070
1189
  'USE DESCRIPTION (update_work_progress) FOR: Plans, checklists, and progress tracking that need to be updated over time. ' +
1071
- 'Comments are typically not used in personal projects.',
1190
+ 'Comments are typically not used in personal projects. ' +
1191
+ CONTENT_LINKING_HELP,
1072
1192
  inputSchema: {
1073
1193
  type: 'object',
1074
1194
  properties: {
1075
- work_item_id: { type: 'string', description: 'The work item UUID' },
1195
+ work_item_id: { type: 'string', description: 'The work item refId (number)' },
1076
1196
  content: {
1077
1197
  type: 'string',
1078
1198
  description: 'Comment content (markdown)',
@@ -1083,11 +1203,12 @@ class WolfpackMCPServer {
1083
1203
  },
1084
1204
  {
1085
1205
  name: 'create_issue_comment',
1086
- description: 'Add a comment to an issue. Requires mcp:comments:create permission.',
1206
+ description: 'Add a comment to an issue. Requires mcp:comments:create permission. ' +
1207
+ CONTENT_LINKING_HELP,
1087
1208
  inputSchema: {
1088
1209
  type: 'object',
1089
1210
  properties: {
1090
- issue_id: { type: 'string', description: 'The issue UUID' },
1211
+ issue_id: { type: 'string', description: 'The issue refId (number)' },
1091
1212
  content: {
1092
1213
  type: 'string',
1093
1214
  description: 'Comment content (markdown)',
@@ -1138,6 +1259,51 @@ class WolfpackMCPServer {
1138
1259
  required: ['image_url'],
1139
1260
  },
1140
1261
  },
1262
+ // Skill tools (progressive disclosure)
1263
+ {
1264
+ name: 'list_skills',
1265
+ description: 'List all skills available to the current agent. Returns lean metadata (name + description) for each skill. ' +
1266
+ 'Use get_skill to load the full instructions for a specific skill when needed.',
1267
+ inputSchema: {
1268
+ type: 'object',
1269
+ properties: {},
1270
+ },
1271
+ },
1272
+ {
1273
+ name: 'get_skill',
1274
+ description: 'Load the full instruction content for a specific skill by name. ' +
1275
+ "Call this when a task matches a skill's description to get detailed instructions before proceeding. " +
1276
+ 'Also returns a list of available resources (scripts, references, assets).',
1277
+ inputSchema: {
1278
+ type: 'object',
1279
+ properties: {
1280
+ skill_name: {
1281
+ type: 'string',
1282
+ description: 'The name of the skill to load (e.g. "deploy-app")',
1283
+ },
1284
+ },
1285
+ required: ['skill_name'],
1286
+ },
1287
+ },
1288
+ {
1289
+ name: 'get_skill_resource',
1290
+ description: 'Get a specific resource file attached to a skill. ' +
1291
+ 'Resources can be scripts, reference documents, or assets that supplement the skill instructions.',
1292
+ inputSchema: {
1293
+ type: 'object',
1294
+ properties: {
1295
+ skill_name: {
1296
+ type: 'string',
1297
+ description: 'The name of the skill',
1298
+ },
1299
+ resource_name: {
1300
+ type: 'string',
1301
+ description: 'The name of the resource file',
1302
+ },
1303
+ },
1304
+ required: ['skill_name', 'resource_name'],
1305
+ },
1306
+ },
1141
1307
  ],
1142
1308
  }));
1143
1309
  this.server.setRequestHandler(CallToolRequestSchema, async (request) => {
@@ -1183,7 +1349,7 @@ class WolfpackMCPServer {
1183
1349
  limit: parsed.limit,
1184
1350
  offset: parsed.offset,
1185
1351
  });
1186
- let text = JSON.stringify(result.items, null, 2);
1352
+ let text = JSON.stringify(stripUuids(result.items), null, 2);
1187
1353
  if (result.truncated) {
1188
1354
  text = `Note: Results truncated. Showing ${result.items.length} of ${result.total} items. Use filters or limit/offset for pagination.\n\n${text}`;
1189
1355
  }
@@ -1195,7 +1361,7 @@ class WolfpackMCPServer {
1195
1361
  const parsed = GetWorkItemSchema.parse(args);
1196
1362
  const workItem = await this.client.getWorkItem(parsed.work_item_id, parsed.project_slug || this.client.getProjectSlug() || undefined);
1197
1363
  if (workItem) {
1198
- let text = JSON.stringify(workItem, null, 2);
1364
+ let text = JSON.stringify(stripUuids(workItem), null, 2);
1199
1365
  // Add hint if no plan detected in description
1200
1366
  if (!hasPlan(workItem.description)) {
1201
1367
  text =
@@ -1212,13 +1378,14 @@ class WolfpackMCPServer {
1212
1378
  }
1213
1379
  case 'update_work_progress': {
1214
1380
  const parsed = UpdateWorkProgressSchema.parse(args);
1215
- const workItem = await this.client.updateWorkProgress(parsed.work_item_id, parsed.description);
1381
+ const teamSlug = parsed.project_slug || this.client.getProjectSlug() || undefined;
1382
+ const workItem = await this.client.updateWorkProgress(parsed.work_item_id, parsed.description, teamSlug);
1216
1383
  if (workItem) {
1217
1384
  return {
1218
1385
  content: [
1219
1386
  {
1220
1387
  type: 'text',
1221
- text: `Updated description on: ${workItem.title}\n\n${JSON.stringify(workItem, null, 2)}`,
1388
+ text: `Updated description on: ${workItem.title}\n\n${JSON.stringify(stripUuids(workItem), null, 2)}`,
1222
1389
  },
1223
1390
  ],
1224
1391
  };
@@ -1229,13 +1396,14 @@ class WolfpackMCPServer {
1229
1396
  }
1230
1397
  case 'update_work_item_status': {
1231
1398
  const parsed = UpdateWorkItemStatusSchema.parse(args);
1232
- const workItem = await this.client.updateWorkItemStatus(parsed.work_item_id, parsed.status);
1399
+ const teamSlug = parsed.project_slug || this.client.getProjectSlug() || undefined;
1400
+ const workItem = await this.client.updateWorkItemStatus(parsed.work_item_id, parsed.status, teamSlug);
1233
1401
  if (workItem) {
1234
1402
  return {
1235
1403
  content: [
1236
1404
  {
1237
1405
  type: 'text',
1238
- text: `Updated status of "${workItem.title}" to ${parsed.status}\n\n${JSON.stringify(workItem, null, 2)}`,
1406
+ text: `Updated status of "${workItem.title}" to ${parsed.status}\n\n${JSON.stringify(stripUuids(workItem), null, 2)}`,
1239
1407
  },
1240
1408
  ],
1241
1409
  };
@@ -1246,9 +1414,10 @@ class WolfpackMCPServer {
1246
1414
  }
1247
1415
  case 'update_work_item_assignee': {
1248
1416
  const parsed = UpdateWorkItemAssigneeSchema.parse(args);
1417
+ const teamSlug = parsed.project_slug || this.client.getProjectSlug() || undefined;
1249
1418
  const workItem = await this.client.updateWorkItemAssignee(parsed.work_item_id, {
1250
1419
  leadingUserId: parsed.leading_user_id,
1251
- });
1420
+ }, teamSlug);
1252
1421
  if (workItem) {
1253
1422
  const assigneeText = parsed.leading_user_id
1254
1423
  ? `assigned to ${parsed.leading_user_id}`
@@ -1257,7 +1426,7 @@ class WolfpackMCPServer {
1257
1426
  content: [
1258
1427
  {
1259
1428
  type: 'text',
1260
- text: `Updated "${workItem.title}" - now ${assigneeText}\n\n${JSON.stringify(workItem, null, 2)}`,
1429
+ text: `Updated "${workItem.title}" - now ${assigneeText}\n\n${JSON.stringify(stripUuids(workItem), null, 2)}`,
1261
1430
  },
1262
1431
  ],
1263
1432
  };
@@ -1268,13 +1437,14 @@ class WolfpackMCPServer {
1268
1437
  }
1269
1438
  case 'update_work_item_title': {
1270
1439
  const parsed = UpdateWorkItemTitleSchema.parse(args);
1271
- const workItem = await this.client.updateWorkItemTitle(parsed.work_item_id, parsed.title);
1440
+ const teamSlug = parsed.project_slug || this.client.getProjectSlug() || undefined;
1441
+ const workItem = await this.client.updateWorkItemTitle(parsed.work_item_id, parsed.title, teamSlug);
1272
1442
  if (workItem) {
1273
1443
  return {
1274
1444
  content: [
1275
1445
  {
1276
1446
  type: 'text',
1277
- text: `Updated title to "${workItem.title}"\n\n${JSON.stringify(workItem, null, 2)}`,
1447
+ text: `Updated title to "${workItem.title}"\n\n${JSON.stringify(stripUuids(workItem), null, 2)}`,
1278
1448
  },
1279
1449
  ],
1280
1450
  };
@@ -1285,7 +1455,8 @@ class WolfpackMCPServer {
1285
1455
  }
1286
1456
  case 'update_work_item_initiative': {
1287
1457
  const parsed = UpdateWorkItemInitiativeSchema.parse(args);
1288
- const workItem = await this.client.updateWorkItemInitiative(parsed.work_item_id, parsed.radar_item_id);
1458
+ const teamSlug = parsed.project_slug || this.client.getProjectSlug() || undefined;
1459
+ const workItem = await this.client.updateWorkItemInitiative(parsed.work_item_id, parsed.radar_item_id, teamSlug);
1289
1460
  if (workItem) {
1290
1461
  const initiativeText = parsed.radar_item_id
1291
1462
  ? `linked to initiative ${parsed.radar_item_id}`
@@ -1294,7 +1465,7 @@ class WolfpackMCPServer {
1294
1465
  content: [
1295
1466
  {
1296
1467
  type: 'text',
1297
- text: `Updated "${workItem.title}" - ${initiativeText}\n\n${JSON.stringify(workItem, null, 2)}`,
1468
+ text: `Updated "${workItem.title}" - ${initiativeText}\n\n${JSON.stringify(stripUuids(workItem), null, 2)}`,
1298
1469
  },
1299
1470
  ],
1300
1471
  };
@@ -1305,15 +1476,16 @@ class WolfpackMCPServer {
1305
1476
  }
1306
1477
  case 'pull_work_item': {
1307
1478
  const parsed = PullWorkItemSchema.parse(args);
1479
+ const teamSlug = parsed.project_slug || this.client.getProjectSlug() || undefined;
1308
1480
  const workItem = await this.client.pullWorkItem(parsed.work_item_id, {
1309
1481
  leadingUserId: parsed.leading_user_id,
1310
- });
1482
+ }, teamSlug);
1311
1483
  if (workItem) {
1312
1484
  return {
1313
1485
  content: [
1314
1486
  {
1315
1487
  type: 'text',
1316
- text: `Pulled "${workItem.title}" from backlog to board (status: new)\n\n${JSON.stringify(workItem, null, 2)}`,
1488
+ text: `Pulled "${workItem.title}" from backlog to board (status: new)\n\n${JSON.stringify(stripUuids(workItem), null, 2)}`,
1317
1489
  },
1318
1490
  ],
1319
1491
  };
@@ -1324,13 +1496,14 @@ class WolfpackMCPServer {
1324
1496
  }
1325
1497
  case 'submit_work_item_form': {
1326
1498
  const parsed = SubmitWorkItemFormSchema.parse(args);
1327
- const workItem = await this.client.submitWorkItemForm(parsed.work_item_id, parsed.form_values);
1499
+ const teamSlug = parsed.project_slug || this.client.getProjectSlug() || undefined;
1500
+ const workItem = await this.client.submitWorkItemForm(parsed.work_item_id, parsed.form_values, teamSlug);
1328
1501
  if (workItem) {
1329
1502
  return {
1330
1503
  content: [
1331
1504
  {
1332
1505
  type: 'text',
1333
- text: `Submitted form values for "${workItem.title}"\n\n${JSON.stringify(workItem, null, 2)}`,
1506
+ text: `Submitted form values for "${workItem.title}"\n\n${JSON.stringify(stripUuids(workItem), null, 2)}`,
1334
1507
  },
1335
1508
  ],
1336
1509
  };
@@ -1349,7 +1522,7 @@ class WolfpackMCPServer {
1349
1522
  limit: parsed.limit,
1350
1523
  offset: parsed.offset,
1351
1524
  });
1352
- let text = JSON.stringify(result.items, null, 2);
1525
+ let text = JSON.stringify(stripUuids(result.items), null, 2);
1353
1526
  if (result.truncated) {
1354
1527
  text = `Note: Results truncated. Showing ${result.items.length} of ${result.total} items. Use stage filter or limit/offset for pagination.\n\n${text}`;
1355
1528
  }
@@ -1362,7 +1535,7 @@ class WolfpackMCPServer {
1362
1535
  const radarItem = await this.client.getRadarItem(parsed.item_id, parsed.project_slug);
1363
1536
  if (radarItem) {
1364
1537
  return {
1365
- content: [{ type: 'text', text: JSON.stringify(radarItem, null, 2) }],
1538
+ content: [{ type: 'text', text: JSON.stringify(stripUuids(radarItem), null, 2) }],
1366
1539
  };
1367
1540
  }
1368
1541
  return {
@@ -1386,7 +1559,7 @@ class WolfpackMCPServer {
1386
1559
  limit: parsed.limit,
1387
1560
  offset: parsed.offset,
1388
1561
  });
1389
- let text = JSON.stringify(result.items, null, 2);
1562
+ let text = JSON.stringify(stripUuids(result.items), null, 2);
1390
1563
  if (result.truncated) {
1391
1564
  text = `Note: Results truncated. Showing ${result.items.length} of ${result.total} items. Use filters or limit/offset for pagination.\n\n${text}`;
1392
1565
  }
@@ -1399,7 +1572,7 @@ class WolfpackMCPServer {
1399
1572
  const issue = await this.client.getIssue(parsed.issue_id, parsed.project_slug);
1400
1573
  if (issue) {
1401
1574
  return {
1402
- content: [{ type: 'text', text: JSON.stringify(issue, null, 2) }],
1575
+ content: [{ type: 'text', text: JSON.stringify(stripUuids(issue), null, 2) }],
1403
1576
  };
1404
1577
  }
1405
1578
  return {
@@ -1424,7 +1597,7 @@ class WolfpackMCPServer {
1424
1597
  content: [
1425
1598
  {
1426
1599
  type: 'text',
1427
- text: `Created work item #${workItem.refId}: ${workItem.title}\n\n${JSON.stringify(workItem, null, 2)}`,
1600
+ text: `Created work item #${workItem.refId}: ${workItem.title}\n\n${JSON.stringify(stripUuids(workItem), null, 2)}`,
1428
1601
  },
1429
1602
  ],
1430
1603
  };
@@ -1449,13 +1622,14 @@ class WolfpackMCPServer {
1449
1622
  content: [
1450
1623
  {
1451
1624
  type: 'text',
1452
- text: `Created issue #${issue.refId}: ${issue.title}\n\n${JSON.stringify(issue, null, 2)}`,
1625
+ text: `Created issue #${issue.refId}: ${issue.title}\n\n${JSON.stringify(stripUuids(issue), null, 2)}`,
1453
1626
  },
1454
1627
  ],
1455
1628
  };
1456
1629
  }
1457
1630
  case 'update_issue': {
1458
1631
  const parsed = UpdateIssueSchema.parse(args);
1632
+ const teamSlug = parsed.project_slug || this.client.getProjectSlug() || undefined;
1459
1633
  const issue = await this.client.updateIssue(parsed.issue_id, {
1460
1634
  title: parsed.title,
1461
1635
  description: parsed.description,
@@ -1463,12 +1637,12 @@ class WolfpackMCPServer {
1463
1637
  severity: parsed.severity,
1464
1638
  assignedToId: parsed.assigned_to_id,
1465
1639
  closingNote: parsed.closing_note,
1466
- });
1640
+ }, teamSlug);
1467
1641
  return {
1468
1642
  content: [
1469
1643
  {
1470
1644
  type: 'text',
1471
- text: `Updated issue #${issue.refId}: ${issue.title}\n\n${JSON.stringify(issue, null, 2)}`,
1645
+ text: `Updated issue #${issue.refId}: ${issue.title}\n\n${JSON.stringify(stripUuids(issue), null, 2)}`,
1472
1646
  },
1473
1647
  ],
1474
1648
  };
@@ -1484,7 +1658,7 @@ class WolfpackMCPServer {
1484
1658
  limit: parsed.limit,
1485
1659
  offset: parsed.offset,
1486
1660
  });
1487
- let text = JSON.stringify(result.items, null, 2);
1661
+ let text = JSON.stringify(stripUuids(result.items), null, 2);
1488
1662
  if (result.truncated) {
1489
1663
  text = `Note: Results truncated. Showing ${result.items.length} of ${result.total} pages. Use limit/offset for pagination.\n\n${text}`;
1490
1664
  }
@@ -1497,7 +1671,7 @@ class WolfpackMCPServer {
1497
1671
  const page = await this.client.getWikiPage(parsed.page_id);
1498
1672
  if (page) {
1499
1673
  return {
1500
- content: [{ type: 'text', text: JSON.stringify(page, null, 2) }],
1674
+ content: [{ type: 'text', text: JSON.stringify(stripUuids(page), null, 2) }],
1501
1675
  };
1502
1676
  }
1503
1677
  return {
@@ -1516,22 +1690,23 @@ class WolfpackMCPServer {
1516
1690
  content: [
1517
1691
  {
1518
1692
  type: 'text',
1519
- text: `Created wiki page: ${page.title}\n\n${JSON.stringify(page, null, 2)}`,
1693
+ text: `Created wiki page: ${page.title}\n\n${JSON.stringify(stripUuids(page), null, 2)}`,
1520
1694
  },
1521
1695
  ],
1522
1696
  };
1523
1697
  }
1524
1698
  case 'update_wiki_page': {
1525
1699
  const parsed = UpdateWikiPageSchema.parse(args);
1700
+ const teamSlug = parsed.project_slug || this.client.getProjectSlug() || undefined;
1526
1701
  const page = await this.client.updateWikiPage(parsed.page_id, {
1527
1702
  title: parsed.title,
1528
1703
  content: parsed.content,
1529
- });
1704
+ }, teamSlug);
1530
1705
  return {
1531
1706
  content: [
1532
1707
  {
1533
1708
  type: 'text',
1534
- text: `Updated wiki page: ${page.title}\n\n${JSON.stringify(page, null, 2)}`,
1709
+ text: `Updated wiki page: ${page.title}\n\n${JSON.stringify(stripUuids(page), null, 2)}`,
1535
1710
  },
1536
1711
  ],
1537
1712
  };
@@ -1547,7 +1722,7 @@ class WolfpackMCPServer {
1547
1722
  limit: parsed.limit,
1548
1723
  offset: parsed.offset,
1549
1724
  });
1550
- let text = JSON.stringify(result.items, null, 2);
1725
+ let text = JSON.stringify(stripUuids(result.items), null, 2);
1551
1726
  if (result.truncated) {
1552
1727
  text = `Note: Results truncated. Showing ${result.items.length} of ${result.total} entries. Use limit/offset for pagination.\n\n${text}`;
1553
1728
  }
@@ -1560,7 +1735,7 @@ class WolfpackMCPServer {
1560
1735
  const entry = await this.client.getJournalEntry(parsed.entry_id, parsed.project_slug);
1561
1736
  if (entry) {
1562
1737
  return {
1563
- content: [{ type: 'text', text: JSON.stringify(entry, null, 2) }],
1738
+ content: [{ type: 'text', text: JSON.stringify(stripUuids(entry), null, 2) }],
1564
1739
  };
1565
1740
  }
1566
1741
  return {
@@ -1572,29 +1747,29 @@ class WolfpackMCPServer {
1572
1747
  const entry = await this.client.createJournalEntry({
1573
1748
  title: parsed.title,
1574
1749
  content: parsed.content,
1575
- date: parsed.date,
1576
1750
  teamSlug: parsed.project_slug || this.client.getProjectSlug() || undefined,
1577
1751
  });
1578
1752
  return {
1579
1753
  content: [
1580
1754
  {
1581
1755
  type: 'text',
1582
- text: `Created journal entry #${entry.refId}: ${entry.title}\n\n${JSON.stringify(entry, null, 2)}`,
1756
+ text: `Created journal entry #${entry.refId}: ${entry.title}\n\n${JSON.stringify(stripUuids(entry), null, 2)}`,
1583
1757
  },
1584
1758
  ],
1585
1759
  };
1586
1760
  }
1587
1761
  case 'update_journal_entry': {
1588
1762
  const parsed = UpdateJournalEntrySchema.parse(args);
1763
+ const teamSlug = parsed.project_slug || this.client.getProjectSlug() || undefined;
1589
1764
  const entry = await this.client.updateJournalEntry(parsed.entry_id, {
1590
1765
  title: parsed.title,
1591
1766
  content: parsed.content,
1592
- });
1767
+ }, teamSlug);
1593
1768
  return {
1594
1769
  content: [
1595
1770
  {
1596
1771
  type: 'text',
1597
- text: `Updated journal entry #${entry.refId}: ${entry.title}\n\n${JSON.stringify(entry, null, 2)}`,
1772
+ text: `Updated journal entry #${entry.refId}: ${entry.title}\n\n${JSON.stringify(stripUuids(entry), null, 2)}`,
1598
1773
  },
1599
1774
  ],
1600
1775
  };
@@ -1602,42 +1777,46 @@ class WolfpackMCPServer {
1602
1777
  // Comment handlers
1603
1778
  case 'list_work_item_comments': {
1604
1779
  const parsed = ListWorkItemCommentsSchema.parse(args);
1605
- const comments = await this.client.listWorkItemComments(parsed.work_item_id);
1780
+ const teamSlug = parsed.project_slug || this.client.getProjectSlug() || undefined;
1781
+ const comments = await this.client.listWorkItemComments(parsed.work_item_id, teamSlug);
1606
1782
  return {
1607
- content: [{ type: 'text', text: JSON.stringify(comments, null, 2) }],
1783
+ content: [{ type: 'text', text: JSON.stringify(stripUuids(comments), null, 2) }],
1608
1784
  };
1609
1785
  }
1610
1786
  case 'list_issue_comments': {
1611
1787
  const parsed = ListIssueCommentsSchema.parse(args);
1612
- const comments = await this.client.listIssueComments(parsed.issue_id);
1788
+ const teamSlug = parsed.project_slug || this.client.getProjectSlug() || undefined;
1789
+ const comments = await this.client.listIssueComments(parsed.issue_id, teamSlug);
1613
1790
  return {
1614
- content: [{ type: 'text', text: JSON.stringify(comments, null, 2) }],
1791
+ content: [{ type: 'text', text: JSON.stringify(stripUuids(comments), null, 2) }],
1615
1792
  };
1616
1793
  }
1617
1794
  case 'create_work_item_comment': {
1618
1795
  const parsed = CreateWorkItemCommentSchema.parse(args);
1796
+ const teamSlug = parsed.project_slug || this.client.getProjectSlug() || undefined;
1619
1797
  const comment = await this.client.createWorkItemComment(parsed.work_item_id, {
1620
1798
  content: parsed.content,
1621
- });
1799
+ }, teamSlug);
1622
1800
  return {
1623
1801
  content: [
1624
1802
  {
1625
1803
  type: 'text',
1626
- text: `Added comment to work item\n\n${JSON.stringify(comment, null, 2)}`,
1804
+ text: `Added comment to work item\n\n${JSON.stringify(stripUuids(comment), null, 2)}`,
1627
1805
  },
1628
1806
  ],
1629
1807
  };
1630
1808
  }
1631
1809
  case 'create_issue_comment': {
1632
1810
  const parsed = CreateIssueCommentSchema.parse(args);
1811
+ const teamSlug = parsed.project_slug || this.client.getProjectSlug() || undefined;
1633
1812
  const comment = await this.client.createIssueComment(parsed.issue_id, {
1634
1813
  content: parsed.content,
1635
- });
1814
+ }, teamSlug);
1636
1815
  return {
1637
1816
  content: [
1638
1817
  {
1639
1818
  type: 'text',
1640
- text: `Added comment to issue\n\n${JSON.stringify(comment, null, 2)}`,
1819
+ text: `Added comment to issue\n\n${JSON.stringify(stripUuids(comment), null, 2)}`,
1641
1820
  },
1642
1821
  ],
1643
1822
  };
@@ -1699,6 +1878,47 @@ class WolfpackMCPServer {
1699
1878
  ],
1700
1879
  };
1701
1880
  }
1881
+ // Skill handlers
1882
+ case 'list_skills': {
1883
+ const skills = await this.client.listSkills();
1884
+ return {
1885
+ content: [{ type: 'text', text: JSON.stringify(skills, null, 2) }],
1886
+ };
1887
+ }
1888
+ case 'get_skill': {
1889
+ const parsed = GetSkillSchema.parse(args);
1890
+ const skill = await this.client.getSkill(parsed.skill_name);
1891
+ if (skill) {
1892
+ return {
1893
+ content: [{ type: 'text', text: JSON.stringify(skill, null, 2) }],
1894
+ };
1895
+ }
1896
+ return {
1897
+ content: [
1898
+ {
1899
+ type: 'text',
1900
+ text: `Skill '${parsed.skill_name}' not found. Use list_skills to see available skills.`,
1901
+ },
1902
+ ],
1903
+ };
1904
+ }
1905
+ case 'get_skill_resource': {
1906
+ const parsed = GetSkillResourceSchema.parse(args);
1907
+ const resource = await this.client.getSkillResource(parsed.skill_name, parsed.resource_name);
1908
+ if (resource) {
1909
+ return {
1910
+ content: [{ type: 'text', text: JSON.stringify(resource, null, 2) }],
1911
+ };
1912
+ }
1913
+ return {
1914
+ content: [
1915
+ {
1916
+ type: 'text',
1917
+ text: `Resource '${parsed.resource_name}' not found in skill '${parsed.skill_name}'.`,
1918
+ },
1919
+ ],
1920
+ };
1921
+ }
1702
1922
  default:
1703
1923
  throw new Error(`Unknown tool: ${name}`);
1704
1924
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "wolfpack-mcp",
3
- "version": "1.0.38",
3
+ "version": "1.0.40",
4
4
  "description": "MCP server for Wolfpack AI-enhanced software delivery tools",
5
5
  "main": "dist/index.js",
6
6
  "type": "module",