mirror of
https://gitea.com/gitea/gitea-mcp.git
synced 2025-11-03 03:41:50 +00:00
Milestone addition and Windows build support (#104)
## Milestone Implementation The `milestone.go` file adds comprehensive milestone functionality to the Gitea MCP server with the following MCP tools: ### Tools Added: 1. __`get_milestone`__ - Retrieves a specific milestone by ID 2. __`list_milestones`__ - Lists repository milestones with filtering options 3. __`create_milestone`__ - Creates new milestones with title, description, and due dates 4. __`edit_milestone`__ - Modifies existing milestones including state changes 5. __`delete_milestone`__ - Removes milestones from repositories ### Integration with Other Components: __Issue Management__: - Issues can be associated with milestones through the `edit_issue` tool - The `milestone` parameter (number) links issues to specific milestones - This creates traceability between development tasks and project milestones __Pull Request Filtering__: - Pull requests can be filtered by milestone using the `milestone` parameter - This enables viewing all PRs related to a specific milestone ### Key Features: - __State Management__: Milestones support "open" and "closed" states - __Due Dates__: Optional due dates for milestone tracking - __Pagination__: List operations support pagination for large datasets - __Full CRUD Operations__: Complete create, read, update, delete capabilities ### Workflow Integration: While there's no direct commit message integration shown in the current implementation, milestones provide project planning capabilities that integrate with: - Issue tracking (linking issues to milestones) - Development workflow (filtering PRs by milestone) - Project management (due dates, state tracking) This addition enables project management capabilities within the Gitea MCP server, allowing users to organize work into milestones and track progress across issues and pull requests. ---------------------- feat: add Windows build support with PowerShell and batch scripts Add comprehensive Windows build support including PowerShell script (build.ps1) and batch wrapper (build.bat) that replicate Makefile functionality. The scripts provide targets for building, installing, cleaning, and development with hot reload support. Also includes detailed BUILDING.md documentation for Windows users. Co-authored-by: hiifong <i@hiif.ong> Reviewed-on: https://gitea.com/gitea/gitea-mcp/pulls/104 Reviewed-by: hiifong <i@hiif.ong> Co-authored-by: Nassim Amar <namar0x0309@pm.me> Co-committed-by: Nassim Amar <namar0x0309@pm.me>
This commit is contained in:
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