pdogra1299/bitbucket-mcp-server
If you are the rightful owner of bitbucket-mcp-server and would like to certify it and/or have it hosted online, please leave a comment on the right or send an email to henry@mcphub.com.
The Bitbucket MCP Server is a Model Context Protocol server designed to facilitate interactions with the Bitbucket API, supporting both Bitbucket Cloud and Bitbucket Server.
Bitbucket MCP Server
An MCP (Model Context Protocol) server that provides tools for interacting with the Bitbucket API, supporting both Bitbucket Cloud and Bitbucket Server.
Features
Currently Implemented Tools
Core PR Lifecycle Tools
get_pull_request
- Retrieve detailed information about a pull requestlist_pull_requests
- List pull requests with filters (state, author, pagination)create_pull_request
- Create new pull requestsupdate_pull_request
- Update PR details (title, description, reviewers, destination branch)add_comment
- Add comments to pull requests (supports replies)merge_pull_request
- Merge pull requests with various strategieslist_pr_commits
- List all commits that are part of a pull requestdelete_branch
- Delete branches after merge
Branch Management Tools
list_branches
- List branches with filtering and paginationdelete_branch
- Delete branches (with protection checks)get_branch
- Get detailed branch information including associated PRslist_branch_commits
- List commits in a branch with advanced filtering
File and Directory Tools
list_directory_content
- List files and directories in a repository pathget_file_content
- Get file content with smart truncation for large files
Code Review Tools
get_pull_request_diff
- Get the diff/changes for a pull requestapprove_pull_request
- Approve a pull requestunapprove_pull_request
- Remove approval from a pull requestrequest_changes
- Request changes on a pull requestremove_requested_changes
- Remove change request from a pull request
Installation
Using npx (Recommended)
The easiest way to use this MCP server is directly with npx:
{
"mcpServers": {
"bitbucket": {
"command": "npx",
"args": [
"-y",
"@nexus2520/bitbucket-mcp-server"
],
"env": {
"BITBUCKET_USERNAME": "your-username",
"BITBUCKET_APP_PASSWORD": "your-app-password"
}
}
}
}
For Bitbucket Server:
{
"mcpServers": {
"bitbucket": {
"command": "npx",
"args": [
"-y",
"@nexus2520/bitbucket-mcp-server"
],
"env": {
"BITBUCKET_USERNAME": "your.email@company.com",
"BITBUCKET_TOKEN": "your-http-access-token",
"BITBUCKET_BASE_URL": "https://bitbucket.yourcompany.com"
}
}
}
}
From Source
- Clone or download this repository
- Install dependencies:
npm install
- Build the TypeScript code:
npm run build
Authentication Setup
This server uses Bitbucket App Passwords for authentication.
Creating an App Password
- Log in to your Bitbucket account
- Navigate to: https://bitbucket.org/account/settings/app-passwords/
- Click "Create app password"
- Give it a descriptive label (e.g., "MCP Server")
- Select the following permissions:
- Account: Read
- Repositories: Read, Write
- Pull requests: Read, Write
- Click "Create"
- Important: Copy the generated password immediately (you won't be able to see it again!)
Running the Setup Script
node scripts/setup-auth.js
This will guide you through the authentication setup process.
Configuration
Add the server to your MCP settings file (usually located at ~/.vscode-server/data/User/globalStorage/saoudrizwan.claude-dev/settings/cline_mcp_settings.json
):
{
"mcpServers": {
"bitbucket": {
"command": "node",
"args": ["/absolute/path/to/bitbucket-mcp-server/build/index.js"],
"env": {
"BITBUCKET_USERNAME": "your-username",
"BITBUCKET_APP_PASSWORD": "your-app-password"
}
}
}
}
Replace:
/absolute/path/to/bitbucket-mcp-server
with the actual path to this directoryyour-username
with your Bitbucket username (not email)your-app-password
with the app password you created
For Bitbucket Server, use:
{
"mcpServers": {
"bitbucket": {
"command": "node",
"args": ["/absolute/path/to/bitbucket-mcp-server/build/index.js"],
"env": {
"BITBUCKET_USERNAME": "your.email@company.com",
"BITBUCKET_TOKEN": "your-http-access-token",
"BITBUCKET_BASE_URL": "https://bitbucket.yourcompany.com"
}
}
}
}
Important for Bitbucket Server users:
- Use your full email address as the username (e.g., "")
- This is required for approval/review actions to work correctly
Usage
Once configured, you can use the available tools:
Get Pull Request
{
"tool": "get_pull_request",
"arguments": {
"workspace": "PROJ", // Required - your project key
"repository": "my-repo",
"pull_request_id": 123
}
}
Returns detailed information about the pull request including:
- Title and description
- Author and reviewers
- Source and destination branches
- Approval status
- Links to web UI and diff
- Merge commit details (when PR is merged):
merge_commit_hash
: The hash of the merge commitmerged_by
: Who performed the mergemerged_at
: When the merge occurredmerge_commit_message
: The merge commit message
- Active comments with nested replies (unresolved comments that need attention):
active_comments
: Array of active comments (up to 20 most recent top-level comments)- Comment text and author
- Creation date
- Whether it's an inline comment (with file path and line number)
- Nested replies (for Bitbucket Server):
replies
: Array of reply comments with same structure- Replies can be nested multiple levels deep
- Parent reference (for Bitbucket Cloud):
parent_id
: ID of the parent comment for replies
active_comment_count
: Total count of unresolved comments (including nested replies)total_comment_count
: Total count of all comments (including resolved and replies)
- File changes:
file_changes
: Array of all files modified in the PR- File path
- Status (added, modified, removed, or renamed)
- Old path (for renamed files)
file_changes_summary
: Summary statistics- Total files changed
- And more...
List Pull Requests
{
"tool": "list_pull_requests",
"arguments": {
"workspace": "PROJ", // Required - your project key
"repository": "my-repo",
"state": "OPEN", // Optional: OPEN, MERGED, DECLINED, ALL (default: OPEN)
"author": "username", // Optional: filter by author (see note below)
"limit": 25, // Optional: max results per page (default: 25)
"start": 0 // Optional: pagination start index (default: 0)
}
}
Returns a paginated list of pull requests with:
- Array of pull requests with same details as get_pull_request
- Total count of matching PRs
- Pagination info (has_more, next_start)
Note on Author Filter:
- For Bitbucket Cloud: Use the username (e.g., "johndoe")
- For Bitbucket Server: Use the full email address (e.g., "")
Create Pull Request
{
"tool": "create_pull_request",
"arguments": {
"workspace": "PROJ",
"repository": "my-repo",
"title": "Add new feature",
"source_branch": "feature/new-feature",
"destination_branch": "main",
"description": "This PR adds a new feature...", // Optional
"reviewers": ["john.doe", "jane.smith"], // Optional
"close_source_branch": true // Optional (default: false)
}
}
Update Pull Request
{
"tool": "update_pull_request",
"arguments": {
"workspace": "PROJ",
"repository": "my-repo",
"pull_request_id": 123,
"title": "Updated title", // Optional
"description": "Updated description", // Optional
"destination_branch": "develop", // Optional
"reviewers": ["new.reviewer"] // Optional - see note below
}
}
Important Note on Reviewers:
- When updating a PR without specifying the
reviewers
parameter, existing reviewers and their approval status are preserved - When providing the
reviewers
parameter:- The reviewer list is replaced with the new list
- For reviewers that already exist on the PR, their approval status is preserved
- New reviewers are added without approval status
- This prevents accidentally removing reviewers when you only want to update the PR description or title
Add Comment
Add a comment to a pull request, either as a general comment or inline on specific code:
// General comment
{
"tool": "add_comment",
"arguments": {
"workspace": "PROJ",
"repository": "my-repo",
"pull_request_id": 123,
"comment_text": "Great work on this PR!"
}
}
// Inline comment on specific line
{
"tool": "add_comment",
"arguments": {
"workspace": "PROJ",
"repository": "my-repo",
"pull_request_id": 123,
"comment_text": "Consider extracting this into a separate function",
"file_path": "src/utils/helpers.js",
"line_number": 42,
"line_type": "CONTEXT" // ADDED, REMOVED, or CONTEXT
}
}
// Reply to existing comment
{
"tool": "add_comment",
"arguments": {
"workspace": "PROJ",
"repository": "my-repo",
"pull_request_id": 123,
"comment_text": "I agree with this suggestion",
"parent_comment_id": 456
}
}
// Add comment with code suggestion (single line)
{
"tool": "add_comment",
"arguments": {
"workspace": "PROJ",
"repository": "my-repo",
"pull_request_id": 123,
"comment_text": "This variable name could be more descriptive.",
"file_path": "src/utils/helpers.js",
"line_number": 42,
"line_type": "CONTEXT",
"suggestion": "const userAuthenticationToken = token;"
}
}
// Add comment with multi-line code suggestion
{
"tool": "add_comment",
"arguments": {
"workspace": "PROJ",
"repository": "my-repo",
"pull_request_id": 123,
"comment_text": "This function could be simplified using array methods.",
"file_path": "src/utils/calculations.js",
"line_number": 50,
"suggestion_end_line": 55,
"line_type": "CONTEXT",
"suggestion": "function calculateTotal(items) {\n return items.reduce((sum, item) => sum + item.price, 0);\n}"
}
}
The suggestion feature formats comments using GitHub-style markdown suggestion blocks that Bitbucket can render. When adding a suggestion:
suggestion
is required and contains the replacement codefile_path
andline_number
are required when using suggestionssuggestion_end_line
is optional and used for multi-line suggestions (defaults toline_number
)- The comment will be formatted with a ````suggestion` markdown block that may be applicable in the Bitbucket UI
Using Code Snippets Instead of Line Numbers
The add_comment
tool now supports finding line numbers automatically using code snippets. This is especially useful when AI tools analyze diffs and may struggle with exact line numbers:
// Add comment using code snippet
{
"tool": "add_comment",
"arguments": {
"workspace": "PROJ",
"repository": "my-repo",
"pull_request_id": 123,
"comment_text": "This variable name could be more descriptive",
"file_path": "src/components/Button.res",
"code_snippet": "let isDisabled = false",
"search_context": {
"before": ["let onClick = () => {"],
"after": ["setLoading(true)"]
}
}
}
// Handle multiple matches with strategy
{
"tool": "add_comment",
"arguments": {
"workspace": "PROJ",
"repository": "my-repo",
"pull_request_id": 123,
"comment_text": "Consider extracting this",
"file_path": "src/utils/helpers.js",
"code_snippet": "return result;",
"search_context": {
"before": ["const result = calculate();"],
"after": ["}"]
},
"match_strategy": "best" // Auto-select highest confidence match
}
}
Code Snippet Parameters:
code_snippet
: The exact code line to find (alternative toline_number
)search_context
: Optional context to disambiguate multiple matchesbefore
: Array of lines that should appear before the targetafter
: Array of lines that should appear after the target
match_strategy
: How to handle multiple matches"strict"
(default): Fail with error showing all matches"best"
: Auto-select the highest confidence match
Error Response for Multiple Matches (strict mode):
{
"error": {
"code": "MULTIPLE_MATCHES_FOUND",
"message": "Code snippet 'return result;' found in 3 locations",
"occurrences": [
{
"line_number": 42,
"file_path": "src/utils/helpers.js",
"preview": " const result = calculate();\n> return result;\n}",
"confidence": 0.9,
"line_type": "ADDED"
},
// ... more matches
],
"suggestion": "To resolve, either:\n1. Add more context...\n2. Use match_strategy: 'best'...\n3. Use line_number directly"
}
}
This feature is particularly useful for:
- AI-powered code review tools that analyze diffs
- Scripts that automatically add comments based on code patterns
- Avoiding line number confusion in large diffs
Note on comment replies:
- Use
parent_comment_id
to reply to any comment (general or inline) - In
get_pull_request
responses:- Bitbucket Server shows replies nested in a
replies
array - Bitbucket Cloud shows a
parent_id
field for reply comments
- Bitbucket Server shows replies nested in a
- You can reply to replies, creating nested conversations
Note on inline comments:
file_path
: The path to the file as shown in the diffline_number
: The line number as shown in the diffline_type
:ADDED
- For newly added lines (green in diff)REMOVED
- For deleted lines (red in diff)CONTEXT
- For unchanged context lines
Add Comment - Complete Usage Guide
The add_comment
tool supports multiple scenarios. Here's when and how to use each approach:
1. General PR Comments (No file/line)
- Use when: Making overall feedback about the PR
- Required params:
comment_text
only - Example: "LGTM!", "Please update the documentation"
2. Reply to Existing Comments
- Use when: Continuing a conversation thread
- Required params:
comment_text
,parent_comment_id
- Works for both general and inline comment replies
3. Inline Comments with Line Number
- Use when: You know the exact line number from the diff
- Required params:
comment_text
,file_path
,line_number
- Optional:
line_type
(defaults to CONTEXT)
4. Inline Comments with Code Snippet
- Use when: You have the code but not the line number (common for AI tools)
- Required params:
comment_text
,file_path
,code_snippet
- The tool will automatically find the line number
- Add
search_context
if the code appears multiple times - Use
match_strategy: "best"
to auto-select when multiple matches exist
5. Code Suggestions
- Use when: Proposing specific code changes
- Required params:
comment_text
,file_path
,line_number
,suggestion
- For multi-line: also add
suggestion_end_line
- Creates applicable suggestion blocks in Bitbucket UI
Decision Flow for AI/Automated Tools:
1. Do you want to suggest code changes?
→ Use suggestion with line_number
2. Do you have the exact line number?
→ Use line_number directly
3. Do you have the code snippet but not line number?
→ Use code_snippet (add search_context if needed)
4. Is it a general comment about the PR?
→ Use comment_text only
5. Are you replying to another comment?
→ Add parent_comment_id
Common Pitfalls to Avoid:
- Don't use both
line_number
andcode_snippet
- pick one - Suggestions always need
file_path
andline_number
- Code snippets must match exactly (including whitespace)
- REMOVED lines reference the source file, ADDED/CONTEXT reference the destination
Merge Pull Request
{
"tool": "merge_pull_request",
"arguments": {
"workspace": "PROJ",
"repository": "my-repo",
"pull_request_id": 123,
"merge_strategy": "squash", // Optional: merge-commit, squash, fast-forward
"close_source_branch": true, // Optional
"commit_message": "Custom merge message" // Optional
}
}
List Branches
{
"tool": "list_branches",
"arguments": {
"workspace": "PROJ",
"repository": "my-repo",
"filter": "feature", // Optional: filter by name pattern
"limit": 25, // Optional (default: 25)
"start": 0 // Optional: for pagination (default: 0)
}
}
Returns a paginated list of branches with:
- Branch name and ID
- Latest commit hash
- Default branch indicator
- Pagination info
Delete Branch
{
"tool": "delete_branch",
"arguments": {
"workspace": "PROJ",
"repository": "my-repo",
"branch_name": "feature/old-feature",
"force": false // Optional (default: false)
}
}
Note: Branch deletion requires appropriate permissions. The branch will be permanently deleted.
Get Branch
{
"tool": "get_branch",
"arguments": {
"workspace": "PROJ",
"repository": "my-repo",
"branch_name": "feature/new-feature",
"include_merged_prs": false // Optional (default: false)
}
}
Returns comprehensive branch information including:
- Branch details:
- Name and ID
- Latest commit (hash, message, author, date)
- Default branch indicator
- Open pull requests from this branch:
- PR title and ID
- Destination branch
- Author and reviewers
- Approval status (approved by, changes requested by, pending)
- PR URL
- Merged pull requests (if
include_merged_prs
is true):- PR title and ID
- Merge date and who merged it
- Statistics:
- Total open PRs count
- Total merged PRs count
- Days since last commit
This tool is particularly useful for:
- Checking if a branch has open PRs before deletion
- Getting an overview of branch activity
- Understanding PR review status
- Identifying stale branches
List Branch Commits
Get all commits in a specific branch with advanced filtering options:
// Basic usage - get recent commits
{
"tool": "list_branch_commits",
"arguments": {
"workspace": "PROJ",
"repository": "my-repo",
"branch_name": "feature/new-feature",
"limit": 50 // Optional (default: 25)
}
}
// Filter by date range
{
"tool": "list_branch_commits",
"arguments": {
"workspace": "PROJ",
"repository": "my-repo",
"branch_name": "main",
"since": "2025-01-01T00:00:00Z", // ISO date string
"until": "2025-01-15T23:59:59Z" // ISO date string
}
}
// Filter by author
{
"tool": "list_branch_commits",
"arguments": {
"workspace": "PROJ",
"repository": "my-repo",
"branch_name": "develop",
"author": "john.doe@company.com", // Email or username
"limit": 100
}
}
// Exclude merge commits
{
"tool": "list_branch_commits",
"arguments": {
"workspace": "PROJ",
"repository": "my-repo",
"branch_name": "release/v2.0",
"include_merge_commits": false
}
}
// Search in commit messages
{
"tool": "list_branch_commits",
"arguments": {
"workspace": "PROJ",
"repository": "my-repo",
"branch_name": "main",
"search": "bugfix", // Search in commit messages
"limit": 50
}
}
// Combine multiple filters
{
"tool": "list_branch_commits",
"arguments": {
"workspace": "PROJ",
"repository": "my-repo",
"branch_name": "develop",
"author": "jane.smith@company.com",
"since": "2025-01-01T00:00:00Z",
"include_merge_commits": false,
"search": "feature",
"limit": 100,
"start": 0 // For pagination
}
}
Filter Parameters:
since
: ISO date string - only show commits after this dateuntil
: ISO date string - only show commits before this dateauthor
: Filter by author email/usernameinclude_merge_commits
: Boolean to include/exclude merge commits (default: true)search
: Search for text in commit messages
Returns detailed commit information:
{
"branch_name": "feature/new-feature",
"branch_head": "abc123def456", // Latest commit hash
"commits": [
{
"hash": "abc123def456",
"abbreviated_hash": "abc123d",
"message": "Add new feature implementation",
"author": {
"name": "John Doe",
"email": "john.doe@example.com"
},
"date": "2025-01-03T10:30:00Z",
"parents": ["parent1hash", "parent2hash"],
"is_merge_commit": false
}
// ... more commits
],
"total_count": 150,
"start": 0,
"limit": 25,
"has_more": true,
"next_start": 25,
"filters_applied": {
"author": "john.doe@example.com",
"since": "2025-01-01",
"include_merge_commits": false
}
}
This tool is particularly useful for:
- Reviewing commit history before releases
- Finding commits by specific authors
- Tracking changes within date ranges
- Searching for specific features or fixes
- Analyzing branch activity patterns
List PR Commits
Get all commits that are part of a pull request:
{
"tool": "list_pr_commits",
"arguments": {
"workspace": "PROJ",
"repository": "my-repo",
"pull_request_id": 123,
"limit": 50, // Optional (default: 25)
"start": 0 // Optional: for pagination
}
}
Returns commit information for the PR:
{
"pull_request_id": 123,
"pull_request_title": "Add awesome feature",
"commits": [
{
"hash": "def456ghi789",
"abbreviated_hash": "def456g",
"message": "Initial implementation",
"author": {
"name": "Jane Smith",
"email": "jane.smith@example.com"
},
"date": "2025-01-02T14:20:00Z",
"parents": ["parent1hash"],
"is_merge_commit": false
}
// ... more commits
],
"total_count": 5,
"start": 0,
"limit": 25,
"has_more": false
}
This tool is particularly useful for:
- Reviewing all changes in a PR before merging
- Understanding the development history of a PR
- Checking commit messages for quality
- Verifying authorship of changes
- Analyzing PR complexity by commit count
Get Pull Request Diff
Get the diff/changes for a pull request with optional filtering capabilities:
// Get full diff (default behavior)
{
"tool": "get_pull_request_diff",
"arguments": {
"workspace": "PROJ",
"repository": "my-repo",
"pull_request_id": 123,
"context_lines": 5 // Optional (default: 3)
}
}
// Exclude specific file types
{
"tool": "get_pull_request_diff",
"arguments": {
"workspace": "PROJ",
"repository": "my-repo",
"pull_request_id": 123,
"exclude_patterns": ["*.lock", "*.svg", "node_modules/**", "*.min.js"]
}
}
// Include only specific file types
{
"tool": "get_pull_request_diff",
"arguments": {
"workspace": "PROJ",
"repository": "my-repo",
"pull_request_id": 123,
"include_patterns": ["*.res", "*.resi", "src/**/*.js"]
}
}
// Get diff for a specific file only
{
"tool": "get_pull_request_diff",
"arguments": {
"workspace": "PROJ",
"repository": "my-repo",
"pull_request_id": 123,
"file_path": "src/components/Button.res"
}
}
// Combine filters
{
"tool": "get_pull_request_diff",
"arguments": {
"workspace": "PROJ",
"repository": "my-repo",
"pull_request_id": 123,
"include_patterns": ["src/**/*"],
"exclude_patterns": ["*.test.js", "*.spec.js"]
}
}
Filtering Options:
include_patterns
: Array of glob patterns to include (whitelist)exclude_patterns
: Array of glob patterns to exclude (blacklist)file_path
: Get diff for a specific file only- Patterns support standard glob syntax (e.g.,
*.js
,src/**/*.res
,!test/**
)
Response includes filtering metadata:
{
"message": "Pull request diff retrieved successfully",
"pull_request_id": 123,
"diff": "..filtered diff content..",
"filter_metadata": {
"total_files": 15,
"included_files": 12,
"excluded_files": 3,
"excluded_file_list": ["package-lock.json", "logo.svg", "yarn.lock"],
"filters_applied": {
"exclude_patterns": ["*.lock", "*.svg"]
}
}
}
Approve Pull Request
{
"tool": "approve_pull_request",
"arguments": {
"workspace": "PROJ",
"repository": "my-repo",
"pull_request_id": 123
}
}
Request Changes
{
"tool": "request_changes",
"arguments": {
"workspace": "PROJ",
"repository": "my-repo",
"pull_request_id": 123,
"comment": "Please address the following issues..." // Optional
}
}
List Directory Content
{
"tool": "list_directory_content",
"arguments": {
"workspace": "PROJ",
"repository": "my-repo",
"path": "src/components", // Optional (defaults to root)
"branch": "main" // Optional (defaults to default branch)
}
}
Returns directory listing with:
- Path and branch information
- Array of contents with:
- Name
- Type (file or directory)
- Size (for files)
- Full path
- Total items count
Get File Content
{
"tool": "get_file_content",
"arguments": {
"workspace": "PROJ",
"repository": "my-repo",
"file_path": "src/index.ts",
"branch": "main", // Optional (defaults to default branch)
"start_line": 1, // Optional: starting line (1-based, use negative for from end)
"line_count": 100, // Optional: number of lines to return
"full_content": false // Optional: force full content (default: false)
}
}
Smart Truncation Features:
- Automatically truncates large files (>50KB) to prevent token overload
- Default line counts based on file type:
- Config files (.yml, .json): 200 lines
- Documentation (.md, .txt): 300 lines
- Code files (.ts, .js, .py): 500 lines
- Log files: Last 100 lines
- Use
start_line: -50
to get last 50 lines (tail functionality) - Files larger than 1MB require explicit
full_content: true
or line parameters
Returns file content with:
- File path and branch
- File size and encoding
- Content (full or truncated based on parameters)
- Line information (if truncated):
- Total lines in file
- Range of returned lines
- Truncation indicator
- Last modified information (commit, author, date)
Example responses:
// Small file - returns full content
{
"file_path": "package.json",
"branch": "main",
"size": 1234,
"encoding": "utf-8",
"content": "{\n \"name\": \"my-project\",\n ...",
"last_modified": {
"commit_id": "abc123",
"author": "John Doe",
"date": "2025-01-21T10:00:00Z"
}
}
// Large file - automatically truncated
{
"file_path": "src/components/LargeComponent.tsx",
"branch": "main",
"size": 125000,
"encoding": "utf-8",
"content": "... first 500 lines ...",
"line_info": {
"total_lines": 3500,
"returned_lines": {
"start": 1,
"end": 500
},
"truncated": true,
"message": "Showing lines 1-500 of 3500. File size: 122.1KB"
}
}
Development
npm run dev
- Watch mode for developmentnpm run build
- Build the TypeScript codenpm start
- Run the built server
Troubleshooting
- Authentication errors: Double-check your username and app password
- 404 errors: Verify the workspace, repository slug, and PR ID
- Permission errors: Ensure your app password has the required permissions
License
MIT