From f4bbd5a09adb5ddf56a14b5796d6c2f5127078bd Mon Sep 17 00:00:00 2001 From: hiifong Date: Sun, 23 Mar 2025 21:32:53 +0800 Subject: [PATCH] Update --- operation/issue/issue.go | 117 ++++++++++++++++++++++++------- operation/pull/pull.go | 92 ++++++++++++++++-------- operation/repo/branch.go | 60 +++++++++++----- operation/repo/commit.go | 27 ++++--- operation/repo/file.go | 140 +++++++++++++++++++++++-------------- operation/repo/repo.go | 61 +++++++++------- operation/search/search.go | 107 ++++++++++++++++++++-------- 7 files changed, 415 insertions(+), 189 deletions(-) diff --git a/operation/issue/issue.go b/operation/issue/issue.go index a8b96c9..c6707c9 100644 --- a/operation/issue/issue.go +++ b/operation/issue/issue.go @@ -24,31 +24,36 @@ var ( GetIssueByIndexTool = mcp.NewTool( GetIssueByIndexToolName, mcp.WithDescription("get issue by index"), - mcp.WithString("owner", mcp.Required(), mcp.Description("repository owner"), mcp.DefaultString("")), - mcp.WithString("repo", mcp.Required(), mcp.Description("repository name"), mcp.DefaultString("")), - mcp.WithNumber("index", mcp.Required(), mcp.Description("repository issue index"), mcp.DefaultNumber(0)), + mcp.WithString("owner", mcp.Required(), mcp.Description("repository owner")), + mcp.WithString("repo", mcp.Required(), mcp.Description("repository name")), + mcp.WithNumber("index", mcp.Required(), mcp.Description("repository issue index")), ) ListRepoIssuesTool = mcp.NewTool( ListRepoIssuesToolName, mcp.WithDescription("List repository issues"), + mcp.WithString("owner", mcp.Required(), mcp.Description("repository owner")), + mcp.WithString("repo", mcp.Required(), mcp.Description("repository name")), + mcp.WithString("state", mcp.Description("issue state"), mcp.DefaultString("all")), + mcp.WithNumber("page", mcp.Description("page number"), mcp.DefaultNumber(1)), + mcp.WithNumber("pageSize", mcp.Description("page size"), mcp.DefaultNumber(100)), ) CreateIssueTool = mcp.NewTool( CreateIssueToolName, mcp.WithDescription("create issue"), - mcp.WithString("owner", mcp.Required(), mcp.Description("repository owner"), mcp.DefaultString("")), - mcp.WithString("repo", mcp.Required(), mcp.Description("repository name"), mcp.DefaultString("")), - mcp.WithString("title", mcp.Required(), mcp.Description("issue title"), mcp.DefaultString("")), - mcp.WithString("body", mcp.Required(), mcp.Description("issue body"), mcp.DefaultString("")), + 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("issue title")), + mcp.WithString("body", mcp.Required(), mcp.Description("issue body")), ) CreateIssueCommentTool = mcp.NewTool( CreateIssueCommentToolName, mcp.WithDescription("create issue comment"), - mcp.WithString("owner", mcp.Required(), mcp.Description("repository owner"), mcp.DefaultString("")), - mcp.WithString("repo", mcp.Required(), mcp.Description("repository name"), mcp.DefaultString("")), - mcp.WithNumber("index", mcp.Required(), mcp.Description("repository issue index"), mcp.DefaultNumber(0)), - mcp.WithString("body", mcp.Required(), mcp.Description("issue comment body"), mcp.DefaultString("")), + mcp.WithString("owner", mcp.Required(), mcp.Description("repository owner")), + mcp.WithString("repo", mcp.Required(), mcp.Description("repository name")), + mcp.WithNumber("index", mcp.Required(), mcp.Description("repository issue index")), + mcp.WithString("body", mcp.Required(), mcp.Description("issue comment body")), ) ) @@ -61,9 +66,18 @@ func RegisterTool(s *server.MCPServer) { func GetIssueByIndexFn(ctx context.Context, req mcp.CallToolRequest) (*mcp.CallToolResult, error) { log.Debugf("Called GetIssueByIndexFn") - owner := req.Params.Arguments["owner"].(string) - repo := req.Params.Arguments["repo"].(string) - index := req.Params.Arguments["index"].(float64) + owner, ok := req.Params.Arguments["owner"].(string) + if !ok { + return nil, fmt.Errorf("owner is required") + } + repo, ok := req.Params.Arguments["repo"].(string) + if !ok { + return nil, fmt.Errorf("repo is required") + } + index, ok := req.Params.Arguments["index"].(float64) + if !ok { + return nil, fmt.Errorf("index is required") + } issue, _, err := gitea.Client().GetIssue(owner, repo, int64(index)) if err != nil { return nil, fmt.Errorf("get %v/%v/issue/%v err", owner, repo, int64(index)) @@ -74,9 +88,33 @@ func GetIssueByIndexFn(ctx context.Context, req mcp.CallToolRequest) (*mcp.CallT func ListRepoIssuesFn(ctx context.Context, req mcp.CallToolRequest) (*mcp.CallToolResult, error) { log.Debugf("Called ListIssuesFn") - owner := req.Params.Arguments["owner"].(string) - repo := req.Params.Arguments["repo"].(string) - opt := gitea_sdk.ListIssueOption{} + owner, ok := req.Params.Arguments["owner"].(string) + if !ok { + return nil, fmt.Errorf("owner is required") + } + repo, ok := req.Params.Arguments["repo"].(string) + if !ok { + return nil, fmt.Errorf("repo is required") + } + state, ok := req.Params.Arguments["state"].(string) + if !ok { + state = "all" + } + page, ok := req.Params.Arguments["page"].(float64) + if !ok { + page = 1 + } + pageSize, ok := req.Params.Arguments["pageSize"].(float64) + if !ok { + pageSize = 100 + } + opt := gitea_sdk.ListIssueOption{ + State: gitea_sdk.StateType(state), + ListOptions: gitea_sdk.ListOptions{ + Page: int(page), + PageSize: int(pageSize), + }, + } issues, _, err := gitea.Client().ListRepoIssues(owner, repo, opt) if err != nil { return nil, fmt.Errorf("get %v/%v/issues err", owner, repo) @@ -86,10 +124,22 @@ func ListRepoIssuesFn(ctx context.Context, req mcp.CallToolRequest) (*mcp.CallTo func CreateIssueFn(ctx context.Context, req mcp.CallToolRequest) (*mcp.CallToolResult, error) { log.Debugf("Called CreateIssueFn") - owner := req.Params.Arguments["owner"].(string) - repo := req.Params.Arguments["repo"].(string) - title := req.Params.Arguments["title"].(string) - body := req.Params.Arguments["body"].(string) + owner, ok := req.Params.Arguments["owner"].(string) + if !ok { + return nil, fmt.Errorf("owner is required") + } + repo, ok := req.Params.Arguments["repo"].(string) + if !ok { + return nil, fmt.Errorf("repo is required") + } + title, ok := req.Params.Arguments["title"].(string) + if !ok { + return nil, fmt.Errorf("title is required") + } + body, ok := req.Params.Arguments["body"].(string) + if !ok { + return nil, fmt.Errorf("body is required") + } issue, _, err := gitea.Client().CreateIssue(owner, repo, gitea_sdk.CreateIssueOption{ Title: title, Body: body, @@ -103,13 +153,26 @@ func CreateIssueFn(ctx context.Context, req mcp.CallToolRequest) (*mcp.CallToolR func CreateIssueCommentFn(ctx context.Context, req mcp.CallToolRequest) (*mcp.CallToolResult, error) { log.Debugf("Called CreateIssueCommentFn") - owner := req.Params.Arguments["owner"].(string) - repo := req.Params.Arguments["repo"].(string) - index := req.Params.Arguments["index"].(float64) - body := req.Params.Arguments["body"].(string) - issueComment, _, err := gitea.Client().CreateIssueComment(owner, repo, int64(index), gitea_sdk.CreateIssueCommentOption{ + owner, ok := req.Params.Arguments["owner"].(string) + if !ok { + return nil, fmt.Errorf("owner is required") + } + repo, ok := req.Params.Arguments["repo"].(string) + if !ok { + return nil, fmt.Errorf("repo is required") + } + index, ok := req.Params.Arguments["index"].(float64) + if !ok { + return nil, fmt.Errorf("index is required") + } + body, ok := req.Params.Arguments["body"].(string) + if !ok { + return nil, fmt.Errorf("body is required") + } + opt := gitea_sdk.CreateIssueCommentOption{ Body: body, - }) + } + issueComment, _, err := gitea.Client().CreateIssueComment(owner, repo, int64(index), opt) if err != nil { return nil, fmt.Errorf("create %v/%v/issue/%v/comment err", owner, repo, int64(index)) } diff --git a/operation/pull/pull.go b/operation/pull/pull.go index 763721e..ae238ff 100644 --- a/operation/pull/pull.go +++ b/operation/pull/pull.go @@ -23,30 +23,30 @@ var ( GetPullRequestByIndexTool = mcp.NewTool( GetPullRequestByIndexToolName, mcp.WithDescription("get pull request by index"), - mcp.WithString("owner", mcp.Required(), mcp.Description("repository owner"), mcp.DefaultString("")), - mcp.WithString("repo", mcp.Required(), mcp.Description("repository name"), mcp.DefaultString("")), - mcp.WithNumber("index", mcp.Required(), mcp.Description("repository pull request index"), mcp.DefaultNumber(0)), + mcp.WithString("owner", mcp.Required(), mcp.Description("repository owner")), + mcp.WithString("repo", mcp.Required(), mcp.Description("repository name")), + mcp.WithNumber("index", mcp.Required(), mcp.Description("repository pull request index")), ) ListRepoPullRequestsTool = mcp.NewTool( ListRepoPullRequestsToolName, mcp.WithDescription("List repository pull requests"), - mcp.WithString("owner", mcp.Required(), mcp.Description("repository owner"), mcp.DefaultString("")), - mcp.WithString("repo", mcp.Required(), mcp.Description("repository name"), mcp.DefaultString("")), - mcp.WithString("state", mcp.Description("state"), mcp.DefaultString("")), - mcp.WithString("sort", mcp.Description("sort"), mcp.DefaultString("")), - mcp.WithNumber("milestone", mcp.Description("milestone"), mcp.DefaultNumber(0)), + mcp.WithString("owner", mcp.Required(), mcp.Description("repository owner")), + mcp.WithString("repo", mcp.Required(), mcp.Description("repository name")), + mcp.WithString("state", mcp.Description("state")), + mcp.WithString("sort", mcp.Description("sort")), + mcp.WithNumber("milestone", mcp.Description("milestone")), ) CreatePullRequestTool = mcp.NewTool( CreatePullRequestToolName, mcp.WithDescription("create pull request"), - mcp.WithString("owner", mcp.Required(), mcp.Description("repository owner"), mcp.DefaultString("")), - mcp.WithString("repo", mcp.Required(), mcp.Description("repository name"), mcp.DefaultString("")), - mcp.WithString("title", mcp.Required(), mcp.Description("pull request title"), mcp.DefaultString("")), - mcp.WithString("body", mcp.Required(), mcp.Description("pull request body"), mcp.DefaultString("")), - mcp.WithString("head", mcp.Required(), mcp.Description("pull request head"), mcp.DefaultString("")), - mcp.WithString("base", mcp.Required(), mcp.Description("pull request base"), mcp.DefaultString("")), + 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("pull request title")), + mcp.WithString("body", mcp.Required(), mcp.Description("pull request body")), + mcp.WithString("head", mcp.Required(), mcp.Description("pull request head")), + mcp.WithString("base", mcp.Required(), mcp.Description("pull request base")), ) ) @@ -58,9 +58,18 @@ func RegisterTool(s *server.MCPServer) { func GetPullRequestByIndexFn(ctx context.Context, req mcp.CallToolRequest) (*mcp.CallToolResult, error) { log.Debugf("Called GetPullRequestByIndexFn") - owner := req.Params.Arguments["owner"].(string) - repo := req.Params.Arguments["repo"].(string) - index := req.Params.Arguments["index"].(float64) + owner, ok := req.Params.Arguments["owner"].(string) + if !ok { + return nil, fmt.Errorf("owner is required") + } + repo, ok := req.Params.Arguments["repo"].(string) + if !ok { + return nil, fmt.Errorf("repo is required") + } + index, ok := req.Params.Arguments["index"].(float64) + if !ok { + return nil, fmt.Errorf("index is required") + } pr, _, err := gitea.Client().GetPullRequest(owner, repo, int64(index)) if err != nil { return nil, fmt.Errorf("get %v/%v/pr/%v err", owner, repo, int64(index)) @@ -71,12 +80,21 @@ func GetPullRequestByIndexFn(ctx context.Context, req mcp.CallToolRequest) (*mcp func ListRepoPullRequestsFn(ctx context.Context, req mcp.CallToolRequest) (*mcp.CallToolResult, error) { log.Debugf("Called ListRepoPullRequests") - owner := req.Params.Arguments["owner"].(string) - repo := req.Params.Arguments["repo"].(string) + owner, ok := req.Params.Arguments["owner"].(string) + if !ok { + return nil, fmt.Errorf("owner is required") + } + repo, ok := req.Params.Arguments["repo"].(string) + if !ok { + return nil, fmt.Errorf("repo is required") + } + state, _ := req.Params.Arguments["state"].(string) + sort, _ := req.Params.Arguments["sort"].(string) + milestone, _ := req.Params.Arguments["milestone"].(float64) opt := gitea_sdk.ListPullRequestsOptions{ - State: gitea_sdk.StateType(req.Params.Arguments["state"].(string)), - Sort: req.Params.Arguments["sort"].(string), - Milestone: req.Params.Arguments["milestone"].(int64), + State: gitea_sdk.StateType(state), + Sort: sort, + Milestone: int64(milestone), ListOptions: gitea_sdk.ListOptions{ Page: 1, PageSize: 1000, @@ -92,12 +110,30 @@ func ListRepoPullRequestsFn(ctx context.Context, req mcp.CallToolRequest) (*mcp. func CreatePullRequestFn(ctx context.Context, req mcp.CallToolRequest) (*mcp.CallToolResult, error) { log.Debugf("Called CreatePullRequestFn") - owner := req.Params.Arguments["owner"].(string) - repo := req.Params.Arguments["repo"].(string) - title := req.Params.Arguments["title"].(string) - body := req.Params.Arguments["body"].(string) - head := req.Params.Arguments["head"].(string) - base := req.Params.Arguments["base"].(string) + owner, ok := req.Params.Arguments["owner"].(string) + if !ok { + return nil, fmt.Errorf("owner is required") + } + repo, ok := req.Params.Arguments["repo"].(string) + if !ok { + return nil, fmt.Errorf("repo is required") + } + title, ok := req.Params.Arguments["title"].(string) + if !ok { + return nil, fmt.Errorf("title is required") + } + body, ok := req.Params.Arguments["body"].(string) + if !ok { + return nil, fmt.Errorf("body is required") + } + head, ok := req.Params.Arguments["head"].(string) + if !ok { + return nil, fmt.Errorf("head is required") + } + base, ok := req.Params.Arguments["base"].(string) + if !ok { + return nil, fmt.Errorf("base is required") + } pr, _, err := gitea.Client().CreatePullRequest(owner, repo, gitea_sdk.CreatePullRequestOption{ Title: title, Body: body, diff --git a/operation/repo/branch.go b/operation/repo/branch.go index 703b139..c21a942 100644 --- a/operation/repo/branch.go +++ b/operation/repo/branch.go @@ -22,34 +22,43 @@ var ( CreateBranchTool = mcp.NewTool( CreateBranchToolName, mcp.WithDescription("Create branch"), - mcp.WithString("owner", mcp.Required(), mcp.Description("repository owner"), mcp.DefaultString("")), - mcp.WithString("repo", mcp.Required(), mcp.Description("repository name"), mcp.DefaultString("")), - mcp.WithString("branch", mcp.Required(), mcp.Description("Name of the branch to create"), mcp.DefaultString("")), - mcp.WithString("old_branch", mcp.Description("Name of the old branch to create from"), mcp.DefaultString("")), + mcp.WithString("owner", mcp.Required(), mcp.Description("repository owner")), + mcp.WithString("repo", mcp.Required(), mcp.Description("repository name")), + mcp.WithString("branch", mcp.Required(), mcp.Description("Name of the branch to create")), + mcp.WithString("old_branch", mcp.Required(), mcp.Description("Name of the old branch to create from")), ) DeleteBranchTool = mcp.NewTool( DeleteBranchToolName, mcp.WithDescription("Delete branch"), - mcp.WithString("owner", mcp.Required(), mcp.Description("repository owner"), mcp.DefaultString("")), - mcp.WithString("repo", mcp.Required(), mcp.Description("repository name"), mcp.DefaultString("")), - mcp.WithString("branch", mcp.Required(), mcp.Description("Name of the branch to delete"), mcp.DefaultString("")), + mcp.WithString("owner", mcp.Required(), mcp.Description("repository owner")), + mcp.WithString("repo", mcp.Required(), mcp.Description("repository name")), + mcp.WithString("branch", mcp.Required(), mcp.Description("Name of the branch to delete")), ) ListBranchesTool = mcp.NewTool( ListBranchesToolName, mcp.WithDescription("List branches"), - mcp.WithString("owner", mcp.Required(), mcp.Description("repository owner"), mcp.DefaultString("")), - mcp.WithString("repo", mcp.Required(), mcp.Description("repository name"), mcp.DefaultString("")), + mcp.WithString("owner", mcp.Required(), mcp.Description("repository owner")), + mcp.WithString("repo", mcp.Required(), mcp.Description("repository name")), ) ) func CreateBranchFn(ctx context.Context, req mcp.CallToolRequest) (*mcp.CallToolResult, error) { log.Debugf("Called CreateBranchFn") - owner := req.Params.Arguments["owner"].(string) - repo := req.Params.Arguments["repo"].(string) - branch := req.Params.Arguments["branch"].(string) - oldBranch := req.Params.Arguments["old_branch"].(string) + owner, ok := req.Params.Arguments["owner"].(string) + if !ok { + return nil, fmt.Errorf("owner is required") + } + repo, ok := req.Params.Arguments["repo"].(string) + if !ok { + return nil, fmt.Errorf("repo is required") + } + branch, ok := req.Params.Arguments["branch"].(string) + if !ok { + return nil, fmt.Errorf("branch is required") + } + oldBranch, _ := req.Params.Arguments["old_branch"].(string) _, _, err := gitea.Client().CreateBranch(owner, repo, gitea_sdk.CreateBranchOption{ BranchName: branch, @@ -64,9 +73,18 @@ func CreateBranchFn(ctx context.Context, req mcp.CallToolRequest) (*mcp.CallTool func DeleteBranchFn(ctx context.Context, req mcp.CallToolRequest) (*mcp.CallToolResult, error) { log.Debugf("Called DeleteBranchFn") - owner := req.Params.Arguments["owner"].(string) - repo := req.Params.Arguments["repo"].(string) - branch := req.Params.Arguments["branch"].(string) + owner, ok := req.Params.Arguments["owner"].(string) + if !ok { + return nil, fmt.Errorf("owner is required") + } + repo, ok := req.Params.Arguments["repo"].(string) + if !ok { + return nil, fmt.Errorf("repo is required") + } + branch, ok := req.Params.Arguments["branch"].(string) + if !ok { + return nil, fmt.Errorf("branch is required") + } _, _, err := gitea.Client().DeleteRepoBranch(owner, repo, branch) if err != nil { return nil, fmt.Errorf("Delete Branch Error: %v", err) @@ -77,8 +95,14 @@ func DeleteBranchFn(ctx context.Context, req mcp.CallToolRequest) (*mcp.CallTool func ListBranchesFn(ctx context.Context, req mcp.CallToolRequest) (*mcp.CallToolResult, error) { log.Debugf("Called ListBranchesFn") - owner := req.Params.Arguments["owner"].(string) - repo := req.Params.Arguments["repo"].(string) + owner, ok := req.Params.Arguments["owner"].(string) + if !ok { + return nil, fmt.Errorf("owner is required") + } + repo, ok := req.Params.Arguments["repo"].(string) + if !ok { + return nil, fmt.Errorf("repo is required") + } opt := gitea_sdk.ListRepoBranchesOptions{ ListOptions: gitea_sdk.ListOptions{ Page: 1, diff --git a/operation/repo/commit.go b/operation/repo/commit.go index f233bbf..9c12fa1 100644 --- a/operation/repo/commit.go +++ b/operation/repo/commit.go @@ -4,10 +4,11 @@ import ( "context" "fmt" - gitea_sdk "code.gitea.io/sdk/gitea" "gitea.com/gitea/gitea-mcp/pkg/gitea" "gitea.com/gitea/gitea-mcp/pkg/log" "gitea.com/gitea/gitea-mcp/pkg/to" + + gitea_sdk "code.gitea.io/sdk/gitea" "github.com/mark3labs/mcp-go/mcp" ) @@ -19,24 +20,32 @@ var ( ListRepoCommitsTool = mcp.NewTool( ListRepoCommitsToolName, mcp.WithDescription("List repository commits"), - mcp.WithString("owner", mcp.Required(), mcp.Description("repository owner"), mcp.DefaultString("")), - mcp.WithString("repo", mcp.Required(), mcp.Description("repository name"), mcp.DefaultString("")), - mcp.WithString("sha", mcp.Description("sha"), mcp.DefaultString("")), - mcp.WithString("path", mcp.Description("path"), mcp.DefaultString("")), + mcp.WithString("owner", mcp.Required(), mcp.Description("repository owner")), + mcp.WithString("repo", mcp.Required(), mcp.Description("repository name")), + mcp.WithString("sha", mcp.Description("sha")), + mcp.WithString("path", mcp.Description("path")), ) ) func ListRepoCommitsFn(ctx context.Context, req mcp.CallToolRequest) (*mcp.CallToolResult, error) { log.Debugf("Called ListRepoCommitsFn") - owner := req.Params.Arguments["owner"].(string) - repo := req.Params.Arguments["repo"].(string) + owner, ok := req.Params.Arguments["owner"].(string) + if !ok { + return nil, fmt.Errorf("owner is required") + } + repo, ok := req.Params.Arguments["repo"].(string) + if !ok { + return nil, fmt.Errorf("repo is required") + } + sha, _ := req.Params.Arguments["sha"].(string) + path, _ := req.Params.Arguments["path"].(string) opt := gitea_sdk.ListCommitOptions{ ListOptions: gitea_sdk.ListOptions{ Page: 1, PageSize: 1000, }, - SHA: req.Params.Arguments["sha"].(string), - Path: req.Params.Arguments["path"].(string), + SHA: sha, + Path: path, } commits, _, err := gitea.Client().ListRepoCommits(owner, repo, opt) if err != nil { diff --git a/operation/repo/file.go b/operation/repo/file.go index f8dd4ed..7c722da 100644 --- a/operation/repo/file.go +++ b/operation/repo/file.go @@ -23,56 +23,62 @@ var ( GetFileTool = mcp.NewTool( GetFileToolName, mcp.WithDescription("Get file"), - mcp.WithString("owner", mcp.Required(), mcp.Description("repository owner"), mcp.DefaultString("")), - mcp.WithString("repo", mcp.Required(), mcp.Description("repository name"), mcp.DefaultString("")), - mcp.WithString("ref", mcp.Required(), mcp.Description("ref"), mcp.DefaultString("")), - mcp.WithString("filePath", mcp.Required(), mcp.Description("file path"), mcp.DefaultString("")), + mcp.WithString("owner", mcp.Required(), mcp.Description("repository owner")), + mcp.WithString("repo", mcp.Required(), mcp.Description("repository name")), + mcp.WithString("ref", mcp.Required(), mcp.Description("ref")), + mcp.WithString("filePath", mcp.Required(), mcp.Description("file path")), ) CreateFileTool = mcp.NewTool( CreateFileToolName, mcp.WithDescription("Create file"), - mcp.WithString("owner", mcp.Required(), mcp.Description("repository owner"), mcp.DefaultString("")), - mcp.WithString("repo", mcp.Required(), mcp.Description("repository name"), mcp.DefaultString("")), - mcp.WithString("filePath", mcp.Required(), mcp.Description("file path"), mcp.DefaultString("")), - mcp.WithString("content", mcp.Required(), mcp.Description("file content"), mcp.DefaultString("")), - mcp.WithString("message", mcp.Required(), mcp.Description("commit message"), mcp.DefaultString("")), - mcp.WithString("branch_name", mcp.Required(), mcp.Description("branch name"), mcp.DefaultString("")), - mcp.WithString("new_branch_name", mcp.Description("new branch name"), mcp.DefaultString("")), + mcp.WithString("owner", mcp.Required(), mcp.Description("repository owner")), + mcp.WithString("repo", mcp.Required(), mcp.Description("repository name")), + mcp.WithString("filePath", mcp.Required(), mcp.Description("file path")), + mcp.WithString("content", mcp.Required(), mcp.Description("file content")), + mcp.WithString("message", mcp.Required(), mcp.Description("commit message")), + mcp.WithString("branch_name", mcp.Required(), mcp.Description("branch name")), + mcp.WithString("new_branch_name", mcp.Description("new branch name")), ) UpdateFileTool = mcp.NewTool( UpdateFileToolName, mcp.WithDescription("Update file"), - mcp.WithString("owner", mcp.Required(), mcp.Description("repository owner"), mcp.DefaultString("")), - mcp.WithString("repo", mcp.Required(), mcp.Description("repository name"), mcp.DefaultString("")), - mcp.WithString("filePath", mcp.Required(), mcp.Description("file path"), mcp.DefaultString("")), - mcp.WithString("content", mcp.Required(), mcp.Description("file content"), mcp.DefaultString("")), - mcp.WithString("message", mcp.Required(), mcp.Description("commit message"), mcp.DefaultString("")), - mcp.WithString("branch_name", mcp.Required(), mcp.Description("branch name"), mcp.DefaultString("")), - mcp.WithString("new_branch_name", mcp.Description("new branch name"), mcp.DefaultString("")), - mcp.WithString("from_path", mcp.Description("from path"), mcp.DefaultString("")), - mcp.WithString("sha", mcp.Description("sha"), mcp.DefaultString("")), + mcp.WithString("owner", mcp.Required(), mcp.Description("repository owner")), + mcp.WithString("repo", mcp.Required(), mcp.Description("repository name")), + mcp.WithString("filePath", mcp.Required(), mcp.Description("file path")), + mcp.WithString("content", mcp.Required(), mcp.Description("file content")), + mcp.WithString("message", mcp.Required(), mcp.Description("commit message")), + mcp.WithString("branch_name", mcp.Required(), mcp.Description("branch name")), ) DeleteFileTool = mcp.NewTool( DeleteFileToolName, mcp.WithDescription("Delete file"), - mcp.WithString("owner", mcp.Required(), mcp.Description("repository owner"), mcp.DefaultString("")), - mcp.WithString("repo", mcp.Required(), mcp.Description("repository name"), mcp.DefaultString("")), - mcp.WithString("filePath", mcp.Required(), mcp.Description("file path"), mcp.DefaultString("")), - mcp.WithString("message", mcp.Required(), mcp.Description("commit message"), mcp.DefaultString("")), - mcp.WithString("branch_name", mcp.Required(), mcp.Description("branch name"), mcp.DefaultString("")), - mcp.WithString("sha", mcp.Description("sha"), mcp.DefaultString("")), + mcp.WithString("owner", mcp.Required(), mcp.Description("repository owner")), + mcp.WithString("repo", mcp.Required(), mcp.Description("repository name")), + mcp.WithString("filePath", mcp.Required(), mcp.Description("file path")), + mcp.WithString("message", mcp.Required(), mcp.Description("commit message")), + mcp.WithString("branch_name", mcp.Required(), mcp.Description("branch name")), + mcp.WithString("sha", mcp.Description("sha")), ) ) func GetFileFn(ctx context.Context, req mcp.CallToolRequest) (*mcp.CallToolResult, error) { log.Debugf("Called GetFileFn") - owner := req.Params.Arguments["owner"].(string) - repo := req.Params.Arguments["repo"].(string) - ref := req.Params.Arguments["ref"].(string) - filePath := req.Params.Arguments["filePath"].(string) + owner, ok := req.Params.Arguments["owner"].(string) + if !ok { + return nil, fmt.Errorf("owner is required") + } + repo, ok := req.Params.Arguments["repo"].(string) + if !ok { + return nil, fmt.Errorf("repo is required") + } + ref, _ := req.Params.Arguments["ref"].(string) + filePath, ok := req.Params.Arguments["filePath"].(string) + if !ok { + return nil, fmt.Errorf("filePath is required") + } file, _, err := gitea.Client().GetFile(owner, repo, ref, filePath) if err != nil { return nil, fmt.Errorf("get file err: %v", err) @@ -82,15 +88,26 @@ func GetFileFn(ctx context.Context, req mcp.CallToolRequest) (*mcp.CallToolResul func CreateFileFn(ctx context.Context, req mcp.CallToolRequest) (*mcp.CallToolResult, error) { log.Debugf("Called CreateFileFn") - owner := req.Params.Arguments["owner"].(string) - repo := req.Params.Arguments["repo"].(string) - filePath := req.Params.Arguments["filePath"].(string) + owner, ok := req.Params.Arguments["owner"].(string) + if !ok { + return nil, fmt.Errorf("owner is required") + } + repo, ok := req.Params.Arguments["repo"].(string) + if !ok { + return nil, fmt.Errorf("repo is required") + } + filePath, ok := req.Params.Arguments["filePath"].(string) + if !ok { + return nil, fmt.Errorf("filePath is required") + } + content, _ := req.Params.Arguments["content"].(string) + message, _ := req.Params.Arguments["message"].(string) + branchName, _ := req.Params.Arguments["branch_name"].(string) opt := gitea_sdk.CreateFileOptions{ - Content: req.Params.Arguments["content"].(string), + Content: content, FileOptions: gitea_sdk.FileOptions{ - Message: req.Params.Arguments["message"].(string), - BranchName: req.Params.Arguments["branch_name"].(string), - NewBranchName: req.Params.Arguments["new_branch_name"].(string), + Message: message, + BranchName: branchName, }, } @@ -103,17 +120,26 @@ func CreateFileFn(ctx context.Context, req mcp.CallToolRequest) (*mcp.CallToolRe func UpdateFileFn(ctx context.Context, req mcp.CallToolRequest) (*mcp.CallToolResult, error) { log.Debugf("Called UpdateFileFn") - owner := req.Params.Arguments["owner"].(string) - repo := req.Params.Arguments["repo"].(string) - filePath := req.Params.Arguments["filePath"].(string) + owner, ok := req.Params.Arguments["owner"].(string) + if !ok { + return nil, fmt.Errorf("owner is required") + } + repo, ok := req.Params.Arguments["repo"].(string) + if !ok { + return nil, fmt.Errorf("repo is required") + } + filePath, ok := req.Params.Arguments["filePath"].(string) + if !ok { + return nil, fmt.Errorf("filePath is required") + } + content, _ := req.Params.Arguments["content"].(string) + message, _ := req.Params.Arguments["message"].(string) + branchName, _ := req.Params.Arguments["branch_name"].(string) opt := gitea_sdk.UpdateFileOptions{ - Content: req.Params.Arguments["content"].(string), - FromPath: req.Params.Arguments["from_path"].(string), - SHA: req.Params.Arguments["sha"].(string), + Content: content, FileOptions: gitea_sdk.FileOptions{ - Message: req.Params.Arguments["message"].(string), - BranchName: req.Params.Arguments["branch_name"].(string), - NewBranchName: req.Params.Arguments["new_branch_name"].(string), + Message: message, + BranchName: branchName, }, } _, _, err := gitea.Client().UpdateFile(owner, repo, filePath, opt) @@ -125,15 +151,25 @@ func UpdateFileFn(ctx context.Context, req mcp.CallToolRequest) (*mcp.CallToolRe func DeleteFileFn(ctx context.Context, req mcp.CallToolRequest) (*mcp.CallToolResult, error) { log.Debugf("Called DeleteFileFn") - owner := req.Params.Arguments["owner"].(string) - repo := req.Params.Arguments["repo"].(string) - filePath := req.Params.Arguments["filePath"].(string) + owner, ok := req.Params.Arguments["owner"].(string) + if !ok { + return nil, fmt.Errorf("owner is required") + } + repo, ok := req.Params.Arguments["repo"].(string) + if !ok { + return nil, fmt.Errorf("repo is required") + } + filePath, ok := req.Params.Arguments["filePath"].(string) + if !ok { + return nil, fmt.Errorf("filePath is required") + } + message, _ := req.Params.Arguments["message"].(string) + branchName, _ := req.Params.Arguments["branch_name"].(string) opt := gitea_sdk.DeleteFileOptions{ FileOptions: gitea_sdk.FileOptions{ - Message: req.Params.Arguments["message"].(string), - BranchName: req.Params.Arguments["branch_name"].(string), + Message: message, + BranchName: branchName, }, - SHA: req.Params.Arguments["sha"].(string), } _, err := gitea.Client().DeleteFile(owner, repo, filePath, opt) if err != nil { diff --git a/operation/repo/repo.go b/operation/repo/repo.go index 6b4e72e..f9c9b09 100644 --- a/operation/repo/repo.go +++ b/operation/repo/repo.go @@ -25,16 +25,16 @@ var ( CreateRepoTool = mcp.NewTool( CreateRepoToolName, mcp.WithDescription("Create repository"), - mcp.WithString("name", mcp.Required(), mcp.Description("Name of the repository to create"), mcp.DefaultString("test")), - mcp.WithString("description", mcp.Description("Description of the repository to create"), mcp.DefaultString("")), - mcp.WithBoolean("private", mcp.Description("Whether the repository is private"), mcp.DefaultBool(true)), - mcp.WithString("issue_labels", mcp.Description("Issue Label set to use"), mcp.DefaultString("")), - mcp.WithBoolean("auto_init", mcp.Description("Whether the repository should be auto-intialized?"), mcp.DefaultBool(false)), - mcp.WithBoolean("template", mcp.Description("Whether the repository is template"), mcp.DefaultBool(false)), - mcp.WithString("gitignores", mcp.Description("Gitignores to use"), mcp.DefaultString("")), - mcp.WithString("license", mcp.Description("License to use"), mcp.DefaultString("MIT")), - mcp.WithString("readme", mcp.Description("Readme of the repository to create"), mcp.DefaultString("")), - mcp.WithString("default_branch", mcp.Description("DefaultBranch of the repository (used when initializes and in template)"), mcp.DefaultString("main")), + mcp.WithString("name", mcp.Required(), mcp.Description("Name of the repository to create")), + mcp.WithString("description", mcp.Description("Description of the repository to create")), + mcp.WithBoolean("private", mcp.Description("Whether the repository is private")), + mcp.WithString("issue_labels", mcp.Description("Issue Label set to use")), + mcp.WithBoolean("auto_init", mcp.Description("Whether the repository should be auto-intialized?")), + mcp.WithBoolean("template", mcp.Description("Whether the repository is template")), + mcp.WithString("gitignores", mcp.Description("Gitignores to use")), + mcp.WithString("license", mcp.Description("License to use")), + mcp.WithString("readme", mcp.Description("Readme of the repository to create")), + mcp.WithString("default_branch", mcp.Description("DefaultBranch of the repository (used when initializes and in template)")), ) ForkRepoTool = mcp.NewTool( @@ -50,7 +50,7 @@ var ( ListMyReposToolName, mcp.WithDescription("List my repositories"), mcp.WithNumber("page", mcp.Required(), mcp.Description("Page number"), mcp.DefaultNumber(1), mcp.Min(1)), - mcp.WithNumber("pageSize", mcp.Required(), mcp.Description("Page size number"), mcp.DefaultNumber(10), mcp.Min(1)), + mcp.WithNumber("pageSize", mcp.Required(), mcp.Description("Page size number"), mcp.DefaultNumber(100), mcp.Min(1)), ) ) @@ -76,16 +76,19 @@ func RegisterTool(s *server.MCPServer) { func CreateRepoFn(ctx context.Context, req mcp.CallToolRequest) (*mcp.CallToolResult, error) { log.Debugf("Called CreateRepoFn") - name := req.Params.Arguments["name"].(string) - description := req.Params.Arguments["description"].(string) - private := req.Params.Arguments["private"].(bool) - issueLabels := req.Params.Arguments["issue_labels"].(string) - autoInit := req.Params.Arguments["auto_init"].(bool) - template := req.Params.Arguments["template"].(bool) - gitignores := req.Params.Arguments["gitignores"].(string) - license := req.Params.Arguments["license"].(string) - readme := req.Params.Arguments["readme"].(string) - defaultBranch := req.Params.Arguments["default_branch"].(string) + name, ok := req.Params.Arguments["name"].(string) + if !ok { + return nil, errors.New("repository name is required") + } + description, _ := req.Params.Arguments["description"].(string) + private, _ := req.Params.Arguments["private"].(bool) + issueLabels, _ := req.Params.Arguments["issue_labels"].(string) + autoInit, _ := req.Params.Arguments["auto_init"].(bool) + template, _ := req.Params.Arguments["template"].(bool) + gitignores, _ := req.Params.Arguments["gitignores"].(string) + license, _ := req.Params.Arguments["license"].(string) + readme, _ := req.Params.Arguments["readme"].(string) + defaultBranch, _ := req.Params.Arguments["default_branch"].(string) opt := gitea_sdk.CreateRepoOption{ Name: name, @@ -108,11 +111,19 @@ func CreateRepoFn(ctx context.Context, req mcp.CallToolRequest) (*mcp.CallToolRe func ForkRepoFn(ctx context.Context, req mcp.CallToolRequest) (*mcp.CallToolResult, error) { log.Debugf("Called ForkRepoFn") - user := req.Params.Arguments["user"].(string) - repo := req.Params.Arguments["repo"].(string) + user, ok := req.Params.Arguments["user"].(string) + if !ok { + return nil, errors.New("user name is required") + } + repo, ok := req.Params.Arguments["repo"].(string) + if !ok { + return nil, errors.New("repository name is required") + } + organization, _ := req.Params.Arguments["organization"].(string) + name, _ := req.Params.Arguments["name"].(string) opt := gitea_sdk.CreateForkOption{ - Organization: ptr.To(req.Params.Arguments["organization"].(string)), - Name: ptr.To(req.Params.Arguments["name"].(string)), + Organization: ptr.To(organization), + Name: ptr.To(name), } _, _, err := gitea.Client().CreateFork(user, repo, opt) if err != nil { diff --git a/operation/search/search.go b/operation/search/search.go index af33c44..86f9612 100644 --- a/operation/search/search.go +++ b/operation/search/search.go @@ -24,7 +24,7 @@ var ( SearchUsersTool = mcp.NewTool( SearchUsersToolName, mcp.WithDescription("search users"), - mcp.WithString("keyword", mcp.Description("Keyword"), mcp.DefaultString("")), + mcp.WithString("keyword", mcp.Description("Keyword")), mcp.WithNumber("page", mcp.Description("Page"), mcp.DefaultNumber(1)), mcp.WithNumber("pageSize", mcp.Description("PageSize"), mcp.DefaultNumber(100)), ) @@ -32,9 +32,9 @@ var ( SearOrgTeamsTool = mcp.NewTool( SearchOrgTeamsToolName, mcp.WithDescription("search organization teams"), - mcp.WithString("org", mcp.Description("organization name"), mcp.DefaultString("")), - mcp.WithString("query", mcp.Description("search organization teams"), mcp.DefaultString("")), - mcp.WithBoolean("includeDescription", mcp.Description("include description?"), mcp.DefaultBool(true)), + mcp.WithString("org", mcp.Description("organization name")), + mcp.WithString("query", mcp.Description("search organization teams")), + mcp.WithBoolean("includeDescription", mcp.Description("include description?")), mcp.WithNumber("page", mcp.Description("Page"), mcp.DefaultNumber(1)), mcp.WithNumber("pageSize", mcp.Description("PageSize"), mcp.DefaultNumber(100)), ) @@ -42,14 +42,14 @@ var ( SearchReposTool = mcp.NewTool( SearchReposToolName, mcp.WithDescription("search repos"), - mcp.WithString("keyword", mcp.Description("Keyword"), mcp.DefaultString("")), - mcp.WithBoolean("keywordIsTopic", mcp.Description("KeywordIsTopic"), mcp.DefaultBool(false)), - mcp.WithBoolean("keywordInDescription", mcp.Description("KeywordInDescription"), mcp.DefaultBool(false)), - mcp.WithNumber("ownerID", mcp.Description("OwnerID"), mcp.DefaultNumber(0)), - mcp.WithBoolean("isPrivate", mcp.Description("IsPrivate"), mcp.DefaultBool(false)), - mcp.WithBoolean("isArchived", mcp.Description("IsArchived"), mcp.DefaultBool(false)), - mcp.WithString("sort", mcp.Description("Sort"), mcp.DefaultString(""), mcp.Enum("")), - mcp.WithString("order", mcp.Description("Order"), mcp.DefaultString(""), mcp.Enum("")), + mcp.WithString("keyword", mcp.Description("Keyword")), + mcp.WithBoolean("keywordIsTopic", mcp.Description("KeywordIsTopic")), + mcp.WithBoolean("keywordInDescription", mcp.Description("KeywordInDescription")), + mcp.WithNumber("ownerID", mcp.Description("OwnerID")), + mcp.WithBoolean("isPrivate", mcp.Description("IsPrivate")), + mcp.WithBoolean("isArchived", mcp.Description("IsArchived")), + mcp.WithString("sort", mcp.Description("Sort")), + mcp.WithString("order", mcp.Description("Order")), mcp.WithNumber("page", mcp.Description("Page"), mcp.DefaultNumber(1)), mcp.WithNumber("pageSize", mcp.Description("PageSize"), mcp.DefaultNumber(100)), ) @@ -63,11 +63,23 @@ func RegisterTool(s *server.MCPServer) { func SearchUsersFn(ctx context.Context, req mcp.CallToolRequest) (*mcp.CallToolResult, error) { log.Debugf("Called SearchUsersFn") + keyword, ok := req.Params.Arguments["keyword"].(string) + if !ok { + return nil, fmt.Errorf("keyword is required") + } + page, ok := req.Params.Arguments["page"].(float64) + if !ok { + page = 1 + } + pageSize, ok := req.Params.Arguments["pageSize"].(float64) + if !ok { + pageSize = 100 + } opt := gitea_sdk.SearchUsersOption{ - KeyWord: req.Params.Arguments["keyword"].(string), + KeyWord: keyword, ListOptions: gitea_sdk.ListOptions{ - Page: req.Params.Arguments["page"].(int), - PageSize: req.Params.Arguments["pageSize"].(int), + Page: int(page), + PageSize: int(pageSize), }, } users, _, err := gitea.Client().SearchUsers(opt) @@ -79,13 +91,29 @@ func SearchUsersFn(ctx context.Context, req mcp.CallToolRequest) (*mcp.CallToolR func SearchOrgTeamsFn(ctx context.Context, req mcp.CallToolRequest) (*mcp.CallToolResult, error) { log.Debugf("Called SearchOrgTeamsFn") - org := req.Params.Arguments["org"].(string) + org, ok := req.Params.Arguments["org"].(string) + if !ok { + return nil, fmt.Errorf("organization is required") + } + query, ok := req.Params.Arguments["query"].(string) + if !ok { + return nil, fmt.Errorf("query is required") + } + includeDescription, _ := req.Params.Arguments["includeDescription"].(bool) + page, ok := req.Params.Arguments["page"].(float64) + if !ok { + page = 1 + } + pageSize, ok := req.Params.Arguments["pageSize"].(float64) + if !ok { + pageSize = 100 + } opt := gitea_sdk.SearchTeamsOptions{ - Query: req.Params.Arguments["query"].(string), - IncludeDescription: req.Params.Arguments["includeDescription"].(bool), + Query: query, + IncludeDescription: includeDescription, ListOptions: gitea_sdk.ListOptions{ - Page: req.Params.Arguments["page"].(int), - PageSize: req.Params.Arguments["pageSize"].(int), + Page: int(page), + PageSize: int(pageSize), }, } teams, _, err := gitea.Client().SearchOrgTeams(org, &opt) @@ -97,18 +125,37 @@ func SearchOrgTeamsFn(ctx context.Context, req mcp.CallToolRequest) (*mcp.CallTo func SearchReposFn(ctx context.Context, req mcp.CallToolRequest) (*mcp.CallToolResult, error) { log.Debugf("Called SearchReposFn") + keyword, ok := req.Params.Arguments["keyword"].(string) + if !ok { + return nil, fmt.Errorf("keyword is required") + } + keywordIsTopic, _ := req.Params.Arguments["keywordIsTopic"].(bool) + keywordInDescription, _ := req.Params.Arguments["keywordInDescription"].(bool) + ownerID, _ := req.Params.Arguments["ownerID"].(float64) + isPrivate, _ := req.Params.Arguments["isPrivate"].(bool) + isArchived, _ := req.Params.Arguments["isArchived"].(bool) + sort, _ := req.Params.Arguments["sort"].(string) + order, _ := req.Params.Arguments["order"].(string) + page, ok := req.Params.Arguments["page"].(float64) + if !ok { + page = 1 + } + pageSize, ok := req.Params.Arguments["pageSize"].(float64) + if !ok { + pageSize = 100 + } opt := gitea_sdk.SearchRepoOptions{ - Keyword: req.Params.Arguments["keyword"].(string), - KeywordIsTopic: req.Params.Arguments["keywordIsTopic"].(bool), - KeywordInDescription: req.Params.Arguments["keywordInDescription"].(bool), - OwnerID: req.Params.Arguments["ownerID"].(int64), - IsPrivate: ptr.To(req.Params.Arguments["isPrivate"].(bool)), - IsArchived: ptr.To(req.Params.Arguments["isArchived"].(bool)), - Sort: req.Params.Arguments["sort"].(string), - Order: req.Params.Arguments["order"].(string), + Keyword: keyword, + KeywordIsTopic: keywordIsTopic, + KeywordInDescription: keywordInDescription, + OwnerID: int64(ownerID), + IsPrivate: ptr.To(isPrivate), + IsArchived: ptr.To(isArchived), + Sort: sort, + Order: order, ListOptions: gitea_sdk.ListOptions{ - Page: req.Params.Arguments["page"].(int), - PageSize: req.Params.Arguments["pageSize"].(int), + Page: int(page), + PageSize: int(pageSize), }, } repos, _, err := gitea.Client().SearchRepos(opt)