From d5cff234cf715af8b21e762cd2a6f5fe54a1127e Mon Sep 17 00:00:00 2001 From: Nicolas FRADIN Date: Wed, 20 May 2026 19:20:58 +0200 Subject: [PATCH] feat: add router handlers for all new MCP tools --- src/router.ts | 340 ++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 340 insertions(+) diff --git a/src/router.ts b/src/router.ts index eec5af4..6c44faf 100644 --- a/src/router.ts +++ b/src/router.ts @@ -107,6 +107,60 @@ export class BitbucketRouter { case 'get_full_pull_request': return this.getFullPullRequest(params); + case 'list_workspaces': + return this.listWorkspaces(params); + + case 'list_repositories': + return this.listRepositories(params); + + case 'get_repository': + return this.getRepository(params); + + case 'list_branches': + return this.listBranches(params); + + case 'create_pull_request': + return this.createPullRequest(params); + + case 'update_pull_request': + return this.updatePullRequest(params); + + case 'merge_pull_request': + return this.mergePullRequest(params); + + case 'decline_pull_request': + return this.declinePullRequest(params); + + case 'approve_pull_request': + return this.approvePullRequest(params); + + case 'unapprove_pull_request': + return this.unapprovePullRequest(params); + + case 'request_changes_pull_request': + return this.requestChangesPullRequest(params); + + case 'remove_request_changes_pull_request': + return this.removeRequestChangesPullRequest(params); + + case 'add_pull_request_comment': + return this.addPullRequestComment(params); + + case 'update_pull_request_comment': + return this.updatePullRequestComment(params); + + case 'delete_pull_request_comment': + return this.deletePullRequestComment(params); + + case 'create_pull_request_task': + return this.createPullRequestTask(params); + + case 'update_pull_request_task': + return this.updatePullRequestTask(params); + + case 'delete_pull_request_task': + return this.deletePullRequestTask(params); + default: return { success: false, @@ -484,6 +538,292 @@ export class BitbucketRouter { return { success: false, error: `Get full PR failed: ${String(error)}` }; } } + + private async listWorkspaces(params: ToolCallParams): Promise { + try { + const result = await this.client.listWorkspaces({ + page: params.page, + pagelen: params.pagelen, + }); + return { success: true, data: result }; + } catch (error) { + return { success: false, error: `List workspaces failed: ${String(error)}` }; + } + } + + private async listRepositories(params: ToolCallParams): Promise { + try { + const { workspace } = this.getDefaultParams(params); + if (!workspace) { + return { success: false, error: 'Missing required parameters: workspace' }; + } + const result = await this.client.listRepositories(workspace, { + role: params.role, + page: params.page, + pagelen: params.pagelen, + }); + return { success: true, data: result }; + } catch (error) { + return { success: false, error: `List repositories failed: ${String(error)}` }; + } + } + + private async getRepository(params: ToolCallParams): Promise { + try { + const { workspace, repoSlug } = this.getDefaultParams(params); + if (!workspace || !repoSlug) { + return { success: false, error: 'Missing required parameters: workspace and repository' }; + } + const result = await this.client.getRepository(workspace, repoSlug); + return { success: true, data: result }; + } catch (error) { + return { success: false, error: `Get repository failed: ${String(error)}` }; + } + } + + private async listBranches(params: ToolCallParams): Promise { + try { + const { workspace, repoSlug } = this.getDefaultParams(params); + if (!workspace || !repoSlug) { + return { success: false, error: 'Missing required parameters: workspace and repository' }; + } + const result = await this.client.listBranches(workspace, repoSlug, { + filter_by_name: params.filter_by_name, + page: params.page, + pagelen: params.pagelen, + }); + return { success: true, data: result }; + } catch (error) { + return { success: false, error: `List branches failed: ${String(error)}` }; + } + } + + private async createPullRequest(params: ToolCallParams): Promise { + try { + const { workspace, repoSlug } = this.getDefaultParams(params); + if (!workspace || !repoSlug || !params.title || !params.source_branch || !params.destination_branch) { + return { success: false, error: 'Missing required parameters: workspace, repository, title, source_branch, destination_branch' }; + } + const result = await this.client.createPullRequest(workspace, repoSlug, { + title: params.title, + source_branch: params.source_branch, + destination_branch: params.destination_branch, + description: params.description, + reviewers: params.reviewers, + close_source_branch: params.close_source_branch, + }); + return { success: true, data: result }; + } catch (error) { + return { success: false, error: `Create pull request failed: ${String(error)}` }; + } + } + + private async updatePullRequest(params: ToolCallParams): Promise { + try { + const { workspace, repoSlug } = this.getDefaultParams(params); + const prId = parseInt(params.pullRequestId || params.pr_id, 10); + if (!workspace || !repoSlug || isNaN(prId)) { + return { success: false, error: 'Missing required parameters' }; + } + const result = await this.client.updatePullRequest(workspace, repoSlug, prId, { + title: params.title, + description: params.description, + reviewers: params.reviewers, + destination_branch: params.destination_branch, + }); + return { success: true, data: result }; + } catch (error) { + return { success: false, error: `Update pull request failed: ${String(error)}` }; + } + } + + private async mergePullRequest(params: ToolCallParams): Promise { + try { + const { workspace, repoSlug } = this.getDefaultParams(params); + const prId = parseInt(params.pullRequestId || params.pr_id, 10); + if (!workspace || !repoSlug || isNaN(prId)) { + return { success: false, error: 'Missing required parameters' }; + } + const result = await this.client.mergePullRequest(workspace, repoSlug, prId, { + merge_strategy: params.merge_strategy, + commit_message: params.commit_message, + close_source_branch: params.close_source_branch, + }); + return { success: true, data: result }; + } catch (error) { + return { success: false, error: `Merge pull request failed: ${String(error)}` }; + } + } + + private async declinePullRequest(params: ToolCallParams): Promise { + try { + const { workspace, repoSlug } = this.getDefaultParams(params); + const prId = parseInt(params.pullRequestId || params.pr_id, 10); + if (!workspace || !repoSlug || isNaN(prId)) { + return { success: false, error: 'Missing required parameters' }; + } + const result = await this.client.declinePullRequest(workspace, repoSlug, prId); + return { success: true, data: result }; + } catch (error) { + return { success: false, error: `Decline pull request failed: ${String(error)}` }; + } + } + + private async approvePullRequest(params: ToolCallParams): Promise { + try { + const { workspace, repoSlug } = this.getDefaultParams(params); + const prId = parseInt(params.pullRequestId || params.pr_id, 10); + if (!workspace || !repoSlug || isNaN(prId)) { + return { success: false, error: 'Missing required parameters' }; + } + const result = await this.client.approvePullRequest(workspace, repoSlug, prId); + return { success: true, data: result }; + } catch (error) { + return { success: false, error: `Approve pull request failed: ${String(error)}` }; + } + } + + private async unapprovePullRequest(params: ToolCallParams): Promise { + try { + const { workspace, repoSlug } = this.getDefaultParams(params); + const prId = parseInt(params.pullRequestId || params.pr_id, 10); + if (!workspace || !repoSlug || isNaN(prId)) { + return { success: false, error: 'Missing required parameters' }; + } + const result = await this.client.unapprovePullRequest(workspace, repoSlug, prId); + return { success: true, data: result }; + } catch (error) { + return { success: false, error: `Unapprove pull request failed: ${String(error)}` }; + } + } + + private async requestChangesPullRequest(params: ToolCallParams): Promise { + try { + const { workspace, repoSlug } = this.getDefaultParams(params); + const prId = parseInt(params.pullRequestId || params.pr_id, 10); + if (!workspace || !repoSlug || isNaN(prId)) { + return { success: false, error: 'Missing required parameters' }; + } + const result = await this.client.requestChangesPullRequest(workspace, repoSlug, prId); + return { success: true, data: result }; + } catch (error) { + return { success: false, error: `Request changes failed: ${String(error)}` }; + } + } + + private async removeRequestChangesPullRequest(params: ToolCallParams): Promise { + try { + const { workspace, repoSlug } = this.getDefaultParams(params); + const prId = parseInt(params.pullRequestId || params.pr_id, 10); + if (!workspace || !repoSlug || isNaN(prId)) { + return { success: false, error: 'Missing required parameters' }; + } + const result = await this.client.removeRequestChangesPullRequest(workspace, repoSlug, prId); + return { success: true, data: result }; + } catch (error) { + return { success: false, error: `Remove request-changes failed: ${String(error)}` }; + } + } + + private async addPullRequestComment(params: ToolCallParams): Promise { + try { + const { workspace, repoSlug } = this.getDefaultParams(params); + const prId = parseInt(params.pullRequestId || params.pr_id, 10); + if (!workspace || !repoSlug || isNaN(prId) || !params.content) { + return { success: false, error: 'Missing required parameters: workspace, repository, pullRequestId, content' }; + } + const opts: any = { content: params.content }; + if (params.inline_path && params.inline_line) { + opts.inline = { path: params.inline_path, to: parseInt(params.inline_line, 10) }; + } + if (params.parent_comment_id) { + opts.parent_id = parseInt(params.parent_comment_id, 10); + } + const result = await this.client.addPullRequestComment(workspace, repoSlug, prId, opts); + return { success: true, data: result }; + } catch (error) { + return { success: false, error: `Add comment failed: ${String(error)}` }; + } + } + + private async updatePullRequestComment(params: ToolCallParams): Promise { + try { + const { workspace, repoSlug } = this.getDefaultParams(params); + const prId = parseInt(params.pullRequestId || params.pr_id, 10); + const commentId = parseInt(params.commentId || params.comment_id, 10); + if (!workspace || !repoSlug || isNaN(prId) || isNaN(commentId) || !params.content) { + return { success: false, error: 'Missing required parameters: workspace, repository, pullRequestId, commentId, content' }; + } + const result = await this.client.updatePullRequestComment(workspace, repoSlug, prId, commentId, { content: params.content }); + return { success: true, data: result }; + } catch (error) { + return { success: false, error: `Update comment failed: ${String(error)}` }; + } + } + + private async deletePullRequestComment(params: ToolCallParams): Promise { + try { + const { workspace, repoSlug } = this.getDefaultParams(params); + const prId = parseInt(params.pullRequestId || params.pr_id, 10); + const commentId = parseInt(params.commentId || params.comment_id, 10); + if (!workspace || !repoSlug || isNaN(prId) || isNaN(commentId)) { + return { success: false, error: 'Missing required parameters' }; + } + const result = await this.client.deletePullRequestComment(workspace, repoSlug, prId, commentId); + return { success: true, data: result }; + } catch (error) { + return { success: false, error: `Delete comment failed: ${String(error)}` }; + } + } + + private async createPullRequestTask(params: ToolCallParams): Promise { + try { + const { workspace, repoSlug } = this.getDefaultParams(params); + const prId = parseInt(params.pullRequestId || params.pr_id, 10); + if (!workspace || !repoSlug || isNaN(prId) || !params.content) { + return { success: false, error: 'Missing required parameters: workspace, repository, pullRequestId, content' }; + } + const opts: any = { content: params.content }; + if (params.comment_id) opts.comment_id = parseInt(params.comment_id, 10); + const result = await this.client.createPullRequestTask(workspace, repoSlug, prId, opts); + return { success: true, data: result }; + } catch (error) { + return { success: false, error: `Create task failed: ${String(error)}` }; + } + } + + private async updatePullRequestTask(params: ToolCallParams): Promise { + try { + const { workspace, repoSlug } = this.getDefaultParams(params); + const prId = parseInt(params.pullRequestId || params.pr_id, 10); + const taskId = parseInt(params.taskId || params.task_id, 10); + if (!workspace || !repoSlug || isNaN(prId) || isNaN(taskId)) { + return { success: false, error: 'Missing required parameters' }; + } + const result = await this.client.updatePullRequestTask(workspace, repoSlug, prId, taskId, { + content: params.content, + state: params.state, + }); + return { success: true, data: result }; + } catch (error) { + return { success: false, error: `Update task failed: ${String(error)}` }; + } + } + + private async deletePullRequestTask(params: ToolCallParams): Promise { + try { + const { workspace, repoSlug } = this.getDefaultParams(params); + const prId = parseInt(params.pullRequestId || params.pr_id, 10); + const taskId = parseInt(params.taskId || params.task_id, 10); + if (!workspace || !repoSlug || isNaN(prId) || isNaN(taskId)) { + return { success: false, error: 'Missing required parameters' }; + } + const result = await this.client.deletePullRequestTask(workspace, repoSlug, prId, taskId); + return { success: true, data: result }; + } catch (error) { + return { success: false, error: `Delete task failed: ${String(error)}` }; + } + } } export default BitbucketRouter; \ No newline at end of file