guiziweb / mcp-redmine
Multi-provider MCP server for project management and time tracking
Installs: 4
Dependents: 0
Suggesters: 0
Security: 0
Stars: 2
Watchers: 0
Forks: 0
Type:project
pkg:composer/guiziweb/mcp-redmine
Requires
- php: >=8.2
- ext-ctype: *
- ext-sodium: *
- doctrine/dbal: ^3
- doctrine/doctrine-bundle: ^2.18
- doctrine/doctrine-migrations-bundle: ^3.7
- doctrine/orm: ^3.6
- kbsali/redmine-api: ^2.8
- knplabs/knp-paginator-bundle: ^6.10
- laminas/laminas-httphandlerrunner: ^2.13
- league/oauth2-google: ^4.1
- lesstif/jira-cloud-restapi: ^1.10
- mcp/sdk: ^0.1.0
- nyholm/psr7: ^1.8.2
- nyholm/psr7-server: ^1.1
- symfony/asset: 7.4.*
- symfony/asset-mapper: 7.4.*
- symfony/clock: 7.4.*
- symfony/console: 7.4.*
- symfony/dotenv: 7.4.*
- symfony/expression-language: 7.4.*
- symfony/flex: ^2.10
- symfony/form: 7.4.*
- symfony/framework-bundle: 7.4.*
- symfony/http-client: 7.4.*
- symfony/monolog-bundle: ^3.11.1
- symfony/psr-http-message-bridge: 7.4.*
- symfony/runtime: 7.4.*
- symfony/security-bundle: 7.4.*
- symfony/serializer: 7.4.*
- symfony/translation: 7.4.*
- symfony/twig-bundle: 7.4.*
- symfony/ux-live-component: ^2.31
- symfony/validator: 7.4.*
- symfony/yaml: 7.4.*
Requires (Dev)
- doctrine/doctrine-fixtures-bundle: ^4.3
- friendsofphp/php-cs-fixer: ^3.92.3
- phpstan/phpstan: ^2.1.33
- phpunit/phpunit: ^10.5.60
- symfony/browser-kit: 7.4.*
- symfony/css-selector: 7.4.*
- symfony/web-profiler-bundle: 7.4.*
Conflicts
README
Multi-provider MCP server connecting AI assistants (Claude, Cursor) to Redmine, Jira and Monday.
Stack
- Symfony 7.4 / PHP 8.2+
- Doctrine ORM (SQLite)
- MCP SDK (
mcp/sdk) - OAuth 2.0 + Google Sign-In
Architecture
src/
├── Mcp/ # MCP Core
│ ├── Application/
│ │ ├── Tool/ # Tools by provider
│ │ │ ├── Redmine/ # 12 tools
│ │ │ ├── Jira/ # 6 tools
│ │ │ └── Monday/ # 5 tools
│ │ └── Resource/ # MCP Resources
│ ├── Domain/
│ │ ├── Model/ # Issue, Project, TimeEntry, etc.
│ │ └── Port/ # Hexagonal interfaces
│ └── Infrastructure/
│ ├── Adapter/ # AdapterFactory, AdapterHolder
│ └── Provider/ # Redmine/, Jira/, Monday/
│
├── OAuth/ # OAuth 2.0 Server
│ └── Infrastructure/
│ ├── Controller/ # /oauth/authorize, /oauth/token
│ └── Security/ # TokenService, CodeStore
│
└── Admin/ # Multi-tenant Admin Panel
└── Infrastructure/
├── Doctrine/Entity/ # User, Organization, McpSession, AccessToken, InviteLink
├── Controller/ # Dashboard, Users, Sessions, Invites
├── Security/Voter/ # Permissions
└── Service/ # ToolRegistry
MCP Tools
| Tool | Description | Redmine | Jira | Monday |
|---|---|---|---|---|
list_projects |
List projects | x | x | x |
list_issues |
Assigned issues | x | x | x |
get_issue_details |
Details + comments + attachments | x | x | x |
update_issue |
Update status/assignee/% | x | ||
get_attachment |
Download attachment | x | x | x |
list_time_entries |
Time entries | x | x | x |
log_time |
Log time | x | x | |
update_time_entry |
Update time entry | x | ||
delete_time_entry |
Delete time entry | x | ||
add_comment |
Add comment | x | ||
update_comment |
Update comment | x | ||
delete_comment |
Delete comment | x |
MCP Resources (Redmine only)
| Resource | Description | Used by |
|---|---|---|
provider://statuses |
Issue statuses | update_issue, list_issues |
provider://projects/{id}/activities |
Activity types | log_time |
provider://projects/{id}/members |
Project members | update_issue (assignment) |
provider://projects/{id}/wiki |
Wiki pages list | - |
provider://projects/{id}/wiki/{title} |
Wiki page content | - |
Multi-tenancy
Entities
- Organization: provider type, config, enabledTools
- User: email, roles, providerCredentials (encrypted), enabledTools
- McpSession: MCP session with TTL (1h default)
- AccessToken: OAuth tokens (hashed)
- InviteLink: Invite links with expiration
Roles
ROLE_USER: standard userROLE_ORG_ADMIN: org adminROLE_SUPER_ADMIN: access to all orgs
Tool Permissions
// Org allows tool AND (user empty OR user allows) $user->hasToolEnabled('log_time')
Admin Panel
| Route | Description |
|---|---|
/admin |
Dashboard (users, active sessions) |
/admin/users |
User management (approve, roles, tools) |
/admin/sessions |
Active MCP sessions |
/admin/invites |
Invite links |
/admin/organization |
Org config |
Auth Flow
- MCP Client →
/oauth/authorize - → Google Sign-In
- → Provider selection + credentials
- →
/oauth/token→ access_token + refresh_token - MCP Client →
/mcpwith Bearer token
Configuration
# .env.local DATABASE_URL="sqlite:///%kernel.project_dir%/var/data.db" ENCRYPTION_KEY=base64-sodium-key # Google OAuth GOOGLE_CLIENT_ID=xxx.apps.googleusercontent.com GOOGLE_CLIENT_SECRET=xxx # Access control (at least one) ALLOWED_EMAIL_DOMAINS=company.com ALLOWED_EMAILS=user@example.com
Commands
make dev # Install deps make test # PHPUnit make static-analysis # PHPStan + CS make cs-fix # Fix code style make deploy # Docker rebuild # Create bot token php bin/console app:create-bot \ --organization=my-org \ --email=bot@company.com \ --api-key=xxx
Local Dev
composer install
cp .env.example .env.local
# Configure .env.local
symfony server:start --port=8080
Technical Notes
Session TTL
MCP sessions expire after 1h of inactivity (DoctrineSessionStore::$ttl = 3600).
Mixed Types
Numeric tool params use mixed + manual cast to workaround Cursor validation bug.
#[Schema(description: 'Project ID')] mixed $project_id = null, // ... $project_id = (int) $project_id;
ToolRegistry
Auto-discovery via marker interfaces (RedmineTool, JiraTool, MondayTool).
Encryption
Provider credentials encrypted with libsodium (EncryptionService).