A Model Context Protocol (MCP) server that provides seamless integration between LLMs and Redmine project management. This server exposes Redmine's REST API as MCP tools, enabling AI assistants to manage issues, projects, time tracking, and more.
- Features
- Installation
- Configuration
- Available Tools
- Usage Examples
- Development
- Testing
- Permissions
- License
This server provides comprehensive access to Redmine's REST API through the following resource categories:
| Category | Operations | Since |
|---|---|---|
| Issues | List, Get, Create, Update, Delete, Watchers | 1.0 |
| Projects | List, Show, Create, Update, Archive, Delete | 1.0 |
| Users | List, Show, Create, Update, Delete | 1.1 |
| Time Entries | List, Show, Create, Update, Delete | 1.1 |
| Attachments | Upload, Download, Get, Update, Delete | 1.3 |
| Versions | List, Show, Create, Update, Delete | 1.3 |
| Issue Categories | List, Show, Create, Update, Delete | 1.3 |
| Issue Statuses | List | 1.3 |
| Trackers | List | 1.3 |
| Memberships | List, Show, Create, Update, Delete | 1.4 |
| Roles | List, Show | 1.4 |
| Enumerations | Priorities, Activities, Document Categories | 2.2 |
- Node.js 18 or higher
- npm 9 or higher
- Access to a Redmine server with REST API enabled
npm install -g mcp-server-redminegit clone https://github.com/yonaka15/mcp-server-redmine.git
cd mcp-server-redmine
npm install
npm run build- Log in to your Redmine instance
- Go to My Account (top right menu)
- Find API access key in the right sidebar
- Click Show to reveal your API key (or Reset to generate a new one)
Note: The REST API must be enabled by your Redmine administrator under Administration > Settings > API.
| Variable | Required | Description |
|---|---|---|
REDMINE_HOST |
Yes | Your Redmine server URL (e.g., https://redmine.example.com) |
REDMINE_API_KEY |
Yes | Your personal API access key |
Add to your Claude Desktop configuration file:
macOS: ~/Library/Application Support/Claude/claude_desktop_config.json
Windows: %APPDATA%\Claude\claude_desktop_config.json
{
"mcpServers": {
"redmine": {
"command": "npx",
"args": ["-y", "mcp-server-redmine"],
"env": {
"REDMINE_HOST": "https://your-redmine.example.com",
"REDMINE_API_KEY": "your-api-key-here"
}
}
}
}{
"mcpServers": {
"redmine": {
"command": "node",
"args": ["/path/to/mcp-server-redmine/dist/index.js"],
"env": {
"REDMINE_HOST": "https://your-redmine.example.com",
"REDMINE_API_KEY": "your-api-key-here"
}
}
}
}| Tool | Description |
|---|---|
list_issues |
Search and filter issues with pagination |
get_issue |
Get detailed issue information |
create_issue |
Create a new issue |
update_issue |
Update an existing issue |
delete_issue |
Permanently delete an issue |
add_issue_watcher |
Add a user as issue watcher |
remove_issue_watcher |
Remove a user from watchers |
| Tool | Description |
|---|---|
list_projects |
List all accessible projects |
show_project |
Get project details with trackers, categories |
create_project |
Create a new project |
update_project |
Update project settings |
archive_project |
Archive a project (read-only) |
unarchive_project |
Restore an archived project |
delete_project |
Permanently delete a project |
list_project_statuses |
Get allowed statuses for project/tracker |
| Tool | Description |
|---|---|
list_time_entries |
Search time entries with filters |
show_time_entry |
Get time entry details |
create_time_entry_for_project |
Log time against a project |
create_time_entry_for_issue |
Log time against an issue |
update_time_entry |
Update a time entry |
delete_time_entry |
Delete a time entry |
| Tool | Description |
|---|---|
list_users |
List all users |
show_user |
Get user details |
create_user |
Create a new user account |
update_user |
Update user information |
delete_user |
Delete a user account |
| Tool | Description |
|---|---|
upload_file |
Upload file from base64 content |
upload_file_from_path |
Upload file from local filesystem |
upload_file_from_clipboard |
Upload image from clipboard (Windows) |
get_attachment |
Get attachment metadata |
download_attachment |
Download attachment content |
update_attachment |
Update attachment filename/description |
delete_attachment |
Delete an attachment |
| Tool | Description |
|---|---|
list_versions |
List project versions |
show_version |
Get version details |
create_version |
Create a new version |
update_version |
Update version settings |
delete_version |
Delete a version |
| Tool | Description |
|---|---|
list_memberships |
List project members |
show_membership |
Get membership details |
create_membership |
Add user/group to project |
update_membership |
Change member roles |
delete_membership |
Remove member from project |
| Tool | Description |
|---|---|
list_issue_categories |
List project categories |
show_issue_category |
Get category details |
create_issue_category |
Create a new category |
update_issue_category |
Update category settings |
delete_issue_category |
Delete a category |
| Tool | Description |
|---|---|
list_issue_statuses |
Get all issue statuses |
list_trackers |
Get all trackers |
list_issue_priorities |
Get priority levels |
list_time_entry_activities |
Get activity types |
list_document_categories |
Get document categories |
list_roles |
Get all roles |
show_role |
Get role permissions |
List all open issues assigned to me in project "webapp"
The LLM will call:
{
"tool": "list_issues",
"arguments": {
"project_id": "webapp",
"status_id": "open",
"assigned_to_id": "me",
"limit": 25
}
}Show issues created in the last week
{
"tool": "list_issues",
"arguments": {
"created_on": ">=2024-01-20",
"sort": "created_on:desc",
"limit": 50
}
}Get issue #1234 with all comments and attachments
{
"tool": "get_issue",
"arguments": {
"id": 1234,
"include": "journals,attachments,watchers,relations"
}
}Create a bug report in project ID 5 for the login page
{
"tool": "create_issue",
"arguments": {
"project_id": 5,
"tracker_id": 1,
"subject": "Login page returns 500 error",
"description": "When submitting the login form with valid credentials, the server returns a 500 Internal Server Error.\n\n**Steps to reproduce:**\n1. Go to /login\n2. Enter valid username and password\n3. Click Submit\n\n**Expected:** Redirect to dashboard\n**Actual:** 500 error page",
"priority_id": 2,
"assigned_to_id": 10
}
}Close issue #1234 with a comment
{
"tool": "update_issue",
"arguments": {
"id": 1234,
"status_id": 5,
"notes": "Fixed in commit abc123. Deployed to production."
}
}Add user ID 15 as a watcher to issue #1234
{
"tool": "add_issue_watcher",
"arguments": {
"issue_id": 1234,
"user_id": 15
}
}Show me all active projects
{
"tool": "list_projects",
"arguments": {
"status": "1",
"include": "trackers,issue_categories"
}
}Create a new project called "Mobile App" under parent project ID 1
{
"tool": "create_project",
"arguments": {
"name": "Mobile App",
"identifier": "mobile-app",
"description": "Mobile application development project",
"parent_id": 1,
"is_public": false,
"enabled_module_names": ["issue_tracking", "time_tracking", "wiki", "repository"],
"tracker_ids": [1, 2, 3]
}
}Archive the old-website project
{
"tool": "archive_project",
"arguments": {
"id": "old-website"
}
}Log 2.5 hours on issue #1234 for development work
{
"tool": "create_time_entry_for_issue",
"arguments": {
"issue_id": 1234,
"hours": 2.5,
"activity_id": 9,
"comments": "Implemented user authentication feature"
}
}Log 1 hour on project "webapp" for a meeting
{
"tool": "create_time_entry_for_project",
"arguments": {
"project_id": "webapp",
"hours": 1,
"activity_id": 10,
"comments": "Sprint planning meeting",
"spent_on": "2024-01-25"
}
}Show my time entries for this week
{
"tool": "list_time_entries",
"arguments": {
"user_id": "me",
"from": "2024-01-22",
"to": "2024-01-26",
"limit": 100
}
}Upload the screenshot from my desktop
{
"tool": "upload_file_from_path",
"arguments": {
"file_path": "C:\\Users\\john\\Desktop\\screenshot.png"
}
}Response:
{
"token": "7167.ed1ccdb093229ca1bd0b043618d88743",
"filename": "screenshot.png"
}Create a bug with the uploaded screenshot
{
"tool": "create_issue",
"arguments": {
"project_id": 5,
"subject": "UI alignment issue on dashboard",
"description": "The chart is not aligned properly on the dashboard.",
"uploads": [
{
"token": "7167.ed1ccdb093229ca1bd0b043618d88743",
"filename": "screenshot.png",
"content_type": "image/png"
}
]
}
}Upload the image I just copied to clipboard
{
"tool": "upload_file_from_clipboard",
"arguments": {
"filename": "error-screenshot.png"
}
}Show me attachment #456
{
"tool": "download_attachment",
"arguments": {
"id": 456
}
}Note: Images are returned in a format viewable by Claude. Excel files are parsed and returned as JSON.
Create version 2.0.0 for project webapp with due date next month
{
"tool": "create_version",
"arguments": {
"project_id": "webapp",
"name": "2.0.0",
"description": "Major release with new features",
"status": "open",
"due_date": "2024-02-28",
"sharing": "none"
}
}Mark version 1.5.0 as closed
{
"tool": "update_version",
"arguments": {
"id": 15,
"status": "closed"
}
}Add user ID 20 to project webapp with Developer and Reporter roles
{
"tool": "create_membership",
"arguments": {
"project_id": "webapp",
"user_id": 20,
"role_ids": [4, 5]
}
}Change user's role to Manager only
{
"tool": "update_membership",
"arguments": {
"id": 123,
"role_ids": [3]
}
}Create an issue with custom field "Customer" set to "Acme Corp"
{
"tool": "create_issue",
"arguments": {
"project_id": 5,
"subject": "Feature request from customer",
"custom_fields": [
{
"id": 1,
"value": "Acme Corp"
},
{
"id": 2,
"value": "high"
}
]
}
}List issues where custom field 3 equals "urgent"
{
"tool": "list_issues",
"arguments": {
"cf_3": "urgent",
"limit": 25
}
}What issue statuses are available?
{
"tool": "list_issue_statuses",
"arguments": {}
}Show me the priority levels
{
"tool": "list_issue_priorities",
"arguments": {}
}What statuses can be used for bugs in project 5?
{
"tool": "list_project_statuses",
"arguments": {
"project_id": 5,
"tracker_id": 1
}
}.
├── src/
│ ├── index.ts # Entry point
│ ├── tools/ # MCP tool definitions
│ │ ├── issues.ts
│ │ ├── projects.ts
│ │ ├── attachments.ts
│ │ └── ...
│ ├── handlers/ # Tool implementation logic
│ │ ├── index.ts
│ │ ├── issues.ts
│ │ └── ...
│ ├── formatters/ # Response formatters
│ │ ├── issues.ts
│ │ └── ...
│ └── lib/
│ ├── client/ # Redmine API client
│ ├── types/ # TypeScript types & Zod schemas
│ └── config.ts # Configuration
├── docs/
│ └── adr/ # Architecture Decision Records
├── package.json
└── tsconfig.json
# Install dependencies
npm install
# Build TypeScript
npm run build
# Development mode with watch
npm run dev
# Start production server
npm start
# Run linting
npm run lint- Define the tool in
src/tools/<resource>.ts:
export const MY_NEW_TOOL: Tool = {
name: "my_new_tool",
description: "Description of what the tool does",
inputSchema: {
type: "object",
properties: {
param1: { type: "string", description: "Parameter description" }
},
required: ["param1"]
}
};- Export from
src/tools/index.ts:
export { MY_NEW_TOOL } from "./my_resource.js";- Implement handler in
src/handlers/<resource>.ts:
export function createMyResourceHandlers(context: HandlerContext) {
return {
my_new_tool: async (args: unknown) => {
// Implementation
}
};
}- Register handler in
src/handlers/index.ts
# Run all tests
npm test
# Run specific test file
npm test -- src/lib/__tests__/client/issues/get.test.ts
# Run tests matching pattern
npm test -- --testPathPattern="issues"Note: For data safety, only GET operations are included in automated tests.
The MCP Inspector provides a GUI and CLI for testing the server.
# Build the project
npm run build
# Set execute permission (Unix/macOS)
chmod +x dist/index.js
# Launch inspector
npx @modelcontextprotocol/inspector dist/index.js# Set environment variables
export REDMINE_API_KEY=your-api-key
export REDMINE_HOST=https://your-redmine.example.com
# List available tools
npx @modelcontextprotocol/inspector --cli \
-e REDMINE_API_KEY=$REDMINE_API_KEY \
-e REDMINE_HOST=$REDMINE_HOST \
node dist/index.js \
--method tools/list
# Call a specific tool
npx @modelcontextprotocol/inspector --cli \
-e REDMINE_API_KEY=$REDMINE_API_KEY \
-e REDMINE_HOST=$REDMINE_HOST \
node dist/index.js \
--method tools/call \
--tool-name list_issues \
--tool-arg limit=5 \
--tool-arg status_id=open# Test API connectivity
curl -H "X-Redmine-API-Key: $REDMINE_API_KEY" \
"$REDMINE_HOST/projects.json"The following operations require Redmine administrator privileges:
| Tool | Requirement |
|---|---|
list_users |
Admin |
create_user |
Admin |
update_user |
Admin |
delete_user |
Admin |
Most operations respect Redmine's permission system:
- Users can only see projects they have access to
- Issue operations require appropriate project roles
- Time entry operations may require specific permissions
For detailed permission information, see the Redmine API Documentation.
Connection Refused
- Verify Redmine server is running
- Check
REDMINE_HOSTURL is correct - Ensure REST API is enabled in Redmine settings
401 Unauthorized
- Verify
REDMINE_API_KEYis correct - Check API key hasn't expired or been revoked
403 Forbidden
- User lacks required permissions
- Some operations require admin privileges
404 Not Found
- Resource ID doesn't exist
- Project identifier is incorrect
Set environment variable for verbose logging:
export DEBUG=mcp:*MIT