backlog-mcp-server 0.8.0 → 0.9.0

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 (86) hide show
  1. package/build/backlog/backlogErrorHandler.js +8 -0
  2. package/build/backlog/customFields.js +70 -0
  3. package/build/backlog/parseBacklogAPIError.js +38 -0
  4. package/build/createTranslationHelper.js +28 -0
  5. package/build/handlers/builders/composeToolHandler.js +26 -0
  6. package/build/handlers/transformers/wrapWithErrorHandling.js +4 -0
  7. package/build/handlers/transformers/wrapWithFieldPicking.js +55 -0
  8. package/build/handlers/transformers/wrapWithTokenLimit.js +21 -0
  9. package/build/handlers/transformers/wrapWithToolResult.js +39 -0
  10. package/build/index.js +101 -0
  11. package/build/registerTools.js +37 -0
  12. package/build/tools/addDocument.js +40 -0
  13. package/build/tools/addIssue.js +97 -0
  14. package/build/tools/addIssueComment.js +44 -0
  15. package/build/tools/addProject.js +39 -0
  16. package/build/tools/addPullRequest.js +65 -0
  17. package/build/tools/addPullRequestComment.js +52 -0
  18. package/build/tools/addVersionMilestone.js +51 -0
  19. package/build/tools/addWatching.js +25 -0
  20. package/build/tools/addWiki.js +29 -0
  21. package/build/tools/countIssues.js +105 -0
  22. package/build/tools/deleteDocument.js +19 -0
  23. package/build/tools/deleteIssue.js +29 -0
  24. package/build/tools/deleteProject.js +29 -0
  25. package/build/tools/deleteVersion.js +35 -0
  26. package/build/tools/deleteWatching.js +17 -0
  27. package/build/tools/dynamicTools/toolsets.js +103 -0
  28. package/build/tools/getCategories.js +30 -0
  29. package/build/tools/getCustomFields.js +37 -0
  30. package/build/tools/getDocument.js +20 -0
  31. package/build/tools/getDocumentTree.js +20 -0
  32. package/build/tools/getDocuments.js +25 -0
  33. package/build/tools/getGitRepositories.js +29 -0
  34. package/build/tools/getGitRepository.js +41 -0
  35. package/build/tools/getIssue.js +29 -0
  36. package/build/tools/getIssueComments.js +45 -0
  37. package/build/tools/getIssueTypes.js +30 -0
  38. package/build/tools/getIssues.js +149 -0
  39. package/build/tools/getMyself.js +14 -0
  40. package/build/tools/getNotifications.js +35 -0
  41. package/build/tools/getNotificationsCount.js +20 -0
  42. package/build/tools/getPriorities.js +13 -0
  43. package/build/tools/getProject.js +29 -0
  44. package/build/tools/getProjectList.js +23 -0
  45. package/build/tools/getPullRequest.js +44 -0
  46. package/build/tools/getPullRequestComments.js +60 -0
  47. package/build/tools/getPullRequests.js +65 -0
  48. package/build/tools/getPullRequestsCount.js +57 -0
  49. package/build/tools/getResolutions.js +13 -0
  50. package/build/tools/getSpace.js +14 -0
  51. package/build/tools/getSpaceActivities.js +42 -0
  52. package/build/tools/getUserRecentUpdates.js +48 -0
  53. package/build/tools/getUserStarsCount.js +25 -0
  54. package/build/tools/getUsers.js +14 -0
  55. package/build/tools/getVersionMilestoneList.js +37 -0
  56. package/build/tools/getWatchingListCount.js +17 -0
  57. package/build/tools/getWatchingListItems.js +17 -0
  58. package/build/tools/getWiki.js +21 -0
  59. package/build/tools/getWikiPages.js +37 -0
  60. package/build/tools/getWikisCount.js +29 -0
  61. package/build/tools/markNotificationAsRead.js +26 -0
  62. package/build/tools/markWatchingAsRead.js +26 -0
  63. package/build/tools/resetUnreadNotificationCount.js +13 -0
  64. package/build/tools/shared/customFieldFiltersSchema.js +78 -0
  65. package/build/tools/tools.js +171 -0
  66. package/build/tools/updateIssue.js +119 -0
  67. package/build/tools/updateProject.js +57 -0
  68. package/build/tools/updatePullRequest.js +68 -0
  69. package/build/tools/updatePullRequestComment.js +51 -0
  70. package/build/tools/updateVersionMilestone.js +57 -0
  71. package/build/tools/updateWatching.js +18 -0
  72. package/build/tools/updateWiki.js +37 -0
  73. package/build/types/mcp.js +1 -0
  74. package/build/types/result.js +3 -0
  75. package/build/types/tool.js +1 -0
  76. package/build/types/toolsets.js +1 -0
  77. package/build/types/zod/backlogOutputDefinition.js +480 -0
  78. package/build/utils/generateFieldsDescription.js +47 -0
  79. package/build/utils/logger.js +20 -0
  80. package/build/utils/resolveIdOrKey.js +25 -0
  81. package/build/utils/runToolSafely.js +18 -0
  82. package/build/utils/tokenCounter.js +11 -0
  83. package/build/utils/toolRegistrar.js +12 -0
  84. package/build/utils/toolsetUtils.js +48 -0
  85. package/build/utils/wrapServerWithToolRegistry.js +16 -0
  86. package/package.json +1 -1
@@ -0,0 +1,65 @@
1
+ import { z } from 'zod';
2
+ import { buildToolSchema } from '../types/tool.js';
3
+ import { PullRequestSchema } from '../types/zod/backlogOutputDefinition.js';
4
+ import { resolveIdOrKey, resolveIdOrName } from '../utils/resolveIdOrKey.js';
5
+ const addPullRequestSchema = buildToolSchema((t) => ({
6
+ projectId: z
7
+ .number()
8
+ .optional()
9
+ .describe(t('TOOL_ADD_PULL_REQUEST_PROJECT_ID', 'The numeric ID of the project (e.g., 12345)')),
10
+ projectKey: z
11
+ .string()
12
+ .optional()
13
+ .describe(t('TOOL_ADD_PULL_REQUEST_PROJECT_KEY', "The key of the project (e.g., 'PROJECT')")),
14
+ repoId: z
15
+ .number()
16
+ .optional()
17
+ .describe(t('TOOL_ADD_PULL_REQUEST_REPO_ID', 'Repository ID')),
18
+ repoName: z
19
+ .string()
20
+ .optional()
21
+ .describe(t('TOOL_ADD_PULL_REQUEST_REPO_NAME', 'Repository name')),
22
+ summary: z
23
+ .string()
24
+ .describe(t('TOOL_ADD_PULL_REQUEST_SUMMARY', 'Summary of the pull request')),
25
+ description: z
26
+ .string()
27
+ .describe(t('TOOL_ADD_PULL_REQUEST_DESCRIPTION', 'Description of the pull request')),
28
+ base: z
29
+ .string()
30
+ .describe(t('TOOL_ADD_PULL_REQUEST_BASE', 'Base branch name')),
31
+ branch: z
32
+ .string()
33
+ .describe(t('TOOL_ADD_PULL_REQUEST_BRANCH', 'Branch name to merge')),
34
+ issueId: z
35
+ .number()
36
+ .optional()
37
+ .describe(t('TOOL_ADD_PULL_REQUEST_ISSUE_ID', 'Issue ID to link')),
38
+ assigneeId: z
39
+ .number()
40
+ .optional()
41
+ .describe(t('TOOL_ADD_PULL_REQUEST_ASSIGNEE_ID', 'User ID of the assignee')),
42
+ notifiedUserId: z
43
+ .array(z.number())
44
+ .optional()
45
+ .describe(t('TOOL_ADD_PULL_REQUEST_NOTIFIED_USER_ID', 'User IDs to notify')),
46
+ }));
47
+ export const addPullRequestTool = (backlog, { t }) => {
48
+ return {
49
+ name: 'add_pull_request',
50
+ description: t('TOOL_ADD_PULL_REQUEST_DESCRIPTION', 'Creates a new pull request'),
51
+ schema: z.object(addPullRequestSchema(t)),
52
+ outputSchema: PullRequestSchema,
53
+ handler: async ({ projectId, projectKey, repoId, repoName, ...params }) => {
54
+ const result = resolveIdOrKey('project', { id: projectId, key: projectKey }, t);
55
+ if (!result.ok) {
56
+ throw result.error;
57
+ }
58
+ const repoRes = resolveIdOrName('repository', { id: repoId, name: repoName }, t);
59
+ if (!repoRes.ok) {
60
+ throw repoRes.error;
61
+ }
62
+ return backlog.postPullRequest(result.value, String(repoRes.value), params);
63
+ },
64
+ };
65
+ };
@@ -0,0 +1,52 @@
1
+ import { z } from 'zod';
2
+ import { buildToolSchema } from '../types/tool.js';
3
+ import { PullRequestCommentSchema } from '../types/zod/backlogOutputDefinition.js';
4
+ import { resolveIdOrKey, resolveIdOrName } from '../utils/resolveIdOrKey.js';
5
+ const addPullRequestCommentSchema = buildToolSchema((t) => ({
6
+ projectId: z
7
+ .number()
8
+ .optional()
9
+ .describe(t('TOOL_ADD_PULL_REQUEST_COMMENT_PROJECT_ID', 'The numeric ID of the project (e.g., 12345)')),
10
+ projectKey: z
11
+ .string()
12
+ .optional()
13
+ .describe(t('TOOL_ADD_PULL_REQUEST_COMMENT_PROJECT_KEY', "The key of the project (e.g., 'PROJECT')")),
14
+ repoId: z
15
+ .number()
16
+ .optional()
17
+ .describe(t('TOOL_ADD_PULL_REQUEST_REPO_ID', 'Repository ID')),
18
+ repoName: z
19
+ .string()
20
+ .optional()
21
+ .describe(t('TOOL_ADD_PULL_REQUEST_REPO_NAME', 'Repository name')),
22
+ number: z
23
+ .number()
24
+ .describe(t('TOOL_ADD_PULL_REQUEST_COMMENT_NUMBER', 'Pull request number')),
25
+ content: z
26
+ .string()
27
+ .describe(t('TOOL_ADD_PULL_REQUEST_COMMENT_CONTENT', 'Comment content')),
28
+ notifiedUserId: z
29
+ .array(z.number())
30
+ .optional()
31
+ .describe(t('TOOL_ADD_PULL_REQUEST_COMMENT_NOTIFIED_USER_ID', 'User IDs to notify')),
32
+ }));
33
+ export const addPullRequestCommentTool = (backlog, { t }) => {
34
+ return {
35
+ name: 'add_pull_request_comment',
36
+ description: t('TOOL_ADD_PULL_REQUEST_COMMENT_DESCRIPTION', 'Adds a comment to a pull request'),
37
+ schema: z.object(addPullRequestCommentSchema(t)),
38
+ outputSchema: PullRequestCommentSchema,
39
+ importantFields: ['id', 'content', 'createdUser'],
40
+ handler: async ({ projectId, projectKey, repoId, repoName, number, ...params }) => {
41
+ const result = resolveIdOrKey('project', { id: projectId, key: projectKey }, t);
42
+ if (!result.ok) {
43
+ throw result.error;
44
+ }
45
+ const repoRes = resolveIdOrName('repository', { id: repoId, name: repoName }, t);
46
+ if (!repoRes.ok) {
47
+ throw repoRes.error;
48
+ }
49
+ return backlog.postPullRequestComments(result.value, String(repoRes.value), number, params);
50
+ },
51
+ };
52
+ };
@@ -0,0 +1,51 @@
1
+ import { z } from 'zod';
2
+ import { buildToolSchema } from '../types/tool.js';
3
+ import { VersionSchema } from '../types/zod/backlogOutputDefinition.js';
4
+ import { resolveIdOrKey } from '../utils/resolveIdOrKey.js';
5
+ const addVersionMilestoneSchema = buildToolSchema((t) => ({
6
+ projectId: z
7
+ .number()
8
+ .optional()
9
+ .describe(t('TOOL_ADD_VERSION_MILESTONE_PROJECT_ID', 'Project ID')),
10
+ projectKey: z
11
+ .string()
12
+ .optional()
13
+ .describe(t('TOOL_ADD_VERSION_MILESTONE_PROJECT_KEY', 'Project key')),
14
+ name: z
15
+ .string()
16
+ .describe(t('TOOL_ADD_VERSION_MILESTONE_NAME', 'Version name')),
17
+ description: z
18
+ .string()
19
+ .optional()
20
+ .describe(t('TOOL_ADD_VERSION_MILESTONE_DESCRIPTION', 'Version description')),
21
+ startDate: z
22
+ .string()
23
+ .optional()
24
+ .describe(t('TOOL_ADD_VERSION_MILESTONE_START_DATE', 'Start date of the version')),
25
+ releaseDueDate: z
26
+ .string()
27
+ .optional()
28
+ .describe(t('TOOL_ADD_VERSION_MILESTONE_RELEASE_DUE_DATE', 'Release due date of the version')),
29
+ }));
30
+ export const addVersionMilestoneTool = (backlog, { t }) => {
31
+ return {
32
+ name: 'add_version_milestone',
33
+ description: t('TOOL_ADD_VERSION_MILESTONE_DESCRIPTION', 'Creates a new version milestone'),
34
+ schema: z.object(addVersionMilestoneSchema(t)),
35
+ outputSchema: VersionSchema,
36
+ importantFields: [
37
+ 'id',
38
+ 'name',
39
+ 'description',
40
+ 'startDate',
41
+ 'releaseDueDate',
42
+ ],
43
+ handler: async ({ projectId, projectKey, ...params }) => {
44
+ const result = resolveIdOrKey('project', { id: projectId, key: projectKey }, t);
45
+ if (!result.ok) {
46
+ throw result.error;
47
+ }
48
+ return backlog.postVersions(result.value, params);
49
+ },
50
+ };
51
+ };
@@ -0,0 +1,25 @@
1
+ import { z } from 'zod';
2
+ import { buildToolSchema } from '../types/tool.js';
3
+ import { WatchingListItemSchema } from '../types/zod/backlogOutputDefinition.js';
4
+ const addWatchingSchema = buildToolSchema((t) => ({
5
+ issueIdOrKey: z
6
+ .union([z.number(), z.string()])
7
+ .describe(t('TOOL_ADD_WATCHING_ISSUE_ID_OR_KEY', 'Issue ID or issue key (e.g., 1234 or "PROJECT-123")')),
8
+ note: z
9
+ .string()
10
+ .describe(t('TOOL_ADD_WATCHING_NOTE', 'Optional note for the watch'))
11
+ .optional()
12
+ .default(''),
13
+ }));
14
+ export const addWatchingTool = (backlog, { t }) => {
15
+ return {
16
+ name: 'add_watching',
17
+ description: t('TOOL_ADD_WATCHING_DESCRIPTION', 'Adds a new watch to an issue'),
18
+ schema: z.object(addWatchingSchema(t)),
19
+ outputSchema: WatchingListItemSchema,
20
+ handler: async ({ issueIdOrKey, note }) => backlog.postWatchingListItem({
21
+ issueIdOrKey,
22
+ note,
23
+ }),
24
+ };
25
+ };
@@ -0,0 +1,29 @@
1
+ import { z } from 'zod';
2
+ import { buildToolSchema } from '../types/tool.js';
3
+ import { WikiSchema } from '../types/zod/backlogOutputDefinition.js';
4
+ const addWikiSchema = buildToolSchema((t) => ({
5
+ projectId: z.number().describe(t('TOOL_ADD_WIKI_PROJECT_ID', 'Project ID')),
6
+ name: z.string().describe(t('TOOL_ADD_WIKI_NAME', 'Name of the wiki page')),
7
+ content: z
8
+ .string()
9
+ .describe(t('TOOL_ADD_WIKI_CONTENT', 'Content of the wiki page')),
10
+ mailNotify: z
11
+ .boolean()
12
+ .optional()
13
+ .describe(t('TOOL_ADD_WIKI_MAIL_NOTIFY', 'Whether to send notification emails (default: false)')),
14
+ }));
15
+ export const addWikiTool = (backlog, { t }) => {
16
+ return {
17
+ name: 'add_wiki',
18
+ description: t('TOOL_ADD_WIKI_DESCRIPTION', 'Creates a new wiki page'),
19
+ schema: z.object(addWikiSchema(t)),
20
+ outputSchema: WikiSchema,
21
+ importantFields: ['id', 'name', 'content', 'createdUser'],
22
+ handler: async ({ projectId, name, content, mailNotify }) => backlog.postWiki({
23
+ projectId,
24
+ name,
25
+ content,
26
+ mailNotify,
27
+ }),
28
+ };
29
+ };
@@ -0,0 +1,105 @@
1
+ import { z } from 'zod';
2
+ import { buildToolSchema } from '../types/tool.js';
3
+ import { IssueCountSchema } from '../types/zod/backlogOutputDefinition.js';
4
+ import { customFieldFiltersToPayload } from '../backlog/customFields.js';
5
+ import { buildCustomFieldFilterSchema } from './shared/customFieldFiltersSchema.js';
6
+ const countIssuesSchema = buildToolSchema((t) => ({
7
+ projectId: z
8
+ .array(z.number())
9
+ .optional()
10
+ .describe(t('TOOL_COUNT_ISSUES_PROJECT_ID', 'Project IDs')),
11
+ issueTypeId: z
12
+ .array(z.number())
13
+ .optional()
14
+ .describe(t('TOOL_COUNT_ISSUES_ISSUE_TYPE_ID', 'Issue type IDs')),
15
+ categoryId: z
16
+ .array(z.number())
17
+ .optional()
18
+ .describe(t('TOOL_COUNT_ISSUES_CATEGORY_ID', 'Category IDs')),
19
+ versionId: z
20
+ .array(z.number())
21
+ .optional()
22
+ .describe(t('TOOL_COUNT_ISSUES_VERSION_ID', 'Version IDs')),
23
+ milestoneId: z
24
+ .array(z.number())
25
+ .optional()
26
+ .describe(t('TOOL_COUNT_ISSUES_MILESTONE_ID', 'Milestone IDs')),
27
+ statusId: z
28
+ .array(z.number())
29
+ .optional()
30
+ .describe(t('TOOL_COUNT_ISSUES_STATUS_ID', 'Status IDs')),
31
+ priorityId: z
32
+ .array(z.number())
33
+ .optional()
34
+ .describe(t('TOOL_COUNT_ISSUES_PRIORITY_ID', 'Priority IDs')),
35
+ assigneeId: z
36
+ .array(z.number())
37
+ .optional()
38
+ .describe(t('TOOL_COUNT_ISSUES_ASSIGNEE_ID', 'Assignee user IDs')),
39
+ createdUserId: z
40
+ .array(z.number())
41
+ .optional()
42
+ .describe(t('TOOL_COUNT_ISSUES_CREATED_USER_ID', 'Created user IDs')),
43
+ resolutionId: z
44
+ .array(z.number())
45
+ .optional()
46
+ .describe(t('TOOL_COUNT_ISSUES_RESOLUTION_ID', 'Resolution IDs')),
47
+ parentIssueId: z
48
+ .array(z.number())
49
+ .optional()
50
+ .describe(t('TOOL_COUNT_ISSUES_PARENT_ISSUE_ID', 'Parent issue IDs')),
51
+ keyword: z
52
+ .string()
53
+ .optional()
54
+ .describe(t('TOOL_COUNT_ISSUES_KEYWORD', 'Keyword to search for in issues')),
55
+ startDateSince: z
56
+ .string()
57
+ .optional()
58
+ .describe(t('TOOL_COUNT_ISSUES_START_DATE_SINCE', 'Start date since (yyyy-MM-dd)')),
59
+ startDateUntil: z
60
+ .string()
61
+ .optional()
62
+ .describe(t('TOOL_COUNT_ISSUES_START_DATE_UNTIL', 'Start date until (yyyy-MM-dd)')),
63
+ dueDateSince: z
64
+ .string()
65
+ .optional()
66
+ .describe(t('TOOL_COUNT_ISSUES_DUE_DATE_SINCE', 'Due date since (yyyy-MM-dd)')),
67
+ dueDateUntil: z
68
+ .string()
69
+ .optional()
70
+ .describe(t('TOOL_COUNT_ISSUES_DUE_DATE_UNTIL', 'Due date until (yyyy-MM-dd)')),
71
+ createdSince: z
72
+ .string()
73
+ .optional()
74
+ .describe(t('TOOL_COUNT_ISSUES_CREATED_SINCE', 'Created since (yyyy-MM-dd)')),
75
+ createdUntil: z
76
+ .string()
77
+ .optional()
78
+ .describe(t('TOOL_COUNT_ISSUES_CREATED_UNTIL', 'Created until (yyyy-MM-dd)')),
79
+ updatedSince: z
80
+ .string()
81
+ .optional()
82
+ .describe(t('TOOL_COUNT_ISSUES_UPDATED_SINCE', 'Updated since (yyyy-MM-dd)')),
83
+ updatedUntil: z
84
+ .string()
85
+ .optional()
86
+ .describe(t('TOOL_COUNT_ISSUES_UPDATED_UNTIL', 'Updated until (yyyy-MM-dd)')),
87
+ customFields: z
88
+ .array(buildCustomFieldFilterSchema(t))
89
+ .optional()
90
+ .describe(t('TOOL_COUNT_ISSUES_CUSTOM_FIELDS', 'Custom field filters (text, numeric, date, or list)')),
91
+ }));
92
+ export const countIssuesTool = (backlog, { t }) => {
93
+ return {
94
+ name: 'count_issues',
95
+ description: t('TOOL_COUNT_ISSUES_DESCRIPTION', 'Returns count of issues'),
96
+ schema: z.object(countIssuesSchema(t)),
97
+ outputSchema: IssueCountSchema,
98
+ handler: async ({ customFields, ...rest }) => {
99
+ return backlog.getIssuesCount({
100
+ ...rest,
101
+ ...customFieldFiltersToPayload(customFields),
102
+ });
103
+ },
104
+ };
105
+ };
@@ -0,0 +1,19 @@
1
+ import { z } from 'zod';
2
+ import { DocumentItemSchema } from '../types/zod/backlogOutputDefinition.js';
3
+ import { buildToolSchema } from '../types/tool.js';
4
+ const deleteDocumentSchema = buildToolSchema((t) => ({
5
+ documentId: z
6
+ .string()
7
+ .describe(t('TOOL_DELETE_DOCUMENT_DOCUMENT_ID', 'Document ID')),
8
+ }));
9
+ export const deleteDocumentTool = (backlog, { t }) => {
10
+ return {
11
+ name: 'delete_document',
12
+ description: t('TOOL_DELETE_DOCUMENT_DESCRIPTION', 'Permanently deletes a document. This is irreversible (hard delete) and the document cannot be recovered. Unlike the Backlog UI trash feature, this operation does not move the document to trash.'),
13
+ schema: z.object(deleteDocumentSchema(t)),
14
+ outputSchema: DocumentItemSchema,
15
+ handler: async ({ documentId }) => {
16
+ return backlog.deleteDocument(documentId);
17
+ },
18
+ };
19
+ };
@@ -0,0 +1,29 @@
1
+ import { z } from 'zod';
2
+ import { buildToolSchema } from '../types/tool.js';
3
+ import { IssueSchema } from '../types/zod/backlogOutputDefinition.js';
4
+ import { resolveIdOrKey } from '../utils/resolveIdOrKey.js';
5
+ const deleteIssueSchema = buildToolSchema((t) => ({
6
+ issueId: z
7
+ .number()
8
+ .optional()
9
+ .describe(t('TOOL_DELETE_ISSUE_ISSUE_ID', 'The numeric ID of the issue (e.g., 12345)')),
10
+ issueKey: z
11
+ .string()
12
+ .optional()
13
+ .describe(t('TOOL_GET_ISSUE_ISSUE_KEY', "The key of the issue (e.g., 'PROJ-123')")),
14
+ }));
15
+ export const deleteIssueTool = (backlog, { t }) => {
16
+ return {
17
+ name: 'delete_issue',
18
+ description: t('TOOL_DELETE_ISSUE_DESCRIPTION', 'Deletes an issue'),
19
+ schema: z.object(deleteIssueSchema(t)),
20
+ outputSchema: IssueSchema,
21
+ handler: async ({ issueId, issueKey }) => {
22
+ const result = resolveIdOrKey('issue', { id: issueId, key: issueKey }, t);
23
+ if (!result.ok) {
24
+ throw result.error;
25
+ }
26
+ return backlog.deleteIssue(result.value);
27
+ },
28
+ };
29
+ };
@@ -0,0 +1,29 @@
1
+ import { z } from 'zod';
2
+ import { buildToolSchema } from '../types/tool.js';
3
+ import { ProjectSchema } from '../types/zod/backlogOutputDefinition.js';
4
+ import { resolveIdOrKey } from '../utils/resolveIdOrKey.js';
5
+ const deleteProjectSchema = buildToolSchema((t) => ({
6
+ projectId: z
7
+ .number()
8
+ .optional()
9
+ .describe(t('TOOL_DELETE_PROJECT_PROJECT_ID', 'The numeric ID of the project (e.g., 12345)')),
10
+ projectKey: z
11
+ .string()
12
+ .optional()
13
+ .describe(t('TOOL_DELETE_PROJECT_PROJECT_KEY', "The key of the project (e.g., 'PROJECT')")),
14
+ }));
15
+ export const deleteProjectTool = (backlog, { t }) => {
16
+ return {
17
+ name: 'delete_project',
18
+ description: t('TOOL_DELETE_PROJECT_DESCRIPTION', 'Deletes a project'),
19
+ schema: z.object(deleteProjectSchema(t)),
20
+ outputSchema: ProjectSchema,
21
+ handler: async ({ projectId, projectKey }) => {
22
+ const result = resolveIdOrKey('project', { id: projectId, key: projectKey }, t);
23
+ if (!result.ok) {
24
+ throw result.error;
25
+ }
26
+ return backlog.deleteProject(result.value);
27
+ },
28
+ };
29
+ };
@@ -0,0 +1,35 @@
1
+ import { z } from 'zod';
2
+ import { buildToolSchema } from '../types/tool.js';
3
+ import { VersionSchema } from '../types/zod/backlogOutputDefinition.js';
4
+ import { resolveIdOrKey } from '../utils/resolveIdOrKey.js';
5
+ const deleteVersionSchema = buildToolSchema((t) => ({
6
+ projectId: z
7
+ .number()
8
+ .optional()
9
+ .describe(t('TOOL_DELETE_VERSION_PROJECT_ID', 'The numeric ID of the project (e.g., 12345)')),
10
+ projectKey: z
11
+ .string()
12
+ .optional()
13
+ .describe(t('TOOL_DELETE_VERSION_PROJECT_KEY', "The key of the project (e.g., 'PROJECT')")),
14
+ id: z
15
+ .number()
16
+ .describe(t('TOOL_DELETE_VERSION_ID', 'The numeric ID of the version to delete (e.g., 67890)')),
17
+ }));
18
+ export const deleteVersionTool = (backlog, { t }) => {
19
+ return {
20
+ name: 'delete_version',
21
+ description: t('TOOL_DELETE_VERSION_DESCRIPTION', 'Deletes a version from a project'),
22
+ schema: z.object(deleteVersionSchema(t)),
23
+ outputSchema: VersionSchema,
24
+ handler: async ({ projectId, projectKey, id }) => {
25
+ const result = resolveIdOrKey('project', { id: projectId, key: projectKey }, t);
26
+ if (!result.ok) {
27
+ throw result.error;
28
+ }
29
+ if (!id) {
30
+ throw new Error(t('TOOL_DELETE_VERSION_MISSING_ID', 'Version ID is required'));
31
+ }
32
+ return backlog.deleteVersions(result.value, id);
33
+ },
34
+ };
35
+ };
@@ -0,0 +1,17 @@
1
+ import { z } from 'zod';
2
+ import { buildToolSchema } from '../types/tool.js';
3
+ import { WatchingListItemSchema } from '../types/zod/backlogOutputDefinition.js';
4
+ const deleteWatchingSchema = buildToolSchema((t) => ({
5
+ watchId: z
6
+ .number()
7
+ .describe(t('TOOL_DELETE_WATCHING_WATCH_ID', 'Watch ID to delete')),
8
+ }));
9
+ export const deleteWatchingTool = (backlog, { t }) => {
10
+ return {
11
+ name: 'delete_watching',
12
+ description: t('TOOL_DELETE_WATCHING_DESCRIPTION', 'Deletes a watch from an issue'),
13
+ schema: z.object(deleteWatchingSchema(t)),
14
+ outputSchema: WatchingListItemSchema,
15
+ handler: async ({ watchId }) => backlog.deletehWatchingListItem(watchId),
16
+ };
17
+ };
@@ -0,0 +1,103 @@
1
+ import { z } from 'zod';
2
+ import { buildToolSchema, } from '../../types/tool.js';
3
+ export const dynamicTools = function (toolRegistrar, helper, toolsetGroup) {
4
+ return {
5
+ toolsets: [
6
+ {
7
+ name: 'dynamic_tools',
8
+ description: 'Tools for managing Backlog space settings and general information.',
9
+ enabled: true,
10
+ tools: [
11
+ enableToolsetTool(toolRegistrar, helper),
12
+ listAvailableToolsets(helper, toolsetGroup),
13
+ getToolsetTools(helper, toolsetGroup),
14
+ ],
15
+ },
16
+ ],
17
+ };
18
+ };
19
+ const enableToolsetSchema = buildToolSchema((t) => ({
20
+ toolset: z
21
+ .string()
22
+ .describe(t('TOOL_ENABLE_TOOLSET_TOOLSET', 'Enable a toolset')),
23
+ }));
24
+ export const enableToolsetTool = (toolRegistrar, { t }) => {
25
+ return {
26
+ name: 'enable_toolset',
27
+ description: t('TOOL_ENABLE_TOOLSET_DESCRIPTION', 'Enable one of the sets of tools the GitHub MCP server provides, use get_toolset_tools and list_available_toolsets first to see what this will enable'),
28
+ schema: z.object(enableToolsetSchema(t)),
29
+ handler: async ({ toolset }) => {
30
+ const msg = await toolRegistrar.enableToolsetAndRefresh(toolset);
31
+ return {
32
+ content: [
33
+ {
34
+ type: 'text',
35
+ text: msg,
36
+ },
37
+ ],
38
+ };
39
+ },
40
+ };
41
+ };
42
+ export const listAvailableToolsets = ({ t }, toolsetGroup) => {
43
+ return {
44
+ name: 'list_available_toolsets',
45
+ description: t('TOOL_LIST_AVAILABLE_TOOLSETS_DESCRIPTION', 'List all available toolsets.'),
46
+ schema: z.object({}),
47
+ handler: async () => {
48
+ const result = toolsetGroup.toolsets.map((ts) => ({
49
+ name: ts.name,
50
+ description: ts.description,
51
+ currentlyEnabled: ts.enabled,
52
+ canEnable: true,
53
+ }));
54
+ return {
55
+ content: [
56
+ {
57
+ type: 'text',
58
+ text: JSON.stringify(result, null, 2),
59
+ },
60
+ ],
61
+ };
62
+ },
63
+ };
64
+ };
65
+ const getToolsetToolsSchema = buildToolSchema((t) => ({
66
+ toolset: z
67
+ .string()
68
+ .describe(t('TOOL_GET_TOOLSET_TOOLS_TOOLSET', 'Toolset name to inspect')),
69
+ }));
70
+ export const getToolsetTools = ({ t }, toolsetGroup) => {
71
+ return {
72
+ name: 'get_toolset_tools',
73
+ description: t('TOOL_GET_TOOLSET_TOOLS_DESCRIPTION', 'List all tools in a specific toolset.'),
74
+ schema: z.object(getToolsetToolsSchema(t)),
75
+ handler: async ({ toolset }) => {
76
+ const found = toolsetGroup.toolsets.find((ts) => ts.name === toolset);
77
+ if (!found) {
78
+ return {
79
+ content: [
80
+ {
81
+ type: 'text',
82
+ text: `Toolset '${toolset}' not found.`,
83
+ },
84
+ ],
85
+ };
86
+ }
87
+ const tools = found.tools.map((tool) => ({
88
+ name: tool.name,
89
+ description: tool.description,
90
+ toolset: found.name,
91
+ canEnable: true,
92
+ }));
93
+ return {
94
+ content: [
95
+ {
96
+ type: 'text',
97
+ text: JSON.stringify(tools, null, 2),
98
+ },
99
+ ],
100
+ };
101
+ },
102
+ };
103
+ };
@@ -0,0 +1,30 @@
1
+ import { z } from 'zod';
2
+ import { buildToolSchema } from '../types/tool.js';
3
+ import { CategorySchema } from '../types/zod/backlogOutputDefinition.js';
4
+ import { resolveIdOrKey } from '../utils/resolveIdOrKey.js';
5
+ const getCategoriesSchema = buildToolSchema((t) => ({
6
+ projectId: z
7
+ .number()
8
+ .optional()
9
+ .describe(t('TOOL_GET_CATEGORIES_PROJECT_ID', 'The numeric ID of the project (e.g., 12345)')),
10
+ projectKey: z
11
+ .string()
12
+ .optional()
13
+ .describe(t('TOOL_GET_CATEGORIES_PROJECT_ID', "The key of the project (e.g., 'PROJECT')")),
14
+ }));
15
+ export const getCategoriesTool = (backlog, { t }) => {
16
+ return {
17
+ name: 'get_categories',
18
+ description: t('TOOL_GET_CATEGORIES_DESCRIPTION', 'Returns list of categories for a project'),
19
+ schema: z.object(getCategoriesSchema(t)),
20
+ importantFields: ['id', 'projectId', 'name'],
21
+ outputSchema: CategorySchema,
22
+ handler: async ({ projectId, projectKey }) => {
23
+ const result = resolveIdOrKey('project', { id: projectId, key: projectKey }, t);
24
+ if (!result.ok) {
25
+ throw result.error;
26
+ }
27
+ return backlog.getCategories(result.value);
28
+ },
29
+ };
30
+ };
@@ -0,0 +1,37 @@
1
+ import { z } from 'zod';
2
+ import { buildToolSchema } from '../types/tool.js';
3
+ import { CustomFieldSchema } from '../types/zod/backlogOutputDefinition.js';
4
+ import { resolveIdOrKey } from '../utils/resolveIdOrKey.js';
5
+ const getCustomFieldsInputSchema = buildToolSchema((t) => ({
6
+ projectId: z
7
+ .number()
8
+ .optional()
9
+ .describe(t('TOOL_GET_CUSTOM_FIELDS_PROJECT_ID', 'The numeric ID of the project (e.g., 12345)')),
10
+ projectKey: z
11
+ .string()
12
+ .optional()
13
+ .describe(t('TOOL_GET_CUSTOM_FIELDS_PROJECT_KEY', "The key of the project (e.g., 'PROJECT')")),
14
+ }));
15
+ export const getCustomFieldsTool = (backlog, { t }) => {
16
+ const inputSchemaObject = z.object(getCustomFieldsInputSchema(t)); // Create the ZodObject for input
17
+ return {
18
+ name: 'get_custom_fields',
19
+ description: t('TOOL_GET_CUSTOM_FIELDS_DESCRIPTION', 'Returns list of custom fields for a project'),
20
+ schema: inputSchemaObject,
21
+ outputSchema: CustomFieldSchema,
22
+ importantFields: [
23
+ 'id',
24
+ 'name',
25
+ 'typeId',
26
+ 'required',
27
+ 'applicableIssueTypes',
28
+ ],
29
+ handler: async ({ projectId, projectKey }) => {
30
+ const result = resolveIdOrKey('project', { id: projectId, key: projectKey }, t);
31
+ if (!result.ok) {
32
+ throw result.error;
33
+ }
34
+ return backlog.getCustomFields(result.value);
35
+ },
36
+ };
37
+ };
@@ -0,0 +1,20 @@
1
+ import { z } from 'zod';
2
+ import { DocumentItemSchema } from '../types/zod/backlogOutputDefinition.js';
3
+ import { buildToolSchema } from '../types/tool.js';
4
+ const getDocumentSchema = buildToolSchema((t) => ({
5
+ documentId: z
6
+ .string()
7
+ .describe(t('TOOL_GET_DOCUMENT_DOCUMENT_ID', 'Document ID')),
8
+ }));
9
+ export const getDocumentTool = (backlog, { t }) => {
10
+ return {
11
+ name: 'get_document',
12
+ description: t('TOOL_GET_DOCUMENT_DESCRIPTION', 'Gets information about a document.'),
13
+ schema: z.object(getDocumentSchema(t)),
14
+ outputSchema: DocumentItemSchema,
15
+ importantFields: ['id', 'title', 'createdUser'],
16
+ handler: async ({ documentId }) => {
17
+ return backlog.getDocument(documentId);
18
+ },
19
+ };
20
+ };