wolfpack-mcp 1.0.28 → 1.0.30

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -276,6 +276,18 @@ Update an existing journal entry.
276
276
 
277
277
  ### Comments
278
278
 
279
+ #### `list_work_item_comments`
280
+
281
+ List all comments on a work item.
282
+
283
+ - `work_item_id` (required): The work item UUID
284
+
285
+ #### `list_issue_comments`
286
+
287
+ List all comments on an issue.
288
+
289
+ - `issue_id` (required): The issue UUID
290
+
279
291
  #### `create_work_item_comment`
280
292
 
281
293
  Add a comment to a work item.
@@ -317,4 +329,10 @@ Upload an image file from disk and get back a permanent URL for use in markdown
317
329
  - `file_path` (required): Absolute path to an image file (JPEG, PNG, GIF, WebP; max 5MB)
318
330
  - `team_id` (optional): Team ID (required for multi-team users)
319
331
 
332
+ #### `download_image`
333
+
334
+ Download and view an image referenced in content fields. Content from work items, issues, wiki pages, journal entries, and comments may contain image references like `![alt](/api/files/images/...)`. Use this tool with that URL path to view the image.
335
+
336
+ - `image_url` (required): The image URL path (e.g. `/api/files/images/{team}/{filename}`)
337
+
320
338
  </details>
package/dist/client.js CHANGED
@@ -411,6 +411,12 @@ export class WolfpackClient {
411
411
  return this.api.patch(`/journal-entries/${entryId}`, data);
412
412
  }
413
413
  // Comment methods
414
+ async listWorkItemComments(workItemId) {
415
+ return this.api.get(`/work-items/${workItemId}/comments`);
416
+ }
417
+ async listIssueComments(issueId) {
418
+ return this.api.get(`/issues/${issueId}/comments`);
419
+ }
414
420
  async createWorkItemComment(workItemId, data) {
415
421
  return this.api.post(`/work-items/${workItemId}/comments`, data);
416
422
  }
@@ -425,22 +431,11 @@ export class WolfpackClient {
425
431
  return this.api.postMultipart(`/teams/${teamSlug}/upload-image`, buffer, filename, mimeType);
426
432
  }
427
433
  /**
428
- * Fetch an image from the MCP images endpoint and return it as a base64 data URI.
429
- * Returns null if the image is over 1.5MB or on any fetch failure.
434
+ * Download an image from the MCP images endpoint and return raw base64 + mimeType.
430
435
  */
431
- async fetchImageAsBase64(team, filename) {
432
- try {
433
- const { buffer, contentType } = await this.api.getBuffer(`/images/${team}/${filename}`);
434
- // Skip images over 1.5MB to prevent response bloat
435
- const MAX_IMAGE_SIZE = 1.5 * 1024 * 1024;
436
- if (buffer.length > MAX_IMAGE_SIZE) {
437
- return null;
438
- }
439
- return `data:${contentType};base64,${buffer.toString('base64')}`;
440
- }
441
- catch {
442
- return null;
443
- }
436
+ async downloadImage(team, filename) {
437
+ const { buffer, contentType } = await this.api.getBuffer(`/images/${team}/${filename}`);
438
+ return { base64: buffer.toString('base64'), mimeType: contentType };
444
439
  }
445
440
  close() {
446
441
  // No cleanup needed for API client
package/dist/index.js CHANGED
@@ -8,7 +8,6 @@ import { readFile, stat } from 'fs/promises';
8
8
  import { basename, extname, resolve } from 'path';
9
9
  import { WolfpackClient } from './client.js';
10
10
  import { validateConfig, config } from './config.js';
11
- import { processContentImages } from './imageProcessor.js';
12
11
  // Get current package version
13
12
  const require = createRequire(import.meta.url);
14
13
  const packageJson = require('../package.json');
@@ -272,6 +271,12 @@ const UpdateJournalEntrySchema = z.object({
272
271
  .describe('Updated content (markdown). Supports base64-encoded images which will be auto-uploaded.'),
273
272
  });
274
273
  // Comment schemas
274
+ const ListWorkItemCommentsSchema = z.object({
275
+ work_item_id: z.string().describe('The work item UUID'),
276
+ });
277
+ const ListIssueCommentsSchema = z.object({
278
+ issue_id: z.string().describe('The issue UUID'),
279
+ });
275
280
  const CreateWorkItemCommentSchema = z.object({
276
281
  work_item_id: z.string().describe('The work item UUID'),
277
282
  content: z
@@ -295,6 +300,11 @@ const UploadImageSchema = z.object({
295
300
  .optional()
296
301
  .describe('Team ID (required for multi-team users, use list_teams to get IDs)'),
297
302
  });
303
+ const DownloadImageSchema = z.object({
304
+ image_url: z
305
+ .string()
306
+ .describe('The image URL path found in content fields (e.g. "/api/files/images/{team}/{filename}").'),
307
+ });
298
308
  // Helper to detect if a work item description contains a plan
299
309
  function hasPlan(description) {
300
310
  if (!description)
@@ -415,7 +425,8 @@ class WolfpackMCPServer {
415
425
  'Call this before updating to see current content. ' +
416
426
  'WORKFLOW: When asked to work on an item, check its status and follow the required state transitions ' +
417
427
  '(pending→pull first, new→doing, blocked/ready/completed/closed→new→doing, then review when done). ' +
418
- '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.',
428
+ '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. ' +
429
+ 'IMAGES: Image references in the description (e.g. `![alt](/api/files/images/...)`) can be viewed using the download_image tool.',
419
430
  inputSchema: {
420
431
  type: 'object',
421
432
  properties: {
@@ -539,7 +550,8 @@ class WolfpackMCPServer {
539
550
  },
540
551
  {
541
552
  name: 'get_radar_item',
542
- description: 'Get a specific radar item (initiative) by ID or refId, including its work items and participants.',
553
+ description: 'Get a specific radar item (initiative) by ID or refId, including its work items and participants. ' +
554
+ 'IMAGES: Image references in the description (e.g. `![alt](/api/files/images/...)`) can be viewed using the download_image tool.',
543
555
  inputSchema: {
544
556
  type: 'object',
545
557
  properties: {
@@ -616,7 +628,8 @@ class WolfpackMCPServer {
616
628
  },
617
629
  {
618
630
  name: 'get_issue',
619
- description: 'Get a specific issue by ID or refId, including comment and attachment counts.',
631
+ description: 'Get a specific issue by ID or refId, including comment and attachment counts. ' +
632
+ 'IMAGES: Image references in the description (e.g. `![alt](/api/files/images/...)`) can be viewed using the download_image tool.',
620
633
  inputSchema: {
621
634
  type: 'object',
622
635
  properties: {
@@ -751,7 +764,8 @@ class WolfpackMCPServer {
751
764
  },
752
765
  {
753
766
  name: 'get_wiki_page',
754
- description: 'Get a specific wiki/documentation page by ID or slug (URL path). Returns full content in markdown.',
767
+ description: 'Get a specific wiki/documentation page by ID or slug (URL path). Returns full content in markdown. ' +
768
+ 'IMAGES: Image references in the content (e.g. `![alt](/api/files/images/...)`) can be viewed using the download_image tool.',
755
769
  inputSchema: {
756
770
  type: 'object',
757
771
  properties: {
@@ -821,7 +835,8 @@ class WolfpackMCPServer {
821
835
  },
822
836
  {
823
837
  name: 'get_journal_entry',
824
- description: 'Get a specific journal/log entry by ID or reference number. Returns full content.',
838
+ description: 'Get a specific journal/log entry by ID or reference number. Returns full content. ' +
839
+ 'IMAGES: Image references in the content (e.g. `![alt](/api/files/images/...)`) can be viewed using the download_image tool.',
825
840
  inputSchema: {
826
841
  type: 'object',
827
842
  properties: {
@@ -867,6 +882,30 @@ class WolfpackMCPServer {
867
882
  },
868
883
  },
869
884
  // Comment tools
885
+ {
886
+ name: 'list_work_item_comments',
887
+ description: 'List all comments on a work item. Returns comments in chronological order. Requires mcp:comments:read permission. ' +
888
+ 'IMAGES: Image references in comments (e.g. `![alt](/api/files/images/...)`) can be viewed using the download_image tool.',
889
+ inputSchema: {
890
+ type: 'object',
891
+ properties: {
892
+ work_item_id: { type: 'string', description: 'The work item UUID' },
893
+ },
894
+ required: ['work_item_id'],
895
+ },
896
+ },
897
+ {
898
+ name: 'list_issue_comments',
899
+ description: 'List all comments on an issue. Returns comments in chronological order. Requires mcp:comments:read permission. ' +
900
+ 'IMAGES: Image references in comments (e.g. `![alt](/api/files/images/...)`) can be viewed using the download_image tool.',
901
+ inputSchema: {
902
+ type: 'object',
903
+ properties: {
904
+ issue_id: { type: 'string', description: 'The issue UUID' },
905
+ },
906
+ required: ['issue_id'],
907
+ },
908
+ },
870
909
  {
871
910
  name: 'create_work_item_comment',
872
911
  description: 'Add a comment to a work item. Requires mcp:comments:create permission. ' +
@@ -924,6 +963,23 @@ class WolfpackMCPServer {
924
963
  required: ['file_path'],
925
964
  },
926
965
  },
966
+ {
967
+ name: 'download_image',
968
+ description: 'Download and view an image referenced in content fields. ' +
969
+ 'Content from work items, issues, wiki pages, journal entries, and comments may contain image references like `![alt](/api/files/images/...)`. ' +
970
+ 'Use this tool with that URL path to download and view the image. ' +
971
+ 'Requires mcp:images:read permission.',
972
+ inputSchema: {
973
+ type: 'object',
974
+ properties: {
975
+ image_url: {
976
+ type: 'string',
977
+ description: 'The image URL path found in content fields (e.g. "/api/files/images/{team}/{filename}").',
978
+ },
979
+ },
980
+ required: ['image_url'],
981
+ },
982
+ },
927
983
  ],
928
984
  }));
929
985
  this.server.setRequestHandler(CallToolRequestSchema, async (request) => {
@@ -981,9 +1037,6 @@ class WolfpackMCPServer {
981
1037
  const parsed = GetWorkItemSchema.parse(args);
982
1038
  const workItem = await this.client.getWorkItem(parsed.work_item_id, parsed.team_id || this.client.getTeamId() || undefined);
983
1039
  if (workItem) {
984
- workItem.description =
985
- (await processContentImages(workItem.description, this.client)) ??
986
- workItem.description;
987
1040
  let text = JSON.stringify(workItem, null, 2);
988
1041
  // Add hint if no plan detected in description
989
1042
  if (!hasPlan(workItem.description)) {
@@ -1096,11 +1149,6 @@ class WolfpackMCPServer {
1096
1149
  const parsed = GetRadarItemSchema.parse(args);
1097
1150
  const radarItem = await this.client.getRadarItem(parsed.item_id, parsed.team_id);
1098
1151
  if (radarItem) {
1099
- radarItem.description =
1100
- (await processContentImages(radarItem.description, this.client)) ??
1101
- radarItem.description;
1102
- radarItem.notes =
1103
- (await processContentImages(radarItem.notes, this.client)) ?? radarItem.notes;
1104
1152
  return {
1105
1153
  content: [{ type: 'text', text: JSON.stringify(radarItem, null, 2) }],
1106
1154
  };
@@ -1138,8 +1186,6 @@ class WolfpackMCPServer {
1138
1186
  const parsed = GetIssueSchema.parse(args);
1139
1187
  const issue = await this.client.getIssue(parsed.issue_id, parsed.team_id);
1140
1188
  if (issue) {
1141
- issue.description =
1142
- (await processContentImages(issue.description, this.client)) ?? issue.description;
1143
1189
  return {
1144
1190
  content: [{ type: 'text', text: JSON.stringify(issue, null, 2) }],
1145
1191
  };
@@ -1234,8 +1280,6 @@ class WolfpackMCPServer {
1234
1280
  const parsed = GetWikiPageSchema.parse(args);
1235
1281
  const page = await this.client.getWikiPage(parsed.page_id);
1236
1282
  if (page) {
1237
- page.content =
1238
- (await processContentImages(page.content, this.client)) ?? page.content;
1239
1283
  return {
1240
1284
  content: [{ type: 'text', text: JSON.stringify(page, null, 2) }],
1241
1285
  };
@@ -1297,8 +1341,6 @@ class WolfpackMCPServer {
1297
1341
  const parsed = GetJournalEntrySchema.parse(args);
1298
1342
  const entry = await this.client.getJournalEntry(parsed.entry_id, parsed.team_id);
1299
1343
  if (entry) {
1300
- entry.content =
1301
- (await processContentImages(entry.content, this.client)) ?? entry.content;
1302
1344
  return {
1303
1345
  content: [{ type: 'text', text: JSON.stringify(entry, null, 2) }],
1304
1346
  };
@@ -1339,6 +1381,20 @@ class WolfpackMCPServer {
1339
1381
  };
1340
1382
  }
1341
1383
  // Comment handlers
1384
+ case 'list_work_item_comments': {
1385
+ const parsed = ListWorkItemCommentsSchema.parse(args);
1386
+ const comments = await this.client.listWorkItemComments(parsed.work_item_id);
1387
+ return {
1388
+ content: [{ type: 'text', text: JSON.stringify(comments, null, 2) }],
1389
+ };
1390
+ }
1391
+ case 'list_issue_comments': {
1392
+ const parsed = ListIssueCommentsSchema.parse(args);
1393
+ const comments = await this.client.listIssueComments(parsed.issue_id);
1394
+ return {
1395
+ content: [{ type: 'text', text: JSON.stringify(comments, null, 2) }],
1396
+ };
1397
+ }
1342
1398
  case 'create_work_item_comment': {
1343
1399
  const parsed = CreateWorkItemCommentSchema.parse(args);
1344
1400
  const comment = await this.client.createWorkItemComment(parsed.work_item_id, {
@@ -1406,6 +1462,24 @@ class WolfpackMCPServer {
1406
1462
  ],
1407
1463
  };
1408
1464
  }
1465
+ case 'download_image': {
1466
+ const parsed = DownloadImageSchema.parse(args);
1467
+ const match = parsed.image_url.match(/\/api\/files\/images\/([^/]+)\/(.+)$/);
1468
+ if (!match) {
1469
+ throw new Error('Invalid image URL. Expected format: /api/files/images/{team}/{filename}');
1470
+ }
1471
+ const [, team, filename] = match;
1472
+ const { base64, mimeType } = await this.client.downloadImage(team, filename);
1473
+ return {
1474
+ content: [
1475
+ {
1476
+ type: 'image',
1477
+ data: base64,
1478
+ mimeType,
1479
+ },
1480
+ ],
1481
+ };
1482
+ }
1409
1483
  default:
1410
1484
  throw new Error(`Unknown tool: ${name}`);
1411
1485
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "wolfpack-mcp",
3
- "version": "1.0.28",
3
+ "version": "1.0.30",
4
4
  "description": "MCP server for Wolfpack AI-enhanced software delivery tools",
5
5
  "main": "dist/index.js",
6
6
  "type": "module",