[Cotlet](https://cotlet.dev/index.md) · [Integrations](https://cotlet.dev/integrations.md) · [How it works](https://cotlet.dev/how-it-works.md) · [Use cases](https://cotlet.dev/use-cases.md) · [Security](https://cotlet.dev/security.md) · [For developers](https://cotlet.dev/for-developers.md) · [For automation agencies](https://cotlet.dev/for-agencies.md) · [Blog](https://cotlet.dev/blog.md) · [API docs](https://cotlet.dev/docs.md) · [Help center](https://cotlet.dev/help.md) · [Changelog](https://cotlet.dev/changelog.md) · [Contact](https://cotlet.dev/contact.md) · [Pricing](https://cotlet.dev/pricing.md) · [Sign up](https://cotlet.dev/signup)

# Redmine API and MCP server

> Yes, Redmine has a REST API (checked 16 Oct 2026). Issues, projects, users and time entries are marked Stable, in JSON or XML, with an API key per user; an administrator must first turn on Enable REST API under Administration > Settings > API. Redmine has no official MCP server: feature request #42689 on redmine.org is still open with status New.

Open-source project management and issue tracking: projects, issues with trackers and statuses, time tracking and a wiki. Teams run it on their own server or on a host such as Planio.

## What is the Redmine API?

Cotlet's Redmine API exposes 12 endpoints for your own Redmine account: list projects, get project, list project members, list issue options, list issues, get issue, list time entries, create issue, update issue, add comment, log time and update time entry. The list_projects endpoint returns projects you can see, with ID, identifier and visibility. Each endpoint takes simple JSON inputs like project_id, limit or offset and works both as an operation of the redmine_read or redmine_write MCP tool for agents and as a REST call for scripts.

- **Category:** [Productivity & teams](https://cotlet.dev/integrations/category/productivity-teams.md)
- **Endpoints:** 12 (7 read, 5 write)
- **Updated:** 2026-10-21

Yes, Redmine has a REST API (checked 16 Oct 2026). Cotlet is a hosted MCP server and REST API for Redmine with 12 endpoints (7 read, 5 write): you sign in once in your own cloud browser, your AI agent does the work.

## Does Redmine have an official API?

Yes, Redmine has a REST API (checked 16 Oct 2026). Issues, projects, users and time entries are marked Stable, in JSON or XML, with an API key per user; an administrator must first turn on Enable REST API under Administration > Settings > API. Redmine has no official MCP server: feature request #42689 on redmine.org is still open with status New.

| Task | Redmine official | Cotlet |
|---|---|---|
| List projects with their trackers and time-entry activities | Yes: Projects API; include=trackers,time_entry_activities | Yes |
| List and filter issues (mine, open, by project) | Yes: Issues API; only open issues by default, 100 per page at most | Yes |
| Read one issue with its history | Yes: include=journals | Yes |
| Create an issue | Yes: Assignee by user ID only; no assigning by name | Yes |
| Update an issue: status, assignee, priority, comment | Yes: notes and private_notes on PUT /issues/ID | Yes |
| Log and correct time on an issue | Yes: Time Entries API; hours required, activity required unless a default exists | Yes |
| List who is on a project | Partly: Memberships API is marked Alpha | Yes |
| Use all of this from an AI agent over MCP | No: No official MCP server | Yes |

Sources: [Redmine Guide: REST API](https://www.redmine.org/projects/redmine/wiki/rest_api), [Redmine Guide: REST API, Issues](https://www.redmine.org/projects/redmine/wiki/Rest_Issues), [Redmine Guide: REST API, Time Entries](https://www.redmine.org/projects/redmine/wiki/Rest_TimeEntries), [Redmine feature request #42689: MCP Server](https://www.redmine.org/issues/42689)

## For AI agents

```text
Yes, Redmine has a REST API (checked 16 Oct 2026). Issues, projects, users and time entries are marked Stable, in JSON or XML, with an API key per user; an administrator must first turn on Enable REST API under Administration > Settings > API. Redmine has no official MCP server: feature request #42689 on redmine.org is still open with status New.
Cotlet provides a hosted MCP server and REST API for Redmine: 12 tools (7 read, 5 write).
Access       Sign up at https://cotlet.dev/app/signup?app=redmine, then request the app and create API keys in the Cotlet console.

MCP server   https://cotlet.dev/mcp/v1
MCP tools    redmine_read, redmine_write, reads and writes apart; call one with {"operation": "<operation>", "arguments": {...}}
REST base    https://cotlet.dev/api/v1/redmine, each operation at its own route, e.g. POST /api/v1/redmine/projects/{project_id}/issues
Auth         Authorization: Bearer <COTLET_API_KEY>. Listing endpoints and schemas needs no key; calling an endpoint needs one. Over MCP the input schemas come with sign-in.
Operations   list_projects, get_project, list_project_members, list_issue_options, list_issues, get_issue, list_time_entries, create_issue, update_issue, add_comment, log_time, update_time_entry
Confirm      create_issue, update_issue, add_comment (by default the user approves each call; the user can switch this off per tool, e.g. for scheduled automations)
Markdown     https://cotlet.dev/integrations/redmine-api-mcp-server.md

How access works:
1. The user signs up at https://cotlet.dev/app/signup?app=redmine, requests Redmine in the Cotlet console and creates an API key there.
2. The user signs in to Redmine once in their Cotlet Cloud Browser (their own Chrome in the cloud, opened from the console) and enables Redmine for agents. An agent cannot do this step.
3. The API key goes into the MCP client or the REST call as a bearer token.

Fits: people who want a hosted Redmine server that someone else maintains, including non-developers. Developers who prefer to run and fix code on their own computer can use an open-source Redmine MCP server instead.

Policy: Cotlet never stores passwords, never solves CAPTCHAs, never bypasses MFA.
Company: legal details in the Terms of service at https://cotlet.dev/terms. Contact contact@cotlet.dev.
Sign-in: the user signs in to Redmine in their own Cloud Browser, a Chrome Cotlet runs for them in the EU; password saving is off, the profile is AES-256-GCM encrypted, and agents get Redmine only after the user enables it. Calls are requests from that browser's IP with its cookies, each listed in the user's Background activity. Disable for agents, signing out in the browser or Reset browser cuts access. Cotlet is run by Take Group sp. z o.o. (EU VAT PL6342984273).
API key: holds no Redmine login or cookies, only asks Cotlet to run a tool. Each key is scoped to chosen apps and tools, read only or read and write. Actions that reach other people wait for the user's approval by default, so a leaked key cannot post or message as the user. Every call is in the activity log; deleting the key ends access at once.
Terms: the user stays responsible for following Redmine's terms; Cotlet is not affiliated with Redmine.
```

## What can an AI agent do in Redmine?

Cotlet is best for teams and freelancers on a Redmine reachable from the internet who want an agent to log time, create issues from notes and triage new ones without running or fixing a server.

- **[Log time on issues](https://cotlet.dev/integrations/redmine-api-mcp-server/log-time-on-issues.md)** (runs: weekly): "Every Friday, list the issues assigned to me that changed this week, check which of them already have time logged, and log the hours I give you on each with the activity Development." → `list_issues`, `list_time_entries`, `list_issue_options`, `log_time`
- **[Create issues from meeting notes](https://cotlet.dev/integrations/redmine-api-mcp-server/create-issues-from-meeting-notes.md)**: "Read these meeting notes and create a Redmine issue in the Billing portal project for every action item. Use the Task tracker, assign the person named in the note and skip anything that already exists as an open issue." → `get_project`, `list_project_members`, `list_issues`, `create_issue`
- **[Triage new issues](https://cotlet.dev/integrations/redmine-api-mcp-server/triage-unassigned-issues.md)** (runs: daily): "Every morning, take the open issues in the Billing portal project that have no assignee, set the priority from the description, assign them by the category, and add a note saying why." → `list_issues`, `get_issue`, `list_issue_options`, `list_project_members`, `update_issue`
- **Weekly status report of open issues** (runs: weekly): "Every Monday, summarize the open issues assigned to me by project, name the ones not updated for a week and the ones with a closing date this week." → `list_issues`, `get_issue`
- **Nudge stale issues** (runs: weekly): "Find open issues in the Intranet project that nobody has touched for 30 days and add a comment asking the assignee whether it is still planned." → `list_issues`, `add_comment`

## Can Redmine automations run on a schedule in n8n, Make or Zapier?

Yes. Cotlet does not replace your automation platform: it gives it a Redmine connection it does not have, with the same API key as your agent. Write actions ask for your OK by default; switch that off in your dashboard for the tools you choose, for example to log time on issues, and the schedule runs on its own. Cotlet runs in the cloud, so it keeps going while your computer is off.

| Where | How to connect | How to schedule |
|---|---|---|
| Your AI agent | Add https://cotlet.dev/mcp/v1 with your API key. | A scheduled agent run, for example a Claude Code routine. |
| n8n | MCP Client node with https://cotlet.dev/mcp/v1, or an HTTP Request node with the endpoint's method and URL, such as GET https://cotlet.dev/api/v1/redmine/issues. | Schedule Trigger node. |
| Make | HTTP module: the endpoint's method and URL with an Authorization: Bearer header, and a JSON body for POST, PUT and PATCH. | Scenario schedule. |
| Zapier | Webhooks by Zapier, Custom Request: the same method, URL, header and body. | Schedule by Zapier trigger. |
| Your own script | GET https://cotlet.dev/api/v1/redmine/issues with your API key. | cron or GitHub Actions. |

## Tools

**For AI agents:** Every endpoint and its schema is public. The 12 endpoints on this page, with parameters and example responses, can be listed without an account. Calling one returns 401 without an API key and 403 while the key has no access to Redmine.

### list_projects

Projects you can see, with ID, identifier and visibility. Access: read. REST: `GET /api/v1/redmine/projects`. MCP: `redmine_read → list_projects`.

| Parameter | Type | Required | Description |
|---|---|---|---|
| `limit` | integer | no | 1 to 100. Default: 25. |
| `offset` | integer | no | How many items to skip. Use offset + limit while it is below total_count. |

Returns every public project plus the private projects your account can access. Use project_id from each item in the other tools. The call does not list subprojects as a tree; each project appears once with its own ID.

Example response:

```json
{
  "projects": [
    {
      "project_id": 12,
      "name": "Billing portal",
      "identifier": "billing-portal",
      "is_public": false,
      "updated_on": "2026-10-14T16:02:00Z"
    },
    {
      "project_id": 15,
      "name": "Intranet",
      "identifier": "intranet",
      "is_public": true,
      "updated_on": "2026-10-09T08:40:00Z"
    }
  ],
  "total_count": 2
}
```

### get_project

One project with its trackers, issue categories and time-entry activities. Access: read. REST: `GET /api/v1/redmine/projects/{project_id}`. MCP: `redmine_read → get_project`.

| Parameter | Type | Required | Description |
|---|---|---|---|
| `project_id` | integer | yes | Numeric project ID from list_projects. Redmine issue endpoints take the number, not the project identifier. |

Returns the project description and the lists you need before creating issues or logging time: trackers, issue categories and the activities allowed for time entries. Read it once per project and reuse the IDs.

Example response:

```json
{
  "project_id": 12,
  "name": "Billing portal",
  "identifier": "billing-portal",
  "description": "Invoices, payments and refunds for customers.",
  "trackers": [
    {
      "id": 1,
      "name": "Bug"
    },
    {
      "id": 2,
      "name": "Task"
    },
    {
      "id": 3,
      "name": "Support"
    }
  ],
  "issue_categories": [
    {
      "id": 4,
      "name": "Payments"
    },
    {
      "id": 5,
      "name": "PDF"
    }
  ],
  "time_entry_activities": [
    {
      "id": 9,
      "name": "Development"
    },
    {
      "id": 10,
      "name": "Design"
    }
  ]
}
```

### list_project_members

People on a project with their user ID and roles. Access: read. REST: `GET /api/v1/redmine/project-members`. MCP: `redmine_read → list_project_members`.

| Parameter | Type | Required | Description |
|---|---|---|---|
| `project_id` | integer | yes | Numeric project ID from list_projects. Redmine issue endpoints take the number, not the project identifier. |
| `limit` | integer | no | 1 to 100. Default: 25. |
| `offset` | integer | no | How many items to skip. Use offset + limit while it is below total_count. |

Returns the memberships of one project. Each item carries the user ID that assigned_to_id expects and the roles the person has there. A membership can come from a group; its roles are then marked inherited.

Example response:

```json
{
  "members": [
    {
      "user_id": 31,
      "name": "Priya Nair",
      "roles": [
        "Developer"
      ]
    },
    {
      "user_id": 27,
      "name": "Tom Becker",
      "roles": [
        "Manager"
      ]
    }
  ],
  "total_count": 2
}
```

### list_issue_options

Issue statuses, priorities and time-entry activities of the instance, with IDs. Access: read. REST: `GET /api/v1/redmine/issue-options`. MCP: `redmine_read → list_issue_options`.

No parameters.

Returns the statuses (with whether each counts as closed), the priorities and the time-entry activities defined on the instance, each with its ID and whether it is the default. Use these IDs in create_issue, update_issue and log_time. Names and IDs differ per instance.

Example response:

```json
{
  "statuses": [
    {
      "id": 1,
      "name": "New",
      "is_closed": false
    },
    {
      "id": 2,
      "name": "In Progress",
      "is_closed": false
    },
    {
      "id": 5,
      "name": "Closed",
      "is_closed": true
    }
  ],
  "priorities": [
    {
      "id": 2,
      "name": "Normal",
      "is_default": true
    },
    {
      "id": 3,
      "name": "High",
      "is_default": false
    }
  ],
  "time_entry_activities": [
    {
      "id": 9,
      "name": "Development",
      "is_default": true
    },
    {
      "id": 10,
      "name": "Design",
      "is_default": false
    }
  ]
}
```

### list_issues

Issues filtered by project, assignee, status and tracker, sorted as you ask. Access: read. REST: `GET /api/v1/redmine/issues`. MCP: `redmine_read → list_issues`.

| Parameter | Type | Required | Description |
|---|---|---|---|
| `project_id` | integer | no | Only issues of this project (numeric ID from list_projects). |
| `assigned_to_id` | string | no | A user ID, or 'me' for the signed-in account. |
| `status` | string | no | 'open' (default), 'closed', 'all', or a status ID from list_issue_options. |
| `tracker_id` | integer | no | Only issues of this tracker. |
| `sort` | string | no | Column to sort by, e.g. 'updated_on:desc'. Default: Redmine's own order. |
| `limit` | integer | no | 1 to 100. Default: 25. |
| `offset` | integer | no | How many items to skip. Use offset + limit while it is below total_count. |

Returns issues with subject, tracker, status, priority, assignee and dates. By default only open issues come back; set status to all or closed to change that. Pages hold up to 100 issues, so read total_count and pass offset for the next page. The project filter takes the numeric project ID.

Example response:

```json
{
  "issues": [
    {
      "issue_id": 4830,
      "project": "Billing portal",
      "tracker": "Bug",
      "status": "New",
      "priority": "Normal",
      "subject": "Refund email not sent",
      "assigned_to": null,
      "updated_on": "2026-10-16T07:12:00Z"
    },
    {
      "issue_id": 4821,
      "project": "Billing portal",
      "tracker": "Bug",
      "status": "In Progress",
      "priority": "High",
      "subject": "Login loop after password reset",
      "assigned_to": "Dana Whitfield",
      "updated_on": "2026-10-15T14:30:00Z"
    }
  ],
  "total_count": 2,
  "offset": 0,
  "limit": 25
}
```

### get_issue

One issue with description, history, subtasks, relations and the statuses you may move it to. Access: read. REST: `GET /api/v1/redmine/issues/{issue_id}`. MCP: `redmine_read → get_issue`.

| Parameter | Type | Required | Description |
|---|---|---|---|
| `issue_id` | integer | yes | Issue number, e.g. 4821 for #4821. |
| `include` | string | no | Comma-separated extras: journals, children, relations, attachments, watchers, allowed_statuses. Default: all of these. |

Returns the full issue: description, custom fields, the journal of notes and field changes in order, subtasks, relations and attachments. allowed_statuses lists the statuses your role may set next. Private notes appear only if your role can see them.

Example response:

```json
{
  "issue_id": 4821,
  "project": "Billing portal",
  "tracker": "Bug",
  "status": "In Progress",
  "priority": "High",
  "subject": "Login loop after password reset",
  "description": "After resetting the password, the login page redirects back to itself.",
  "author": "Tom Becker",
  "assigned_to": "Dana Whitfield",
  "journals": [
    {
      "user": "Tom Becker",
      "created_on": "2026-10-14T09:05:00Z",
      "notes": "Happens in Firefox only.",
      "private": false
    }
  ],
  "children": [],
  "allowed_statuses": [
    {
      "id": 2,
      "name": "In Progress"
    },
    {
      "id": 3,
      "name": "Resolved"
    }
  ]
}
```

### list_time_entries

Logged hours by project, user and date range. Access: read. REST: `GET /api/v1/redmine/time-entries`. MCP: `redmine_read → list_time_entries`.

| Parameter | Type | Required | Description |
|---|---|---|---|
| `project_id` | integer | no | Only entries of this project. |
| `user_id` | integer | no | Only entries of this user. |
| `from` | date | no | First day, YYYY-MM-DD. |
| `to` | date | no | Last day, YYYY-MM-DD. |
| `limit` | integer | no | 1 to 100. Default: 25. |
| `offset` | integer | no | How many items to skip. Use offset + limit while it is below total_count. |

Returns time entries with issue, user, activity, hours, date and comment. Use from and to for a date range and user_id to see one person. Pages hold up to 100 entries; read total_count and pass offset for more. Hours are decimals, so 0.25 is 15 minutes.

Example response:

```json
{
  "time_entries": [
    {
      "time_entry_id": 18390,
      "project": "Billing portal",
      "issue_id": 4790,
      "user": "Dana Whitfield",
      "activity": "Development",
      "hours": 2,
      "spent_on": "2026-10-12",
      "comments": "Retry logic"
    }
  ],
  "total_count": 1,
  "offset": 0,
  "limit": 25
}
```

### create_issue

Create an issue in a project with tracker, subject, description, priority and assignee. Access: write, asks the user first. REST: `POST /api/v1/redmine/projects/{project_id}/issues`. MCP: `redmine_write → create_issue`.

| Parameter | Type | Required | Description |
|---|---|---|---|
| `project_id` | integer | yes | Numeric project ID from list_projects. Redmine issue endpoints take the number, not the project identifier. |
| `tracker_id` | integer | yes | Tracker ID from get_project. |
| `subject` | string | yes | Issue title. |
| `description` | string | no | Issue text. |
| `priority_id` | integer | no | Priority ID from list_issue_options. Default: the instance default. |
| `assigned_to_id` | integer | no | User ID from list_project_members. |
| `category_id` | integer | no | Issue category ID from get_project. |
| `parent_issue_id` | integer | no | Number of the parent issue, to create a subtask. |
| `is_private` | boolean | no | true makes the issue private. Default: false. |

Creates the issue and returns its number and link. The assignee is a user ID from list_project_members; Redmine cannot assign by name. Pass parent_issue_id to make a subtask. Needs the Add Issues permission in your role on the project. The assignee and watchers can be notified according to their notification settings. By default you confirm each call; you can switch that off for this tool.

Example response:

```json
{
  "issue_id": 4832,
  "url": "https://redmine.example.com/issues/4832",
  "project": "Billing portal",
  "tracker": "Task",
  "status": "New",
  "priority": "Normal",
  "subject": "Fix invoice footer on PDF",
  "assigned_to": "Priya Nair",
  "author": "Dana Whitfield",
  "created_on": "2026-10-16T09:20:00Z"
}
```

### update_issue

Change status, priority, assignee or other fields of an issue and optionally add a note. Access: write, asks the user first. REST: `PATCH /api/v1/redmine/issues/{issue_id}`. MCP: `redmine_write → update_issue`.

| Parameter | Type | Required | Description |
|---|---|---|---|
| `issue_id` | integer | yes | Issue number, e.g. 4821 for #4821. |
| `status_id` | integer | no | Status ID from list_issue_options; must be one of allowed_statuses. |
| `priority_id` | integer | no | Priority ID from list_issue_options. |
| `assigned_to_id` | integer | no | User ID from list_project_members. |
| `subject` | string | no | New title. |
| `description` | string | no | New description. |
| `notes` | string | no | Note saved with the update. |
| `private_notes` | boolean | no | true marks the note private. Default: false. |

Applies the fields you pass and leaves the rest as they are. A note passed with the change is saved in the same update. Changing subject or description needs the Edit Issues permission; get_issue shows which statuses you may set. Watchers of the issue can be notified. By default you confirm each call; you can switch that off for this tool.

Example response:

```json
{
  "issue_id": 4830,
  "status": "New",
  "priority": "High",
  "assigned_to": "Priya Nair",
  "note_added": true,
  "updated_on": "2026-10-16T09:31:00Z"
}
```

### add_comment

Add a note to an issue without changing any field. Access: write, asks the user first. REST: `POST /api/v1/redmine/issues/{issue_id}/comments`. MCP: `redmine_write → add_comment`.

| Parameter | Type | Required | Description |
|---|---|---|---|
| `issue_id` | integer | yes | Issue number, e.g. 4821 for #4821. |
| `notes` | string | yes | Text of the note. |
| `private` | boolean | no | true makes the note private. Default: false. |

Adds one note to the issue history and returns its position in the journal. Set private to true for a note only roles with the right to see private notes can read. Watchers of the issue can be notified. By default you confirm each call; you can switch that off for this tool.

Example response:

```json
{
  "issue_id": 4790,
  "note_added": true,
  "private": false,
  "created_on": "2026-10-16T09:40:00Z"
}
```

### log_time

Log hours on an issue or a project with an activity and a comment. Access: write. REST: `POST /api/v1/redmine/times`. MCP: `redmine_write → log_time`.

| Parameter | Type | Required | Description |
|---|---|---|---|
| `issue_id` | integer | no | Issue to log on. Give this or project_id. |
| `project_id` | integer | no | Project to log on when no issue applies. |
| `hours` | number | yes | Decimal hours, e.g. 1.5. |
| `activity_id` | integer | no | Activity ID from list_issue_options. Required unless the instance has a default activity. |
| `spent_on` | date | no | Day worked, YYYY-MM-DD. Default: today. |
| `comments` | string | no | Short description, 255 characters at most. |

Creates a time entry for the signed-in account and returns it. Pass issue_id or project_id. Hours are decimals, so 0.25 is 15 minutes. The activity is required unless the instance has a default; the comment is 255 characters at most. log_time runs without asking first: it reaches no one and is corrected with update_time_entry.

Example response:

```json
{
  "time_entry_id": 18433,
  "project": "Billing portal",
  "issue_id": 4821,
  "user": "Dana Whitfield",
  "activity": "Development",
  "hours": 1.5,
  "spent_on": "2026-10-15",
  "comments": "Reproduced the login loop and patched the session check"
}
```

### update_time_entry

Correct the hours, activity, date or comment of a time entry. Access: write. REST: `PATCH /api/v1/redmine/time-entries/{time_entry_id}`. MCP: `redmine_write → update_time_entry`.

| Parameter | Type | Required | Description |
|---|---|---|---|
| `time_entry_id` | integer | yes | Entry ID from list_time_entries or log_time. |
| `hours` | number | no | Decimal hours. |
| `activity_id` | integer | no | Activity ID from list_issue_options. |
| `spent_on` | date | no | Day worked, YYYY-MM-DD. |
| `comments` | string | no | Short description, 255 characters at most. |

Changes the fields you pass on an entry and returns the result. It reaches no one and is undone by another call with the old values, so it runs without asking first.

Example response:

```json
{
  "time_entry_id": 18433,
  "issue_id": 4821,
  "activity": "Development",
  "hours": 2,
  "spent_on": "2026-10-15",
  "comments": "Reproduced the login loop and patched the session check"
}
```

## How do I connect Redmine to Claude Code, Codex or Cursor?

Connecting Redmine takes three steps: sign up, sign in to Redmine once in your Cloud Browser and enable it for agents, then add one MCP server or call the REST API with the same key.

### Connect Redmine to your agent.

1. **Create an account** Sign up and add Redmine in the console. Your API key is there too.

2. **Sign in to Redmine in your Cloud Browser** Open your Cloud Browser in the console: your own Chrome in the cloud. Sign in to Redmine there yourself, the way you always do, then press Enable for agents, read only or read and write. We never save your password, and your agent keeps working even when your computer is off.

3. **Add Cotlet to your agent** Paste the snippet for your client. The same server and key serve every app you connect, so you do this once.

   Claude Code:

```
claude mcp add --transport http cotlet \
  https://cotlet.dev/mcp/v1 \
  --header "Authorization: Bearer $COTLET_API_KEY"
```

   Cursor:

```
{
  "mcpServers": {
    "cotlet": {
      "url": "https://cotlet.dev/mcp/v1",
      "headers": {
        "Authorization": "Bearer ${COTLET_API_KEY}"
      }
    }
  }
}
```

   Codex:

```
# ~/.codex/config.toml
[mcp_servers.cotlet]
url = "https://cotlet.dev/mcp/v1"
bearer_token_env_var = "COTLET_API_KEY"
```

4. **Ask your agent** Ask in plain words. Your agent finds the Redmine tools on the server and calls them for you; anything that reaches other people waits for your OK unless you switch that off for a tool.

```
Every Friday, list the issues assigned to me that changed this week, check which of them already have time logged, and log the hours I give you on each with the activity Development.
```

### Call Redmine from your scripts.

1. **Export your API key** Your scripts use the same API key as your agent. Keep it in an environment variable, never in your code.

```
export COTLET_API_KEY="cotlet_..."
```

2. **Call a tool** Every tool is an endpoint under /api/v1/redmine with its own method and path, listed with the endpoints above. Path parameters go in the URL; the other parameters go in the query for GET and DELETE and in a JSON body otherwise.

```
curl -X POST https://cotlet.dev/api/v1/redmine/projects/12/issues \
  -H "Authorization: Bearer $COTLET_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"tracker_id":2,"subject":"Fix invoice footer on PDF","description":"From the 14 Oct planning call: the footer overlaps the totals on page 2.","assigned_to_id":31}'
```

3. **Read the result** You get plain JSON back, ready for your script. A failed call costs nothing.

```
{
  "issue_id": 4832,
  "url": "https://redmine.example.com/issues/4832",
  "project": "Billing portal",
  "tracker": "Task",
  "status": "New",
  "priority": "Normal",
  "subject": "Fix invoice footer on PDF",
  "assigned_to": "Priya Nair",
  "author": "Dana Whitfield",
  "created_on": "2026-10-16T09:20:00Z"
}
```

## Why use Cotlet for Redmine?

**Built for agents**

- One MCP server for every app you connect.
- The same tools as a REST API for scripts and cron jobs.
- Works with Claude Code, Codex and Cursor.

**Your login stays yours**

- You sign in to Redmine yourself, in your own Cloud Browser. We never save your password; the profile is encrypted with AES-256-GCM, the cipher 1Password uses.
- A+ on Qualys SSL Labs, securityheaders.com and Mozilla Observatory.
- The model never sees a login.
- No stored passwords, no CAPTCHA solving, no MFA bypass.

**You stay in control**

- Scope each API key: its apps, its tools, read only or read and write.
- Anything that reaches other people waits for your OK, so a leaked key cannot post or message as you.
- Every background request listed in your Background activity. Disable for agents in one click.

**Kept working for you**

- We test every integration every 6 hours.
- When Redmine changes, the tool pauses until we fix it.
- Failed calls cost nothing.

## Is it safe to connect Redmine to Cotlet?

Yes. You sign in to Redmine yourself, in your own Cloud Browser, and we never save your password. Your agents only get Redmine once you enable it, and every background request is listed. The browser profile is stored encrypted with AES-256-GCM, the same cipher 1Password uses for its vaults and Apple for iCloud Keychain. Independent public scanners grade cotlet.dev A+ and find it clean; click a result to rerun it yourself.

- **A+ on Qualys SSL Labs**: Encryption in transit: TLS setup and certificates, on all four server addresses. [Live result](https://www.ssllabs.com/ssltest/analyze.html?d=cotlet.dev)
- **A+ on securityheaders.com**: Browser protections sent with every page, all six headers present. [Live result](https://securityheaders.com/?q=cotlet.dev&followRedirects=on)
- **A+ on Mozilla Observatory**: Mozilla's web security baseline: score 120 of 100, 12 of 12 tests passed. [Live result](https://developer.mozilla.org/en-US/observatory/analyze?host=cotlet.dev)
- **Clean on Sucuri SiteCheck**: No malware, spam or defacement, and not on any of 9 blocklists, Google Safe Browsing included. [Live result](https://sitecheck.sucuri.net/results/cotlet.dev)

[How Cotlet protects your access](https://cotlet.dev/security.md)

### Common concerns

**Who runs Cotlet?**

Cotlet is run by Take Group, a Polish software company working since 2019. Take Group runs about 3,200 websites on its own systems and has its own DevOps team for infrastructure security. We built and used integrations like this inside the company for years before opening them as Cotlet.

**Is this an official Redmine integration?**

No, Cotlet is independent of Redmine. Redmine's own API is too limited for this work. Cotlet works through your own Redmine account, the way you use Redmine in the browser, so you need no partner approval and no developer setup.

**What about client data and GDPR?**

Cotlet is run from the EU and follows the GDPR. Cloud Browsers run in Finland, a Tier 1 country in the ITU Global Cybersecurity Index 2024. Data passes through a call and is not kept after it.

**Can I start with read only?**

Yes. Enable the app for agents as read only, or make the API key read only, and anything that reaches other people waits for your OK unless you switch that off per tool.

**Is it reliable?**

Every Cotlet service is checked every 3 minutes from Europe, North America, Asia and Australia. The live results and any outage are public at status.cotlet.dev.

**How do I stop?**

Press Disable for agents next to Redmine in your console: your agents lose access at once and you stay signed in. Signing out of Redmine in the browser works too, and Reset browser deletes the whole profile.

## Is there a Redmine MCP server on GitHub?

Yes. Open-source Redmine MCP servers exist on GitHub, usually maintained by one person. You install one yourself, give it your instance address and an API key, and keep it running; when Redmine or the server changes, you or the maintainer fix it. Calling the REST API from your own script works the same way: the address and key live in your code. Cotlet hosts the same kind of server for you, and our team keeps it working.

|  | GitHub MCP server | Cotlet |
|---|---|---|
| Setup | Install the server, set the instance URL and your API key in every MCP client or script | Sign up, sign in to your Redmine once, add one MCP server or API key |
| When Redmine changes | It breaks until you or the maintainer fix it | Our team tests it daily and fixes it for you; failed calls are free |
| Your Redmine access | An API key in a config file or environment variable on your computer, with all your permissions | Signed in inside your own Cloud Browser in the EU, profile encrypted, only for the apps you enable, disabled for agents in one click |
| When access expires | The key keeps working until it is changed; nothing to renew | Your Cloud Browser keeps you signed in; if Redmine signs you out, your agent gets a link to sign in again |
| Which instances | Any instance your computer can reach, including one behind a VPN | Instances reachable from the internet: hosted Redmine such as Planio, or self-hosted with a public address |
| Where it runs | Your computer, while it is on | Hosted: Claude Code, Codex, Cursor, n8n and scripts, also on a schedule |
| Price | Free, paid for with your time | Free 7-day trial, then pay-as-you-go credit packs, no subscription |

### Which one fits you

**Pick Cotlet if**

- you are not a developer, or you do not want to maintain a server
- you need it to keep working when Redmine changes, without checking it yourself
- your agent or a script should run it on a schedule, also while your computer is off

**Pick an open-source server if**

- you are comfortable installing, updating and fixing it yourself
- you want your sign-in to stay on your own computer
- you only need it now and then, from one MCP client

## How much does the Redmine API cost?

Free 7-day trial with 2,000 credits, no card needed. After that, the Redmine API is pay as you go with no limit on apps: Credit packs from $29 for 5,000 credits, one-time, no subscription. A successful call uses 20 to 30 credits (25 for most tools, about $0.10 to $0.15), your Cloud Browser uses 50 credits a day while it has an app enabled for agents, however many apps that is, and an agent driving the browser itself uses 5 credits a minute. Credit packs stay valid for 12 months and stack, so unused credits carry over.

| Credits | Price, one time | Calls at 25 credits | Per 1,000 credits |
|---|---|---|---|
| 5,000 | $29 | 200 | $5.80 |
| 15,000 | $79 | 600 | $5.27 |
| 32,000 | $149 | 1,280 | $4.66 |
| 60,000 | $249 | 2,400 | $4.15 |

Only successful calls use credits; failed calls and timeouts cost nothing. At a balance of 0 calls pause, never a surprise charge. Authenticate with the `Authorization: Bearer` header. [See full pricing](https://cotlet.dev/pricing.md)

## How Cotlet holds your access

Cotlet hosts MCP servers and REST APIs for apps with no usable API. Your agent works in your own Redmine account.

- **Company details:** Cotlet is run by Take Group sp. z o.o., a company registered in Poland. Its full address and registration numbers are in the Terms of service. [Terms of service](https://cotlet.dev/terms)
- **Your sign-in:** You sign in to Redmine yourself, in your own Cloud Browser: a Chrome we run for you in the EU, one per app. We never save your password (password saving is off), the profile is stored encrypted with AES-256-GCM, and your agents get Redmine only after you enable it. When Redmine signs you out, your agent gives you a link to sign in again. [Security](https://cotlet.dev/security.md)
- **Revoking access:** Press Disable for agents next to Redmine, sign out of Redmine in your Cloud Browser, or reset the browser. Every background request is listed in your Background activity. Actions that reach other people wait for your OK unless you switch that off per tool.
- **What we never do:** Store passwords, solve CAPTCHAs or bypass MFA.
- **Redmine's terms:** You use your own Redmine account and stay responsible for following Redmine's terms. Cotlet is independent and not affiliated with Redmine. [Terms](https://cotlet.dev/terms)
- **Contact:** Questions about the company, security or an app: [contact@cotlet.dev](mailto:contact@cotlet.dev)

## Frequently asked questions

**How do I get access?**

Sign up free, open Redmine in the console and press Request access. Then you create your API key and connect Redmine there.

**Do I need to be technical?**

No. You sign in to Redmine once in your Cloud Browser, a normal Chrome you open from the console, and paste one command into your agent, or one URL into n8n. Your agent can walk you through it. There is no server to install, update or fix.

**Is it safe to connect Redmine to Cotlet?**

Yes. You sign in to Redmine yourself, in your own Cloud Browser in the EU, and we never save your password. Your agents only get Redmine once you enable it, every background request is listed, and the browser profile is stored encrypted with AES-256-GCM, the cipher 1Password uses for its vaults. The AI model never sees a login, posts and messages wait for your OK, and Disable for agents cuts access in one click. Independent scanners grade cotlet.dev A+ on Qualys SSL Labs, securityheaders.com and Mozilla Observatory; live results are on https://cotlet.dev/security.

**Is a hosted server safer than a local one? My Redmine sign-in would leave my computer.**

On Cotlet you sign in inside your own Cloud Browser, which only you open, and its profile is stored encrypted with AES-256-GCM in the EU. Agents get only the apps you enable, and every background request is listed. A local server keeps your Redmine cookie in a plain file on your computer, readable by any program you run, and stops when your computer is off.

**Why does Cotlet send requests instead of clicking in my browser?**

To be fast, Cotlet doesn't click through Redmine's pages. It sends the same requests your browser would, from your browser's IP with its cookies, without opening a window. Redmine sees the same browser and IP you signed in with, and every request is listed in your Background activity.

**What if someone gets my Cotlet API key?**

The key holds no Redmine login or cookies, it only asks Cotlet to run a tool. It can call only the apps and tools you gave it, and a read-only key changes nothing. Anything that reaches other people, like posts, comments or messages, waits for your OK in the dashboard by default, so a leaked key cannot post or message as you. When you switch approval off for a scheduled job, give that job its own key limited to that one tool. Every call is in your activity log, and deleting the key ends access at once.

**Why a signed-in browser and not OAuth, like other integration platforms?**

Redmine offers no OAuth token you can simply grant for these tools: its official API leaves them out or needs a developer app, a plan or an approval first (see the official API section above). That is why Cotlet sets the limits itself: per key, per tool, with your approval before anything reaches other people. Cotlet is run by Take Group sp. z o.o., an EU company (VAT PL6342984273).

**Does my Redmine have to be reachable from the internet?**

Yes. Cotlet runs in the cloud, so it can sign in only to an instance with an address it can reach, such as hosted Redmine or a self-hosted one with a public address. An instance only on a VPN or intranet is out of reach.

**How many issues does one call return?**

Redmine returns 25 items per page by default and at most 100, with total_count in the response. list_issues and list_time_entries take offset to read the next page. Only open issues are returned unless you ask for closed or all.

**Which Redmine permissions does my agent need?**

The same as you: creating issues needs the Add Issues permission in your role on the project, and changing subject or description needs Edit Issues. Which fields and statuses you can change depends on your role and the tracker workflow.

**Can my agent post or send messages in Redmine without asking me?**

No. Every call to create_issue, update_issue or add_comment waits for your OK by default. For scheduled automations you can switch confirmation off per tool in your dashboard, for example only for approvals. log_time, update_time_entry runs without asking, because it sends nothing to anyone and one call undoes it.

**Can I use the Redmine API in n8n?**

Yes. Add https://cotlet.dev/mcp/v1 with your API key in n8n's MCP Client node, or call its endpoints under https://cotlet.dev/api/v1/redmine from the HTTP Request node.

---

Give your AI agents your signed-in browser.

**Product:** [Integrations](https://cotlet.dev/integrations.md) · [Use cases](https://cotlet.dev/use-cases.md) · [How it works](https://cotlet.dev/how-it-works.md) · [Pricing](https://cotlet.dev/pricing.md) · [Security](https://cotlet.dev/security.md)

**Resources:** [Blog](https://cotlet.dev/blog.md) · [API docs](https://cotlet.dev/docs.md) · [Help center](https://cotlet.dev/help.md) · [Changelog](https://cotlet.dev/changelog.md) · [GitHub](https://github.com/cotletdev/cotlet)

**Solutions:** [For developers](https://cotlet.dev/for-developers.md) · [For automation agencies](https://cotlet.dev/for-agencies.md)

**Company:** [About](https://cotlet.dev/about.md) · [AI info: company facts](https://cotlet.dev/ai-info.md) · [Contact](https://cotlet.dev/contact.md)

**Legal:** [Terms of service](https://cotlet.dev/terms) · [Privacy policy](https://cotlet.dev/privacy) · [Refund policy](https://cotlet.dev/refunds) · [Acceptable use](https://cotlet.dev/acceptable-use) · [Cookie policy](https://cotlet.dev/cookies) · [DPA](https://cotlet.dev/dpa) · [Subprocessors](https://cotlet.dev/subprocessors)

**Elsewhere:** [Status page](https://status.cotlet.dev) · [Cotlet on GitHub](https://github.com/cotletdev) · [Cotlet on X](https://x.com/cotletdev) · [Cotlet on LinkedIn](https://www.linkedin.com/company/cotletdev) · [Cotlet on Product Hunt](https://www.producthunt.com/products/cotlet) · [Cotlet on Crunchbase](https://www.crunchbase.com/organization/cotlet) · [Cotlet on SaaSHub](https://www.saashub.com/cotlet)

Cotlet is an independent service. It is not affiliated with, endorsed by or sponsored by any of the products listed on this site. Product names are trademarks of their respective owners.

## For AI agents: sign your user up

Is your user asking you to sign them up for Cotlet? You can do it for them, no account or key needed.

1. Read the fields and their allowed values: GET https://cotlet.dev/api/v1/access-requests
2. Ask the user for each value: email, apps, what you will do with them. If they leave the password to you, generate a strong one and show it to them.
3. Show the user what you will send, then POST it as JSON to https://cotlet.dev/api/v1/access-requests.

One call creates the account and sends the access request; we email the user when access is granted.
