@thelabnyc/redmine-mcp 0.2.0 → 0.3.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/LICENSE CHANGED
@@ -1,6 +1,6 @@
1
1
  ISC License
2
2
 
3
- Copyright (c) 2025 - 2025 thelab
3
+ Copyright (c) 2025 - 2026 thelab
4
4
 
5
5
  Permission to use, copy, modify, and/or distribute this software for any
6
6
  purpose with or without fee is hereby granted, provided that the above
package/dist/redmine.d.ts CHANGED
@@ -76,6 +76,11 @@ export interface RedmineRelation {
76
76
  relation_type: string;
77
77
  delay?: number;
78
78
  }
79
+ /** Data from Redmine Agile plugin. Only present if plugin is installed. */
80
+ export interface RedmineAgileData {
81
+ story_points?: number | null;
82
+ position?: number | null;
83
+ }
79
84
  export interface RedmineIssue {
80
85
  id: number;
81
86
  project: RedmineProject;
@@ -97,6 +102,7 @@ export interface RedmineIssue {
97
102
  watchers?: RedmineWatcher[];
98
103
  relations?: RedmineRelation[];
99
104
  children?: RedmineIssue[];
105
+ agile_data_attributes?: RedmineAgileData;
100
106
  }
101
107
  export interface GetIssueOptions {
102
108
  includeAttachments?: boolean;
@@ -177,6 +183,35 @@ export interface ListProjectMembersOptions {
177
183
  limit?: number;
178
184
  offset?: number;
179
185
  }
186
+ export interface ListMyIssuesOptions {
187
+ statusId?: number | "open" | "closed" | "*";
188
+ projectId?: string | number;
189
+ limit?: number;
190
+ offset?: number;
191
+ sort?: string;
192
+ }
193
+ export interface RedmineIssueSummary {
194
+ id: number;
195
+ project: RedmineProject;
196
+ tracker: RedmineTracker;
197
+ status: RedmineStatus;
198
+ priority: RedminePriority;
199
+ subject: string;
200
+ due_date?: string;
201
+ done_ratio: number;
202
+ updated_on: string;
203
+ /** Board position from Redmine Agile plugin. Undefined if plugin not installed. */
204
+ position?: number | null;
205
+ }
206
+ export interface RedmineProjectSummary {
207
+ id: number;
208
+ identifier: string;
209
+ name: string;
210
+ }
211
+ export interface ListProjectsOptions {
212
+ limit?: number;
213
+ offset?: number;
214
+ }
180
215
  export declare class RedmineClient {
181
216
  private readonly config;
182
217
  constructor(config: Config);
@@ -196,4 +231,16 @@ export declare class RedmineClient {
196
231
  }>;
197
232
  listIssueStatuses(): Promise<RedmineIssueStatusDetail[]>;
198
233
  getCurrentUser(): Promise<RedmineCurrentUser>;
234
+ listMyIssues(options?: ListMyIssuesOptions): Promise<{
235
+ issues: RedmineIssueSummary[];
236
+ total_count: number;
237
+ offset: number;
238
+ limit: number;
239
+ }>;
240
+ listProjects(options?: ListProjectsOptions): Promise<{
241
+ projects: RedmineProjectSummary[];
242
+ total_count: number;
243
+ offset: number;
244
+ limit: number;
245
+ }>;
199
246
  }
package/dist/redmine.js CHANGED
@@ -181,5 +181,90 @@ export class RedmineClient {
181
181
  const { api_key: _, ...user } = data.user;
182
182
  return user;
183
183
  }
184
+ async listMyIssues(options = {}) {
185
+ const DEFAULT_SORT = "priority:desc,updated_on:desc";
186
+ const params = new URLSearchParams();
187
+ params.set("assigned_to_id", "me");
188
+ if (options.statusId !== undefined) {
189
+ params.set("status_id", String(options.statusId));
190
+ }
191
+ if (options.projectId !== undefined) {
192
+ params.set("project_id", String(options.projectId));
193
+ }
194
+ if (options.limit !== undefined) {
195
+ params.set("limit", String(options.limit));
196
+ }
197
+ if (options.offset !== undefined) {
198
+ params.set("offset", String(options.offset));
199
+ }
200
+ params.set("sort", options.sort ?? DEFAULT_SORT);
201
+ const url = `${this.config.redmineUrl}/issues.json?${params.toString()}`;
202
+ const response = await fetch(url, {
203
+ method: "GET",
204
+ headers: {
205
+ "X-Redmine-API-Key": this.config.redmineApiKey,
206
+ "Accept": "application/json",
207
+ },
208
+ });
209
+ if (!response.ok) {
210
+ const errorDetails = await this.extractErrorDetails(response);
211
+ throw new Error(`Failed to fetch issues: ${response.status} ${response.statusText}${errorDetails}`);
212
+ }
213
+ const data = (await response.json());
214
+ // Return slim summaries to reduce response size
215
+ const summaries = data.issues.map((issue) => ({
216
+ id: issue.id,
217
+ project: issue.project,
218
+ tracker: issue.tracker,
219
+ status: issue.status,
220
+ priority: issue.priority,
221
+ subject: issue.subject,
222
+ due_date: issue.due_date,
223
+ done_ratio: issue.done_ratio,
224
+ updated_on: issue.updated_on,
225
+ position: issue.agile_data_attributes?.position,
226
+ }));
227
+ return {
228
+ issues: summaries,
229
+ total_count: data.total_count,
230
+ offset: data.offset,
231
+ limit: data.limit,
232
+ };
233
+ }
234
+ async listProjects(options = {}) {
235
+ const params = new URLSearchParams();
236
+ if (options.limit !== undefined) {
237
+ params.set("limit", String(options.limit));
238
+ }
239
+ if (options.offset !== undefined) {
240
+ params.set("offset", String(options.offset));
241
+ }
242
+ const queryString = params.toString();
243
+ const url = `${this.config.redmineUrl}/projects.json${queryString ? `?${queryString}` : ""}`;
244
+ const response = await fetch(url, {
245
+ method: "GET",
246
+ headers: {
247
+ "X-Redmine-API-Key": this.config.redmineApiKey,
248
+ "Accept": "application/json",
249
+ },
250
+ });
251
+ if (!response.ok) {
252
+ const errorDetails = await this.extractErrorDetails(response);
253
+ throw new Error(`Failed to fetch projects: ${response.status} ${response.statusText}${errorDetails}`);
254
+ }
255
+ const data = (await response.json());
256
+ // Return slim summaries
257
+ const summaries = data.projects.map((project) => ({
258
+ id: project.id,
259
+ identifier: project.identifier,
260
+ name: project.name,
261
+ }));
262
+ return {
263
+ projects: summaries,
264
+ total_count: data.total_count,
265
+ offset: data.offset,
266
+ limit: data.limit,
267
+ };
268
+ }
184
269
  }
185
270
  //# sourceMappingURL=redmine.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"redmine.js","sourceRoot":"","sources":["../src/redmine.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"redmine.js","sourceRoot":"","sources":["../src/redmine.ts"],"names":[],"mappings":"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"}
package/dist/server.js CHANGED
@@ -11,7 +11,7 @@ export function createServer() {
11
11
  const redmineClient = new RedmineClient(config);
12
12
  const server = new McpServer({
13
13
  name: "redmine-mcp",
14
- version: "0.2.0",
14
+ version: "0.3.0",
15
15
  });
16
16
  registerAllTools(server, redmineClient);
17
17
  return server;
@@ -1,5 +1,5 @@
1
1
  import { Client } from "@modelcontextprotocol/sdk/client/index.js";
2
- import type { GetIssueResult, RedmineCurrentUser, RedmineIssue, RedmineIssueStatusDetail, RedmineMembership, RedmineTimeEntry } from "./redmine.js";
2
+ import type { GetIssueResult, RedmineCurrentUser, RedmineIssue, RedmineIssueStatusDetail, RedmineIssueSummary, RedmineMembership, RedmineProjectSummary, RedmineTimeEntry } from "./redmine.js";
3
3
  export declare const mockFetch: import("vitest").Mock<import("@vitest/spy").Procedure>;
4
4
  export interface TextContent {
5
5
  type: "text";
@@ -45,16 +45,10 @@ export declare function createTestClientServer(): Promise<{
45
45
  method: string;
46
46
  params?: {
47
47
  [x: string]: unknown;
48
- task?: {
49
- [x: string]: unknown;
50
- ttl?: number | null | undefined;
51
- pollInterval?: number | undefined;
52
- } | undefined;
53
48
  _meta?: {
54
49
  [x: string]: unknown;
55
50
  progressToken?: string | number | undefined;
56
51
  "io.modelcontextprotocol/related-task"?: {
57
- [x: string]: unknown;
58
52
  taskId: string;
59
53
  } | undefined;
60
54
  } | undefined;
@@ -65,8 +59,8 @@ export declare function createTestClientServer(): Promise<{
65
59
  [x: string]: unknown;
66
60
  _meta?: {
67
61
  [x: string]: unknown;
62
+ progressToken?: string | number | undefined;
68
63
  "io.modelcontextprotocol/related-task"?: {
69
- [x: string]: unknown;
70
64
  taskId: string;
71
65
  } | undefined;
72
66
  } | undefined;
@@ -75,8 +69,8 @@ export declare function createTestClientServer(): Promise<{
75
69
  [x: string]: unknown;
76
70
  _meta?: {
77
71
  [x: string]: unknown;
72
+ progressToken?: string | number | undefined;
78
73
  "io.modelcontextprotocol/related-task"?: {
79
- [x: string]: unknown;
80
74
  taskId: string;
81
75
  } | undefined;
82
76
  } | undefined;
@@ -98,6 +92,18 @@ export declare function parseUpdateResult(result: ToolResult): {
98
92
  };
99
93
  export declare function parseIssueStatusesResult(result: ToolResult): RedmineIssueStatusDetail[];
100
94
  export declare function parseCurrentUserResult(result: ToolResult): RedmineCurrentUser;
95
+ export declare function parseMyIssuesResult(result: ToolResult): {
96
+ issues: RedmineIssueSummary[];
97
+ total_count: number;
98
+ offset: number;
99
+ limit: number;
100
+ };
101
+ export declare function parseProjectsResult(result: ToolResult): {
102
+ projects: RedmineProjectSummary[];
103
+ total_count: number;
104
+ offset: number;
105
+ limit: number;
106
+ };
101
107
  /**
102
108
  * Setup environment for tests - call in beforeEach
103
109
  */
@@ -48,6 +48,14 @@ export function parseCurrentUserResult(result) {
48
48
  const text = getTextContent(result);
49
49
  return JSON.parse(text);
50
50
  }
51
+ export function parseMyIssuesResult(result) {
52
+ const text = getTextContent(result);
53
+ return JSON.parse(text);
54
+ }
55
+ export function parseProjectsResult(result) {
56
+ const text = getTextContent(result);
57
+ return JSON.parse(text);
58
+ }
51
59
  /**
52
60
  * Setup environment for tests - call in beforeEach
53
61
  */
@@ -1 +1 @@
1
- {"version":3,"file":"test-utils.js","sourceRoot":"","sources":["../src/test-utils.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAE,MAAM,2CAA2C,CAAC;AACnE,OAAO,EAAE,iBAAiB,EAAE,MAAM,uCAAuC,CAAC;AAC1E,OAAO,EAAE,EAAE,EAAE,MAAM,QAAQ,CAAC;AAU5B,OAAO,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AAE3C,sBAAsB;AACtB,MAAM,CAAC,MAAM,SAAS,GAAG,EAAE,CAAC,EAAE,EAAE,CAAC;AACjC,EAAE,CAAC,UAAU,CAAC,OAAO,EAAE,SAAS,CAAC,CAAC;AA0ClC;;GAEG;AACH,MAAM,CAAC,KAAK,UAAU,sBAAsB;IACxC,MAAM,MAAM,GAAG,YAAY,EAAE,CAAC;IAC9B,MAAM,MAAM,GAAG,IAAI,MAAM,CAAC;QACtB,IAAI,EAAE,aAAa;QACnB,OAAO,EAAE,OAAO;KACnB,CAAC,CAAC;IAEH,MAAM,CAAC,eAAe,EAAE,eAAe,CAAC,GACpC,iBAAiB,CAAC,gBAAgB,EAAE,CAAC;IAEzC,MAAM,OAAO,CAAC,GAAG,CAAC;QACd,MAAM,CAAC,OAAO,CAAC,eAAe,CAAC;QAC/B,MAAM,CAAC,OAAO,CAAC,eAAe,CAAC;KAClC,CAAC,CAAC;IAEH,OAAO,EAAE,MAAM,EAAE,MAAM,EAAE,OAAO,EAAE,GAAG,EAAE,CAAC,MAAM,CAAC,KAAK,EAAE,EAAE,CAAC;AAC7D,CAAC;AAED,MAAM,UAAU,cAAc,CAAC,MAAkB;IAC7C,MAAM,WAAW,GAAG,MAAM,CAAC,OAAO,CAAC,IAAI,CACnC,CAAC,CAAC,EAAoB,EAAE,CAAC,CAAC,CAAC,IAAI,KAAK,MAAM,CAC7C,CAAC;IACF,IAAI,CAAC,WAAW,EAAE,CAAC;QACf,MAAM,IAAI,KAAK,CAAC,uBAAuB,CAAC,CAAC;IAC7C,CAAC;IACD,OAAO,WAAW,CAAC,IAAI,CAAC;AAC5B,CAAC;AAED,MAAM,UAAU,gBAAgB,CAAC,MAAkB;IAC/C,MAAM,IAAI,GAAG,cAAc,CAAC,MAAM,CAAC,CAAC;IACpC,OAAO,IAAI,CAAC,KAAK,CAAC,IAAI,CAAmB,CAAC;AAC9C,CAAC;AAED,MAAM,UAAU,sBAAsB,CAAC,MAAkB;IAIrD,MAAM,IAAI,GAAG,cAAc,CAAC,MAAM,CAAC,CAAC;IACpC,OAAO,IAAI,CAAC,KAAK,CAAC,IAAI,CAGrB,CAAC;AACN,CAAC;AAED,MAAM,UAAU,iBAAiB,CAAC,MAAkB;IAMhD,MAAM,IAAI,GAAG,cAAc,CAAC,MAAM,CAAC,CAAC;IACpC,OAAO,IAAI,CAAC,KAAK,CAAC,IAAI,CAKrB,CAAC;AACN,CAAC;AAED,MAAM,UAAU,wBAAwB,CACpC,MAAkB;IAElB,MAAM,IAAI,GAAG,cAAc,CAAC,MAAM,CAAC,CAAC;IACpC,OAAO,IAAI,CAAC,KAAK,CAAC,IAAI,CAA+B,CAAC;AAC1D,CAAC;AAED,MAAM,UAAU,sBAAsB,CAAC,MAAkB;IACrD,MAAM,IAAI,GAAG,cAAc,CAAC,MAAM,CAAC,CAAC;IACpC,OAAO,IAAI,CAAC,KAAK,CAAC,IAAI,CAAuB,CAAC;AAClD,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,YAAY;IACxB,SAAS,CAAC,SAAS,EAAE,CAAC;IACtB,OAAO,CAAC,GAAG,CAAC,WAAW,GAAG,0BAA0B,CAAC;IACrD,OAAO,CAAC,GAAG,CAAC,eAAe,GAAG,cAAc,CAAC;AACjD,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,cAAc;IAC1B,OAAO,OAAO,CAAC,GAAG,CAAC,WAAW,CAAC;IAC/B,OAAO,OAAO,CAAC,GAAG,CAAC,eAAe,CAAC;AACvC,CAAC"}
1
+ {"version":3,"file":"test-utils.js","sourceRoot":"","sources":["../src/test-utils.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,238 @@
1
+ import { afterEach, beforeEach, describe, expect, it } from "vitest";
2
+ import { cleanupTestEnv, createTestClientServer, getTextContent, mockFetch, parseMyIssuesResult, setupTestEnv, } from "../../test-utils.js";
3
+ // Full API response (what Redmine returns)
4
+ const sampleIssuesResponse = {
5
+ issues: [
6
+ {
7
+ id: 123,
8
+ project: { id: 1, name: "Project A" },
9
+ tracker: { id: 1, name: "Bug" },
10
+ status: { id: 1, name: "New" },
11
+ priority: { id: 2, name: "Normal" },
12
+ author: { id: 1, name: "John Doe" },
13
+ assigned_to: { id: 2, name: "Jane Smith" },
14
+ subject: "First issue",
15
+ description: "Description of first issue",
16
+ done_ratio: 0,
17
+ created_on: "2024-01-15T10:00:00Z",
18
+ updated_on: "2024-01-20T14:30:00Z",
19
+ agile_data_attributes: { story_points: null, position: 5 },
20
+ },
21
+ {
22
+ id: 456,
23
+ project: { id: 2, name: "Project B" },
24
+ tracker: { id: 2, name: "Feature" },
25
+ status: { id: 2, name: "In Progress" },
26
+ priority: { id: 3, name: "High" },
27
+ author: { id: 3, name: "Bob Wilson" },
28
+ assigned_to: { id: 2, name: "Jane Smith" },
29
+ subject: "Second issue",
30
+ description: "Description of second issue",
31
+ done_ratio: 50,
32
+ created_on: "2024-01-10T09:00:00Z",
33
+ updated_on: "2024-01-18T11:00:00Z",
34
+ agile_data_attributes: { story_points: 3, position: 2 },
35
+ },
36
+ ],
37
+ total_count: 2,
38
+ offset: 0,
39
+ limit: 25,
40
+ };
41
+ describe("list-my-issues tool", () => {
42
+ beforeEach(() => {
43
+ setupTestEnv();
44
+ });
45
+ afterEach(() => {
46
+ cleanupTestEnv();
47
+ });
48
+ it("returns issues assigned to current user", async () => {
49
+ mockFetch.mockResolvedValueOnce({
50
+ ok: true,
51
+ status: 200,
52
+ json: () => Promise.resolve(sampleIssuesResponse),
53
+ });
54
+ const { client, cleanup } = await createTestClientServer();
55
+ try {
56
+ const result = (await client.callTool({
57
+ name: "list-my-issues",
58
+ arguments: {},
59
+ }));
60
+ // Verify fetch was called with correct URL and default sort
61
+ expect(mockFetch).toHaveBeenCalledTimes(1);
62
+ const [url, options] = mockFetch.mock.calls[0];
63
+ expect(url).toContain("/issues.json");
64
+ expect(url).toContain("assigned_to_id=me");
65
+ expect(url).toContain("sort=priority%3Adesc%2Cupdated_on%3Adesc");
66
+ expect(options.headers["X-Redmine-API-Key"]).toBe("test-api-key");
67
+ // Verify response - should be slim (no description, author, etc.)
68
+ expect(result.isError).toBeFalsy();
69
+ const responseData = parseMyIssuesResult(result);
70
+ expect(responseData.issues).toHaveLength(2);
71
+ expect(responseData.total_count).toBe(2);
72
+ expect(responseData.issues[0].id).toBe(123);
73
+ expect(responseData.issues[0].subject).toBe("First issue");
74
+ expect(responseData.issues[0].done_ratio).toBe(0);
75
+ expect(responseData.issues[0].position).toBe(5);
76
+ expect(responseData.issues[1].id).toBe(456);
77
+ expect(responseData.issues[1].subject).toBe("Second issue");
78
+ expect(responseData.issues[1].done_ratio).toBe(50);
79
+ expect(responseData.issues[1].position).toBe(2);
80
+ // Verify slim fields only - these should NOT be present
81
+ expect(responseData.issues[0]).not.toHaveProperty("description");
82
+ expect(responseData.issues[0]).not.toHaveProperty("author");
83
+ expect(responseData.issues[0]).not.toHaveProperty("assigned_to");
84
+ expect(responseData.issues[0]).not.toHaveProperty("created_on");
85
+ }
86
+ finally {
87
+ await cleanup();
88
+ }
89
+ });
90
+ it("passes status filter to API", async () => {
91
+ mockFetch.mockResolvedValueOnce({
92
+ ok: true,
93
+ status: 200,
94
+ json: () => Promise.resolve({ ...sampleIssuesResponse, issues: [] }),
95
+ });
96
+ const { client, cleanup } = await createTestClientServer();
97
+ try {
98
+ await client.callTool({
99
+ name: "list-my-issues",
100
+ arguments: { statusId: "closed" },
101
+ });
102
+ const [url] = mockFetch.mock.calls[0];
103
+ expect(url).toContain("status_id=closed");
104
+ }
105
+ finally {
106
+ await cleanup();
107
+ }
108
+ });
109
+ it("passes project filter to API", async () => {
110
+ mockFetch.mockResolvedValueOnce({
111
+ ok: true,
112
+ status: 200,
113
+ json: () => Promise.resolve({ ...sampleIssuesResponse, issues: [] }),
114
+ });
115
+ const { client, cleanup } = await createTestClientServer();
116
+ try {
117
+ await client.callTool({
118
+ name: "list-my-issues",
119
+ arguments: { projectId: "my-project" },
120
+ });
121
+ const [url] = mockFetch.mock.calls[0];
122
+ expect(url).toContain("project_id=my-project");
123
+ }
124
+ finally {
125
+ await cleanup();
126
+ }
127
+ });
128
+ it("passes pagination parameters to API", async () => {
129
+ mockFetch.mockResolvedValueOnce({
130
+ ok: true,
131
+ status: 200,
132
+ json: () => Promise.resolve({
133
+ ...sampleIssuesResponse,
134
+ offset: 10,
135
+ limit: 5,
136
+ }),
137
+ });
138
+ const { client, cleanup } = await createTestClientServer();
139
+ try {
140
+ const result = (await client.callTool({
141
+ name: "list-my-issues",
142
+ arguments: { limit: 5, offset: 10 },
143
+ }));
144
+ const [url] = mockFetch.mock.calls[0];
145
+ expect(url).toContain("limit=5");
146
+ expect(url).toContain("offset=10");
147
+ const responseData = parseMyIssuesResult(result);
148
+ expect(responseData.offset).toBe(10);
149
+ expect(responseData.limit).toBe(5);
150
+ }
151
+ finally {
152
+ await cleanup();
153
+ }
154
+ });
155
+ it("passes sort parameter to API", async () => {
156
+ mockFetch.mockResolvedValueOnce({
157
+ ok: true,
158
+ status: 200,
159
+ json: () => Promise.resolve(sampleIssuesResponse),
160
+ });
161
+ const { client, cleanup } = await createTestClientServer();
162
+ try {
163
+ await client.callTool({
164
+ name: "list-my-issues",
165
+ arguments: { sort: "priority:desc" },
166
+ });
167
+ const [url] = mockFetch.mock.calls[0];
168
+ expect(url).toContain("sort=priority%3Adesc");
169
+ }
170
+ finally {
171
+ await cleanup();
172
+ }
173
+ });
174
+ it("handles API errors gracefully", async () => {
175
+ mockFetch.mockResolvedValueOnce({
176
+ ok: false,
177
+ status: 401,
178
+ statusText: "Unauthorized",
179
+ json: () => Promise.resolve({ errors: ["Invalid API key"] }),
180
+ });
181
+ const { client, cleanup } = await createTestClientServer();
182
+ try {
183
+ const result = (await client.callTool({
184
+ name: "list-my-issues",
185
+ arguments: {},
186
+ }));
187
+ expect(result.isError).toBe(true);
188
+ const errorText = getTextContent(result);
189
+ expect(errorText).toContain("401");
190
+ }
191
+ finally {
192
+ await cleanup();
193
+ }
194
+ });
195
+ it("handles network errors gracefully", async () => {
196
+ mockFetch.mockRejectedValueOnce(new Error("Network error"));
197
+ const { client, cleanup } = await createTestClientServer();
198
+ try {
199
+ const result = (await client.callTool({
200
+ name: "list-my-issues",
201
+ arguments: {},
202
+ }));
203
+ expect(result.isError).toBe(true);
204
+ const errorText = getTextContent(result);
205
+ expect(errorText).toContain("Network error");
206
+ }
207
+ finally {
208
+ await cleanup();
209
+ }
210
+ });
211
+ it("returns empty list when no issues assigned", async () => {
212
+ mockFetch.mockResolvedValueOnce({
213
+ ok: true,
214
+ status: 200,
215
+ json: () => Promise.resolve({
216
+ issues: [],
217
+ total_count: 0,
218
+ offset: 0,
219
+ limit: 25,
220
+ }),
221
+ });
222
+ const { client, cleanup } = await createTestClientServer();
223
+ try {
224
+ const result = (await client.callTool({
225
+ name: "list-my-issues",
226
+ arguments: {},
227
+ }));
228
+ expect(result.isError).toBeFalsy();
229
+ const responseData = parseMyIssuesResult(result);
230
+ expect(responseData.issues).toHaveLength(0);
231
+ expect(responseData.total_count).toBe(0);
232
+ }
233
+ finally {
234
+ await cleanup();
235
+ }
236
+ });
237
+ });
238
+ //# sourceMappingURL=list-my-issues.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"list-my-issues.test.js","sourceRoot":"","sources":["../../../src/tools/__tests__/list-my-issues.test.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,214 @@
1
+ import { afterEach, beforeEach, describe, expect, it } from "vitest";
2
+ import { cleanupTestEnv, createTestClientServer, getTextContent, mockFetch, parseProjectsResult, setupTestEnv, } from "../../test-utils.js";
3
+ const sampleProjectsResponse = {
4
+ projects: [
5
+ {
6
+ id: 154,
7
+ name: "Tula",
8
+ identifier: "tula",
9
+ description: "Tula project description",
10
+ status: 1,
11
+ is_public: false,
12
+ created_on: "2024-01-01T00:00:00Z",
13
+ updated_on: "2024-01-15T00:00:00Z",
14
+ },
15
+ {
16
+ id: 164,
17
+ name: "First Aid Beauty",
18
+ identifier: "pg_fab",
19
+ description: "FAB project",
20
+ status: 1,
21
+ is_public: false,
22
+ created_on: "2024-01-02T00:00:00Z",
23
+ updated_on: "2024-01-16T00:00:00Z",
24
+ },
25
+ {
26
+ id: 134,
27
+ name: "Emtek",
28
+ identifier: "emtek-website",
29
+ description: "Emtek website project",
30
+ status: 1,
31
+ is_public: false,
32
+ created_on: "2024-01-03T00:00:00Z",
33
+ updated_on: "2024-01-17T00:00:00Z",
34
+ },
35
+ ],
36
+ total_count: 3,
37
+ offset: 0,
38
+ limit: 100,
39
+ };
40
+ describe("list-projects tool", () => {
41
+ beforeEach(() => {
42
+ setupTestEnv();
43
+ });
44
+ afterEach(() => {
45
+ cleanupTestEnv();
46
+ });
47
+ it("returns projects as JSON", async () => {
48
+ mockFetch.mockResolvedValueOnce({
49
+ ok: true,
50
+ status: 200,
51
+ json: () => Promise.resolve(sampleProjectsResponse),
52
+ });
53
+ const { client, cleanup } = await createTestClientServer();
54
+ try {
55
+ const result = (await client.callTool({
56
+ name: "list-projects",
57
+ arguments: {},
58
+ }));
59
+ expect(result.isError).toBeFalsy();
60
+ const parsed = parseProjectsResult(result);
61
+ expect(parsed.total_count).toBe(3);
62
+ expect(parsed.projects).toHaveLength(3);
63
+ // Check slim response (only id, identifier, name)
64
+ expect(parsed.projects[0]).toEqual({
65
+ id: 154,
66
+ identifier: "tula",
67
+ name: "Tula",
68
+ });
69
+ expect(parsed.projects[1]).toEqual({
70
+ id: 164,
71
+ identifier: "pg_fab",
72
+ name: "First Aid Beauty",
73
+ });
74
+ expect(parsed.projects[2]).toEqual({
75
+ id: 134,
76
+ identifier: "emtek-website",
77
+ name: "Emtek",
78
+ });
79
+ // Verify extra fields are stripped
80
+ expect(parsed.projects[0]).not.toHaveProperty("description");
81
+ expect(parsed.projects[0]).not.toHaveProperty("status");
82
+ expect(parsed.projects[0]).not.toHaveProperty("is_public");
83
+ expect(parsed.projects[0]).not.toHaveProperty("created_on");
84
+ expect(parsed.projects[0]).not.toHaveProperty("updated_on");
85
+ // Verify fetch was called correctly
86
+ expect(mockFetch).toHaveBeenCalledTimes(1);
87
+ const [url, options] = mockFetch.mock.calls[0];
88
+ expect(url).toContain("/projects.json");
89
+ expect(url).toContain("limit=100");
90
+ expect(options.headers["X-Redmine-API-Key"]).toBe("test-api-key");
91
+ }
92
+ finally {
93
+ await cleanup();
94
+ }
95
+ });
96
+ it("passes pagination parameters to API", async () => {
97
+ mockFetch.mockResolvedValueOnce({
98
+ ok: true,
99
+ status: 200,
100
+ json: () => Promise.resolve({
101
+ ...sampleProjectsResponse,
102
+ offset: 10,
103
+ limit: 25,
104
+ }),
105
+ });
106
+ const { client, cleanup } = await createTestClientServer();
107
+ try {
108
+ const result = (await client.callTool({
109
+ name: "list-projects",
110
+ arguments: { limit: 25, offset: 10 },
111
+ }));
112
+ const parsed = parseProjectsResult(result);
113
+ expect(parsed.offset).toBe(10);
114
+ expect(parsed.limit).toBe(25);
115
+ const [url] = mockFetch.mock.calls[0];
116
+ expect(url).toContain("limit=25");
117
+ expect(url).toContain("offset=10");
118
+ }
119
+ finally {
120
+ await cleanup();
121
+ }
122
+ });
123
+ it("returns pagination info when more projects exist", async () => {
124
+ mockFetch.mockResolvedValueOnce({
125
+ ok: true,
126
+ status: 200,
127
+ json: () => Promise.resolve({
128
+ projects: sampleProjectsResponse.projects.slice(0, 2),
129
+ total_count: 68,
130
+ offset: 0,
131
+ limit: 2,
132
+ }),
133
+ });
134
+ const { client, cleanup } = await createTestClientServer();
135
+ try {
136
+ const result = (await client.callTool({
137
+ name: "list-projects",
138
+ arguments: { limit: 2 },
139
+ }));
140
+ const parsed = parseProjectsResult(result);
141
+ expect(parsed.total_count).toBe(68);
142
+ expect(parsed.projects).toHaveLength(2);
143
+ expect(parsed.offset).toBe(0);
144
+ expect(parsed.limit).toBe(2);
145
+ }
146
+ finally {
147
+ await cleanup();
148
+ }
149
+ });
150
+ it("handles API errors gracefully", async () => {
151
+ mockFetch.mockResolvedValueOnce({
152
+ ok: false,
153
+ status: 401,
154
+ statusText: "Unauthorized",
155
+ json: () => Promise.resolve({ errors: ["Invalid API key"] }),
156
+ });
157
+ const { client, cleanup } = await createTestClientServer();
158
+ try {
159
+ const result = (await client.callTool({
160
+ name: "list-projects",
161
+ arguments: {},
162
+ }));
163
+ expect(result.isError).toBe(true);
164
+ const errorText = getTextContent(result);
165
+ expect(errorText).toContain("401");
166
+ }
167
+ finally {
168
+ await cleanup();
169
+ }
170
+ });
171
+ it("handles network errors gracefully", async () => {
172
+ mockFetch.mockRejectedValueOnce(new Error("Network error"));
173
+ const { client, cleanup } = await createTestClientServer();
174
+ try {
175
+ const result = (await client.callTool({
176
+ name: "list-projects",
177
+ arguments: {},
178
+ }));
179
+ expect(result.isError).toBe(true);
180
+ const errorText = getTextContent(result);
181
+ expect(errorText).toContain("Network error");
182
+ }
183
+ finally {
184
+ await cleanup();
185
+ }
186
+ });
187
+ it("returns empty list when no projects", async () => {
188
+ mockFetch.mockResolvedValueOnce({
189
+ ok: true,
190
+ status: 200,
191
+ json: () => Promise.resolve({
192
+ projects: [],
193
+ total_count: 0,
194
+ offset: 0,
195
+ limit: 100,
196
+ }),
197
+ });
198
+ const { client, cleanup } = await createTestClientServer();
199
+ try {
200
+ const result = (await client.callTool({
201
+ name: "list-projects",
202
+ arguments: {},
203
+ }));
204
+ expect(result.isError).toBeFalsy();
205
+ const parsed = parseProjectsResult(result);
206
+ expect(parsed.total_count).toBe(0);
207
+ expect(parsed.projects).toHaveLength(0);
208
+ }
209
+ finally {
210
+ await cleanup();
211
+ }
212
+ });
213
+ });
214
+ //# sourceMappingURL=list-projects.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"list-projects.test.js","sourceRoot":"","sources":["../../../src/tools/__tests__/list-projects.test.ts"],"names":[],"mappings":"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"}
@@ -2,8 +2,10 @@ import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
2
2
  import type { RedmineClient } from "../redmine.js";
3
3
  import { registerGetIssueTool } from "./get-issue.js";
4
4
  import { registerListIssueStatusesTool } from "./list-issue-statuses.js";
5
+ import { registerListMyIssuesTool } from "./list-my-issues.js";
5
6
  import { registerListProjectMembersTool } from "./list-project-members.js";
7
+ import { registerListProjectsTool } from "./list-projects.js";
6
8
  import { registerUpdateIssueTool } from "./update-issue.js";
7
9
  import { registerWhoamiTool } from "./whoami.js";
8
10
  export declare function registerAllTools(server: McpServer, redmineClient: RedmineClient): void;
9
- export { registerGetIssueTool, registerListIssueStatusesTool, registerListProjectMembersTool, registerUpdateIssueTool, registerWhoamiTool, };
11
+ export { registerGetIssueTool, registerListIssueStatusesTool, registerListMyIssuesTool, registerListProjectMembersTool, registerListProjectsTool, registerUpdateIssueTool, registerWhoamiTool, };
@@ -1,14 +1,18 @@
1
1
  import { registerGetIssueTool } from "./get-issue.js";
2
2
  import { registerListIssueStatusesTool } from "./list-issue-statuses.js";
3
+ import { registerListMyIssuesTool } from "./list-my-issues.js";
3
4
  import { registerListProjectMembersTool } from "./list-project-members.js";
5
+ import { registerListProjectsTool } from "./list-projects.js";
4
6
  import { registerUpdateIssueTool } from "./update-issue.js";
5
7
  import { registerWhoamiTool } from "./whoami.js";
6
8
  export function registerAllTools(server, redmineClient) {
7
9
  registerGetIssueTool(server, redmineClient);
10
+ registerListMyIssuesTool(server, redmineClient);
8
11
  registerListProjectMembersTool(server, redmineClient);
12
+ registerListProjectsTool(server, redmineClient);
9
13
  registerUpdateIssueTool(server, redmineClient);
10
14
  registerListIssueStatusesTool(server, redmineClient);
11
15
  registerWhoamiTool(server, redmineClient);
12
16
  }
13
- export { registerGetIssueTool, registerListIssueStatusesTool, registerListProjectMembersTool, registerUpdateIssueTool, registerWhoamiTool, };
17
+ export { registerGetIssueTool, registerListIssueStatusesTool, registerListMyIssuesTool, registerListProjectMembersTool, registerListProjectsTool, registerUpdateIssueTool, registerWhoamiTool, };
14
18
  //# sourceMappingURL=index.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/tools/index.ts"],"names":[],"mappings":"AAGA,OAAO,EAAE,oBAAoB,EAAE,MAAM,gBAAgB,CAAC;AACtD,OAAO,EAAE,6BAA6B,EAAE,MAAM,0BAA0B,CAAC;AACzE,OAAO,EAAE,8BAA8B,EAAE,MAAM,2BAA2B,CAAC;AAC3E,OAAO,EAAE,uBAAuB,EAAE,MAAM,mBAAmB,CAAC;AAC5D,OAAO,EAAE,kBAAkB,EAAE,MAAM,aAAa,CAAC;AAEjD,MAAM,UAAU,gBAAgB,CAC5B,MAAiB,EACjB,aAA4B;IAE5B,oBAAoB,CAAC,MAAM,EAAE,aAAa,CAAC,CAAC;IAC5C,8BAA8B,CAAC,MAAM,EAAE,aAAa,CAAC,CAAC;IACtD,uBAAuB,CAAC,MAAM,EAAE,aAAa,CAAC,CAAC;IAC/C,6BAA6B,CAAC,MAAM,EAAE,aAAa,CAAC,CAAC;IACrD,kBAAkB,CAAC,MAAM,EAAE,aAAa,CAAC,CAAC;AAC9C,CAAC;AAED,OAAO,EACH,oBAAoB,EACpB,6BAA6B,EAC7B,8BAA8B,EAC9B,uBAAuB,EACvB,kBAAkB,GACrB,CAAC"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/tools/index.ts"],"names":[],"mappings":"AAGA,OAAO,EAAE,oBAAoB,EAAE,MAAM,gBAAgB,CAAC;AACtD,OAAO,EAAE,6BAA6B,EAAE,MAAM,0BAA0B,CAAC;AACzE,OAAO,EAAE,wBAAwB,EAAE,MAAM,qBAAqB,CAAC;AAC/D,OAAO,EAAE,8BAA8B,EAAE,MAAM,2BAA2B,CAAC;AAC3E,OAAO,EAAE,wBAAwB,EAAE,MAAM,oBAAoB,CAAC;AAC9D,OAAO,EAAE,uBAAuB,EAAE,MAAM,mBAAmB,CAAC;AAC5D,OAAO,EAAE,kBAAkB,EAAE,MAAM,aAAa,CAAC;AAEjD,MAAM,UAAU,gBAAgB,CAC5B,MAAiB,EACjB,aAA4B;IAE5B,oBAAoB,CAAC,MAAM,EAAE,aAAa,CAAC,CAAC;IAC5C,wBAAwB,CAAC,MAAM,EAAE,aAAa,CAAC,CAAC;IAChD,8BAA8B,CAAC,MAAM,EAAE,aAAa,CAAC,CAAC;IACtD,wBAAwB,CAAC,MAAM,EAAE,aAAa,CAAC,CAAC;IAChD,uBAAuB,CAAC,MAAM,EAAE,aAAa,CAAC,CAAC;IAC/C,6BAA6B,CAAC,MAAM,EAAE,aAAa,CAAC,CAAC;IACrD,kBAAkB,CAAC,MAAM,EAAE,aAAa,CAAC,CAAC;AAC9C,CAAC;AAED,OAAO,EACH,oBAAoB,EACpB,6BAA6B,EAC7B,wBAAwB,EACxB,8BAA8B,EAC9B,wBAAwB,EACxB,uBAAuB,EACvB,kBAAkB,GACrB,CAAC"}
@@ -0,0 +1,3 @@
1
+ import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
2
+ import type { RedmineClient } from "../redmine.js";
3
+ export declare function registerListMyIssuesTool(server: McpServer, redmineClient: RedmineClient): void;
@@ -0,0 +1,70 @@
1
+ import * as z from "zod";
2
+ export function registerListMyIssuesTool(server, redmineClient) {
3
+ server.registerTool("list-my-issues", {
4
+ title: "List My Redmine Issues",
5
+ description: `List all Redmine issues assigned to the current user.
6
+ Results are paginated - use limit and offset to fetch more.
7
+ IMPORTANT: When the user asks for issues for "this project" or similar:
8
+ 1. First check the project's CLAUDE.md for a Redmine or Planio project
9
+ mapping (e.g., "Redmine Project ID: 154" or "Planio Project: my-project")
10
+ 2. If no mapping exists, DO NOT guess the project ID from folder/repo names
11
+ 3. Instead, inform the user that no Redmine/Planio project is configured for
12
+ this codebase and suggest they add it to CLAUDE.md
13
+ 4. Offer to list all assigned issues instead, but wait for confirmation
14
+ IMPORTANT: Always present results directly in your response text so the user
15
+ can see them without expanding tool output.`,
16
+ inputSchema: {
17
+ statusId: z
18
+ .union([z.number(), z.enum(["open", "closed", "*"])])
19
+ .optional()
20
+ .describe("Filter by status: a status ID, 'open' for open issues, 'closed' for closed issues, or '*' for all (Redmine defaults to open when not specified)"),
21
+ projectId: z
22
+ .union([z.string(), z.number()])
23
+ .optional()
24
+ .describe("Filter by project ID or identifier (e.g., 'my-project' or 154)"),
25
+ limit: z
26
+ .number()
27
+ .optional()
28
+ .describe("Maximum number of issues to return (default 25)"),
29
+ offset: z
30
+ .number()
31
+ .optional()
32
+ .describe("Number of issues to skip for pagination"),
33
+ sort: z
34
+ .string()
35
+ .optional()
36
+ .describe("Sort field and direction, e.g., 'priority:desc', 'updated_on:desc', 'due_date:asc' (default: priority:desc,updated_on:desc)"),
37
+ },
38
+ }, async ({ statusId, projectId, limit, offset, sort }) => {
39
+ try {
40
+ const result = await redmineClient.listMyIssues({
41
+ statusId,
42
+ projectId,
43
+ limit,
44
+ offset,
45
+ sort,
46
+ });
47
+ return {
48
+ content: [
49
+ {
50
+ type: "text",
51
+ text: JSON.stringify(result, null, 2),
52
+ },
53
+ ],
54
+ };
55
+ }
56
+ catch (error) {
57
+ const message = error instanceof Error ? error.message : String(error);
58
+ return {
59
+ isError: true,
60
+ content: [
61
+ {
62
+ type: "text",
63
+ text: `Error listing issues: ${message}`,
64
+ },
65
+ ],
66
+ };
67
+ }
68
+ });
69
+ }
70
+ //# sourceMappingURL=list-my-issues.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"list-my-issues.js","sourceRoot":"","sources":["../../src/tools/list-my-issues.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,CAAC,MAAM,KAAK,CAAC;AAIzB,MAAM,UAAU,wBAAwB,CACpC,MAAiB,EACjB,aAA4B;IAE5B,MAAM,CAAC,YAAY,CACf,gBAAgB,EAChB;QACI,KAAK,EAAE,wBAAwB;QAC/B,WAAW,EAAE;;;;;;;;;;wDAU+B;QAC5C,WAAW,EAAE;YACT,QAAQ,EAAE,CAAC;iBACN,KAAK,CAAC,CAAC,CAAC,CAAC,MAAM,EAAE,EAAE,CAAC,CAAC,IAAI,CAAC,CAAC,MAAM,EAAE,QAAQ,EAAE,GAAG,CAAC,CAAC,CAAC,CAAC;iBACpD,QAAQ,EAAE;iBACV,QAAQ,CACL,iJAAiJ,CACpJ;YACL,SAAS,EAAE,CAAC;iBACP,KAAK,CAAC,CAAC,CAAC,CAAC,MAAM,EAAE,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,CAAC;iBAC/B,QAAQ,EAAE;iBACV,QAAQ,CACL,gEAAgE,CACnE;YACL,KAAK,EAAE,CAAC;iBACH,MAAM,EAAE;iBACR,QAAQ,EAAE;iBACV,QAAQ,CACL,iDAAiD,CACpD;YACL,MAAM,EAAE,CAAC;iBACJ,MAAM,EAAE;iBACR,QAAQ,EAAE;iBACV,QAAQ,CAAC,yCAAyC,CAAC;YACxD,IAAI,EAAE,CAAC;iBACF,MAAM,EAAE;iBACR,QAAQ,EAAE;iBACV,QAAQ,CACL,6HAA6H,CAChI;SACR;KACJ,EACD,KAAK,EAAE,EAAE,QAAQ,EAAE,SAAS,EAAE,KAAK,EAAE,MAAM,EAAE,IAAI,EAAE,EAAE,EAAE;QACnD,IAAI,CAAC;YACD,MAAM,MAAM,GAAG,MAAM,aAAa,CAAC,YAAY,CAAC;gBAC5C,QAAQ;gBACR,SAAS;gBACT,KAAK;gBACL,MAAM;gBACN,IAAI;aACP,CAAC,CAAC;YAEH,OAAO;gBACH,OAAO,EAAE;oBACL;wBACI,IAAI,EAAE,MAAe;wBACrB,IAAI,EAAE,IAAI,CAAC,SAAS,CAAC,MAAM,EAAE,IAAI,EAAE,CAAC,CAAC;qBACxC;iBACJ;aACJ,CAAC;QACN,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACb,MAAM,OAAO,GACT,KAAK,YAAY,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;YAC3D,OAAO;gBACH,OAAO,EAAE,IAAI;gBACb,OAAO,EAAE;oBACL;wBACI,IAAI,EAAE,MAAe;wBACrB,IAAI,EAAE,yBAAyB,OAAO,EAAE;qBAC3C;iBACJ;aACJ,CAAC;QACN,CAAC;IACL,CAAC,CACJ,CAAC;AACN,CAAC"}
@@ -0,0 +1,3 @@
1
+ import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
2
+ import type { RedmineClient } from "../redmine.js";
3
+ export declare function registerListProjectsTool(server: McpServer, redmineClient: RedmineClient): void;
@@ -0,0 +1,51 @@
1
+ import * as z from "zod";
2
+ export function registerListProjectsTool(server, redmineClient) {
3
+ server.registerTool("list-projects", {
4
+ title: "List Redmine Projects",
5
+ description: `List all Redmine/Planio projects the user has access to.
6
+ Returns project ID, identifier (slug), and name. Use this to find project
7
+ IDs for filtering issues or to help users set up CLAUDE.md project mappings.
8
+ IMPORTANT: Always present results directly in your response text so the
9
+ user can see them without expanding tool output. If the user asks for
10
+ specific projects (e.g., "list sks projects"), filter the results to show
11
+ only matching projects.`,
12
+ inputSchema: {
13
+ limit: z
14
+ .number()
15
+ .optional()
16
+ .describe("Maximum number of projects to return (default 100)"),
17
+ offset: z
18
+ .number()
19
+ .optional()
20
+ .describe("Number of projects to skip for pagination"),
21
+ },
22
+ }, async ({ limit, offset }) => {
23
+ try {
24
+ const result = await redmineClient.listProjects({
25
+ limit: limit ?? 100,
26
+ offset,
27
+ });
28
+ return {
29
+ content: [
30
+ {
31
+ type: "text",
32
+ text: JSON.stringify(result, null, 2),
33
+ },
34
+ ],
35
+ };
36
+ }
37
+ catch (error) {
38
+ const message = error instanceof Error ? error.message : String(error);
39
+ return {
40
+ isError: true,
41
+ content: [
42
+ {
43
+ type: "text",
44
+ text: `Error listing projects: ${message}`,
45
+ },
46
+ ],
47
+ };
48
+ }
49
+ });
50
+ }
51
+ //# sourceMappingURL=list-projects.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"list-projects.js","sourceRoot":"","sources":["../../src/tools/list-projects.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,CAAC,MAAM,KAAK,CAAC;AAIzB,MAAM,UAAU,wBAAwB,CACpC,MAAiB,EACjB,aAA4B;IAE5B,MAAM,CAAC,YAAY,CACf,eAAe,EACf;QACI,KAAK,EAAE,uBAAuB;QAC9B,WAAW,EAAE;;;;;;oCAMW;QACxB,WAAW,EAAE;YACT,KAAK,EAAE,CAAC;iBACH,MAAM,EAAE;iBACR,QAAQ,EAAE;iBACV,QAAQ,CACL,oDAAoD,CACvD;YACL,MAAM,EAAE,CAAC;iBACJ,MAAM,EAAE;iBACR,QAAQ,EAAE;iBACV,QAAQ,CAAC,2CAA2C,CAAC;SAC7D;KACJ,EACD,KAAK,EAAE,EAAE,KAAK,EAAE,MAAM,EAAE,EAAE,EAAE;QACxB,IAAI,CAAC;YACD,MAAM,MAAM,GAAG,MAAM,aAAa,CAAC,YAAY,CAAC;gBAC5C,KAAK,EAAE,KAAK,IAAI,GAAG;gBACnB,MAAM;aACT,CAAC,CAAC;YAEH,OAAO;gBACH,OAAO,EAAE;oBACL;wBACI,IAAI,EAAE,MAAe;wBACrB,IAAI,EAAE,IAAI,CAAC,SAAS,CAAC,MAAM,EAAE,IAAI,EAAE,CAAC,CAAC;qBACxC;iBACJ;aACJ,CAAC;QACN,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACb,MAAM,OAAO,GACT,KAAK,YAAY,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;YAC3D,OAAO;gBACH,OAAO,EAAE,IAAI;gBACb,OAAO,EAAE;oBACL;wBACI,IAAI,EAAE,MAAe;wBACrB,IAAI,EAAE,2BAA2B,OAAO,EAAE;qBAC7C;iBACJ;aACJ,CAAC;QACN,CAAC;IACL,CAAC,CACJ,CAAC;AACN,CAAC"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@thelabnyc/redmine-mcp",
3
- "version": "0.2.0",
3
+ "version": "0.3.0",
4
4
  "license": "ISC",
5
5
  "author": "thelab <thelabdev@thelab.co>",
6
6
  "repository": {