Skip to main content
Glama
bobmaertz

Bitbucket MCP Server

by bobmaertz
pullrequests.ts7.06 kB
/** * Pull Request MCP Tools */ import type { Tool } from '@modelcontextprotocol/sdk/types.js'; import type { ToolContext } from '../server.js'; /** * Register pull request tools */ export function registerPullRequestTools(): Tool[] { return [ { name: 'bitbucket_list_pull_requests', description: 'List pull requests for a Bitbucket repository. Returns PR titles, IDs, states, authors, and descriptions.', inputSchema: { type: 'object', properties: { workspace: { type: 'string', description: 'Bitbucket workspace ID', }, repo_slug: { type: 'string', description: 'Repository slug', }, state: { type: 'string', enum: ['OPEN', 'MERGED', 'DECLINED', 'SUPERSEDED'], description: 'Filter by PR state (optional)', }, pagelen: { type: 'number', description: 'Number of items per page (default: 50)', }, }, required: ['workspace', 'repo_slug'], }, }, { name: 'bitbucket_get_pull_request', description: 'Get detailed information about a specific pull request including description, reviewers, participants, and status.', inputSchema: { type: 'object', properties: { workspace: { type: 'string', description: 'Bitbucket workspace ID', }, repo_slug: { type: 'string', description: 'Repository slug', }, pr_id: { type: 'number', description: 'Pull request ID', }, }, required: ['workspace', 'repo_slug', 'pr_id'], }, }, { name: 'bitbucket_get_pr_commits', description: 'Get the list of commits included in a pull request.', inputSchema: { type: 'object', properties: { workspace: { type: 'string', description: 'Bitbucket workspace ID', }, repo_slug: { type: 'string', description: 'Repository slug', }, pr_id: { type: 'number', description: 'Pull request ID', }, }, required: ['workspace', 'repo_slug', 'pr_id'], }, }, { name: 'bitbucket_get_pr_diff', description: 'Get the diff for a pull request showing all code changes.', inputSchema: { type: 'object', properties: { workspace: { type: 'string', description: 'Bitbucket workspace ID', }, repo_slug: { type: 'string', description: 'Repository slug', }, pr_id: { type: 'number', description: 'Pull request ID', }, }, required: ['workspace', 'repo_slug', 'pr_id'], }, }, ]; } /** * Handle list_pull_requests tool */ export async function handleListPullRequests(context: ToolContext, args: Record<string, unknown>) { const workspace = (args.workspace as string) || context.config.workspace; const repoSlug = (args.repo_slug as string) || context.config.defaultRepo; if (!repoSlug) { throw new Error('repo_slug is required'); } const state = args.state as 'OPEN' | 'MERGED' | 'DECLINED' | 'SUPERSEDED' | undefined; const pagelen = args.pagelen as number | undefined; const response = await context.bitbucket.pullRequests.list(workspace, repoSlug, { state, pagelen, }); const prList = response.values.map((pr) => ({ id: pr.id, title: pr.title, state: pr.state, author: pr.author.display_name, created_on: pr.created_on, updated_on: pr.updated_on, source_branch: pr.source.branch.name, destination_branch: pr.destination.branch.name, comment_count: pr.comment_count, task_count: pr.task_count, })); return { content: [ { type: 'text', text: JSON.stringify( { total: response.size, pull_requests: prList, }, null, 2 ), }, ], }; } /** * Handle get_pull_request tool */ export async function handleGetPullRequest(context: ToolContext, args: Record<string, unknown>) { const workspace = (args.workspace as string) || context.config.workspace; const repoSlug = (args.repo_slug as string) || context.config.defaultRepo; const prId = args.pr_id as number; if (!repoSlug) { throw new Error('repo_slug is required'); } if (!prId) { throw new Error('pr_id is required'); } const pr = await context.bitbucket.pullRequests.get(workspace, repoSlug, prId); const prDetails = { id: pr.id, title: pr.title, description: pr.description, state: pr.state, author: pr.author.display_name, created_on: pr.created_on, updated_on: pr.updated_on, source_branch: pr.source.branch.name, destination_branch: pr.destination.branch.name, comment_count: pr.comment_count, task_count: pr.task_count, reviewers: pr.reviewers.map((r) => r.display_name), participants: pr.participants.map((p) => ({ name: p.user.display_name, role: p.role, approved: p.approved, })), }; return { content: [ { type: 'text', text: JSON.stringify(prDetails, null, 2), }, ], }; } /** * Handle get_pr_commits tool */ export async function handleGetPRCommits(context: ToolContext, args: Record<string, unknown>) { const workspace = (args.workspace as string) || context.config.workspace; const repoSlug = (args.repo_slug as string) || context.config.defaultRepo; const prId = args.pr_id as number; if (!repoSlug) { throw new Error('repo_slug is required'); } if (!prId) { throw new Error('pr_id is required'); } const response = await context.bitbucket.pullRequests.getCommits(workspace, repoSlug, prId); const commits = response.values.map((commit) => ({ hash: commit.hash, message: commit.message, author: commit.author.raw, date: commit.date, })); return { content: [ { type: 'text', text: JSON.stringify( { total: response.size, commits, }, null, 2 ), }, ], }; } /** * Handle get_pr_diff tool */ export async function handleGetPRDiff(context: ToolContext, args: Record<string, unknown>) { const workspace = (args.workspace as string) || context.config.workspace; const repoSlug = (args.repo_slug as string) || context.config.defaultRepo; const prId = args.pr_id as number; if (!repoSlug) { throw new Error('repo_slug is required'); } if (!prId) { throw new Error('pr_id is required'); } const diff = await context.bitbucket.pullRequests.getDiff(workspace, repoSlug, prId); return { content: [ { type: 'text', text: diff, }, ], }; }

Latest Blog Posts

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/bobmaertz/bitbucket-mcp'

If you have feedback or need assistance with the MCP directory API, please join our Discord server