backlog-mcp-server 0.13.4 → 0.14.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.
package/README.md CHANGED
@@ -1,5 +1,6 @@
1
1
  # Backlog MCP Server
2
2
 
3
+ [![MCP Toplist](https://mcptoplist.com/badge/glama%2Fnulab%2Fbacklog-mcp-server.svg)](https://mcptoplist.com/server/glama%2Fnulab%2Fbacklog-mcp-server)
3
4
  ![MIT License](https://img.shields.io/badge/license-MIT-green.svg)
4
5
  ![Build](https://github.com/nulab/backlog-mcp-server/actions/workflows/ci.yml/badge.svg)
5
6
  ![Last Commit](https://img.shields.io/github/last-commit/nulab/backlog-mcp-server.svg)
@@ -306,6 +307,9 @@ Tools for managing issues, their comments, and related items like priorities, ca
306
307
  - `get_issue_comments`: Returns list of comments for an issue.
307
308
  - `add_issue_comment`: Adds a comment to an issue.
308
309
  - `update_issue_comment`: Updates a comment on an issue.
310
+ - `get_related_issues`: Returns list of issues related to a specific issue.
311
+ - `add_related_issue`: Relates an issue to another issue.
312
+ - `remove_related_issue`: Removes the relation between an issue and a related issue.
309
313
  - `get_priorities`: Returns list of priorities.
310
314
  - `get_categories`: Returns list of categories for a project.
311
315
  - `get_custom_fields`: Returns list of custom fields for a project.
@@ -0,0 +1,32 @@
1
+ import { z } from 'zod';
2
+ import { buildToolSchema } from '../types/tool.js';
3
+ import { RelatedIssueSchema } from '../types/zod/backlogOutputDefinition.js';
4
+ import { resolveIdOrKey } from '../utils/resolveIdOrKey.js';
5
+ const addRelatedIssueSchema = buildToolSchema((t) => ({
6
+ issueId: z
7
+ .number()
8
+ .optional()
9
+ .describe(t('TOOL_ADD_RELATED_ISSUE_ISSUE_ID', 'The numeric ID of the issue (e.g., 12345)')),
10
+ issueKey: z
11
+ .string()
12
+ .optional()
13
+ .describe(t('TOOL_ADD_RELATED_ISSUE_ISSUE_KEY', "The key of the issue (e.g., 'PROJ-123')")),
14
+ targetIssueId: z
15
+ .number()
16
+ .describe(t('TOOL_ADD_RELATED_ISSUE_TARGET_ISSUE_ID', 'The numeric ID of the issue to relate to (e.g., 12346)')),
17
+ }));
18
+ export const addRelatedIssueTool = (backlog, { t }) => {
19
+ return {
20
+ name: 'add_related_issue',
21
+ description: t('TOOL_ADD_RELATED_ISSUE_DESCRIPTION', 'Relates an issue to another issue'),
22
+ schema: z.object(addRelatedIssueSchema(t)),
23
+ outputSchema: RelatedIssueSchema,
24
+ handler: async ({ issueId, issueKey, targetIssueId }) => {
25
+ const result = resolveIdOrKey('issue', { id: issueId, key: issueKey }, t);
26
+ if (!result.ok) {
27
+ throw result.error;
28
+ }
29
+ return backlog.addRelatedIssue(result.value, { targetIssueId });
30
+ },
31
+ };
32
+ };
@@ -0,0 +1,30 @@
1
+ import { z } from 'zod';
2
+ import { buildToolSchema } from '../types/tool.js';
3
+ import { RelatedIssueSchema } from '../types/zod/backlogOutputDefinition.js';
4
+ import { resolveIdOrKey } from '../utils/resolveIdOrKey.js';
5
+ const getRelatedIssuesSchema = buildToolSchema((t) => ({
6
+ issueId: z
7
+ .number()
8
+ .optional()
9
+ .describe(t('TOOL_GET_RELATED_ISSUES_ISSUE_ID', 'The numeric ID of the issue (e.g., 12345)')),
10
+ issueKey: z
11
+ .string()
12
+ .optional()
13
+ .describe(t('TOOL_GET_RELATED_ISSUES_ISSUE_KEY', "The key of the issue (e.g., 'PROJ-123')")),
14
+ }));
15
+ export const getRelatedIssuesTool = (backlog, { t }) => {
16
+ return {
17
+ name: 'get_related_issues',
18
+ description: t('TOOL_GET_RELATED_ISSUES_DESCRIPTION', 'Returns list of issues related to a specific issue'),
19
+ schema: z.object(getRelatedIssuesSchema(t)),
20
+ importantFields: ['issueKey', 'summary', 'status', 'type'],
21
+ outputSchema: RelatedIssueSchema,
22
+ handler: async ({ issueId, issueKey }) => {
23
+ const result = resolveIdOrKey('issue', { id: issueId, key: issueKey }, t);
24
+ if (!result.ok) {
25
+ throw result.error;
26
+ }
27
+ return backlog.getRelatedIssues(result.value);
28
+ },
29
+ };
30
+ };
@@ -0,0 +1,32 @@
1
+ import { z } from 'zod';
2
+ import { buildToolSchema } from '../types/tool.js';
3
+ import { RelatedIssueSchema } from '../types/zod/backlogOutputDefinition.js';
4
+ import { resolveIdOrKey } from '../utils/resolveIdOrKey.js';
5
+ const removeRelatedIssueSchema = buildToolSchema((t) => ({
6
+ issueId: z
7
+ .number()
8
+ .optional()
9
+ .describe(t('TOOL_REMOVE_RELATED_ISSUE_ISSUE_ID', 'The numeric ID of the issue (e.g., 12345)')),
10
+ issueKey: z
11
+ .string()
12
+ .optional()
13
+ .describe(t('TOOL_REMOVE_RELATED_ISSUE_ISSUE_KEY', "The key of the issue (e.g., 'PROJ-123')")),
14
+ relatedIssueId: z
15
+ .number()
16
+ .describe(t('TOOL_REMOVE_RELATED_ISSUE_RELATED_ISSUE_ID', 'The numeric ID of the related issue to unlink (e.g., 12346)')),
17
+ }));
18
+ export const removeRelatedIssueTool = (backlog, { t }) => {
19
+ return {
20
+ name: 'remove_related_issue',
21
+ description: t('TOOL_REMOVE_RELATED_ISSUE_DESCRIPTION', 'Removes the relation between an issue and a related issue'),
22
+ schema: z.object(removeRelatedIssueSchema(t)),
23
+ outputSchema: RelatedIssueSchema,
24
+ handler: async ({ issueId, issueKey, relatedIssueId }) => {
25
+ const result = resolveIdOrKey('issue', { id: issueId, key: issueKey }, t);
26
+ if (!result.ok) {
27
+ throw result.error;
28
+ }
29
+ return backlog.removeRelatedIssue(result.value, relatedIssueId);
30
+ },
31
+ };
32
+ };
@@ -15,6 +15,9 @@ import { getGitRepositoryTool } from './getGitRepository.js';
15
15
  import { getIssueTool } from './getIssue.js';
16
16
  import { getIssueCommentsTool } from './getIssueComments.js';
17
17
  import { getIssuesTool } from './getIssues.js';
18
+ import { getRelatedIssuesTool } from './getRelatedIssues.js';
19
+ import { addRelatedIssueTool } from './addRelatedIssue.js';
20
+ import { removeRelatedIssueTool } from './removeRelatedIssue.js';
18
21
  import { getIssueTypesTool } from './getIssueTypes.js';
19
22
  import { getMyselfTool } from './getMyself.js';
20
23
  import { getNotificationsTool } from './getNotifications.js';
@@ -100,6 +103,9 @@ export const allTools = (backlog, helper) => {
100
103
  getIssueCommentsTool(backlog, helper),
101
104
  addIssueCommentTool(backlog, helper),
102
105
  updateIssueCommentTool(backlog, helper),
106
+ getRelatedIssuesTool(backlog, helper),
107
+ addRelatedIssueTool(backlog, helper),
108
+ removeRelatedIssueTool(backlog, helper),
103
109
  getPrioritiesTool(backlog, helper),
104
110
  getCategoriesTool(backlog, helper),
105
111
  getCustomFieldsTool(backlog, helper),
@@ -76,6 +76,10 @@ const updateIssueSchema = buildToolSchema((t) => ({
76
76
  .array(z.number())
77
77
  .optional()
78
78
  .describe(t('TOOL_UPDATE_ISSUE_ATTACHMENT_ID', 'Attachment IDs')),
79
+ parentIssueId: z
80
+ .number()
81
+ .optional()
82
+ .describe(t('TOOL_UPDATE_ISSUE_PARENT_ISSUE_ID', 'Parent issue ID')),
79
83
  comment: z
80
84
  .string()
81
85
  .optional()
@@ -211,6 +211,10 @@ export const IssueSchema = z.object({
211
211
  sharedFiles: z.array(SharedFileSchema),
212
212
  stars: z.array(StarSchema),
213
213
  });
214
+ // An issue plus the relation type that links it to the issue it was fetched from.
215
+ export const RelatedIssueSchema = IssueSchema.extend({
216
+ type: z.string(),
217
+ });
214
218
  export const ProjectSchema = z.object({
215
219
  id: z.number(),
216
220
  projectKey: z.string(),
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "backlog-mcp-server",
3
- "version": "0.13.4",
3
+ "version": "0.14.0",
4
4
  "type": "module",
5
5
  "bin": {
6
6
  "backlog-mcp-server": "./build/index.js"
@@ -26,7 +26,7 @@
26
26
  "dependencies": {
27
27
  "@hono/node-server": "^2.0.10",
28
28
  "@modelcontextprotocol/sdk": "^1.29.0",
29
- "backlog-js": "^0.18.1",
29
+ "backlog-js": "^0.19.0",
30
30
  "cosmiconfig": "^9.0.1",
31
31
  "env-var": "^7.5.0",
32
32
  "graphql": "^16.14.1",