bitbucket-mcp
Advanced tools
1008
dist/index.js
@@ -116,2 +116,439 @@ #!/usr/bin/env node | ||
}, | ||
{ | ||
name: "createPullRequest", | ||
description: "Create a new pull request", | ||
inputSchema: { | ||
type: "object", | ||
properties: { | ||
workspace: { | ||
type: "string", | ||
description: "Bitbucket workspace name", | ||
}, | ||
repo_slug: { type: "string", description: "Repository slug" }, | ||
title: { type: "string", description: "Pull request title" }, | ||
description: { | ||
type: "string", | ||
description: "Pull request description", | ||
}, | ||
sourceBranch: { | ||
type: "string", | ||
description: "Source branch name", | ||
}, | ||
targetBranch: { | ||
type: "string", | ||
description: "Target branch name", | ||
}, | ||
reviewers: { | ||
type: "array", | ||
items: { type: "string" }, | ||
description: "List of reviewer usernames", | ||
}, | ||
}, | ||
required: [ | ||
"workspace", | ||
"repo_slug", | ||
"title", | ||
"description", | ||
"sourceBranch", | ||
"targetBranch", | ||
], | ||
}, | ||
}, | ||
{ | ||
name: "getPullRequest", | ||
description: "Get details for a specific pull request", | ||
inputSchema: { | ||
type: "object", | ||
properties: { | ||
workspace: { | ||
type: "string", | ||
description: "Bitbucket workspace name", | ||
}, | ||
repo_slug: { type: "string", description: "Repository slug" }, | ||
pull_request_id: { | ||
type: "string", | ||
description: "Pull request ID", | ||
}, | ||
}, | ||
required: ["workspace", "repo_slug", "pull_request_id"], | ||
}, | ||
}, | ||
{ | ||
name: "updatePullRequest", | ||
description: "Update a pull request", | ||
inputSchema: { | ||
type: "object", | ||
properties: { | ||
workspace: { | ||
type: "string", | ||
description: "Bitbucket workspace name", | ||
}, | ||
repo_slug: { type: "string", description: "Repository slug" }, | ||
pull_request_id: { | ||
type: "string", | ||
description: "Pull request ID", | ||
}, | ||
title: { type: "string", description: "New pull request title" }, | ||
description: { | ||
type: "string", | ||
description: "New pull request description", | ||
}, | ||
}, | ||
required: ["workspace", "repo_slug", "pull_request_id"], | ||
}, | ||
}, | ||
{ | ||
name: "getPullRequestActivity", | ||
description: "Get activity log for a pull request", | ||
inputSchema: { | ||
type: "object", | ||
properties: { | ||
workspace: { | ||
type: "string", | ||
description: "Bitbucket workspace name", | ||
}, | ||
repo_slug: { type: "string", description: "Repository slug" }, | ||
pull_request_id: { | ||
type: "string", | ||
description: "Pull request ID", | ||
}, | ||
}, | ||
required: ["workspace", "repo_slug", "pull_request_id"], | ||
}, | ||
}, | ||
{ | ||
name: "approvePullRequest", | ||
description: "Approve a pull request", | ||
inputSchema: { | ||
type: "object", | ||
properties: { | ||
workspace: { | ||
type: "string", | ||
description: "Bitbucket workspace name", | ||
}, | ||
repo_slug: { type: "string", description: "Repository slug" }, | ||
pull_request_id: { | ||
type: "string", | ||
description: "Pull request ID", | ||
}, | ||
}, | ||
required: ["workspace", "repo_slug", "pull_request_id"], | ||
}, | ||
}, | ||
{ | ||
name: "unapprovePullRequest", | ||
description: "Remove approval from a pull request", | ||
inputSchema: { | ||
type: "object", | ||
properties: { | ||
workspace: { | ||
type: "string", | ||
description: "Bitbucket workspace name", | ||
}, | ||
repo_slug: { type: "string", description: "Repository slug" }, | ||
pull_request_id: { | ||
type: "string", | ||
description: "Pull request ID", | ||
}, | ||
}, | ||
required: ["workspace", "repo_slug", "pull_request_id"], | ||
}, | ||
}, | ||
{ | ||
name: "declinePullRequest", | ||
description: "Decline a pull request", | ||
inputSchema: { | ||
type: "object", | ||
properties: { | ||
workspace: { | ||
type: "string", | ||
description: "Bitbucket workspace name", | ||
}, | ||
repo_slug: { type: "string", description: "Repository slug" }, | ||
pull_request_id: { | ||
type: "string", | ||
description: "Pull request ID", | ||
}, | ||
message: { type: "string", description: "Reason for declining" }, | ||
}, | ||
required: ["workspace", "repo_slug", "pull_request_id"], | ||
}, | ||
}, | ||
{ | ||
name: "mergePullRequest", | ||
description: "Merge a pull request", | ||
inputSchema: { | ||
type: "object", | ||
properties: { | ||
workspace: { | ||
type: "string", | ||
description: "Bitbucket workspace name", | ||
}, | ||
repo_slug: { type: "string", description: "Repository slug" }, | ||
pull_request_id: { | ||
type: "string", | ||
description: "Pull request ID", | ||
}, | ||
message: { type: "string", description: "Merge commit message" }, | ||
strategy: { | ||
type: "string", | ||
enum: ["merge-commit", "squash", "fast-forward"], | ||
description: "Merge strategy", | ||
}, | ||
}, | ||
required: ["workspace", "repo_slug", "pull_request_id"], | ||
}, | ||
}, | ||
{ | ||
name: "getPullRequestComments", | ||
description: "List comments on a pull request", | ||
inputSchema: { | ||
type: "object", | ||
properties: { | ||
workspace: { | ||
type: "string", | ||
description: "Bitbucket workspace name", | ||
}, | ||
repo_slug: { type: "string", description: "Repository slug" }, | ||
pull_request_id: { | ||
type: "string", | ||
description: "Pull request ID", | ||
}, | ||
}, | ||
required: ["workspace", "repo_slug", "pull_request_id"], | ||
}, | ||
}, | ||
{ | ||
name: "getPullRequestDiff", | ||
description: "Get diff for a pull request", | ||
inputSchema: { | ||
type: "object", | ||
properties: { | ||
workspace: { | ||
type: "string", | ||
description: "Bitbucket workspace name", | ||
}, | ||
repo_slug: { type: "string", description: "Repository slug" }, | ||
pull_request_id: { | ||
type: "string", | ||
description: "Pull request ID", | ||
}, | ||
}, | ||
required: ["workspace", "repo_slug", "pull_request_id"], | ||
}, | ||
}, | ||
{ | ||
name: "getPullRequestCommits", | ||
description: "Get commits on a pull request", | ||
inputSchema: { | ||
type: "object", | ||
properties: { | ||
workspace: { | ||
type: "string", | ||
description: "Bitbucket workspace name", | ||
}, | ||
repo_slug: { type: "string", description: "Repository slug" }, | ||
pull_request_id: { | ||
type: "string", | ||
description: "Pull request ID", | ||
}, | ||
}, | ||
required: ["workspace", "repo_slug", "pull_request_id"], | ||
}, | ||
}, | ||
{ | ||
name: "getRepositoryBranchingModel", | ||
description: "Get the branching model for a repository", | ||
inputSchema: { | ||
type: "object", | ||
properties: { | ||
workspace: { | ||
type: "string", | ||
description: "Bitbucket workspace name", | ||
}, | ||
repo_slug: { type: "string", description: "Repository slug" }, | ||
}, | ||
required: ["workspace", "repo_slug"], | ||
}, | ||
}, | ||
{ | ||
name: "getRepositoryBranchingModelSettings", | ||
description: "Get the branching model config for a repository", | ||
inputSchema: { | ||
type: "object", | ||
properties: { | ||
workspace: { | ||
type: "string", | ||
description: "Bitbucket workspace name", | ||
}, | ||
repo_slug: { type: "string", description: "Repository slug" }, | ||
}, | ||
required: ["workspace", "repo_slug"], | ||
}, | ||
}, | ||
{ | ||
name: "updateRepositoryBranchingModelSettings", | ||
description: "Update the branching model config for a repository", | ||
inputSchema: { | ||
type: "object", | ||
properties: { | ||
workspace: { | ||
type: "string", | ||
description: "Bitbucket workspace name", | ||
}, | ||
repo_slug: { type: "string", description: "Repository slug" }, | ||
development: { | ||
type: "object", | ||
description: "Development branch settings", | ||
properties: { | ||
name: { type: "string", description: "Branch name" }, | ||
use_mainbranch: { | ||
type: "boolean", | ||
description: "Use main branch", | ||
}, | ||
}, | ||
}, | ||
production: { | ||
type: "object", | ||
description: "Production branch settings", | ||
properties: { | ||
name: { type: "string", description: "Branch name" }, | ||
use_mainbranch: { | ||
type: "boolean", | ||
description: "Use main branch", | ||
}, | ||
enabled: { | ||
type: "boolean", | ||
description: "Enable production branch", | ||
}, | ||
}, | ||
}, | ||
branch_types: { | ||
type: "array", | ||
description: "Branch types configuration", | ||
items: { | ||
type: "object", | ||
properties: { | ||
kind: { | ||
type: "string", | ||
description: "Branch type kind (e.g., bugfix, feature)", | ||
}, | ||
prefix: { type: "string", description: "Branch prefix" }, | ||
enabled: { | ||
type: "boolean", | ||
description: "Enable this branch type", | ||
}, | ||
}, | ||
required: ["kind"], | ||
}, | ||
}, | ||
}, | ||
required: ["workspace", "repo_slug"], | ||
}, | ||
}, | ||
{ | ||
name: "getEffectiveRepositoryBranchingModel", | ||
description: "Get the effective branching model for a repository", | ||
inputSchema: { | ||
type: "object", | ||
properties: { | ||
workspace: { | ||
type: "string", | ||
description: "Bitbucket workspace name", | ||
}, | ||
repo_slug: { type: "string", description: "Repository slug" }, | ||
}, | ||
required: ["workspace", "repo_slug"], | ||
}, | ||
}, | ||
{ | ||
name: "getProjectBranchingModel", | ||
description: "Get the branching model for a project", | ||
inputSchema: { | ||
type: "object", | ||
properties: { | ||
workspace: { | ||
type: "string", | ||
description: "Bitbucket workspace name", | ||
}, | ||
project_key: { type: "string", description: "Project key" }, | ||
}, | ||
required: ["workspace", "project_key"], | ||
}, | ||
}, | ||
{ | ||
name: "getProjectBranchingModelSettings", | ||
description: "Get the branching model config for a project", | ||
inputSchema: { | ||
type: "object", | ||
properties: { | ||
workspace: { | ||
type: "string", | ||
description: "Bitbucket workspace name", | ||
}, | ||
project_key: { type: "string", description: "Project key" }, | ||
}, | ||
required: ["workspace", "project_key"], | ||
}, | ||
}, | ||
{ | ||
name: "updateProjectBranchingModelSettings", | ||
description: "Update the branching model config for a project", | ||
inputSchema: { | ||
type: "object", | ||
properties: { | ||
workspace: { | ||
type: "string", | ||
description: "Bitbucket workspace name", | ||
}, | ||
project_key: { type: "string", description: "Project key" }, | ||
development: { | ||
type: "object", | ||
description: "Development branch settings", | ||
properties: { | ||
name: { type: "string", description: "Branch name" }, | ||
use_mainbranch: { | ||
type: "boolean", | ||
description: "Use main branch", | ||
}, | ||
}, | ||
}, | ||
production: { | ||
type: "object", | ||
description: "Production branch settings", | ||
properties: { | ||
name: { type: "string", description: "Branch name" }, | ||
use_mainbranch: { | ||
type: "boolean", | ||
description: "Use main branch", | ||
}, | ||
enabled: { | ||
type: "boolean", | ||
description: "Enable production branch", | ||
}, | ||
}, | ||
}, | ||
branch_types: { | ||
type: "array", | ||
description: "Branch types configuration", | ||
items: { | ||
type: "object", | ||
properties: { | ||
kind: { | ||
type: "string", | ||
description: "Branch type kind (e.g., bugfix, feature)", | ||
}, | ||
prefix: { type: "string", description: "Branch prefix" }, | ||
enabled: { | ||
type: "boolean", | ||
description: "Enable this branch type", | ||
}, | ||
}, | ||
required: ["kind"], | ||
}, | ||
}, | ||
}, | ||
required: ["workspace", "project_key"], | ||
}, | ||
}, | ||
], | ||
@@ -133,2 +570,38 @@ })); | ||
return await this.getPullRequests(args.workspace, args.repo_slug, args.state, args.limit); | ||
case "createPullRequest": | ||
return await this.createPullRequest(args.workspace, args.repo_slug, args.title, args.description, args.sourceBranch, args.targetBranch, args.reviewers); | ||
case "getPullRequest": | ||
return await this.getPullRequest(args.workspace, args.repo_slug, args.pull_request_id); | ||
case "updatePullRequest": | ||
return await this.updatePullRequest(args.workspace, args.repo_slug, args.pull_request_id, args.title, args.description); | ||
case "getPullRequestActivity": | ||
return await this.getPullRequestActivity(args.workspace, args.repo_slug, args.pull_request_id); | ||
case "approvePullRequest": | ||
return await this.approvePullRequest(args.workspace, args.repo_slug, args.pull_request_id); | ||
case "unapprovePullRequest": | ||
return await this.unapprovePullRequest(args.workspace, args.repo_slug, args.pull_request_id); | ||
case "declinePullRequest": | ||
return await this.declinePullRequest(args.workspace, args.repo_slug, args.pull_request_id, args.message); | ||
case "mergePullRequest": | ||
return await this.mergePullRequest(args.workspace, args.repo_slug, args.pull_request_id, args.message, args.strategy); | ||
case "getPullRequestComments": | ||
return await this.getPullRequestComments(args.workspace, args.repo_slug, args.pull_request_id); | ||
case "getPullRequestDiff": | ||
return await this.getPullRequestDiff(args.workspace, args.repo_slug, args.pull_request_id); | ||
case "getPullRequestCommits": | ||
return await this.getPullRequestCommits(args.workspace, args.repo_slug, args.pull_request_id); | ||
case "getRepositoryBranchingModel": | ||
return await this.getRepositoryBranchingModel(args.workspace, args.repo_slug); | ||
case "getRepositoryBranchingModelSettings": | ||
return await this.getRepositoryBranchingModelSettings(args.workspace, args.repo_slug); | ||
case "updateRepositoryBranchingModelSettings": | ||
return await this.updateRepositoryBranchingModelSettings(args.workspace, args.repo_slug, args.development, args.production, args.branch_types); | ||
case "getEffectiveRepositoryBranchingModel": | ||
return await this.getEffectiveRepositoryBranchingModel(args.workspace, args.repo_slug); | ||
case "getProjectBranchingModel": | ||
return await this.getProjectBranchingModel(args.workspace, args.project_key); | ||
case "getProjectBranchingModelSettings": | ||
return await this.getProjectBranchingModelSettings(args.workspace, args.project_key); | ||
case "updateProjectBranchingModelSettings": | ||
return await this.updateProjectBranchingModelSettings(args.workspace, args.project_key, args.development, args.production, args.branch_types); | ||
default: | ||
@@ -228,2 +701,537 @@ throw new McpError(ErrorCode.MethodNotFound, `Unknown tool: ${request.params.name}`); | ||
} | ||
async createPullRequest(workspace, repo_slug, title, description, sourceBranch, targetBranch, reviewers) { | ||
try { | ||
logger.info("Creating Bitbucket pull request", { | ||
workspace, | ||
repo_slug, | ||
title, | ||
sourceBranch, | ||
targetBranch, | ||
}); | ||
// Prepare reviewers format if provided | ||
const reviewersArray = reviewers?.map((username) => ({ | ||
username, | ||
})) || []; | ||
// Create the pull request | ||
const response = await this.api.post(`/repositories/${workspace}/${repo_slug}/pullrequests`, { | ||
title, | ||
description, | ||
source: { | ||
branch: { | ||
name: sourceBranch, | ||
}, | ||
}, | ||
destination: { | ||
branch: { | ||
name: targetBranch, | ||
}, | ||
}, | ||
reviewers: reviewersArray, | ||
close_source_branch: true, | ||
}); | ||
return { | ||
content: [ | ||
{ | ||
type: "text", | ||
text: JSON.stringify(response.data, null, 2), | ||
}, | ||
], | ||
}; | ||
} | ||
catch (error) { | ||
logger.error("Error creating pull request", { | ||
error, | ||
workspace, | ||
repo_slug, | ||
}); | ||
throw new McpError(ErrorCode.InternalError, `Failed to create pull request: ${error instanceof Error ? error.message : String(error)}`); | ||
} | ||
} | ||
async getPullRequest(workspace, repo_slug, pull_request_id) { | ||
try { | ||
logger.info("Getting Bitbucket pull request details", { | ||
workspace, | ||
repo_slug, | ||
pull_request_id, | ||
}); | ||
const response = await this.api.get(`/repositories/${workspace}/${repo_slug}/pullrequests/${pull_request_id}`); | ||
return { | ||
content: [ | ||
{ | ||
type: "text", | ||
text: JSON.stringify(response.data, null, 2), | ||
}, | ||
], | ||
}; | ||
} | ||
catch (error) { | ||
logger.error("Error getting pull request details", { | ||
error, | ||
workspace, | ||
repo_slug, | ||
pull_request_id, | ||
}); | ||
throw new McpError(ErrorCode.InternalError, `Failed to get pull request details: ${error instanceof Error ? error.message : String(error)}`); | ||
} | ||
} | ||
async updatePullRequest(workspace, repo_slug, pull_request_id, title, description) { | ||
try { | ||
logger.info("Updating Bitbucket pull request", { | ||
workspace, | ||
repo_slug, | ||
pull_request_id, | ||
}); | ||
// Only include fields that are provided | ||
const updateData = {}; | ||
if (title !== undefined) | ||
updateData.title = title; | ||
if (description !== undefined) | ||
updateData.description = description; | ||
const response = await this.api.put(`/repositories/${workspace}/${repo_slug}/pullrequests/${pull_request_id}`, updateData); | ||
return { | ||
content: [ | ||
{ | ||
type: "text", | ||
text: JSON.stringify(response.data, null, 2), | ||
}, | ||
], | ||
}; | ||
} | ||
catch (error) { | ||
logger.error("Error updating pull request", { | ||
error, | ||
workspace, | ||
repo_slug, | ||
pull_request_id, | ||
}); | ||
throw new McpError(ErrorCode.InternalError, `Failed to update pull request: ${error instanceof Error ? error.message : String(error)}`); | ||
} | ||
} | ||
async getPullRequestActivity(workspace, repo_slug, pull_request_id) { | ||
try { | ||
logger.info("Getting Bitbucket pull request activity", { | ||
workspace, | ||
repo_slug, | ||
pull_request_id, | ||
}); | ||
const response = await this.api.get(`/repositories/${workspace}/${repo_slug}/pullrequests/${pull_request_id}/activity`); | ||
return { | ||
content: [ | ||
{ | ||
type: "text", | ||
text: JSON.stringify(response.data.values, null, 2), | ||
}, | ||
], | ||
}; | ||
} | ||
catch (error) { | ||
logger.error("Error getting pull request activity", { | ||
error, | ||
workspace, | ||
repo_slug, | ||
pull_request_id, | ||
}); | ||
throw new McpError(ErrorCode.InternalError, `Failed to get pull request activity: ${error instanceof Error ? error.message : String(error)}`); | ||
} | ||
} | ||
async approvePullRequest(workspace, repo_slug, pull_request_id) { | ||
try { | ||
logger.info("Approving Bitbucket pull request", { | ||
workspace, | ||
repo_slug, | ||
pull_request_id, | ||
}); | ||
const response = await this.api.post(`/repositories/${workspace}/${repo_slug}/pullrequests/${pull_request_id}/approve`); | ||
return { | ||
content: [ | ||
{ | ||
type: "text", | ||
text: JSON.stringify(response.data, null, 2), | ||
}, | ||
], | ||
}; | ||
} | ||
catch (error) { | ||
logger.error("Error approving pull request", { | ||
error, | ||
workspace, | ||
repo_slug, | ||
pull_request_id, | ||
}); | ||
throw new McpError(ErrorCode.InternalError, `Failed to approve pull request: ${error instanceof Error ? error.message : String(error)}`); | ||
} | ||
} | ||
async unapprovePullRequest(workspace, repo_slug, pull_request_id) { | ||
try { | ||
logger.info("Unapproving Bitbucket pull request", { | ||
workspace, | ||
repo_slug, | ||
pull_request_id, | ||
}); | ||
const response = await this.api.delete(`/repositories/${workspace}/${repo_slug}/pullrequests/${pull_request_id}/approve`); | ||
return { | ||
content: [ | ||
{ | ||
type: "text", | ||
text: "Pull request approval removed successfully.", | ||
}, | ||
], | ||
}; | ||
} | ||
catch (error) { | ||
logger.error("Error unapproving pull request", { | ||
error, | ||
workspace, | ||
repo_slug, | ||
pull_request_id, | ||
}); | ||
throw new McpError(ErrorCode.InternalError, `Failed to unapprove pull request: ${error instanceof Error ? error.message : String(error)}`); | ||
} | ||
} | ||
async declinePullRequest(workspace, repo_slug, pull_request_id, message) { | ||
try { | ||
logger.info("Declining Bitbucket pull request", { | ||
workspace, | ||
repo_slug, | ||
pull_request_id, | ||
}); | ||
// Include message if provided | ||
const data = message ? { message } : {}; | ||
const response = await this.api.post(`/repositories/${workspace}/${repo_slug}/pullrequests/${pull_request_id}/decline`, data); | ||
return { | ||
content: [ | ||
{ | ||
type: "text", | ||
text: JSON.stringify(response.data, null, 2), | ||
}, | ||
], | ||
}; | ||
} | ||
catch (error) { | ||
logger.error("Error declining pull request", { | ||
error, | ||
workspace, | ||
repo_slug, | ||
pull_request_id, | ||
}); | ||
throw new McpError(ErrorCode.InternalError, `Failed to decline pull request: ${error instanceof Error ? error.message : String(error)}`); | ||
} | ||
} | ||
async mergePullRequest(workspace, repo_slug, pull_request_id, message, strategy) { | ||
try { | ||
logger.info("Merging Bitbucket pull request", { | ||
workspace, | ||
repo_slug, | ||
pull_request_id, | ||
strategy, | ||
}); | ||
// Build request data | ||
const data = {}; | ||
if (message) | ||
data.message = message; | ||
if (strategy) | ||
data.merge_strategy = strategy; | ||
const response = await this.api.post(`/repositories/${workspace}/${repo_slug}/pullrequests/${pull_request_id}/merge`, data); | ||
return { | ||
content: [ | ||
{ | ||
type: "text", | ||
text: JSON.stringify(response.data, null, 2), | ||
}, | ||
], | ||
}; | ||
} | ||
catch (error) { | ||
logger.error("Error merging pull request", { | ||
error, | ||
workspace, | ||
repo_slug, | ||
pull_request_id, | ||
}); | ||
throw new McpError(ErrorCode.InternalError, `Failed to merge pull request: ${error instanceof Error ? error.message : String(error)}`); | ||
} | ||
} | ||
async getPullRequestComments(workspace, repo_slug, pull_request_id) { | ||
try { | ||
logger.info("Getting Bitbucket pull request comments", { | ||
workspace, | ||
repo_slug, | ||
pull_request_id, | ||
}); | ||
const response = await this.api.get(`/repositories/${workspace}/${repo_slug}/pullrequests/${pull_request_id}/comments`); | ||
return { | ||
content: [ | ||
{ | ||
type: "text", | ||
text: JSON.stringify(response.data.values, null, 2), | ||
}, | ||
], | ||
}; | ||
} | ||
catch (error) { | ||
logger.error("Error getting pull request comments", { | ||
error, | ||
workspace, | ||
repo_slug, | ||
pull_request_id, | ||
}); | ||
throw new McpError(ErrorCode.InternalError, `Failed to get pull request comments: ${error instanceof Error ? error.message : String(error)}`); | ||
} | ||
} | ||
async getPullRequestDiff(workspace, repo_slug, pull_request_id) { | ||
try { | ||
logger.info("Getting Bitbucket pull request diff", { | ||
workspace, | ||
repo_slug, | ||
pull_request_id, | ||
}); | ||
const response = await this.api.get(`/repositories/${workspace}/${repo_slug}/pullrequests/${pull_request_id}/diff`, { | ||
headers: { | ||
Accept: "text/plain", | ||
}, | ||
responseType: "text", | ||
}); | ||
return { | ||
content: [ | ||
{ | ||
type: "text", | ||
text: response.data, | ||
}, | ||
], | ||
}; | ||
} | ||
catch (error) { | ||
logger.error("Error getting pull request diff", { | ||
error, | ||
workspace, | ||
repo_slug, | ||
pull_request_id, | ||
}); | ||
throw new McpError(ErrorCode.InternalError, `Failed to get pull request diff: ${error instanceof Error ? error.message : String(error)}`); | ||
} | ||
} | ||
async getPullRequestCommits(workspace, repo_slug, pull_request_id) { | ||
try { | ||
logger.info("Getting Bitbucket pull request commits", { | ||
workspace, | ||
repo_slug, | ||
pull_request_id, | ||
}); | ||
const response = await this.api.get(`/repositories/${workspace}/${repo_slug}/pullrequests/${pull_request_id}/commits`); | ||
return { | ||
content: [ | ||
{ | ||
type: "text", | ||
text: JSON.stringify(response.data.values, null, 2), | ||
}, | ||
], | ||
}; | ||
} | ||
catch (error) { | ||
logger.error("Error getting pull request commits", { | ||
error, | ||
workspace, | ||
repo_slug, | ||
pull_request_id, | ||
}); | ||
throw new McpError(ErrorCode.InternalError, `Failed to get pull request commits: ${error instanceof Error ? error.message : String(error)}`); | ||
} | ||
} | ||
async getRepositoryBranchingModel(workspace, repo_slug) { | ||
try { | ||
logger.info("Getting repository branching model", { | ||
workspace, | ||
repo_slug, | ||
}); | ||
const response = await this.api.get(`/repositories/${workspace}/${repo_slug}/branching-model`); | ||
return { | ||
content: [ | ||
{ | ||
type: "text", | ||
text: JSON.stringify(response.data, null, 2), | ||
}, | ||
], | ||
}; | ||
} | ||
catch (error) { | ||
logger.error("Error getting repository branching model", { | ||
error, | ||
workspace, | ||
repo_slug, | ||
}); | ||
throw new McpError(ErrorCode.InternalError, `Failed to get repository branching model: ${error instanceof Error ? error.message : String(error)}`); | ||
} | ||
} | ||
async getRepositoryBranchingModelSettings(workspace, repo_slug) { | ||
try { | ||
logger.info("Getting repository branching model settings", { | ||
workspace, | ||
repo_slug, | ||
}); | ||
const response = await this.api.get(`/repositories/${workspace}/${repo_slug}/branching-model/settings`); | ||
return { | ||
content: [ | ||
{ | ||
type: "text", | ||
text: JSON.stringify(response.data, null, 2), | ||
}, | ||
], | ||
}; | ||
} | ||
catch (error) { | ||
logger.error("Error getting repository branching model settings", { | ||
error, | ||
workspace, | ||
repo_slug, | ||
}); | ||
throw new McpError(ErrorCode.InternalError, `Failed to get repository branching model settings: ${error instanceof Error ? error.message : String(error)}`); | ||
} | ||
} | ||
async updateRepositoryBranchingModelSettings(workspace, repo_slug, development, production, branch_types) { | ||
try { | ||
logger.info("Updating repository branching model settings", { | ||
workspace, | ||
repo_slug, | ||
development, | ||
production, | ||
branch_types, | ||
}); | ||
// Build request data with only the fields that are provided | ||
const updateData = {}; | ||
if (development) | ||
updateData.development = development; | ||
if (production) | ||
updateData.production = production; | ||
if (branch_types) | ||
updateData.branch_types = branch_types; | ||
const response = await this.api.put(`/repositories/${workspace}/${repo_slug}/branching-model/settings`, updateData); | ||
return { | ||
content: [ | ||
{ | ||
type: "text", | ||
text: JSON.stringify(response.data, null, 2), | ||
}, | ||
], | ||
}; | ||
} | ||
catch (error) { | ||
logger.error("Error updating repository branching model settings", { | ||
error, | ||
workspace, | ||
repo_slug, | ||
}); | ||
throw new McpError(ErrorCode.InternalError, `Failed to update repository branching model settings: ${error instanceof Error ? error.message : String(error)}`); | ||
} | ||
} | ||
async getEffectiveRepositoryBranchingModel(workspace, repo_slug) { | ||
try { | ||
logger.info("Getting effective repository branching model", { | ||
workspace, | ||
repo_slug, | ||
}); | ||
const response = await this.api.get(`/repositories/${workspace}/${repo_slug}/effective-branching-model`); | ||
return { | ||
content: [ | ||
{ | ||
type: "text", | ||
text: JSON.stringify(response.data, null, 2), | ||
}, | ||
], | ||
}; | ||
} | ||
catch (error) { | ||
logger.error("Error getting effective repository branching model", { | ||
error, | ||
workspace, | ||
repo_slug, | ||
}); | ||
throw new McpError(ErrorCode.InternalError, `Failed to get effective repository branching model: ${error instanceof Error ? error.message : String(error)}`); | ||
} | ||
} | ||
async getProjectBranchingModel(workspace, project_key) { | ||
try { | ||
logger.info("Getting project branching model", { | ||
workspace, | ||
project_key, | ||
}); | ||
const response = await this.api.get(`/workspaces/${workspace}/projects/${project_key}/branching-model`); | ||
return { | ||
content: [ | ||
{ | ||
type: "text", | ||
text: JSON.stringify(response.data, null, 2), | ||
}, | ||
], | ||
}; | ||
} | ||
catch (error) { | ||
logger.error("Error getting project branching model", { | ||
error, | ||
workspace, | ||
project_key, | ||
}); | ||
throw new McpError(ErrorCode.InternalError, `Failed to get project branching model: ${error instanceof Error ? error.message : String(error)}`); | ||
} | ||
} | ||
async getProjectBranchingModelSettings(workspace, project_key) { | ||
try { | ||
logger.info("Getting project branching model settings", { | ||
workspace, | ||
project_key, | ||
}); | ||
const response = await this.api.get(`/workspaces/${workspace}/projects/${project_key}/branching-model/settings`); | ||
return { | ||
content: [ | ||
{ | ||
type: "text", | ||
text: JSON.stringify(response.data, null, 2), | ||
}, | ||
], | ||
}; | ||
} | ||
catch (error) { | ||
logger.error("Error getting project branching model settings", { | ||
error, | ||
workspace, | ||
project_key, | ||
}); | ||
throw new McpError(ErrorCode.InternalError, `Failed to get project branching model settings: ${error instanceof Error ? error.message : String(error)}`); | ||
} | ||
} | ||
async updateProjectBranchingModelSettings(workspace, project_key, development, production, branch_types) { | ||
try { | ||
logger.info("Updating project branching model settings", { | ||
workspace, | ||
project_key, | ||
development, | ||
production, | ||
branch_types, | ||
}); | ||
// Build request data with only the fields that are provided | ||
const updateData = {}; | ||
if (development) | ||
updateData.development = development; | ||
if (production) | ||
updateData.production = production; | ||
if (branch_types) | ||
updateData.branch_types = branch_types; | ||
const response = await this.api.put(`/workspaces/${workspace}/projects/${project_key}/branching-model/settings`, updateData); | ||
return { | ||
content: [ | ||
{ | ||
type: "text", | ||
text: JSON.stringify(response.data, null, 2), | ||
}, | ||
], | ||
}; | ||
} | ||
catch (error) { | ||
logger.error("Error updating project branching model settings", { | ||
error, | ||
workspace, | ||
project_key, | ||
}); | ||
throw new McpError(ErrorCode.InternalError, `Failed to update project branching model settings: ${error instanceof Error ? error.message : String(error)}`); | ||
} | ||
} | ||
async run() { | ||
@@ -230,0 +1238,0 @@ const transport = new StdioServerTransport(); |
{ | ||
"name": "bitbucket-mcp", | ||
"version": "4.0.0", | ||
"version": "4.1.0", | ||
"description": "Model Context Protocol (MCP) server for Bitbucket Cloud and Server API integration", | ||
@@ -43,7 +43,7 @@ "type": "module", | ||
"type": "git", | ||
"url": "git+https://github.com/yourusername/bitbucket-mcp.git" | ||
"url": "git+https://github.com/MatanYemini/bitbucket-mcp" | ||
}, | ||
"homepage": "https://github.com/yourusername/bitbucket-mcp#readme", | ||
"homepage": "https://github.com/MatanYemini/bitbucket-mcp#readme", | ||
"bugs": { | ||
"url": "https://github.com/yourusername/bitbucket-mcp/issues" | ||
"url": "https://github.com/MatanYemini/bitbucket-mcp/issues" | ||
}, | ||
@@ -50,0 +50,0 @@ "dependencies": { |
528
README.md
# Bitbucket MCP | ||
A Model Context Protocol (MCP) server for integrating with Bitbucket Cloud and Server APIs. This MCP server allows AI assistants to interact with Bitbucket repositories, pull requests, and other resources. | ||
A Model Context Protocol (MCP) server for integrating with Bitbucket Cloud and Server APIs. This MCP server enables AI assistants like Cursor to interact with your Bitbucket repositories, pull requests, and other resources. | ||
## Safety First | ||
This is a safe and responsible package — no DELETE operations are used, so there’s no risk of data loss. | ||
Every pull request is analyzed with CodeQL to ensure the code remains secure. | ||
[](https://github.com/MatanYemini/bitbucket-mcp/actions/workflows/github-code-scanning/codeql) | ||
[](https://github.com/MatanYemini/bitbucket-mcp) | ||
[](https://opensource.org/licenses/MIT) | ||
[](https://www.npmjs.com/package/bitbucket-mcp) | ||
[](https://smithery.ai/server/@MatanYemini/bitbucket-mcp) | ||
## Overview | ||
Checkout out the [official npm package](https://www.npmjs.com/package/bitbucket-mcp) | ||
This server implements the Model Context Protocol standard to provide AI assistants with access to Bitbucket data and operations. It includes tools for: | ||
This server implements the [Model Context Protocol](https://modelcontextprotocol.io/) standard to provide AI assistants with access to Bitbucket data and operations. It includes tools for: | ||
- Listing and retrieving repositories | ||
- Managing pull requests | ||
- Working with repository content | ||
- Getting repository details | ||
- Fetching pull requests | ||
- And more... | ||
## Getting Started | ||
## Installation | ||
### Prerequisites | ||
### Using NPX (Recommended) | ||
- Node.js 18 or higher | ||
- A Bitbucket Cloud account or Bitbucket Server instance | ||
- Optional: Bitbucket API token for authenticated requests | ||
The easiest way to use this MCP server is via NPX, which allows you to run it without installing it globally: | ||
### Installation | ||
```bash | ||
# Run with environment variables | ||
BITBUCKET_URL="https://bitbucket.org/your-workspace" \ | ||
BITBUCKET_USERNAME="your-username" \ | ||
BITBUCKET_PASSWORD="your-app-password" \ | ||
npx -y bitbucket-mcp@latest | ||
``` | ||
### Manual Installation | ||
Alternatively, you can install it globally or as part of your project: | ||
```bash | ||
# Clone the repository | ||
git clone https://github.com/yourusername/bitbucket-mcp.git | ||
cd bitbucket-mcp | ||
# Install globally | ||
npm install -g bitbucket-mcp | ||
# Install dependencies | ||
npm install | ||
# Or install in your project | ||
npm install bitbucket-mcp | ||
``` | ||
# Build the project | ||
npm run build | ||
Then run it with: | ||
```bash | ||
# If installed globally | ||
BITBUCKET_URL="https://bitbucket.org/your-workspace" \ | ||
BITBUCKET_USERNAME="your-username" \ | ||
BITBUCKET_PASSWORD="your-app-password" \ | ||
bitbucket-mcp | ||
# If installed in your project | ||
BITBUCKET_URL="https://bitbucket.org/your-workspace" \ | ||
BITBUCKET_USERNAME="your-username" \ | ||
BITBUCKET_PASSWORD="your-app-password" \ | ||
npx bitbucket-mcp | ||
``` | ||
### Configuration | ||
## Configuration | ||
Configure the server using environment variables: | ||
### Environment Variables | ||
```bash | ||
# Bitbucket API token (optional, but recommended) | ||
export BITBUCKET_TOKEN=your_token_here | ||
Configure the server using the following environment variables: | ||
# For custom Bitbucket Server installations | ||
export BITBUCKET_API_URL=https://your-bitbucket-server.com/api | ||
| Variable | Description | Required | | ||
| --------------------- | ----------------------------------------------------------------- | -------- | | ||
| `BITBUCKET_URL` | Bitbucket base URL (e.g., "https://bitbucket.org/your-workspace") | Yes | | ||
| `BITBUCKET_USERNAME` | Your Bitbucket username | Yes\* | | ||
| `BITBUCKET_PASSWORD` | Your Bitbucket app password | Yes\* | | ||
| `BITBUCKET_TOKEN` | Your Bitbucket access token (alternative to username/password) | No | | ||
| `BITBUCKET_WORKSPACE` | Default workspace to use when not specified | No | | ||
\* Either `BITBUCKET_TOKEN` or both `BITBUCKET_USERNAME` and `BITBUCKET_PASSWORD` must be provided. | ||
### Creating a Bitbucket App Password | ||
1. Log in to your Bitbucket account | ||
2. Go to Personal Settings > App Passwords | ||
3. Create a new app password with the following permissions: | ||
- Repositories: Read | ||
- Pull requests: Read, Write | ||
4. Copy the generated password and use it as the `BITBUCKET_PASSWORD` environment variable | ||
## Integration with Cursor | ||
To integrate this MCP server with Cursor: | ||
1. Open Cursor | ||
2. Go to Settings > Extensions | ||
3. Click on "Model Context Protocol" | ||
4. Add a new MCP configuration: | ||
```json | ||
"bitbucket": { | ||
"command": "npx", | ||
"env": { | ||
"BITBUCKET_URL": "https://bitbucket.org/your-workspace", | ||
"BITBUCKET_USERNAME": "your-username", | ||
"BITBUCKET_PASSWORD": "your-app-password" | ||
}, | ||
"args": ["-y", "bitbucket-mcp@latest"] | ||
} | ||
``` | ||
### Running the Server | ||
5. Save the configuration | ||
6. Use the "/bitbucket" command in Cursor to access Bitbucket repositories and pull requests | ||
```bash | ||
# Start the server | ||
npm start | ||
### Using a Local Build with Cursor | ||
# Or run in development mode | ||
npm run dev | ||
If you're developing locally and want to test your changes: | ||
# Use standalone mode for direct stdio communication | ||
npm run standalone | ||
```json | ||
"bitbucket-local": { | ||
"command": "node", | ||
"env": { | ||
"BITBUCKET_URL": "https://bitbucket.org/your-workspace", | ||
"BITBUCKET_USERNAME": "your-username", | ||
"BITBUCKET_PASSWORD": "your-app-password" | ||
}, | ||
"args": ["/path/to/your/local/bitbucket-mcp/dist/index.js"] | ||
} | ||
``` | ||
@@ -62,51 +133,361 @@ | ||
This MCP server provides tools for interacting with Bitbucket repositories and pull requests. For a comprehensive list of all available tools with detailed documentation, please see [TOOLS.md](TOOLS.md). | ||
This MCP server provides tools for interacting with Bitbucket repositories and pull requests. Below is a comprehensive list of the available operations: | ||
Some of the available tools include: | ||
### Repository Operations | ||
- **listRepositories**: List repositories in a workspace | ||
- **getRepository**: Get details for a specific repository | ||
- **getPullRequests**: Get pull requests for a repository | ||
#### `listRepositories` | ||
## Integration with MCP Clients | ||
Lists repositories in a workspace. | ||
This server can be integrated with any MCP client by connecting to the server endpoint: | ||
**Parameters:** | ||
- HTTP endpoint: `http://localhost:3000/mcp` | ||
- When running in standalone mode, communication happens over stdio | ||
- `workspace` (optional): Bitbucket workspace name | ||
- `limit` (optional): Maximum number of repositories to return | ||
#### `getRepository` | ||
Gets details for a specific repository. | ||
**Parameters:** | ||
- `workspace`: Bitbucket workspace name | ||
- `repo_slug`: Repository slug | ||
### Pull Request Operations | ||
#### `getPullRequests` | ||
Gets pull requests for a repository. | ||
**Parameters:** | ||
- `workspace`: Bitbucket workspace name | ||
- `repo_slug`: Repository slug | ||
- `state` (optional): Pull request state (`OPEN`, `MERGED`, `DECLINED`, `SUPERSEDED`) | ||
- `limit` (optional): Maximum number of pull requests to return | ||
#### `createPullRequest` | ||
Creates a new pull request. | ||
**Parameters:** | ||
- `workspace`: Bitbucket workspace name | ||
- `repo_slug`: Repository slug | ||
- `title`: Pull request title | ||
- `description`: Pull request description | ||
- `sourceBranch`: Source branch name | ||
- `targetBranch`: Target branch name | ||
- `reviewers` (optional): List of reviewer usernames | ||
#### `getPullRequest` | ||
Gets details for a specific pull request. | ||
**Parameters:** | ||
- `workspace`: Bitbucket workspace name | ||
- `repo_slug`: Repository slug | ||
- `pull_request_id`: Pull request ID | ||
#### `updatePullRequest` | ||
Updates a pull request. | ||
**Parameters:** | ||
- `workspace`: Bitbucket workspace name | ||
- `repo_slug`: Repository slug | ||
- `pull_request_id`: Pull request ID | ||
- Various optional update parameters (title, description, etc.) | ||
#### `getPullRequestActivity` | ||
Gets the activity log for a pull request. | ||
**Parameters:** | ||
- `workspace`: Bitbucket workspace name | ||
- `repo_slug`: Repository slug | ||
- `pull_request_id`: Pull request ID | ||
#### `approvePullRequest` | ||
Approves a pull request. | ||
**Parameters:** | ||
- `workspace`: Bitbucket workspace name | ||
- `repo_slug`: Repository slug | ||
- `pull_request_id`: Pull request ID | ||
#### `unapprovePullRequest` | ||
Removes an approval from a pull request. | ||
**Parameters:** | ||
- `workspace`: Bitbucket workspace name | ||
- `repo_slug`: Repository slug | ||
- `pull_request_id`: Pull request ID | ||
#### `declinePullRequest` | ||
Declines a pull request. | ||
**Parameters:** | ||
- `workspace`: Bitbucket workspace name | ||
- `repo_slug`: Repository slug | ||
- `pull_request_id`: Pull request ID | ||
- `message` (optional): Reason for declining | ||
#### `mergePullRequest` | ||
Merges a pull request. | ||
**Parameters:** | ||
- `workspace`: Bitbucket workspace name | ||
- `repo_slug`: Repository slug | ||
- `pull_request_id`: Pull request ID | ||
- `message` (optional): Merge commit message | ||
- `strategy` (optional): Merge strategy (`merge-commit`, `squash`, `fast-forward`) | ||
#### `requestChanges` | ||
Requests changes on a pull request. | ||
**Parameters:** | ||
- `workspace`: Bitbucket workspace name | ||
- `repo_slug`: Repository slug | ||
- `pull_request_id`: Pull request ID | ||
#### `removeChangeRequest` | ||
Removes a change request from a pull request. | ||
**Parameters:** | ||
- `workspace`: Bitbucket workspace name | ||
- `repo_slug`: Repository slug | ||
- `pull_request_id`: Pull request ID | ||
### Pull Request Comment Operations | ||
#### `getPullRequestComments` | ||
Lists comments on a pull request. | ||
**Parameters:** | ||
- `workspace`: Bitbucket workspace name | ||
- `repo_slug`: Repository slug | ||
- `pull_request_id`: Pull request ID | ||
#### `createPullRequestComment` | ||
Creates a comment on a pull request. | ||
**Parameters:** | ||
- `workspace`: Bitbucket workspace name | ||
- `repo_slug`: Repository slug | ||
- `pull_request_id`: Pull request ID | ||
- `content`: Comment content | ||
- `inline` (optional): Inline comment information | ||
#### `getPullRequestComment` | ||
Gets a specific comment on a pull request. | ||
**Parameters:** | ||
- `workspace`: Bitbucket workspace name | ||
- `repo_slug`: Repository slug | ||
- `pull_request_id`: Pull request ID | ||
- `comment_id`: Comment ID | ||
#### `updatePullRequestComment` | ||
Updates a comment on a pull request. | ||
**Parameters:** | ||
- `workspace`: Bitbucket workspace name | ||
- `repo_slug`: Repository slug | ||
- `pull_request_id`: Pull request ID | ||
- `comment_id`: Comment ID | ||
- `content`: Updated comment content | ||
#### `deletePullRequestComment` | ||
Deletes a comment on a pull request. | ||
**Parameters:** | ||
- `workspace`: Bitbucket workspace name | ||
- `repo_slug`: Repository slug | ||
- `pull_request_id`: Pull request ID | ||
- `comment_id`: Comment ID | ||
#### `resolveComment` | ||
Resolves a comment thread on a pull request. | ||
**Parameters:** | ||
- `workspace`: Bitbucket workspace name | ||
- `repo_slug`: Repository slug | ||
- `pull_request_id`: Pull request ID | ||
- `comment_id`: Comment ID | ||
#### `reopenComment` | ||
Reopens a resolved comment thread on a pull request. | ||
**Parameters:** | ||
- `workspace`: Bitbucket workspace name | ||
- `repo_slug`: Repository slug | ||
- `pull_request_id`: Pull request ID | ||
- `comment_id`: Comment ID | ||
### Pull Request Diff Operations | ||
#### `getPullRequestDiff` | ||
Gets the diff for a pull request. | ||
**Parameters:** | ||
- `workspace`: Bitbucket workspace name | ||
- `repo_slug`: Repository slug | ||
- `pull_request_id`: Pull request ID | ||
#### `getPullRequestDiffStat` | ||
Gets the diff statistics for a pull request. | ||
**Parameters:** | ||
- `workspace`: Bitbucket workspace name | ||
- `repo_slug`: Repository slug | ||
- `pull_request_id`: Pull request ID | ||
#### `getPullRequestPatch` | ||
Gets the patch for a pull request. | ||
**Parameters:** | ||
- `workspace`: Bitbucket workspace name | ||
- `repo_slug`: Repository slug | ||
- `pull_request_id`: Pull request ID | ||
### Pull Request Task Operations | ||
#### `getPullRequestTasks` | ||
Lists tasks on a pull request. | ||
**Parameters:** | ||
- `workspace`: Bitbucket workspace name | ||
- `repo_slug`: Repository slug | ||
- `pull_request_id`: Pull request ID | ||
#### `createPullRequestTask` | ||
Creates a task on a pull request. | ||
**Parameters:** | ||
- `workspace`: Bitbucket workspace name | ||
- `repo_slug`: Repository slug | ||
- `pull_request_id`: Pull request ID | ||
- `content`: Task content | ||
- `comment` (optional): Comment ID to associate with the task | ||
- `pending` (optional): Whether the task is pending | ||
#### `getPullRequestTask` | ||
Gets a specific task on a pull request. | ||
**Parameters:** | ||
- `workspace`: Bitbucket workspace name | ||
- `repo_slug`: Repository slug | ||
- `pull_request_id`: Pull request ID | ||
- `task_id`: Task ID | ||
#### `updatePullRequestTask` | ||
Updates a task on a pull request. | ||
**Parameters:** | ||
- `workspace`: Bitbucket workspace name | ||
- `repo_slug`: Repository slug | ||
- `pull_request_id`: Pull request ID | ||
- `task_id`: Task ID | ||
- `content` (optional): Updated task content | ||
- `state` (optional): Updated task state | ||
#### `deletePullRequestTask` | ||
Deletes a task on a pull request. | ||
**Parameters:** | ||
- `workspace`: Bitbucket workspace name | ||
- `repo_slug`: Repository slug | ||
- `pull_request_id`: Pull request ID | ||
- `task_id`: Task ID | ||
### Other Pull Request Operations | ||
#### `getPullRequestCommits` | ||
Lists commits on a pull request. | ||
**Parameters:** | ||
- `workspace`: Bitbucket workspace name | ||
- `repo_slug`: Repository slug | ||
- `pull_request_id`: Pull request ID | ||
#### `getPullRequestStatuses` | ||
Lists commit statuses for a pull request. | ||
**Parameters:** | ||
- `workspace`: Bitbucket workspace name | ||
- `repo_slug`: Repository slug | ||
- `pull_request_id`: Pull request ID | ||
## Development | ||
### Project Structure | ||
### Prerequisites | ||
``` | ||
bitbucket-mcp/ | ||
├── src/ | ||
│ ├── api/ # API-related code | ||
│ ├── services/ # Service implementations | ||
│ ├── types/ # TypeScript type definitions | ||
│ ├── utils/ # Utility functions | ||
│ └── index.ts # Entry point | ||
├── package.json | ||
└── tsconfig.json | ||
``` | ||
- Node.js 18 or higher | ||
- npm or yarn | ||
### Adding New Tools | ||
### Setup | ||
To add a new tool, modify the `src/index.ts` file and add your tool definition: | ||
```bash | ||
# Clone the repository | ||
git clone https://github.com/MatanYemini/bitbucket-mcp.git | ||
cd bitbucket-mcp | ||
```typescript | ||
const newTool = server.tool( | ||
"newToolName", | ||
{ | ||
param1: z.string(), | ||
param2: z.number().optional(), | ||
}, | ||
async ({ param1, param2 }) => { | ||
// Implementation goes here | ||
return { | ||
content: [{ type: "text", text: "Result" }], | ||
}; | ||
} | ||
); | ||
# Install dependencies | ||
npm install | ||
# Build the project | ||
npm run build | ||
# Run in development mode | ||
npm run dev | ||
``` | ||
@@ -117,1 +498,8 @@ | ||
This project is licensed under the MIT License - see the [LICENSE](LICENSE) file for details. | ||
## Links | ||
- [GitHub Repository](https://github.com/MatanYemini/bitbucket-mcp) | ||
- [npm Package](https://www.npmjs.com/package/bitbucket-mcp) | ||
- [Model Context Protocol](https://modelcontextprotocol.io/) | ||
- [Bitbucket REST API - Pull Requests](https://developer.atlassian.com/cloud/bitbucket/rest/api-group-pullrequests/) |
Sorry, the diff of this file is not supported yet
Major refactor
Supply chain riskPackage has recently undergone a major refactor. It may be unstable or indicate significant internal changes. Use caution when updating to versions that include significant changes.
Found 1 instance in 1 package
Environment variable access
Supply chain riskPackage accesses environment variables, which may be a sign of credential stuffing or data theft.
Found 2 instances in 1 package
No bug tracker
MaintenancePackage does not have a linked bug tracker in package.json.
Found 1 instance in 1 package
No website
QualityPackage does not have a website.
Found 1 instance in 1 package
102319
179.73%1247
125.09%0
-100%0
-100%504
334.48%6
-33.33%6
-60%1
Infinity%