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/label"
 | 
			
		||||
	"gitea.com/gitea/gitea-mcp/operation/milestone"
 | 
			
		||||
	"gitea.com/gitea/gitea-mcp/operation/pull"
 | 
			
		||||
	"gitea.com/gitea/gitea-mcp/operation/repo"
 | 
			
		||||
	"gitea.com/gitea/gitea-mcp/operation/search"
 | 
			
		||||
@@ -40,6 +41,9 @@ func RegisterTool(s *server.MCPServer) {
 | 
			
		||||
	// Label Tool
 | 
			
		||||
	s.AddTools(label.Tool.Tools()...)
 | 
			
		||||
 | 
			
		||||
	// Milestone Tool
 | 
			
		||||
	s.AddTools(milestone.Tool.Tools()...)
 | 
			
		||||
 | 
			
		||||
	// Pull Tool
 | 
			
		||||
	s.AddTools(pull.Tool.Tools()...)
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user