Bitbucket MCP Server (Python)
<!-- mcp-name: io.github.lawp09/bitbucket-mcp -->Connect Claude Code, OpenAI Codex, Cursor, VS Code (GitHub Copilot), and any MCP-compatible AI assistant to your Bitbucket Cloud repositories. Review pull requests, monitor pipelines, and manage your code — all through natural language.
Features
- 60+ MCP tools — repositories, pull requests, comments, tasks, diffs, pipelines (runtime + config), build statuses, reviewers, draft PRs, batch review, issue tracker, commits, source/file browsing
- MCP 2025 tool annotations — every tool advertises
readOnlyHint/destructiveHint/idempotentHint/openWorldHint+ a human-readable title, so clients (Claude Code, Cursor) auto-include read-only tools and warn before destructive operations - Slim responses — stripped API noise for lower LLM token usage
- Configurable — enable/disable tools via
configs/tools.jsonorBITBUCKET_TOOLS_CONFIGenv var - Secure credentials — environment variables or system keychain
Quick Start
1. Install
The recommended way to run the server is via uvx (zero install, isolated environment):
# Always latest version
uvx --from bitbucket-mcp-py bitbucket-mcp
# Pin a specific version
uvx --from bitbucket-mcp-py==1.8.1 bitbucket-mcp
<details> <summary>Alternative install methods</summary>Why
--from? The PyPI package isbitbucket-mcp-pybut the command entry point isbitbucket-mcp. The--fromflag tells uvx which package to install.
| Mode | Command | Best for |
|---|---|---|
| pip global | pip install bitbucket-mcp-py | Simple, persistent install |
| Local dev | pip install -e . in project dir | Contributing to the project |
| Docker | See Docker section | Container-based workflows |
2. Configure credentials
Set the following environment variables (or use a .env file — see Credentials):
| Variable | Description |
|---|---|
BITBUCKET_USERNAME | Your Bitbucket email |
BITBUCKET_TOKEN | Your Bitbucket API token |
BITBUCKET_WORKSPACE | Your workspace slug |
Get your API token at: https://id.atlassian.com/manage-profile/security/api-tokens
⚠️ Use a scoped token, not a global one. When creating the token, select specific scopes (e.g.
Repositories: Read,Pull requests: Read/Write). Global tokens without explicit scopes do not work with this MCP server.
3. Configure your AI assistant
Claude Code (recommended)
Option A — CLI (fastest):
claude mcp add bitbucket-mcp \
-e BITBUCKET_USERNAME=your-email@example.com \
-e BITBUCKET_TOKEN=your-api-token \
-e BITBUCKET_WORKSPACE=your-workspace \
-- uvx --from bitbucket-mcp-py bitbucket-mcp
Option B — JSON config (~/.claude.json or project .mcp.json):
{
"mcpServers": {
"bitbucket-mcp": {
"type": "stdio",
"command": "uvx",
"args": ["--from", "bitbucket-mcp-py", "bitbucket-mcp"],
"env": {
"BITBUCKET_USERNAME": "your-email@example.com",
"BITBUCKET_TOKEN": "your-api-token",
"BITBUCKET_WORKSPACE": "your-workspace"
}
}
}
}
OpenAI Codex
Option A — CLI (fastest):
codex mcp add bitbucket-mcp \
--env BITBUCKET_USERNAME=your-email@example.com \
--env BITBUCKET_TOKEN=your-api-token \
--env BITBUCKET_WORKSPACE=your-workspace \
-- uvx --from bitbucket-mcp-py bitbucket-mcp
Option B — TOML config (~/.codex/config.toml):
[mcp_servers.bitbucket-mcp]
command = "uvx"
args = ["--from", "bitbucket-mcp-py", "bitbucket-mcp"]
env = { BITBUCKET_USERNAME = "your-email@example.com", BITBUCKET_TOKEN = "your-api-token", BITBUCKET_WORKSPACE = "your-workspace" }
Cursor
Add to ~/.cursor/mcp.json:
{
"mcpServers": {
"bitbucket-mcp": {
"command": "uvx",
"args": ["--from", "bitbucket-mcp-py", "bitbucket-mcp"],
"env": {
"BITBUCKET_USERNAME": "your-email@example.com",
"BITBUCKET_TOKEN": "your-api-token",
"BITBUCKET_WORKSPACE": "your-workspace"
}
}
}
}
VS Code (GitHub Copilot)
Add to .vscode/mcp.json (workspace) or ~/Library/Application Support/Code/User/mcp.json (global, macOS):
{
"servers": {
"bitbucket-mcp": {
"type": "stdio",
"command": "uvx",
"args": ["--from", "bitbucket-mcp-py", "bitbucket-mcp"],
"env": {
"BITBUCKET_USERNAME": "your-email@example.com",
"BITBUCKET_TOKEN": "your-api-token",
"BITBUCKET_WORKSPACE": "your-workspace"
}
}
}
}
Available Tools
| Category | Tools |
|---|---|
| Repositories | list_repositories, get_repository, get_repository_tags |
| Pull Requests | get_pull_requests, get_pull_request, create_pull_request, update_pull_request, approve_pull_request, unapprove_pull_request, request_changes_pull_request, unrequest_changes_pull_request, decline_pull_request, merge_pull_request |
| Comments | get_pull_request_comments, add_pull_request_comment, get_pull_request_comment, update_pull_request_comment, delete_pull_request_comment, resolve_pull_request_comment, reopen_pull_request_comment, get_pull_request_activity |
| Tasks PR | get_pull_request_tasks, get_pull_request_task, create_pull_request_task, update_pull_request_task, delete_pull_request_task |
| Diff / Review | get_pull_request_diff, get_pull_request_patch, get_pull_request_diffstat, get_pull_request_commits |
| PR Discovery | get_pull_requests_pending_review |
| Build / CI | get_pull_request_statuses, get_commit_statuses |
| Pipelines | list_pipeline_runs, get_pipeline_run, get_pipeline_steps, get_pipeline_step_logs, run_pipeline, stop_pipeline |
| Pipelines Config | get_pipeline_config, list_pipeline_variables, get_pipeline_variable, create_pipeline_variable, update_pipeline_variable, delete_pipeline_variable, list_pipeline_schedules, get_pipeline_schedule, list_pipeline_schedule_executions, create_pipeline_schedule, update_pipeline_schedule, delete_pipeline_schedule, list_pipeline_caches, delete_pipeline_cache |
| Reviewers | get_effective_default_reviewers, suggest_pull_request_reviewers |
| Draft PR | create_draft_pull_request, publish_draft_pull_request, convert_pull_request_to_draft |
| Batch Review | submit_pull_request_batch_review |
| Review Summary | get_pull_request_review_summary |
| Issues | list_issues, get_issue, create_issue, update_issue, delete_issue, get_issue_comments, get_issue_comment, add_issue_comment, update_issue_comment, delete_issue_comment |
| Commits | list_commits, get_commit, get_commit_comments, get_commit_comment, add_commit_comment |
| Source | get_file_content, list_directory |
| Deployments | list_environments, get_environment, create_environment, delete_environment, list_deployments, get_deployment, list_deployment_variables, create_deployment_variable, update_deployment_variable, delete_deployment_variable |
| Branch Restrictions | list_branch_restrictions, get_branch_restriction, create_branch_restriction, update_branch_restriction, delete_branch_restriction |
| Workspace | list_workspace_members, get_workspace_member, list_workspace_permissions, list_repository_permissions |
Disabled by default:
merge_pull_request(safety),stop_pipeline(safety),get_pull_request_patch(git am format — not useful for AI review),convert_pull_request_to_draft(not supported by Bitbucket API),delete_issue(safety),delete_issue_comment(safety),add_commit_comment(write op),create_pipeline_variable/update_pipeline_variable/delete_pipeline_variable(write ops),create_pipeline_schedule/update_pipeline_schedule/delete_pipeline_schedule(write ops),delete_pipeline_cache(safety),create_environment/delete_environment/create_deployment_variable/update_deployment_variable/delete_deployment_variable(write ops),create_branch_restriction/update_branch_restriction/delete_branch_restriction(write ops). Enable inconfigs/tools.json.
Governance scopes — Branch restriction read tools need the
repositoryscope (repository:adminmay be required depending on repo config); the write tools needrepository:admin. Workspace member/permission tools need theaccountscope. The/membersendpoint lists users without a per-user permission (uselist_workspace_permissionsfor roles).
Deployments scopes — the read tools (
list_environments,get_environment,list_deployments,get_deployment,list_deployment_variables) need thedeploymentscope; the write tools needdeployment:write. Bitbucket has no server-side filter for deployments by environment (BCLOUD-18729) — filter on theenvironmentfield oflist_deploymentsinstead. There is noupdate_environmenttool: Bitbucket exposes noPUTfor environments (onlyPOST .../changesfor locking).
Custom tool configuration
By default the server reads configs/tools.json bundled with the package. You can point to a custom file at runtime without rebuilding:
export BITBUCKET_TOOLS_CONFIG=/path/to/my-tools.json
Fallback chain (first match wins):
BITBUCKET_TOOLS_CONFIGenvironment variable- Built-in
configs/tools.json
Fail-safe behaviour — If
BITBUCKET_TOOLS_CONFIGis set but the file is missing or contains invalid JSON, the server raises an error on startup (explicit failure rather than silently ignoring the override). If the built-in default is missing, all tools are enabled.
Token tip —
get_pull_request_diffaccepts an optionalpathparameter to filter the diff to a single file, reducing token usage by ~95% on large PRs:get_pull_request_diff(repo_slug, pull_request_id, path="src/services/myService.ts")
MCP Prompts
The server also exposes MCP Prompts — parameterised templates that compatible clients (Claude Code, Cursor, ...) surface as slash commands. Instead of remembering tool names, you invoke a prompt and the assistant orchestrates the right tools for you. They appear in the client's prompt picker (prompts/list).
| Prompt | Arguments | What it does |
|---|---|---|
review_pull_request | repo_slug, pull_request_id | Full AI review: metadata → diffstat → diff → comments → tasks, then Summary / Risk / Quality / Security / Recommendation |
debug_pipeline_failure | repo_slug, pipeline_uuid | Diagnose a failed pipeline: run → steps → failed-step logs, then Root cause / Failed step / Error / Fix |
summarize_repository | repo_slug | Repo overview: info → recent commits → open PRs → CI → issues, then Purpose / Activity / Health / Contributors |
onboard_reviewer | repo_slug, pull_request_id | Help a new reviewer: PR context → commits → diff → review history, then Context / Changes / Review-so-far / Focus |
Prompts are enabled/disabled in configs/tools.json under the top-level prompts key (separate from tools).
Credentials
Option 1: .env file (recommended)
cp .env.example .env
# Edit .env with your credentials
Option 2: System keychain (most secure)
pip install 'bitbucket-mcp-py[keyring]'
python3 -c "import keyring; keyring.set_password('bitbucket-mcp', 'bitbucket_token', 'YOUR_TOKEN')"
Docker (Alternative)
If you prefer running the server in a container:
docker build -t bitbucket-mcp-py .
docker run -d --name bitbucket-mcp --env-file .env bitbucket-mcp-py
Then configure your AI assistant to use docker exec:
{
"mcpServers": {
"bitbucket-mcp": {
"command": "docker",
"args": ["exec", "-i", "bitbucket-mcp", "python", "-m", "src.main", "--transport", "stdio"]
}
}
}
Transports
The server speaks stdio by default (the standard transport for local MCP clients). For a network deployment it also supports Streamable HTTP (MCP spec 2025-03-26):
# Streamable HTTP on 0.0.0.0:8080
python -m src.main --transport http --host 0.0.0.0 --port 8080
Clients connect to
http://<host>:<port>/mcp(e.g.http://localhost:8080/mcp).
--transport sse(legacy Server-Sent Events) is still accepted but deprecated — it emits aDeprecationWarning. Prefer--transport http.
Development
# Install dev dependencies
uv sync --extra dev
# Run tests
uv run pytest tests/ -v
# Run specific test
uv run pytest tests/test_client.py -v
Requirements
- Python 3.12+
- Bitbucket API token
License
MIT
References
- MCP Registry — Official MCP server registry
- PyPI Package — Python package
- MCP Python SDK
- Bitbucket API 2.0
- FastMCP Framework