Files
bitbucket-mcp/docs/superpowers/specs/2026-05-20-bitbucket-mcp-features-design.md
Nicolas FRADIN 666fc05dd0 Add design spec for missing Bitbucket MCP features
Covers domain client split, write operations (PR, comment, task),
and repository/workspace/branch browsing tools.

Co-Authored-By: Claude Sonnet 4.6 (1M context) <noreply@anthropic.com>
2026-05-20 18:33:35 +02:00

9.5 KiB

Bitbucket MCP Server — Missing Features Design

Date: 2026-05-20
Status: Approved


Overview

Extend the existing read-only Bitbucket MCP server with:

  1. Repository/workspace browsing — list workspaces, repos, branches; get repo metadata
  2. PR write operations — create, update, merge, decline, approve, request-changes
  3. Comment write operations — add, update, delete comments (general and inline)
  4. Task write operations — create, update, delete PR tasks

The server's public contract (tool names, parameter shapes, ToolResult response envelope) remains unchanged; new tools are additive.


Architecture

The current monolithic bitbucket-client.ts is split into domain modules. A shared base-client.ts owns the Axios instance, initialization guard, error interceptors, and formatError. Domain clients extend or compose the base. BitbucketClient becomes a composition root that wires all domain clients together and exposes a flat API to the router.

src/
├── index.ts                      # MCP server — tool schemas added here
├── router.ts                     # Tool dispatcher — new switch cases added
├── config.ts                     # Unchanged
├── bitbucket-client.ts           # Composition root: instantiates & delegates to domain clients
└── clients/
    ├── base-client.ts            # Shared Axios instance, ensureInitialized, formatError, error interceptors
    ├── pull-request-client.ts    # All PR methods (read + write)
    ├── repository-client.ts      # Workspace, repo, branch methods
    └── comment-client.ts         # Comment + task CRUD

The router continues calling this.client.<method>() — the composition root makes this transparent.


Domain Clients

base-client.ts

Extracted from the current bitbucket-client.ts:

  • Holds the AxiosInstance
  • initializeClient(options) — loads config, creates axios, attaches interceptors
  • ensureInitialized() — polling guard used by all domain clients
  • handleResponseError(error) — 401/403/429 logging and rate-limit wait
  • formatError(error) — HTTP status + message formatter
  • sleep(ms) — utility

All domain clients receive a reference to the base client (or extend it) to share the axios instance and initialization state.

pull-request-client.ts

Existing read methods (migrated from current bitbucket-client.ts):

  • listPullRequests, getPullRequest, getPullRequestActivities
  • getPullRequestChanges, getPullRequestComments, getPullRequestComment
  • getPullRequestCommits, getPullRequestDiff, getPullRequestPatch
  • getPullRequestParticipants, getPullRequestReviewers, getPullRequestStatus
  • getPullRequestTasks, getPullRequestTaskCount, getFullPullRequest

New write methods:

Method HTTP Endpoint
createPullRequest(ws, repo, opts) POST /repositories/{ws}/{repo}/pullrequests
updatePullRequest(ws, repo, id, opts) PUT /repositories/{ws}/{repo}/pullrequests/{id}
mergePullRequest(ws, repo, id, opts) POST .../pullrequests/{id}/merge
declinePullRequest(ws, repo, id) POST .../pullrequests/{id}/decline
approvePullRequest(ws, repo, id) POST .../pullrequests/{id}/approve
unapprovePullRequest(ws, repo, id) DELETE .../pullrequests/{id}/approve
requestChangesPullRequest(ws, repo, id) POST .../pullrequests/{id}/request-changes
removeRequestChangesPullRequest(ws, repo, id) DELETE .../pullrequests/{id}/request-changes

createPullRequest options:

{
  title: string;
  source_branch: string;
  destination_branch: string;
  description?: string;
  reviewers?: string[];         // account UUIDs or usernames
  close_source_branch?: boolean;
}

mergePullRequest options:

{
  merge_strategy?: 'merge_commit' | 'squash' | 'fast_forward';
  commit_message?: string;
  close_source_branch?: boolean;
}

updatePullRequest options (all optional, at least one required):

{
  title?: string;
  description?: string;
  reviewers?: string[];
  destination_branch?: string;
}

repository-client.ts

New domain client — no existing methods to migrate.

Method HTTP Endpoint
listWorkspaces(opts) GET /workspaces
listRepositories(ws, opts) GET /repositories/{workspace}
getRepository(ws, repo) GET /repositories/{workspace}/{repo_slug}
listBranches(ws, repo, opts) GET /repositories/{ws}/{repo}/refs/branches

listWorkspaces options: page, pagelen
listRepositories options: role (member|contributor|owner), page, pagelen
listBranches options: page, pagelen, filter_by_name (maps to q=name~"<value>")

comment-client.ts

Existing read methods (migrated):

  • getPullRequestComments, getPullRequestComment

New write methods:

Method HTTP Endpoint
addPullRequestComment(ws, repo, id, opts) POST .../pullrequests/{id}/comments
updatePullRequestComment(ws, repo, id, commentId, opts) PUT .../comments/{commentId}
deletePullRequestComment(ws, repo, id, commentId) DELETE .../comments/{commentId}
createPullRequestTask(ws, repo, id, opts) POST .../pullrequests/{id}/tasks
updatePullRequestTask(ws, repo, id, taskId, opts) PUT .../tasks/{taskId}
deletePullRequestTask(ws, repo, id, taskId) DELETE .../tasks/{taskId}

addPullRequestComment options:

{
  content: string;
  inline?: { path: string; to: number };  // inline comment on file:line
  parent_id?: number;                      // reply to existing comment
}

updatePullRequestComment options:

{ content: string }

createPullRequestTask options:

{
  content: string;
  comment_id?: number;  // anchor to a specific comment
}

updatePullRequestTask options:

{
  content?: string;
  state?: 'RESOLVED' | 'UNRESOLVED';
}

New MCP Tools (index.ts)

Repository/Workspace

Tool name Required params Optional params
list_workspaces page, pagelen
list_repositories workspace role, page, pagelen
get_repository workspace, repository
list_branches workspace, repository filter_by_name, page, pagelen

PR Write

Tool name Required params Optional params
create_pull_request workspace, repository, title, source_branch, destination_branch description, reviewers, close_source_branch
update_pull_request workspace, repository, pullRequestId title, description, reviewers, destination_branch
merge_pull_request workspace, repository, pullRequestId merge_strategy, commit_message, close_source_branch
decline_pull_request workspace, repository, pullRequestId
approve_pull_request workspace, repository, pullRequestId
unapprove_pull_request workspace, repository, pullRequestId
request_changes_pull_request workspace, repository, pullRequestId
remove_request_changes_pull_request workspace, repository, pullRequestId

Comment Write

Tool name Required params Optional params
add_pull_request_comment workspace, repository, pullRequestId, content inline_path, inline_line, parent_comment_id
update_pull_request_comment workspace, repository, pullRequestId, commentId, content
delete_pull_request_comment workspace, repository, pullRequestId, commentId

Task Write

Tool name Required params Optional params
create_pull_request_task workspace, repository, pullRequestId, content comment_id
update_pull_request_task workspace, repository, pullRequestId, taskId content, state
delete_pull_request_task workspace, repository, pullRequestId, taskId

Router (router.ts)

New switch cases added to executeTool() for every new tool. Same pattern as existing cases:

  1. Extract workspace, repoSlug via getDefaultParams()
  2. Parse integer IDs
  3. Validate required params — return { success: false, error: '...' } if missing
  4. Delegate to this.client.<method>()
  5. Return { success: true, data: result }

No new helper is needed for write ops; the existing pattern is clear enough.


Error Handling

  • Write operations do not retry on failure.
  • base-client.ts error interceptor handles 401/403/429 (existing behavior preserved).
  • All domain client methods catch errors and re-throw with this.formatError(error).
  • Router catches and returns { success: false, error: '...' }.

Testing

Unit tests (tests/unit/router.test.ts):

  • New cases added for every new tool, mocking BitbucketClient identically to existing tests.

Integration tests (tests/integration/bitbucket-api.test.ts):

  • Read operations (workspaces, repos, branches) added unconditionally.
  • Write operations (merge, decline, approve, comment, task) gated on RUN_WRITE_TESTS=true env var to prevent accidental mutation of real PRs.

Out of Scope

  • Webhooks, pipelines, deployments, issue tracker, snippets.
  • Any Bitbucket Server (self-hosted) support — this server targets Bitbucket Cloud only.
  • Streaming / SSE responses.