- Step 0: enable the MCP server (both variants)
- Variant 1: OAuth
- Variant 2: API key
- What happens on failure
The MCP server supports two ways to authenticate. Both identify a Redmine user: a client always acts as that user and never gets more than the user may do.
| OAuth 2.0 (recommended) | API key | |
|---|---|---|
| Sign-in | the user approves the client on a Redmine consent page | none, the key is pasted into the client |
| Limits | only the scopes ticked on the application and the roles of the user | no scopes, all rights of the user, writes included |
| Expiry and revoke | tokens expire and refresh; revoke by deleting the application or the token | no expiry; revoke by resetting the key |
| Enabled | always, with the MCP server | off by default, an administrator must allow it |
| Use it for | Claude, ChatGPT, Codex, Gemini CLI, Cursor and any client with OAuth settings | clients that can only send a fixed bearer token (xAI, Grok and others), scripts |
Step 0: enable the MCP server (both variants)
- Open Administration → Settings → API and tick Enable REST web service. Core Redmine accepts OAuth tokens and API keys only when it is on; the plugin settings page warns if it is not.
- Open Administration → Plugins → Redmine Agent → Configure and tick Enable MCP server. Save.
- Check Administration → Settings → General: Host name and path and Protocol must be the public address (with HTTPS). OAuth metadata is built from them.
- The server URL is shown in the plugin settings as MCP server URL:
https://your-redmine.example.com/mcp.
Variant 1: OAuth
- Open Administration → Applications and click New application.
- Name: the client name, for example "Claude" (one application per client, so that it can be revoked separately).
- Redirect URI: the callback address of the client (see the table in MCP server):
- claude.ai and Claude Desktop:
https://claude.ai/api/mcp/auth_callback - Claude Code:
http://localhost:8765/callback - ChatGPT: the callback URL shown in the connector form
- Codex, Gemini CLI, Cursor and other local clients: the loopback URL from the OAuth settings of the client
- claude.ai and Claude Desktop:
- Scopes: tick the permissions that the client may use, for example
view_issues,add_issues,edit_issues,add_issue_notes,log_time. For a read-only client tick onlyview_*scopes. The client may request more: it gets only the ticked ones. Tools of the client are limited to these scopes and to the roles of the user. - Keep Confidential ticked and click Submit.
- Copy the UID (client ID) and the secret. Redmine shows the secret only once; if it is lost, create a new application.
- In the client enter the server URL
https://your-redmine.example.com/mcpand the client ID and secret:- claude.ai: Settings → Connectors → Add custom connector → Advanced settings → OAuth Client ID and Secret
- Claude Code:
MCP_CLIENT_SECRET=CLIENT_SECRET claude mcp add --transport http --client-id CLIENT_ID --client-secret --callback-port 8765 redmine https://your-redmine.example.com/mcp - ChatGPT: Connector → Advanced → User-defined OAuth client
- other clients: the OAuth client ID and secret fields of the client
- The client opens the Redmine sign-in and consent page. Sign in, check the listed scopes and click Authorize.
- Check: ask the client "who am I in Redmine?" (it calls
get_current_user) or runtools/list.
To revoke access delete the application in Administration → Applications.
Variant 2: API key
- Do step 0 and additionally open Administration → Plugins → Redmine Agent → Configure and tick Allow MCP access with API key. Save. Without it an API key is rejected with 401.
- Each user opens My account and, in the API access key block on the right, clicks Show (or Reset to create a new key). The REST web service must be enabled, otherwise the block is not shown.
- In the client set the header with the key:
Authorization: Bearer API_KEY(orX-Redmine-API-Key: API_KEY). Thekeyquery parameter andX-Redmine-Switch-Userare not supported.
curl -s https://your-redmine.example.com/mcp \
-H "Authorization: Bearer API_KEY" \
-H "Content-Type: application/json" \
-d '{"jsonrpc":"2.0","id":1,"method":"tools/call","params":{"name":"get_current_user","arguments":{}}}'
The key has no scopes and no expiry, so the client can do everything its user can, including writes and deletions. Use a dedicated low-privilege user for such clients, keep the key secret and reset it if it leaks (My account → API access key → Reset).
What happens on failure
| Situation | Answer |
|---|---|
| MCP server off | 404 |
| no or invalid token | 401 with WWW-Authenticate: Bearer and the address of the resource metadata |
| API key while the setting is off | 401 |
| tool not allowed by scopes or roles | the tool is not in tools/list; a direct call is refused |
See MCP troubleshooting.