targetprocess-mcp-server 2.6.7 → 2.6.9
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/build/handlers/create_bug_based_on_card.js +14 -0
- package/build/handlers/get_bug_content.js +1 -0
- package/build/index.js +70 -23
- package/build/tp.js +35 -5
- package/package.json +1 -1
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
export async function handleCreateBugBasedOnCard(tp, params) {
|
|
2
|
+
const bugResponse = await tp.createBug(params);
|
|
3
|
+
if (!bugResponse) {
|
|
4
|
+
return {
|
|
5
|
+
content: [{
|
|
6
|
+
type: 'text',
|
|
7
|
+
text: `Failed to create bug "${params.title}"\n JSON: ${JSON.stringify(bugResponse, null, 2)}`
|
|
8
|
+
}],
|
|
9
|
+
};
|
|
10
|
+
}
|
|
11
|
+
return {
|
|
12
|
+
content: [{ type: 'text', text: JSON.stringify(bugResponse) }],
|
|
13
|
+
};
|
|
14
|
+
}
|
|
@@ -14,6 +14,7 @@ export async function handleGetBugContent(tp, id) {
|
|
|
14
14
|
id: bug.Id,
|
|
15
15
|
description: '',
|
|
16
16
|
origin: '',
|
|
17
|
+
release: bug.Release ? { id: bug.Release.Id, name: bug.Release.Name } : null,
|
|
17
18
|
};
|
|
18
19
|
try {
|
|
19
20
|
const dom = new JSDOM(`<html><body><div id="content">${bug.Description}</div></body></html>`);
|
package/build/index.js
CHANGED
|
@@ -25,6 +25,7 @@ import { handleAddComment } from "./handlers/add_comment.js";
|
|
|
25
25
|
import { handleGetUserStoryComments } from "./handlers/get_user_story_comments.js";
|
|
26
26
|
import { handleGetBugComments } from "./handlers/get_bug_comments.js";
|
|
27
27
|
import { handleCreateBug } from "./handlers/create_bug.js";
|
|
28
|
+
import { handleCreateBugBasedOnCard } from "./handlers/create_bug_based_on_card.js";
|
|
28
29
|
import { handleCreateUserStory } from "./handlers/create_user_story.js";
|
|
29
30
|
import { handleCreateFormattedUserStory } from "./handlers/create_formatted_user_story.js";
|
|
30
31
|
import { handleCreateFormattedFeature } from "./handlers/create_formatted_feature.js";
|
|
@@ -354,7 +355,8 @@ server.registerTool('create_bug_based_on_card', {
|
|
|
354
355
|
3) format the new bug inside html <div> tags with Environment (describes where bug was found, dev, feature, review or uat Environment), Issue Description, Steps to Reproduce, Expected Behavior, Actual Behavior and Attachments sections (note: section titles should be wrapped in <h3> tags, e.g. <h3>Issue Description</h3>);
|
|
355
356
|
4) IF the user specified a team by name (not ID), call "get_teams" to find the matching team and use its ID as teamId;
|
|
356
357
|
5) IF the user specified a project by name (not ID), call "get_projects" to find the matching project and use its ID as projectId;
|
|
357
|
-
6)
|
|
358
|
+
6) IF the user specified a release by name (not ID), call "get_current_releases" to find the matching release and use its ID as releaseId;
|
|
359
|
+
7) add a comment to the card with created bug Id and its Title`,
|
|
358
360
|
inputSchema: {
|
|
359
361
|
title: z.string()
|
|
360
362
|
.describe('Bug card title that summarizes the problem in concise, descriptive, and actionable manner, enabling a developer to understand the issue without opening the report'),
|
|
@@ -384,6 +386,11 @@ server.registerTool('create_bug_based_on_card', {
|
|
|
384
386
|
])
|
|
385
387
|
.optional()
|
|
386
388
|
.describe('Where the bug was found, defaults to "Manual QA" if no origin was specified'),
|
|
389
|
+
releaseId: z.string()
|
|
390
|
+
.min(5)
|
|
391
|
+
.max(9)
|
|
392
|
+
.optional()
|
|
393
|
+
.describe('Optional Release ID to assign this bug to — if user gave a release name, resolve it via "get_current_releases" first'),
|
|
387
394
|
projectId: z.string()
|
|
388
395
|
.optional()
|
|
389
396
|
.describe('Optional Project ID — if user gave a project name, resolve it via "get_projects" first; defaults to TP_PROJECT_ID from config'),
|
|
@@ -391,23 +398,7 @@ server.registerTool('create_bug_based_on_card', {
|
|
|
391
398
|
.optional()
|
|
392
399
|
.describe('Optional Team ID — if user gave a team name, resolve it via "get_teams" first; defaults to TP_TEAM_ID from config'),
|
|
393
400
|
},
|
|
394
|
-
}, async ({ title, card, bugContent, origin, projectId, teamId }) => {
|
|
395
|
-
const bugResponse = await tp.createBug({ title, card, bugContent, origin, projectId, teamId });
|
|
396
|
-
if (!bugResponse) {
|
|
397
|
-
return {
|
|
398
|
-
content: [{
|
|
399
|
-
type: 'text',
|
|
400
|
-
text: `Failed to create bug "${title}"\n JSON: ${JSON.stringify(bugResponse, null, 2)}`
|
|
401
|
-
}]
|
|
402
|
-
};
|
|
403
|
-
}
|
|
404
|
-
return {
|
|
405
|
-
content: [{
|
|
406
|
-
type: 'text',
|
|
407
|
-
text: JSON.stringify(bugResponse)
|
|
408
|
-
}],
|
|
409
|
-
};
|
|
410
|
-
});
|
|
401
|
+
}, async ({ title, card, bugContent, origin, releaseId, projectId, teamId }) => handleCreateBugBasedOnCard(tp, { title, card, bugContent, origin, releaseId, projectId, teamId }));
|
|
411
402
|
server.registerTool('update_bug', {
|
|
412
403
|
title: 'Update a bug card',
|
|
413
404
|
description: `Update a bug card with data proded from user input.
|
|
@@ -416,7 +407,8 @@ server.registerTool('update_bug', {
|
|
|
416
407
|
1) IF the user specified a team by name (not ID), call "get_teams" to find the matching team and use its ID as teamId;
|
|
417
408
|
2) IF the user specified a project by name (not ID), call "get_projects" to find the matching project and use its ID as projectId;
|
|
418
409
|
3) IF the user specified a state by name (not ID), call "get_bug_workflows" to find the matching state and use its ID as entityStateId;
|
|
419
|
-
4) IF the user specified a sprint/iteration by name, call "get_team_iterations" to find the matching iteration and use its ID as teamIterationId
|
|
410
|
+
4) IF the user specified a sprint/iteration by name, call "get_team_iterations" to find the matching iteration and use its ID as teamIterationId;
|
|
411
|
+
5) IF the user specified a release by name (not ID), call "get_current_releases" to find the matching release and use its ID as releaseId;`,
|
|
420
412
|
inputSchema: {
|
|
421
413
|
id: z.string()
|
|
422
414
|
.min(5)
|
|
@@ -441,6 +433,11 @@ server.registerTool('update_bug', {
|
|
|
441
433
|
])
|
|
442
434
|
.optional()
|
|
443
435
|
.describe('Where the bug was found, defaults to "Manual QA"'),
|
|
436
|
+
releaseId: z.string()
|
|
437
|
+
.min(5)
|
|
438
|
+
.max(9)
|
|
439
|
+
.optional()
|
|
440
|
+
.describe('Optional Release ID to assign this bug to — if user gave a release name, resolve it via "get_current_releases" first'),
|
|
444
441
|
projectId: z.string()
|
|
445
442
|
.optional()
|
|
446
443
|
.describe('Optional Project ID — if user gave a project name, resolve it via "get_projects" first; defaults to TP_PROJECT_ID from config'),
|
|
@@ -457,7 +454,7 @@ server.registerTool('update_bug', {
|
|
|
457
454
|
.optional()
|
|
458
455
|
.describe('Optional Team Iteration (sprint) ID — resolve it via "get_team_iterations" first'),
|
|
459
456
|
},
|
|
460
|
-
}, async ({ id, title, bugContent, origin, projectId, teamId, entityStateId, tags, teamIterationId }) => handleUpdateBug(tp, { id, title, bugContent, origin, projectId, teamId, entityStateId, tags, teamIterationId }));
|
|
457
|
+
}, async ({ id, title, bugContent, origin, releaseId, projectId, teamId, entityStateId, tags, teamIterationId }) => handleUpdateBug(tp, { id, title, bugContent, origin, releaseId, projectId, teamId, entityStateId, tags, teamIterationId }));
|
|
461
458
|
server.registerTool('update_user_story_state', {
|
|
462
459
|
title: 'Update a user story card sub state',
|
|
463
460
|
description: `Update a user story card sub state with data provided from user input.
|
|
@@ -480,6 +477,50 @@ server.registerTool('update_user_story_state', {
|
|
|
480
477
|
.describe('Team Assignment ID, resolve it via "get_user_story_content" first'),
|
|
481
478
|
},
|
|
482
479
|
}, async ({ id, teamId, teamAssignmentId, entityStateId }) => handleUpdateUserStorySubState(tp, { id, teamId, teamAssignmentId, entityStateId }));
|
|
480
|
+
server.registerTool('set_business_value', {
|
|
481
|
+
title: 'Set Business Value on a TP card',
|
|
482
|
+
description: `Set the Business Value (Priority) on a Targetprocess User Story, Feature, or Epic.
|
|
483
|
+
Business Value in the TP UI maps to the Priority field in the API.
|
|
484
|
+
CRITICAL WORKFLOW: Call "get_priorities" first to retrieve the list of valid priority IDs and their names for this instance before calling this tool — do not guess priority IDs.`,
|
|
485
|
+
inputSchema: {
|
|
486
|
+
id: z.string()
|
|
487
|
+
.describe('ID of the card to update (e.g. "151282")'),
|
|
488
|
+
entityType: z.enum(['UserStories', 'Features', 'Epics'])
|
|
489
|
+
.describe('Entity type of the card'),
|
|
490
|
+
priorityId: z.string()
|
|
491
|
+
.describe('Priority ID — resolve via "get_priorities" first'),
|
|
492
|
+
},
|
|
493
|
+
}, async ({ id, entityType, priorityId }) => {
|
|
494
|
+
if (entityType === 'UserStories') {
|
|
495
|
+
const story = await tp.getUserStory(id);
|
|
496
|
+
const featureId = story?.Feature?.Id;
|
|
497
|
+
if (featureId) {
|
|
498
|
+
const siblings = await tp.getUserStoriesInFeatureWithPriority(String(featureId));
|
|
499
|
+
const conflict = (siblings?.Items ?? []).find((s) => String(s.Id) !== String(id) && s.Priority?.Id === parseInt(priorityId));
|
|
500
|
+
if (conflict) {
|
|
501
|
+
return {
|
|
502
|
+
content: [{
|
|
503
|
+
type: 'text',
|
|
504
|
+
text: `Cannot set Business Value: story "${conflict.Name}" (${conflict.Id}) in the same feature already has this priority. Choose a different value.`,
|
|
505
|
+
}],
|
|
506
|
+
};
|
|
507
|
+
}
|
|
508
|
+
}
|
|
509
|
+
}
|
|
510
|
+
const response = await tp.setBusinessValue({ id, entityType, priorityId });
|
|
511
|
+
if (!response) {
|
|
512
|
+
return { content: [{ type: 'text', text: `Failed to set business value on ${entityType} ${id}` }] };
|
|
513
|
+
}
|
|
514
|
+
return { content: [{ type: 'text', text: JSON.stringify(response) }] };
|
|
515
|
+
});
|
|
516
|
+
server.registerTool('get_priorities', {
|
|
517
|
+
title: 'Get available Business Value / Priority options',
|
|
518
|
+
description: `Returns the list of Priority options available in this Targetprocess instance. Use this before calling "set_business_value" to resolve a priority name (e.g. "Must Have", "Normal", "10") to its ID.`,
|
|
519
|
+
inputSchema: {},
|
|
520
|
+
}, async () => {
|
|
521
|
+
const response = await tp.getPriorities();
|
|
522
|
+
return { content: [{ type: 'text', text: JSON.stringify(response) }] };
|
|
523
|
+
});
|
|
483
524
|
server.registerTool('update_user_story', {
|
|
484
525
|
title: 'Update a user story card',
|
|
485
526
|
description: `Update a user story card with data provided from user input.
|
|
@@ -544,7 +585,8 @@ server.registerTool('create_bug', {
|
|
|
544
585
|
1) format the new bug inside html <div> tags with Environment(describes where bug was found, dev, feature, review or uat Environment), Issue Description, Steps to Reproduce, Expected Behavior, Actual Behavior and Attachments sections (note: section titles should be wrapped in <h3> tags, e.g. <h3>Issue Description</h3>, step to reproduce should be wrapped in <ol>);
|
|
545
586
|
2) IF the user specified a team by name (not ID), call "get_teams" to find the matching team and use its ID as teamId;
|
|
546
587
|
3) IF the user specified a project by name (not ID), call "get_projects" to find the matching project and use its ID as projectId;
|
|
547
|
-
4) IF the user specified a sprint/iteration by name, call "get_team_iterations" to find the matching iteration and use its ID as teamIterationId
|
|
588
|
+
4) IF the user specified a sprint/iteration by name, call "get_team_iterations" to find the matching iteration and use its ID as teamIterationId;
|
|
589
|
+
5) IF the user specified a release by name (not ID), call "get_current_releases" to find the matching release and use its ID as releaseId;`,
|
|
548
590
|
inputSchema: {
|
|
549
591
|
title: z.string()
|
|
550
592
|
.describe('Bug card title that summarizes the problem in concise, descriptive, and actionable manner, enabling a developer to understand the issue without opening the report'),
|
|
@@ -563,6 +605,11 @@ server.registerTool('create_bug', {
|
|
|
563
605
|
])
|
|
564
606
|
.optional()
|
|
565
607
|
.describe('Where the bug was found, defaults to "Manual QA" if no origin was specified'),
|
|
608
|
+
releaseId: z.string()
|
|
609
|
+
.min(5)
|
|
610
|
+
.max(9)
|
|
611
|
+
.optional()
|
|
612
|
+
.describe('Optional Release ID to assign this bug to — if user gave a release name, resolve it via "get_current_releases" first'),
|
|
566
613
|
projectId: z.string()
|
|
567
614
|
.optional()
|
|
568
615
|
.describe('Optional Project ID — if user gave a project name, resolve it via "get_projects" first; defaults to TP_PROJECT_ID from config'),
|
|
@@ -579,7 +626,7 @@ server.registerTool('create_bug', {
|
|
|
579
626
|
.optional()
|
|
580
627
|
.describe('Optional Team Iteration (sprint) ID — resolve it via "get_team_iterations" first'),
|
|
581
628
|
},
|
|
582
|
-
}, async ({ title, bugContent, origin, projectId, teamId, entityStateId, tags, teamIterationId }) => handleCreateBug(tp, { title, bugContent, origin, projectId, teamId, entityStateId, tags, teamIterationId }));
|
|
629
|
+
}, async ({ title, bugContent, origin, releaseId, projectId, teamId, entityStateId, tags, teamIterationId }) => handleCreateBug(tp, { title, bugContent, origin, releaseId, projectId, teamId, entityStateId, tags, teamIterationId }));
|
|
583
630
|
server.registerTool('create_user_story', {
|
|
584
631
|
title: 'Create a new user story',
|
|
585
632
|
description: `Create a new user story in Targetprocess.
|
|
@@ -823,7 +870,7 @@ server.registerTool('create_formatted_feature', {
|
|
|
823
870
|
}, async ({ title, header, definitions, scope, nonFunctionalRequirements, crossCuttingScenarios, childStories, openQuestions, references, notes, epicId, releaseId, projectId, teamId }) => handleCreateFormattedFeature(tp, { title, header, definitions, scope, nonFunctionalRequirements, crossCuttingScenarios, childStories, openQuestions, references, notes, epicId, releaseId, projectId, teamId }));
|
|
824
871
|
server.registerTool('create_feature', {
|
|
825
872
|
title: 'Create a new feature',
|
|
826
|
-
description: `
|
|
873
|
+
description: `DEPRECATED — use "create_formatted_feature" instead for all new features. Only call this tool when you have a fully pre-written HTML description and the user has explicitly opted out of the structured template.`,
|
|
827
874
|
inputSchema: {
|
|
828
875
|
title: z.string()
|
|
829
876
|
.describe('Feature title'),
|
package/build/tp.js
CHANGED
|
@@ -186,7 +186,7 @@ export class TpClient {
|
|
|
186
186
|
});
|
|
187
187
|
return response;
|
|
188
188
|
}
|
|
189
|
-
async createBug({ title, card, bugContent, origin, projectId, teamId }) {
|
|
189
|
+
async createBug({ title, card, bugContent, origin, releaseId, projectId, teamId }) {
|
|
190
190
|
const bug = {
|
|
191
191
|
"Name": title,
|
|
192
192
|
"Project": {
|
|
@@ -207,6 +207,8 @@ export class TpClient {
|
|
|
207
207
|
"value": origin
|
|
208
208
|
}];
|
|
209
209
|
}
|
|
210
|
+
if (releaseId)
|
|
211
|
+
bug["Release"] = { "Id": releaseId };
|
|
210
212
|
if (card.type === "UserStory") {
|
|
211
213
|
bug["UserStory"] = { "Id": card.id };
|
|
212
214
|
}
|
|
@@ -258,7 +260,25 @@ export class TpClient {
|
|
|
258
260
|
param: { "format": "json" },
|
|
259
261
|
}, userStory);
|
|
260
262
|
}
|
|
261
|
-
async
|
|
263
|
+
async setBusinessValue({ id, entityType, priorityId }) {
|
|
264
|
+
const entity = { "Id": id, "Priority": { "Id": priorityId } };
|
|
265
|
+
return this.post({
|
|
266
|
+
pathParam: [entityType, id],
|
|
267
|
+
param: { "format": "json" },
|
|
268
|
+
}, entity);
|
|
269
|
+
}
|
|
270
|
+
async getUserStoriesInFeatureWithPriority(featureId) {
|
|
271
|
+
return this.get({
|
|
272
|
+
pathParam: ["UserStories"],
|
|
273
|
+
param: {
|
|
274
|
+
"format": "json",
|
|
275
|
+
"where": `(Feature.Id eq ${featureId})`,
|
|
276
|
+
"select": "Id,Name,Priority",
|
|
277
|
+
"take": "200",
|
|
278
|
+
},
|
|
279
|
+
});
|
|
280
|
+
}
|
|
281
|
+
async updateBug({ id, title, bugContent, origin, releaseId, projectId, teamId, entityStateId, tags, teamIterationId }) {
|
|
262
282
|
const bug = { "Id": id };
|
|
263
283
|
if (title)
|
|
264
284
|
bug["Name"] = title;
|
|
@@ -270,16 +290,18 @@ export class TpClient {
|
|
|
270
290
|
"type": "DropDown",
|
|
271
291
|
"value": origin
|
|
272
292
|
}];
|
|
293
|
+
if (releaseId)
|
|
294
|
+
bug["Release"] = { "Id": releaseId };
|
|
273
295
|
if (projectId)
|
|
274
296
|
bug["Project"] = { "Id": projectId };
|
|
275
297
|
if (teamId)
|
|
276
298
|
bug["assignedTeams"] = [{
|
|
277
299
|
"team": {
|
|
278
|
-
"
|
|
300
|
+
"Id": teamId || config.tp.teamId
|
|
279
301
|
}
|
|
280
302
|
}];
|
|
281
303
|
if (entityStateId)
|
|
282
|
-
bug["entityState"] = { "
|
|
304
|
+
bug["entityState"] = { "Id": entityStateId };
|
|
283
305
|
if (tags)
|
|
284
306
|
bug["Tags"] = tags;
|
|
285
307
|
if (teamIterationId)
|
|
@@ -289,7 +311,7 @@ export class TpClient {
|
|
|
289
311
|
param: { "format": "json" },
|
|
290
312
|
}, bug);
|
|
291
313
|
}
|
|
292
|
-
async createBugOnly({ title, bugContent, origin, projectId, teamId, entityStateId, tags, teamIterationId }) {
|
|
314
|
+
async createBugOnly({ title, bugContent, origin, releaseId, projectId, teamId, entityStateId, tags, teamIterationId }) {
|
|
293
315
|
const bug = {
|
|
294
316
|
"Name": title,
|
|
295
317
|
"Project": {
|
|
@@ -309,6 +331,8 @@ export class TpClient {
|
|
|
309
331
|
"value": origin
|
|
310
332
|
}];
|
|
311
333
|
}
|
|
334
|
+
if (releaseId)
|
|
335
|
+
bug["Release"] = { "Id": releaseId };
|
|
312
336
|
if (entityStateId)
|
|
313
337
|
bug["EntityState"] = { "Id": entityStateId };
|
|
314
338
|
if (tags)
|
|
@@ -878,6 +902,12 @@ export class TpClient {
|
|
|
878
902
|
param: { "format": "json" },
|
|
879
903
|
});
|
|
880
904
|
}
|
|
905
|
+
async getPriorities() {
|
|
906
|
+
return this.get({
|
|
907
|
+
pathParam: ["Priorities"],
|
|
908
|
+
param: { "format": "json", "take": "200" },
|
|
909
|
+
});
|
|
910
|
+
}
|
|
881
911
|
async getProcessWorkflows({ processId }) {
|
|
882
912
|
return this.get({
|
|
883
913
|
pathParam: ["Process"],
|