mirror of
https://gitea.com/gitea/gitea-mcp.git
synced 2026-01-17 05:02:43 +00:00
feat(pull): add PR review tools (#111)
Add 8 new MCP tools for managing pull request reviews: Read operations: - list_pull_request_reviews: list all reviews for a PR - get_pull_request_review: get a specific review by ID - list_pull_request_review_comments: list inline comments for a review Write operations: - create_pull_request_review: create a review with optional inline comments - submit_pull_request_review: submit a pending review - delete_pull_request_review: delete a review - dismiss_pull_request_review: dismiss a review with optional message - delete_pull_request_reviewer: remove reviewer requests from a PR Fixes #107 Co-authored-by: hiifong <i@hiif.ong> Co-authored-by: hiifong <f@f.style> Reviewed-on: https://gitea.com/gitea/gitea-mcp/pulls/111 Co-authored-by: Thomas Foubert <thomas.foubert@mistral.ai> Co-committed-by: Thomas Foubert <thomas.foubert@mistral.ai>
This commit is contained in:
10
README.md
10
README.md
@@ -165,7 +165,7 @@ list all my repositories
|
|||||||
The Gitea MCP Server supports the following tools:
|
The Gitea MCP Server supports the following tools:
|
||||||
|
|
||||||
| Tool | Scope | Description |
|
| Tool | Scope | Description |
|
||||||
| :-----------------------------: | :----------: | :------------------------------------------------------: |
|
| :-------------------------------: | :----------: | :------------------------------------------------------: |
|
||||||
| get_my_user_info | User | Get the information of the authenticated user |
|
| get_my_user_info | User | Get the information of the authenticated user |
|
||||||
| get_user_orgs | User | Get organizations associated with the authenticated user |
|
| get_user_orgs | User | Get organizations associated with the authenticated user |
|
||||||
| create_repo | Repository | Create a new repository |
|
| create_repo | Repository | Create a new repository |
|
||||||
@@ -200,6 +200,14 @@ The Gitea MCP Server supports the following tools:
|
|||||||
| list_repo_pull_requests | Pull Request | List all pull requests in a repository |
|
| list_repo_pull_requests | Pull Request | List all pull requests in a repository |
|
||||||
| create_pull_request | Pull Request | Create a new pull request |
|
| create_pull_request | Pull Request | Create a new pull request |
|
||||||
| create_pull_request_reviewer | Pull Request | Add reviewers to a pull request |
|
| create_pull_request_reviewer | Pull Request | Add reviewers to a pull request |
|
||||||
|
| delete_pull_request_reviewer | Pull Request | Remove reviewers from a pull request |
|
||||||
|
| list_pull_request_reviews | Pull Request | List all reviews for a pull request |
|
||||||
|
| get_pull_request_review | Pull Request | Get a specific review by ID |
|
||||||
|
| list_pull_request_review_comments | Pull Request | List inline comments for a review |
|
||||||
|
| create_pull_request_review | Pull Request | Create a review with optional inline comments |
|
||||||
|
| submit_pull_request_review | Pull Request | Submit a pending review |
|
||||||
|
| delete_pull_request_review | Pull Request | Delete a review |
|
||||||
|
| dismiss_pull_request_review | Pull Request | Dismiss a review with optional message |
|
||||||
| search_users | User | Search for users |
|
| search_users | User | Search for users |
|
||||||
| search_org_teams | Organization | Search for teams in an organization |
|
| search_org_teams | Organization | Search for teams in an organization |
|
||||||
| list_org_labels | Organization | List labels defined at organization level |
|
| list_org_labels | Organization | List labels defined at organization level |
|
||||||
|
|||||||
@@ -165,7 +165,7 @@ cp gitea-mcp /usr/local/bin/
|
|||||||
Gitea MCP 服务器支持以下工具:
|
Gitea MCP 服务器支持以下工具:
|
||||||
|
|
||||||
| 工具 | 范围 | 描述 |
|
| 工具 | 范围 | 描述 |
|
||||||
| :--------------------------: | :------: | :------------------------: |
|
| :-------------------------------: | :------: | :------------------------: |
|
||||||
| get_my_user_info | 用户 | 获取已认证用户信息 |
|
| get_my_user_info | 用户 | 获取已认证用户信息 |
|
||||||
| get_user_orgs | 用户 | 获取已认证用户关联组织 |
|
| get_user_orgs | 用户 | 获取已认证用户关联组织 |
|
||||||
| create_repo | 仓库 | 创建新仓库 |
|
| create_repo | 仓库 | 创建新仓库 |
|
||||||
@@ -200,6 +200,14 @@ Gitea MCP 服务器支持以下工具:
|
|||||||
| list_repo_pull_requests | 拉取请求 | 列出所有拉取请求 |
|
| list_repo_pull_requests | 拉取请求 | 列出所有拉取请求 |
|
||||||
| create_pull_request | 拉取请求 | 创建新拉取请求 |
|
| create_pull_request | 拉取请求 | 创建新拉取请求 |
|
||||||
| create_pull_request_reviewer | 拉取请求 | 为拉取请求添加审查者 |
|
| create_pull_request_reviewer | 拉取请求 | 为拉取请求添加审查者 |
|
||||||
|
| delete_pull_request_reviewer | 拉取请求 | 移除拉取请求的审查者 |
|
||||||
|
| list_pull_request_reviews | 拉取请求 | 列出拉取请求的所有审查 |
|
||||||
|
| get_pull_request_review | 拉取请求 | 按 ID 获取特定审查 |
|
||||||
|
| list_pull_request_review_comments | 拉取请求 | 列出审查的行内评论 |
|
||||||
|
| create_pull_request_review | 拉取请求 | 创建审查(可含行内评论) |
|
||||||
|
| submit_pull_request_review | 拉取请求 | 提交待处理的审查 |
|
||||||
|
| delete_pull_request_review | 拉取请求 | 删除审查 |
|
||||||
|
| dismiss_pull_request_review | 拉取请求 | 驳回审查(可附消息) |
|
||||||
| search_users | 用户 | 搜索用户 |
|
| search_users | 用户 | 搜索用户 |
|
||||||
| search_org_teams | 组织 | 搜索组织团队 |
|
| search_org_teams | 组织 | 搜索组织团队 |
|
||||||
| list_org_labels | 组织 | 列出组织标签 |
|
| list_org_labels | 组织 | 列出组织标签 |
|
||||||
|
|||||||
@@ -165,7 +165,7 @@ cp gitea-mcp /usr/local/bin/
|
|||||||
Gitea MCP 伺服器支援以下工具:
|
Gitea MCP 伺服器支援以下工具:
|
||||||
|
|
||||||
| 工具 | 範圍 | 描述 |
|
| 工具 | 範圍 | 描述 |
|
||||||
| :--------------------------: | :------: | :--------------------------: |
|
| :-------------------------------: | :------: | :--------------------------: |
|
||||||
| get_my_user_info | 用戶 | 取得已認證用戶資訊 |
|
| get_my_user_info | 用戶 | 取得已認證用戶資訊 |
|
||||||
| get_user_orgs | 用戶 | 取得已認證用戶所屬組織 |
|
| get_user_orgs | 用戶 | 取得已認證用戶所屬組織 |
|
||||||
| create_repo | 倉庫 | 創建新倉庫 |
|
| create_repo | 倉庫 | 創建新倉庫 |
|
||||||
@@ -200,6 +200,14 @@ Gitea MCP 伺服器支援以下工具:
|
|||||||
| list_repo_pull_requests | 拉取請求 | 列出所有拉取請求 |
|
| list_repo_pull_requests | 拉取請求 | 列出所有拉取請求 |
|
||||||
| create_pull_request | 拉取請求 | 創建新拉取請求 |
|
| create_pull_request | 拉取請求 | 創建新拉取請求 |
|
||||||
| create_pull_request_reviewer | 拉取請求 | 為拉取請求添加審查者 |
|
| create_pull_request_reviewer | 拉取請求 | 為拉取請求添加審查者 |
|
||||||
|
| delete_pull_request_reviewer | 拉取請求 | 移除拉取請求的審查者 |
|
||||||
|
| list_pull_request_reviews | 拉取請求 | 列出拉取請求的所有審查 |
|
||||||
|
| get_pull_request_review | 拉取請求 | 依 ID 取得特定審查 |
|
||||||
|
| list_pull_request_review_comments | 拉取請求 | 列出審查的行內評論 |
|
||||||
|
| create_pull_request_review | 拉取請求 | 創建審查(可含行內評論) |
|
||||||
|
| submit_pull_request_review | 拉取請求 | 提交待處理的審查 |
|
||||||
|
| delete_pull_request_review | 拉取請求 | 刪除審查 |
|
||||||
|
| dismiss_pull_request_review | 拉取請求 | 駁回審查(可附訊息) |
|
||||||
| search_users | 用戶 | 搜尋用戶 |
|
| search_users | 用戶 | 搜尋用戶 |
|
||||||
| search_org_teams | 組織 | 搜尋組織團隊 |
|
| search_org_teams | 組織 | 搜尋組織團隊 |
|
||||||
| list_org_labels | 組織 | 列出組織標籤 |
|
| list_org_labels | 組織 | 列出組織標籤 |
|
||||||
|
|||||||
@@ -21,6 +21,14 @@ const (
|
|||||||
ListRepoPullRequestsToolName = "list_repo_pull_requests"
|
ListRepoPullRequestsToolName = "list_repo_pull_requests"
|
||||||
CreatePullRequestToolName = "create_pull_request"
|
CreatePullRequestToolName = "create_pull_request"
|
||||||
CreatePullRequestReviewerToolName = "create_pull_request_reviewer"
|
CreatePullRequestReviewerToolName = "create_pull_request_reviewer"
|
||||||
|
DeletePullRequestReviewerToolName = "delete_pull_request_reviewer"
|
||||||
|
ListPullRequestReviewsToolName = "list_pull_request_reviews"
|
||||||
|
GetPullRequestReviewToolName = "get_pull_request_review"
|
||||||
|
ListPullRequestReviewCommentsToolName = "list_pull_request_review_comments"
|
||||||
|
CreatePullRequestReviewToolName = "create_pull_request_review"
|
||||||
|
SubmitPullRequestReviewToolName = "submit_pull_request_review"
|
||||||
|
DeletePullRequestReviewToolName = "delete_pull_request_review"
|
||||||
|
DismissPullRequestReviewToolName = "dismiss_pull_request_review"
|
||||||
)
|
)
|
||||||
|
|
||||||
var (
|
var (
|
||||||
@@ -64,6 +72,94 @@ var (
|
|||||||
mcp.WithArray("reviewers", mcp.Description("list of reviewer usernames"), mcp.Items(map[string]interface{}{"type": "string"})),
|
mcp.WithArray("reviewers", mcp.Description("list of reviewer usernames"), mcp.Items(map[string]interface{}{"type": "string"})),
|
||||||
mcp.WithArray("team_reviewers", mcp.Description("list of team reviewer names"), mcp.Items(map[string]interface{}{"type": "string"})),
|
mcp.WithArray("team_reviewers", mcp.Description("list of team reviewer names"), mcp.Items(map[string]interface{}{"type": "string"})),
|
||||||
)
|
)
|
||||||
|
|
||||||
|
DeletePullRequestReviewerTool = mcp.NewTool(
|
||||||
|
DeletePullRequestReviewerToolName,
|
||||||
|
mcp.WithDescription("remove reviewer requests from a pull request"),
|
||||||
|
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("pull request index")),
|
||||||
|
mcp.WithArray("reviewers", mcp.Description("list of reviewer usernames to remove"), mcp.Items(map[string]interface{}{"type": "string"})),
|
||||||
|
mcp.WithArray("team_reviewers", mcp.Description("list of team reviewer names to remove"), mcp.Items(map[string]interface{}{"type": "string"})),
|
||||||
|
)
|
||||||
|
|
||||||
|
ListPullRequestReviewsTool = mcp.NewTool(
|
||||||
|
ListPullRequestReviewsToolName,
|
||||||
|
mcp.WithDescription("list all reviews for a pull request"),
|
||||||
|
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("pull request index")),
|
||||||
|
mcp.WithNumber("page", mcp.Description("page number"), mcp.DefaultNumber(1)),
|
||||||
|
mcp.WithNumber("pageSize", mcp.Description("page size"), mcp.DefaultNumber(100)),
|
||||||
|
)
|
||||||
|
|
||||||
|
GetPullRequestReviewTool = mcp.NewTool(
|
||||||
|
GetPullRequestReviewToolName,
|
||||||
|
mcp.WithDescription("get a specific review for a pull request"),
|
||||||
|
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("pull request index")),
|
||||||
|
mcp.WithNumber("review_id", mcp.Required(), mcp.Description("review ID")),
|
||||||
|
)
|
||||||
|
|
||||||
|
ListPullRequestReviewCommentsTool = mcp.NewTool(
|
||||||
|
ListPullRequestReviewCommentsToolName,
|
||||||
|
mcp.WithDescription("list all comments for a specific pull request review"),
|
||||||
|
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("pull request index")),
|
||||||
|
mcp.WithNumber("review_id", mcp.Required(), mcp.Description("review ID")),
|
||||||
|
)
|
||||||
|
|
||||||
|
CreatePullRequestReviewTool = mcp.NewTool(
|
||||||
|
CreatePullRequestReviewToolName,
|
||||||
|
mcp.WithDescription("create a review for a pull request"),
|
||||||
|
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("pull request index")),
|
||||||
|
mcp.WithString("state", mcp.Description("review state"), mcp.Enum("APPROVED", "REQUEST_CHANGES", "COMMENT", "PENDING")),
|
||||||
|
mcp.WithString("body", mcp.Description("review body/comment")),
|
||||||
|
mcp.WithString("commit_id", mcp.Description("commit SHA to review")),
|
||||||
|
mcp.WithArray("comments", mcp.Description("inline review comments (objects with path, body, old_line_num, new_line_num)"), mcp.Items(map[string]interface{}{
|
||||||
|
"type": "object",
|
||||||
|
"properties": map[string]interface{}{
|
||||||
|
"path": map[string]interface{}{"type": "string", "description": "file path to comment on"},
|
||||||
|
"body": map[string]interface{}{"type": "string", "description": "comment body"},
|
||||||
|
"old_line_num": map[string]interface{}{"type": "number", "description": "line number in the old file (for deletions/changes)"},
|
||||||
|
"new_line_num": map[string]interface{}{"type": "number", "description": "line number in the new file (for additions/changes)"},
|
||||||
|
},
|
||||||
|
})),
|
||||||
|
)
|
||||||
|
|
||||||
|
SubmitPullRequestReviewTool = mcp.NewTool(
|
||||||
|
SubmitPullRequestReviewToolName,
|
||||||
|
mcp.WithDescription("submit a pending pull request review"),
|
||||||
|
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("pull request index")),
|
||||||
|
mcp.WithNumber("review_id", mcp.Required(), mcp.Description("review ID")),
|
||||||
|
mcp.WithString("state", mcp.Required(), mcp.Description("final review state"), mcp.Enum("APPROVED", "REQUEST_CHANGES", "COMMENT")),
|
||||||
|
mcp.WithString("body", mcp.Description("submission message")),
|
||||||
|
)
|
||||||
|
|
||||||
|
DeletePullRequestReviewTool = mcp.NewTool(
|
||||||
|
DeletePullRequestReviewToolName,
|
||||||
|
mcp.WithDescription("delete a pull request review"),
|
||||||
|
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("pull request index")),
|
||||||
|
mcp.WithNumber("review_id", mcp.Required(), mcp.Description("review ID")),
|
||||||
|
)
|
||||||
|
|
||||||
|
DismissPullRequestReviewTool = mcp.NewTool(
|
||||||
|
DismissPullRequestReviewToolName,
|
||||||
|
mcp.WithDescription("dismiss a pull request review"),
|
||||||
|
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("pull request index")),
|
||||||
|
mcp.WithNumber("review_id", mcp.Required(), mcp.Description("review ID")),
|
||||||
|
mcp.WithString("message", mcp.Description("dismissal reason")),
|
||||||
|
)
|
||||||
)
|
)
|
||||||
|
|
||||||
func init() {
|
func init() {
|
||||||
@@ -75,6 +171,18 @@ func init() {
|
|||||||
Tool: ListRepoPullRequestsTool,
|
Tool: ListRepoPullRequestsTool,
|
||||||
Handler: ListRepoPullRequestsFn,
|
Handler: ListRepoPullRequestsFn,
|
||||||
})
|
})
|
||||||
|
Tool.RegisterRead(server.ServerTool{
|
||||||
|
Tool: ListPullRequestReviewsTool,
|
||||||
|
Handler: ListPullRequestReviewsFn,
|
||||||
|
})
|
||||||
|
Tool.RegisterRead(server.ServerTool{
|
||||||
|
Tool: GetPullRequestReviewTool,
|
||||||
|
Handler: GetPullRequestReviewFn,
|
||||||
|
})
|
||||||
|
Tool.RegisterRead(server.ServerTool{
|
||||||
|
Tool: ListPullRequestReviewCommentsTool,
|
||||||
|
Handler: ListPullRequestReviewCommentsFn,
|
||||||
|
})
|
||||||
Tool.RegisterWrite(server.ServerTool{
|
Tool.RegisterWrite(server.ServerTool{
|
||||||
Tool: CreatePullRequestTool,
|
Tool: CreatePullRequestTool,
|
||||||
Handler: CreatePullRequestFn,
|
Handler: CreatePullRequestFn,
|
||||||
@@ -83,6 +191,26 @@ func init() {
|
|||||||
Tool: CreatePullRequestReviewerTool,
|
Tool: CreatePullRequestReviewerTool,
|
||||||
Handler: CreatePullRequestReviewerFn,
|
Handler: CreatePullRequestReviewerFn,
|
||||||
})
|
})
|
||||||
|
Tool.RegisterWrite(server.ServerTool{
|
||||||
|
Tool: DeletePullRequestReviewerTool,
|
||||||
|
Handler: DeletePullRequestReviewerFn,
|
||||||
|
})
|
||||||
|
Tool.RegisterWrite(server.ServerTool{
|
||||||
|
Tool: CreatePullRequestReviewTool,
|
||||||
|
Handler: CreatePullRequestReviewFn,
|
||||||
|
})
|
||||||
|
Tool.RegisterWrite(server.ServerTool{
|
||||||
|
Tool: SubmitPullRequestReviewTool,
|
||||||
|
Handler: SubmitPullRequestReviewFn,
|
||||||
|
})
|
||||||
|
Tool.RegisterWrite(server.ServerTool{
|
||||||
|
Tool: DeletePullRequestReviewTool,
|
||||||
|
Handler: DeletePullRequestReviewFn,
|
||||||
|
})
|
||||||
|
Tool.RegisterWrite(server.ServerTool{
|
||||||
|
Tool: DismissPullRequestReviewTool,
|
||||||
|
Handler: DismissPullRequestReviewFn,
|
||||||
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
func GetPullRequestByIndexFn(ctx context.Context, req mcp.CallToolRequest) (*mcp.CallToolResult, error) {
|
func GetPullRequestByIndexFn(ctx context.Context, req mcp.CallToolRequest) (*mcp.CallToolResult, error) {
|
||||||
@@ -260,3 +388,359 @@ func CreatePullRequestReviewerFn(ctx context.Context, req mcp.CallToolRequest) (
|
|||||||
|
|
||||||
return to.TextResult(successMsg)
|
return to.TextResult(successMsg)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func DeletePullRequestReviewerFn(ctx context.Context, req mcp.CallToolRequest) (*mcp.CallToolResult, error) {
|
||||||
|
log.Debugf("Called DeletePullRequestReviewerFn")
|
||||||
|
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"))
|
||||||
|
}
|
||||||
|
index, ok := req.GetArguments()["index"].(float64)
|
||||||
|
if !ok {
|
||||||
|
return to.ErrorResult(fmt.Errorf("index is required"))
|
||||||
|
}
|
||||||
|
|
||||||
|
var reviewers []string
|
||||||
|
if reviewersArg, exists := req.GetArguments()["reviewers"]; exists {
|
||||||
|
if reviewersSlice, ok := reviewersArg.([]interface{}); ok {
|
||||||
|
for _, reviewer := range reviewersSlice {
|
||||||
|
if reviewerStr, ok := reviewer.(string); ok {
|
||||||
|
reviewers = append(reviewers, reviewerStr)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
var teamReviewers []string
|
||||||
|
if teamReviewersArg, exists := req.GetArguments()["team_reviewers"]; exists {
|
||||||
|
if teamReviewersSlice, ok := teamReviewersArg.([]interface{}); ok {
|
||||||
|
for _, teamReviewer := range teamReviewersSlice {
|
||||||
|
if teamReviewerStr, ok := teamReviewer.(string); ok {
|
||||||
|
teamReviewers = append(teamReviewers, teamReviewerStr)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
client, err := gitea.ClientFromContext(ctx)
|
||||||
|
if err != nil {
|
||||||
|
return to.ErrorResult(fmt.Errorf("get gitea client err: %v", err))
|
||||||
|
}
|
||||||
|
|
||||||
|
_, err = client.DeleteReviewRequests(owner, repo, int64(index), gitea_sdk.PullReviewRequestOptions{
|
||||||
|
Reviewers: reviewers,
|
||||||
|
TeamReviewers: teamReviewers,
|
||||||
|
})
|
||||||
|
if err != nil {
|
||||||
|
return to.ErrorResult(fmt.Errorf("delete review requests for %v/%v/pr/%v err: %v", owner, repo, int64(index), err))
|
||||||
|
}
|
||||||
|
|
||||||
|
successMsg := map[string]interface{}{
|
||||||
|
"message": "Successfully deleted review requests",
|
||||||
|
"reviewers": reviewers,
|
||||||
|
"team_reviewers": teamReviewers,
|
||||||
|
"pr_index": int64(index),
|
||||||
|
"repository": fmt.Sprintf("%s/%s", owner, repo),
|
||||||
|
}
|
||||||
|
|
||||||
|
return to.TextResult(successMsg)
|
||||||
|
}
|
||||||
|
|
||||||
|
func ListPullRequestReviewsFn(ctx context.Context, req mcp.CallToolRequest) (*mcp.CallToolResult, error) {
|
||||||
|
log.Debugf("Called ListPullRequestReviewsFn")
|
||||||
|
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"))
|
||||||
|
}
|
||||||
|
index, ok := req.GetArguments()["index"].(float64)
|
||||||
|
if !ok {
|
||||||
|
return to.ErrorResult(fmt.Errorf("index is required"))
|
||||||
|
}
|
||||||
|
page, ok := req.GetArguments()["page"].(float64)
|
||||||
|
if !ok {
|
||||||
|
page = 1
|
||||||
|
}
|
||||||
|
pageSize, ok := req.GetArguments()["pageSize"].(float64)
|
||||||
|
if !ok {
|
||||||
|
pageSize = 100
|
||||||
|
}
|
||||||
|
|
||||||
|
client, err := gitea.ClientFromContext(ctx)
|
||||||
|
if err != nil {
|
||||||
|
return to.ErrorResult(fmt.Errorf("get gitea client err: %v", err))
|
||||||
|
}
|
||||||
|
|
||||||
|
reviews, _, err := client.ListPullReviews(owner, repo, int64(index), gitea_sdk.ListPullReviewsOptions{
|
||||||
|
ListOptions: gitea_sdk.ListOptions{
|
||||||
|
Page: int(page),
|
||||||
|
PageSize: int(pageSize),
|
||||||
|
},
|
||||||
|
})
|
||||||
|
if err != nil {
|
||||||
|
return to.ErrorResult(fmt.Errorf("list reviews for %v/%v/pr/%v err: %v", owner, repo, int64(index), err))
|
||||||
|
}
|
||||||
|
|
||||||
|
return to.TextResult(reviews)
|
||||||
|
}
|
||||||
|
|
||||||
|
func GetPullRequestReviewFn(ctx context.Context, req mcp.CallToolRequest) (*mcp.CallToolResult, error) {
|
||||||
|
log.Debugf("Called GetPullRequestReviewFn")
|
||||||
|
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"))
|
||||||
|
}
|
||||||
|
index, ok := req.GetArguments()["index"].(float64)
|
||||||
|
if !ok {
|
||||||
|
return to.ErrorResult(fmt.Errorf("index is required"))
|
||||||
|
}
|
||||||
|
reviewID, ok := req.GetArguments()["review_id"].(float64)
|
||||||
|
if !ok {
|
||||||
|
return to.ErrorResult(fmt.Errorf("review_id is required"))
|
||||||
|
}
|
||||||
|
|
||||||
|
client, err := gitea.ClientFromContext(ctx)
|
||||||
|
if err != nil {
|
||||||
|
return to.ErrorResult(fmt.Errorf("get gitea client err: %v", err))
|
||||||
|
}
|
||||||
|
|
||||||
|
review, _, err := client.GetPullReview(owner, repo, int64(index), int64(reviewID))
|
||||||
|
if err != nil {
|
||||||
|
return to.ErrorResult(fmt.Errorf("get review %v for %v/%v/pr/%v err: %v", int64(reviewID), owner, repo, int64(index), err))
|
||||||
|
}
|
||||||
|
|
||||||
|
return to.TextResult(review)
|
||||||
|
}
|
||||||
|
|
||||||
|
func ListPullRequestReviewCommentsFn(ctx context.Context, req mcp.CallToolRequest) (*mcp.CallToolResult, error) {
|
||||||
|
log.Debugf("Called ListPullRequestReviewCommentsFn")
|
||||||
|
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"))
|
||||||
|
}
|
||||||
|
index, ok := req.GetArguments()["index"].(float64)
|
||||||
|
if !ok {
|
||||||
|
return to.ErrorResult(fmt.Errorf("index is required"))
|
||||||
|
}
|
||||||
|
reviewID, ok := req.GetArguments()["review_id"].(float64)
|
||||||
|
if !ok {
|
||||||
|
return to.ErrorResult(fmt.Errorf("review_id is required"))
|
||||||
|
}
|
||||||
|
|
||||||
|
client, err := gitea.ClientFromContext(ctx)
|
||||||
|
if err != nil {
|
||||||
|
return to.ErrorResult(fmt.Errorf("get gitea client err: %v", err))
|
||||||
|
}
|
||||||
|
|
||||||
|
comments, _, err := client.ListPullReviewComments(owner, repo, int64(index), int64(reviewID))
|
||||||
|
if err != nil {
|
||||||
|
return to.ErrorResult(fmt.Errorf("list review comments for review %v on %v/%v/pr/%v err: %v", int64(reviewID), owner, repo, int64(index), err))
|
||||||
|
}
|
||||||
|
|
||||||
|
return to.TextResult(comments)
|
||||||
|
}
|
||||||
|
|
||||||
|
func CreatePullRequestReviewFn(ctx context.Context, req mcp.CallToolRequest) (*mcp.CallToolResult, error) {
|
||||||
|
log.Debugf("Called CreatePullRequestReviewFn")
|
||||||
|
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"))
|
||||||
|
}
|
||||||
|
index, ok := req.GetArguments()["index"].(float64)
|
||||||
|
if !ok {
|
||||||
|
return to.ErrorResult(fmt.Errorf("index is required"))
|
||||||
|
}
|
||||||
|
|
||||||
|
opt := gitea_sdk.CreatePullReviewOptions{}
|
||||||
|
|
||||||
|
if state, ok := req.GetArguments()["state"].(string); ok {
|
||||||
|
opt.State = gitea_sdk.ReviewStateType(state)
|
||||||
|
}
|
||||||
|
if body, ok := req.GetArguments()["body"].(string); ok {
|
||||||
|
opt.Body = body
|
||||||
|
}
|
||||||
|
if commitID, ok := req.GetArguments()["commit_id"].(string); ok {
|
||||||
|
opt.CommitID = commitID
|
||||||
|
}
|
||||||
|
|
||||||
|
// Parse inline comments
|
||||||
|
if commentsArg, exists := req.GetArguments()["comments"]; exists {
|
||||||
|
if commentsSlice, ok := commentsArg.([]interface{}); ok {
|
||||||
|
for _, comment := range commentsSlice {
|
||||||
|
if commentMap, ok := comment.(map[string]interface{}); ok {
|
||||||
|
reviewComment := gitea_sdk.CreatePullReviewComment{}
|
||||||
|
if path, ok := commentMap["path"].(string); ok {
|
||||||
|
reviewComment.Path = path
|
||||||
|
}
|
||||||
|
if body, ok := commentMap["body"].(string); ok {
|
||||||
|
reviewComment.Body = body
|
||||||
|
}
|
||||||
|
if oldLineNum, ok := commentMap["old_line_num"].(float64); ok {
|
||||||
|
reviewComment.OldLineNum = int64(oldLineNum)
|
||||||
|
}
|
||||||
|
if newLineNum, ok := commentMap["new_line_num"].(float64); ok {
|
||||||
|
reviewComment.NewLineNum = int64(newLineNum)
|
||||||
|
}
|
||||||
|
opt.Comments = append(opt.Comments, reviewComment)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
client, err := gitea.ClientFromContext(ctx)
|
||||||
|
if err != nil {
|
||||||
|
return to.ErrorResult(fmt.Errorf("get gitea client err: %v", err))
|
||||||
|
}
|
||||||
|
|
||||||
|
review, _, err := client.CreatePullReview(owner, repo, int64(index), opt)
|
||||||
|
if err != nil {
|
||||||
|
return to.ErrorResult(fmt.Errorf("create review for %v/%v/pr/%v err: %v", owner, repo, int64(index), err))
|
||||||
|
}
|
||||||
|
|
||||||
|
return to.TextResult(review)
|
||||||
|
}
|
||||||
|
|
||||||
|
func SubmitPullRequestReviewFn(ctx context.Context, req mcp.CallToolRequest) (*mcp.CallToolResult, error) {
|
||||||
|
log.Debugf("Called SubmitPullRequestReviewFn")
|
||||||
|
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"))
|
||||||
|
}
|
||||||
|
index, ok := req.GetArguments()["index"].(float64)
|
||||||
|
if !ok {
|
||||||
|
return to.ErrorResult(fmt.Errorf("index is required"))
|
||||||
|
}
|
||||||
|
reviewID, ok := req.GetArguments()["review_id"].(float64)
|
||||||
|
if !ok {
|
||||||
|
return to.ErrorResult(fmt.Errorf("review_id is required"))
|
||||||
|
}
|
||||||
|
state, ok := req.GetArguments()["state"].(string)
|
||||||
|
if !ok {
|
||||||
|
return to.ErrorResult(fmt.Errorf("state is required"))
|
||||||
|
}
|
||||||
|
|
||||||
|
opt := gitea_sdk.SubmitPullReviewOptions{
|
||||||
|
State: gitea_sdk.ReviewStateType(state),
|
||||||
|
}
|
||||||
|
if body, ok := req.GetArguments()["body"].(string); ok {
|
||||||
|
opt.Body = body
|
||||||
|
}
|
||||||
|
|
||||||
|
client, err := gitea.ClientFromContext(ctx)
|
||||||
|
if err != nil {
|
||||||
|
return to.ErrorResult(fmt.Errorf("get gitea client err: %v", err))
|
||||||
|
}
|
||||||
|
|
||||||
|
review, _, err := client.SubmitPullReview(owner, repo, int64(index), int64(reviewID), opt)
|
||||||
|
if err != nil {
|
||||||
|
return to.ErrorResult(fmt.Errorf("submit review %v for %v/%v/pr/%v err: %v", int64(reviewID), owner, repo, int64(index), err))
|
||||||
|
}
|
||||||
|
|
||||||
|
return to.TextResult(review)
|
||||||
|
}
|
||||||
|
|
||||||
|
func DeletePullRequestReviewFn(ctx context.Context, req mcp.CallToolRequest) (*mcp.CallToolResult, error) {
|
||||||
|
log.Debugf("Called DeletePullRequestReviewFn")
|
||||||
|
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"))
|
||||||
|
}
|
||||||
|
index, ok := req.GetArguments()["index"].(float64)
|
||||||
|
if !ok {
|
||||||
|
return to.ErrorResult(fmt.Errorf("index is required"))
|
||||||
|
}
|
||||||
|
reviewID, ok := req.GetArguments()["review_id"].(float64)
|
||||||
|
if !ok {
|
||||||
|
return to.ErrorResult(fmt.Errorf("review_id is required"))
|
||||||
|
}
|
||||||
|
|
||||||
|
client, err := gitea.ClientFromContext(ctx)
|
||||||
|
if err != nil {
|
||||||
|
return to.ErrorResult(fmt.Errorf("get gitea client err: %v", err))
|
||||||
|
}
|
||||||
|
|
||||||
|
_, err = client.DeletePullReview(owner, repo, int64(index), int64(reviewID))
|
||||||
|
if err != nil {
|
||||||
|
return to.ErrorResult(fmt.Errorf("delete review %v for %v/%v/pr/%v err: %v", int64(reviewID), owner, repo, int64(index), err))
|
||||||
|
}
|
||||||
|
|
||||||
|
successMsg := map[string]interface{}{
|
||||||
|
"message": "Successfully deleted review",
|
||||||
|
"review_id": int64(reviewID),
|
||||||
|
"pr_index": int64(index),
|
||||||
|
"repository": fmt.Sprintf("%s/%s", owner, repo),
|
||||||
|
}
|
||||||
|
|
||||||
|
return to.TextResult(successMsg)
|
||||||
|
}
|
||||||
|
|
||||||
|
func DismissPullRequestReviewFn(ctx context.Context, req mcp.CallToolRequest) (*mcp.CallToolResult, error) {
|
||||||
|
log.Debugf("Called DismissPullRequestReviewFn")
|
||||||
|
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"))
|
||||||
|
}
|
||||||
|
index, ok := req.GetArguments()["index"].(float64)
|
||||||
|
if !ok {
|
||||||
|
return to.ErrorResult(fmt.Errorf("index is required"))
|
||||||
|
}
|
||||||
|
reviewID, ok := req.GetArguments()["review_id"].(float64)
|
||||||
|
if !ok {
|
||||||
|
return to.ErrorResult(fmt.Errorf("review_id is required"))
|
||||||
|
}
|
||||||
|
|
||||||
|
opt := gitea_sdk.DismissPullReviewOptions{}
|
||||||
|
if message, ok := req.GetArguments()["message"].(string); ok {
|
||||||
|
opt.Message = message
|
||||||
|
}
|
||||||
|
|
||||||
|
client, err := gitea.ClientFromContext(ctx)
|
||||||
|
if err != nil {
|
||||||
|
return to.ErrorResult(fmt.Errorf("get gitea client err: %v", err))
|
||||||
|
}
|
||||||
|
|
||||||
|
_, err = client.DismissPullReview(owner, repo, int64(index), int64(reviewID), opt)
|
||||||
|
if err != nil {
|
||||||
|
return to.ErrorResult(fmt.Errorf("dismiss review %v for %v/%v/pr/%v err: %v", int64(reviewID), owner, repo, int64(index), err))
|
||||||
|
}
|
||||||
|
|
||||||
|
successMsg := map[string]interface{}{
|
||||||
|
"message": "Successfully dismissed review",
|
||||||
|
"review_id": int64(reviewID),
|
||||||
|
"pr_index": int64(index),
|
||||||
|
"repository": fmt.Sprintf("%s/%s", owner, repo),
|
||||||
|
}
|
||||||
|
|
||||||
|
return to.TextResult(successMsg)
|
||||||
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user