UNPKG

@aashari/mcp-server-atlassian-bitbucket

Version:

Node.js/TypeScript MCP server for Atlassian Bitbucket. Enables AI systems (LLMs) to interact with workspaces, repositories, and pull requests via tools (list, get, comment, search). Connects AI directly to version control workflows through the standard MC

192 lines (191 loc) 9.17 kB
"use strict"; var __importDefault = (this && this.__importDefault) || function (mod) { return (mod && mod.__esModule) ? mod : { "default": mod }; }; Object.defineProperty(exports, "__esModule", { value: true }); exports.handleCreateBranch = handleCreateBranch; exports.handleListBranches = handleListBranches; const vendor_atlassian_repositories_service_js_1 = __importDefault(require("../services/vendor.atlassian.repositories.service.js")); const logger_util_js_1 = require("../utils/logger.util.js"); const error_handler_util_js_1 = require("../utils/error-handler.util.js"); const defaults_util_js_1 = require("../utils/defaults.util.js"); const pagination_util_js_1 = require("../utils/pagination.util.js"); const formatter_util_js_1 = require("../utils/formatter.util.js"); const workspace_util_js_1 = require("../utils/workspace.util.js"); // Logger instance for this module const logger = logger_util_js_1.Logger.forContext('controllers/atlassian.repositories.branch.controller.ts'); /** * Creates a new branch in a repository. * @param options Options including workspace, repo, new branch name, and source target. * @returns Confirmation message. */ async function handleCreateBranch(options) { const { repoSlug, newBranchName, sourceBranchOrCommit } = options; let { workspaceSlug } = options; const methodLogger = logger.forMethod('handleCreateBranch'); try { methodLogger.debug('Creating new branch with options:', options); // Handle optional workspaceSlug if (!workspaceSlug) { methodLogger.debug('No workspace provided, fetching default workspace'); const defaultWorkspace = await (0, workspace_util_js_1.getDefaultWorkspace)(); if (!defaultWorkspace) { throw new Error('No default workspace found. Please provide a workspace slug.'); } workspaceSlug = defaultWorkspace; methodLogger.debug(`Using default workspace: ${defaultWorkspace}`); } if (!repoSlug) { throw new Error('Repository slug is required'); } if (!newBranchName) { throw new Error('New branch name is required'); } if (!sourceBranchOrCommit) { throw new Error('Source branch or commit is required as the starting point'); } // First, check if branch already exists to avoid potential errors methodLogger.debug('Checking if branch already exists'); try { // Call API to check if branch exists // Note: this is a simulation as the actual API might not have this specific endpoint // We'll make a call using the list branches endpoint with a filter const existingBranches = await vendor_atlassian_repositories_service_js_1.default.listBranches({ workspace: workspaceSlug, repo_slug: repoSlug, q: `name="${newBranchName}"`, }); // If we get matching branches, assume the branch exists if (existingBranches.values && existingBranches.values.length > 0) { methodLogger.warn(`Branch '${newBranchName}' already exists in ${workspaceSlug}/${repoSlug}`); return { content: `⚠️ Branch \`${newBranchName}\` already exists in the repository.`, }; } } catch (error) { // If error is 404, branch doesn't exist and we can proceed if (error.statusCode !== 404) { throw error; // Other errors should be propagated } methodLogger.debug(`Branch '${newBranchName}' does not exist, proceeding with creation`); } // Prepare the branch creation parameters const createParams = { workspace: workspaceSlug, repo_slug: repoSlug, name: newBranchName, target: { hash: sourceBranchOrCommit, }, }; // Create the branch methodLogger.debug('Creating branch with params:', createParams); const result = await vendor_atlassian_repositories_service_js_1.default.createBranch(createParams); // Confirm success with a meaningful message methodLogger.debug('Branch created successfully:', result); return { content: `✅ Successfully created branch \`${newBranchName}\` from \`${sourceBranchOrCommit}\` in ${workspaceSlug}/${repoSlug}.`, }; } catch (error) { throw (0, error_handler_util_js_1.handleControllerError)(error, { entityType: 'Branch', operation: 'create', source: 'controllers/atlassian.repositories.branch.controller.ts@handleCreateBranch', additionalInfo: options, }); } } /** * Lists branches in a repository with optional filtering * * @param options - Options containing workspaceSlug, repoSlug, and filters * @returns Formatted list of branches and pagination information */ async function handleListBranches(options) { const methodLogger = logger.forMethod('handleListBranches'); methodLogger.debug('Listing branches with options:', options); try { // Apply defaults const defaults = { limit: defaults_util_js_1.DEFAULT_PAGE_SIZE, sort: 'name', // Default sort by name }; const params = (0, defaults_util_js_1.applyDefaults)(options, defaults); // Handle optional workspaceSlug if (!params.workspaceSlug) { methodLogger.debug('No workspace provided, fetching default workspace'); const defaultWorkspace = await (0, workspace_util_js_1.getDefaultWorkspace)(); if (!defaultWorkspace) { throw new Error('No default workspace found. Please provide a workspace slug.'); } params.workspaceSlug = defaultWorkspace; methodLogger.debug(`Using default workspace: ${defaultWorkspace}`); } // Required parameters check if (!params.repoSlug) { throw new Error('Repository slug is required'); } // Call the service to list branches methodLogger.debug('Listing branches with params:', { workspace: params.workspaceSlug, repo_slug: params.repoSlug, q: params.query ? `name ~ "${params.query}"` : undefined, sort: params.sort, pagelen: params.limit, page: params.cursor ? parseInt(params.cursor, 10) : undefined, }); const branchesData = await vendor_atlassian_repositories_service_js_1.default.listBranches({ workspace: params.workspaceSlug, repo_slug: params.repoSlug, q: params.query ? `name ~ "${params.query}"` : undefined, sort: params.sort, pagelen: params.limit, page: params.cursor ? parseInt(params.cursor, 10) : undefined, }); methodLogger.debug(`Retrieved ${branchesData.values?.length || 0} branches`); // Extract pagination information const pagination = (0, pagination_util_js_1.extractPaginationInfo)(branchesData, pagination_util_js_1.PaginationType.PAGE); // Format branches data into Markdown let content = ''; if (!branchesData.values || branchesData.values.length === 0) { content = 'No branches found in this repository.'; } else { content = `# Branches in \`${params.workspaceSlug}/${params.repoSlug}\`\n\n`; if (params.query) { content += `Filtered by query: "${params.query}"\n\n`; } branchesData.values.forEach((branch) => { // Using target.hash to get the commit hash this branch points to const commitHash = branch.target?.hash?.substring(0, 8) || 'N/A'; content += `## ${branch.name}\n\n`; content += `- **Latest Commit**: ${commitHash}\n`; content += `- **Type**: ${branch.type || 'branch'}\n`; if (branch.default_merge_strategy) { content += `- **Default Merge Strategy**: ${branch.default_merge_strategy}\n`; } if (branch.merge_strategies && branch.merge_strategies.length) { content += `- **Available Merge Strategies**: ${branch.merge_strategies.join(', ')}\n`; } content += '\n'; }); } // Add pagination information if available if (pagination && (pagination.hasMore || pagination.count !== undefined)) { const paginationString = (0, formatter_util_js_1.formatPagination)(pagination); content += paginationString; } return { content }; } catch (error) { throw (0, error_handler_util_js_1.handleControllerError)(error, { entityType: 'Branches', operation: 'listing', source: 'controllers/atlassian.repositories.branch.controller.ts@handleListBranches', additionalInfo: options, }); } }