Skip to content

v2.3.0: OAuth-proxy auth mode and reliable test runs

Choose a tag to compare

@jztan jztan released this 12 Jun 14:03

Highlights

This release adds a new opt-in authentication mode, REDMINE_AUTH_MODE=oauth-proxy. In this mode the MCP server acts as the OAuth authorization server that clients talk to, serving Dynamic Client Registration plus /authorize, /token, and /register, while proxying the upstream flow to Redmine/Doorkeeper and keeping user consent on Redmine. This unlocks clients that require DCR or CIMD without Redmine having to serve RFC 8414 metadata or implement DCR, which the existing introspection-based oauth mode could not provide on split-host deployments.

Security is sensible by default: oauth-proxy restricts client redirect URIs to loopback (http://localhost:*, http://127.0.0.1:*), so a registered client cannot point the flow at a remote target unless you explicitly allow it. Secrets can be supplied via *_FILE env vars for Docker and Kubernetes.

Legacy and oauth modes are unchanged, and legacy remains the default. This release also fixes --all test runs that were silently skipping every integration test.

Changes

Added

  • New opt-in REDMINE_AUTH_MODE=oauth-proxy mode: the server serves DCR, /authorize, /token, and /register, proxies the upstream flow to Redmine/Doorkeeper, and keeps consent on Redmine. Supports DCR/CIMD clients on split-host deployments without Redmine serving RFC 8414 metadata or DCR. Requires a stable REDMINE_MCP_JWT_SIGNING_KEY. (#153)
  • /health now probes Redmine introspection in both oauth and oauth-proxy modes.
  • Mount the app behind a public base path via REDMINE_MCP_BASE_URL.
  • Supply secrets via *_FILE env vars for Docker/Kubernetes.
  • oauth-proxy mode supports hosted clients via REDMINE_MCP_ALLOWED_CLIENT_REDIRECT_URIS (comma- or space-separated glob patterns, or * to accept any redirect URI).

Fixed

  • python tests/run_tests.py --all now actually runs the integration suite. It runs the unit phase and the integration phase as two separate pytest processes so each gets the correct environment, and integration coverage is appended. (#156)

Changed

  • Secret *_FILE env vars now raise a clear error naming the variable and path when the referenced file cannot be read, instead of a bare FileNotFoundError.

Security

  • oauth-proxy mode restricts client redirect URIs to loopback (http://localhost:*, http://127.0.0.1:*) by default, preventing a registered client from pointing the flow at a remote target out of the box.

Acknowledgements

Thanks to @aadnehovda for contributing:

  • designed and implemented the oauth-proxy authentication mode backed by FastMCP OAuthProxy, and refactored the remote OAuth setup into RedmineAuthProvider (#153)

Thanks to @timcomport for contributing:

  • verified the oauth-proxy mode end to end on a split-host VS Code + Redmine 6.1.1 deployment and caught the Step 4 authorization-server metadata path discrepancy (#140)

Installation

pip install redmine-mcp-server==2.3.0

Links