mirror of
				https://gitea.com/gitea/gitea-mcp.git
				synced 2025-11-04 12:21:50 +00:00 
			
		
		
		
	Compare commits
	
		
			1 Commits
		
	
	
		
	
	| Author | SHA1 | Date | |
|---|---|---|---|
| 
						 | 
					bdd9fb1816 | 
							
								
								
									
										63
									
								
								BUILDING.md
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										63
									
								
								BUILDING.md
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,63 @@
 | 
				
			|||||||
 | 
					# Building gitea-mcp on Windows
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					This project includes PowerShell and batch scripts to build the gitea-mcp application on Windows systems.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					## Prerequisites
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					- Go 1.24 or later
 | 
				
			||||||
 | 
					- Git (for version information)
 | 
				
			||||||
 | 
					- PowerShell 5.1 or later (included with Windows 10/11)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					## Build Scripts
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					### PowerShell Script (`build.ps1`)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					The main build script that replicates all Makefile functionality:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					```powershell
 | 
				
			||||||
 | 
					# Show help
 | 
				
			||||||
 | 
					.\build.ps1 help
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# Build the application
 | 
				
			||||||
 | 
					.\build.ps1 build
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# Install the application
 | 
				
			||||||
 | 
					.\build.ps1 install
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# Clean build artifacts
 | 
				
			||||||
 | 
					.\build.ps1 clean
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# Run in development mode (hot reload)
 | 
				
			||||||
 | 
					.\build.ps1 dev
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# Update vendor dependencies
 | 
				
			||||||
 | 
					.\build.ps1 vendor
 | 
				
			||||||
 | 
					```
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					### Batch File Wrapper (`build.bat`)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					A simple wrapper to run the PowerShell script:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					```cmd
 | 
				
			||||||
 | 
					# Run with default help target
 | 
				
			||||||
 | 
					build.bat
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# Run specific target
 | 
				
			||||||
 | 
					build.bat build
 | 
				
			||||||
 | 
					build.bat install
 | 
				
			||||||
 | 
					```
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					## Available Targets
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					- **help** - Print help message
 | 
				
			||||||
 | 
					- **build** - Build the application executable
 | 
				
			||||||
 | 
					- **install** - Build and install to GOPATH/bin
 | 
				
			||||||
 | 
					- **uninstall** - Remove executable from GOPATH/bin
 | 
				
			||||||
 | 
					- **clean** - Remove build artifacts
 | 
				
			||||||
 | 
					- **air** - Install air for hot reload development
 | 
				
			||||||
 | 
					- **dev** - Run with hot reload development
 | 
				
			||||||
 | 
					- **vendor** - Tidy and verify Go module dependencies
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					## Output
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					The build process creates `gitea-mcp.exe` in the project directory.
 | 
				
			||||||
							
								
								
									
										2
									
								
								build.bat
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										2
									
								
								build.bat
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,2 @@
 | 
				
			|||||||
 | 
					@echo off
 | 
				
			||||||
 | 
					powershell -ExecutionPolicy Bypass -File "%~dp0build.ps1" %*
 | 
				
			||||||
							
								
								
									
										220
									
								
								build.ps1
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										220
									
								
								build.ps1
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,220 @@
 | 
				
			|||||||
 | 
					#!/usr/bin/env pwsh
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# PowerShell build script for gitea-mcp
 | 
				
			||||||
 | 
					# Replicates the functionality of the Makefile
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					param(
 | 
				
			||||||
 | 
					    [string]$Target = "help"
 | 
				
			||||||
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# Configuration
 | 
				
			||||||
 | 
					$EXECUTABLE = "gitea-mcp.exe"
 | 
				
			||||||
 | 
					$VERSION = & git describe --tags --always 2>$null | ForEach-Object { $_ -replace '-', '+' -replace '^v', '' }
 | 
				
			||||||
 | 
					if (-not $VERSION) { $VERSION = "dev" }
 | 
				
			||||||
 | 
					$LDFLAGS = "-X `"main.Version=$VERSION`""
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# Colors for output (Windows PowerShell compatible)
 | 
				
			||||||
 | 
					$CYAN = "Cyan"
 | 
				
			||||||
 | 
					$RESET = "White"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					function Write-Header {
 | 
				
			||||||
 | 
					    param([string]$Message)
 | 
				
			||||||
 | 
					    Write-Host "=== $Message ===" -ForegroundColor Green
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					function Write-Info {
 | 
				
			||||||
 | 
					    param([string]$Message)
 | 
				
			||||||
 | 
					    Write-Host $Message -ForegroundColor Yellow
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					function Write-Success {
 | 
				
			||||||
 | 
					    param([string]$Message)
 | 
				
			||||||
 | 
					    Write-Host $Message -ForegroundColor Green
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					function Write-Error {
 | 
				
			||||||
 | 
					    param([string]$Message)
 | 
				
			||||||
 | 
					    Write-Host $Message -ForegroundColor Red
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					function Get-Help {
 | 
				
			||||||
 | 
					    Write-Host "Usage: .\build.ps1 [target]" -ForegroundColor Green
 | 
				
			||||||
 | 
					    Write-Host ""
 | 
				
			||||||
 | 
					    Write-Host "Targets:" -ForegroundColor Green
 | 
				
			||||||
 | 
					    Write-Host ""
 | 
				
			||||||
 | 
					    
 | 
				
			||||||
 | 
					    Write-Host ("{0,-30}" -f "help") -ForegroundColor Cyan -NoNewline
 | 
				
			||||||
 | 
					    Write-Host " Print this help message."
 | 
				
			||||||
 | 
					    Write-Host ("{0,-30}" -f "build") -ForegroundColor Cyan -NoNewline
 | 
				
			||||||
 | 
					    Write-Host " Build the application."
 | 
				
			||||||
 | 
					    Write-Host ("{0,-30}" -f "install") -ForegroundColor Cyan -NoNewline
 | 
				
			||||||
 | 
					    Write-Host " Install the application."
 | 
				
			||||||
 | 
					    Write-Host ("{0,-30}" -f "uninstall") -ForegroundColor Cyan -NoNewline
 | 
				
			||||||
 | 
					    Write-Host " Uninstall the application."
 | 
				
			||||||
 | 
					    Write-Host ("{0,-30}" -f "clean") -ForegroundColor Cyan -NoNewline
 | 
				
			||||||
 | 
					    Write-Host " Clean the build artifacts."
 | 
				
			||||||
 | 
					    Write-Host ("{0,-30}" -f "air") -ForegroundColor Cyan -NoNewline
 | 
				
			||||||
 | 
					    Write-Host " Install air for hot reload."
 | 
				
			||||||
 | 
					    Write-Host ("{0,-30}" -f "dev") -ForegroundColor Cyan -NoNewline
 | 
				
			||||||
 | 
					    Write-Host " Run the application with hot reload."
 | 
				
			||||||
 | 
					    Write-Host ("{0,-30}" -f "vendor") -ForegroundColor Cyan -NoNewline
 | 
				
			||||||
 | 
					    Write-Host " Tidy and verify module dependencies."
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					function Build-App {
 | 
				
			||||||
 | 
					    Write-Header "Building application"
 | 
				
			||||||
 | 
					    
 | 
				
			||||||
 | 
					    $ldflags = "-s -w $LDFLAGS"
 | 
				
			||||||
 | 
					    Write-Info "go build -v -ldflags '$ldflags' -o $EXECUTABLE"
 | 
				
			||||||
 | 
					    
 | 
				
			||||||
 | 
					    try {
 | 
				
			||||||
 | 
					        & go build -v -ldflags $ldflags -o $EXECUTABLE
 | 
				
			||||||
 | 
					        if ($LASTEXITCODE -eq 0) {
 | 
				
			||||||
 | 
					            Write-Success "Build successful: $EXECUTABLE"
 | 
				
			||||||
 | 
					        } else {
 | 
				
			||||||
 | 
					            Write-Error "Build failed with exit code: $LASTEXITCODE"
 | 
				
			||||||
 | 
					            exit $LASTEXITCODE
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    } catch {
 | 
				
			||||||
 | 
					        Write-Error "Build failed: $_"
 | 
				
			||||||
 | 
					        exit 1
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					function Install-App {
 | 
				
			||||||
 | 
					    Write-Header "Installing application"
 | 
				
			||||||
 | 
					    
 | 
				
			||||||
 | 
					    # First build the application
 | 
				
			||||||
 | 
					    Build-App
 | 
				
			||||||
 | 
					    
 | 
				
			||||||
 | 
					    $GOPATH = $env:GOPATH
 | 
				
			||||||
 | 
					    if (-not $GOPATH) {
 | 
				
			||||||
 | 
					        $GOPATH = Join-Path $env:USERPROFILE "go"
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    
 | 
				
			||||||
 | 
					    $installDir = Join-Path $GOPATH "bin"
 | 
				
			||||||
 | 
					    $installPath = Join-Path $installDir $EXECUTABLE
 | 
				
			||||||
 | 
					    
 | 
				
			||||||
 | 
					    Write-Info "Installing $EXECUTABLE to $installPath"
 | 
				
			||||||
 | 
					    
 | 
				
			||||||
 | 
					    # Create directory if it doesn't exist
 | 
				
			||||||
 | 
					    if (-not (Test-Path $installDir)) {
 | 
				
			||||||
 | 
					        New-Item -ItemType Directory -Path $installDir -Force | Out-Null
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    
 | 
				
			||||||
 | 
					    # Copy the executable
 | 
				
			||||||
 | 
					    if (Test-Path $EXECUTABLE) {
 | 
				
			||||||
 | 
					        Copy-Item $EXECUTABLE $installPath -Force
 | 
				
			||||||
 | 
					        Write-Success "Installed $EXECUTABLE to $installPath"
 | 
				
			||||||
 | 
					        Write-Info "Please add $installDir to your PATH if it is not already there."
 | 
				
			||||||
 | 
					    } else {
 | 
				
			||||||
 | 
					        Write-Error "Executable not found. Please build first."
 | 
				
			||||||
 | 
					        exit 1
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					function Uninstall-App {
 | 
				
			||||||
 | 
					    Write-Header "Uninstalling application"
 | 
				
			||||||
 | 
					    
 | 
				
			||||||
 | 
					    $GOPATH = $env:GOPATH
 | 
				
			||||||
 | 
					    if (-not $GOPATH) {
 | 
				
			||||||
 | 
					        $GOPATH = Join-Path $env:USERPROFILE "go"
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    
 | 
				
			||||||
 | 
					    $installPath = Join-Path $GOPATH "bin" $EXECUTABLE
 | 
				
			||||||
 | 
					    
 | 
				
			||||||
 | 
					    Write-Info "Uninstalling $EXECUTABLE from $installPath"
 | 
				
			||||||
 | 
					    
 | 
				
			||||||
 | 
					    if (Test-Path $installPath) {
 | 
				
			||||||
 | 
					        Remove-Item $installPath -Force
 | 
				
			||||||
 | 
					        Write-Success "Uninstalled $EXECUTABLE from $installPath"
 | 
				
			||||||
 | 
					    } else {
 | 
				
			||||||
 | 
					        Write-Warning "$EXECUTABLE not found at $installPath"
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					function Clean-Build {
 | 
				
			||||||
 | 
					    Write-Header "Cleaning build artifacts"
 | 
				
			||||||
 | 
					    
 | 
				
			||||||
 | 
					    Write-Info "Cleaning up $EXECUTABLE"
 | 
				
			||||||
 | 
					    
 | 
				
			||||||
 | 
					    if (Test-Path $EXECUTABLE) {
 | 
				
			||||||
 | 
					        Remove-Item $EXECUTABLE -Force
 | 
				
			||||||
 | 
					        Write-Success "Cleaned up $EXECUTABLE"
 | 
				
			||||||
 | 
					    } else {
 | 
				
			||||||
 | 
					        Write-Warning "$EXECUTABLE not found"
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					function Install-Air {
 | 
				
			||||||
 | 
					    Write-Header "Installing air for hot reload"
 | 
				
			||||||
 | 
					    
 | 
				
			||||||
 | 
					    # Check if air is already installed
 | 
				
			||||||
 | 
					    $airPath = Get-Command air -ErrorAction SilentlyContinue
 | 
				
			||||||
 | 
					    if ($airPath) {
 | 
				
			||||||
 | 
					        Write-Success "air is already installed"
 | 
				
			||||||
 | 
					        return
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    
 | 
				
			||||||
 | 
					    Write-Info "Installing github.com/air-verse/air@latest"
 | 
				
			||||||
 | 
					    try {
 | 
				
			||||||
 | 
					        & go install github.com/air-verse/air@latest
 | 
				
			||||||
 | 
					        if ($LASTEXITCODE -eq 0) {
 | 
				
			||||||
 | 
					            Write-Success "air installed successfully"
 | 
				
			||||||
 | 
					        } else {
 | 
				
			||||||
 | 
					            Write-Error "Failed to install air"
 | 
				
			||||||
 | 
					            exit $LASTEXITCODE
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    } catch {
 | 
				
			||||||
 | 
					        Write-Error "Failed to install air: $_"
 | 
				
			||||||
 | 
					        exit 1
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					function Start-Dev {
 | 
				
			||||||
 | 
					    Write-Header "Starting development mode with hot reload"
 | 
				
			||||||
 | 
					    
 | 
				
			||||||
 | 
					    # Install air first
 | 
				
			||||||
 | 
					    Install-Air
 | 
				
			||||||
 | 
					    
 | 
				
			||||||
 | 
					    Write-Info "Starting air with build configuration"
 | 
				
			||||||
 | 
					    & air --build.cmd "go build -o $EXECUTABLE" --build.bin "./$EXECUTABLE"
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					function Update-Vendor {
 | 
				
			||||||
 | 
					    Write-Header "Tidying and verifying module dependencies"
 | 
				
			||||||
 | 
					    
 | 
				
			||||||
 | 
					    Write-Info "Running go mod tidy"
 | 
				
			||||||
 | 
					    & go mod tidy
 | 
				
			||||||
 | 
					    if ($LASTEXITCODE -ne 0) {
 | 
				
			||||||
 | 
					        Write-Error "go mod tidy failed"
 | 
				
			||||||
 | 
					        exit $LASTEXITCODE
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    
 | 
				
			||||||
 | 
					    Write-Info "Running go mod verify"
 | 
				
			||||||
 | 
					    & go mod verify
 | 
				
			||||||
 | 
					    if ($LASTEXITCODE -ne 0) {
 | 
				
			||||||
 | 
					        Write-Error "go mod verify failed"
 | 
				
			||||||
 | 
					        exit $LASTEXITCODE
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    
 | 
				
			||||||
 | 
					    Write-Success "Dependencies updated successfully"
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# Main execution logic
 | 
				
			||||||
 | 
					switch ($Target.ToLower()) {
 | 
				
			||||||
 | 
					    "help" { Get-Help }
 | 
				
			||||||
 | 
					    "build" { Build-App }
 | 
				
			||||||
 | 
					    "install" { Install-App }
 | 
				
			||||||
 | 
					    "uninstall" { Uninstall-App }
 | 
				
			||||||
 | 
					    "clean" { Clean-Build }
 | 
				
			||||||
 | 
					    "air" { Install-Air }
 | 
				
			||||||
 | 
					    "dev" { Start-Dev }
 | 
				
			||||||
 | 
					    "vendor" { Update-Vendor }
 | 
				
			||||||
 | 
					    default {
 | 
				
			||||||
 | 
					        Write-Error "Unknown target: $Target"
 | 
				
			||||||
 | 
					        Write-Host ""
 | 
				
			||||||
 | 
					        Get-Help
 | 
				
			||||||
 | 
					        exit 1
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
							
								
								
									
										275
									
								
								operation/milestone/milestone.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										275
									
								
								operation/milestone/milestone.go
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,275 @@
 | 
				
			|||||||
 | 
					package milestone
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import (
 | 
				
			||||||
 | 
						"context"
 | 
				
			||||||
 | 
						"fmt"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						"gitea.com/gitea/gitea-mcp/pkg/gitea"
 | 
				
			||||||
 | 
						"gitea.com/gitea/gitea-mcp/pkg/log"
 | 
				
			||||||
 | 
						"gitea.com/gitea/gitea-mcp/pkg/ptr"
 | 
				
			||||||
 | 
						"gitea.com/gitea/gitea-mcp/pkg/to"
 | 
				
			||||||
 | 
						"gitea.com/gitea/gitea-mcp/pkg/tool"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						gitea_sdk "code.gitea.io/sdk/gitea"
 | 
				
			||||||
 | 
						"github.com/mark3labs/mcp-go/mcp"
 | 
				
			||||||
 | 
						"github.com/mark3labs/mcp-go/server"
 | 
				
			||||||
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					var Tool = tool.New()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					const (
 | 
				
			||||||
 | 
						GetMilestoneToolName    = "get_milestone"
 | 
				
			||||||
 | 
						ListMilestonesToolName  = "list_milestones"
 | 
				
			||||||
 | 
						CreateMilestoneToolName = "create_milestone"
 | 
				
			||||||
 | 
						EditMilestoneToolName   = "edit_milestone"
 | 
				
			||||||
 | 
						DeleteMilestoneToolName = "delete_milestone"
 | 
				
			||||||
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					var (
 | 
				
			||||||
 | 
						GetMilestoneTool = mcp.NewTool(
 | 
				
			||||||
 | 
							GetMilestoneToolName,
 | 
				
			||||||
 | 
							mcp.WithDescription("get milestone by id"),
 | 
				
			||||||
 | 
							mcp.WithString("owner", mcp.Required(), mcp.Description("repository owner")),
 | 
				
			||||||
 | 
							mcp.WithString("repo", mcp.Required(), mcp.Description("repository name")),
 | 
				
			||||||
 | 
							mcp.WithNumber("id", mcp.Required(), mcp.Description("milestone id")),
 | 
				
			||||||
 | 
						)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						ListMilestonesTool = mcp.NewTool(
 | 
				
			||||||
 | 
							ListMilestonesToolName,
 | 
				
			||||||
 | 
							mcp.WithDescription("List milestones"),
 | 
				
			||||||
 | 
							mcp.WithString("owner", mcp.Required(), mcp.Description("repository owner")),
 | 
				
			||||||
 | 
							mcp.WithString("repo", mcp.Required(), mcp.Description("repository name")),
 | 
				
			||||||
 | 
							mcp.WithString("state", mcp.Description("milestone state"), mcp.DefaultString("all")),
 | 
				
			||||||
 | 
							mcp.WithString("name", mcp.Description("milestone name")),
 | 
				
			||||||
 | 
							mcp.WithNumber("page", mcp.Description("page number"), mcp.DefaultNumber(1)),
 | 
				
			||||||
 | 
							mcp.WithNumber("pageSize", mcp.Description("page size"), mcp.DefaultNumber(100)),
 | 
				
			||||||
 | 
						)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						CreateMilestoneTool = mcp.NewTool(
 | 
				
			||||||
 | 
							CreateMilestoneToolName,
 | 
				
			||||||
 | 
							mcp.WithDescription("create milestone"),
 | 
				
			||||||
 | 
							mcp.WithString("owner", mcp.Required(), mcp.Description("repository owner")),
 | 
				
			||||||
 | 
							mcp.WithString("repo", mcp.Required(), mcp.Description("repository name")),
 | 
				
			||||||
 | 
							mcp.WithString("title", mcp.Required(), mcp.Description("milestone title")),
 | 
				
			||||||
 | 
							mcp.WithString("description", mcp.Description("milestone description")),
 | 
				
			||||||
 | 
							mcp.WithString("due_on", mcp.Description("due date")),
 | 
				
			||||||
 | 
						)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						EditMilestoneTool = mcp.NewTool(
 | 
				
			||||||
 | 
							EditMilestoneToolName,
 | 
				
			||||||
 | 
							mcp.WithDescription("edit milestone"),
 | 
				
			||||||
 | 
							mcp.WithString("owner", mcp.Required(), mcp.Description("repository owner")),
 | 
				
			||||||
 | 
							mcp.WithString("repo", mcp.Required(), mcp.Description("repository name")),
 | 
				
			||||||
 | 
							mcp.WithNumber("id", mcp.Required(), mcp.Description("milestone id")),
 | 
				
			||||||
 | 
							mcp.WithString("title", mcp.Description("milestone title")),
 | 
				
			||||||
 | 
							mcp.WithString("description", mcp.Description("milestone description")),
 | 
				
			||||||
 | 
							mcp.WithString("due_on", mcp.Description("due date")),
 | 
				
			||||||
 | 
							mcp.WithString("state", mcp.Description("milestone state, one of open, closed")),
 | 
				
			||||||
 | 
						)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						DeleteMilestoneTool = mcp.NewTool(
 | 
				
			||||||
 | 
							DeleteMilestoneToolName,
 | 
				
			||||||
 | 
							mcp.WithDescription("delete milestone"),
 | 
				
			||||||
 | 
							mcp.WithString("owner", mcp.Required(), mcp.Description("repository owner")),
 | 
				
			||||||
 | 
							mcp.WithString("repo", mcp.Required(), mcp.Description("repository name")),
 | 
				
			||||||
 | 
							mcp.WithNumber("id", mcp.Required(), mcp.Description("milestone id")),
 | 
				
			||||||
 | 
						)
 | 
				
			||||||
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func init() {
 | 
				
			||||||
 | 
						Tool.RegisterRead(server.ServerTool{
 | 
				
			||||||
 | 
							Tool:    GetMilestoneTool,
 | 
				
			||||||
 | 
							Handler: GetMilestoneFn,
 | 
				
			||||||
 | 
						})
 | 
				
			||||||
 | 
						Tool.RegisterRead(server.ServerTool{
 | 
				
			||||||
 | 
							Tool:    ListMilestonesTool,
 | 
				
			||||||
 | 
							Handler: ListMilestonesFn,
 | 
				
			||||||
 | 
						})
 | 
				
			||||||
 | 
						Tool.RegisterWrite(server.ServerTool{
 | 
				
			||||||
 | 
							Tool:    CreateMilestoneTool,
 | 
				
			||||||
 | 
							Handler: CreateMilestoneFn,
 | 
				
			||||||
 | 
						})
 | 
				
			||||||
 | 
						Tool.RegisterWrite(server.ServerTool{
 | 
				
			||||||
 | 
							Tool:    EditMilestoneTool,
 | 
				
			||||||
 | 
							Handler: EditMilestoneFn,
 | 
				
			||||||
 | 
						})
 | 
				
			||||||
 | 
						Tool.RegisterWrite(server.ServerTool{
 | 
				
			||||||
 | 
							Tool:    DeleteMilestoneTool,
 | 
				
			||||||
 | 
							Handler: DeleteMilestoneFn,
 | 
				
			||||||
 | 
						})
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func GetMilestoneFn(ctx context.Context, req mcp.CallToolRequest) (*mcp.CallToolResult, error) {
 | 
				
			||||||
 | 
						log.Debugf("Called GetMilestoneFn")
 | 
				
			||||||
 | 
						owner, ok := req.GetArguments()["owner"].(string)
 | 
				
			||||||
 | 
						if !ok {
 | 
				
			||||||
 | 
							return to.ErrorResult(fmt.Errorf("owner is required"))
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						repo, ok := req.GetArguments()["repo"].(string)
 | 
				
			||||||
 | 
						if !ok {
 | 
				
			||||||
 | 
							return to.ErrorResult(fmt.Errorf("repo is required"))
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						id, ok := req.GetArguments()["id"].(float64)
 | 
				
			||||||
 | 
						if !ok {
 | 
				
			||||||
 | 
							return to.ErrorResult(fmt.Errorf("id is required"))
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						client, err := gitea.ClientFromContext(ctx)
 | 
				
			||||||
 | 
						if err != nil {
 | 
				
			||||||
 | 
							return to.ErrorResult(fmt.Errorf("get gitea client err: %v", err))
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						milestone, _, err := client.GetMilestone(owner, repo, int64(id))
 | 
				
			||||||
 | 
						if err != nil {
 | 
				
			||||||
 | 
							return to.ErrorResult(fmt.Errorf("get %v/%v/milestone/%v err: %v", owner, repo, int64(id), err))
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return to.TextResult(milestone)
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func ListMilestonesFn(ctx context.Context, req mcp.CallToolRequest) (*mcp.CallToolResult, error) {
 | 
				
			||||||
 | 
						log.Debugf("Called ListMilestonesFn")
 | 
				
			||||||
 | 
						owner, ok := req.GetArguments()["owner"].(string)
 | 
				
			||||||
 | 
						if !ok {
 | 
				
			||||||
 | 
							return to.ErrorResult(fmt.Errorf("owner is required"))
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						repo, ok := req.GetArguments()["repo"].(string)
 | 
				
			||||||
 | 
						if !ok {
 | 
				
			||||||
 | 
							return to.ErrorResult(fmt.Errorf("repo is required"))
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						state, ok := req.GetArguments()["state"].(string)
 | 
				
			||||||
 | 
						if !ok {
 | 
				
			||||||
 | 
							state = "all"
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						name, ok := req.GetArguments()["name"].(string)
 | 
				
			||||||
 | 
						if !ok {
 | 
				
			||||||
 | 
							name = ""
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						page, ok := req.GetArguments()["page"].(float64)
 | 
				
			||||||
 | 
						if !ok {
 | 
				
			||||||
 | 
							page = 1
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						pageSize, ok := req.GetArguments()["pageSize"].(float64)
 | 
				
			||||||
 | 
						if !ok {
 | 
				
			||||||
 | 
							pageSize = 100
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						opt := gitea_sdk.ListMilestoneOption{
 | 
				
			||||||
 | 
							State: gitea_sdk.StateType(state),
 | 
				
			||||||
 | 
							Name:  name,
 | 
				
			||||||
 | 
							ListOptions: gitea_sdk.ListOptions{
 | 
				
			||||||
 | 
								Page:     int(page),
 | 
				
			||||||
 | 
								PageSize: int(pageSize),
 | 
				
			||||||
 | 
							},
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						client, err := gitea.ClientFromContext(ctx)
 | 
				
			||||||
 | 
						if err != nil {
 | 
				
			||||||
 | 
							return to.ErrorResult(fmt.Errorf("get gitea client err: %v", err))
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						milestones, _, err := client.ListRepoMilestones(owner, repo, opt)
 | 
				
			||||||
 | 
						if err != nil {
 | 
				
			||||||
 | 
							return to.ErrorResult(fmt.Errorf("get %v/%v/milestones err: %v", owner, repo, err))
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						return to.TextResult(milestones)
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func CreateMilestoneFn(ctx context.Context, req mcp.CallToolRequest) (*mcp.CallToolResult, error) {
 | 
				
			||||||
 | 
						log.Debugf("Called CreateMilestoneFn")
 | 
				
			||||||
 | 
						owner, ok := req.GetArguments()["owner"].(string)
 | 
				
			||||||
 | 
						if !ok {
 | 
				
			||||||
 | 
							return to.ErrorResult(fmt.Errorf("owner is required"))
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						repo, ok := req.GetArguments()["repo"].(string)
 | 
				
			||||||
 | 
						if !ok {
 | 
				
			||||||
 | 
							return to.ErrorResult(fmt.Errorf("repo is required"))
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						title, ok := req.GetArguments()["title"].(string)
 | 
				
			||||||
 | 
						if !ok {
 | 
				
			||||||
 | 
							return to.ErrorResult(fmt.Errorf("title is required"))
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						opt := gitea_sdk.CreateMilestoneOption{
 | 
				
			||||||
 | 
							Title: title,
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						description, ok := req.GetArguments()["description"].(string)
 | 
				
			||||||
 | 
						if ok {
 | 
				
			||||||
 | 
							opt.Description = description
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						client, err := gitea.ClientFromContext(ctx)
 | 
				
			||||||
 | 
						if err != nil {
 | 
				
			||||||
 | 
							return to.ErrorResult(fmt.Errorf("get gitea client err: %v", err))
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						milestone, _, err := client.CreateMilestone(owner, repo, opt)
 | 
				
			||||||
 | 
						if err != nil {
 | 
				
			||||||
 | 
							return to.ErrorResult(fmt.Errorf("create %v/%v/milestone err: %v", owner, repo, err))
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return to.TextResult(milestone)
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func EditMilestoneFn(ctx context.Context, req mcp.CallToolRequest) (*mcp.CallToolResult, error) {
 | 
				
			||||||
 | 
						log.Debugf("Called EditMilestoneFn")
 | 
				
			||||||
 | 
						owner, ok := req.GetArguments()["owner"].(string)
 | 
				
			||||||
 | 
						if !ok {
 | 
				
			||||||
 | 
							return to.ErrorResult(fmt.Errorf("owner is required"))
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						repo, ok := req.GetArguments()["repo"].(string)
 | 
				
			||||||
 | 
						if !ok {
 | 
				
			||||||
 | 
							return to.ErrorResult(fmt.Errorf("repo is required"))
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						id, ok := req.GetArguments()["id"].(float64)
 | 
				
			||||||
 | 
						if !ok {
 | 
				
			||||||
 | 
							return to.ErrorResult(fmt.Errorf("id is required"))
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						opt := gitea_sdk.EditMilestoneOption{}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						title, ok := req.GetArguments()["title"].(string)
 | 
				
			||||||
 | 
						if ok {
 | 
				
			||||||
 | 
							opt.Title = title
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						description, ok := req.GetArguments()["description"].(string)
 | 
				
			||||||
 | 
						if ok {
 | 
				
			||||||
 | 
							opt.Description = ptr.To(description)
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						state, ok := req.GetArguments()["state"].(string)
 | 
				
			||||||
 | 
						if ok {
 | 
				
			||||||
 | 
							opt.State = ptr.To(gitea_sdk.StateType(state))
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						client, err := gitea.ClientFromContext(ctx)
 | 
				
			||||||
 | 
						if err != nil {
 | 
				
			||||||
 | 
							return to.ErrorResult(fmt.Errorf("get gitea client err: %v", err))
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						milestone, _, err := client.EditMilestone(owner, repo, int64(id), opt)
 | 
				
			||||||
 | 
						if err != nil {
 | 
				
			||||||
 | 
							return to.ErrorResult(fmt.Errorf("edit %v/%v/milestone/%v err: %v", owner, repo, int64(id), err))
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return to.TextResult(milestone)
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func DeleteMilestoneFn(ctx context.Context, req mcp.CallToolRequest) (*mcp.CallToolResult, error) {
 | 
				
			||||||
 | 
						log.Debugf("Called DeleteMilestoneFn")
 | 
				
			||||||
 | 
						owner, ok := req.GetArguments()["owner"].(string)
 | 
				
			||||||
 | 
						if !ok {
 | 
				
			||||||
 | 
							return to.ErrorResult(fmt.Errorf("owner is required"))
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						repo, ok := req.GetArguments()["repo"].(string)
 | 
				
			||||||
 | 
						if !ok {
 | 
				
			||||||
 | 
							return to.ErrorResult(fmt.Errorf("repo is required"))
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						id, ok := req.GetArguments()["id"].(float64)
 | 
				
			||||||
 | 
						if !ok {
 | 
				
			||||||
 | 
							return to.ErrorResult(fmt.Errorf("id is required"))
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						client, err := gitea.ClientFromContext(ctx)
 | 
				
			||||||
 | 
						if err != nil {
 | 
				
			||||||
 | 
							return to.ErrorResult(fmt.Errorf("get gitea client err: %v", err))
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						_, err = client.DeleteMilestone(owner, repo, int64(id))
 | 
				
			||||||
 | 
						if err != nil {
 | 
				
			||||||
 | 
							return to.ErrorResult(fmt.Errorf("delete %v/%v/milestone/%v err: %v", owner, repo, int64(id), err))
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return to.TextResult("Milestone deleted successfully")
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
@@ -12,6 +12,7 @@ import (
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
	"gitea.com/gitea/gitea-mcp/operation/issue"
 | 
						"gitea.com/gitea/gitea-mcp/operation/issue"
 | 
				
			||||||
	"gitea.com/gitea/gitea-mcp/operation/label"
 | 
						"gitea.com/gitea/gitea-mcp/operation/label"
 | 
				
			||||||
 | 
						"gitea.com/gitea/gitea-mcp/operation/milestone"
 | 
				
			||||||
	"gitea.com/gitea/gitea-mcp/operation/pull"
 | 
						"gitea.com/gitea/gitea-mcp/operation/pull"
 | 
				
			||||||
	"gitea.com/gitea/gitea-mcp/operation/repo"
 | 
						"gitea.com/gitea/gitea-mcp/operation/repo"
 | 
				
			||||||
	"gitea.com/gitea/gitea-mcp/operation/search"
 | 
						"gitea.com/gitea/gitea-mcp/operation/search"
 | 
				
			||||||
@@ -40,6 +41,9 @@ func RegisterTool(s *server.MCPServer) {
 | 
				
			|||||||
	// Label Tool
 | 
						// Label Tool
 | 
				
			||||||
	s.AddTools(label.Tool.Tools()...)
 | 
						s.AddTools(label.Tool.Tools()...)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// Milestone Tool
 | 
				
			||||||
 | 
						s.AddTools(milestone.Tool.Tools()...)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	// Pull Tool
 | 
						// Pull Tool
 | 
				
			||||||
	s.AddTools(pull.Tool.Tools()...)
 | 
						s.AddTools(pull.Tool.Tools()...)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 
 | 
				
			|||||||
		Reference in New Issue
	
	Block a user