Files
leo-claude-mktplace/plugins/projman/mcp-servers/gitea/mcp_server/tools/milestones.py
lmiranda 74b28170fa feat: major improvements to projman plugin v1.0.0
- Remove Wiki.js MCP server entirely
- Add wiki, milestone, and dependency tools to Gitea MCP server
- Add parallel execution support based on dependency graph
- Add mandatory pre-planning validations (org check, labels, docs/changes)
- Add CLI blocking rules to all agents (API-only)
- Add standardized task naming: [Sprint XX] <type>: <description>
- Add branch naming convention: feat/, fix/, debug/ prefixes
- Add MR body template without subtasks
- Add auto-close issues via commit keywords
- Create claude-config-maintainer plugin for CLAUDE.md optimization
- Update all sprint commands with new tools and workflows
- Update documentation to remove Wiki.js references

New MCP tools:
- Wiki: list_wiki_pages, get_wiki_page, create_wiki_page, create_lesson, search_lessons
- Milestones: list_milestones, get_milestone, create_milestone, update_milestone
- Dependencies: list_issue_dependencies, create_issue_dependency, get_execution_order
- Validation: validate_repo_org, get_branch_protection, create_label

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-19 17:12:35 -05:00

146 lines
3.8 KiB
Python

"""
Milestone management tools for MCP server.
Provides async wrappers for milestone operations:
- CRUD operations for milestones
- Milestone-sprint relationship tracking
"""
import asyncio
import logging
from typing import List, Dict, Optional
logging.basicConfig(level=logging.INFO)
logger = logging.getLogger(__name__)
class MilestoneTools:
"""Async wrappers for Gitea milestone operations"""
def __init__(self, gitea_client):
"""
Initialize milestone tools.
Args:
gitea_client: GiteaClient instance
"""
self.gitea = gitea_client
async def list_milestones(
self,
state: str = 'open',
repo: Optional[str] = None
) -> List[Dict]:
"""
List all milestones in repository.
Args:
state: Milestone state (open, closed, all)
repo: Repository in owner/repo format
Returns:
List of milestone dictionaries
"""
loop = asyncio.get_event_loop()
return await loop.run_in_executor(
None,
lambda: self.gitea.list_milestones(state, repo)
)
async def get_milestone(
self,
milestone_id: int,
repo: Optional[str] = None
) -> Dict:
"""
Get a specific milestone by ID.
Args:
milestone_id: Milestone ID
repo: Repository in owner/repo format
Returns:
Milestone dictionary
"""
loop = asyncio.get_event_loop()
return await loop.run_in_executor(
None,
lambda: self.gitea.get_milestone(milestone_id, repo)
)
async def create_milestone(
self,
title: str,
description: Optional[str] = None,
due_on: Optional[str] = None,
repo: Optional[str] = None
) -> Dict:
"""
Create a new milestone.
Args:
title: Milestone title (e.g., "v2.0 Release", "Sprint 17")
description: Milestone description
due_on: Due date in ISO 8601 format (e.g., "2025-02-01T00:00:00Z")
repo: Repository in owner/repo format
Returns:
Created milestone dictionary
"""
loop = asyncio.get_event_loop()
return await loop.run_in_executor(
None,
lambda: self.gitea.create_milestone(title, description, due_on, repo)
)
async def update_milestone(
self,
milestone_id: int,
title: Optional[str] = None,
description: Optional[str] = None,
state: Optional[str] = None,
due_on: Optional[str] = None,
repo: Optional[str] = None
) -> Dict:
"""
Update an existing milestone.
Args:
milestone_id: Milestone ID
title: New title (optional)
description: New description (optional)
state: New state - 'open' or 'closed' (optional)
due_on: New due date (optional)
repo: Repository in owner/repo format
Returns:
Updated milestone dictionary
"""
loop = asyncio.get_event_loop()
return await loop.run_in_executor(
None,
lambda: self.gitea.update_milestone(
milestone_id, title, description, state, due_on, repo
)
)
async def delete_milestone(
self,
milestone_id: int,
repo: Optional[str] = None
) -> bool:
"""
Delete a milestone.
Args:
milestone_id: Milestone ID
repo: Repository in owner/repo format
Returns:
True if deleted successfully
"""
loop = asyncio.get_event_loop()
return await loop.run_in_executor(
None,
lambda: self.gitea.delete_milestone(milestone_id, repo)
)