bitbucket_pipelines
Control, trigger, stop, and monitor Bitbucket Pipelines CI/CD. Manage pipeline variables and enable/disable pipelines.
Instructions
Manage Bitbucket Pipelines CI/CD. Actions:
list: List pipelines in a repository
get: Get details of a specific pipeline
trigger: Trigger a new pipeline run on a branch
trigger_custom: Trigger a custom pipeline with a specific pattern
stop: Stop a running pipeline
list_steps: List steps of a pipeline
get_step: Get details of a specific step
get_logs: Get logs for a pipeline step
get_config: Get pipeline configuration (enabled status)
set_enabled: Enable or disable pipelines for a repository
list_variables: List pipeline variables
get_variable: Get a specific pipeline variable
create_variable: Create a pipeline variable
update_variable: Update a pipeline variable
delete_variable: Delete a pipeline variable
Input Schema
| Name | Required | Description | Default |
|---|---|---|---|
| action | Yes | Action to perform | |
| workspace | No | Workspace slug (uses BITBUCKET_WORKSPACE env if omitted) | |
| repo_slug | Yes | Repository slug | |
| pipeline_uuid | No | Pipeline UUID | |
| step_uuid | No | Step UUID | |
| branch_name | No | Branch name to trigger pipeline on (required for trigger/trigger_custom) | |
| pattern | No | Custom pipeline pattern (for trigger_custom) | |
| variables | No | Pipeline variables for trigger | |
| enabled | No | Enable or disable pipelines | |
| variable_uuid | No | Variable UUID | |
| key | No | Variable key | |
| value | No | Variable value | |
| secured | No | Whether variable is secured | |
| sort | No | Sort field | |
| target_branch | No | Filter by target branch | |
| page | No | Page number for pagination | |
| pagelen | No | Results per page (default: 25, max 100) | |
| format | No | Output format: json (full), toon (compact tokens), compact (essential fields only) |
Implementation Reference
- src/server.ts:90-91 (registration)Registration of the bitbucket_pipelines tool via registerPipelineTools() call in the BitbucketMCPServer class
// Pipeline tools (1 tool with 15 actions) registerPipelineTools(this.server, this.client, this.config); - src/tools/pipeline-tools.ts:17-491 (handler)Handler function registerPipelineTools that registers the 'bitbucket_pipelines' MCP tool with 15 actions (list, get, trigger, trigger_custom, stop, list_steps, get_step, get_logs, get_config, set_enabled, list_variables, get_variable, create_variable, update_variable, delete_variable) using Zod schema validation
export function registerPipelineTools( server: McpServer, client: BitbucketClient, config: Config ): void { const pipelinesApi = new PipelinesAPI(client); server.tool( 'bitbucket_pipelines', `Manage Bitbucket Pipelines CI/CD. Actions: - list: List pipelines in a repository - get: Get details of a specific pipeline - trigger: Trigger a new pipeline run on a branch - trigger_custom: Trigger a custom pipeline with a specific pattern - stop: Stop a running pipeline - list_steps: List steps of a pipeline - get_step: Get details of a specific step - get_logs: Get logs for a pipeline step - get_config: Get pipeline configuration (enabled status) - set_enabled: Enable or disable pipelines for a repository - list_variables: List pipeline variables - get_variable: Get a specific pipeline variable - create_variable: Create a pipeline variable - update_variable: Update a pipeline variable - delete_variable: Delete a pipeline variable`, { action: z .enum([ 'list', 'get', 'trigger', 'trigger_custom', 'stop', 'list_steps', 'get_step', 'get_logs', 'get_config', 'set_enabled', 'list_variables', 'get_variable', 'create_variable', 'update_variable', 'delete_variable', ]) .describe('Action to perform'), workspace: z .string() .optional() .describe('Workspace slug (uses BITBUCKET_WORKSPACE env if omitted)'), repo_slug: z.string().describe('Repository slug'), // For get/stop/list_steps actions pipeline_uuid: z.string().optional().describe('Pipeline UUID'), // For get_step/get_logs actions step_uuid: z.string().optional().describe('Step UUID'), // For trigger actions branch_name: z .string() .optional() .describe('Branch name to trigger pipeline on (required for trigger/trigger_custom)'), pattern: z.string().optional().describe('Custom pipeline pattern (for trigger_custom)'), variables: z .array( z.object({ key: z.string(), value: z.string(), secured: z.boolean().optional(), }) ) .optional() .describe('Pipeline variables for trigger'), // For set_enabled action enabled: z.boolean().optional().describe('Enable or disable pipelines'), // For variable actions variable_uuid: z.string().optional().describe('Variable UUID'), key: z.string().optional().describe('Variable key'), value: z.string().optional().describe('Variable value'), secured: z.boolean().optional().describe('Whether variable is secured'), // For list action sort: z.string().optional().describe('Sort field'), target_branch: z.string().optional().describe('Filter by target branch'), // Pagination page: z.number().optional().describe('Page number for pagination'), pagelen: z.number().optional().describe('Results per page (default: 25, max 100)'), // Output format format: z .enum(['json', 'toon', 'compact']) .optional() .describe( 'Output format: json (full), toon (compact tokens), compact (essential fields only)' ), }, async (params) => { const workspace = params.workspace || config.workspace; if (!workspace) { return { content: [ { type: 'text' as const, text: 'Error: workspace is required (provide it or set BITBUCKET_WORKSPACE env)', }, ], isError: true, }; } const { action, repo_slug } = params; const format = (params.format ?? config.outputFormat) as OutputFormat; try { switch (action) { case 'list': { const result = await pipelinesApi.list(workspace, repo_slug, { sort: params.sort, 'target.branch': params.target_branch, page: params.page, pagelen: params.pagelen, }); return { content: [ { type: 'text' as const, text: formatOutput(paginateResult(result), format, PIPELINE_COMPACT_FIELDS), }, ], }; } case 'get': { if (!params.pipeline_uuid) { return { content: [ { type: 'text' as const, text: 'Error: pipeline_uuid is required for get action', }, ], isError: true, }; } const result = await pipelinesApi.get(workspace, repo_slug, params.pipeline_uuid); return { content: [ { type: 'text' as const, text: formatOutput(result, format, PIPELINE_COMPACT_FIELDS), }, ], }; } case 'trigger': { if (!params.branch_name) { return { content: [ { type: 'text' as const, text: 'Error: branch_name is required for trigger action', }, ], isError: true, }; } const result = await pipelinesApi.triggerBranch( workspace, repo_slug, params.branch_name, params.variables ); return { content: [ { type: 'text' as const, text: formatOutput(result, format, PIPELINE_COMPACT_FIELDS), }, ], }; } case 'trigger_custom': { if (!params.branch_name || !params.pattern) { return { content: [ { type: 'text' as const, text: 'Error: branch_name and pattern are required for trigger_custom action', }, ], isError: true, }; } const result = await pipelinesApi.triggerCustom( workspace, repo_slug, params.branch_name, params.pattern, params.variables ); return { content: [ { type: 'text' as const, text: formatOutput(result, format, PIPELINE_COMPACT_FIELDS), }, ], }; } case 'stop': { if (!params.pipeline_uuid) { return { content: [ { type: 'text' as const, text: 'Error: pipeline_uuid is required for stop action', }, ], isError: true, }; } await pipelinesApi.stop(workspace, repo_slug, params.pipeline_uuid); return { content: [{ type: 'text' as const, text: 'Pipeline stopped successfully' }], }; } case 'list_steps': { if (!params.pipeline_uuid) { return { content: [ { type: 'text' as const, text: 'Error: pipeline_uuid is required for list_steps action', }, ], isError: true, }; } const result = await pipelinesApi.listSteps( workspace, repo_slug, params.pipeline_uuid, { page: params.page, pagelen: params.pagelen, } ); return { content: [ { type: 'text' as const, text: formatOutput(paginateResult(result), format, PIPELINE_STEP_COMPACT_FIELDS), }, ], }; } case 'get_step': { if (!params.pipeline_uuid || !params.step_uuid) { return { content: [ { type: 'text' as const, text: 'Error: pipeline_uuid and step_uuid are required for get_step action', }, ], isError: true, }; } const result = await pipelinesApi.getStep( workspace, repo_slug, params.pipeline_uuid, params.step_uuid ); return { content: [ { type: 'text' as const, text: formatOutput(result, format, PIPELINE_STEP_COMPACT_FIELDS), }, ], }; } case 'get_logs': { if (!params.pipeline_uuid || !params.step_uuid) { return { content: [ { type: 'text' as const, text: 'Error: pipeline_uuid and step_uuid are required for get_logs action', }, ], isError: true, }; } const result = await pipelinesApi.getStepLogs( workspace, repo_slug, params.pipeline_uuid, params.step_uuid ); return { content: [{ type: 'text' as const, text: result }], }; } case 'get_config': { const result = await pipelinesApi.getConfig(workspace, repo_slug); return { content: [{ type: 'text' as const, text: formatOutput(result, format) }], }; } case 'set_enabled': { if (params.enabled === undefined) { return { content: [ { type: 'text' as const, text: 'Error: enabled is required for set_enabled action', }, ], isError: true, }; } await pipelinesApi.setEnabled(workspace, repo_slug, params.enabled); return { content: [ { type: 'text' as const, text: `Pipelines ${params.enabled ? 'enabled' : 'disabled'} successfully`, }, ], }; } case 'list_variables': { const result = await pipelinesApi.listVariables(workspace, repo_slug, { page: params.page, pagelen: params.pagelen, }); return { content: [ { type: 'text' as const, text: formatOutput( paginateResult(result), format, PIPELINE_VARIABLE_COMPACT_FIELDS ), }, ], }; } case 'get_variable': { if (!params.variable_uuid) { return { content: [ { type: 'text' as const, text: 'Error: variable_uuid is required for get_variable action', }, ], isError: true, }; } const result = await pipelinesApi.getVariable( workspace, repo_slug, params.variable_uuid ); return { content: [ { type: 'text' as const, text: formatOutput(result, format, PIPELINE_VARIABLE_COMPACT_FIELDS), }, ], }; } case 'create_variable': { if (!params.key || !params.value) { return { content: [ { type: 'text' as const, text: 'Error: key and value are required for create_variable action', }, ], isError: true, }; } const result = await pipelinesApi.createVariable(workspace, repo_slug, { key: params.key, value: params.value, secured: params.secured, }); return { content: [ { type: 'text' as const, text: formatOutput(result, format, PIPELINE_VARIABLE_COMPACT_FIELDS), }, ], }; } case 'update_variable': { if (!params.variable_uuid) { return { content: [ { type: 'text' as const, text: 'Error: variable_uuid is required for update_variable action', }, ], isError: true, }; } const result = await pipelinesApi.updateVariable( workspace, repo_slug, params.variable_uuid, { key: params.key, value: params.value, secured: params.secured, } ); return { content: [ { type: 'text' as const, text: formatOutput(result, format, PIPELINE_VARIABLE_COMPACT_FIELDS), }, ], }; } case 'delete_variable': { if (!params.variable_uuid) { return { content: [ { type: 'text' as const, text: 'Error: variable_uuid is required for delete_variable action', }, ], isError: true, }; } await pipelinesApi.deleteVariable(workspace, repo_slug, params.variable_uuid); return { content: [{ type: 'text' as const, text: 'Variable deleted successfully' }], }; } default: return { content: [{ type: 'text' as const, text: `Unknown action: ${action}` }], isError: true, }; } } catch (error) { const message = error instanceof Error ? error.message : 'Unknown error'; return { content: [{ type: 'text' as const, text: `Error: ${message}` }], isError: true, }; } } ); } - src/tools/pipeline-tools.ts:42-107 (schema)Zod input schema for the bitbucket_pipelines tool, defining all parameters including action enum, workspace, repo_slug, pipeline_uuid, step_uuid, branch_name, pattern, variables, enabled, variable_uuid, key, value, secured, sort, target_branch, page, pagelen, and format
{ action: z .enum([ 'list', 'get', 'trigger', 'trigger_custom', 'stop', 'list_steps', 'get_step', 'get_logs', 'get_config', 'set_enabled', 'list_variables', 'get_variable', 'create_variable', 'update_variable', 'delete_variable', ]) .describe('Action to perform'), workspace: z .string() .optional() .describe('Workspace slug (uses BITBUCKET_WORKSPACE env if omitted)'), repo_slug: z.string().describe('Repository slug'), // For get/stop/list_steps actions pipeline_uuid: z.string().optional().describe('Pipeline UUID'), // For get_step/get_logs actions step_uuid: z.string().optional().describe('Step UUID'), // For trigger actions branch_name: z .string() .optional() .describe('Branch name to trigger pipeline on (required for trigger/trigger_custom)'), pattern: z.string().optional().describe('Custom pipeline pattern (for trigger_custom)'), variables: z .array( z.object({ key: z.string(), value: z.string(), secured: z.boolean().optional(), }) ) .optional() .describe('Pipeline variables for trigger'), // For set_enabled action enabled: z.boolean().optional().describe('Enable or disable pipelines'), // For variable actions variable_uuid: z.string().optional().describe('Variable UUID'), key: z.string().optional().describe('Variable key'), value: z.string().optional().describe('Variable value'), secured: z.boolean().optional().describe('Whether variable is secured'), // For list action sort: z.string().optional().describe('Sort field'), target_branch: z.string().optional().describe('Filter by target branch'), // Pagination page: z.number().optional().describe('Page number for pagination'), pagelen: z.number().optional().describe('Results per page (default: 25, max 100)'), // Output format format: z .enum(['json', 'toon', 'compact']) .optional() .describe( 'Output format: json (full), toon (compact tokens), compact (essential fields only)' ), }, - PipelinesAPI class with methods for all pipeline operations: list, get, trigger, triggerBranch, triggerCustom, stop, listSteps, getStep, getStepLogs, listVariables, getVariable, createVariable, updateVariable, deleteVariable, getConfig, setEnabled
export class PipelinesAPI { constructor(private readonly client: BitbucketClient) {} /** * List pipelines for a repository */ async list( workspace: string, repoSlug: string, options?: ListPipelinesOptions ): Promise<PaginatedResponse<Pipeline>> { const params: Record<string, string | number | boolean | undefined> = { ...buildPaginationParams(options), sort: options?.sort, 'target.branch': options?.['target.branch'], 'target.ref_name': options?.['target.ref_name'], }; return this.client.getPaginated<Pipeline>( `/repositories/${workspace}/${repoSlug}/pipelines`, params ); } /** * Get a specific pipeline */ async get(workspace: string, repoSlug: string, pipelineUuid: string): Promise<Pipeline> { return this.client.get<Pipeline>( `/repositories/${workspace}/${repoSlug}/pipelines/${pipelineUuid}` ); } /** * Trigger a new pipeline */ async trigger( workspace: string, repoSlug: string, request: TriggerPipelineRequest ): Promise<Pipeline> { return this.client.post<Pipeline>(`/repositories/${workspace}/${repoSlug}/pipelines`, request); } /** * Trigger a pipeline for a branch */ async triggerBranch( workspace: string, repoSlug: string, branchName: string, variables?: Array<{ key: string; value: string; secured?: boolean }> ): Promise<Pipeline> { return this.trigger(workspace, repoSlug, { target: { type: 'pipeline_ref_target', ref_type: 'branch', ref_name: branchName, }, variables, }); } /** * Trigger a custom pipeline */ async triggerCustom( workspace: string, repoSlug: string, branchName: string, pattern: string, variables?: Array<{ key: string; value: string; secured?: boolean }> ): Promise<Pipeline> { return this.trigger(workspace, repoSlug, { target: { type: 'pipeline_ref_target', ref_type: 'branch', ref_name: branchName, selector: { type: 'custom', pattern, }, }, variables, }); } /** * Stop a running pipeline */ async stop(workspace: string, repoSlug: string, pipelineUuid: string): Promise<void> { await this.client.post( `/repositories/${workspace}/${repoSlug}/pipelines/${pipelineUuid}/stop_pipeline` ); } /** * List pipeline steps */ async listSteps( workspace: string, repoSlug: string, pipelineUuid: string, options?: PaginationOptions ): Promise<PaginatedResponse<PipelineStep>> { const params = buildPaginationParams(options); return this.client.getPaginated<PipelineStep>( `/repositories/${workspace}/${repoSlug}/pipelines/${pipelineUuid}/steps`, params ); } /** * Get a specific pipeline step */ async getStep( workspace: string, repoSlug: string, pipelineUuid: string, stepUuid: string ): Promise<PipelineStep> { return this.client.get<PipelineStep>( `/repositories/${workspace}/${repoSlug}/pipelines/${pipelineUuid}/steps/${stepUuid}` ); } /** * Get pipeline step logs */ async getStepLogs( workspace: string, repoSlug: string, pipelineUuid: string, stepUuid: string ): Promise<string> { return this.client.getRaw( `/repositories/${workspace}/${repoSlug}/pipelines/${pipelineUuid}/steps/${stepUuid}/log` ); } /** * List repository pipeline variables */ async listVariables( workspace: string, repoSlug: string, options?: PaginationOptions ): Promise<PaginatedResponse<PipelineVariable>> { const params = buildPaginationParams(options); return this.client.getPaginated<PipelineVariable>( `/repositories/${workspace}/${repoSlug}/pipelines_config/variables`, params ); } /** * Get a specific pipeline variable */ async getVariable( workspace: string, repoSlug: string, variableUuid: string ): Promise<PipelineVariable> { return this.client.get<PipelineVariable>( `/repositories/${workspace}/${repoSlug}/pipelines_config/variables/${variableUuid}` ); } /** * Create a pipeline variable */ async createVariable( workspace: string, repoSlug: string, variable: { key: string; value: string; secured?: boolean } ): Promise<PipelineVariable> { return this.client.post<PipelineVariable>( `/repositories/${workspace}/${repoSlug}/pipelines_config/variables`, variable ); } /** * Update a pipeline variable */ async updateVariable( workspace: string, repoSlug: string, variableUuid: string, variable: { key?: string; value?: string; secured?: boolean } ): Promise<PipelineVariable> { return this.client.put<PipelineVariable>( `/repositories/${workspace}/${repoSlug}/pipelines_config/variables/${variableUuid}`, variable ); } /** * Delete a pipeline variable */ async deleteVariable(workspace: string, repoSlug: string, variableUuid: string): Promise<void> { await this.client.delete( `/repositories/${workspace}/${repoSlug}/pipelines_config/variables/${variableUuid}` ); } /** * Get pipeline configuration */ async getConfig(workspace: string, repoSlug: string): Promise<{ enabled: boolean }> { return this.client.get<{ enabled: boolean }>( `/repositories/${workspace}/${repoSlug}/pipelines_config` ); } /** * Enable or disable pipelines */ async setEnabled(workspace: string, repoSlug: string, enabled: boolean): Promise<void> { await this.client.put(`/repositories/${workspace}/${repoSlug}/pipelines_config`, { enabled, }); } } - src/utils/compact-fields.ts:120-154 (helper)Compact field definitions for pipeline (PIPELINE_COMPACT_FIELDS), pipeline step (PIPELINE_STEP_COMPACT_FIELDS), and pipeline variable (PIPELINE_VARIABLE_COMPACT_FIELDS) used for compact output format
export const PIPELINE_COMPACT_FIELDS = [ 'uuid', 'build_number', 'state.name', 'state.result.name', 'target.ref_name', 'target.ref_type', 'creator.display_name', 'created_on', 'completed_on', 'duration_in_seconds', ]; /** * Pipeline Step - Essential fields for pipeline step listings */ export const PIPELINE_STEP_COMPACT_FIELDS = [ 'uuid', 'name', 'state.name', 'state.result.name', 'started_on', 'completed_on', 'duration_in_seconds', ]; /** * Pipeline Variable - Essential fields for variable listings */ export const PIPELINE_VARIABLE_COMPACT_FIELDS = [ 'uuid', 'key', 'value', 'secured', ];