- 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>
146 lines
3.8 KiB
Python
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)
|
|
)
|