Skip to main content
Glama

Atlassian Bitbucket MCP Server

by aashari
atlassian.pullrequests.cli.ts18.3 kB
import { Command } from 'commander'; import { Logger } from '../utils/logger.util.js'; import { handleCliError } from '../utils/error.util.js'; import atlassianPullRequestsController from '../controllers/atlassian.pullrequests.controller.js'; /** * CLI module for managing Bitbucket pull requests. * Provides commands for listing, retrieving, and manipulating pull requests. * All commands require valid Atlassian credentials. */ // Create a contextualized logger for this file const cliLogger = Logger.forContext('cli/atlassian.pullrequests.cli.ts'); // Log CLI initialization cliLogger.debug('Bitbucket pull requests CLI module initialized'); /** * Register Bitbucket pull requests CLI commands with the Commander program * @param program - The Commander program instance to register commands with * @throws Error if command registration fails */ function register(program: Command): void { const methodLogger = Logger.forContext( 'cli/atlassian.pullrequests.cli.ts', 'register', ); methodLogger.debug('Registering Bitbucket Pull Requests CLI commands...'); registerListPullRequestsCommand(program); registerGetPullRequestCommand(program); registerListPullRequestCommentsCommand(program); registerAddPullRequestCommentCommand(program); registerAddPullRequestCommand(program); registerUpdatePullRequestCommand(program); registerApprovePullRequestCommand(program); registerRejectPullRequestCommand(program); methodLogger.debug('CLI commands registered successfully'); } /** * Register the command for listing Bitbucket pull requests * @param program - The Commander program instance */ function registerListPullRequestsCommand(program: Command): void { program .command('ls-prs') .description( 'List pull requests in a Bitbucket repository, with filtering and pagination.', ) .option( '-w, --workspace-slug <slug>', 'Workspace slug containing the repository. If not provided, the system will use your default workspace (either configured via BITBUCKET_DEFAULT_WORKSPACE or the first workspace in your account). Example: "myteam"', ) .requiredOption( '-r, --repo-slug <slug>', 'Repository slug containing the pull requests. This must be a valid repository in the specified workspace. Example: "project-api"', ) .option( '-s, --state <state>', 'Filter by pull request state: "OPEN", "MERGED", "DECLINED", or "SUPERSEDED". If omitted, returns pull requests in all states.', ) .option( '-q, --query <string>', 'Filter pull requests by query string. Searches pull request title and description.', ) .option( '-l, --limit <number>', 'Maximum number of items to return (1-100). Defaults to 25 if omitted.', ) .option( '-c, --cursor <string>', 'Pagination cursor for retrieving the next set of results.', ) .action(async (options) => { const actionLogger = Logger.forContext( 'cli/atlassian.pullrequests.cli.ts', 'ls-prs', ); try { actionLogger.debug('Processing command options:', options); // Map CLI options to controller params - keep only type conversions const filterOptions = { workspaceSlug: options.workspaceSlug, repoSlug: options.repoSlug, state: options.state as | 'OPEN' | 'MERGED' | 'DECLINED' | 'SUPERSEDED' | undefined, query: options.query, limit: options.limit ? parseInt(options.limit, 10) : undefined, cursor: options.cursor, }; actionLogger.debug( 'Fetching pull requests with filters:', filterOptions, ); const result = await atlassianPullRequestsController.list(filterOptions); actionLogger.debug('Successfully retrieved pull requests'); // Display the content which now includes pagination information console.log(result.content); } catch (error) { actionLogger.error('Operation failed:', error); handleCliError(error); } }); } /** * Register the command for retrieving a specific Bitbucket pull request * @param program - The Commander program instance */ function registerGetPullRequestCommand(program: Command): void { program .command('get-pr') .description( 'Get detailed information about a specific Bitbucket pull request.', ) .option( '-w, --workspace-slug <slug>', 'Workspace slug containing the repository. If not provided, uses your default workspace. Example: "myteam"', ) .requiredOption( '-r, --repo-slug <slug>', 'Repository slug containing the pull request. Must be a valid repository in the specified workspace. Example: "project-api"', ) .requiredOption( '-p, --pr-id <id>', 'Numeric ID of the pull request to retrieve. Must be a valid pull request ID in the specified repository. Example: "42"', ) .option( '--include-full-diff', 'Retrieve the full diff content instead of just the summary. Default: true (rich output by default)', true, ) .option( '--include-comments', 'Retrieve comments for the pull request. Default: false. Note: Enabling this may increase response time for pull requests with many comments due to additional API calls', false, ) .action(async (options) => { const actionLogger = Logger.forContext( 'cli/atlassian.pullrequests.cli.ts', 'get-pr', ); try { actionLogger.debug('Processing command options:', options); // Map CLI options to controller params const params = { workspaceSlug: options.workspaceSlug, repoSlug: options.repoSlug, prId: options.prId, includeFullDiff: options.includeFullDiff, includeComments: options.includeComments, }; actionLogger.debug('Fetching pull request:', params); const result = await atlassianPullRequestsController.get(params); actionLogger.debug('Successfully retrieved pull request'); console.log(result.content); } catch (error) { actionLogger.error('Operation failed:', error); handleCliError(error); } }); } /** * Register the command for listing comments on a Bitbucket pull request * @param program - The Commander program instance */ function registerListPullRequestCommentsCommand(program: Command): void { program .command('ls-pr-comments') .description( 'List comments on a specific Bitbucket pull request, with pagination.', ) .option( '-w, --workspace-slug <slug>', 'Workspace slug containing the repository. If not provided, uses your default workspace. Example: "myteam"', ) .requiredOption( '-r, --repo-slug <slug>', 'Repository slug containing the pull request. Must be a valid repository in the specified workspace. Example: "project-api"', ) .requiredOption( '-p, --pr-id <id>', 'Numeric ID of the pull request to retrieve comments from. Must be a valid pull request ID in the specified repository. Example: "42"', ) .option( '-l, --limit <number>', 'Maximum number of items to return (1-100). Defaults to 25 if omitted.', ) .option( '-c, --cursor <string>', 'Pagination cursor for retrieving the next set of results.', ) .action(async (options) => { const actionLogger = Logger.forContext( 'cli/atlassian.pullrequests.cli.ts', 'ls-pr-comments', ); try { actionLogger.debug('Processing command options:', options); // Map CLI options to controller params - keep only type conversions const params = { workspaceSlug: options.workspaceSlug, repoSlug: options.repoSlug, prId: options.prId, limit: options.limit ? parseInt(options.limit, 10) : undefined, cursor: options.cursor, }; actionLogger.debug('Fetching pull request comments:', params); const result = await atlassianPullRequestsController.listComments(params); actionLogger.debug( 'Successfully retrieved pull request comments', ); // Display the content which now includes pagination information console.log(result.content); } catch (error) { actionLogger.error('Operation failed:', error); handleCliError(error); } }); } /** * Register the command for adding a comment to a pull request * @param program - The Commander program instance */ function registerAddPullRequestCommentCommand(program: Command): void { program .command('add-pr-comment') .description('Add a comment to a Bitbucket pull request.') .option( '-w, --workspace-slug <slug>', 'Workspace slug containing the repository. If not provided, uses your default workspace. Example: "myteam"', ) .requiredOption( '-r, --repo-slug <slug>', 'Repository slug containing the pull request. Must be a valid repository in the specified workspace. Example: "project-api"', ) .requiredOption( '-p, --pr-id <id>', 'Numeric ID of the pull request to add a comment to. Must be a valid pull request ID in the specified repository. Example: "42"', ) .requiredOption( '-m, --content <text>', 'The content of the comment to add to the pull request. Can include markdown formatting.', ) .option( '-f, --path <file-path>', 'Optional: The file path to add an inline comment to.', ) .option( '-L, --line <line-number>', 'Optional: The line number to add the inline comment to.', parseInt, ) .option( '--parent-id <id>', 'Optional: The ID of the parent comment to reply to. If provided, this comment will be a reply to the specified comment.', ) .action(async (options) => { const actionLogger = Logger.forContext( 'cli/atlassian.pullrequests.cli.ts', 'add-pr-comment', ); try { actionLogger.debug('Processing command options:', options); // Build parameters object const params: { workspaceSlug?: string; repoSlug: string; prId: string; content: string; inline?: { path: string; line: number; }; parentId?: string; } = { workspaceSlug: options.workspaceSlug, repoSlug: options.repoSlug, prId: options.prId, content: options.content, }; // Add inline comment details if both path and line are provided if (options.path && options.line) { params.inline = { path: options.path, line: options.line, }; } else if (options.path || options.line) { throw new Error( 'Both -f/--path and -L/--line are required for inline comments', ); } // Add parent ID if provided if (options.parentId) { params.parentId = options.parentId; } actionLogger.debug('Creating pull request comment:', { ...params, content: '(content length: ' + options.content.length + ')', }); const result = await atlassianPullRequestsController.addComment(params); actionLogger.debug('Successfully created pull request comment'); console.log(result.content); } catch (error) { actionLogger.error('Operation failed:', error); handleCliError(error); } }); } /** * Register the command for adding a new pull request * @param program - The Commander program instance */ function registerAddPullRequestCommand(program: Command): void { program .command('add-pr') .description('Add a new pull request in a Bitbucket repository.') .option( '-w, --workspace-slug <slug>', 'Workspace slug containing the repository. If not provided, uses your default workspace. Example: "myteam"', ) .requiredOption( '-r, --repo-slug <slug>', 'Repository slug to create the pull request in. Must be a valid repository in the specified workspace. Example: "project-api"', ) .requiredOption( '-t, --title <title>', 'Title for the pull request. Example: "Add new feature"', ) .requiredOption( '-s, --source-branch <branch>', 'Source branch name (the branch containing your changes). Example: "feature/new-login"', ) .option( '-d, --destination-branch <branch>', 'Destination branch name (the branch you want to merge into, defaults to main). Example: "develop"', ) .option( '--description <text>', 'Optional description for the pull request.', ) .option( '--close-source-branch', 'Whether to close the source branch after the pull request is merged. Default: false', false, ) .action(async (options) => { const actionLogger = Logger.forContext( 'cli/atlassian.pullrequests.cli.ts', 'add-pr', ); try { actionLogger.debug('Processing command options:', options); // Map CLI options to controller params const params = { workspaceSlug: options.workspaceSlug, repoSlug: options.repoSlug, title: options.title, sourceBranch: options.sourceBranch, destinationBranch: options.destinationBranch, description: options.description, closeSourceBranch: options.closeSourceBranch, }; actionLogger.debug('Creating pull request:', { ...params, description: options.description ? '(description provided)' : '(no description)', }); const result = await atlassianPullRequestsController.add(params); actionLogger.debug('Successfully created pull request'); console.log(result.content); } catch (error) { actionLogger.error('Operation failed:', error); handleCliError(error); } }); } /** * Register the command for updating a Bitbucket pull request * @param program - The Commander program instance */ function registerUpdatePullRequestCommand(program: Command): void { program .command('update-pr') .description( 'Update an existing pull request in a Bitbucket repository.', ) .option( '-w, --workspace-slug <slug>', 'Workspace slug containing the repository (optional, uses default workspace if not provided). Example: "myteam"', ) .requiredOption( '-r, --repo-slug <slug>', 'Repository slug containing the pull request. Example: "project-api"', ) .requiredOption( '-p, --pull-request-id <id>', 'Pull request ID to update. Example: 123', parseInt, ) .option( '-t, --title <title>', 'Updated title for the pull request. Example: "Updated Feature Implementation"', ) .option( '--description <text>', 'Updated description for the pull request.', ) .action(async (options) => { const actionLogger = Logger.forContext( 'cli/atlassian.pullrequests.cli.ts', 'update-pr', ); try { actionLogger.debug('Processing command options:', options); // Validate that at least one field to update is provided if (!options.title && !options.description) { throw new Error( 'At least one field to update (title or description) must be provided', ); } // Map CLI options to controller params const params = { workspaceSlug: options.workspaceSlug, repoSlug: options.repoSlug, pullRequestId: options.pullRequestId, title: options.title, description: options.description, }; actionLogger.debug('Updating pull request:', { ...params, description: options.description ? '(description provided)' : '(no description)', }); const result = await atlassianPullRequestsController.update(params); actionLogger.debug('Successfully updated pull request'); console.log(result.content); } catch (error) { actionLogger.error('Operation failed:', error); handleCliError(error); } }); } /** * Register the command for approving a Bitbucket pull request * @param program - The Commander program instance */ function registerApprovePullRequestCommand(program: Command): void { program .command('approve-pr') .description('Approve a pull request in a Bitbucket repository.') .option( '-w, --workspace-slug <slug>', 'Workspace slug containing the repository (optional, uses default workspace if not provided). Example: "myteam"', ) .requiredOption( '-r, --repo-slug <slug>', 'Repository slug containing the pull request. Example: "project-api"', ) .requiredOption( '-p, --pull-request-id <id>', 'Pull request ID to approve. Example: 123', parseInt, ) .action(async (options) => { const actionLogger = Logger.forContext( 'cli/atlassian.pullrequests.cli.ts', 'approve-pr', ); try { actionLogger.debug('Processing command options:', options); // Map CLI options to controller params const params = { workspaceSlug: options.workspaceSlug, repoSlug: options.repoSlug, pullRequestId: options.pullRequestId, }; actionLogger.debug('Approving pull request:', params); const result = await atlassianPullRequestsController.approve(params); actionLogger.debug('Successfully approved pull request'); console.log(result.content); } catch (error) { actionLogger.error('Operation failed:', error); handleCliError(error); } }); } /** * Register the command for requesting changes on a Bitbucket pull request * @param program - The Commander program instance */ function registerRejectPullRequestCommand(program: Command): void { program .command('reject-pr') .description( 'Request changes on a pull request in a Bitbucket repository.', ) .option( '-w, --workspace-slug <slug>', 'Workspace slug containing the repository (optional, uses default workspace if not provided). Example: "myteam"', ) .requiredOption( '-r, --repo-slug <slug>', 'Repository slug containing the pull request. Example: "project-api"', ) .requiredOption( '-p, --pull-request-id <id>', 'Pull request ID to request changes on. Example: 123', parseInt, ) .action(async (options) => { const actionLogger = Logger.forContext( 'cli/atlassian.pullrequests.cli.ts', 'reject-pr', ); try { actionLogger.debug('Processing command options:', options); // Map CLI options to controller params const params = { workspaceSlug: options.workspaceSlug, repoSlug: options.repoSlug, pullRequestId: options.pullRequestId, }; actionLogger.debug( 'Requesting changes on pull request:', params, ); const result = await atlassianPullRequestsController.reject(params); actionLogger.debug( 'Successfully requested changes on pull request', ); console.log(result.content); } catch (error) { actionLogger.error('Operation failed:', error); handleCliError(error); } }); } export default { register };

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/aashari/mcp-server-atlassian-bitbucket'

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