Document RUN_WRITE_TESTS and TEST_PR_ID env vars across all three files. Fix .env.template to keep write-test vars commented out. Reference .env.template as the starting point for local development setup. Co-Authored-By: Claude Sonnet 4.6 (1M context) <noreply@anthropic.com>
311 lines
11 KiB
Markdown
311 lines
11 KiB
Markdown
<div align="center">
|
|
|
|
# Bitbucket MCP Server
|
|
|
|
**A Model Context Protocol server for AI agents to interact with Bitbucket Cloud Pull Requests**
|
|
|
|
[](https://nodejs.org/)
|
|
[](https://www.typescriptlang.org/)
|
|
[](https://modelcontextprotocol.io/)
|
|
[](LICENSE)
|
|
|
|
</div>
|
|
|
|
---
|
|
|
|
## 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](https://id.atlassian.com/manage-profile/security/api-tokens) with **repository read** permissions (note: App Passwords are no longer supported by Bitbucket)
|
|
|
|
### 2. Install & Build
|
|
|
|
```bash
|
|
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):
|
|
|
|
```json
|
|
{
|
|
"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):
|
|
|
|
```json
|
|
{
|
|
"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-mcp` with the actual absolute path where you cloned the repo.
|
|
> - `DEFAULT_WORKSPACE` and `DEFAULT_REPO` are optional but convenient — they let you omit those parameters from every tool call.
|
|
> - Get your API token from [Atlassian API Tokens](https://id.atlassian.com/manage-profile/security/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 `page` and `pagelen` parameters.
|
|
|
|
---
|
|
|
|
## Example
|
|
|
|
```json
|
|
{
|
|
"name": "list_pull_requests",
|
|
"arguments": {
|
|
"workspace": "my-team",
|
|
"repository": "backend-api",
|
|
"state": "open"
|
|
}
|
|
}
|
|
```
|
|
|
|
Response:
|
|
|
|
```json
|
|
{
|
|
"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:
|
|
|
|
```env
|
|
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
|
|
```
|
|
|
|
```bash
|
|
# Run with hot reload
|
|
npm run dev
|
|
|
|
# Or run directly
|
|
npm start
|
|
```
|
|
|
|
### Testing
|
|
|
|
```bash
|
|
# 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](https://id.atlassian.com/manage-profile/security/api-tokens)
|
|
|
|
> **Note:** Bitbucket no longer supports App Passwords. You must use an API Token instead.
|
|
|
|
Credential resolution order:
|
|
1. Environment variables (`BITBUCKET_MCP_EMAIL` + `BITBUCKET_MCP_TOKEN`)
|
|
2. `.env` file in project root
|
|
3. Interactive prompt (development only)
|
|
|
|
---
|
|
|
|
## License
|
|
|
|
[MIT](LICENSE)
|