The `/workspaces` API endpoint was updated to `/user/workspaces` to correctly retrieve workspaces for the authenticated user. Configuration guidance for `DEFAULT_WORKSPACE` and `DEFAULT_REPO` in documentation and templates now explicitly references deriving these values from the Bitbucket repository URL, simplifying initial setup.
Bitbucket MCP Server
A Model Context Protocol server for AI agents to interact with Bitbucket Cloud Pull Requests
Overview
This MCP server exposes Bitbucket Cloud operations as tools that AI agents (Claude, etc.) can invoke over stdio. It connects your AI workflow directly to your Bitbucket repositories — covering everything from read-only PR inspection to full write operations.
Capabilities
| Category | Operations |
|---|---|
| Workspaces & Repos | List workspaces, list/get repositories, list branches |
| Pull Requests (read) | List, get details, get full expanded PR, status |
| Pull Requests (write) | Create, update, merge, decline |
| Code Review | Diff, patch, file changes, commits |
| Collaboration | Comments (read/add/edit/delete), activities, participants, reviewers |
| Review Workflow | Approve, unapprove, request changes, remove request-changes |
| Tasks | Get tasks, task count, create/update/delete tasks |
| Auth | Token validation |
Quick Start
Get up and running in 4 steps:
1. Prerequisites
- Node.js 24.13+ (see
.nvmrc) - A Bitbucket Cloud API Token with repository read permissions (note: App Passwords are no longer supported by Bitbucket)
2. Install & Build
git clone <repository-url>
cd bitbucket-mcp
npm install
npm run build
3. Configure in Claude
Add the MCP server to your Claude configuration:
Claude Code — edit ~/.claude.json (global) or .claude/settings.json (per-project):
{
"mcpServers": {
"bitbucket": {
"command": "node",
"args": ["/absolute/path/to/bitbucket-mcp/dist/index.js"],
"env": {
"BITBUCKET_MCP_EMAIL": "your_email@example.com",
"BITBUCKET_MCP_TOKEN": "your_api_token",
"DEFAULT_WORKSPACE": "your-workspace",
"DEFAULT_REPO": "your-repo"
}
}
}
}
Claude Desktop — edit ~/Library/Application Support/Claude/claude_desktop_config.json (macOS) or %APPDATA%\Claude\claude_desktop_config.json (Windows):
{
"mcpServers": {
"bitbucket": {
"command": "node",
"args": ["/absolute/path/to/bitbucket-mcp/dist/index.js"],
"env": {
"BITBUCKET_MCP_EMAIL": "your_email@example.com",
"BITBUCKET_MCP_TOKEN": "your_api_token",
"DEFAULT_WORKSPACE": "your-workspace",
"DEFAULT_REPO": "your-repo"
}
}
}
}
Important:
- Replace
/absolute/path/to/bitbucket-mcpwith the actual absolute path where you cloned the repo.DEFAULT_WORKSPACEandDEFAULT_REPOare optional but convenient — they let you omit those parameters from every tool call.- Read them directly from your Bitbucket repo URL:
https://bitbucket.org/{workspace}/{repository}/pull-requestsFor example,https://bitbucket.org/my-workspace/my-repo/pull-requests→DEFAULT_WORKSPACE=my-workspace,DEFAULT_REPO=my-repo- Get your API token from Atlassian API Tokens.
4. Verify
Restart Claude (or reload MCP servers), then ask Claude to run the validate_token tool. If credentials are correct, it will confirm the connection is working.
Available Tools
Authentication
| Tool | Description |
|---|---|
validate_token |
Verify credentials are valid |
Workspaces & Repositories
| Tool | Description | Key Parameters |
|---|---|---|
list_workspaces |
List all workspaces the authenticated user belongs to | page?, pagelen? |
list_repositories |
List repositories in a workspace | workspace, role?, page?, pagelen? |
get_repository |
Get metadata for a specific repository | workspace, repository |
list_branches |
List branches in a repository | workspace, repository, filter_by_name?, page?, pagelen? |
Pull Request Discovery
| Tool | Description | Key Parameters |
|---|---|---|
list_pull_requests |
List PRs in a repository | workspace, repository, state?, author? |
get_pull_request |
Get PR summary | workspace, repository, pullRequestId |
get_full_pull_request |
Get PR with all fields expanded | workspace, repository, pullRequestId |
get_pull_request_status |
Get PR state (open/merged/declined) | workspace, repository, pullRequestId |
Pull Request Write Operations
| Tool | Description | Key Parameters |
|---|---|---|
create_pull_request |
Create a new pull request | workspace, repository, title, source_branch, destination_branch, description?, reviewers?, close_source_branch? |
update_pull_request |
Update title, description, reviewers, or destination branch | workspace, repository, pullRequestId, title?, description?, reviewers?, destination_branch? |
merge_pull_request |
Merge an open pull request | workspace, repository, pullRequestId, merge_strategy?, commit_message?, close_source_branch? |
decline_pull_request |
Decline (close) an open pull request | workspace, repository, pullRequestId |
Review Workflow
| Tool | Description | Key Parameters |
|---|---|---|
approve_pull_request |
Approve a pull request | workspace, repository, pullRequestId |
unapprove_pull_request |
Remove your approval | workspace, repository, pullRequestId |
request_changes_pull_request |
Request changes on a pull request | workspace, repository, pullRequestId |
remove_request_changes_pull_request |
Remove a request-changes vote | workspace, repository, pullRequestId |
Code Changes
| Tool | Description | Key Parameters |
|---|---|---|
get_pull_request_diff |
Get unified diff | workspace, repository, pullRequestId, path?, context? |
get_pull_request_patch |
Get raw patch file | workspace, repository, pullRequestId |
get_pull_request_changes |
List modified files | workspace, repository, pullRequestId |
get_pull_request_commits |
List commits in PR | workspace, repository, pullRequestId |
Comments
| Tool | Description | Key Parameters |
|---|---|---|
get_pull_request_comments |
Get all comments | workspace, repository, pullRequestId |
get_pull_request_comment |
Get a specific comment | workspace, repository, pullRequestId, commentId |
add_pull_request_comment |
Add a general or inline comment | workspace, repository, pullRequestId, content, inline_path?, inline_line?, parent_comment_id? |
update_pull_request_comment |
Edit an existing comment | workspace, repository, pullRequestId, commentId, content |
delete_pull_request_comment |
Delete a comment | workspace, repository, pullRequestId, commentId |
Activities & Participants
| Tool | Description | Key Parameters |
|---|---|---|
get_pull_request_activities |
Get activity feed | workspace, repository, pullRequestId |
get_pull_request_participants |
Get all participants | workspace, repository, pullRequestId |
get_pull_request_reviewers |
Get assigned reviewers | workspace, repository, pullRequestId |
Tasks
| Tool | Description | Key Parameters |
|---|---|---|
get_pull_request_tasks |
Get PR tasks | workspace, repository, pullRequestId |
get_pull_request_task_count |
Get task count | workspace, repository, pullRequestId |
create_pull_request_task |
Create a review task | workspace, repository, pullRequestId, content, comment_id? |
update_pull_request_task |
Update or resolve/unresolve a task | workspace, repository, pullRequestId, taskId, content?, state? |
delete_pull_request_task |
Delete a task | workspace, repository, pullRequestId, taskId |
Pagination: Tools that return lists support
pageandpagelenparameters.
Example
{
"name": "list_pull_requests",
"arguments": {
"workspace": "my-team",
"repository": "backend-api",
"state": "open"
}
}
Response:
{
"pull_requests": [
{
"id": 42,
"title": "feat: add user authentication",
"state": "OPEN",
"author": { "display_name": "Jane Doe" },
"source": { "branch": { "name": "feature/auth" } },
"destination": { "branch": { "name": "main" } }
}
],
"count": 1
}
Development
Running Locally
For development, you can use a .env file instead of configuring credentials in the MCP client. Copy .env.template to .env and fill in your values:
BITBUCKET_MCP_EMAIL=your_email@example.com
BITBUCKET_MCP_TOKEN=your_api_token
DEFAULT_WORKSPACE=my-workspace
DEFAULT_REPO=my-repo
# Only needed when running write integration tests (see Testing below)
# RUN_WRITE_TESTS=true
# TEST_PR_ID=123
# Run with hot reload
npm run dev
# Or run directly
npm start
Testing
# Run all tests (unit only by default)
npm test
# Run tests in watch mode
npm run test:watch
# Integration tests — read-only, requires valid credentials in .env
npm run test:integration
# Type check
npx tsc --noEmit
# Coverage report
npm run test:coverage
Write operation tests (approve/unapprove, comments, tasks) are disabled by default and require two additional variables in your .env:
| Variable | Description |
|---|---|
RUN_WRITE_TESTS=true |
Opt in to running write tests |
TEST_PR_ID=<id> |
ID of a PR you own and can safely modify |
TEST_PR_ID is mandatory — write tests will never fall back to a random PR from the repository. If it is not set, each write test is skipped with a warning. This prevents accidental modifications to PRs you don't intend to touch.
Project Structure
src/
├── index.ts # MCP server & tool schema definitions
├── router.ts # Tool name → API method dispatcher
├── bitbucket-client.ts # Axios HTTP client for Bitbucket Cloud API
└── config.ts # Credential & default config loading
tests/
├── unit/ # Mocked unit tests
└── integration/ # Live API tests
Authentication Details
This server uses HTTP Basic Authentication with the Bitbucket Cloud REST API v2.0:
- Username = your Bitbucket email
- Password = an API Token
Note: Bitbucket no longer supports App Passwords. You must use an API Token instead.
Credential resolution order:
- Environment variables (
BITBUCKET_MCP_EMAIL+BITBUCKET_MCP_TOKEN) .envfile in project root- Interactive prompt (development only)