@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
JavaScript
;
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,
});
}
}