A Model Context Protocol (MCP) server for Atlassian Bitbucket Server (Stash), distributed as a Docker image on Docker Hub. It gives AI assistants access to your repositories, pull requests, code reviews, builds, and search — through 41 purpose-built tools.
41 tools covering comprehensive Bitbucket Server workflows:
| Category | Tools | Highlights |
|---|---|---|
| Projects | 1 | Discover projects |
| Dashboard | 5 | User-centric PR views + server info |
| Repositories | 3 | Repos, overview, file content |
| Git | 3 | Branches, tags, file listing |
| Search | 4 | Code, commits, PRs, users |
| History | 5 | List/inspect commits, compare refs, full commit context |
| Pull Requests | 8 | List/get/context/diff + create/update/merge + approve |
| Comments | 4 | Read, write, reply with code context |
| Tasks | 4 | Full CRUD for review tasks |
| Builds | 3 | CI/CD status per commit/PR/repo |
| Integrations | 1 | Jira issue links |
These tools reduce multiple API calls to a single invocation:
get_pull_request_context— Complete PR with comments, tasks, diff, activityget_repository_overview— Branches, tags, and open PRs in one callget_commit_context— Commit details with changes and diff
- Circuit Breaker — Prevents cascading failures when Bitbucket is unavailable
- Retry with Backoff — Automatic retry for transient errors (429, 502, 503, 504)
- Graceful Degradation — Returns cached data when the API fails
- Response Truncation — 50 KB limit prevents context overflow
- Cache Invalidation — Write operations automatically refresh related caches
- Docker Desktop installed
- A Bitbucket Server (self-hosted) instance
- A Personal Access Token with repository read/write permissions
Add the following to your VS Code MCP configuration file
(Command Palette → MCP: Open user configuration):
{
"servers": {
"stash-bitbucket": {
"command": "docker",
"args": [
"run", "-i", "--rm",
"-e", "BITBUCKET_URL",
"-e", "BITBUCKET_TOKEN",
"diomonogatari/stash-mcp:latest"
],
"env": {
"BITBUCKET_URL": "https://your-stash-server.com/",
"BITBUCKET_TOKEN": "your_personal_access_token"
},
"type": "stdio"
}
}
}That's it. VS Code will pull the image on first use and start the server automatically.
Tip — pin to a specific tag instead of
latest(e.g.diomonogatari/stash-mcp:1.1.0) to avoid running a stale local image when a new version is published. Docker skips the pull when a local image already has thelatesttag. If you must uselatest, force a pull withdocker run --pull=always ... diomonogatari/stash-mcp:latest.
Open Settings → Developer → Edit Config (or edit claude_desktop_config.json
directly) and add the server under the mcpServers key:
{
"mcpServers": {
"stash-bitbucket": {
"command": "docker",
"args": [
"run", "-i", "--rm",
"-e", "BITBUCKET_URL",
"-e", "BITBUCKET_TOKEN",
"diomonogatari/stash-mcp:latest"
],
"env": {
"BITBUCKET_URL": "https://your-stash-server.com/",
"BITBUCKET_TOKEN": "your_personal_access_token"
}
}
}
}Config file location:
| OS | Path |
|---|---|
| macOS | ~/Library/Application Support/Claude/claude_desktop_config.json |
| Windows | %APPDATA%\Claude\claude_desktop_config.json |
| Linux | ~/.config/Claude/claude_desktop_config.json |
Quit and relaunch Claude Desktop after saving. The Bitbucket tools appear under the tools (slider) icon. Docker Desktop must be running.
Note: Claude Desktop uses the
mcpServerskey (and no"type"field), whereas the VS Code example above uses theserverskey. Thecommandandargsare identical.
claude mcp add stash-bitbucket \
--transport stdio \
--env BITBUCKET_URL=https://your-stash-server.com/ \
--env BITBUCKET_TOKEN=your_personal_access_token \
-- docker run -i --rm -e BITBUCKET_URL -e BITBUCKET_TOKEN diomonogatari/stash-mcp:latestThis registers the server at local scope (current project, just you). Use
--scope user to make it available across all your projects, or --scope project
to commit it to a shared .mcp.json. Verify with claude mcp list or the /mcp
command inside a session (it should report stash-bitbucket connected with 41
tools), and remove it with claude mcp remove stash-bitbucket.
Pass additional environment variables to tune resilience and caching behaviour:
{
"servers": {
"stash-bitbucket": {
"command": "docker",
"args": [
"run", "-i", "--rm",
"-e", "BITBUCKET_URL",
"-e", "BITBUCKET_TOKEN",
"-e", "BITBUCKET_RETRY_COUNT",
"-e", "BITBUCKET_CIRCUIT_TIMEOUT",
"-e", "BITBUCKET_CACHE_TTL_SECONDS",
"-e", "BITBUCKET_READ_ONLY_MODE",
"-e", "BITBUCKET_PROJECTS",
"diomonogatari/stash-mcp:latest"
],
"env": {
"BITBUCKET_URL": "https://your-stash-server.com/",
"BITBUCKET_TOKEN": "your_personal_access_token",
"BITBUCKET_RETRY_COUNT": "5",
"BITBUCKET_CIRCUIT_TIMEOUT": "60",
"BITBUCKET_CACHE_TTL_SECONDS": "120",
"BITBUCKET_READ_ONLY_MODE": "false",
"BITBUCKET_PROJECTS": "PROJ,TEAM"
},
"type": "stdio"
}
}
}| Setting | Environment Variable | Default | Description |
|---|---|---|---|
| Server URL | BITBUCKET_URL |
— | Bitbucket Server base URL (required) |
| Access Token | BITBUCKET_TOKEN |
— | Personal Access Token (required) |
| Retry Count | BITBUCKET_RETRY_COUNT |
3 | Max retry attempts (0–10) |
| Circuit Timeout | BITBUCKET_CIRCUIT_TIMEOUT |
30 | Circuit breaker duration in seconds (5–300) |
| Cache TTL | BITBUCKET_CACHE_TTL_SECONDS |
60 | Cache time-to-live in seconds (10–600) |
| Read-Only Mode | BITBUCKET_READ_ONLY_MODE |
false | Disable write operations (true or 1) |
| Projects | BITBUCKET_PROJECTS |
— | Comma-separated project keys to cache at startup (e.g. PROJ,TEAM). When omitted, derives scope from recent repositories. |
For detailed documentation of all 41 tools, see docs/TOOLSET.md.
1. get_pull_request_context (with includeComments=true, includeDiff=true)
2. Review the diff and existing comments
3. add_pull_request_comment (for feedback)
4. create_pull_request_task (for required changes)
5. approve_pull_request (when satisfied)
1. search_commits (messageContains="JIRA-123")
2. get_commit_context (includeDiff=true)
3. search_code (to find current implementation)
1. get_repository_overview (quick overview)
2. list_files (browse structure)
3. get_file_content (read specific files)
For list operations, use minimalOutput=true to reduce response size:
list_repositories— Returns repository slugs onlylist_branches— Returns branch names onlylist_pull_requests— Returns compact PR summary
-
Clone the repository with submodules:
git clone --recurse-submodules https://github.com/diomonogatari/stash-mcp.git
If you already cloned without submodules:
git submodule update --init --recursive
-
Install the .NET 10.0 SDK
# Build the solution
dotnet build stash-mcp.slnx
# Run tests
dotnet test stash-mcp.slnxdotnet run --project src/StashMcpServer/StashMcpServer.csproj -- \
--stash-url https://your-server.com/ --pat your_patThe double dash (
--) separatesdotnet runarguments from application arguments.
| Flag | Default | Description |
|---|---|---|
--stash-url |
BITBUCKET_URL env var |
Bitbucket Server base URL |
--pat |
BITBUCKET_TOKEN env var |
Personal Access Token |
--log-level |
Information |
Serilog log level: Verbose, Debug, Information, Warning, Error, Fatal |
docker build -t diomonogatari/stash-mcp:dev .
docker run -i --rm \
-e BITBUCKET_URL=https://your-stash-server.com/ \
-e BITBUCKET_TOKEN=your_personal_access_token \
diomonogatari/stash-mcp:devDocker skips the pull when the latest tag already exists locally.
Force a fresh pull:
docker pull diomonogatari/stash-mcp:latestOr pin to a specific version tag (e.g. diomonogatari/stash-mcp:1.1.0).
- Verify
BITBUCKET_URLincludes the trailing slash and protocol (https://your-server.com/) - Ensure the Docker container can reach your Bitbucket Server (check corporate VPN, proxy, or firewall rules)
- For Docker Desktop on macOS/Windows, use
host.docker.internalif Bitbucket runs on the host machine
- Verify the Personal Access Token has Repository Read (and Repository Write if you need write operations) permissions
- Check that the token has not expired
- Set
BITBUCKET_READ_ONLY_MODE=trueif only read access is needed
- Increase the log level to see what is happening:
--log-level Debug(CLI) or append--log-level Debugafter the image name in thedocker runcommand - Check that the
BITBUCKET_PROJECTSvariable (if set) contains valid project keys — invalid keys cause the startup cache to fail silently
┌──────────────────────────────────────────────────────────┐
│ MCP Server Layer │
│ ┌──────────────────────────────────────────────────┐ │
│ │ Domain Tool Classes (9 classes, 41 tools) │ │
│ │ ProjectTools RepositoryTools PullRequestTools │ │
│ │ SearchTools GitTools HistoryTools │ │
│ │ BuildTools DashboardTools IntegrationTools │ │
│ └──────────┬───────────────────────────────────────┘ │
│ │ inherits ToolBase (shared helpers) │
│ ┌──────────▼───────────────────────────────────────┐ │
│ │ Formatting │ DiffFormatter ResponseTruncation │ │
│ │ │ MinimalOutputFormatter (50KB limit)│ │
│ └──────────┬───────────────────────────────────────┘ │
│ │ │
│ ┌──────────▼───────────────────────────────────────┐ │
│ │ ResilientApiService │ │
│ │ • Circuit Breaker (Polly) │ │
│ │ • Retry with Exponential Backoff │ │
│ │ • Graceful Degradation (stale cache) │ │
│ │ • Cache Invalidation on Writes │ │
│ └──────────┬───────────────────────────────────────┘ │
│ │ │
│ ┌──────────▼──────┐ ┌──────────────────────────────┐ │
│ │ Cache Layer │ │ IMemoryCache (TTL=60s) │ │
│ │ (Static) │ │ ConcurrentDict (projects) │ │
│ └──────────┬──────┘ └──────────────────────────────┘ │
│ │ │
│ Transport: stdio │
└─────────────┼────────────────────────────────────────────┘
│
▼
Bitbucket Server API (via Bitbucket.Net submodule)
For detailed architecture documentation, see docs/ARCHITECTURE.md.
Never commit your Personal Access Token to source control.
- Use environment variables (as shown in the configuration examples above)
- Restrict PAT permissions to the minimum required scopes
- Use secure credential storage where available
- Architecture — System design and folder structure
- Tool Reference — Detailed documentation for all 41 tools
- Local Bitbucket — Run a real Bitbucket Server in Docker for end-to-end testing
- Contributing — Development setup and pull request guidelines
- Security — Vulnerability reporting and credential safety
- Changelog — Version history and release notes
See LICENSE for details.