A complete command-line interface and Model Context Protocol (MCP) server written in Go that provides programmatic integration with Bitbucket Cloud workspaces and repositories.
- Dual mode — Use as an interactive CLI for daily work, or launch as an MCP server (
bbkt mcp) for AI agents (Claude Desktop, Cursor, etc.). - Git-aware — Most commands auto-detect the current workspace and repo from
.git/config, sobbkt prs listJust Works inside a Bitbucket repo. - Multi-profile — Switch between personal and work Atlassian accounts with
--profileorBBKT_PROFILE; auto-selects the right profile based on your git config email. - Two auth modes — Atlassian API tokens (Basic auth) or interactive OAuth 2.0 with automatic token refresh.
- Scope-aware MCP — At startup the MCP server introspects your token's granted scopes and silently hides tools the token can't use, preventing the AI from hallucinating successful writes it doesn't have permission for.
- Read and write — Repositories, workspaces, pipelines, issues, pull requests, comments, and source code (read/write/delete) — all via the API.
Installs the latest release binary for your OS/arch from GitHub Releases.
# System-wide (uses sudo if /usr/local/bin isn't writable)
curl -sSL https://raw.githubusercontent.com/zach-snell/bbkt/main/install.sh | bash
# User-local, no sudo (~/.local/bin)
curl -sSL https://raw.githubusercontent.com/zach-snell/bbkt/main/install.sh | bash -s -- --userFish users on --user: run fish_add_path ~/.local/bin once if it isn't already on $PATH.
Download a prebuilt binary for your OS/arch directly from the Releases page (Linux/macOS/Windows, amd64 + arm64).
git clone https://github.com/zach-snell/bbkt.git
cd bbkt
go build -o bbkt ./cmd/bbktRequires Go 1.26+.
# 1. Authenticate (interactive — prompts for email + Atlassian API token)
bbkt auth
# 2. Verify
bbkt status
# 3. Use it. Inside a Bitbucket repo, workspace/repo are inferred from git.
bbkt prs list
bbkt pipelines trigger --ref-name main
bbkt source read README.mdFor OAuth instead of an API token:
export BITBUCKET_OAUTH_CLIENT_ID=<consumer-key>
export BITBUCKET_OAUTH_CLIENT_SECRET=<consumer-secret>
bbkt auth --oauthbbkt stores credentials at ~/.config/bbkt/credentials.json and supports multiple profiles.
bbkt auth # save to "default" profile
bbkt auth --profile work # save to a named profileImportant: Bitbucket Cloud REST API requires scoped API tokens since the September 2025 phase-2 of app-password deprecation. At id.atlassian.com/manage-profile/security/api-tokens, use the "Create API token with scopes" button — not plain "Create API token". Unscoped tokens authenticate to Atlassian but Bitbucket rejects them; bbkt will detect this and point you here.
Recommended scope set for full read/write:
read:account
read:user:bitbucket read:workspace:bitbucket
read:repository:bitbucket write:repository:bitbucket
read:pullrequest:bitbucket write:pullrequest:bitbucket
read:pipeline:bitbucket write:pipeline:bitbucket
Register an OAuth consumer in your Bitbucket workspace settings, then:
export BITBUCKET_OAUTH_CLIENT_ID=<consumer-key>
export BITBUCKET_OAUTH_CLIENT_SECRET=<consumer-secret>
bbkt auth --oauthbbkt opens a browser, captures the callback on http://localhost:8976, exchanges the code for tokens, and stores them. Access tokens auto-refresh on expiry. To override the callback port (must match your registered redirect_uri):
export BBKT_OAUTH_CALLBACK_PORT=9876bbkt profile # list profiles, mark active
bbkt profile use work # set active profile
bbkt profile refresh # refresh cached workspace list per profile
BBKT_PROFILE=work bbkt prs list # one-shot profile overrideWhen BBKT_PROFILE is unset, bbkt tries to auto-select a profile whose accessible workspaces match your git config email; otherwise it falls back to active_profile.
Setting any of these env vars bypasses the stored profile entirely:
# API token
export BITBUCKET_USERNAME=you@example.com # despite the name, this is your Atlassian email
export BITBUCKET_API_TOKEN=ATATT3xFf...
# OAuth bearer
export BITBUCKET_ACCESS_TOKEN=<oauth-access-token>Global flags (all commands): --json raw JSON output, --profile <name> profile override.
# Auth & profiles
bbkt auth [--oauth] [--profile <name>] # set up credentials
bbkt status # show active profile + token health
bbkt logout # remove stored credentials
bbkt profile [use <name> | refresh] # manage profiles
# Workspaces / repos
bbkt workspaces [list | get <workspace>]
bbkt repos [list | get | create | delete]
[--query <q>] [--role <owner|admin|contributor|member>]
# Pull requests (workspace/repo inferred from git)
bbkt prs list # --state OPEN|MERGED|SUPERSEDED|DECLINED
bbkt prs get <pr-id>
bbkt prs create --title <t> --source <branch> [--destination <branch>]
bbkt prs merge <pr-id> [--strategy merge_commit|squash|fast_forward]
bbkt prs approve <pr-id>
bbkt prs decline <pr-id>
bbkt prs comments [list | add | resolve] # --content, --parent, --file, --to, --from
# Pipelines
bbkt pipelines list # --status SUCCESSFUL|FAILED|INPROGRESS
bbkt pipelines get <pipeline-uuid>
bbkt pipelines trigger --ref-name <branch> [--ref-type branch|tag|bookmark]
bbkt pipelines stop <pipeline-uuid>
bbkt pipelines steps <pipeline-uuid>
bbkt pipelines log <pipeline-uuid> <step-uuid>
# Issues
bbkt issues [list | get | create | update]
[--state] [--kind bug|enhancement|proposal|task] [--priority ...]
# Source code
bbkt source read <path> [--ref <ref>]
bbkt source tree [<path>] [--max-depth <n>]
bbkt source search <query>
bbkt source history <path>
bbkt source write <path> --content <text> [--message <m>] [--branch <b>]
bbkt source delete <path> [--message <m>]Most commands prompt interactively (via huh) when required arguments are missing. Run bbkt <command> --help for full flag details.
bbkt mcp launches a Model Context Protocol server for AI agents. Two transports:
Add to your MCP client config:
{
"mcpServers": {
"bitbucket": {
"command": "/absolute/path/to/bbkt",
"args": ["mcp"]
}
}
}By default the server reads credentials from ~/.config/bbkt/credentials.json (the profile set up via bbkt auth). To override per-client:
{
"mcpServers": {
"bitbucket": {
"command": "/absolute/path/to/bbkt",
"args": ["mcp"],
"env": {
"BBKT_PROFILE": "work"
}
}
}
}bbkt mcp --port 8080This serves the MCP Streamable Transport (SSE-based) on the given port.
The MCP server calls Bitbucket's /user endpoint at startup to introspect your token's granted scopes, then silently drops any tool whose required scope is missing. This prevents the AI from confidently calling, say, manage_pipelines (pipeline scope) on a read-only token and getting a 403 it can't recover from.
To explicitly deny tools even when scopes allow them:
export BITBUCKET_DISABLED_TOOLS="manage_repositories,manage_pipelines"To skip credential loading entirely (tools will return auth-required errors when invoked — useful for testing the transport):
bbkt mcp --no-auth| Variable | Purpose | Required |
|---|---|---|
BITBUCKET_USERNAME |
Atlassian email (despite the legacy name) — used with BITBUCKET_API_TOKEN |
Only for env-var API-token auth |
BITBUCKET_API_TOKEN |
Atlassian scoped API token | Only for env-var API-token auth |
BITBUCKET_ACCESS_TOKEN |
OAuth 2.0 bearer token (overrides stored profile) | Only for env-var OAuth |
BITBUCKET_OAUTH_CLIENT_ID |
OAuth consumer Key | Only for bbkt auth --oauth |
BITBUCKET_OAUTH_CLIENT_SECRET |
OAuth consumer Secret | Only for bbkt auth --oauth |
BBKT_PROFILE |
Profile name override (one-shot) | No |
BBKT_OAUTH_CALLBACK_PORT |
Local callback port for OAuth flow (default 8976) | No |
BITBUCKET_DISABLED_TOOLS |
Comma-separated MCP tools to disable | No |
When BITBUCKET_ACCESS_TOKEN or (BITBUCKET_USERNAME + BITBUCKET_API_TOKEN) is set, the stored profile is bypassed entirely.
| Tool | Operations | Required Scope |
|---|---|---|
manage_workspaces |
list, get | — |
manage_repositories |
list, get, create, delete | repository |
manage_refs |
list, create, delete branches and tags | repository |
manage_commits |
list, get, diff, diffstat | repository |
manage_source |
read, list_directory, get_history, search, write, delete | repository |
manage_pull_requests |
list, get, create, update, merge, approve, unapprove, decline, diff, diffstat, commits | pullrequest |
manage_pr_comments |
list, create, update, delete, resolve, unresolve | pullrequest |
manage_pipelines |
list, get, trigger, stop, list-steps, get-step-log | pipeline |
manage_issues |
list, get, create, update | issue |
Scopes shown are the OAuth-style names. For Atlassian API tokens, the equivalent granular scopes are read:<scope>:bitbucket / write:<scope>:bitbucket.
Requires Go 1.26+.
go test ./... # unit tests
go test -tags=live ./... # live integration tests (requires BBKT_LIVE_* secrets)
golangci-lint run ./...The repo also has a docs site (Astro) under docs/ deployed to https://zach-snell.github.io/bbkt/.
Apache 2.0 — see LICENSE.
