targetprocess-mcp-server 2.4.1 → 2.4.2

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
@@ -94,6 +94,8 @@ Cards — Write
94
94
  - `create_formatted_user_story` — Create a new user story with a structured template description (title, header object with asA/iWant/soThat, acceptanceCriteria array, scenarios array with Gherkin steps, optional definitions, examplesTable, edgeCases, references, notes, optional featureId, releaseId, projectId, teamId)
95
95
  > [!NOTE]
96
96
  > `projectId` and `teamId` are optional — fall back to `TP_PROJECT_ID` and `TP_TEAM_ID` from config
97
+ - `format_existing_user_story` — Re-format the description of an existing user story using the structured template (id, header object with asA/iWant/soThat, acceptanceCriteria array, scenarios array with Gherkin steps, optional title, definitions, examplesTable, edgeCases, references, notes)
98
+ > Call `get_user_story_content` first to read the current content, then reconstruct the structured fields before calling this tool
97
99
  - `create_feature` — Create a new feature (title, optional description, optional epicId, optional releaseId, optional projectId, optional teamId)
98
100
  > [!NOTE]
99
101
  > `projectId` and `teamId` are optional — fall back to `TP_PROJECT_ID` and `TP_TEAM_ID` from config
@@ -0,0 +1,55 @@
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
+ }
package/build/index.js CHANGED
@@ -39,6 +39,7 @@ 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";
42
43
  const server = new McpServer({
43
44
  name: "tp",
44
45
  version: "1.0.0"
@@ -1385,6 +1386,72 @@ server.registerTool('get_my_time_logs', {
1385
1386
  .describe('Number of entries to return, default is 25'),
1386
1387
  },
1387
1388
  }, 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 }));
1388
1455
  async function main() {
1389
1456
  const transport = new StdioServerTransport();
1390
1457
  await server.connect(transport);
package/package.json CHANGED
@@ -27,7 +27,7 @@
27
27
  "engines": {
28
28
  "node": ">=20.x"
29
29
  },
30
- "version": "2.4.1",
30
+ "version": "2.4.2",
31
31
  "description": "MCP server for Tartget Process",
32
32
  "main": "build/index.js",
33
33
  "keywords": [