backlog-mcp-server 0.13.1 → 0.13.3
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.ja.md +0 -12
- package/README.md +1 -12
- package/build/index.js +13 -0
- package/build/tools/tools.js +2 -0
- package/build/tools/updateIssueComment.js +36 -0
- package/build/types/zod/backlogOutputDefinition.js +13 -1
- package/build/utils/backlogClientRegistry.js +11 -2
- package/package.json +4 -4
package/README.ja.md
CHANGED
|
@@ -363,18 +363,6 @@ docker run -i --rm ghcr.io/nulab/backlog-mcp-server node build/index.js --export
|
|
|
363
363
|
npx github:nulab/backlog-mcp-server --export-translations
|
|
364
364
|
```
|
|
365
365
|
|
|
366
|
-
### 日本語翻訳テンプレートの使用
|
|
367
|
-
|
|
368
|
-
サンプルの日本語設定ファイルは次の場所に提供されています:
|
|
369
|
-
|
|
370
|
-
```bash
|
|
371
|
-
translationConfig/.backlog-mcp-serverrc.json.example
|
|
372
|
-
```
|
|
373
|
-
|
|
374
|
-
これを使用するには、ホームディレクトリに `.backlog-mcp-serverrc.json` としてコピーします:
|
|
375
|
-
|
|
376
|
-
その後、必要に応じてファイルを編集して説明をカスタマイズできます。
|
|
377
|
-
|
|
378
366
|
### 環境変数の使用
|
|
379
367
|
|
|
380
368
|
または、環境変数を介してツールの説明をオーバーライドすることもできます。
|
package/README.md
CHANGED
|
@@ -305,6 +305,7 @@ Tools for managing issues, their comments, and related items like priorities, ca
|
|
|
305
305
|
- `delete_issue`: Deletes an issue.
|
|
306
306
|
- `get_issue_comments`: Returns list of comments for an issue.
|
|
307
307
|
- `add_issue_comment`: Adds a comment to an issue.
|
|
308
|
+
- `update_issue_comment`: Updates a comment on an issue.
|
|
308
309
|
- `get_priorities`: Returns list of priorities.
|
|
309
310
|
- `get_categories`: Returns list of categories for a project.
|
|
310
311
|
- `get_custom_fields`: Returns list of custom fields for a project.
|
|
@@ -472,18 +473,6 @@ or
|
|
|
472
473
|
npx github:nulab/backlog-mcp-server --export-translations
|
|
473
474
|
```
|
|
474
475
|
|
|
475
|
-
### Using a Japanese Translation Template
|
|
476
|
-
|
|
477
|
-
A sample Japanese configuration file is provided at:
|
|
478
|
-
|
|
479
|
-
```bash
|
|
480
|
-
translationConfig/.backlog-mcp-serverrc.json.example
|
|
481
|
-
```
|
|
482
|
-
|
|
483
|
-
To use it, copy it to your home directory as .backlog-mcp-serverrc.json:
|
|
484
|
-
|
|
485
|
-
You can then edit the file to customize the descriptions as needed.
|
|
486
|
-
|
|
487
476
|
### Using Environment Variables
|
|
488
477
|
|
|
489
478
|
Alternatively, you can override tool descriptions via environment variables.
|
package/build/index.js
CHANGED
|
@@ -145,6 +145,19 @@ const createServer = () => createBacklogMcpServer({
|
|
|
145
145
|
dynamicToolsets: argv.dynamicToolsets,
|
|
146
146
|
});
|
|
147
147
|
if (argv.exportTranslations) {
|
|
148
|
+
// Translation keys are only recorded once a tool asks for them, so build a
|
|
149
|
+
// server with every toolset enabled before dumping. Without this the dump is
|
|
150
|
+
// empty, because no tool has been created yet at this point.
|
|
151
|
+
createBacklogMcpServer({
|
|
152
|
+
version,
|
|
153
|
+
useFields,
|
|
154
|
+
backlog,
|
|
155
|
+
clientRegistry,
|
|
156
|
+
transHelper,
|
|
157
|
+
enabledToolsets: ['all'],
|
|
158
|
+
mcpOption,
|
|
159
|
+
dynamicToolsets: true,
|
|
160
|
+
});
|
|
148
161
|
const data = transHelper.dump();
|
|
149
162
|
// eslint-disable-next-line no-console
|
|
150
163
|
console.log(JSON.stringify(data, null, 2));
|
package/build/tools/tools.js
CHANGED
|
@@ -45,6 +45,7 @@ import { getWikisCountTool } from './getWikisCount.js';
|
|
|
45
45
|
import { markNotificationAsReadTool } from './markNotificationAsRead.js';
|
|
46
46
|
import { resetUnreadNotificationCountTool } from './resetUnreadNotificationCount.js';
|
|
47
47
|
import { updateIssueTool } from './updateIssue.js';
|
|
48
|
+
import { updateIssueCommentTool } from './updateIssueComment.js';
|
|
48
49
|
import { updateProjectTool } from './updateProject.js';
|
|
49
50
|
import { updatePullRequestTool } from './updatePullRequest.js';
|
|
50
51
|
import { updatePullRequestCommentTool } from './updatePullRequestComment.js';
|
|
@@ -98,6 +99,7 @@ export const allTools = (backlog, helper) => {
|
|
|
98
99
|
deleteIssueTool(backlog, helper),
|
|
99
100
|
getIssueCommentsTool(backlog, helper),
|
|
100
101
|
addIssueCommentTool(backlog, helper),
|
|
102
|
+
updateIssueCommentTool(backlog, helper),
|
|
101
103
|
getPrioritiesTool(backlog, helper),
|
|
102
104
|
getCategoriesTool(backlog, helper),
|
|
103
105
|
getCustomFieldsTool(backlog, helper),
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
import { z } from 'zod';
|
|
2
|
+
import { buildToolSchema } from '../types/tool.js';
|
|
3
|
+
import { IssueCommentSchema } from '../types/zod/backlogOutputDefinition.js';
|
|
4
|
+
import { resolveIdOrKey } from '../utils/resolveIdOrKey.js';
|
|
5
|
+
const updateIssueCommentSchema = buildToolSchema((t) => ({
|
|
6
|
+
issueId: z
|
|
7
|
+
.number()
|
|
8
|
+
.optional()
|
|
9
|
+
.describe(t('TOOL_UPDATE_ISSUE_COMMENT_ISSUE_ID', 'The numeric ID of the issue (e.g., 12345)')),
|
|
10
|
+
issueKey: z
|
|
11
|
+
.string()
|
|
12
|
+
.optional()
|
|
13
|
+
.describe(t('TOOL_UPDATE_ISSUE_COMMENT_ISSUE_KEY', "The key of the issue (e.g., 'PROJ-123')")),
|
|
14
|
+
commentId: z
|
|
15
|
+
.number()
|
|
16
|
+
.describe(t('TOOL_UPDATE_ISSUE_COMMENT_COMMENT_ID', 'Comment ID')),
|
|
17
|
+
content: z
|
|
18
|
+
.string()
|
|
19
|
+
.describe(t('TOOL_UPDATE_ISSUE_COMMENT_CONTENT', 'Comment content')),
|
|
20
|
+
}));
|
|
21
|
+
export const updateIssueCommentTool = (backlog, { t }) => {
|
|
22
|
+
return {
|
|
23
|
+
name: 'update_issue_comment',
|
|
24
|
+
description: t('TOOL_UPDATE_ISSUE_COMMENT_DESCRIPTION', 'Updates a comment on an issue'),
|
|
25
|
+
schema: z.object(updateIssueCommentSchema(t)),
|
|
26
|
+
outputSchema: IssueCommentSchema,
|
|
27
|
+
importantFields: ['id', 'content', 'createdUser', 'updated'],
|
|
28
|
+
handler: async ({ issueId, issueKey, commentId, content }) => {
|
|
29
|
+
const result = resolveIdOrKey('issue', { id: issueId, key: issueKey }, t);
|
|
30
|
+
if (!result.ok) {
|
|
31
|
+
throw result.error;
|
|
32
|
+
}
|
|
33
|
+
return backlog.patchIssueComment(result.value, commentId, { content });
|
|
34
|
+
},
|
|
35
|
+
};
|
|
36
|
+
};
|
|
@@ -158,6 +158,18 @@ export const CustomFieldSchema = z.object({
|
|
|
158
158
|
required: z.boolean(),
|
|
159
159
|
applicableIssueTypes: z.array(z.number()),
|
|
160
160
|
});
|
|
161
|
+
// A custom field *value* attached to an issue (as returned by the Backlog API),
|
|
162
|
+
// as opposed to a custom field *definition* (CustomFieldSchema above). The
|
|
163
|
+
// concrete `value` shape depends on the field type, so it is left unconstrained.
|
|
164
|
+
export const CustomFieldValueSchema = z.object({
|
|
165
|
+
id: z.number(),
|
|
166
|
+
fieldTypeId: CustomFieldTypeSchema,
|
|
167
|
+
name: z.string(),
|
|
168
|
+
value: z.unknown(),
|
|
169
|
+
// Present on "checkbox" / "radio" fields that allow free-text input for an
|
|
170
|
+
// "other" option; holds whatever the user typed there (null when unused).
|
|
171
|
+
otherValue: z.string().nullable().optional(),
|
|
172
|
+
});
|
|
161
173
|
export const SharedFileSchema = z.object({
|
|
162
174
|
id: z.number(),
|
|
163
175
|
projectId: z.number(),
|
|
@@ -194,7 +206,7 @@ export const IssueSchema = z.object({
|
|
|
194
206
|
created: z.string(),
|
|
195
207
|
updatedUser: UserSchema,
|
|
196
208
|
updated: z.string(),
|
|
197
|
-
customFields: z.array(
|
|
209
|
+
customFields: z.array(CustomFieldValueSchema),
|
|
198
210
|
attachments: z.array(IssueFileInfoSchema),
|
|
199
211
|
sharedFiles: z.array(SharedFileSchema),
|
|
200
212
|
stars: z.array(StarSchema),
|
|
@@ -1,6 +1,10 @@
|
|
|
1
1
|
import { Backlog } from 'backlog-js';
|
|
2
2
|
import { getCurrentAccessToken } from '../auth/backlogAuthContext.js';
|
|
3
3
|
import { getCurrentOrganization } from './backlogOrganizationContext.js';
|
|
4
|
+
import packageJson from '../../package.json' with { type: 'json' };
|
|
5
|
+
// Sent as the User-Agent header on Backlog API requests so that traffic
|
|
6
|
+
// originating from this MCP Server can be identified in access logs / observability tooling.
|
|
7
|
+
const USER_AGENT = `backlog-mcp-server/${packageJson.version}`;
|
|
4
8
|
export function createBacklogClientRegistry(input = {}) {
|
|
5
9
|
const env = input.env ?? process.env;
|
|
6
10
|
const multiOrgRegistry = createMultiOrganizationRegistryFromEnv(env);
|
|
@@ -13,7 +17,7 @@ export function createBacklogClientRegistry(input = {}) {
|
|
|
13
17
|
throw new Error('Configure either BACKLOG_ORG_<NAME>_DOMAIN and BACKLOG_ORG_<NAME>_API_KEY with BACKLOG_DEFAULT_ORG, or both BACKLOG_DOMAIN and BACKLOG_API_KEY.');
|
|
14
18
|
}
|
|
15
19
|
const defaultName = 'default';
|
|
16
|
-
const client = new Backlog({ host: domain, apiKey });
|
|
20
|
+
const client = new Backlog({ host: domain, apiKey, userAgent: USER_AGENT });
|
|
17
21
|
const info = {
|
|
18
22
|
name: defaultName,
|
|
19
23
|
domain,
|
|
@@ -87,6 +91,7 @@ function createMultiOrganizationRegistryFromEnv(env) {
|
|
|
87
91
|
clients.set(name, new Backlog({
|
|
88
92
|
host: config.domain,
|
|
89
93
|
apiKey: config.apiKey,
|
|
94
|
+
userAgent: USER_AGENT,
|
|
90
95
|
}));
|
|
91
96
|
return {
|
|
92
97
|
name,
|
|
@@ -131,7 +136,11 @@ export function createOAuthBacklogClientRegistry(domain) {
|
|
|
131
136
|
if (!token) {
|
|
132
137
|
throw new Error('No OAuth access token in current request context');
|
|
133
138
|
}
|
|
134
|
-
return new Backlog({
|
|
139
|
+
return new Backlog({
|
|
140
|
+
host: domain,
|
|
141
|
+
accessToken: token,
|
|
142
|
+
userAgent: USER_AGENT,
|
|
143
|
+
});
|
|
135
144
|
};
|
|
136
145
|
return {
|
|
137
146
|
resolveClient: () => resolveOAuthClient(),
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "backlog-mcp-server",
|
|
3
|
-
"version": "0.13.
|
|
3
|
+
"version": "0.13.3",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"bin": {
|
|
6
6
|
"backlog-mcp-server": "./build/index.js"
|
|
@@ -24,13 +24,13 @@
|
|
|
24
24
|
"build"
|
|
25
25
|
],
|
|
26
26
|
"dependencies": {
|
|
27
|
-
"@hono/node-server": "^2.0.
|
|
27
|
+
"@hono/node-server": "^2.0.10",
|
|
28
28
|
"@modelcontextprotocol/sdk": "^1.29.0",
|
|
29
|
-
"backlog-js": "^0.
|
|
29
|
+
"backlog-js": "^0.18.1",
|
|
30
30
|
"cosmiconfig": "^9.0.1",
|
|
31
31
|
"env-var": "^7.5.0",
|
|
32
32
|
"graphql": "^16.14.1",
|
|
33
|
-
"hono": "^4.12.
|
|
33
|
+
"hono": "^4.12.27",
|
|
34
34
|
"pino": "^10.3.1",
|
|
35
35
|
"pino-pretty": "^13.1.3",
|
|
36
36
|
"yargs": "^18.0.0",
|