backlog-mcp-server 0.15.0 → 0.16.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 (118) hide show
  1. package/README.ja.md +20 -10
  2. package/README.md +20 -10
  3. package/build/auth/backlogAuthContext.d.ts +2 -0
  4. package/build/auth/backlogOAuthClient.d.ts +10 -0
  5. package/build/auth/backlogOAuthConfig.d.ts +9 -0
  6. package/build/auth/bearerAuthMiddleware.d.ts +4 -0
  7. package/build/auth/oauthRoutes.d.ts +4 -0
  8. package/build/auth/tokenStore.d.ts +62 -0
  9. package/build/backlog/backlogErrorHandler.d.ts +2 -0
  10. package/build/backlog/customFields.d.ts +29 -0
  11. package/build/backlog/parseBacklogAPIError.d.ts +8 -0
  12. package/build/createBacklogMcpServer.d.ts +29 -0
  13. package/build/createBacklogMcpServer.js +9 -4
  14. package/build/createDescriptionHelper.d.ts +18 -0
  15. package/build/createDescriptionHelper.js +24 -0
  16. package/build/handlers/builders/composeToolHandler.d.ts +31 -0
  17. package/build/handlers/builders/composeToolHandler.js +21 -9
  18. package/build/handlers/transformers/wrapWithErrorHandling.d.ts +2 -0
  19. package/build/handlers/transformers/wrapWithFieldPicking.d.ts +4 -0
  20. package/build/handlers/transformers/wrapWithOrganizationContext.d.ts +3 -0
  21. package/build/handlers/transformers/wrapWithTokenLimit.d.ts +2 -0
  22. package/build/handlers/transformers/wrapWithToolResult.d.ts +6 -0
  23. package/build/httpMcpServer.d.ts +22 -0
  24. package/build/index.d.ts +2 -0
  25. package/build/index.js +29 -11
  26. package/build/lib.d.ts +25 -0
  27. package/build/lib.js +20 -0
  28. package/build/loadDescriptionOverrides.d.ts +17 -0
  29. package/build/loadDescriptionOverrides.js +24 -0
  30. package/build/registerTools.d.ts +5 -0
  31. package/build/registerTools.js +7 -6
  32. package/build/tools/addDocument.d.ts +15 -0
  33. package/build/tools/addIssue.d.ts +30 -0
  34. package/build/tools/addIssueComment.d.ts +14 -0
  35. package/build/tools/addProject.d.ts +18 -0
  36. package/build/tools/addPullRequest.d.ts +20 -0
  37. package/build/tools/addPullRequestComment.d.ts +16 -0
  38. package/build/tools/addRelatedIssue.d.ts +12 -0
  39. package/build/tools/addVersionMilestone.d.ts +15 -0
  40. package/build/tools/addWatching.d.ts +11 -0
  41. package/build/tools/addWiki.d.ts +13 -0
  42. package/build/tools/countIssues.d.ts +48 -0
  43. package/build/tools/deleteIssue.d.ts +11 -0
  44. package/build/tools/deleteProject.d.ts +11 -0
  45. package/build/tools/deleteVersion.d.ts +12 -0
  46. package/build/tools/deleteWatching.d.ts +10 -0
  47. package/build/tools/dynamicTools/organizations.d.ts +6 -0
  48. package/build/tools/dynamicTools/toolsets.d.ts +15 -0
  49. package/build/tools/getCategories.d.ts +11 -0
  50. package/build/tools/getCustomFields.d.ts +12 -0
  51. package/build/tools/getDocument.d.ts +10 -0
  52. package/build/tools/getDocumentTree.d.ts +10 -0
  53. package/build/tools/getDocuments.d.ts +11 -0
  54. package/build/tools/getGitRepositories.d.ts +11 -0
  55. package/build/tools/getGitRepository.d.ts +13 -0
  56. package/build/tools/getIssue.d.ts +11 -0
  57. package/build/tools/getIssueComments.d.ts +18 -0
  58. package/build/tools/getIssueTypes.d.ts +11 -0
  59. package/build/tools/getIssues.d.ts +75 -0
  60. package/build/tools/getMyself.d.ts +7 -0
  61. package/build/tools/getNotifications.d.ts +16 -0
  62. package/build/tools/getNotificationsCount.d.ts +11 -0
  63. package/build/tools/getPriorities.d.ts +7 -0
  64. package/build/tools/getProject.d.ts +11 -0
  65. package/build/tools/getProjectList.d.ts +11 -0
  66. package/build/tools/getProjectUsers.d.ts +11 -0
  67. package/build/tools/getPullRequest.d.ts +14 -0
  68. package/build/tools/getPullRequestComments.d.ts +21 -0
  69. package/build/tools/getPullRequests.d.ts +19 -0
  70. package/build/tools/getPullRequestsCount.d.ts +17 -0
  71. package/build/tools/getRelatedIssues.d.ts +11 -0
  72. package/build/tools/getResolutions.d.ts +7 -0
  73. package/build/tools/getSpace.d.ts +7 -0
  74. package/build/tools/getSpaceActivities.d.ts +45 -0
  75. package/build/tools/getUserRecentUpdates.d.ts +46 -0
  76. package/build/tools/getUserStarsCount.d.ts +12 -0
  77. package/build/tools/getUsers.d.ts +7 -0
  78. package/build/tools/getVersionMilestoneList.d.ts +11 -0
  79. package/build/tools/getWatchingListCount.d.ts +10 -0
  80. package/build/tools/getWatchingListItems.d.ts +10 -0
  81. package/build/tools/getWiki.d.ts +10 -0
  82. package/build/tools/getWikiPages.d.ts +12 -0
  83. package/build/tools/getWikisCount.d.ts +11 -0
  84. package/build/tools/markNotificationAsRead.d.ts +13 -0
  85. package/build/tools/markWatchingAsRead.d.ts +13 -0
  86. package/build/tools/removeRelatedIssue.d.ts +12 -0
  87. package/build/tools/resetUnreadNotificationCount.d.ts +7 -0
  88. package/build/tools/shared/customFieldFiltersSchema.d.ts +21 -0
  89. package/build/tools/tools.d.ts +4 -0
  90. package/build/tools/updateIssue.d.ts +34 -0
  91. package/build/tools/updateIssueComment.d.ts +13 -0
  92. package/build/tools/updateProject.d.ts +21 -0
  93. package/build/tools/updatePullRequest.d.ts +20 -0
  94. package/build/tools/updatePullRequestComment.d.ts +16 -0
  95. package/build/tools/updateVersionMilestone.d.ts +17 -0
  96. package/build/tools/updateWatching.d.ts +11 -0
  97. package/build/tools/updateWiki.d.ts +13 -0
  98. package/build/types/mcp.d.ts +10 -0
  99. package/build/types/result.d.ts +10 -0
  100. package/build/types/tool.d.ts +24 -0
  101. package/build/types/toolsets.d.ts +16 -0
  102. package/build/types/zod/backlogOutputDefinition.d.ts +3334 -0
  103. package/build/types/zod/backlogOutputDefinition.js +0 -16
  104. package/build/utils/backlogClientRegistry.d.ts +28 -0
  105. package/build/utils/backlogClientRegistry.js +4 -0
  106. package/build/utils/backlogOrganizationContext.d.ts +2 -0
  107. package/build/utils/generateFieldsDescription.d.ts +5 -0
  108. package/build/utils/logger.d.ts +2 -0
  109. package/build/utils/logger.js +27 -14
  110. package/build/utils/resolveIdOrKey.d.ts +18 -0
  111. package/build/utils/runToolSafely.d.ts +6 -0
  112. package/build/utils/tokenCounter.d.ts +1 -0
  113. package/build/utils/toolRegistrar.d.ts +5 -0
  114. package/build/utils/toolsetUtils.d.ts +6 -0
  115. package/build/utils/toolsetUtils.js +0 -20
  116. package/build/utils/wrapServerWithToolRegistry.d.ts +6 -0
  117. package/package.json +12 -3
  118. package/build/createTranslationHelper.js +0 -28
@@ -84,7 +84,6 @@ export const CustomFieldTypeSchema = z.nativeEnum({
84
84
  CheckBox: 7,
85
85
  Radio: 8,
86
86
  });
87
- export const WebhookActivityIdSchema = z.number();
88
87
  export const UserSchema = z.object({
89
88
  id: z.number(),
90
89
  userId: z.string(),
@@ -434,21 +433,6 @@ export const WikiListItemSchema = z.object({
434
433
  export const WikiCountSchema = z.object({
435
434
  count: z.number(),
436
435
  });
437
- export const DocumentSchema = z.object({
438
- id: z.number(),
439
- projectId: z.number(),
440
- name: z.string(),
441
- content: z.string(),
442
- createdUser: UserSchema,
443
- created: z.string(),
444
- updatedUser: UserSchema,
445
- updated: z.string(),
446
- });
447
- export const DocumentAttachmentSchema = z.object({
448
- filename: z.string(),
449
- body: z.any(),
450
- url: z.string(),
451
- });
452
436
  export const DocumentTagSchema = z.object({
453
437
  id: z.number(),
454
438
  name: z.string(),
@@ -0,0 +1,28 @@
1
+ import { Backlog } from 'backlog-js';
2
+ export type BacklogOrganizationInfo = {
3
+ name: string;
4
+ domain: string;
5
+ isDefault: boolean;
6
+ };
7
+ export type BacklogClientResolver = (organization?: string) => Backlog;
8
+ export type BacklogClientRegistry = {
9
+ resolveClient: BacklogClientResolver;
10
+ createScopedClient: () => Backlog;
11
+ listOrganizations: () => BacklogOrganizationInfo[];
12
+ getDefaultOrganization: () => string | undefined;
13
+ /**
14
+ * Whether more than one Backlog space can be addressed. Only then is it worth
15
+ * spending an `organization` parameter on every tool and publishing
16
+ * `list_organizations` — with a single space there is nothing to choose.
17
+ * Keyed on the configured mode, not the organization count, so a multi-org
18
+ * setup that happens to declare one space still exposes the parameter.
19
+ */
20
+ isMultiOrganization: boolean;
21
+ };
22
+ type Environment = Record<string, string | undefined>;
23
+ type RegistryInput = {
24
+ env?: Environment;
25
+ };
26
+ export declare function createBacklogClientRegistry(input?: RegistryInput): BacklogClientRegistry;
27
+ export declare function createOAuthBacklogClientRegistry(domain: string): BacklogClientRegistry;
28
+ export {};
@@ -39,6 +39,7 @@ export function createBacklogClientRegistry(input = {}) {
39
39
  }),
40
40
  listOrganizations: () => [info],
41
41
  getDefaultOrganization: () => defaultName,
42
+ isMultiOrganization: false,
42
43
  };
43
44
  }
44
45
  function createMultiOrganizationRegistryFromEnv(env) {
@@ -115,6 +116,7 @@ function createMultiOrganizationRegistryFromEnv(env) {
115
116
  }),
116
117
  listOrganizations: () => organizationInfo,
117
118
  getDefaultOrganization: () => defaultOrganization,
119
+ isMultiOrganization: true,
118
120
  };
119
121
  }
120
122
  function resolveKnownClient(clients, organization) {
@@ -147,6 +149,8 @@ export function createOAuthBacklogClientRegistry(domain) {
147
149
  createScopedClient: () => createBacklogClientProxy(resolveOAuthClient),
148
150
  listOrganizations: () => [info],
149
151
  getDefaultOrganization: () => defaultName,
152
+ // OAuth authorises against one Backlog domain per server.
153
+ isMultiOrganization: false,
150
154
  };
151
155
  }
152
156
  function createBacklogClientProxy(resolveClient) {
@@ -0,0 +1,2 @@
1
+ export declare function runWithOrganization<T>(organization: string | undefined, fn: () => Promise<T>): Promise<T>;
2
+ export declare function getCurrentOrganization(): string | undefined;
@@ -0,0 +1,5 @@
1
+ import { z, ZodRawShape } from 'zod';
2
+ /**
3
+ * Generate GraphQL like fields and type specs from Zod types
4
+ */
5
+ export declare function generateFieldsDescription(outputSchema: z.ZodObject<ZodRawShape>, importantFields?: string[], typeName?: string): string;
@@ -0,0 +1,2 @@
1
+ import pino from 'pino';
2
+ export declare const logger: pino.Logger<never, boolean>;
@@ -3,18 +3,31 @@ if (!process.env.NODE_ENV) {
3
3
  process.env.NODE_ENV = 'production';
4
4
  }
5
5
  const isProd = process.env.NODE_ENV === 'production';
6
- export const logger = pino({
7
- level: isProd ? 'error' : 'debug',
8
- transport: isProd
9
- ? undefined
10
- : {
11
- target: 'pino-pretty',
12
- options: {
13
- destination: 2,
14
- colorize: true,
15
- translateTime: 'SYS:yyyy-mm-dd HH:MM:ss.l',
16
- ignore: 'pid,hostname',
17
- singleLine: true,
6
+ // Plain JSON on stderr. stdout carries the JSON-RPC stream on the stdio
7
+ // transport, so a log line landing there would corrupt the protocol.
8
+ const plainLogger = () => pino({ level: isProd ? 'error' : 'debug' }, pino.destination({ dest: 2, sync: false }));
9
+ // `pino-pretty` is a development-only dependency, so an installed copy of this
10
+ // package does not have it. pino resolves a transport target eagerly and throws
11
+ // synchronously when it cannot, so asking is cheaper than probing the module
12
+ // graph — and a dev-mode run without pino-pretty still gets its logs.
13
+ const prettyLogger = () => {
14
+ try {
15
+ return pino({
16
+ level: 'debug',
17
+ transport: {
18
+ target: 'pino-pretty',
19
+ options: {
20
+ destination: 2,
21
+ colorize: true,
22
+ translateTime: 'SYS:yyyy-mm-dd HH:MM:ss.l',
23
+ ignore: 'pid,hostname',
24
+ singleLine: true,
25
+ },
18
26
  },
19
- },
20
- }, isProd ? pino.destination({ dest: 2, sync: false }) : undefined);
27
+ });
28
+ }
29
+ catch {
30
+ return plainLogger();
31
+ }
32
+ };
33
+ export const logger = isProd ? plainLogger() : prettyLogger();
@@ -0,0 +1,18 @@
1
+ import { DescriptionHelper } from '../createDescriptionHelper.js';
2
+ export type EntityName = 'issue' | 'project' | 'repository';
3
+ type ResolveResult = {
4
+ ok: true;
5
+ value: string | number;
6
+ } | {
7
+ ok: false;
8
+ error: Error;
9
+ };
10
+ export declare const resolveIdOrKey: <E extends EntityName>(entity: E, values: {
11
+ id?: number;
12
+ key?: string;
13
+ }, t: DescriptionHelper["t"]) => ResolveResult;
14
+ export declare const resolveIdOrName: <E extends EntityName>(entity: E, values: {
15
+ id?: number;
16
+ name?: string;
17
+ }, t: DescriptionHelper["t"]) => ResolveResult;
18
+ export {};
@@ -0,0 +1,6 @@
1
+ import { ErrorLike, SafeResult } from '../types/result.js';
2
+ /**
3
+ * Runs a tool handler safely, catching any errors and converting to SafeResult.
4
+ * The `onError` handler defines how to turn unknown errors into ErrorLike objects.
5
+ */
6
+ export declare function runToolSafely<I, O>(fn: (input: I) => Promise<O>, onError?: (err: unknown) => ErrorLike): (input: I) => Promise<SafeResult<O>>;
@@ -0,0 +1 @@
1
+ export declare function countTokens(text: string): number;
@@ -0,0 +1,5 @@
1
+ import { MCPOptions } from '../types/mcp.js';
2
+ import { ToolRegistrar } from '../types/tool.js';
3
+ import { ToolsetGroup } from '../types/toolsets.js';
4
+ import { BacklogMCPServer } from './wrapServerWithToolRegistry.js';
5
+ export declare function createToolRegistrar(server: BacklogMCPServer, toolsetGroup: ToolsetGroup, options: MCPOptions): ToolRegistrar;
@@ -0,0 +1,6 @@
1
+ import { Backlog } from 'backlog-js';
2
+ import { ToolsetGroup, Toolset } from '../types/toolsets.js';
3
+ import { DescriptionHelper } from '../createDescriptionHelper.js';
4
+ export declare function getToolset(group: ToolsetGroup, name: string): Toolset | undefined;
5
+ export declare function enableToolset(group: ToolsetGroup, name: string): string;
6
+ export declare const buildToolsetGroup: (backlog: Backlog, helper: DescriptionHelper, enabledToolsets: string[]) => ToolsetGroup;
@@ -11,26 +11,6 @@ export function enableToolset(group, name) {
11
11
  ts.enabled = true;
12
12
  return `Toolset ${name} enabled`;
13
13
  }
14
- export function getEnabledTools(group) {
15
- return group.toolsets.filter((ts) => ts.enabled).flatMap((ts) => ts.tools);
16
- }
17
- export function listAvailableToolsets(group) {
18
- return group.toolsets.map((ts) => ({
19
- name: ts.name,
20
- description: ts.description,
21
- currentlyEnabled: ts.enabled,
22
- canEnable: true,
23
- }));
24
- }
25
- export function listToolsetTools(group, name) {
26
- const ts = getToolset(group, name);
27
- return (ts?.tools.map((tool) => ({
28
- name: tool.name,
29
- description: tool.description,
30
- toolset: name,
31
- canEnable: true,
32
- })) ?? []);
33
- }
34
14
  export const buildToolsetGroup = (backlog, helper, enabledToolsets) => {
35
15
  const toolsetGroup = allTools(backlog, helper);
36
16
  const knownNames = toolsetGroup.toolsets.map((ts) => ts.name);
@@ -0,0 +1,6 @@
1
+ import type { McpServer, StandardSchemaWithJSON, ToolCallback } from '@modelcontextprotocol/server';
2
+ export interface BacklogMCPServer extends McpServer {
3
+ __registeredToolNames?: Set<string>;
4
+ registerOnce: (name: string, description: string, schema: StandardSchemaWithJSON, handler: ToolCallback<StandardSchemaWithJSON>) => void;
5
+ }
6
+ export declare function wrapServerWithToolRegistry(server: McpServer): BacklogMCPServer;
package/package.json CHANGED
@@ -1,10 +1,19 @@
1
1
  {
2
2
  "name": "backlog-mcp-server",
3
- "version": "0.15.0",
3
+ "version": "0.16.0",
4
4
  "type": "module",
5
5
  "bin": {
6
6
  "backlog-mcp-server": "./build/index.js"
7
7
  },
8
+ "main": "./build/lib.js",
9
+ "types": "./build/lib.d.ts",
10
+ "exports": {
11
+ ".": {
12
+ "types": "./build/lib.d.ts",
13
+ "import": "./build/lib.js"
14
+ },
15
+ "./package.json": "./package.json"
16
+ },
8
17
  "engines": {
9
18
  "node": ">=22"
10
19
  },
@@ -31,9 +40,8 @@
31
40
  "cosmiconfig": "^9.0.1",
32
41
  "env-var": "^7.5.0",
33
42
  "graphql": "^16.14.1",
34
- "hono": "^4.12.27",
43
+ "hono": "^4.12.34",
35
44
  "pino": "^10.3.1",
36
- "pino-pretty": "^13.1.3",
37
45
  "yargs": "^18.0.0",
38
46
  "zod": "^4.4.3"
39
47
  },
@@ -48,6 +56,7 @@
48
56
  "eslint": "^10.4.1",
49
57
  "eslint-config-prettier": "^10.1.8",
50
58
  "eslint-plugin-prettier": "^5.5.6",
59
+ "pino-pretty": "^13.1.3",
51
60
  "prettier": "^3.8.3",
52
61
  "tsx": "^4.22.4",
53
62
  "typescript": "^6.0.3",
@@ -1,28 +0,0 @@
1
- import { cosmiconfigSync } from 'cosmiconfig';
2
- import os from 'os';
3
- export function createTranslationHelper(options) {
4
- const usedKeys = {};
5
- const configName = options?.configName ?? 'backlog-mcp-server';
6
- // Load config file
7
- const explorer = cosmiconfigSync(configName);
8
- const searchPath = options?.searchDir ?? os.homedir();
9
- const configResult = explorer.search(searchPath);
10
- const config = configResult?.config || {};
11
- function toEnvKey(key) {
12
- return `BACKLOG_MCP_${key}`;
13
- }
14
- function t(key, fallback) {
15
- const upperKey = key.toUpperCase();
16
- if (usedKeys[upperKey]) {
17
- return usedKeys[upperKey];
18
- }
19
- // Priority:ENV → config → fallback
20
- const value = process.env[toEnvKey(upperKey)] || config[upperKey] || fallback;
21
- usedKeys[upperKey] = value;
22
- return value;
23
- }
24
- function dump() {
25
- return { ...usedKeys };
26
- }
27
- return { t, dump };
28
- }