wolfpack-mcp 1.0.37 → 1.0.38

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 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
@@ -202,6 +202,17 @@ export class WolfpackClient {
202
202
  throw error;
203
203
  }
204
204
  }
205
+ async updateWorkItemInitiative(workItemId, radarItemId) {
206
+ try {
207
+ return await this.api.put(`/work-items/${workItemId}/initiative`, { radarItemId });
208
+ }
209
+ catch (error) {
210
+ if (error && typeof error === 'object' && 'status' in error && error.status === 404) {
211
+ return null;
212
+ }
213
+ throw error;
214
+ }
215
+ }
205
216
  async pullWorkItem(workItemId, data) {
206
217
  try {
207
218
  return await this.api.post(`/work-items/${workItemId}/pull`, data || {});
@@ -213,6 +224,19 @@ export class WolfpackClient {
213
224
  throw error;
214
225
  }
215
226
  }
227
+ async submitWorkItemForm(workItemId, formValues) {
228
+ try {
229
+ return await this.api.put(`/work-items/${workItemId}/form`, {
230
+ formValues,
231
+ });
232
+ }
233
+ catch (error) {
234
+ if (error && typeof error === 'object' && 'status' in error && error.status === 404) {
235
+ return null;
236
+ }
237
+ throw error;
238
+ }
239
+ }
216
240
  // Radar Item (Initiative/Roadmap) methods
217
241
  async listRadarItems(options) {
218
242
  const params = new URLSearchParams();
package/dist/index.js CHANGED
@@ -117,6 +117,13 @@ const UpdateWorkItemTitleSchema = z.object({
117
117
  work_item_id: z.string().describe('The ID of the work item'),
118
118
  title: z.string().describe('New title for the work item'),
119
119
  });
120
+ const UpdateWorkItemInitiativeSchema = z.object({
121
+ work_item_id: z.string().describe('The ID of the work item'),
122
+ radar_item_id: z
123
+ .string()
124
+ .nullable()
125
+ .describe('Radar/initiative item ID to link to, or null to unlink'),
126
+ });
120
127
  const PullWorkItemSchema = z.object({
121
128
  work_item_id: z.string().describe('The ID of the work item to pull from backlog'),
122
129
  leading_user_id: z
@@ -124,6 +131,10 @@ const PullWorkItemSchema = z.object({
124
131
  .optional()
125
132
  .describe('User ID to assign as leading user (defaults to API key owner)'),
126
133
  });
134
+ const SubmitWorkItemFormSchema = z.object({
135
+ work_item_id: z.string().describe('The ID of the work item'),
136
+ form_values: z.record(z.any()).describe('Key-value pairs matching formDefinition field names'),
137
+ });
127
138
  // Radar Item (Initiative/Roadmap) schemas
128
139
  const ListRadarItemsSchema = z.object({
129
140
  project_slug: z.string().optional().describe('Project slug to filter radar items'),
@@ -189,6 +200,10 @@ const CreateWorkItemSchema = z.object({
189
200
  .optional()
190
201
  .describe('Initial status: "pending" (backlog), "new" (to do), "doing", "review", "ready", "blocked", "completed". Defaults to "new".'),
191
202
  priority: z.number().optional().describe('Priority level (0-4, higher is more important)'),
203
+ size: z
204
+ .enum(['S', 'M', 'L'])
205
+ .optional()
206
+ .describe('Size estimate: "S" (small), "M" (medium), "L" (large)'),
192
207
  leading_user_id: z.string().optional().describe('User ID to assign as leading user'),
193
208
  category_id: z.string().optional().describe('Category ID to organize the work item'),
194
209
  radar_item_id: z.string().optional().describe('Radar/initiative item ID to link to'),
@@ -448,6 +463,7 @@ class WolfpackMCPServer {
448
463
  'WORKFLOW: When asked to work on an item, check its status and follow the required state transitions ' +
449
464
  '(pending→pull first, new→doing, blocked/ready/completed/closed→new→doing, then review when done). ' +
450
465
  '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. ' +
466
+ '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
467
  'IMAGES: Image references in the description (e.g. `![alt](/api/files/images/...)`) can be viewed using the download_image tool.',
452
468
  inputSchema: {
453
469
  type: 'object',
@@ -557,6 +573,25 @@ class WolfpackMCPServer {
557
573
  required: ['work_item_id', 'title'],
558
574
  },
559
575
  },
576
+ {
577
+ name: 'update_work_item_initiative',
578
+ description: 'Link or unlink a work item to/from a radar item (initiative). ' +
579
+ 'Pass a radar_item_id to link, or null to remove the initiative link.',
580
+ inputSchema: {
581
+ type: 'object',
582
+ properties: {
583
+ work_item_id: {
584
+ type: 'string',
585
+ description: 'The ID of the work item',
586
+ },
587
+ radar_item_id: {
588
+ type: ['string', 'null'],
589
+ description: 'Radar/initiative item ID to link to, or null to unlink',
590
+ },
591
+ },
592
+ required: ['work_item_id', 'radar_item_id'],
593
+ },
594
+ },
560
595
  {
561
596
  name: 'pull_work_item',
562
597
  description: 'Pull a specific work item from the backlog to the board. ' +
@@ -580,6 +615,26 @@ class WolfpackMCPServer {
580
615
  required: ['work_item_id'],
581
616
  },
582
617
  },
618
+ {
619
+ name: 'submit_work_item_form',
620
+ description: 'Submit form values for a procedure-created work item. ' +
621
+ 'Use get_work_item first to see formDefinition (field names, types, required) and current formValues. ' +
622
+ 'Then call this with form_values mapping field names to values.',
623
+ inputSchema: {
624
+ type: 'object',
625
+ properties: {
626
+ work_item_id: {
627
+ type: 'string',
628
+ description: 'The ID of the work item',
629
+ },
630
+ form_values: {
631
+ type: 'object',
632
+ description: 'Key-value pairs matching formDefinition field names',
633
+ },
634
+ },
635
+ required: ['work_item_id', 'form_values'],
636
+ },
637
+ },
583
638
  // Radar Item (Initiative/Roadmap) tools
584
639
  {
585
640
  name: 'list_radar_items',
@@ -737,6 +792,11 @@ class WolfpackMCPServer {
737
792
  type: 'number',
738
793
  description: 'Priority level (0-4, higher is more important)',
739
794
  },
795
+ size: {
796
+ type: 'string',
797
+ enum: ['S', 'M', 'L'],
798
+ description: 'Size estimate: "S" (small), "M" (medium), "L" (large)',
799
+ },
740
800
  leading_user_id: {
741
801
  type: 'string',
742
802
  description: 'User ID to assign as leading user',
@@ -1223,6 +1283,26 @@ class WolfpackMCPServer {
1223
1283
  content: [{ type: 'text', text: 'Work item not found' }],
1224
1284
  };
1225
1285
  }
1286
+ case 'update_work_item_initiative': {
1287
+ const parsed = UpdateWorkItemInitiativeSchema.parse(args);
1288
+ const workItem = await this.client.updateWorkItemInitiative(parsed.work_item_id, parsed.radar_item_id);
1289
+ if (workItem) {
1290
+ const initiativeText = parsed.radar_item_id
1291
+ ? `linked to initiative ${parsed.radar_item_id}`
1292
+ : 'unlinked from initiative';
1293
+ return {
1294
+ content: [
1295
+ {
1296
+ type: 'text',
1297
+ text: `Updated "${workItem.title}" - ${initiativeText}\n\n${JSON.stringify(workItem, null, 2)}`,
1298
+ },
1299
+ ],
1300
+ };
1301
+ }
1302
+ return {
1303
+ content: [{ type: 'text', text: 'Work item not found' }],
1304
+ };
1305
+ }
1226
1306
  case 'pull_work_item': {
1227
1307
  const parsed = PullWorkItemSchema.parse(args);
1228
1308
  const workItem = await this.client.pullWorkItem(parsed.work_item_id, {
@@ -1242,6 +1322,23 @@ class WolfpackMCPServer {
1242
1322
  content: [{ type: 'text', text: 'Work item not found' }],
1243
1323
  };
1244
1324
  }
1325
+ case 'submit_work_item_form': {
1326
+ const parsed = SubmitWorkItemFormSchema.parse(args);
1327
+ const workItem = await this.client.submitWorkItemForm(parsed.work_item_id, parsed.form_values);
1328
+ if (workItem) {
1329
+ return {
1330
+ content: [
1331
+ {
1332
+ type: 'text',
1333
+ text: `Submitted form values for "${workItem.title}"\n\n${JSON.stringify(workItem, null, 2)}`,
1334
+ },
1335
+ ],
1336
+ };
1337
+ }
1338
+ return {
1339
+ content: [{ type: 'text', text: 'Work item not found' }],
1340
+ };
1341
+ }
1245
1342
  // Radar Item handlers
1246
1343
  case 'list_radar_items': {
1247
1344
  const parsed = ListRadarItemsSchema.parse(args);
@@ -1317,6 +1414,7 @@ class WolfpackMCPServer {
1317
1414
  description: parsed.description,
1318
1415
  status: parsed.status,
1319
1416
  priority: parsed.priority,
1417
+ size: parsed.size,
1320
1418
  leadingUserId: parsed.leading_user_id,
1321
1419
  categoryId: parsed.category_id,
1322
1420
  radarItemId: parsed.radar_item_id,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "wolfpack-mcp",
3
- "version": "1.0.37",
3
+ "version": "1.0.38",
4
4
  "description": "MCP server for Wolfpack AI-enhanced software delivery tools",
5
5
  "main": "dist/index.js",
6
6
  "type": "module",