targetprocess-mcp-server 2.6.5 → 2.6.7-a

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
@@ -159,6 +159,51 @@ Developer Tools
159
159
  ---
160
160
 
161
161
  ## Installation
162
+ ### As a Claude Code Plugin
163
+
164
+ **Prerequisites:** Claude Code CLI installed, and a Targetprocess account with API access.
165
+
166
+ 1. **Get your Targetprocess API token**
167
+ In Targetprocess, go to *Settings → Authentication and Security → New Access Token* and copy it.
168
+
169
+ 2. **Add this repo as a plugin marketplace**
170
+ Run inside Claude Code:
171
+ ```bash
172
+ /plugin marketplace add SerhiiMaksymiv/targetprocess-mcp-server
173
+ ```
174
+
175
+ 3. **Install the plugin**
176
+ ```bash
177
+ /plugin install targetprocess-mcp
178
+ ```
179
+
180
+ 4. **Fill in the configuration prompts**
181
+ Claude Code will ask for each value in turn:
182
+ | Prompt | What to enter |
183
+ |---|---|
184
+ | Targetprocess API Token | The token from step 1 (input is masked) |
185
+ | Targetprocess Base URL | Your API endpoint, e.g. `https://yourcompany.tpondemand.com/api/v1` |
186
+ | Targetprocess Owner ID | Your user ID — leave the default flow, install first and run the `get_logged_in_user` tool to look it up if you don't know it yet |
187
+ | Targetprocess Project ID *(optional)* | Look up via the `get_projects` tool — press Enter to skip |
188
+ | Targetprocess Team ID *(optional)* | Look up via the `get_teams` tool — press Enter to skip |
189
+
190
+ Values are stored by Claude Code (the token is kept masked/sensitive) — no manual editing of `settings.json` needed.
191
+
192
+ 5. **Restart Claude Code** (or start a new session) so the plugin's MCP server connects with the new config.
193
+
194
+ 6. **Verify it's connected**
195
+ ```bash
196
+ /mcp
197
+ ```
198
+ `targetprocess` should show as connected. Try asking Claude something like *"show me the current active release"* to confirm the tools work end to end.
199
+
200
+ **Updating config later:** re-run `/plugin install targetprocess-mcp` (or use `/plugin` to manage installed plugins) to be re-prompted for values.
201
+
202
+ **Uninstalling:**
203
+ ```bash
204
+ /plugin uninstall targetprocess-mcp
205
+ ```
206
+
162
207
  ### Local Installation for Development
163
208
  ```json
164
209
  {
@@ -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) add a comment to the card with created bug Id and its Title`,
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.
@@ -544,7 +541,8 @@ server.registerTool('create_bug', {
544
541
  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
542
  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
543
  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;`,
544
+ 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;
545
+ 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
546
  inputSchema: {
549
547
  title: z.string()
550
548
  .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 +561,11 @@ server.registerTool('create_bug', {
563
561
  ])
564
562
  .optional()
565
563
  .describe('Where the bug was found, defaults to "Manual QA" if no origin was specified'),
564
+ releaseId: z.string()
565
+ .min(5)
566
+ .max(9)
567
+ .optional()
568
+ .describe('Optional Release ID to assign this bug to — if user gave a release name, resolve it via "get_current_releases" first'),
566
569
  projectId: z.string()
567
570
  .optional()
568
571
  .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 +582,7 @@ server.registerTool('create_bug', {
579
582
  .optional()
580
583
  .describe('Optional Team Iteration (sprint) ID — resolve it via "get_team_iterations" first'),
581
584
  },
582
- }, async ({ title, bugContent, origin, projectId, teamId, entityStateId, tags, teamIterationId }) => handleCreateBug(tp, { title, bugContent, origin, projectId, teamId, entityStateId, tags, teamIterationId }));
585
+ }, async ({ title, bugContent, origin, releaseId, projectId, teamId, entityStateId, tags, teamIterationId }) => handleCreateBug(tp, { title, bugContent, origin, releaseId, projectId, teamId, entityStateId, tags, teamIterationId }));
583
586
  server.registerTool('create_user_story', {
584
587
  title: 'Create a new user story',
585
588
  description: `Create a new user story in Targetprocess.
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,7 @@ export class TpClient {
258
260
  param: { "format": "json" },
259
261
  }, userStory);
260
262
  }
261
- async updateBug({ id, title, bugContent, origin, projectId, teamId, entityStateId, tags, teamIterationId }) {
263
+ async updateBug({ id, title, bugContent, origin, releaseId, projectId, teamId, entityStateId, tags, teamIterationId }) {
262
264
  const bug = { "Id": id };
263
265
  if (title)
264
266
  bug["Name"] = title;
@@ -270,6 +272,8 @@ export class TpClient {
270
272
  "type": "DropDown",
271
273
  "value": origin
272
274
  }];
275
+ if (releaseId)
276
+ bug["Release"] = { "Id": releaseId };
273
277
  if (projectId)
274
278
  bug["Project"] = { "Id": projectId };
275
279
  if (teamId)
@@ -289,17 +293,12 @@ export class TpClient {
289
293
  param: { "format": "json" },
290
294
  }, bug);
291
295
  }
292
- async createBugOnly({ title, bugContent, origin = "Manual QA", projectId, teamId, entityStateId, tags, teamIterationId }) {
296
+ async createBugOnly({ title, bugContent, origin, releaseId, projectId, teamId, entityStateId, tags, teamIterationId }) {
293
297
  const bug = {
294
298
  "Name": title,
295
299
  "Project": {
296
300
  "Id": projectId || config.tp.projectId
297
301
  },
298
- "customFields": [{
299
- "name": "Origin",
300
- "type": "DropDown",
301
- "value": origin
302
- }],
303
302
  "assignedTeams": [{
304
303
  "team": {
305
304
  "id": teamId || config.tp.teamId
@@ -307,6 +306,15 @@ export class TpClient {
307
306
  }],
308
307
  "Description": bugContent,
309
308
  };
309
+ if (origin) {
310
+ bug["customFields"] = [{
311
+ "name": "Origin",
312
+ "type": "DropDown",
313
+ "value": origin
314
+ }];
315
+ }
316
+ if (releaseId)
317
+ bug["Release"] = { "Id": releaseId };
310
318
  if (entityStateId)
311
319
  bug["EntityState"] = { "Id": entityStateId };
312
320
  if (tags)
@@ -440,17 +448,8 @@ export class TpClient {
440
448
  async createBugBasedOnUserStory(title, userStoryId, bugContent) {
441
449
  const bug = {
442
450
  "Name": title,
443
- "Project": {
444
- "Id": config.tp.projectId
445
- },
446
- "UserStory": {
447
- "Id": userStoryId
448
- },
449
- "customFields": [{
450
- "name": "Origin",
451
- "type": "DropDown",
452
- "value": "Manual QA"
453
- }],
451
+ "Project": { "Id": config.tp.projectId },
452
+ "UserStory": { "Id": userStoryId },
454
453
  "assignedTeams": [{
455
454
  "team": {
456
455
  "id": config.tp.teamId
package/package.json CHANGED
@@ -27,7 +27,7 @@
27
27
  "engines": {
28
28
  "node": ">=20.x"
29
29
  },
30
- "version": "2.6.5",
30
+ "version": "2.6.7a",
31
31
  "description": "MCP server for Tartget Process",
32
32
  "main": "build/index.js",
33
33
  "keywords": [