Initial commit: Gitea MCP Server
This commit is contained in:
@@ -0,0 +1,227 @@
|
||||
package stars
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
|
||||
"gitea.com/gitea/gitea-mcp/pkg/gitea"
|
||||
"gitea.com/gitea/gitea-mcp/pkg/log"
|
||||
"gitea.com/gitea/gitea-mcp/pkg/params"
|
||||
"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 (
|
||||
StarsReadToolName = "stars_read"
|
||||
StarsWriteToolName = "stars_write"
|
||||
)
|
||||
|
||||
var (
|
||||
StarsReadTool = mcp.NewTool(
|
||||
StarsReadToolName,
|
||||
mcp.WithDescription("Read stars information. Use method 'list_stargazers' to list repo stargazers, 'list_starred' to list user's starred repos, 'my_starred' for your starred repos, 'check' to check if user starred a repo."),
|
||||
mcp.WithString("method", mcp.Required(), mcp.Description("operation to perform"), mcp.Enum("list_stargazers", "list_starred", "my_starred", "check")),
|
||||
mcp.WithString("owner", mcp.Required(), mcp.Description("repository owner")),
|
||||
mcp.WithString("repo", mcp.Required(), mcp.Description("repository name")),
|
||||
mcp.WithString("user", mcp.Description("username (for 'list_starred', 'check')")),
|
||||
)
|
||||
|
||||
StarsWriteTool = mcp.NewTool(
|
||||
StarsWriteToolName,
|
||||
mcp.WithDescription("Star or unstar a repository."),
|
||||
mcp.WithString("method", mcp.Required(), mcp.Description("operation to perform"), mcp.Enum("star", "unstar")),
|
||||
mcp.WithString("owner", mcp.Required(), mcp.Description("repository owner")),
|
||||
mcp.WithString("repo", mcp.Required(), mcp.Description("repository name")),
|
||||
)
|
||||
)
|
||||
|
||||
func init() {
|
||||
Tool.RegisterRead(server.ServerTool{
|
||||
Tool: StarsReadTool,
|
||||
Handler: starsReadFn,
|
||||
})
|
||||
Tool.RegisterWrite(server.ServerTool{
|
||||
Tool: StarsWriteTool,
|
||||
Handler: starsWriteFn,
|
||||
})
|
||||
}
|
||||
|
||||
func starsReadFn(ctx context.Context, req mcp.CallToolRequest) (*mcp.CallToolResult, error) {
|
||||
method, err := params.GetString(req.GetArguments(), "method")
|
||||
if err != nil {
|
||||
return to.ErrorResult(err)
|
||||
}
|
||||
switch method {
|
||||
case "list_stargazers":
|
||||
return listStargazersFn(ctx, req)
|
||||
case "list_starred":
|
||||
return listStarredFn(ctx, req)
|
||||
case "my_starred":
|
||||
return myStarredFn(ctx, req)
|
||||
case "check":
|
||||
return checkStarFn(ctx, req)
|
||||
default:
|
||||
return to.ErrorResult(fmt.Errorf("unknown method: %s", method))
|
||||
}
|
||||
}
|
||||
|
||||
func starsWriteFn(ctx context.Context, req mcp.CallToolRequest) (*mcp.CallToolResult, error) {
|
||||
method, err := params.GetString(req.GetArguments(), "method")
|
||||
if err != nil {
|
||||
return to.ErrorResult(err)
|
||||
}
|
||||
switch method {
|
||||
case "star":
|
||||
return starRepoFn(ctx, req)
|
||||
case "unstar":
|
||||
return unstarRepoFn(ctx, req)
|
||||
default:
|
||||
return to.ErrorResult(fmt.Errorf("unknown method: %s", method))
|
||||
}
|
||||
}
|
||||
|
||||
func listStargazersFn(ctx context.Context, req mcp.CallToolRequest) (*mcp.CallToolResult, error) {
|
||||
log.Debugf("Called listStargazersFn")
|
||||
owner, err := params.GetString(req.GetArguments(), "owner")
|
||||
if err != nil {
|
||||
return to.ErrorResult(err)
|
||||
}
|
||||
repo, err := params.GetString(req.GetArguments(), "repo")
|
||||
if err != nil {
|
||||
return to.ErrorResult(err)
|
||||
}
|
||||
client, err := gitea.ClientFromContext(ctx)
|
||||
if err != nil {
|
||||
return to.ErrorResult(fmt.Errorf("get gitea client err: %v", err))
|
||||
}
|
||||
users, _, err := client.ListRepoStargazers(owner, repo, gitea_sdk.ListStargazersOptions{})
|
||||
if err != nil {
|
||||
return to.ErrorResult(fmt.Errorf("list stargazers err: %v", err))
|
||||
}
|
||||
return to.TextResult(slimUsers(users))
|
||||
}
|
||||
|
||||
func listStarredFn(ctx context.Context, req mcp.CallToolRequest) (*mcp.CallToolResult, error) {
|
||||
log.Debugf("Called listStarredFn")
|
||||
user, err := params.GetString(req.GetArguments(), "user")
|
||||
if err != nil {
|
||||
return to.ErrorResult(err)
|
||||
}
|
||||
client, err := gitea.ClientFromContext(ctx)
|
||||
if err != nil {
|
||||
return to.ErrorResult(fmt.Errorf("get gitea client err: %v", err))
|
||||
}
|
||||
repos, _, err := client.GetStarredRepos(user)
|
||||
if err != nil {
|
||||
return to.ErrorResult(fmt.Errorf("list starred repos err: %v", err))
|
||||
}
|
||||
return to.TextResult(slimRepos(repos))
|
||||
}
|
||||
|
||||
func myStarredFn(ctx context.Context, req mcp.CallToolRequest) (*mcp.CallToolResult, error) {
|
||||
log.Debugf("Called myStarredFn")
|
||||
client, err := gitea.ClientFromContext(ctx)
|
||||
if err != nil {
|
||||
return to.ErrorResult(fmt.Errorf("get gitea client err: %v", err))
|
||||
}
|
||||
repos, _, err := client.GetMyStarredRepos()
|
||||
if err != nil {
|
||||
return to.ErrorResult(fmt.Errorf("list my starred repos err: %v", err))
|
||||
}
|
||||
return to.TextResult(slimRepos(repos))
|
||||
}
|
||||
|
||||
func checkStarFn(ctx context.Context, req mcp.CallToolRequest) (*mcp.CallToolResult, error) {
|
||||
log.Debugf("Called checkStarFn")
|
||||
owner, err := params.GetString(req.GetArguments(), "owner")
|
||||
if err != nil {
|
||||
return to.ErrorResult(err)
|
||||
}
|
||||
repo, err := params.GetString(req.GetArguments(), "repo")
|
||||
if err != nil {
|
||||
return to.ErrorResult(err)
|
||||
}
|
||||
client, err := gitea.ClientFromContext(ctx)
|
||||
if err != nil {
|
||||
return to.ErrorResult(fmt.Errorf("get gitea client err: %v", err))
|
||||
}
|
||||
starred, _, err := client.IsRepoStarring(owner, repo)
|
||||
if err != nil {
|
||||
return to.ErrorResult(fmt.Errorf("check star err: %v", err))
|
||||
}
|
||||
return to.TextResult(map[string]any{"starred": starred})
|
||||
}
|
||||
|
||||
func starRepoFn(ctx context.Context, req mcp.CallToolRequest) (*mcp.CallToolResult, error) {
|
||||
log.Debugf("Called starRepoFn")
|
||||
owner, err := params.GetString(req.GetArguments(), "owner")
|
||||
if err != nil {
|
||||
return to.ErrorResult(err)
|
||||
}
|
||||
repo, err := params.GetString(req.GetArguments(), "repo")
|
||||
if err != nil {
|
||||
return to.ErrorResult(err)
|
||||
}
|
||||
client, err := gitea.ClientFromContext(ctx)
|
||||
if err != nil {
|
||||
return to.ErrorResult(fmt.Errorf("get gitea client err: %v", err))
|
||||
}
|
||||
_, err = client.StarRepo(owner, repo)
|
||||
if err != nil {
|
||||
return to.ErrorResult(fmt.Errorf("star repo err: %v", err))
|
||||
}
|
||||
return to.TextResult("Repository starred successfully")
|
||||
}
|
||||
|
||||
func unstarRepoFn(ctx context.Context, req mcp.CallToolRequest) (*mcp.CallToolResult, error) {
|
||||
log.Debugf("Called unstarRepoFn")
|
||||
owner, err := params.GetString(req.GetArguments(), "owner")
|
||||
if err != nil {
|
||||
return to.ErrorResult(err)
|
||||
}
|
||||
repo, err := params.GetString(req.GetArguments(), "repo")
|
||||
if err != nil {
|
||||
return to.ErrorResult(err)
|
||||
}
|
||||
client, err := gitea.ClientFromContext(ctx)
|
||||
if err != nil {
|
||||
return to.ErrorResult(fmt.Errorf("get gitea client err: %v", err))
|
||||
}
|
||||
_, err = client.UnStarRepo(owner, repo)
|
||||
if err != nil {
|
||||
return to.ErrorResult(fmt.Errorf("unstar repo err: %v", err))
|
||||
}
|
||||
return to.TextResult("Repository unstarred successfully")
|
||||
}
|
||||
|
||||
func slimUsers(users []*gitea_sdk.User) []map[string]any {
|
||||
out := make([]map[string]any, 0, len(users))
|
||||
for _, u := range users {
|
||||
out = append(out, map[string]any{
|
||||
"id": u.ID,
|
||||
"login": u.UserName,
|
||||
"full_name": u.FullName,
|
||||
"avatar_url": u.AvatarURL,
|
||||
})
|
||||
}
|
||||
return out
|
||||
}
|
||||
|
||||
func slimRepos(repos []*gitea_sdk.Repository) []map[string]any {
|
||||
out := make([]map[string]any, 0, len(repos))
|
||||
for _, r := range repos {
|
||||
out = append(out, map[string]any{
|
||||
"id": r.ID,
|
||||
"name": r.Name,
|
||||
"full_name": r.FullName,
|
||||
"private": r.Private,
|
||||
})
|
||||
}
|
||||
return out
|
||||
}
|
||||
Reference in New Issue
Block a user