A Model Context Protocol (MCP) server that provides seamless integration with OpenProject API v3. This server enables LLM applications to interact with OpenProject for project management, work package tracking, and task creation.
- 🔌 Full OpenProject API v3 Integration
- 📋 Project Management: List and filter projects
- 📝 Work Package Management: Create, list, and filter work packages
- 🏷️ Type Management: List available work package types
- 🔐 Secure Authentication: API key-based authentication
- 🌐 Proxy Support: Optional HTTP proxy configuration
- 🚀 Async Operations: Built with modern async/await patterns
- 📊 Comprehensive Logging: Configurable logging levels
- Python 3.10 or higher
- uv (fast Python package manager)
- An OpenProject instance (cloud or self-hosted)
- OpenProject API key (generated from your user profile)
macOS/Linux:
curl -LsSf https://astral.sh/uv/install.sh | shWindows:
powershell -c "irm https://astral.sh/uv/install.ps1 | iex"Alternative (using pip):
pip install uvgit clone https://github.com/yourusername/openproject-mcp.git
cd openproject-mcp# Create virtual environment and install dependencies in one command
uv syncAlternative (manual steps):
# Create virtual environment
uv venv
# Install dependencies
uv pip install -r requirements.txt# Copy the environment template
cp env_example.txt .envEdit .env and add your OpenProject configuration:
OPENPROJECT_URL=https://your-instance.openproject.com
OPENPROJECT_API_KEY=your-api-key-here| Variable | Required | Description | Example |
|---|---|---|---|
OPENPROJECT_URL |
Yes | Your OpenProject instance URL | https://mycompany.openproject.com |
OPENPROJECT_API_KEY |
Yes | API key from your OpenProject user profile | 8169846b42461e6e... |
OPENPROJECT_PROXY |
No | HTTP proxy URL if needed | http://proxy.company.com:8080 |
LOG_LEVEL |
No | Logging level (DEBUG, INFO, WARNING, ERROR) | INFO |
TEST_CONNECTION_ON_STARTUP |
No | Test API connection when server starts | true |
- Log in to your OpenProject instance
- Go to My account (click your avatar)
- Navigate to Access tokens
- Click + Add to create a new token
- Give it a name and copy the generated token
Using uv (recommended):
uv run python openproject-mcp.pyAlternative (manual activation):
# Activate virtual environment
source .venv/bin/activate # On Windows: .venv\Scripts\activate
# Run the server
python openproject-mcp.pyNote: If you renamed the file from openproject_mcp_server.py, update your configuration accordingly.
Add this configuration to your Claude Desktop config file:
Windows: %APPDATA%\Claude\claude_desktop_config.json
macOS: ~/Library/Application Support/Claude/claude_desktop_config.json
{
"mcpServers": {
"openproject": {
"command": "/path/to/your/project/.venv/bin/python",
"args": ["/path/to/your/project/openproject-mcp.py"]
}
}
}Note: Replace /path/to/your/project/ with the actual path to your project directory.
Alternative with uv (if uv is in your system PATH):
{
"mcpServers": {
"openproject": {
"command": "uv",
"args": ["run", "python", "/path/to/your/project/openproject-mcp.py"]
}
}
}Why use the direct Python path? The direct Python path approach is more reliable because:
- It doesn't require
uvto be in the system PATH - It avoids potential issues with
uv runtrying to install the project as a package - It's simpler and more straightforward for MCP server configurations
Test the connection to your OpenProject instance.
Example:
Test the OpenProject connection
List all projects you have access to.
Parameters:
active_only(boolean, optional): Show only active projects (default: true)
Example:
List all active projects
List work packages with optional filtering.
Parameters:
project_id(integer, optional): Filter by specific projectstatus(string, optional): Filter by status - "open", "closed", or "all" (default: "open")
Example:
Show all open work packages in project 5
List available work package types.
Parameters:
project_id(integer, optional): Filter types by project
Example:
List all work package types
Create a new work package.
Parameters:
project_id(integer, required): The project IDsubject(string, required): Work package titletype_id(integer, required): Type ID (e.g., 1 for Task)description(string, optional): Description in Markdown formatpriority_id(integer, optional): Priority IDassignee_id(integer, optional): User ID to assign to
Example:
Create a new task in project 5 titled "Update documentation" with type ID 1
List all users in the OpenProject instance.
Parameters:
active_only(boolean, optional): Show only active users (default: true)
Get detailed information about a specific user.
Parameters:
user_id(integer, required): User ID
List project memberships showing users and their roles.
Parameters:
project_id(integer, optional): Filter by specific projectuser_id(integer, optional): Filter by specific user
List all available work package statuses.
List all available work package priorities.
Get detailed information about a specific work package.
Parameters:
work_package_id(integer, required): Work package ID
Update an existing work package.
Parameters:
work_package_id(integer, required): Work package IDsubject(string, optional): Work package titledescription(string, optional): Description in Markdown formattype_id(integer, optional): Type IDstatus_id(integer, optional): Status IDpriority_id(integer, optional): Priority IDassignee_id(integer, optional): User ID to assign topercentage_done(integer, optional): Completion percentage (0-100)
Delete a work package.
Parameters:
work_package_id(integer, required): Work package ID
List time entries with optional filtering.
Parameters:
work_package_id(integer, optional): Filter by specific work packageuser_id(integer, optional): Filter by specific user
Create a new time entry.
Parameters:
work_package_id(integer, required): Work package IDhours(number, required): Hours spent (e.g., 2.5)spent_on(string, required): Date when time was spent (YYYY-MM-DD format)comment(string, optional): Comment/descriptionactivity_id(integer, optional): Activity ID
Update an existing time entry.
Parameters:
time_entry_id(integer, required): Time entry IDhours(number, optional): Hours spentspent_on(string, optional): Date when time was spentcomment(string, optional): Comment/descriptionactivity_id(integer, optional): Activity ID
Delete a time entry.
Parameters:
time_entry_id(integer, required): Time entry ID
List available time entry activities.
List project versions/milestones.
Parameters:
project_id(integer, optional): Filter by specific project
Create a new project version/milestone.
Parameters:
project_id(integer, required): Project IDname(string, required): Version namedescription(string, optional): Version descriptionstart_date(string, optional): Start date (YYYY-MM-DD format)end_date(string, optional): End date (YYYY-MM-DD format)status(string, optional): Version status (open, locked, closed)
Create a new project.
Parameters:
name(string, required): Project nameidentifier(string, required): Project identifier (unique)description(string, optional): Project descriptionpublic(boolean, optional): Whether the project is publicstatus(string, optional): Project statusparent_id(integer, optional): Parent project ID
Example:
Create a new project named "Website Redesign" with identifier "web-redesign"
Update an existing project.
Parameters:
project_id(integer, required): Project IDname(string, optional): Project nameidentifier(string, optional): Project identifierdescription(string, optional): Project descriptionpublic(boolean, optional): Whether the project is publicstatus(string, optional): Project statusparent_id(integer, optional): Parent project ID
Delete a project.
Parameters:
project_id(integer, required): Project ID
Get detailed information about a specific project.
Parameters:
project_id(integer, required): Project ID
Create a new project membership.
Parameters:
project_id(integer, required): Project IDuser_id(integer, optional): User ID (required if group_id not provided)group_id(integer, optional): Group ID (required if user_id not provided)role_ids(array, optional): Array of role IDsrole_id(integer, optional): Single role ID (alternative to role_ids)notification_message(string, optional): Optional notification message
Example:
Add user 5 to project 2 with role ID 3 (Developer role)
Update an existing membership.
Parameters:
membership_id(integer, required): Membership IDrole_ids(array, optional): Array of role IDsrole_id(integer, optional): Single role IDnotification_message(string, optional): Optional notification message
Delete a membership.
Parameters:
membership_id(integer, required): Membership ID
Get detailed information about a specific membership.
Parameters:
membership_id(integer, required): Membership ID
List all members of a specific project.
Parameters:
project_id(integer, required): Project ID
Example:
List all members of project 5
List all projects a specific user is assigned to.
Parameters:
user_id(integer, required): User ID
List all available roles.
Example:
List all available roles in the OpenProject instance
Get detailed information about a specific role.
Parameters:
role_id(integer, required): Role ID
Set a parent for a work package (create parent-child relationship).
Parameters:
work_package_id(integer, required): Work package ID to become a childparent_id(integer, required): Work package ID to become the parent
Example:
Set work package 15 as a child of work package 10
Remove parent relationship from a work package (make it top-level).
Parameters:
work_package_id(integer, required): Work package ID to remove parent from
List all child work packages of a parent.
Parameters:
parent_id(integer, required): Parent work package IDinclude_descendants(boolean, optional): Include grandchildren and all descendants (default: false)
Example:
List all children of work package 10 including descendants
Create a relationship between work packages.
Parameters:
from_id(integer, required): Source work package IDto_id(integer, required): Target work package IDrelation_type(string, required): Relation type (blocks, follows, precedes, relates, duplicates, includes, requires, partof)lag(integer, optional): Lag in working days (for follows/precedes)description(string, optional): Optional description of the relation
Example:
Create a "blocks" relation where work package 5 blocks work package 8
List work package relations with optional filtering.
Parameters:
work_package_id(integer, optional): Filter relations involving this work package IDrelation_type(string, optional): Filter by relation type
Update an existing work package relation.
Parameters:
relation_id(integer, required): Relation IDrelation_type(string, optional): New relation typelag(integer, optional): Lag in working daysdescription(string, optional): Optional description
Delete a work package relation.
Parameters:
relation_id(integer, required): Relation ID
Get detailed information about a specific work package relation.
Parameters:
relation_id(integer, required): Relation ID
# Install development dependencies
uv sync --extra dev
# Or install manually
uv pip install -e ".[dev]"uv run pytest tests/# Format code
uv run black openproject-mcp.py
# Lint code
uv run flake8 openproject-mcp.py# Add a new dependency
uv add package-name
# Add a development dependency
uv add --dev package-name
# Update dependencies
uv syncAll these tools have been tested and work correctly with admin privileges:
Core Project Management:
test_connection,check_permissions,list_projects,create_project,update_projectdelete_project,get_project
Work Package Management:
list_work_packages,list_types,create_work_package,update_work_packagedelete_work_package,get_work_package,list_statuses,list_priorities
Work Package Hierarchy & Relations:
set_work_package_parent,remove_work_package_parent,list_work_package_childrencreate_work_package_relation,list_work_package_relations,update_work_package_relationdelete_work_package_relation,get_work_package_relation
User & Membership Management:
list_users,get_user,create_membership,update_membership,delete_membershipget_membership,list_project_members,list_user_projects,list_roles,get_role
Time Tracking:
list_time_entries,create_time_entry,update_time_entry,delete_time_entry
Project Versions:
list_versions,create_version
list_memberships: Works globally and withproject_idfiltering. User ID filtering (user_id) may not be supported in all OpenProject instances.
list_time_entry_activities: Returns 404 but time entry activities ARE functional! Use these predefined activity IDs:- Management (ID: 1): Administrative and planning tasks
- Specification (ID: 2): Requirements and documentation
- Development (ID: 3): Coding and implementation
- Testing (ID: 4): Quality assurance and testing
Example: create_time_entry with activity_id: 3 for Development work
Most create/update/delete operations require appropriate permissions:
- Project Operations: Require global "Create project" and "Edit project" permissions. Deletion typically requires admin rights
- Work Package Operations: Require "Create/Edit work packages" permission in target projects
- Work Package Relations & Hierarchy: Require "Edit work packages" permission for creating/modifying parent-child relationships and dependencies
- Membership Management: Require "Manage members" permission for target projects
- Time Entry Operations: Require time tracking permissions
- Version Management: Require project admin or version management permissions
- User Operations: Admin privileges may be needed for comprehensive user management
- Role Management: Read-only operations generally available; admin privileges may be needed for detailed role information
Use the check_permissions tool to diagnose permission-related issues.
- 401 Unauthorized: Check your API key is correct and active
- 403 Forbidden: Ensure your user has the necessary permissions
- 404 Not Found: Verify the OpenProject URL and that resources exist
- Proxy Errors: Check proxy settings and authentication
Enable debug logging by setting:
LOG_LEVEL=DEBUG- No projects found: Ensure your API user has project view permissions
- SSL errors: May occur with self-signed certificates or proxy SSL interception
- Timeout errors: Increase timeout or check network connectivity
- Never commit your
.envfile to version control - Use environment variables for sensitive data
- Rotate API keys regularly
- Use HTTPS for all OpenProject connections
- Configure proxy authentication securely if needed
- Fork the repository
- Create a feature branch (
git checkout -b feature/amazing-feature) - Commit your changes (
git commit -m 'Add amazing feature') - Push to the branch (
git push origin feature/amazing-feature) - Open a Pull Request
This project is licensed under the MIT License - see the LICENSE file for details.
- Built for the Model Context Protocol
- Integrates with OpenProject
- Inspired by the MCP community
- 🐛 Issues: GitHub Issues
- 💬 Discussions: GitHub Discussions