targetprocess-mcp-server 2.3.0 → 2.3.1

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.
Files changed (37) hide show
  1. package/README.md +39 -0
  2. package/build/config.js +0 -0
  3. package/build/handlers/add_comment.js +14 -0
  4. package/build/handlers/create_bug.js +14 -0
  5. package/build/handlers/create_feature.js +14 -0
  6. package/build/handlers/create_task.js +14 -0
  7. package/build/handlers/create_user_story.js +14 -0
  8. package/build/handlers/get_bug_comments.js +45 -0
  9. package/build/handlers/get_bug_content.js +37 -0
  10. package/build/handlers/get_card_current_status.js +23 -0
  11. package/build/handlers/get_commit_message.js +42 -0
  12. package/build/handlers/get_current_releases.js +20 -0
  13. package/build/handlers/get_feature_user_stories.js +23 -0
  14. package/build/handlers/get_in_progress_tasks_and_bugs.js +35 -0
  15. package/build/handlers/get_logged_in_user.js +23 -0
  16. package/build/handlers/get_my_time_logs.js +20 -0
  17. package/build/handlers/get_projects.js +23 -0
  18. package/build/handlers/get_release_bugs.js +20 -0
  19. package/build/handlers/get_release_features.js +20 -0
  20. package/build/handlers/get_release_open_bugs.js +20 -0
  21. package/build/handlers/get_release_open_user_stories.js +20 -0
  22. package/build/handlers/get_release_user_stories.js +20 -0
  23. package/build/handlers/get_teams.js +41 -0
  24. package/build/handlers/get_user_by_id.js +14 -0
  25. package/build/handlers/get_user_story_bugs.js +23 -0
  26. package/build/handlers/get_user_story_comments.js +45 -0
  27. package/build/handlers/get_user_story_content.js +44 -0
  28. package/build/handlers/get_users.js +20 -0
  29. package/build/handlers/list_my_bugs.js +23 -0
  30. package/build/handlers/list_my_user_stories.js +23 -0
  31. package/build/handlers/log_time.js +14 -0
  32. package/build/handlers/update_bug.js +14 -0
  33. package/build/handlers/update_user_story_sub_state.js +14 -0
  34. package/build/index.js +94 -859
  35. package/build/tp.js +25 -0
  36. package/build/types.js +0 -0
  37. package/package.json +12 -7
package/README.md CHANGED
@@ -51,6 +51,8 @@ User Stories
51
51
  Tasks
52
52
  - `get_in_progress_tasks_and_bugs` — Get all Tasks and Bugs currently in "In Progress" state assigned to a given user (userId)
53
53
  - `create_task` — Create a new task linked to a user story (title, userStoryId, optional description)
54
+ - `list_my_user_stories` — List User Stories assigned to the current user, optionally filtered by state (optional state, optional take, optional skip)
55
+ - `list_my_bugs` — List Bugs assigned to the current user, optionally filtered by state (optional state, optional take, optional skip)
54
56
 
55
57
  Cards — Read
56
58
  - `get_card_current_status` — Get EntityState, TeamState, and assigned teams for a card (id, optional resourceType: UserStory | Bug | Feature, default: UserStory)
@@ -68,6 +70,9 @@ Cards — Write
68
70
  > Resolve state name → ID via `get_bug_workflows` before passing `entityStateId`
69
71
  - `update_user_story` — Update an existing user story (id, optional title, optional description, optional projectId, optional teamId, optional entityStateId)
70
72
  > Resolve state name → ID via `get_user_story_workflows` before passing `entityStateId`
73
+ - `update_user_story_state` — Update the sub-state (team assignment entity state) for a user story (id, optional entityStateId, optional teamId, optional teamAssignmentId)
74
+ > 1. Call `get_user_story_content` first to find the assigned team and `teamAssignmentId`
75
+ > 2. Call `get_user_story_workflows` to resolve the target state name → `entityStateId`
71
76
  - `create_bug` — Create a standalone bug (title, bugContent, optional origin, optional projectId, optional teamId, optional entityStateName)
72
77
  > `origin` accepted values: `Production - Customer`, `Production - Internal`, `Pre-Release - Customer`, `Pre-Release - Internal`, `Regression - Dev01`, `Regression - Team Env`, `Manual QA` *(default)*, `Developer Raised`, `Operations`
73
78
  > `entityStateName` accepted values: `Backlog`, `In Triage`, `Ready for Dev`, `In Dev`, `Blocked`, `PR Raised`, `Ready for Feature PCH`, `Ready for Feature QA`, `In Feature QA`, `Failed Feature QA`, `Ready for Merge`, `Ready to Deploy to Dev01`, `Ready for Dev01 QA`, `In Dev01 QA`, `Failed Dev01 QA`, `Ready to Deploy to prod`, `Closed`
@@ -101,12 +106,17 @@ Projects
101
106
 
102
107
  Teams
103
108
  - `get_teams` — Get all Targetprocess teams returning id and name (no params needed)
109
+ - `get_teams_and_team_assignments` — Get all teams and team assignments (id and name for each) (no params needed)
104
110
 
105
111
  User
106
112
  - `get_logged_in_user` — Get the currently logged-in user's info (no params needed)
107
113
  - `get_users` — Get all Targetprocess users (no params needed)
108
114
  - `get_user_by_id` — Get a single Targetprocess user by their ID (id)
109
115
 
116
+ Time Tracking
117
+ - `log_time` — Log time spent on a Task, User Story, or Bug (entityId, entityType: Task | UserStory | Bug, hours, optional description, optional date)
118
+ - `get_my_time_logs` — Get recent time log entries submitted by the current user (optional take)
119
+
110
120
  Developer Tools
111
121
  - `get_commit_message` — Returns a formatted commit message string for a task or bug ID (id, type: task | bug)
112
122
  > Format for task on a user story: `F#<featureId> US#<userStoryId> T#<taskId> <title>`
@@ -177,3 +187,32 @@ cd targetprocess-mcp-server
177
187
  npm install
178
188
  npm run build
179
189
  ```
190
+
191
+ ## Testing
192
+
193
+ Tests live in `tests/` and use [Vitest](https://vitest.dev/). All tool handlers are extracted to `src/handlers/` and tested with mocked `TpClient` instances — no network calls are made.
194
+
195
+ ```bash
196
+ npx vitest run # run all tests once
197
+ npx vitest # watch mode
198
+ ```
199
+
200
+ ### Coverage
201
+
202
+ **33 of 46 tools (72%) are covered by unit tests.**
203
+
204
+ | Test file | Handlers covered |
205
+ |---|---|
206
+ | `get_bug_content.test.ts` | `get_bug_content` |
207
+ | `get_user_story_content.test.ts` | `get_user_story_content` |
208
+ | `get_commit_message.test.ts` | `get_commit_message` |
209
+ | `get_current_releases.test.ts` | `get_current_releases` |
210
+ | `get_projects.test.ts` | `get_projects` |
211
+ | `get_logged_in_user.test.ts` | `get_logged_in_user` |
212
+ | `get_user_by_id.test.ts` | `get_user_by_id` |
213
+ | `release_tools.test.ts` | `get_release_user_stories`, `get_release_bugs`, `get_release_features`, `get_release_open_bugs`, `get_release_open_user_stories` |
214
+ | `user_team_tools.test.ts` | `get_users`, `get_teams`, `get_teams_and_team_assignments` |
215
+ | `comment_tools.test.ts` | `add_comment`, `get_user_story_comments`, `get_bug_comments` |
216
+ | `creation_tools.test.ts` | `create_bug`, `create_user_story`, `create_feature`, `create_task`, `update_bug`, `update_user_story_state` |
217
+ | `my_work_tools.test.ts` | `get_in_progress_tasks_and_bugs`, `list_my_user_stories`, `list_my_bugs`, `log_time`, `get_my_time_logs` |
218
+ | `entity_tools.test.ts` | `get_feature_user_stories`, `get_user_story_bugs`, `get_card_current_status` |
package/build/config.js CHANGED
File without changes
@@ -0,0 +1,14 @@
1
+ export async function handleAddComment(tp, id, comment) {
2
+ const response = await tp.addComment(id, comment);
3
+ if (!response) {
4
+ return {
5
+ content: [{
6
+ type: 'text',
7
+ text: `Failed to add comment to user story, id: ${id}\n JSON: ${JSON.stringify(response, null, 2)}`
8
+ }],
9
+ };
10
+ }
11
+ return {
12
+ content: [{ type: 'text', text: JSON.stringify(response) }],
13
+ };
14
+ }
@@ -0,0 +1,14 @@
1
+ export async function handleCreateBug(tp, params) {
2
+ const bugResponse = await tp.createBugOnly(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
+ }
@@ -0,0 +1,14 @@
1
+ export async function handleCreateFeature(tp, params) {
2
+ const response = await tp.createFeature(params);
3
+ if (!response) {
4
+ return {
5
+ content: [{
6
+ type: 'text',
7
+ text: `Failed to create feature "${params.title}"\n JSON: ${JSON.stringify(response, null, 2)}`
8
+ }],
9
+ };
10
+ }
11
+ return {
12
+ content: [{ type: 'text', text: JSON.stringify(response) }],
13
+ };
14
+ }
@@ -0,0 +1,14 @@
1
+ export async function handleCreateTask(tp, params) {
2
+ const response = await tp.createTask(params);
3
+ if (!response) {
4
+ return {
5
+ content: [{
6
+ type: 'text',
7
+ text: `Failed to create task "${params.title}"\n JSON: ${JSON.stringify(response, null, 2)}`
8
+ }],
9
+ };
10
+ }
11
+ return {
12
+ content: [{ type: 'text', text: JSON.stringify(response) }],
13
+ };
14
+ }
@@ -0,0 +1,14 @@
1
+ export async function handleCreateUserStory(tp, params) {
2
+ const response = await tp.createUserStory(params);
3
+ if (!response) {
4
+ return {
5
+ content: [{
6
+ type: 'text',
7
+ text: `Failed to create user story "${params.title}"\n JSON: ${JSON.stringify(response, null, 2)}`
8
+ }],
9
+ };
10
+ }
11
+ return {
12
+ content: [{ type: 'text', text: JSON.stringify(response) }],
13
+ };
14
+ }
@@ -0,0 +1,45 @@
1
+ import { JSDOM } from 'jsdom';
2
+ export async function handleGetBugComments(tp, id, results) {
3
+ const response = await tp.getBugComments(id, results);
4
+ if (!response) {
5
+ return {
6
+ content: [{
7
+ type: 'text',
8
+ text: `Failed to get comments for bug id: ${id}`
9
+ }],
10
+ };
11
+ }
12
+ const items = response.Items || [];
13
+ if (items.length === 0) {
14
+ return {
15
+ content: [{
16
+ type: 'text',
17
+ text: `No comments found for bug id: ${id}`,
18
+ }],
19
+ };
20
+ }
21
+ try {
22
+ const parsedItems = items.map((item) => {
23
+ const dom = new JSDOM(`<html><body><div id="content">${item.Description}</div></body></html>`);
24
+ const descriptionText = dom.window.document.getElementById('content')?.textContent;
25
+ return {
26
+ id: item.Id,
27
+ description: descriptionText,
28
+ createDate: item.CreateDate,
29
+ owner: item.Owner.FullName,
30
+ };
31
+ });
32
+ return {
33
+ content: [{ type: 'text', text: JSON.stringify(parsedItems) }],
34
+ };
35
+ }
36
+ catch (error) {
37
+ console.error('Error parsing bug comments:', error);
38
+ return {
39
+ content: [{
40
+ type: 'text',
41
+ text: `Failed to parse bug comments for bug id: ${id}`,
42
+ }],
43
+ };
44
+ }
45
+ }
@@ -0,0 +1,37 @@
1
+ import { JSDOM } from 'jsdom';
2
+ export async function handleGetBugContent(tp, id) {
3
+ const bug = await tp.getBug(id);
4
+ if (!bug) {
5
+ return {
6
+ content: [{
7
+ type: 'text',
8
+ text: `Failed to get bug, id: ${id}\n JSON: ${JSON.stringify(bug, null, 2)}`
9
+ }],
10
+ };
11
+ }
12
+ const bugResult = {
13
+ name: bug.Name,
14
+ id: bug.Id,
15
+ description: '',
16
+ origin: '',
17
+ };
18
+ try {
19
+ const dom = new JSDOM(`<html><body><div id="content">${bug.Description}</div></body></html>`);
20
+ const descriptionText = dom.window.document.getElementById('content')?.textContent;
21
+ if (descriptionText) {
22
+ bugResult.description = descriptionText;
23
+ }
24
+ }
25
+ catch (error) {
26
+ console.error('Error parsing bug description:', error);
27
+ }
28
+ try {
29
+ bugResult.origin = bug.CustomFields?.find((field) => field?.Value === 'Origin')?.Value;
30
+ }
31
+ catch (error) {
32
+ console.error('Error parsing bug origin:', error);
33
+ }
34
+ return {
35
+ content: [{ type: 'text', text: JSON.stringify(bugResult) }],
36
+ };
37
+ }
@@ -0,0 +1,23 @@
1
+ export async function handleGetCardCurrentStatus(tp, id, resourceType = 'UserStory') {
2
+ const response = await tp.getCardStatus(id, resourceType);
3
+ if (!response) {
4
+ return {
5
+ content: [{
6
+ type: 'text',
7
+ text: `Failed to get card status for ${resourceType} id: ${id}`
8
+ }],
9
+ };
10
+ }
11
+ const items = response.items || [];
12
+ if (items.length === 0) {
13
+ return {
14
+ content: [{
15
+ type: 'text',
16
+ text: `No status data found for ${resourceType} id: ${id}`,
17
+ }],
18
+ };
19
+ }
20
+ return {
21
+ content: [{ type: 'text', text: JSON.stringify(items[0]) }],
22
+ };
23
+ }
@@ -0,0 +1,42 @@
1
+ export async function handleGetCommitMessage(tp, id, type) {
2
+ if (type === 'task') {
3
+ const task = await tp.getTask(id);
4
+ if (!task) {
5
+ return {
6
+ content: [{ type: 'text', text: `Failed to get task with id: ${id}` }],
7
+ };
8
+ }
9
+ const userStory = task.UserStory;
10
+ if (!userStory) {
11
+ return {
12
+ content: [{ type: 'text', text: `Task ${id} has no linked user story` }],
13
+ };
14
+ }
15
+ const feature = userStory.Feature;
16
+ const prefix = feature
17
+ ? `F#${feature.Id} US#${userStory.Id} T#${task.Id}`
18
+ : `US#${userStory.Id} T#${task.Id}`;
19
+ return {
20
+ content: [{ type: 'text', text: `${prefix} ${task.Name}` }],
21
+ };
22
+ }
23
+ const bug = await tp.getBugWithRelations(id);
24
+ if (!bug) {
25
+ return {
26
+ content: [{ type: 'text', text: `Failed to get bug with id: ${id}` }],
27
+ };
28
+ }
29
+ const userStory = bug.UserStory;
30
+ const feature = userStory?.Feature ?? bug.Feature;
31
+ if (!userStory) {
32
+ return {
33
+ content: [{ type: 'text', text: `B#${bug.Id} ${bug.Name}` }],
34
+ };
35
+ }
36
+ const prefix = feature
37
+ ? `F#${feature.Id} US#${userStory.Id} B#${bug.Id}`
38
+ : `US#${userStory.Id} B#${bug.Id}`;
39
+ return {
40
+ content: [{ type: 'text', text: `${prefix} ${bug.Name}` }],
41
+ };
42
+ }
@@ -0,0 +1,20 @@
1
+ export async function handleGetCurrentReleases(tp) {
2
+ const releases = await tp.getCurrentReleases();
3
+ if (!releases) {
4
+ return {
5
+ content: [{
6
+ type: 'text',
7
+ text: `Failed to get current releases, JSON: ${JSON.stringify(releases, null, 2)}`
8
+ }],
9
+ };
10
+ }
11
+ const items = releases.Items || [];
12
+ if (items.length === 0) {
13
+ return {
14
+ content: [{ type: 'text', text: 'No releases found' }],
15
+ };
16
+ }
17
+ return {
18
+ content: [{ type: 'text', text: JSON.stringify(items) }],
19
+ };
20
+ }
@@ -0,0 +1,23 @@
1
+ export async function handleGetFeatureUserStories(tp, id) {
2
+ const response = await tp.getFeatureUserStories(id);
3
+ if (!response) {
4
+ return {
5
+ content: [{
6
+ type: 'text',
7
+ text: `Failed to get user stories for feature id: ${id}`
8
+ }],
9
+ };
10
+ }
11
+ const items = response.items || [];
12
+ if (items.length === 0) {
13
+ return {
14
+ content: [{
15
+ type: 'text',
16
+ text: `No user stories found in outer items for feature id: ${id}`,
17
+ }],
18
+ };
19
+ }
20
+ return {
21
+ content: [{ type: 'text', text: JSON.stringify(items) }],
22
+ };
23
+ }
@@ -0,0 +1,35 @@
1
+ export async function handleGetInProgressTasksAndBugs(tp, userId) {
2
+ const result = await tp.getInProgressTasksAndBugs(userId);
3
+ const tasks = result.tasks.map((t) => ({
4
+ type: 'Task',
5
+ id: t.Id,
6
+ name: t.Name,
7
+ state: t.EntityState?.Name,
8
+ userStoryId: t.UserStory?.Id,
9
+ userStoryName: t.UserStory?.Name,
10
+ featureId: t.UserStory?.Feature?.Id,
11
+ featureName: t.UserStory?.Feature?.Name,
12
+ }));
13
+ const bugs = result.bugs.map((b) => ({
14
+ type: 'Bug',
15
+ id: b.Id,
16
+ name: b.Name,
17
+ state: b.EntityState?.Name,
18
+ userStoryId: b.UserStory?.Id,
19
+ userStoryName: b.UserStory?.Name,
20
+ featureId: b.UserStory?.Feature?.Id ?? b.Feature?.Id,
21
+ featureName: b.UserStory?.Feature?.Name ?? b.Feature?.Name,
22
+ }));
23
+ const items = [...tasks, ...bugs];
24
+ if (items.length === 0) {
25
+ return {
26
+ content: [{
27
+ type: 'text',
28
+ text: `No in-progress tasks or bugs found for user ID: ${userId}`,
29
+ }],
30
+ };
31
+ }
32
+ return {
33
+ content: [{ type: 'text', text: JSON.stringify(items) }],
34
+ };
35
+ }
@@ -0,0 +1,23 @@
1
+ export async function handleGetLoggedInUser(tp) {
2
+ const ctx = await tp.getContext();
3
+ if (!ctx) {
4
+ return {
5
+ content: [{
6
+ type: 'text',
7
+ text: `Failed to get context, JSON: ${JSON.stringify(ctx, null, 2)}`
8
+ }],
9
+ };
10
+ }
11
+ const loggedInUser = ctx.LoggedUser;
12
+ if (!loggedInUser) {
13
+ return {
14
+ content: [{
15
+ type: 'text',
16
+ text: `Failed to get logged in user in this context, JSON: ${JSON.stringify(ctx, null, 2)}`
17
+ }],
18
+ };
19
+ }
20
+ return {
21
+ content: [{ type: 'text', text: JSON.stringify(loggedInUser) }],
22
+ };
23
+ }
@@ -0,0 +1,20 @@
1
+ export async function handleGetMyTimeLogs(tp, take) {
2
+ const response = await tp.getMyTimeLogs(take);
3
+ if (!response) {
4
+ return {
5
+ content: [{
6
+ type: 'text',
7
+ text: `Failed to get time logs, JSON: ${JSON.stringify(response, null, 2)}`
8
+ }],
9
+ };
10
+ }
11
+ const items = response.Items || [];
12
+ if (items.length === 0) {
13
+ return {
14
+ content: [{ type: 'text', text: 'No time logs found' }],
15
+ };
16
+ }
17
+ return {
18
+ content: [{ type: 'text', text: JSON.stringify(items) }],
19
+ };
20
+ }
@@ -0,0 +1,23 @@
1
+ export async function handleGetProjects(tp) {
2
+ const response = await tp.getProjects();
3
+ if (!response) {
4
+ return {
5
+ content: [{
6
+ type: 'text',
7
+ text: `Failed to get projects, JSON: ${JSON.stringify(response, null, 2)}`
8
+ }],
9
+ };
10
+ }
11
+ const items = response.Items || [];
12
+ if (items.length === 0) {
13
+ return {
14
+ content: [{ type: 'text', text: 'No projects found' }],
15
+ };
16
+ }
17
+ return {
18
+ content: [{
19
+ type: 'text',
20
+ text: JSON.stringify(items.map((p) => ({ id: p.Id, name: p.Name })))
21
+ }],
22
+ };
23
+ }
@@ -0,0 +1,20 @@
1
+ export async function handleGetReleaseBugs(tp, name, results) {
2
+ const release = await tp.getReleaseBugs({ name, results });
3
+ if (!release) {
4
+ return {
5
+ content: [{
6
+ type: 'text',
7
+ text: `Failed to get ${name} release bugs, JSON: ${JSON.stringify(release, null, 2)}`
8
+ }],
9
+ };
10
+ }
11
+ const items = release.Items || [];
12
+ if (items.length === 0) {
13
+ return {
14
+ content: [{ type: 'text', text: 'No release bugs found' }],
15
+ };
16
+ }
17
+ return {
18
+ content: [{ type: 'text', text: JSON.stringify(items) }],
19
+ };
20
+ }
@@ -0,0 +1,20 @@
1
+ export async function handleGetReleaseFeatures(tp, name, results) {
2
+ const release = await tp.getReleaseFeatures({ name, results });
3
+ if (!release) {
4
+ return {
5
+ content: [{
6
+ type: 'text',
7
+ text: `Failed to get ${name} release features, JSON: ${JSON.stringify(release, null, 2)}`
8
+ }],
9
+ };
10
+ }
11
+ const items = release.Items || [];
12
+ if (items.length === 0) {
13
+ return {
14
+ content: [{ type: 'text', text: 'No release features found' }],
15
+ };
16
+ }
17
+ return {
18
+ content: [{ type: 'text', text: JSON.stringify(items) }],
19
+ };
20
+ }
@@ -0,0 +1,20 @@
1
+ export async function handleGetReleaseOpenBugs(tp, name, results, withDescription) {
2
+ const release = await tp.getReleaseOpenBugs({ name, results, withDescription });
3
+ if (!release) {
4
+ return {
5
+ content: [{
6
+ type: 'text',
7
+ text: `Failed to get ${name} release bugs, JSON: ${JSON.stringify(release, null, 2)}`
8
+ }],
9
+ };
10
+ }
11
+ const items = release.Items || [];
12
+ if (items.length === 0) {
13
+ return {
14
+ content: [{ type: 'text', text: 'No release bugs found' }],
15
+ };
16
+ }
17
+ return {
18
+ content: [{ type: 'text', text: JSON.stringify(items) }],
19
+ };
20
+ }
@@ -0,0 +1,20 @@
1
+ export async function handleGetReleaseOpenUserStories(tp, name, results, withDescription) {
2
+ const release = await tp.getReleaseOpenUserStories({ name, results, withDescription });
3
+ if (!release) {
4
+ return {
5
+ content: [{
6
+ type: 'text',
7
+ text: `Failed to get ${name} release user stories, JSON: ${JSON.stringify(release, null, 2)}`
8
+ }],
9
+ };
10
+ }
11
+ const items = release.Items || [];
12
+ if (items.length === 0) {
13
+ return {
14
+ content: [{ type: 'text', text: 'No release user stories found' }],
15
+ };
16
+ }
17
+ return {
18
+ content: [{ type: 'text', text: JSON.stringify(items) }],
19
+ };
20
+ }
@@ -0,0 +1,20 @@
1
+ export async function handleGetReleaseUserStories(tp, name, results, withDescription) {
2
+ const release = await tp.getReleaseUserStories({ name, results, withDescription });
3
+ if (!release) {
4
+ return {
5
+ content: [{
6
+ type: 'text',
7
+ text: `Failed to get ${name} release user stories, JSON: ${JSON.stringify(release, null, 2)}`
8
+ }],
9
+ };
10
+ }
11
+ const items = release.Items || [];
12
+ if (items.length === 0) {
13
+ return {
14
+ content: [{ type: 'text', text: 'No release user stories found' }],
15
+ };
16
+ }
17
+ return {
18
+ content: [{ type: 'text', text: JSON.stringify(items) }],
19
+ };
20
+ }
@@ -0,0 +1,41 @@
1
+ export async function handleGetTeams(tp) {
2
+ const response = await tp.getTeams();
3
+ if (!response) {
4
+ return {
5
+ content: [{
6
+ type: 'text',
7
+ text: `Failed to get teams, JSON: ${JSON.stringify(response, null, 2)}`
8
+ }],
9
+ };
10
+ }
11
+ const items = response.Items || [];
12
+ if (items.length === 0) {
13
+ return {
14
+ content: [{ type: 'text', text: 'No teams found' }],
15
+ };
16
+ }
17
+ return {
18
+ content: [{ type: 'text', text: JSON.stringify(items.map((t) => ({ id: t.Id, name: t.Name }))) }],
19
+ };
20
+ }
21
+ export async function handleGetTeamsAndTeamAssignments(tp) {
22
+ const teams = await tp.getTeams();
23
+ const teamAssignments = await tp.getTeamAssignments();
24
+ if (!teams || !teamAssignments) {
25
+ return {
26
+ content: [{
27
+ type: 'text',
28
+ text: `Failed to get teams and team assignments, JSON: ${JSON.stringify({ teams, teamAssignments }, null, 2)}`
29
+ }],
30
+ };
31
+ }
32
+ return {
33
+ content: [{
34
+ type: 'text',
35
+ text: JSON.stringify({
36
+ teams: teams.Items.map((t) => ({ id: t.Id, name: t.Name })),
37
+ teamAssignments: teamAssignments.Items.map((t) => ({ id: t.Id, name: t.Team.Name })),
38
+ }),
39
+ }],
40
+ };
41
+ }
@@ -0,0 +1,14 @@
1
+ export async function handleGetUserById(tp, id) {
2
+ const user = await tp.getUser(id);
3
+ if (!user) {
4
+ return {
5
+ content: [{
6
+ type: 'text',
7
+ text: `Failed to get user, id: ${id}\n JSON: ${JSON.stringify(user, null, 2)}`
8
+ }],
9
+ };
10
+ }
11
+ return {
12
+ content: [{ type: 'text', text: JSON.stringify(user) }],
13
+ };
14
+ }
@@ -0,0 +1,23 @@
1
+ export async function handleGetUserStoryBugs(tp, id) {
2
+ const response = await tp.getUserStoryBugs(id);
3
+ if (!response) {
4
+ return {
5
+ content: [{
6
+ type: 'text',
7
+ text: `Failed to get bugs for user story id: ${id}`
8
+ }],
9
+ };
10
+ }
11
+ const items = response.items || [];
12
+ if (items.length === 0) {
13
+ return {
14
+ content: [{
15
+ type: 'text',
16
+ text: `No bugs found for user story id: ${id}`,
17
+ }],
18
+ };
19
+ }
20
+ return {
21
+ content: [{ type: 'text', text: JSON.stringify(items) }],
22
+ };
23
+ }