diff --git a/README.md b/README.md index 3dc67cc..d0ec24d 100644 --- a/README.md +++ b/README.md @@ -164,83 +164,91 @@ list all my repositories The Gitea MCP Server supports the following tools: -| Tool | Scope | Description | -| :-----------------------------: | :----------: | :------------------------------------------------------: | -| get_my_user_info | User | Get the information of the authenticated user | -| get_user_orgs | User | Get organizations associated with the authenticated user | -| create_repo | Repository | Create a new repository | -| fork_repo | Repository | Fork a repository | -| list_my_repos | Repository | List all repositories owned by the authenticated user | -| create_branch | Branch | Create a new branch | -| delete_branch | Branch | Delete a branch | -| list_branches | Branch | List all branches in a repository | -| create_release | Release | Create a new release in a repository | -| delete_release | Release | Delete a release from a repository | -| get_release | Release | Get a release | -| get_latest_release | Release | Get the latest release in a repository | -| list_releases | Release | List all releases in a repository | -| create_tag | Tag | Create a new tag | -| delete_tag | Tag | Delete a tag | -| get_tag | Tag | Get a tag | -| list_tags | Tag | List all tags in a repository | -| list_repo_commits | Commit | List all commits in a repository | -| get_file_content | File | Get the content and metadata of a file | -| get_dir_content | File | Get a list of entries in a directory | -| create_file | File | Create a new file | -| update_file | File | Update an existing file | -| delete_file | File | Delete a file | -| get_issue_by_index | Issue | Get an issue by its index | -| list_repo_issues | Issue | List all issues in a repository | -| create_issue | Issue | Create a new issue | -| create_issue_comment | Issue | Create a comment on an issue | -| edit_issue | Issue | Edit a issue | -| edit_issue_comment | Issue | Edit a comment on an issue | -| get_issue_comments_by_index | Issue | Get comments of an issue by its index | -| get_pull_request_by_index | Pull Request | Get a pull request by its index | -| 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_reviewer | Pull Request | Add reviewers to a pull request | -| search_users | User | Search for users | -| search_org_teams | Organization | Search for teams in an organization | -| list_org_labels | Organization | List labels defined at organization level | -| create_org_label | Organization | Create a label in an organization | -| edit_org_label | Organization | Edit a label in an organization | -| delete_org_label | Organization | Delete a label in an organization | -| search_repos | Repository | Search for repositories | -| list_repo_action_secrets | Actions | List repository Actions secrets (metadata only) | -| upsert_repo_action_secret | Actions | Create/update (upsert) a repository Actions secret | -| delete_repo_action_secret | Actions | Delete a repository Actions secret | -| list_org_action_secrets | Actions | List organization Actions secrets (metadata only) | -| upsert_org_action_secret | Actions | Create/update (upsert) an organization Actions secret | -| delete_org_action_secret | Actions | Delete an organization Actions secret | -| list_repo_action_variables | Actions | List repository Actions variables | -| get_repo_action_variable | Actions | Get a repository Actions variable | -| create_repo_action_variable | Actions | Create a repository Actions variable | -| update_repo_action_variable | Actions | Update a repository Actions variable | -| delete_repo_action_variable | Actions | Delete a repository Actions variable | -| list_org_action_variables | Actions | List organization Actions variables | -| get_org_action_variable | Actions | Get an organization Actions variable | -| create_org_action_variable | Actions | Create an organization Actions variable | -| update_org_action_variable | Actions | Update an organization Actions variable | -| delete_org_action_variable | Actions | Delete an organization Actions variable | -| list_repo_action_workflows | Actions | List repository Actions workflows | -| get_repo_action_workflow | Actions | Get a repository Actions workflow | -| dispatch_repo_action_workflow | Actions | Trigger (dispatch) a repository Actions workflow | -| list_repo_action_runs | Actions | List repository Actions runs | -| get_repo_action_run | Actions | Get a repository Actions run | -| cancel_repo_action_run | Actions | Cancel a repository Actions run | -| rerun_repo_action_run | Actions | Rerun a repository Actions run | -| list_repo_action_jobs | Actions | List repository Actions jobs | -| list_repo_action_run_jobs | Actions | List Actions jobs for a run | -| get_repo_action_job_log_preview | Actions | Get a job log preview (tail/limited) | -| download_repo_action_job_log | Actions | Download a job log to a file | -| get_gitea_mcp_server_version | Server | Get the version of the Gitea MCP Server | -| list_wiki_pages | Wiki | List all wiki pages in a repository | -| get_wiki_page | Wiki | Get a wiki page content and metadata | -| get_wiki_revisions | Wiki | Get revisions history of a wiki page | -| create_wiki_page | Wiki | Create a new wiki page | -| update_wiki_page | Wiki | Update an existing wiki page | -| delete_wiki_page | Wiki | Delete a wiki page | +| Tool | Scope | Description | +| :-------------------------------: | :----------: | :------------------------------------------------------: | +| get_my_user_info | User | Get the information of the authenticated user | +| get_user_orgs | User | Get organizations associated with the authenticated user | +| create_repo | Repository | Create a new repository | +| fork_repo | Repository | Fork a repository | +| list_my_repos | Repository | List all repositories owned by the authenticated user | +| create_branch | Branch | Create a new branch | +| delete_branch | Branch | Delete a branch | +| list_branches | Branch | List all branches in a repository | +| create_release | Release | Create a new release in a repository | +| delete_release | Release | Delete a release from a repository | +| get_release | Release | Get a release | +| get_latest_release | Release | Get the latest release in a repository | +| list_releases | Release | List all releases in a repository | +| create_tag | Tag | Create a new tag | +| delete_tag | Tag | Delete a tag | +| get_tag | Tag | Get a tag | +| list_tags | Tag | List all tags in a repository | +| list_repo_commits | Commit | List all commits in a repository | +| get_file_content | File | Get the content and metadata of a file | +| get_dir_content | File | Get a list of entries in a directory | +| create_file | File | Create a new file | +| update_file | File | Update an existing file | +| delete_file | File | Delete a file | +| get_issue_by_index | Issue | Get an issue by its index | +| list_repo_issues | Issue | List all issues in a repository | +| create_issue | Issue | Create a new issue | +| create_issue_comment | Issue | Create a comment on an issue | +| edit_issue | Issue | Edit a issue | +| edit_issue_comment | Issue | Edit a comment on an issue | +| get_issue_comments_by_index | Issue | Get comments of an issue by its index | +| get_pull_request_by_index | Pull Request | Get a pull request by its index | +| 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_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_org_teams | Organization | Search for teams in an organization | +| list_org_labels | Organization | List labels defined at organization level | +| create_org_label | Organization | Create a label in an organization | +| edit_org_label | Organization | Edit a label in an organization | +| delete_org_label | Organization | Delete a label in an organization | +| search_repos | Repository | Search for repositories | +| list_repo_action_secrets | Actions | List repository Actions secrets (metadata only) | +| upsert_repo_action_secret | Actions | Create/update (upsert) a repository Actions secret | +| delete_repo_action_secret | Actions | Delete a repository Actions secret | +| list_org_action_secrets | Actions | List organization Actions secrets (metadata only) | +| upsert_org_action_secret | Actions | Create/update (upsert) an organization Actions secret | +| delete_org_action_secret | Actions | Delete an organization Actions secret | +| list_repo_action_variables | Actions | List repository Actions variables | +| get_repo_action_variable | Actions | Get a repository Actions variable | +| create_repo_action_variable | Actions | Create a repository Actions variable | +| update_repo_action_variable | Actions | Update a repository Actions variable | +| delete_repo_action_variable | Actions | Delete a repository Actions variable | +| list_org_action_variables | Actions | List organization Actions variables | +| get_org_action_variable | Actions | Get an organization Actions variable | +| create_org_action_variable | Actions | Create an organization Actions variable | +| update_org_action_variable | Actions | Update an organization Actions variable | +| delete_org_action_variable | Actions | Delete an organization Actions variable | +| list_repo_action_workflows | Actions | List repository Actions workflows | +| get_repo_action_workflow | Actions | Get a repository Actions workflow | +| dispatch_repo_action_workflow | Actions | Trigger (dispatch) a repository Actions workflow | +| list_repo_action_runs | Actions | List repository Actions runs | +| get_repo_action_run | Actions | Get a repository Actions run | +| cancel_repo_action_run | Actions | Cancel a repository Actions run | +| rerun_repo_action_run | Actions | Rerun a repository Actions run | +| list_repo_action_jobs | Actions | List repository Actions jobs | +| list_repo_action_run_jobs | Actions | List Actions jobs for a run | +| get_repo_action_job_log_preview | Actions | Get a job log preview (tail/limited) | +| download_repo_action_job_log | Actions | Download a job log to a file | +| get_gitea_mcp_server_version | Server | Get the version of the Gitea MCP Server | +| list_wiki_pages | Wiki | List all wiki pages in a repository | +| get_wiki_page | Wiki | Get a wiki page content and metadata | +| get_wiki_revisions | Wiki | Get revisions history of a wiki page | +| create_wiki_page | Wiki | Create a new wiki page | +| update_wiki_page | Wiki | Update an existing wiki page | +| delete_wiki_page | Wiki | Delete a wiki page | ## 🐛 Debugging diff --git a/README.zh-cn.md b/README.zh-cn.md index de63d83..e08ec7c 100644 --- a/README.zh-cn.md +++ b/README.zh-cn.md @@ -164,56 +164,64 @@ cp gitea-mcp /usr/local/bin/ Gitea MCP 服务器支持以下工具: -| 工具 | 范围 | 描述 | -| :--------------------------: | :------: | :------------------------: | -| get_my_user_info | 用户 | 获取已认证用户信息 | -| get_user_orgs | 用户 | 获取已认证用户关联组织 | -| create_repo | 仓库 | 创建新仓库 | -| fork_repo | 仓库 | 复刻仓库 | -| list_my_repos | 仓库 | 列出用户所有仓库 | -| create_branch | 分支 | 创建新分支 | -| delete_branch | 分支 | 删除分支 | -| list_branches | 分支 | 列出所有分支 | -| create_release | 版本发布 | 创建新版本发布 | -| delete_release | 版本发布 | 删除版本发布 | -| get_release | 版本发布 | 获取版本发布 | -| get_latest_release | 版本发布 | 获取最新版本发布 | -| list_releases | 版本发布 | 列出所有版本发布 | -| create_tag | 标签 | 创建新标签 | -| delete_tag | 标签 | 删除标签 | -| get_tag | 标签 | 获取标签 | -| list_tags | 标签 | 列出所有标签 | -| list_repo_commits | 提交 | 列出所有提交 | -| get_file_content | 文件 | 获取文件内容和元数据 | -| get_dir_content | 文件 | 获取目录内容列表 | -| create_file | 文件 | 创建新文件 | -| update_file | 文件 | 更新现有文件 | -| delete_file | 文件 | 删除文件 | -| get_issue_by_index | 问题 | 按索引获取问题 | -| list_repo_issues | 问题 | 列出所有问题 | -| create_issue | 问题 | 创建新问题 | -| create_issue_comment | 问题 | 在问题上创建评论 | -| edit_issue | 问题 | 编辑问题 | -| edit_issue_comment | 问题 | 编辑问题评论 | -| get_issue_comments_by_index | 问题 | 按索引获取问题评论 | -| get_pull_request_by_index | 拉取请求 | 按索引获取拉取请求 | -| list_repo_pull_requests | 拉取请求 | 列出所有拉取请求 | -| create_pull_request | 拉取请求 | 创建新拉取请求 | -| create_pull_request_reviewer | 拉取请求 | 为拉取请求添加审查者 | -| search_users | 用户 | 搜索用户 | -| search_org_teams | 组织 | 搜索组织团队 | -| list_org_labels | 组织 | 列出组织标签 | -| create_org_label | 组织 | 创建组织标签 | -| edit_org_label | 组织 | 编辑组织标签 | -| delete_org_label | 组织 | 删除组织标签 | -| search_repos | 仓库 | 搜索仓库 | -| get_gitea_mcp_server_version | 服务器 | 获取 Gitea MCP 服务器版本 | -| list_wiki_pages | Wiki | 列出所有 Wiki 页面 | -| get_wiki_page | Wiki | 获取 Wiki 页面内容和元数据 | -| get_wiki_revisions | Wiki | 获取 Wiki 修订历史 | -| create_wiki_page | Wiki | 创建新 Wiki 页面 | -| update_wiki_page | Wiki | 更新现有 Wiki 页面 | -| delete_wiki_page | Wiki | 删除 Wiki 页面 | +| 工具 | 范围 | 描述 | +| :-------------------------------: | :------: | :------------------------: | +| get_my_user_info | 用户 | 获取已认证用户信息 | +| get_user_orgs | 用户 | 获取已认证用户关联组织 | +| create_repo | 仓库 | 创建新仓库 | +| fork_repo | 仓库 | 复刻仓库 | +| list_my_repos | 仓库 | 列出用户所有仓库 | +| create_branch | 分支 | 创建新分支 | +| delete_branch | 分支 | 删除分支 | +| list_branches | 分支 | 列出所有分支 | +| create_release | 版本发布 | 创建新版本发布 | +| delete_release | 版本发布 | 删除版本发布 | +| get_release | 版本发布 | 获取版本发布 | +| get_latest_release | 版本发布 | 获取最新版本发布 | +| list_releases | 版本发布 | 列出所有版本发布 | +| create_tag | 标签 | 创建新标签 | +| delete_tag | 标签 | 删除标签 | +| get_tag | 标签 | 获取标签 | +| list_tags | 标签 | 列出所有标签 | +| list_repo_commits | 提交 | 列出所有提交 | +| get_file_content | 文件 | 获取文件内容和元数据 | +| get_dir_content | 文件 | 获取目录内容列表 | +| create_file | 文件 | 创建新文件 | +| update_file | 文件 | 更新现有文件 | +| delete_file | 文件 | 删除文件 | +| get_issue_by_index | 问题 | 按索引获取问题 | +| list_repo_issues | 问题 | 列出所有问题 | +| create_issue | 问题 | 创建新问题 | +| create_issue_comment | 问题 | 在问题上创建评论 | +| edit_issue | 问题 | 编辑问题 | +| edit_issue_comment | 问题 | 编辑问题评论 | +| get_issue_comments_by_index | 问题 | 按索引获取问题评论 | +| get_pull_request_by_index | 拉取请求 | 按索引获取拉取请求 | +| list_repo_pull_requests | 拉取请求 | 列出所有拉取请求 | +| create_pull_request | 拉取请求 | 创建新拉取请求 | +| 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_org_teams | 组织 | 搜索组织团队 | +| list_org_labels | 组织 | 列出组织标签 | +| create_org_label | 组织 | 创建组织标签 | +| edit_org_label | 组织 | 编辑组织标签 | +| delete_org_label | 组织 | 删除组织标签 | +| search_repos | 仓库 | 搜索仓库 | +| get_gitea_mcp_server_version | 服务器 | 获取 Gitea MCP 服务器版本 | +| list_wiki_pages | Wiki | 列出所有 Wiki 页面 | +| get_wiki_page | Wiki | 获取 Wiki 页面内容和元数据 | +| get_wiki_revisions | Wiki | 获取 Wiki 修订历史 | +| create_wiki_page | Wiki | 创建新 Wiki 页面 | +| update_wiki_page | Wiki | 更新现有 Wiki 页面 | +| delete_wiki_page | Wiki | 删除 Wiki 页面 | ## 🐛 调试 diff --git a/README.zh-tw.md b/README.zh-tw.md index 7da44ca..e471956 100644 --- a/README.zh-tw.md +++ b/README.zh-tw.md @@ -164,56 +164,64 @@ cp gitea-mcp /usr/local/bin/ Gitea MCP 伺服器支援以下工具: -| 工具 | 範圍 | 描述 | -| :--------------------------: | :------: | :--------------------------: | -| get_my_user_info | 用戶 | 取得已認證用戶資訊 | -| get_user_orgs | 用戶 | 取得已認證用戶所屬組織 | -| create_repo | 倉庫 | 創建新倉庫 | -| fork_repo | 倉庫 | 復刻倉庫 | -| list_my_repos | 倉庫 | 列出用戶所有倉庫 | -| create_branch | 分支 | 創建新分支 | -| delete_branch | 分支 | 刪除分支 | -| list_branches | 分支 | 列出所有分支 | -| create_release | 版本發布 | 創建新版本發布 | -| delete_release | 版本發布 | 刪除版本發布 | -| get_release | 版本發布 | 取得版本發布 | -| get_latest_release | 版本發布 | 取得最新版本發布 | -| list_releases | 版本發布 | 列出所有版本發布 | -| create_tag | 標籤 | 創建新標籤 | -| delete_tag | 標籤 | 刪除標籤 | -| get_tag | 標籤 | 取得標籤 | -| list_tags | 標籤 | 列出所有標籤 | -| list_repo_commits | 提交 | 列出所有提交 | -| get_file_content | 文件 | 取得文件內容與中繼資料 | -| get_dir_content | 文件 | 取得目錄內容列表 | -| create_file | 文件 | 創建新文件 | -| update_file | 文件 | 更新現有文件 | -| delete_file | 文件 | 刪除文件 | -| get_issue_by_index | 問題 | 依索引取得問題 | -| list_repo_issues | 問題 | 列出所有問題 | -| create_issue | 問題 | 創建新問題 | -| create_issue_comment | 問題 | 在問題上創建評論 | -| edit_issue | 問題 | 編輯問題 | -| edit_issue_comment | 問題 | 編輯問題評論 | -| get_issue_comments_by_index | 問題 | 依索引取得問題評論 | -| get_pull_request_by_index | 拉取請求 | 依索引取得拉取請求 | -| list_repo_pull_requests | 拉取請求 | 列出所有拉取請求 | -| create_pull_request | 拉取請求 | 創建新拉取請求 | -| create_pull_request_reviewer | 拉取請求 | 為拉取請求添加審查者 | -| search_users | 用戶 | 搜尋用戶 | -| search_org_teams | 組織 | 搜尋組織團隊 | -| list_org_labels | 組織 | 列出組織標籤 | -| create_org_label | 組織 | 創建組織標籤 | -| edit_org_label | 組織 | 編輯組織標籤 | -| delete_org_label | 組織 | 刪除組織標籤 | -| search_repos | 倉庫 | 搜尋倉庫 | -| get_gitea_mcp_server_version | 伺服器 | 取得 Gitea MCP 伺服器版本 | -| list_wiki_pages | Wiki | 列出所有 Wiki 頁面 | -| get_wiki_page | Wiki | 取得 Wiki 頁面內容與中繼資料 | -| get_wiki_revisions | Wiki | 取得 Wiki 修訂歷史 | -| create_wiki_page | Wiki | 創建新 Wiki 頁面 | -| update_wiki_page | Wiki | 更新現有 Wiki 頁面 | -| delete_wiki_page | Wiki | 刪除 Wiki 頁面 | +| 工具 | 範圍 | 描述 | +| :-------------------------------: | :------: | :--------------------------: | +| get_my_user_info | 用戶 | 取得已認證用戶資訊 | +| get_user_orgs | 用戶 | 取得已認證用戶所屬組織 | +| create_repo | 倉庫 | 創建新倉庫 | +| fork_repo | 倉庫 | 復刻倉庫 | +| list_my_repos | 倉庫 | 列出用戶所有倉庫 | +| create_branch | 分支 | 創建新分支 | +| delete_branch | 分支 | 刪除分支 | +| list_branches | 分支 | 列出所有分支 | +| create_release | 版本發布 | 創建新版本發布 | +| delete_release | 版本發布 | 刪除版本發布 | +| get_release | 版本發布 | 取得版本發布 | +| get_latest_release | 版本發布 | 取得最新版本發布 | +| list_releases | 版本發布 | 列出所有版本發布 | +| create_tag | 標籤 | 創建新標籤 | +| delete_tag | 標籤 | 刪除標籤 | +| get_tag | 標籤 | 取得標籤 | +| list_tags | 標籤 | 列出所有標籤 | +| list_repo_commits | 提交 | 列出所有提交 | +| get_file_content | 文件 | 取得文件內容與中繼資料 | +| get_dir_content | 文件 | 取得目錄內容列表 | +| create_file | 文件 | 創建新文件 | +| update_file | 文件 | 更新現有文件 | +| delete_file | 文件 | 刪除文件 | +| get_issue_by_index | 問題 | 依索引取得問題 | +| list_repo_issues | 問題 | 列出所有問題 | +| create_issue | 問題 | 創建新問題 | +| create_issue_comment | 問題 | 在問題上創建評論 | +| edit_issue | 問題 | 編輯問題 | +| edit_issue_comment | 問題 | 編輯問題評論 | +| get_issue_comments_by_index | 問題 | 依索引取得問題評論 | +| get_pull_request_by_index | 拉取請求 | 依索引取得拉取請求 | +| list_repo_pull_requests | 拉取請求 | 列出所有拉取請求 | +| create_pull_request | 拉取請求 | 創建新拉取請求 | +| 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_org_teams | 組織 | 搜尋組織團隊 | +| list_org_labels | 組織 | 列出組織標籤 | +| create_org_label | 組織 | 創建組織標籤 | +| edit_org_label | 組織 | 編輯組織標籤 | +| delete_org_label | 組織 | 刪除組織標籤 | +| search_repos | 倉庫 | 搜尋倉庫 | +| get_gitea_mcp_server_version | 伺服器 | 取得 Gitea MCP 伺服器版本 | +| list_wiki_pages | Wiki | 列出所有 Wiki 頁面 | +| get_wiki_page | Wiki | 取得 Wiki 頁面內容與中繼資料 | +| get_wiki_revisions | Wiki | 取得 Wiki 修訂歷史 | +| create_wiki_page | Wiki | 創建新 Wiki 頁面 | +| update_wiki_page | Wiki | 更新現有 Wiki 頁面 | +| delete_wiki_page | Wiki | 刪除 Wiki 頁面 | ## 🐛 調試 diff --git a/operation/pull/pull.go b/operation/pull/pull.go index f6ddf03..59c2d50 100644 --- a/operation/pull/pull.go +++ b/operation/pull/pull.go @@ -17,10 +17,18 @@ import ( var Tool = tool.New() const ( - GetPullRequestByIndexToolName = "get_pull_request_by_index" - ListRepoPullRequestsToolName = "list_repo_pull_requests" - CreatePullRequestToolName = "create_pull_request" - CreatePullRequestReviewerToolName = "create_pull_request_reviewer" + GetPullRequestByIndexToolName = "get_pull_request_by_index" + ListRepoPullRequestsToolName = "list_repo_pull_requests" + CreatePullRequestToolName = "create_pull_request" + 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 ( @@ -64,6 +72,94 @@ var ( 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"})), ) + + 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() { @@ -75,6 +171,18 @@ func init() { Tool: ListRepoPullRequestsTool, 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: CreatePullRequestTool, Handler: CreatePullRequestFn, @@ -83,6 +191,26 @@ func init() { Tool: CreatePullRequestReviewerTool, 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) { @@ -260,3 +388,359 @@ func CreatePullRequestReviewerFn(ctx context.Context, req mcp.CallToolRequest) ( 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) +}