@thelabnyc/redmine-mcp 0.1.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 +15 -0
- package/README.md +227 -0
- package/dist/cli.d.ts +2 -0
- package/dist/cli.js +13 -0
- package/dist/cli.js.map +1 -0
- package/dist/config.d.ts +5 -0
- package/dist/config.js +17 -0
- package/dist/config.js.map +1 -0
- package/dist/index.d.ts +5 -0
- package/dist/index.js +4 -0
- package/dist/index.js.map +1 -0
- package/dist/redmine.d.ts +188 -0
- package/dist/redmine.js +165 -0
- package/dist/redmine.js.map +1 -0
- package/dist/server.d.ts +9 -0
- package/dist/server.js +27 -0
- package/dist/server.js.map +1 -0
- package/dist/test-utils.d.ts +107 -0
- package/dist/test-utils.js +66 -0
- package/dist/test-utils.js.map +1 -0
- package/dist/tools/__tests__/get-issue.test.d.ts +1 -0
- package/dist/tools/__tests__/get-issue.test.js +204 -0
- package/dist/tools/__tests__/get-issue.test.js.map +1 -0
- package/dist/tools/__tests__/list-issue-statuses.test.d.ts +1 -0
- package/dist/tools/__tests__/list-issue-statuses.test.js +75 -0
- package/dist/tools/__tests__/list-issue-statuses.test.js.map +1 -0
- package/dist/tools/__tests__/list-project-members.test.d.ts +1 -0
- package/dist/tools/__tests__/list-project-members.test.js +109 -0
- package/dist/tools/__tests__/list-project-members.test.js.map +1 -0
- package/dist/tools/__tests__/update-issue.test.d.ts +1 -0
- package/dist/tools/__tests__/update-issue.test.js +455 -0
- package/dist/tools/__tests__/update-issue.test.js.map +1 -0
- package/dist/tools/__tests__/whoami.test.d.ts +1 -0
- package/dist/tools/__tests__/whoami.test.js +122 -0
- package/dist/tools/__tests__/whoami.test.js.map +1 -0
- package/dist/tools/get-issue.d.ts +3 -0
- package/dist/tools/get-issue.js +71 -0
- package/dist/tools/get-issue.js.map +1 -0
- package/dist/tools/index.d.ts +9 -0
- package/dist/tools/index.js +14 -0
- package/dist/tools/index.js.map +1 -0
- package/dist/tools/list-issue-statuses.d.ts +3 -0
- package/dist/tools/list-issue-statuses.js +32 -0
- package/dist/tools/list-issue-statuses.js.map +1 -0
- package/dist/tools/list-project-members.d.ts +3 -0
- package/dist/tools/list-project-members.js +48 -0
- package/dist/tools/list-project-members.js.map +1 -0
- package/dist/tools/update-issue.d.ts +3 -0
- package/dist/tools/update-issue.js +192 -0
- package/dist/tools/update-issue.js.map +1 -0
- package/dist/tools/utils.d.ts +12 -0
- package/dist/tools/utils.js +14 -0
- package/dist/tools/utils.js.map +1 -0
- package/dist/tools/whoami.d.ts +3 -0
- package/dist/tools/whoami.js +32 -0
- package/dist/tools/whoami.js.map +1 -0
- package/package.json +41 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
ISC License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2025 - 2025 thelab
|
|
4
|
+
|
|
5
|
+
Permission to use, copy, modify, and/or distribute this software for any
|
|
6
|
+
purpose with or without fee is hereby granted, provided that the above
|
|
7
|
+
copyright notice and this permission notice appear in all copies.
|
|
8
|
+
|
|
9
|
+
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH
|
|
10
|
+
REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
|
|
11
|
+
AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,
|
|
12
|
+
INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
|
|
13
|
+
LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
|
|
14
|
+
OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
|
|
15
|
+
PERFORMANCE OF THIS SOFTWARE.
|
package/README.md
ADDED
|
@@ -0,0 +1,227 @@
|
|
|
1
|
+
# @thelabnyc/redmine-mcp
|
|
2
|
+
|
|
3
|
+
An MCP (Model Context Protocol) server that allows AI agents like Claude to interact with Redmine project management data.
|
|
4
|
+
|
|
5
|
+
## Features
|
|
6
|
+
|
|
7
|
+
- Fetch issue details by ID, including subject, description, status, priority, and assignee
|
|
8
|
+
- Update issues: change status, assign users, add notes, and more
|
|
9
|
+
- Log time spent on issues with integrated time tracking
|
|
10
|
+
- List project members to find user IDs for assignments
|
|
11
|
+
- List available issue statuses to find valid status IDs
|
|
12
|
+
- Retrieve change history (journals) with every request
|
|
13
|
+
- Optionally include attachments, watchers, relations, and child issues
|
|
14
|
+
|
|
15
|
+
## Installation
|
|
16
|
+
|
|
17
|
+
```bash
|
|
18
|
+
npm install @thelabnyc/redmine-mcp
|
|
19
|
+
```
|
|
20
|
+
|
|
21
|
+
Or clone and build from source:
|
|
22
|
+
|
|
23
|
+
```bash
|
|
24
|
+
git clone https://gitlab.com/thelabnyc/redmine-mcp.git
|
|
25
|
+
cd redmine-mcp
|
|
26
|
+
npm install
|
|
27
|
+
npm run build
|
|
28
|
+
```
|
|
29
|
+
|
|
30
|
+
## Configuration
|
|
31
|
+
|
|
32
|
+
The server requires two environment variables:
|
|
33
|
+
|
|
34
|
+
| Variable | Description | Example |
|
|
35
|
+
| ----------------- | --------------------------------- | --------------------------- |
|
|
36
|
+
| `REDMINE_URL` | Base URL of your Redmine instance | `https://mycompany.plan.io` |
|
|
37
|
+
| `REDMINE_API_KEY` | Your Redmine API key | `abc123def456...` |
|
|
38
|
+
|
|
39
|
+
### Getting your Redmine API Key
|
|
40
|
+
|
|
41
|
+
1. Log into your Redmine instance
|
|
42
|
+
2. Go to **My Account** (click your name in the top right)
|
|
43
|
+
3. In the right sidebar, find **API access key**
|
|
44
|
+
4. Click **Show** to reveal your key, or **Reset** to generate a new one
|
|
45
|
+
|
|
46
|
+
## Usage with Claude Code
|
|
47
|
+
|
|
48
|
+
Add the server to your Claude Code configuration:
|
|
49
|
+
|
|
50
|
+
### Project-level configuration
|
|
51
|
+
|
|
52
|
+
Create or edit `.claude/settings.json` in your project:
|
|
53
|
+
|
|
54
|
+
```json
|
|
55
|
+
{
|
|
56
|
+
"mcpServers": {
|
|
57
|
+
"redmine": {
|
|
58
|
+
"command": "npx",
|
|
59
|
+
"args": ["@thelabnyc/redmine-mcp"],
|
|
60
|
+
"env": {
|
|
61
|
+
"REDMINE_URL": "https://your-instance.plan.io",
|
|
62
|
+
"REDMINE_API_KEY": "your-api-key-here"
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
```
|
|
68
|
+
|
|
69
|
+
### User-level configuration
|
|
70
|
+
|
|
71
|
+
Add to `~/.claude/settings.json` to make available across all projects:
|
|
72
|
+
|
|
73
|
+
```json
|
|
74
|
+
{
|
|
75
|
+
"mcpServers": {
|
|
76
|
+
"redmine": {
|
|
77
|
+
"command": "npx",
|
|
78
|
+
"args": ["@thelabnyc/redmine-mcp"],
|
|
79
|
+
"env": {
|
|
80
|
+
"REDMINE_URL": "https://your-instance.plan.io",
|
|
81
|
+
"REDMINE_API_KEY": "your-api-key-here"
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
```
|
|
87
|
+
|
|
88
|
+
### Using a local build
|
|
89
|
+
|
|
90
|
+
If you've cloned the repository:
|
|
91
|
+
|
|
92
|
+
```json
|
|
93
|
+
{
|
|
94
|
+
"mcpServers": {
|
|
95
|
+
"redmine": {
|
|
96
|
+
"command": "node",
|
|
97
|
+
"args": ["/path/to/redmine-mcp/dist/cli.js"],
|
|
98
|
+
"env": {
|
|
99
|
+
"REDMINE_URL": "https://your-instance.plan.io",
|
|
100
|
+
"REDMINE_API_KEY": "your-api-key-here"
|
|
101
|
+
}
|
|
102
|
+
}
|
|
103
|
+
}
|
|
104
|
+
}
|
|
105
|
+
```
|
|
106
|
+
|
|
107
|
+
## Available Tools
|
|
108
|
+
|
|
109
|
+
### get-issue
|
|
110
|
+
|
|
111
|
+
Fetch details about a Redmine issue by ID.
|
|
112
|
+
|
|
113
|
+
**Parameters:**
|
|
114
|
+
|
|
115
|
+
| Parameter | Type | Required | Description |
|
|
116
|
+
| -------------------- | ------- | -------- | ------------------------------------ |
|
|
117
|
+
| `issueId` | string | Yes | Issue ID (e.g., `#12345` or `12345`) |
|
|
118
|
+
| `includeAttachments` | boolean | No | Include file attachments |
|
|
119
|
+
| `includeWatchers` | boolean | No | Include watchers list |
|
|
120
|
+
| `includeRelations` | boolean | No | Include related issues |
|
|
121
|
+
| `includeChildren` | boolean | No | Include child issues |
|
|
122
|
+
|
|
123
|
+
**Note:** Change history (journals) is always included by default.
|
|
124
|
+
|
|
125
|
+
**Example usage in Claude:**
|
|
126
|
+
|
|
127
|
+
> "Look up Redmine issue #12345 and summarize the recent activity"
|
|
128
|
+
|
|
129
|
+
Or:
|
|
130
|
+
|
|
131
|
+
> "What's the status of issue 6789? Include any attachments."
|
|
132
|
+
|
|
133
|
+
### update-issue
|
|
134
|
+
|
|
135
|
+
Update a Redmine issue. Can change fields, add notes, and log time spent.
|
|
136
|
+
|
|
137
|
+
**Parameters:**
|
|
138
|
+
|
|
139
|
+
| Parameter | Type | Required | Description |
|
|
140
|
+
| ---------------- | ------- | -------- | ---------------------------------------------------- |
|
|
141
|
+
| `issueId` | string | Yes | Issue ID (e.g., `#12345` or `12345`) |
|
|
142
|
+
| `subject` | string | No | New issue subject/title |
|
|
143
|
+
| `description` | string | No | New issue description |
|
|
144
|
+
| `statusId` | number | No | Status ID to set |
|
|
145
|
+
| `priorityId` | number | No | Priority ID to set |
|
|
146
|
+
| `assignedToId` | number | No | User ID to assign (use 0 to unassign) |
|
|
147
|
+
| `trackerId` | number | No | Tracker ID to set |
|
|
148
|
+
| `parentIssueId` | number | No | Parent issue ID |
|
|
149
|
+
| `startDate` | string | No | Start date (YYYY-MM-DD format) |
|
|
150
|
+
| `dueDate` | string | No | Due date (YYYY-MM-DD format) |
|
|
151
|
+
| `doneRatio` | number | No | Percent done (0-100) |
|
|
152
|
+
| `estimatedHours` | number | No | Estimated hours for the issue |
|
|
153
|
+
| `notes` | string | No | Comment/note to add to the issue journal |
|
|
154
|
+
| `privateNotes` | boolean | No | Make the notes private |
|
|
155
|
+
| `logHours` | number | No | Hours to log as a time entry |
|
|
156
|
+
| `logActivityId` | number | No | Activity ID for time entry (uses default if omitted) |
|
|
157
|
+
| `logComments` | string | No | Comments for the time entry |
|
|
158
|
+
| `logSpentOn` | string | No | Date for time entry (YYYY-MM-DD, defaults to today) |
|
|
159
|
+
|
|
160
|
+
**Example usage in Claude:**
|
|
161
|
+
|
|
162
|
+
> "Update issue #12345 to status 2 and assign to user 5"
|
|
163
|
+
|
|
164
|
+
Or:
|
|
165
|
+
|
|
166
|
+
> "Add a note to issue #6789 saying 'Fixed the bug' and log 1.5 hours"
|
|
167
|
+
|
|
168
|
+
Or:
|
|
169
|
+
|
|
170
|
+
> "Mark issue #12345 as 75% done and log 2 hours of development time"
|
|
171
|
+
|
|
172
|
+
### list-project-members
|
|
173
|
+
|
|
174
|
+
List all members of a Redmine project. Use this to find user IDs for assigning issues.
|
|
175
|
+
|
|
176
|
+
**Parameters:**
|
|
177
|
+
|
|
178
|
+
| Parameter | Type | Required | Description |
|
|
179
|
+
| ----------- | ------ | -------- | ---------------------------------------------------- |
|
|
180
|
+
| `projectId` | string | Yes | Project ID or identifier (e.g., `my-project` or `1`) |
|
|
181
|
+
| `limit` | number | No | Maximum number of members to return (default 25) |
|
|
182
|
+
| `offset` | number | No | Number of members to skip for pagination |
|
|
183
|
+
|
|
184
|
+
**Example usage in Claude:**
|
|
185
|
+
|
|
186
|
+
> "List all members of the 'my-project' project"
|
|
187
|
+
|
|
188
|
+
Or:
|
|
189
|
+
|
|
190
|
+
> "Who can I assign issues to in project #1?"
|
|
191
|
+
|
|
192
|
+
### list-issue-statuses
|
|
193
|
+
|
|
194
|
+
List all available issue statuses. Use this to find valid status IDs when updating issues.
|
|
195
|
+
|
|
196
|
+
**Parameters:** None
|
|
197
|
+
|
|
198
|
+
**Example usage in Claude:**
|
|
199
|
+
|
|
200
|
+
> "What statuses can I set for issues?"
|
|
201
|
+
|
|
202
|
+
Or:
|
|
203
|
+
|
|
204
|
+
> "List the available issue statuses so I can update issue #123"
|
|
205
|
+
|
|
206
|
+
## Development
|
|
207
|
+
|
|
208
|
+
```bash
|
|
209
|
+
# Install dependencies
|
|
210
|
+
npm install
|
|
211
|
+
|
|
212
|
+
# Run tests
|
|
213
|
+
npm test
|
|
214
|
+
|
|
215
|
+
# Run tests in watch mode
|
|
216
|
+
npm run test:watch
|
|
217
|
+
|
|
218
|
+
# Build
|
|
219
|
+
npm run build
|
|
220
|
+
|
|
221
|
+
# Lint
|
|
222
|
+
npm run lint
|
|
223
|
+
```
|
|
224
|
+
|
|
225
|
+
## License
|
|
226
|
+
|
|
227
|
+
ISC
|
package/dist/cli.d.ts
ADDED
package/dist/cli.js
ADDED
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
import { startServer } from "./server.js";
|
|
3
|
+
async function main() {
|
|
4
|
+
try {
|
|
5
|
+
await startServer();
|
|
6
|
+
}
|
|
7
|
+
catch (error) {
|
|
8
|
+
console.error("Failed to start Redmine MCP server:", error);
|
|
9
|
+
process.exit(1);
|
|
10
|
+
}
|
|
11
|
+
}
|
|
12
|
+
void main();
|
|
13
|
+
//# sourceMappingURL=cli.js.map
|
package/dist/cli.js.map
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"cli.js","sourceRoot":"","sources":["../src/cli.ts"],"names":[],"mappings":";AACA,OAAO,EAAE,WAAW,EAAE,MAAM,aAAa,CAAC;AAE1C,KAAK,UAAU,IAAI;IACf,IAAI,CAAC;QACD,MAAM,WAAW,EAAE,CAAC;IACxB,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACb,OAAO,CAAC,KAAK,CAAC,qCAAqC,EAAE,KAAK,CAAC,CAAC;QAC5D,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IACpB,CAAC;AACL,CAAC;AAED,KAAK,IAAI,EAAE,CAAC"}
|
package/dist/config.d.ts
ADDED
package/dist/config.js
ADDED
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
export function getConfig() {
|
|
2
|
+
const redmineUrl = process.env.REDMINE_URL;
|
|
3
|
+
const redmineApiKey = process.env.REDMINE_API_KEY;
|
|
4
|
+
if (!redmineUrl) {
|
|
5
|
+
throw new Error("REDMINE_URL environment variable is required");
|
|
6
|
+
}
|
|
7
|
+
if (!redmineApiKey) {
|
|
8
|
+
throw new Error("REDMINE_API_KEY environment variable is required");
|
|
9
|
+
}
|
|
10
|
+
// Remove trailing slash if present
|
|
11
|
+
const normalizedUrl = redmineUrl.replace(/\/$/, "");
|
|
12
|
+
return {
|
|
13
|
+
redmineUrl: normalizedUrl,
|
|
14
|
+
redmineApiKey,
|
|
15
|
+
};
|
|
16
|
+
}
|
|
17
|
+
//# sourceMappingURL=config.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"config.js","sourceRoot":"","sources":["../src/config.ts"],"names":[],"mappings":"AAKA,MAAM,UAAU,SAAS;IACrB,MAAM,UAAU,GAAG,OAAO,CAAC,GAAG,CAAC,WAAW,CAAC;IAC3C,MAAM,aAAa,GAAG,OAAO,CAAC,GAAG,CAAC,eAAe,CAAC;IAElD,IAAI,CAAC,UAAU,EAAE,CAAC;QACd,MAAM,IAAI,KAAK,CAAC,8CAA8C,CAAC,CAAC;IACpE,CAAC;IACD,IAAI,CAAC,aAAa,EAAE,CAAC;QACjB,MAAM,IAAI,KAAK,CAAC,kDAAkD,CAAC,CAAC;IACxE,CAAC;IAED,mCAAmC;IACnC,MAAM,aAAa,GAAG,UAAU,CAAC,OAAO,CAAC,KAAK,EAAE,EAAE,CAAC,CAAC;IAEpD,OAAO;QACH,UAAU,EAAE,aAAa;QACzB,aAAa;KAChB,CAAC;AACN,CAAC"}
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
export { createServer, startServer } from "./server.js";
|
|
2
|
+
export { getConfig } from "./config.js";
|
|
3
|
+
export type { Config } from "./config.js";
|
|
4
|
+
export { RedmineClient } from "./redmine.js";
|
|
5
|
+
export type { RedmineIssue, RedmineJournal, RedmineAttachment, RedmineUser, RedmineProject, RedmineTracker, RedmineStatus, RedminePriority, GetIssueOptions, UpdateIssueData, CreateTimeEntryData, RedmineTimeEntry, RedmineActivity, RedmineMembership, ListProjectMembersOptions, RedmineIssueStatusDetail, RedmineCurrentUser, RedmineCustomField, RedmineJournalDetail, RedmineWatcher, RedmineRelation, } from "./redmine.js";
|
package/dist/index.js
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,WAAW,EAAE,MAAM,aAAa,CAAC;AACxD,OAAO,EAAE,SAAS,EAAE,MAAM,aAAa,CAAC;AAExC,OAAO,EAAE,aAAa,EAAE,MAAM,cAAc,CAAC"}
|
|
@@ -0,0 +1,188 @@
|
|
|
1
|
+
import type { Config } from "./config.js";
|
|
2
|
+
export interface RedmineUser {
|
|
3
|
+
id: number;
|
|
4
|
+
name: string;
|
|
5
|
+
}
|
|
6
|
+
export interface RedmineCustomField {
|
|
7
|
+
id: number;
|
|
8
|
+
name: string;
|
|
9
|
+
value: string | string[];
|
|
10
|
+
}
|
|
11
|
+
export interface RedmineCurrentUser {
|
|
12
|
+
id: number;
|
|
13
|
+
login: string;
|
|
14
|
+
firstname: string;
|
|
15
|
+
lastname: string;
|
|
16
|
+
mail: string;
|
|
17
|
+
created_on: string;
|
|
18
|
+
updated_on?: string;
|
|
19
|
+
last_login_on?: string;
|
|
20
|
+
passwd_changed_on?: string;
|
|
21
|
+
avatar_url?: string;
|
|
22
|
+
status: number;
|
|
23
|
+
custom_fields?: RedmineCustomField[];
|
|
24
|
+
}
|
|
25
|
+
export interface RedmineProject {
|
|
26
|
+
id: number;
|
|
27
|
+
name: string;
|
|
28
|
+
}
|
|
29
|
+
export interface RedmineTracker {
|
|
30
|
+
id: number;
|
|
31
|
+
name: string;
|
|
32
|
+
}
|
|
33
|
+
export interface RedmineStatus {
|
|
34
|
+
id: number;
|
|
35
|
+
name: string;
|
|
36
|
+
}
|
|
37
|
+
export interface RedminePriority {
|
|
38
|
+
id: number;
|
|
39
|
+
name: string;
|
|
40
|
+
}
|
|
41
|
+
export interface RedmineIssueStatusDetail {
|
|
42
|
+
id: number;
|
|
43
|
+
name: string;
|
|
44
|
+
is_closed: boolean;
|
|
45
|
+
}
|
|
46
|
+
export interface RedmineJournalDetail {
|
|
47
|
+
property: string;
|
|
48
|
+
name: string;
|
|
49
|
+
old_value?: string;
|
|
50
|
+
new_value?: string;
|
|
51
|
+
}
|
|
52
|
+
export interface RedmineJournal {
|
|
53
|
+
id: number;
|
|
54
|
+
user: RedmineUser;
|
|
55
|
+
notes: string;
|
|
56
|
+
created_on: string;
|
|
57
|
+
details: RedmineJournalDetail[];
|
|
58
|
+
}
|
|
59
|
+
export interface RedmineAttachment {
|
|
60
|
+
id: number;
|
|
61
|
+
filename: string;
|
|
62
|
+
filesize: number;
|
|
63
|
+
content_type: string;
|
|
64
|
+
description?: string;
|
|
65
|
+
author: RedmineUser;
|
|
66
|
+
created_on: string;
|
|
67
|
+
}
|
|
68
|
+
export interface RedmineWatcher {
|
|
69
|
+
id: number;
|
|
70
|
+
name: string;
|
|
71
|
+
}
|
|
72
|
+
export interface RedmineRelation {
|
|
73
|
+
id: number;
|
|
74
|
+
issue_id: number;
|
|
75
|
+
issue_to_id: number;
|
|
76
|
+
relation_type: string;
|
|
77
|
+
delay?: number;
|
|
78
|
+
}
|
|
79
|
+
export interface RedmineIssue {
|
|
80
|
+
id: number;
|
|
81
|
+
project: RedmineProject;
|
|
82
|
+
tracker: RedmineTracker;
|
|
83
|
+
status: RedmineStatus;
|
|
84
|
+
priority: RedminePriority;
|
|
85
|
+
author: RedmineUser;
|
|
86
|
+
assigned_to?: RedmineUser;
|
|
87
|
+
subject: string;
|
|
88
|
+
description?: string;
|
|
89
|
+
start_date?: string;
|
|
90
|
+
due_date?: string;
|
|
91
|
+
done_ratio: number;
|
|
92
|
+
estimated_hours?: number;
|
|
93
|
+
created_on: string;
|
|
94
|
+
updated_on: string;
|
|
95
|
+
journals?: RedmineJournal[];
|
|
96
|
+
attachments?: RedmineAttachment[];
|
|
97
|
+
watchers?: RedmineWatcher[];
|
|
98
|
+
relations?: RedmineRelation[];
|
|
99
|
+
children?: RedmineIssue[];
|
|
100
|
+
}
|
|
101
|
+
export interface GetIssueOptions {
|
|
102
|
+
includeAttachments?: boolean;
|
|
103
|
+
includeWatchers?: boolean;
|
|
104
|
+
includeRelations?: boolean;
|
|
105
|
+
includeChildren?: boolean;
|
|
106
|
+
}
|
|
107
|
+
export interface UpdateIssueData {
|
|
108
|
+
subject?: string;
|
|
109
|
+
description?: string;
|
|
110
|
+
status_id?: number;
|
|
111
|
+
priority_id?: number;
|
|
112
|
+
assigned_to_id?: number;
|
|
113
|
+
tracker_id?: number;
|
|
114
|
+
parent_issue_id?: number;
|
|
115
|
+
start_date?: string;
|
|
116
|
+
due_date?: string;
|
|
117
|
+
done_ratio?: number;
|
|
118
|
+
estimated_hours?: number;
|
|
119
|
+
notes?: string;
|
|
120
|
+
private_notes?: boolean;
|
|
121
|
+
}
|
|
122
|
+
export interface CreateTimeEntryData {
|
|
123
|
+
issue_id: number;
|
|
124
|
+
hours: number;
|
|
125
|
+
activity_id?: number;
|
|
126
|
+
spent_on?: string;
|
|
127
|
+
comments?: string;
|
|
128
|
+
}
|
|
129
|
+
export interface RedmineTimeEntry {
|
|
130
|
+
id: number;
|
|
131
|
+
project: RedmineProject;
|
|
132
|
+
issue?: {
|
|
133
|
+
id: number;
|
|
134
|
+
};
|
|
135
|
+
user: RedmineUser;
|
|
136
|
+
activity: {
|
|
137
|
+
id: number;
|
|
138
|
+
name: string;
|
|
139
|
+
};
|
|
140
|
+
hours: number;
|
|
141
|
+
comments?: string;
|
|
142
|
+
spent_on: string;
|
|
143
|
+
created_on: string;
|
|
144
|
+
updated_on: string;
|
|
145
|
+
}
|
|
146
|
+
export interface RedmineActivity {
|
|
147
|
+
id: number;
|
|
148
|
+
name: string;
|
|
149
|
+
is_default: boolean;
|
|
150
|
+
}
|
|
151
|
+
export interface RedmineMembership {
|
|
152
|
+
id: number;
|
|
153
|
+
project: RedmineProject;
|
|
154
|
+
user?: RedmineUser;
|
|
155
|
+
group?: {
|
|
156
|
+
id: number;
|
|
157
|
+
name: string;
|
|
158
|
+
};
|
|
159
|
+
roles: Array<{
|
|
160
|
+
id: number;
|
|
161
|
+
name: string;
|
|
162
|
+
inherited?: boolean;
|
|
163
|
+
}>;
|
|
164
|
+
}
|
|
165
|
+
export interface ListProjectMembersOptions {
|
|
166
|
+
limit?: number;
|
|
167
|
+
offset?: number;
|
|
168
|
+
}
|
|
169
|
+
export declare class RedmineClient {
|
|
170
|
+
private readonly config;
|
|
171
|
+
constructor(config: Config);
|
|
172
|
+
/**
|
|
173
|
+
* Extract error details from a failed response body
|
|
174
|
+
*/
|
|
175
|
+
private extractErrorDetails;
|
|
176
|
+
getIssue(issueId: number, options?: GetIssueOptions): Promise<RedmineIssue>;
|
|
177
|
+
updateIssue(issueId: number, data: UpdateIssueData): Promise<RedmineIssue>;
|
|
178
|
+
createTimeEntry(data: CreateTimeEntryData): Promise<RedmineTimeEntry>;
|
|
179
|
+
getTimeEntryActivities(): Promise<RedmineActivity[]>;
|
|
180
|
+
listProjectMembers(projectId: string | number, options?: ListProjectMembersOptions): Promise<{
|
|
181
|
+
memberships: RedmineMembership[];
|
|
182
|
+
total_count: number;
|
|
183
|
+
offset: number;
|
|
184
|
+
limit: number;
|
|
185
|
+
}>;
|
|
186
|
+
listIssueStatuses(): Promise<RedmineIssueStatusDetail[]>;
|
|
187
|
+
getCurrentUser(): Promise<RedmineCurrentUser>;
|
|
188
|
+
}
|
package/dist/redmine.js
ADDED
|
@@ -0,0 +1,165 @@
|
|
|
1
|
+
export class RedmineClient {
|
|
2
|
+
config;
|
|
3
|
+
constructor(config) {
|
|
4
|
+
this.config = config;
|
|
5
|
+
}
|
|
6
|
+
/**
|
|
7
|
+
* Extract error details from a failed response body
|
|
8
|
+
*/
|
|
9
|
+
async extractErrorDetails(response) {
|
|
10
|
+
try {
|
|
11
|
+
const body = (await response.json());
|
|
12
|
+
if (body.errors && Array.isArray(body.errors)) {
|
|
13
|
+
return ` - ${body.errors.join(", ")}`;
|
|
14
|
+
}
|
|
15
|
+
return "";
|
|
16
|
+
}
|
|
17
|
+
catch {
|
|
18
|
+
// Response body is not JSON or couldn't be parsed
|
|
19
|
+
return "";
|
|
20
|
+
}
|
|
21
|
+
}
|
|
22
|
+
async getIssue(issueId, options = {}) {
|
|
23
|
+
// Build include params - journals always included
|
|
24
|
+
const includes = ["journals"];
|
|
25
|
+
if (options.includeAttachments)
|
|
26
|
+
includes.push("attachments");
|
|
27
|
+
if (options.includeWatchers)
|
|
28
|
+
includes.push("watchers");
|
|
29
|
+
if (options.includeRelations)
|
|
30
|
+
includes.push("relations");
|
|
31
|
+
if (options.includeChildren)
|
|
32
|
+
includes.push("children");
|
|
33
|
+
const includeParam = includes.join(",");
|
|
34
|
+
const url = `${this.config.redmineUrl}/issues/${issueId}.json?include=${includeParam}`;
|
|
35
|
+
const response = await fetch(url, {
|
|
36
|
+
method: "GET",
|
|
37
|
+
headers: {
|
|
38
|
+
"X-Redmine-API-Key": this.config.redmineApiKey,
|
|
39
|
+
"Accept": "application/json",
|
|
40
|
+
},
|
|
41
|
+
});
|
|
42
|
+
if (!response.ok) {
|
|
43
|
+
const errorDetails = await this.extractErrorDetails(response);
|
|
44
|
+
throw new Error(`Failed to fetch issue ${issueId}: ${response.status} ${response.statusText}${errorDetails}`);
|
|
45
|
+
}
|
|
46
|
+
const data = (await response.json());
|
|
47
|
+
return data.issue;
|
|
48
|
+
}
|
|
49
|
+
async updateIssue(issueId, data) {
|
|
50
|
+
const url = `${this.config.redmineUrl}/issues/${issueId}.json`;
|
|
51
|
+
const response = await fetch(url, {
|
|
52
|
+
method: "PUT",
|
|
53
|
+
headers: {
|
|
54
|
+
"X-Redmine-API-Key": this.config.redmineApiKey,
|
|
55
|
+
"Accept": "application/json",
|
|
56
|
+
"Content-Type": "application/json",
|
|
57
|
+
},
|
|
58
|
+
body: JSON.stringify({ issue: data }),
|
|
59
|
+
});
|
|
60
|
+
if (!response.ok) {
|
|
61
|
+
const errorDetails = await this.extractErrorDetails(response);
|
|
62
|
+
throw new Error(`Failed to update issue ${issueId}: ${response.status} ${response.statusText}${errorDetails}`);
|
|
63
|
+
}
|
|
64
|
+
// Redmine PUT returns empty body on success, so fetch the updated issue
|
|
65
|
+
return this.getIssue(issueId);
|
|
66
|
+
}
|
|
67
|
+
async createTimeEntry(data) {
|
|
68
|
+
const url = `${this.config.redmineUrl}/time_entries.json`;
|
|
69
|
+
const response = await fetch(url, {
|
|
70
|
+
method: "POST",
|
|
71
|
+
headers: {
|
|
72
|
+
"X-Redmine-API-Key": this.config.redmineApiKey,
|
|
73
|
+
"Accept": "application/json",
|
|
74
|
+
"Content-Type": "application/json",
|
|
75
|
+
},
|
|
76
|
+
body: JSON.stringify({ time_entry: data }),
|
|
77
|
+
});
|
|
78
|
+
if (!response.ok) {
|
|
79
|
+
const errorDetails = await this.extractErrorDetails(response);
|
|
80
|
+
throw new Error(`Failed to create time entry: ${response.status} ${response.statusText}${errorDetails}`);
|
|
81
|
+
}
|
|
82
|
+
const result = (await response.json());
|
|
83
|
+
return result.time_entry;
|
|
84
|
+
}
|
|
85
|
+
async getTimeEntryActivities() {
|
|
86
|
+
const url = `${this.config.redmineUrl}/enumerations/time_entry_activities.json`;
|
|
87
|
+
const response = await fetch(url, {
|
|
88
|
+
method: "GET",
|
|
89
|
+
headers: {
|
|
90
|
+
"X-Redmine-API-Key": this.config.redmineApiKey,
|
|
91
|
+
"Accept": "application/json",
|
|
92
|
+
},
|
|
93
|
+
});
|
|
94
|
+
if (!response.ok) {
|
|
95
|
+
const errorDetails = await this.extractErrorDetails(response);
|
|
96
|
+
throw new Error(`Failed to fetch time entry activities: ${response.status} ${response.statusText}${errorDetails}`);
|
|
97
|
+
}
|
|
98
|
+
const data = (await response.json());
|
|
99
|
+
return data.time_entry_activities;
|
|
100
|
+
}
|
|
101
|
+
async listProjectMembers(projectId, options = {}) {
|
|
102
|
+
const params = new URLSearchParams();
|
|
103
|
+
if (options.limit !== undefined) {
|
|
104
|
+
params.set("limit", String(options.limit));
|
|
105
|
+
}
|
|
106
|
+
if (options.offset !== undefined) {
|
|
107
|
+
params.set("offset", String(options.offset));
|
|
108
|
+
}
|
|
109
|
+
const queryString = params.toString();
|
|
110
|
+
const url = `${this.config.redmineUrl}/projects/${projectId}/memberships.json${queryString ? `?${queryString}` : ""}`;
|
|
111
|
+
const response = await fetch(url, {
|
|
112
|
+
method: "GET",
|
|
113
|
+
headers: {
|
|
114
|
+
"X-Redmine-API-Key": this.config.redmineApiKey,
|
|
115
|
+
"Accept": "application/json",
|
|
116
|
+
},
|
|
117
|
+
});
|
|
118
|
+
if (!response.ok) {
|
|
119
|
+
const errorDetails = await this.extractErrorDetails(response);
|
|
120
|
+
throw new Error(`Failed to fetch project members: ${response.status} ${response.statusText}${errorDetails}`);
|
|
121
|
+
}
|
|
122
|
+
const data = (await response.json());
|
|
123
|
+
return {
|
|
124
|
+
memberships: data.memberships,
|
|
125
|
+
total_count: data.total_count,
|
|
126
|
+
offset: data.offset,
|
|
127
|
+
limit: data.limit,
|
|
128
|
+
};
|
|
129
|
+
}
|
|
130
|
+
async listIssueStatuses() {
|
|
131
|
+
const url = `${this.config.redmineUrl}/issue_statuses.json`;
|
|
132
|
+
const response = await fetch(url, {
|
|
133
|
+
method: "GET",
|
|
134
|
+
headers: {
|
|
135
|
+
"X-Redmine-API-Key": this.config.redmineApiKey,
|
|
136
|
+
"Accept": "application/json",
|
|
137
|
+
},
|
|
138
|
+
});
|
|
139
|
+
if (!response.ok) {
|
|
140
|
+
const errorDetails = await this.extractErrorDetails(response);
|
|
141
|
+
throw new Error(`Failed to fetch issue statuses: ${response.status} ${response.statusText}${errorDetails}`);
|
|
142
|
+
}
|
|
143
|
+
const data = (await response.json());
|
|
144
|
+
return data.issue_statuses;
|
|
145
|
+
}
|
|
146
|
+
async getCurrentUser() {
|
|
147
|
+
const url = `${this.config.redmineUrl}/users/current.json`;
|
|
148
|
+
const response = await fetch(url, {
|
|
149
|
+
method: "GET",
|
|
150
|
+
headers: {
|
|
151
|
+
"X-Redmine-API-Key": this.config.redmineApiKey,
|
|
152
|
+
"Accept": "application/json",
|
|
153
|
+
},
|
|
154
|
+
});
|
|
155
|
+
if (!response.ok) {
|
|
156
|
+
const errorDetails = await this.extractErrorDetails(response);
|
|
157
|
+
throw new Error(`Failed to fetch current user: ${response.status} ${response.statusText}${errorDetails}`);
|
|
158
|
+
}
|
|
159
|
+
const data = (await response.json());
|
|
160
|
+
// Exclude api_key from response - agent doesn't need it
|
|
161
|
+
const { api_key: _, ...user } = data.user;
|
|
162
|
+
return user;
|
|
163
|
+
}
|
|
164
|
+
}
|
|
165
|
+
//# sourceMappingURL=redmine.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"redmine.js","sourceRoot":"","sources":["../src/redmine.ts"],"names":[],"mappings":"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"}
|
package/dist/server.d.ts
ADDED
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
|
|
2
|
+
/**
|
|
3
|
+
* Creates and configures the Redmine MCP server instance
|
|
4
|
+
*/
|
|
5
|
+
export declare function createServer(): McpServer;
|
|
6
|
+
/**
|
|
7
|
+
* Starts the MCP server with stdio transport
|
|
8
|
+
*/
|
|
9
|
+
export declare function startServer(): Promise<void>;
|