backlog-mcp-server 0.12.0 → 0.13.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.ja.md CHANGED
@@ -101,8 +101,8 @@ docker pull ghcr.io/nulab/backlog-mcp-server:latest
101
101
  ```bash
102
102
  git clone https://github.com/nulab/backlog-mcp-server.git
103
103
  cd backlog-mcp-server
104
- npm install
105
- npm run build
104
+ pnpm install
105
+ pnpm run build
106
106
  ```
107
107
 
108
108
  2. テンプレートから `.env` を作成し、必須の環境変数を設定します:
@@ -119,7 +119,7 @@ cp .env.example .env
119
119
  3. ローカルで起動します:
120
120
 
121
121
  ```bash
122
- npm run dev
122
+ pnpm run dev
123
123
  ```
124
124
 
125
125
  4. MCPとして使用するJSONを設定します:
@@ -529,7 +529,7 @@ MAX_TOKENS=10000
529
529
  ### テストの実行
530
530
 
531
531
  ```bash
532
- npm test
532
+ pnpm test
533
533
  ```
534
534
 
535
535
  ### 新しいツールの追加
package/README.md CHANGED
@@ -101,8 +101,8 @@ Replace `your-domain.backlog.com` with your Backlog domain and `your-api-key` wi
101
101
  ```bash
102
102
  git clone https://github.com/nulab/backlog-mcp-server.git
103
103
  cd backlog-mcp-server
104
- npm install
105
- npm run build
104
+ pnpm install
105
+ pnpm run build
106
106
  ```
107
107
 
108
108
  2. Create `.env` from template and set required variables:
@@ -119,7 +119,7 @@ Set the following values in `.env`:
119
119
  3. Run locally:
120
120
 
121
121
  ```bash
122
- npm run dev
122
+ pnpm run dev
123
123
  ```
124
124
 
125
125
  4. Set your json to use as MCP
@@ -144,7 +144,7 @@ npm run dev
144
144
  By default the server uses **stdio**. To run the [MCP Streamable HTTP](https://modelcontextprotocol.io/) transport instead (JSON-RPC over HTTP, same tools as stdio), start with `--transport http` or set `MCP_TRANSPORT=http`.
145
145
 
146
146
  ```bash
147
- npm run build
147
+ pnpm run build
148
148
  MCP_TRANSPORT=http MCP_HTTP_PORT=3333 node build/index.js
149
149
  ```
150
150
 
@@ -154,13 +154,13 @@ MCP_TRANSPORT=http MCP_HTTP_PORT=3333 node build/index.js
154
154
 
155
155
  Environment variables (CLI flags override when both are set):
156
156
 
157
- | Variable | Description |
158
- | -------- | ----------- |
159
- | `MCP_TRANSPORT` | `stdio` (default) or `http` |
160
- | `MCP_HTTP_HOST` | Bind address (default `127.0.0.1`) |
161
- | `MCP_HTTP_PORT` | Port (default `3333`) |
162
- | `MCP_HTTP_PATH` | URL path (default `/mcp`) |
163
- | `MCP_HTTP_JSON_RESPONSE` | `true` to prefer JSON responses over SSE when supported |
157
+ | Variable | Description |
158
+ | ------------------------ | ------------------------------------------------------------------------------------------ |
159
+ | `MCP_TRANSPORT` | `stdio` (default) or `http` |
160
+ | `MCP_HTTP_HOST` | Bind address (default `127.0.0.1`) |
161
+ | `MCP_HTTP_PORT` | Port (default `3333`) |
162
+ | `MCP_HTTP_PATH` | URL path (default `/mcp`) |
163
+ | `MCP_HTTP_JSON_RESPONSE` | `true` to prefer JSON responses over SSE when supported |
164
164
  | `MCP_HTTP_ALLOWED_HOSTS` | Comma-separated allowed `Host` values when binding to `0.0.0.0` (DNS rebinding protection) |
165
165
 
166
166
  ### OAuth 2.0 Authentication (Remote MCP)
@@ -178,11 +178,11 @@ The server implements the [MCP Third-Party Authorization Flow](https://modelcont
178
178
 
179
179
  2. Set the following environment variables (in addition to `BACKLOG_DOMAIN`):
180
180
 
181
- | Variable | Description |
182
- | -------- | ----------- |
183
- | `BACKLOG_OAUTH_CLIENT_ID` | OAuth Client ID from your Backlog application |
184
- | `BACKLOG_OAUTH_CLIENT_SECRET` | OAuth Client Secret from your Backlog application |
185
- | `MCP_SERVER_BASE_URL` | Public URL of your MCP server (e.g., `https://mcp.example.com`) |
181
+ | Variable | Description |
182
+ | ----------------------------- | --------------------------------------------------------------- |
183
+ | `BACKLOG_OAUTH_CLIENT_ID` | OAuth Client ID from your Backlog application |
184
+ | `BACKLOG_OAUTH_CLIENT_SECRET` | OAuth Client Secret from your Backlog application |
185
+ | `MCP_SERVER_BASE_URL` | Public URL of your MCP server (e.g., `https://mcp.example.com`) |
186
186
 
187
187
  > **Note:** `BACKLOG_API_KEY` is **not required** when OAuth is enabled — each user authenticates with their own Backlog account.
188
188
 
@@ -198,18 +198,19 @@ node build/index.js --transport http --http-host 0.0.0.0 --http-port 3333
198
198
 
199
199
  The server automatically exposes the following OAuth endpoints when OAuth is enabled:
200
200
 
201
- | Endpoint | Description |
202
- | -------- | ----------- |
203
- | `GET /.well-known/oauth-authorization-server` | OAuth Authorization Server Metadata ([RFC 8414](https://datatracker.ietf.org/doc/html/rfc8414)) |
204
- | `GET /.well-known/oauth-protected-resource/mcp` | OAuth Protected Resource Metadata ([RFC 9728](https://datatracker.ietf.org/doc/html/rfc9728)) |
205
- | `POST /register` | Dynamic Client Registration ([RFC 7591](https://datatracker.ietf.org/doc/html/rfc7591)) |
206
- | `GET /authorize` | Authorization endpoint (redirects to Backlog OAuth) |
207
- | `GET /callback` | Backlog OAuth callback |
208
- | `POST /token` | Token endpoint (authorization code & refresh token) |
201
+ | Endpoint | Description |
202
+ | ----------------------------------------------- | ----------------------------------------------------------------------------------------------- |
203
+ | `GET /.well-known/oauth-authorization-server` | OAuth Authorization Server Metadata ([RFC 8414](https://datatracker.ietf.org/doc/html/rfc8414)) |
204
+ | `GET /.well-known/oauth-protected-resource/mcp` | OAuth Protected Resource Metadata ([RFC 9728](https://datatracker.ietf.org/doc/html/rfc9728)) |
205
+ | `POST /register` | Dynamic Client Registration ([RFC 7591](https://datatracker.ietf.org/doc/html/rfc7591)) |
206
+ | `GET /authorize` | Authorization endpoint (redirects to Backlog OAuth) |
207
+ | `GET /callback` | Backlog OAuth callback |
208
+ | `POST /token` | Token endpoint (authorization code & refresh token) |
209
209
 
210
210
  MCP clients that support the MCP authorization specification will use these endpoints automatically.
211
211
 
212
212
  > **Limitations:**
213
+ >
213
214
  > - OAuth mode currently supports a single Backlog organization. It is not compatible with the multi-organization configuration.
214
215
  > - Client registrations and tokens are stored in memory and will be lost on server restart.
215
216
 
@@ -288,6 +289,7 @@ Tools for managing projects, categories, custom fields, and issue types.
288
289
  - `get_project_list`: Returns list of projects.
289
290
  - `add_project`: Creates a new project.
290
291
  - `get_project`: Returns information about a specific project.
292
+ - `get_project_users`: Returns list of users in a specific project.
291
293
  - `update_project`: Updates an existing project.
292
294
  - `delete_project`: Deletes a project.
293
295
 
@@ -633,7 +635,7 @@ This section demonstrates advanced configuration using multiple environment vari
633
635
  ### Running Tests
634
636
 
635
637
  ```bash
636
- npm test
638
+ pnpm test
637
639
  ```
638
640
 
639
641
  ### Adding New Tools
package/build/index.js CHANGED
@@ -2,7 +2,6 @@
2
2
  // Copyright (c) 2025 Nulab inc.
3
3
  // Licensed under the MIT License.
4
4
  import { StdioServerTransport } from '@modelcontextprotocol/sdk/server/stdio.js';
5
- import dotenv from 'dotenv';
6
5
  import { default as env } from 'env-var';
7
6
  import yargs from 'yargs';
8
7
  import { hideBin } from 'yargs/helpers';
@@ -20,11 +19,11 @@ const { version } = packageJson;
20
19
  // as an error event on stdout/stderr streams — both must be handled.
21
20
  process.on('SIGPIPE', () => { });
22
21
  process.stdout.on('error', (err) => {
23
- if (err.code !== 'EPIPE')
22
+ if (!('code' in err) || err.code !== 'EPIPE')
24
23
  throw err;
25
24
  });
26
25
  process.stderr.on('error', (err) => {
27
- if (err.code !== 'EPIPE')
26
+ if (!('code' in err) || err.code !== 'EPIPE')
28
27
  throw err;
29
28
  });
30
29
  process.on('uncaughtException', (error) => {
@@ -35,7 +34,12 @@ process.on('unhandledRejection', (reason) => {
35
34
  logger.error({ err: reason }, 'Unhandled rejection');
36
35
  process.exit(1);
37
36
  });
38
- dotenv.config();
37
+ try {
38
+ process.loadEnvFile();
39
+ }
40
+ catch {
41
+ // .env file is optional
42
+ }
39
43
  const oauthConfig = getBacklogOAuthConfig();
40
44
  const argv = yargs(hideBin(process.argv))
41
45
  .option('transport', {
@@ -0,0 +1,30 @@
1
+ import { z } from 'zod';
2
+ import { buildToolSchema } from '../types/tool.js';
3
+ import { UserSchema } from '../types/zod/backlogOutputDefinition.js';
4
+ import { resolveIdOrKey } from '../utils/resolveIdOrKey.js';
5
+ const getProjectUsersSchema = buildToolSchema((t) => ({
6
+ projectId: z
7
+ .number()
8
+ .optional()
9
+ .describe(t('TOOL_GET_PROJECT_USERS_PROJECT_ID', 'The numeric ID of the project (e.g., 12345)')),
10
+ projectKey: z
11
+ .string()
12
+ .optional()
13
+ .describe(t('TOOL_GET_PROJECT_USERS_PROJECT_KEY', "The key of the project (e.g., 'PROJECT')")),
14
+ }));
15
+ export const getProjectUsersTool = (backlog, { t }) => {
16
+ return {
17
+ name: 'get_project_users',
18
+ description: t('TOOL_GET_PROJECT_USERS_DESCRIPTION', 'Returns list of users in a specific project'),
19
+ schema: z.object(getProjectUsersSchema(t)),
20
+ outputSchema: UserSchema,
21
+ importantFields: ['userId', 'name', 'roleType', 'lang'],
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.getProjectUsers(result.value);
28
+ },
29
+ };
30
+ };
@@ -22,6 +22,7 @@ import { getNotificationsCountTool } from './getNotificationsCount.js';
22
22
  import { getPrioritiesTool } from './getPriorities.js';
23
23
  import { getProjectTool } from './getProject.js';
24
24
  import { getProjectListTool } from './getProjectList.js';
25
+ import { getProjectUsersTool } from './getProjectUsers.js';
25
26
  import { getPullRequestTool } from './getPullRequest.js';
26
27
  import { getPullRequestCommentsTool } from './getPullRequestComments.js';
27
28
  import { getPullRequestsTool } from './getPullRequests.js';
@@ -79,6 +80,7 @@ export const allTools = (backlog, helper) => {
79
80
  getProjectListTool(backlog, helper),
80
81
  addProjectTool(backlog, helper),
81
82
  getProjectTool(backlog, helper),
83
+ getProjectUsersTool(backlog, helper),
82
84
  updateProjectTool(backlog, helper),
83
85
  deleteProjectTool(backlog, helper),
84
86
  ],
package/package.json CHANGED
@@ -1,16 +1,61 @@
1
1
  {
2
2
  "name": "backlog-mcp-server",
3
- "version": "0.12.0",
3
+ "version": "0.13.0",
4
4
  "type": "module",
5
5
  "bin": {
6
6
  "backlog-mcp-server": "./build/index.js"
7
7
  },
8
+ "engines": {
9
+ "node": ">=22"
10
+ },
11
+ "devEngines": {
12
+ "runtime": {
13
+ "name": "node",
14
+ "version": ">=22",
15
+ "onFail": "warn"
16
+ }
17
+ },
8
18
  "license": "MIT",
9
19
  "repository": {
10
20
  "type": "git",
11
21
  "url": "git+https://github.com/nulab/backlog-mcp-server.git"
12
22
  },
23
+ "files": [
24
+ "build"
25
+ ],
26
+ "dependencies": {
27
+ "@hono/node-server": "^2.0.4",
28
+ "@modelcontextprotocol/sdk": "^1.29.0",
29
+ "backlog-js": "^0.16.0",
30
+ "cosmiconfig": "^9.0.1",
31
+ "env-var": "^7.5.0",
32
+ "graphql": "^16.14.1",
33
+ "hono": "^4.12.25",
34
+ "pino": "^10.3.1",
35
+ "pino-pretty": "^13.1.3",
36
+ "yargs": "^18.0.0",
37
+ "zod": "^3.24.3"
38
+ },
39
+ "devDependencies": {
40
+ "@eslint/js": "^10.0.1",
41
+ "@release-it/conventional-changelog": "^11.0.1",
42
+ "@types/node": "^25.9.2",
43
+ "@types/yargs": "^17.0.35",
44
+ "@typescript-eslint/eslint-plugin": "^8.60.1",
45
+ "@typescript-eslint/parser": "^8.60.1",
46
+ "@typescript-eslint/utils": "^8.60.1",
47
+ "@vitest/coverage-v8": "^4.1.8",
48
+ "eslint": "^10.4.1",
49
+ "eslint-config-prettier": "^10.1.8",
50
+ "eslint-plugin-prettier": "^5.5.6",
51
+ "prettier": "^3.8.3",
52
+ "release-it": "^20.2.0",
53
+ "tsx": "^4.22.4",
54
+ "typescript": "^6.0.3",
55
+ "vitest": "^4.1.8"
56
+ },
13
57
  "scripts": {
58
+ "preinstall": "npx only-allow pnpm",
14
59
  "dev": "tsx src/index.ts",
15
60
  "build": "tsc && chmod 755 build/index.js",
16
61
  "test": "vitest run",
@@ -22,40 +67,5 @@
22
67
  "format:fix": "prettier --write \"**/*.{ts,tsx}\"",
23
68
  "typecheck": "tsc --noEmit",
24
69
  "typecheck:all": "tsc --noEmit --project tsconfig.test.json"
25
- },
26
- "files": [
27
- "build"
28
- ],
29
- "dependencies": {
30
- "@hono/node-server": "^1.19.14",
31
- "@modelcontextprotocol/sdk": "^1.26.0",
32
- "backlog-js": "^0.16.0",
33
- "cosmiconfig": "^9.0.0",
34
- "dotenv": "^16.5.0",
35
- "env-var": "^7.5.0",
36
- "graphql": "^16.11.0",
37
- "hono": "^4.12.23",
38
- "pino": "^9.9.0",
39
- "pino-pretty": "^13.1.1",
40
- "yargs": "^18.0.0",
41
- "zod": "^3.24.3"
42
- },
43
- "devDependencies": {
44
- "@eslint/js": "^9.24.0",
45
- "@release-it/conventional-changelog": "^11.0.0",
46
- "@types/node": "^22.14.1",
47
- "@types/yargs": "^17.0.33",
48
- "@typescript-eslint/eslint-plugin": "^8.30.1",
49
- "@typescript-eslint/parser": "^8.30.1",
50
- "@typescript-eslint/utils": "^8.30.1",
51
- "@vitest/coverage-v8": "^4.0.0",
52
- "eslint": "^9.24.0",
53
- "eslint-config-prettier": "^10.1.2",
54
- "eslint-plugin-prettier": "^5.2.6",
55
- "prettier": "^3.5.3",
56
- "release-it": "^20.0.1",
57
- "tsx": "^4.20.6",
58
- "typescript": "^5.8.3",
59
- "vitest": "^4.0.0"
60
70
  }
61
- }
71
+ }