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 +18 -0
- package/dist/client.js +10 -15
- package/dist/index.js +94 -20
- package/package.json +1 -1
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 ``. 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
|
-
*
|
|
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
|
|
432
|
-
|
|
433
|
-
|
|
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. ``) 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. ``) 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. ``) 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. ``) 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. ``) 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. ``) 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. ``) 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 ``. ' +
|
|
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
|
}
|