"""Project management tools for OpenProject MCP server."""
from typing import Any
from ..client import OpenProjectClient
from ..utils.hal import build_formattable
async def get_project(project_id: str) -> dict[str, Any]:
"""Get detailed information about a project.
Args:
project_id: Project identifier or ID
Returns:
Project object with all properties, links, and embedded resources
"""
client = OpenProjectClient()
try:
result = await client.get(f"projects/{project_id}")
return result
finally:
await client.close()
async def list_projects(
filters: str | None = None, page: int = 1, page_size: int = 20
) -> dict[str, Any]:
"""List all accessible projects with optional filtering and pagination.
Args:
filters: Optional JSON filter string (e.g., '[{"active":{"operator":"=","values":["t"]}}]')
page: Page number (default: 1)
page_size: Items per page (default: 20)
Returns:
Paginated collection of projects with metadata
"""
client = OpenProjectClient()
try:
params: dict[str, Any] = {
"pageSize": page_size,
"offset": (page - 1) * page_size,
}
if filters:
params["filters"] = filters
result = await client.get("projects", params=params)
return result
finally:
await client.close()
async def update_project(
project_id: str,
lock_version: int,
name: str | None = None,
description: str | None = None,
public: bool | None = None,
active: bool | None = None,
) -> dict[str, Any]:
"""Update an existing project.
Args:
project_id: Project identifier or ID
lock_version: Current lock version (get from project first)
name: New project name
description: New project description in markdown
public: Whether project is public
active: Whether project is active
Returns:
Updated project object
"""
client = OpenProjectClient()
try:
payload: dict[str, Any] = {
"lockVersion": lock_version,
}
if name is not None:
payload["name"] = name
if description is not None:
payload["description"] = build_formattable(description)
if public is not None:
payload["public"] = public
if active is not None:
payload["active"] = active
result = await client.patch(f"projects/{project_id}", data=payload)
return result
finally:
await client.close()