"""Gitea milestone operations tools for MCP server.""" from typing import Any, Optional from mcp.types import Tool, TextContent from ..client import GiteaClient, GiteaClientError def get_milestone_tools() -> list[Tool]: """Get list of milestone operation tools. Returns: list[Tool]: List of MCP tools for milestone operations. """ return [ Tool( name="gitea_list_milestones", description="List milestones in a Gitea repository with optional state filter", inputSchema={ "type": "object", "properties": { "owner": { "type": "string", "description": "Repository owner (username or organization)", }, "repo": { "type": "string", "description": "Repository name", }, "state": { "type": "string", "description": "Filter by state: open, closed, or all (default: open)", "enum": ["open", "closed", "all"], "default": "open", }, }, "required": ["owner", "repo"], }, ), Tool( name="gitea_create_milestone", description="Create a new milestone in a Gitea repository", inputSchema={ "type": "object", "properties": { "owner": { "type": "string", "description": "Repository owner (username or organization)", }, "repo": { "type": "string", "description": "Repository name", }, "title": { "type": "string", "description": "Milestone title", }, "description": { "type": "string", "description": "Milestone description (optional)", }, "due_on": { "type": "string", "description": "Due date in ISO 8601 format, e.g., '2024-12-31T23:59:59Z' (optional)", }, }, "required": ["owner", "repo", "title"], }, ), ] async def handle_milestone_tool( name: str, arguments: dict[str, Any], client: GiteaClient ) -> list[TextContent]: """Handle milestone tool calls. Args: name: Tool name. arguments: Tool arguments. client: Gitea API client instance. Returns: list[TextContent]: Tool response. """ try: if name == "gitea_list_milestones": return await _list_milestones(arguments, client) elif name == "gitea_create_milestone": return await _create_milestone(arguments, client) else: return [ TextContent( type="text", text=f"Unknown milestone tool: {name}", ) ] except GiteaClientError as e: return [ TextContent( type="text", text=f"Error: {str(e)}", ) ] async def _list_milestones( arguments: dict[str, Any], client: GiteaClient ) -> list[TextContent]: """List milestones in a repository. Args: arguments: Tool arguments containing owner, repo, and optional state filter. client: Gitea API client instance. Returns: list[TextContent]: List of milestones. """ owner = arguments["owner"] repo = arguments["repo"] state = arguments.get("state", "open") params = {"state": state} async with client: milestones = await client.get( f"/repos/{owner}/{repo}/milestones", params=params ) # Format response if not milestones: return [ TextContent( type="text", text=f"No {state} milestones found in {owner}/{repo}", ) ] result = f"Found {len(milestones)} {state} milestone(s) in {owner}/{repo}:\n\n" for milestone in milestones: result += f"{milestone.get('title', 'Untitled')}\n" result += f" State: {milestone.get('state', 'unknown')}\n" if milestone.get("description"): result += f" Description: {milestone['description']}\n" if milestone.get("due_on"): result += f" Due: {milestone['due_on']}\n" result += f" Open Issues: {milestone.get('open_issues', 0)}\n" result += f" Closed Issues: {milestone.get('closed_issues', 0)}\n" result += f" Created: {milestone.get('created_at', 'N/A')}\n\n" return [TextContent(type="text", text=result)] async def _create_milestone( arguments: dict[str, Any], client: GiteaClient ) -> list[TextContent]: """Create a new milestone. Args: arguments: Tool arguments containing owner, repo, title, and optional fields. client: Gitea API client instance. Returns: list[TextContent]: Created milestone details. """ owner = arguments["owner"] repo = arguments["repo"] data = { "title": arguments["title"], } if "description" in arguments: data["description"] = arguments["description"] if "due_on" in arguments: data["due_on"] = arguments["due_on"] async with client: milestone = await client.post( f"/repos/{owner}/{repo}/milestones", json=data ) result = f"Created milestone: {milestone['title']}\n" if milestone.get("description"): result += f"Description: {milestone['description']}\n" if milestone.get("due_on"): result += f"Due: {milestone['due_on']}\n" return [TextContent(type="text", text=result)]