Bitbucket Data Center / Server
First-class integration with self-hosted enterprise Bitbucket โ see and act on pull requests, branches, builds, and repository administration from inside C3.
Overview
C3 ships with c3_bitbucket โ a single MCP tool that lets Claude Code (and the human, via the Hub UI) read and act on a self-hosted Bitbucket Data Center / Server instance. There is no separate browser context-switch: PRs, diffs, builds, branches, comments, approvals, and merges are all accessible inside the C3 workflow.
Scope: Bitbucket Data Center / Server only (the on-prem enterprise product, REST API /rest/api/1.0, Bearer-token auth via Personal Access Tokens). Bitbucket Cloud (bitbucket.org) is not currently supported โ its API path, auth model, and pagination differ.
What you get
| Surface | Where | Use it for |
|---|---|---|
c3_bitbucket MCP tool |
Claude Code | Action-dispatched Bitbucket operations from inside an AI session |
c3 bitbucket CLI |
Terminal | One-time login, account switching, default-repo pinning |
| Bitbucket tab | Hub UI (per-project) | Visual PR / branch / activity / admin browsing |
/api/bitbucket/* |
Project server | REST endpoints proxying to the Bitbucket REST client |
Quick start
Three commands to wire up an enterprise Bitbucket server and pin a working repo.
Log in
c3 bitbucket login \
--url https://bitbucket.example.com
Prompts for username and Personal Access Token (PAT). The PAT goes straight into the OS keyring; .c3/config.json only records the username + URL pair.
Pin defaults
c3 bitbucket set-default \
--project PROJ \
--repo my-service
Lets c3_bitbucket calls skip project= and repo= arguments โ the configured defaults are used automatically.
Verify
c3 bitbucket status
Lists active account + accounts list, runs an application-properties probe to confirm the PAT works.
First call from Claude Code
# Whoami
c3_bitbucket(action='whoami')
# Open PRs in the pinned repo
c3_bitbucket(action='list_prs', state='OPEN')
# Detail of a specific PR
c3_bitbucket(action='get_pr', pr_id=42)
Authentication & security
Personal Access Tokens
C3 uses Bitbucket Data Center Personal Access Tokens (Bearer auth). Generate one in your Bitbucket profile under Manage account โ Personal access tokens. Choose a permission level matching what you intend to do:
| Permission | What c3_bitbucket can do |
|---|---|
REPO_READ | Browse projects, repos, PRs, diffs, branches, builds, activity |
REPO_WRITE | + Create / comment / approve / decline / merge PRs ยท create / delete branches |
REPO_ADMIN | + Update repo settings ยท webhooks ยท permissions |
PROJECT_* | Equivalent permissions but scoped to a whole project key |
Where the token lives
| OS keyring | Token text, under service c3-bitbucket, account {base_url}|{username}. Backed by Windows Credential Manager, macOS Keychain, or Linux Secret Service. |
.c3/config.json |
Non-secret bitbucket section: list of known accounts, active-account pointer, default project + repo, TLS-verify flag. Never contains the token. |
Why both? The OS keyring has no portable list API on every backend, so C3 also keeps a non-secret accounts index in .c3/config.json. This makes c3 bitbucket status able to show all configured accounts without prompting the keyring per-entry. Tokens themselves only flow through the keyring.
TLS verification
Default: verify_tls = true. To disable verification for self-signed enterprise CAs, pass --insecure on c3 bitbucket login, or flip bitbucket.verify_tls to false in .c3/config.json.
Use with care. Disabling TLS verification means a network-positioned attacker could steal your PAT. Only set it when the server certificate is signed by an internal CA you trust, and prefer importing the CA into the system trust store.
Multiple servers / accounts
save_credentials appends each (base_url, username) pair to the accounts index. Switch with c3 bitbucket use --url ... --username .... The active account is what every c3_bitbucket call resolves to.
Action reference
The MCP tool dispatches by action. Twenty-seven actions are grouped below by capability. Project + repo default from bitbucket.default_project / default_repo when not provided.
Read & discovery
| Action | Args | Description |
|---|---|---|
status | โ | Active account, accounts list, defaults, server-version probe. Works without a valid token (returns connection: FAIL in that case) |
whoami | โ | Authenticated user (PAT owner) |
list_projects | name? | All projects visible to the PAT, optionally filtered by name |
list_repos | project | Repos under a project key |
get_repo | project, repo | Repo metadata โ name, scmId, public flag, clone URLs |
list_prs | project, repo, state?, author?, reviewer?, limit? | Pull requests โ default state=OPEN; supports MERGED, DECLINED, ALL |
get_pr | project, repo, pr_id | Full PR detail incl. version, reviewers, description, open-tasks |
get_pr_diff | project, repo, pr_id, context_lines? | Unified diff (truncated to 6000 chars in the response) |
get_pr_activities | project, repo, pr_id | PR event timeline (comments, approvals, reviewer changes) |
list_branches | project, repo, filter? | Branches with ahead/behind counts and default-branch flag |
list_commits | project, repo, branch?, path?, limit? | Commit log on a branch / path |
list_activity | project, repo, limit? | Repo activity feed (commit-based) |
build_status | commit? | CI build statuses for a commit. If commit is omitted, the default branch's HEAD is used. |
Pull-request writes
| Action | Args | Description |
|---|---|---|
create_pr | title, from_branch, to_branch, description?, reviewers? | Open a new PR. reviewers may be a list or comma-separated string. |
comment_pr | pr_id, body | Add a top-level comment |
approve_pr | pr_id | Mark the PR approved as the current user |
unapprove_pr | pr_id | Withdraw approval |
decline_pr | pr_id | Decline the PR. Auto-fetches the current PR version first. |
merge_pr | pr_id, message? | Merge the PR. Auto-fetches the current PR version first; logs to the C3 edit ledger. |
Branch writes
| Action | Args | Description |
|---|---|---|
create_branch | name, start_point, message? | Create a branch from a ref. Goes through the /rest/branch-utils/1.0 API. |
delete_branch | name, dry_run? | Delete a branch. Logs to the edit ledger. |
Repository administration
| Action | Args | Description |
|---|---|---|
repo_settings | project, repo | Read repo settings (currently the same as get_repo) |
update_repo_settings | project, repo, settings | PUT updated settings JSON to the repo. settings may be a dict or JSON string. |
list_webhooks | project, repo | All webhooks on the repo |
create_webhook | name, url, events, active?, secret? | Create a webhook. events is a list or comma-separated string (e.g. repo:refs_changed,pr:opened). |
delete_webhook | webhook_id | Remove a webhook |
list_permissions | project, repo | User and group permission grants on the repo |
Argument fall-back. Any action in the table whose row says it needs project, repo will fall back to bitbucket.default_project and bitbucket.default_repo from .c3/config.json when the call omits them. Use c3 bitbucket set-default to pin them.
CLI commands
Five subcommands cover account lifecycle and repo defaults. Run any with --help for full flags.
| Command | Description |
|---|---|
c3 bitbucket login --url <URL> [--username <U>] [--token <T>] [--insecure] | Interactive PAT prompt (getpass masked). Writes to keyring, appends to accounts index, sets active. Runs a connection probe. |
c3 bitbucket logout [--url <URL>] [--username <U>] | Removes from keyring and accounts index. Falls back to the active account when args are omitted. |
c3 bitbucket status | Lists accounts, marks the active one, runs an application-properties probe. |
c3 bitbucket use --url <URL> --username <U> | Switch active account (no token re-entry needed if the keyring already has it). |
c3 bitbucket set-default --project <K> --repo <R> | Pin the project key + repo slug used by c3_bitbucket calls when args are omitted. |
Hub UI tab
The per-project Hub UI gains a Bitbucket tab in its sidebar (between Edits and Instructions). Five sub-views:
| Sub-view | Shows |
|---|---|
| Overview | Active account ยท default project + repo ยท server version & connection state ยท all configured accounts |
| Pull Requests | State filter (OPEN / MERGED / DECLINED / ALL) ยท PR list with state badge ยท click-through detail JSON |
| Branches | Branch list with latest commit hash and default-branch marker |
| Activity | Recent commit feed |
| Admin | Webhooks (id, active, name โ URL, events) ยท user / group permission grants |
Endpoints powering the tab live in cli/server.py under /api/bitbucket/*. The Hub server (port 3330) does not host these โ Bitbucket is per-project, so the API runs inside each project's session-server (default port 3333).
Audit trail โ Edit ledger integration
State changes that happen on the platform side (not in your local working tree) are still appended to the C3 edit ledger so the audit trail is complete. The path for these entries is virtual:
bitbucket://<project>/<repo>
The following actions log to the ledger when they succeed:
| Action | Why it's logged |
|---|---|
create_pr | New PR opened โ relevant for review timeline |
comment_pr | Discussion contribution worth recovering on / clear |
approve_pr / unapprove_pr | Reviewer state changes |
decline_pr | PR closed without merge |
merge_pr | Code now lives in the target branch โ high-impact |
create_branch / delete_branch | Branch topology changed |
update_repo_settings | Repo-level config drift |
create_webhook / delete_webhook | Integration footprint changed |
Read-only actions and the status probe are not logged. Token text is stripped from logged kwargs before persisting.
.c3/config.json โ bitbucket section
Default shape (gets created on first c3 bitbucket login):
{
"bitbucket": {
"active": { "base_url": "https://bitbucket.example.com", "username": "alice" },
"accounts": [
{ "base_url": "https://bitbucket.example.com", "username": "alice" }
],
"default_project": "PROJ",
"default_repo": "my-service",
"verify_tls": true
}
}
active | Pointer to the account whose token will be loaded for every c3_bitbucket call. |
accounts | Non-secret index of all known (base_url, username) pairs. |
default_project | Project key used when an action call omits project=. |
default_repo | Repo slug used when an action call omits repo=. |
verify_tls | Set to false for self-signed enterprise certificates. Prefer fixing the trust chain at the OS level instead. |
.c3/ is gitignored by default. Even so, never write a token under this section by hand. The keyring is the authoritative store; this file is just the index.
Example workflows
Review and merge a PR
# 1. See what's open
c3_bitbucket(action='list_prs', state='OPEN')
# 2. Drill into one
c3_bitbucket(action='get_pr', pr_id=42)
c3_bitbucket(action='get_pr_diff', pr_id=42)
# 3. Comment with review notes
c3_bitbucket(action='comment_pr', pr_id=42,
body='LGTM modulo the test in test_x.py:42')
# 4. Approve, then merge โ version is fetched automatically
c3_bitbucket(action='approve_pr', pr_id=42)
c3_bitbucket(action='merge_pr', pr_id=42,
message='Merge feat/bitbucket โ release v2.30.0')
Open a PR for the current branch
# Push the branch first via c3_shell (auto-logs to ledger)
c3_shell(cmd='git push -u origin feat/bitbucket')
# Then open the PR
c3_bitbucket(action='create_pr',
title='feat: Bitbucket Data Center integration (v2.30.0)',
from_branch='feat/bitbucket',
to_branch='main',
description='See CHANGELOG [2.30.0] for details.',
reviewers='alice,bob')
Cut a feature branch via the API
c3_bitbucket(action='create_branch',
name='feat/oauth-fix',
start_point='refs/heads/main')
Check CI status before merging
# Latest commit on the PR's source branch
pr = c3_bitbucket(action='get_pr', pr_id=42)
# (in agent code) โ fromRef.latestCommit
c3_bitbucket(action='build_status', commit='<sha>')
Inventory webhooks before changing CI
c3_bitbucket(action='list_webhooks')
c3_bitbucket(action='create_webhook',
name='jenkins',
url='https://ci.example.com/hooks/bitbucket',
events='repo:refs_changed,pr:opened,pr:merged',
active=true,
secret='shared-with-jenkins')
Troubleshooting
| Symptom | Cause & fix |
|---|---|
[bitbucket:no-account] |
Active account isn't set in .c3/config.json. Run c3 bitbucket login --url <URL> or c3 bitbucket use --url ... --username ... if the token is already stored. |
[bitbucket:no-token] |
Account is in the index but the keyring entry is missing (e.g. .c3/ was copied to a different machine). Re-run c3 bitbucket login --url ... --username ... to put the PAT back into the keyring. |
| HTTP 401 on a fresh PAT | The PAT was issued for a different Bitbucket server, or the project / repo permission isn't on the token. Generate a new token with at least REPO_READ. |
| HTTP 403 on PR write | The token has REPO_READ but the action needs REPO_WRITE. Re-issue with the right level. |
HTTP 409 on merge_pr / decline_pr |
PR version is stale (somebody else updated it). The handler auto-fetches the current version on each call, so simply retrying the same MCP action usually succeeds. |
SSL: CERTIFICATE_VERIFY_FAILED |
Self-signed enterprise CA. Either import the CA into the OS trust store (preferred), or set bitbucket.verify_tls = false in .c3/config.json. |
| Connection probe times out | Server is reachable from the browser but blocked at the OS firewall (e.g. corporate proxy). Set HTTPS_PROXY in your environment โ urllib picks it up automatically. |
The 'keyring' package is required |
pip install keyring โ added as a dependency in v2.30.0 but missing if you upgraded without re-installing. |
Where to look
- Activity log: Hub UI โ Bitbucket tab โ Overview, plus
.c3/activity_log.jsonlfor raw events taggedbitbucket_action. - Edit ledger:
c3_edits(action='history', file='bitbucket://<project>/<repo>')for all platform-side mutations. - Tool calls:
c3_session(action='log')entries record everyc3_bitbucketdispatch with action name and (sanitized) args.
Need to add an action this surface doesn't cover? File an issue or pull request โ the integration is intentionally thin around the Bitbucket REST 1.0 API in services/bitbucket_client.py.