mirror of
https://gitea.com/gitea/gitea-mcp.git
synced 2025-11-03 03:41:50 +00:00
## 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>
146 lines
3.4 KiB
Go
146 lines
3.4 KiB
Go
package operation
|
|
|
|
import (
|
|
"context"
|
|
"fmt"
|
|
"net/http"
|
|
"os"
|
|
"os/signal"
|
|
"strings"
|
|
"syscall"
|
|
"time"
|
|
|
|
"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"
|
|
"gitea.com/gitea/gitea-mcp/operation/user"
|
|
"gitea.com/gitea/gitea-mcp/operation/version"
|
|
"gitea.com/gitea/gitea-mcp/operation/wiki"
|
|
mcpContext "gitea.com/gitea/gitea-mcp/pkg/context"
|
|
"gitea.com/gitea/gitea-mcp/pkg/flag"
|
|
"gitea.com/gitea/gitea-mcp/pkg/log"
|
|
|
|
"github.com/mark3labs/mcp-go/server"
|
|
)
|
|
|
|
var mcpServer *server.MCPServer
|
|
|
|
func RegisterTool(s *server.MCPServer) {
|
|
// User Tool
|
|
s.AddTools(user.Tool.Tools()...)
|
|
|
|
// Repo Tool
|
|
s.AddTools(repo.Tool.Tools()...)
|
|
|
|
// Issue Tool
|
|
s.AddTools(issue.Tool.Tools()...)
|
|
|
|
// Label Tool
|
|
s.AddTools(label.Tool.Tools()...)
|
|
|
|
// Milestone Tool
|
|
s.AddTools(milestone.Tool.Tools()...)
|
|
|
|
// Pull Tool
|
|
s.AddTools(pull.Tool.Tools()...)
|
|
|
|
// Search Tool
|
|
s.AddTools(search.Tool.Tools()...)
|
|
|
|
// Version Tool
|
|
s.AddTools(version.Tool.Tools()...)
|
|
|
|
// Wiki Tool
|
|
s.AddTools(wiki.Tool.Tools()...)
|
|
|
|
s.DeleteTools("")
|
|
}
|
|
|
|
// parseBearerToken extracts the Bearer token from an Authorization header.
|
|
// Returns the token and true if valid, empty string and false otherwise.
|
|
func parseBearerToken(authHeader string) (string, bool) {
|
|
const bearerPrefix = "Bearer "
|
|
if len(authHeader) < len(bearerPrefix) || !strings.HasPrefix(authHeader, bearerPrefix) {
|
|
return "", false
|
|
}
|
|
|
|
token := strings.TrimSpace(authHeader[len(bearerPrefix):])
|
|
if token == "" {
|
|
return "", false
|
|
}
|
|
|
|
return token, true
|
|
}
|
|
|
|
func getContextWithToken(ctx context.Context, r *http.Request) context.Context {
|
|
authHeader := r.Header.Get("Authorization")
|
|
if authHeader == "" {
|
|
return ctx
|
|
}
|
|
|
|
token, ok := parseBearerToken(authHeader)
|
|
if !ok {
|
|
return ctx
|
|
}
|
|
|
|
return context.WithValue(ctx, mcpContext.TokenContextKey, token)
|
|
}
|
|
|
|
func Run() error {
|
|
mcpServer = newMCPServer(flag.Version)
|
|
RegisterTool(mcpServer)
|
|
switch flag.Mode {
|
|
case "stdio":
|
|
if err := server.ServeStdio(
|
|
mcpServer,
|
|
); err != nil {
|
|
return err
|
|
}
|
|
case "http":
|
|
httpServer := server.NewStreamableHTTPServer(
|
|
mcpServer,
|
|
server.WithLogger(log.New()),
|
|
server.WithHeartbeatInterval(30*time.Second),
|
|
server.WithHTTPContextFunc(getContextWithToken),
|
|
)
|
|
log.Infof("Gitea MCP HTTP server listening on :%d", flag.Port)
|
|
|
|
// Graceful shutdown setup
|
|
sigCh := make(chan os.Signal, 1)
|
|
signal.Notify(sigCh, os.Interrupt, syscall.SIGTERM)
|
|
shutdownDone := make(chan struct{})
|
|
|
|
go func() {
|
|
<-sigCh
|
|
log.Infof("Shutdown signal received, gracefully stopping HTTP server...")
|
|
shutdownCtx, cancel := context.WithTimeout(context.Background(), 10*time.Second)
|
|
defer cancel()
|
|
if err := httpServer.Shutdown(shutdownCtx); err != nil {
|
|
log.Errorf("HTTP server shutdown error: %v", err)
|
|
}
|
|
close(shutdownDone)
|
|
}()
|
|
|
|
if err := httpServer.Start(fmt.Sprintf(":%d", flag.Port)); err != nil {
|
|
return err
|
|
}
|
|
<-shutdownDone // Wait for shutdown to finish
|
|
default:
|
|
return fmt.Errorf("invalid transport type: %s. Must be 'stdio' or 'http'", flag.Mode)
|
|
}
|
|
return nil
|
|
}
|
|
|
|
func newMCPServer(version string) *server.MCPServer {
|
|
return server.NewMCPServer(
|
|
"Gitea MCP Server",
|
|
version,
|
|
server.WithToolCapabilities(true),
|
|
server.WithLogging(),
|
|
server.WithRecovery(),
|
|
)
|
|
}
|