targetprocess-mcp-server 2.4.2 → 2.4.4
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/index.js +30 -102
- package/package.json +1 -1
- package/build/handlers/format_existing_user_story.js +0 -55
package/build/index.js
CHANGED
|
@@ -23,7 +23,7 @@ import { handleAddComment } from "./handlers/add_comment.js";
|
|
|
23
23
|
import { handleGetUserStoryComments } from "./handlers/get_user_story_comments.js";
|
|
24
24
|
import { handleGetBugComments } from "./handlers/get_bug_comments.js";
|
|
25
25
|
import { handleCreateBug } from "./handlers/create_bug.js";
|
|
26
|
-
|
|
26
|
+
import { handleCreateUserStory } from "./handlers/create_user_story.js";
|
|
27
27
|
import { handleCreateFeature } from "./handlers/create_feature.js";
|
|
28
28
|
import { handleCreateTask } from "./handlers/create_task.js";
|
|
29
29
|
import { handleUpdateBug } from "./handlers/update_bug.js";
|
|
@@ -39,7 +39,6 @@ import { handleUpdateUserStorySubState } from "./handlers/update_user_story_sub_
|
|
|
39
39
|
import { handleGetCardRelations } from "./handlers/get_card_relations.js";
|
|
40
40
|
import { handleCreateCardRelation } from "./handlers/create_card_relation.js";
|
|
41
41
|
import { handleDeleteCardRelation } from "./handlers/delete_card_relation.js";
|
|
42
|
-
import { handleFormatExistingUserStory } from "./handlers/format_existing_user_story.js";
|
|
43
42
|
const server = new McpServer({
|
|
44
43
|
name: "tp",
|
|
45
44
|
version: "1.0.0"
|
|
@@ -531,39 +530,34 @@ server.registerTool('create_bug', {
|
|
|
531
530
|
.describe('Optional Entity State ID — if user gave a state name, resolve it via "get_bug_workflows" first; defaults to "Done"'),
|
|
532
531
|
},
|
|
533
532
|
}, async ({ title, bugContent, origin, projectId, teamId, entityStateId }) => handleCreateBug(tp, { title, bugContent, origin, projectId, teamId, entityStateId }));
|
|
534
|
-
// server.registerTool(
|
|
535
|
-
// 'create_user_story',
|
|
536
|
-
// {
|
|
537
|
-
// title: 'Create a new user story',
|
|
538
|
-
// description: `Create a new user story in Targetprocess.`,
|
|
539
|
-
// inputSchema: {
|
|
540
|
-
// title: z.string()
|
|
541
|
-
// .describe('User story title'),
|
|
542
|
-
// description: z.string()
|
|
543
|
-
// .optional()
|
|
544
|
-
// .describe('Optional user story description (when provided, format as HTML)'),
|
|
545
|
-
// featureId: z.string()
|
|
546
|
-
// .min(5)
|
|
547
|
-
// .max(6)
|
|
548
|
-
// .optional()
|
|
549
|
-
// .describe('Optional Feature ID to link this user story to (e.g. 145636)'),
|
|
550
|
-
// releaseId: z.string()
|
|
551
|
-
// .min(5)
|
|
552
|
-
// .max(6)
|
|
553
|
-
// .optional()
|
|
554
|
-
// .describe('Optional Release ID to link this user story to (e.g. 145200)'),
|
|
555
|
-
// projectId: z.string()
|
|
556
|
-
// .optional()
|
|
557
|
-
// .describe('Optional Project ID — defaults to TP_PROJECT_ID from config'),
|
|
558
|
-
// teamId: z.string()
|
|
559
|
-
// .optional()
|
|
560
|
-
// .describe('Optional Team ID — defaults to TP_TEAM_ID from config'),
|
|
561
|
-
// },
|
|
562
|
-
// },
|
|
563
|
-
// async ({ title, description, featureId, releaseId, projectId, teamId }) =>
|
|
564
|
-
// handleCreateUserStory(tp, { title, description, featureId, releaseId, projectId, teamId })
|
|
565
|
-
// )
|
|
566
533
|
server.registerTool('create_user_story', {
|
|
534
|
+
title: 'Create a new user story',
|
|
535
|
+
description: `Create a new user story in Targetprocess.`,
|
|
536
|
+
inputSchema: {
|
|
537
|
+
title: z.string()
|
|
538
|
+
.describe('User story title'),
|
|
539
|
+
description: z.string()
|
|
540
|
+
.optional()
|
|
541
|
+
.describe('Optional user story description (when provided, format as HTML)'),
|
|
542
|
+
featureId: z.string()
|
|
543
|
+
.min(5)
|
|
544
|
+
.max(6)
|
|
545
|
+
.optional()
|
|
546
|
+
.describe('Optional Feature ID to link this user story to (e.g. 145636)'),
|
|
547
|
+
releaseId: z.string()
|
|
548
|
+
.min(5)
|
|
549
|
+
.max(6)
|
|
550
|
+
.optional()
|
|
551
|
+
.describe('Optional Release ID to link this user story to (e.g. 145200)'),
|
|
552
|
+
projectId: z.string()
|
|
553
|
+
.optional()
|
|
554
|
+
.describe('Optional Project ID — defaults to TP_PROJECT_ID from config'),
|
|
555
|
+
teamId: z.string()
|
|
556
|
+
.optional()
|
|
557
|
+
.describe('Optional Team ID — defaults to TP_TEAM_ID from config'),
|
|
558
|
+
},
|
|
559
|
+
}, async ({ title, description, featureId, releaseId, projectId, teamId }) => handleCreateUserStory(tp, { title, description, featureId, releaseId, projectId, teamId }));
|
|
560
|
+
server.registerTool('create_formatted_user_story', {
|
|
567
561
|
title: 'Create a formatted user story',
|
|
568
562
|
description: `Create a new user story in Targetprocess with a structured, template-driven description.
|
|
569
563
|
The description is assembled from discrete sections (header, definitions, acceptance criteria, Gherkin scenarios, edge cases, references, notes) and stored as HTML.
|
|
@@ -641,12 +635,12 @@ server.registerTool('create_user_story', {
|
|
|
641
635
|
.describe('Optional Team ID — defaults to TP_TEAM_ID from config'),
|
|
642
636
|
},
|
|
643
637
|
}, async ({ title, header, definitions, acceptanceCriteria, scenarios, examplesTable, edgeCases, references, notes, featureId, releaseId, projectId, teamId }) => {
|
|
644
|
-
const gherkinBlock = (items) => items.map((s, indx) => `<div><strong>Scenario ${indx + 1} - ${s.name}:</strong></div><div>${s.steps.map(step => `<div>\t${step}</div>`).join('\n')}</div>`).join('
|
|
638
|
+
const gherkinBlock = (items) => items.map((s, indx) => `<div><strong>Scenario ${indx + 1} - ${s.name}:</strong></div><div>${s.steps.map(step => `<div>\t${step}</div>`).join('\n')}</div>`).join('<br>');
|
|
645
639
|
const parts = ['<div>'];
|
|
646
640
|
parts.push('<h3>Header</h3>');
|
|
647
641
|
if (header.storyId)
|
|
648
642
|
parts.push(`<p><strong>Story ID:</strong> ${header.storyId}</p>`);
|
|
649
|
-
parts.push(`<p>As a ${header.asA}
|
|
643
|
+
parts.push(`<p>As a ${header.asA} <br> I want ${header.iWant} <br> so that ${header.soThat}</p>`);
|
|
650
644
|
if (definitions) {
|
|
651
645
|
parts.push('<h3>Definitions</h3>');
|
|
652
646
|
parts.push(`<div>`);
|
|
@@ -1386,72 +1380,6 @@ server.registerTool('get_my_time_logs', {
|
|
|
1386
1380
|
.describe('Number of entries to return, default is 25'),
|
|
1387
1381
|
},
|
|
1388
1382
|
}, async ({ take }) => handleGetMyTimeLogs(tp, take));
|
|
1389
|
-
server.registerTool('format_existing_user_story', {
|
|
1390
|
-
title: 'Format an existing user story',
|
|
1391
|
-
description: `Re-format the description of an existing user story using the structured template (Header, Definitions, Acceptance Criteria, Gherkin Scenarios, Edge Cases, References, Notes).
|
|
1392
|
-
This is identical in structure to "create_user_story" but updates an existing card instead of creating a new one.
|
|
1393
|
-
CRITICAL WORKFLOW: Before calling this tool, you MUST follow these steps:
|
|
1394
|
-
1) Call "get_user_story_content" to retrieve the current content of the user story;
|
|
1395
|
-
2) Extract or derive the structured fields (header, definitions, acceptanceCriteria, scenarios, etc.) from the existing description;
|
|
1396
|
-
3) Optionally update the title if the user requested it.`,
|
|
1397
|
-
inputSchema: {
|
|
1398
|
-
id: z.string()
|
|
1399
|
-
.min(5)
|
|
1400
|
-
.max(6)
|
|
1401
|
-
.describe('ID of the user story to format (e.g. 145789)'),
|
|
1402
|
-
title: z.string()
|
|
1403
|
-
.optional()
|
|
1404
|
-
.describe('Updated user story title — omit to keep the existing title'),
|
|
1405
|
-
header: z.object({
|
|
1406
|
-
storyId: z.string()
|
|
1407
|
-
.optional()
|
|
1408
|
-
.describe('Story ID if already known (e.g. US-12345), omit if not applicable'),
|
|
1409
|
-
asA: z.string()
|
|
1410
|
-
.describe('Role or persona — the "As a ..." part'),
|
|
1411
|
-
iWant: z.string()
|
|
1412
|
-
.describe('Goal — the "I want ..." part'),
|
|
1413
|
-
soThat: z.string()
|
|
1414
|
-
.describe('Benefit — the "so that ..." part'),
|
|
1415
|
-
})
|
|
1416
|
-
.describe('Story header following the As a / I want / so that format'),
|
|
1417
|
-
definitions: z.array(z.object({
|
|
1418
|
-
term: z.string()
|
|
1419
|
-
.describe('The term, module name, or feature flag being defined'),
|
|
1420
|
-
description: z.string()
|
|
1421
|
-
.describe('Explanation of the term'),
|
|
1422
|
-
})),
|
|
1423
|
-
acceptanceCriteria: z.array(z.string())
|
|
1424
|
-
.min(1)
|
|
1425
|
-
.describe('Bullet checklist items for quick review sign-off — each string is one criterion'),
|
|
1426
|
-
scenarios: z.array(z.object({
|
|
1427
|
-
name: z.string()
|
|
1428
|
-
.describe('Scenario name'),
|
|
1429
|
-
steps: z.array(z.string())
|
|
1430
|
-
.min(1)
|
|
1431
|
-
.describe('Gherkin steps — each string is a full step line, e.g. "Given I am on the login page"'),
|
|
1432
|
-
}))
|
|
1433
|
-
.min(1)
|
|
1434
|
-
.describe('Gherkin scenario blocks, one per behavior branch'),
|
|
1435
|
-
examplesTable: z.string()
|
|
1436
|
-
.optional()
|
|
1437
|
-
.describe('Examples table for parameterized or matrix behavior (plain text or Gherkin Examples: table format)'),
|
|
1438
|
-
edgeCases: z.array(z.object({
|
|
1439
|
-
name: z.string()
|
|
1440
|
-
.describe('Edge case scenario name'),
|
|
1441
|
-
steps: z.array(z.string())
|
|
1442
|
-
.min(1)
|
|
1443
|
-
.describe('Gherkin steps for this edge case'),
|
|
1444
|
-
}))
|
|
1445
|
-
.optional()
|
|
1446
|
-
.describe('Explicit edge case or boundary condition scenarios'),
|
|
1447
|
-
references: z.string()
|
|
1448
|
-
.optional()
|
|
1449
|
-
.describe('Links to Axure mockups or other external references (not inline in prose)'),
|
|
1450
|
-
notes: z.string()
|
|
1451
|
-
.optional()
|
|
1452
|
-
.describe('Anything that helps understand the story context but does not fit other sections'),
|
|
1453
|
-
},
|
|
1454
|
-
}, async ({ id, title, header, definitions, acceptanceCriteria, scenarios, examplesTable, edgeCases, references, notes }) => handleFormatExistingUserStory(tp, { id, title, header, definitions, acceptanceCriteria, scenarios, examplesTable, edgeCases, references, notes }));
|
|
1455
1383
|
async function main() {
|
|
1456
1384
|
const transport = new StdioServerTransport();
|
|
1457
1385
|
await server.connect(transport);
|
package/package.json
CHANGED
|
@@ -1,55 +0,0 @@
|
|
|
1
|
-
export async function handleFormatExistingUserStory(tp, params) {
|
|
2
|
-
const { id, title, header, definitions, acceptanceCriteria, scenarios, examplesTable, edgeCases, references, notes, } = params;
|
|
3
|
-
const gherkinBlock = (items) => items.map((s, indx) => `<div><strong>Scenario ${indx + 1} - ${s.name}:</strong></div><div>${s.steps.map(step => `<div>\t${step}</div>`).join('\n')}</div>`).join('\n');
|
|
4
|
-
const parts = ['<div>'];
|
|
5
|
-
parts.push('<h3>Header</h3>');
|
|
6
|
-
if (header.storyId)
|
|
7
|
-
parts.push(`<p><strong>Story ID:</strong> ${header.storyId}</p>`);
|
|
8
|
-
parts.push(`<p>As a ${header.asA} / I want ${header.iWant} / so that ${header.soThat}</p>`);
|
|
9
|
-
if (definitions && definitions.length > 0) {
|
|
10
|
-
parts.push('<h3>Definitions</h3>');
|
|
11
|
-
parts.push(`<div>`);
|
|
12
|
-
for (const def of definitions) {
|
|
13
|
-
parts.push(`<p><strong>${def.term}</strong> — ${def.description}</p>`);
|
|
14
|
-
}
|
|
15
|
-
parts.push(`</div>`);
|
|
16
|
-
}
|
|
17
|
-
parts.push('<h3>Acceptance Criteria</h3>');
|
|
18
|
-
parts.push('<ol>');
|
|
19
|
-
for (const criterion of acceptanceCriteria) {
|
|
20
|
-
parts.push(`<li>${criterion}</li>`);
|
|
21
|
-
}
|
|
22
|
-
parts.push('</ol>');
|
|
23
|
-
parts.push('<h3>Scenarios</h3>');
|
|
24
|
-
parts.push(gherkinBlock(scenarios));
|
|
25
|
-
if (examplesTable) {
|
|
26
|
-
parts.push('<h3>Examples</h3>');
|
|
27
|
-
parts.push(`<pre>${examplesTable}</pre>`);
|
|
28
|
-
}
|
|
29
|
-
if (edgeCases && edgeCases.length > 0) {
|
|
30
|
-
parts.push('<h3>Edge Cases</h3>');
|
|
31
|
-
parts.push(gherkinBlock(edgeCases));
|
|
32
|
-
}
|
|
33
|
-
if (references) {
|
|
34
|
-
parts.push('<h3>References</h3>');
|
|
35
|
-
parts.push(`<p>${references}</p>`);
|
|
36
|
-
}
|
|
37
|
-
if (notes) {
|
|
38
|
-
parts.push('<h3>Notes</h3>');
|
|
39
|
-
parts.push(`<p>${notes}</p>`);
|
|
40
|
-
}
|
|
41
|
-
parts.push('</div>');
|
|
42
|
-
const description = parts.join('\n');
|
|
43
|
-
const response = await tp.updateUserStory({ id, title, description });
|
|
44
|
-
if (!response) {
|
|
45
|
-
return {
|
|
46
|
-
content: [{
|
|
47
|
-
type: 'text',
|
|
48
|
-
text: `Failed to format user story id: ${id}\n JSON: ${JSON.stringify(response, null, 2)}`
|
|
49
|
-
}],
|
|
50
|
-
};
|
|
51
|
-
}
|
|
52
|
-
return {
|
|
53
|
-
content: [{ type: 'text', text: JSON.stringify(response) }],
|
|
54
|
-
};
|
|
55
|
-
}
|