redmine-mcp-proxy
Provides a proxy for multi-user, network-reachable access to a Redmine MCP server, with per-user impersonation and integration with the Redmine REST API.
Click on "Install Server".
Wait a few minutes for the server to deploy. Once ready, it will show a "Started" state.
In the chat, type
@followed by the MCP server name and your instructions, e.g., "@redmine-mcp-proxyshow my open issues"
That's it! The server will respond to your query, and you can continue using it as needed.
Here is a step-by-step guide with screenshots.
redmine-mcp-proxy
A Streamable HTTP → stdio bridge that turns a stdio Model Context Protocol Redmine server into a multi-user, network-reachable MCP endpoint — with per-user impersonation baked in.
Point your AI platform (Ozwell, Claude, etc.) at a single URL:
https://rm.os.mieweb.org/mcp…and every logged-in user transparently acts as themselves in Redmine — no shared service account, no per-user API keys, no prompt-injectable identity.
Why this exists
MCP Redmine servers speak stdio (one process, one identity). That's great for a single desktop user, but it doesn't work when:
Many people share one AI assistant, and each must act as their own Redmine user (correct "assigned to me", correct author, correct permissions).
The MCP client is a hosted web platform that can only reach an HTTP URL, not a local subprocess.
This proxy solves both: it exposes Streamable HTTP on /mcp, and for every
session it spawns a dedicated backend subprocess locked to the requesting
user's identity.
Related MCP server: Redmine MCP server for Cursor
How the Proxy works
sequenceDiagram
participant AI as AI Platform (Ozwell / Claude)
participant Proxy as redmine-mcp-proxy (HTTP :80/mcp)
participant Sub as redmine-mcp-rs subprocess (stdio)
participant RM as Redmine REST API
AI->>Proxy: POST /mcp (initialize)<br/>x-ozwell-user-email: rgara@mieweb.com
Note over Proxy: resolveUser() extracts identity
Proxy->>Sub: spawn(redmine-mcp-rs)<br/>REDMINE_ON_BEHALF_OF=rgara@mieweb.com<br/>REDMINE_LOCK_ON_BEHALF_OF=1
Proxy-->>AI: mcp-session-id: <uuid>
AI->>Proxy: POST /mcp (tools/call)<br/>mcp-session-id: <uuid>
Proxy->>Sub: forward JSON-RPC (stdin)
Sub->>RM: GET /issues.json<br/>X-Redmine-Switch-User: rgara
RM-->>Sub: issues visible to rgara
Sub-->>Proxy: JSON-RPC result (stdout)
Proxy-->>AI: Streamable HTTP responseStep by step:
Identity resolution. On the first request of a session,
resolveUser(req)determines who the caller is, in priority order:Priority
Source
Sent by
1
x-redmine-userheaderExplicit override
2
x-ozwell-user-emailheaderOzwell AI platform (auto)
3
x-ozwell-user-nameheaderOzwell AI platform (auto)
4
?user=query parameterManual / testing
5
Basic-auth username
Clients that send credentials
No identity → HTTP 401. Nobody gets an anonymous or admin session by accident.
Per-session subprocess. A new session spawns one backend MCP process (the Rust
redmine-mcp-rsbinary) with the environment locked to that user:env: { REDMINE_URL, REDMINE_API_KEY, // admin key, server-side only REDMINE_ON_BEHALF_OF: onBehalfOf, // the resolved user REDMINE_LOCK_ON_BEHALF_OF: "1", // AI cannot override this }REDMINE_LOCK_ON_BEHALF_OF=1is the security keystone: even if the model is tricked ("act as the admin", "switch to user X"), the backend ignores any per-call identity and stays pinned to the header-derived user.Bidirectional bridge. The proxy wires the two transports together:
StreamableHTTPServerTransport(facing the AI) ⇄StdioClientTransport(facing the subprocess). Messages are forwarded verbatim in both directions, so tool names and arguments pass through unchanged.Session tracking. Each session is keyed by the
mcp-session-idheader. Subsequent requests reuse the same subprocess; closing either transport tears down the pair and frees the process.Impersonation on the wire. The backend translates
REDMINE_ON_BEHALF_OFinto Redmine'sX-Redmine-Switch-Userheader on every REST call, so Redmine enforces that user's real permissions and ownership.
Configuration
Create /opt/redmine-mcp-proxy/.env (chmod 600 — it holds the admin key):
PORT=80
REDMINE_URL=https://pm.mieweb.com/
REDMINE_API_KEY=<redmine-admin-api-key>Variable | Required | Description |
| no | Listen port (default |
| yes | Redmine base URL |
| yes | Admin API key (needed for impersonation) |
The path to the backend binary is set in server.mjs (the command: field of
the StdioClientTransport). Swap it for node index.js to use the Node
redmine-mcp server instead of the
Rust one.
Run
npm install
node server.mjsAs a systemd service
/etc/systemd/system/redmine-mcp-proxy.service:
[Unit]
Description=Redmine MCP Streamable HTTP proxy
After=network.target
[Service]
Type=simple
User=pralambomanarivo
EnvironmentFile=/opt/redmine-mcp-proxy/.env
ExecStart=/usr/bin/node /opt/redmine-mcp-proxy/server.mjs
Restart=always
RestartSec=2
[Install]
WantedBy=multi-user.targetsudo systemctl enable --now redmine-mcp-proxyBinding to port 80 as a non-root user requires
sudo setcap cap_net_bind_service=+ep "$(command -v node)".
Endpoints
Method | Path | Purpose |
|
|
|
|
| Streamable HTTP MCP endpoint |
|
| Terminate a session ( |
curl -s https://rm.os.mieweb.org/health
# {"status":"ok","sessions":1,"users":["rgara@mieweb.com"]}Security model
Admin key never leaves the server. The AI platform only sends a user identity header; the key lives in
.envand is injected into the subprocess.Locked impersonation.
REDMINE_LOCK_ON_BEHALF_OF=1makes identity header-driven and prompt-injection-proof.Fail-closed. No resolvable identity →
401, never an anonymous/admin fallback.Least privilege on the wire. Redmine evaluates every request against the impersonated user's actual permissions.
Related
redmine-mcp-rs— the Rust MCP backend this proxy spawns (single static binary, fast startup).redmine-mcp— the original Node MCP server (fully compatible backend).
This server cannot be installed
Maintenance
Resources
Unclaimed servers have limited discoverability.
Looking for Admin?
If you are the server author, to access and configure the admin panel.
Related MCP Servers
- Flicense-qualityDmaintenanceAn MCP server providing 63 tools to interact with Redmine instances, covering issues, projects, time entries, and wiki pages. It utilizes streamable HTTP transport and supports per-client authentication for secure management of Redmine resources.Last updated35
- Alicense-qualityDmaintenanceEnables interacting with a Redmine instance via REST API, allowing issues, projects, time logging, and generic endpoint calls through an MCP agent.Last updated106MIT
- Alicense-qualityDmaintenanceModel Context Protocol (MCP) server for Redmine that provides comprehensive access to the Redmine REST API, enabling users to operate Redmine from MCP clients such as Claude Desktop.Last updated5MIT
- AlicenseBqualityDmaintenanceMCP server for Redmine project management, enabling tools for managing projects, issues, users, time entries, groups, memberships, versions, wiki, news, attachments, search, and Agile sprints via the Redmine REST API.Last updated89151MIT
Related MCP Connectors
A MCP server built for developers enabling Git based project management with project and personal…
Self-hosted federated MCP gateway: one OAuth 2.1 MCP server in front of N apps, user-level scopes.
MCP server for generating rough-draft project plans from natural-language prompts.
Latest Blog Posts
- Who's Calling? MCP Hosts Are an Identity Blind Spot (And the Spec Knows It)By Om-Shree-0709 on .mcpAgent IdentityOAuth 2.1
- Your AI Chatbot Just Exposed Your CEO's Salary to an InternBy Om-Shree-0709 on .Agent IdentityMCP SecurityOAuth Delegation
- Why MCP Servers Need Execution Sandboxing (And Why Your Current Stack Isn't Enough)By Om-Shree-0709 on .Agentic AiPrompt InjectionWebAssembly
MCP directory API
We provide all the information about MCP servers via our MCP API.
curl -X GET 'https://glama.ai/api/mcp/v1/servers/mieweb/redmine-mcp-proxy'
If you have feedback or need assistance with the MCP directory API, please join our Discord server