@gohcltech/bitbucket-mcp
Version:
Bitbucket integration for Claude via Model Context Protocol
527 lines • 23.3 kB
TypeScript
/**
* @fileoverview Issue-specific HTTP client for Bitbucket API operations.
*
* This module provides comprehensive issue tracking functionality including:
* - Listing and filtering issues with various criteria
* - Creating, updating, and deleting issues
* - Managing issue assignments, voting, and watching
* - Handling issue comments and discussions
* - Working with components, milestones, and versions
* - Advanced issue workflow operations
*
* Issues in Bitbucket provide bug tracking, feature requests, and task
* management capabilities. They support categorization through components,
* project planning through milestones, and release tracking through versions.
*/
import { BaseClient, BitbucketApiResponse } from './base-client.js';
import { Issue, IssueComment, Component, Milestone, Version } from '../types/issue/index.js';
/**
* HTTP client for Bitbucket issue tracking operations.
*
* Provides comprehensive methods for managing issues, comments, and related
* metadata. Supports advanced filtering, workflow operations, and project
* management features including components, milestones, and versions.
*
* @example
* ```typescript
* const client = new IssueClient(oauthService);
*
* // Create a new bug report
* const issue = await client.createIssue('workspace', 'repo', {
* title: 'Login page crashes on mobile',
* content: { raw: 'Detailed description of the bug...', markup: 'markdown' },
* kind: 'bug',
* priority: 'major',
* component: { name: 'frontend' }
* });
*
* // Assign and track the issue
* await client.assignIssue('workspace', 'repo', issue.id, 'developer-username');
* await client.watchIssue('workspace', 'repo', issue.id);
*
* // Add progress comments
* await client.addIssueComment('workspace', 'repo', issue.id,
* 'Investigation started - reproduced on iOS 16');
* ```
*/
export declare class IssueClient extends BaseClient {
/**
* Retrieves issues from a repository with comprehensive filtering options.
*
* Supports filtering by state, priority, kind, assignee, reporter, component,
* milestone, version, and custom queries. Issues can be sorted by various
* criteria and paginated for efficient retrieval.
*
* @param workspaceSlug - Unique identifier for the workspace
* @param repoSlug - Unique identifier for the repository
* @param params - Optional query parameters for filtering and pagination
* @param params.state - Filter by issue state (new, open, resolved, on hold, invalid, duplicate, wontfix, closed)
* @param params.kind - Filter by issue type (bug, enhancement, proposal, task)
* @param params.priority - Filter by priority (trivial, minor, major, critical, blocker)
* @param params.assignee - Filter by assignee username
* @param params.reporter - Filter by reporter username
* @param params.component - Filter by component name
* @param params.milestone - Filter by milestone name
* @param params.version - Filter by version name
* @param params.sort - Sort order (created_on, updated_on, priority, votes)
* @param params.limit - Maximum number of issues to return (1-100)
* @returns Promise resolving to paginated issue list
* @throws {AuthenticationError} If not authenticated
* @throws {BitbucketApiError} If repository not found or request fails
*
* @example
* ```typescript
* // Get open bugs assigned to specific developer
* const openBugs = await client.getIssues('workspace', 'repo', {
* state: 'open',
* kind: 'bug',
* assignee: 'john.doe',
* sort: 'priority'
* });
*
* // Get high priority issues for current milestone
* const urgentIssues = await client.getIssues('workspace', 'repo', {
* priority: 'critical',
* milestone: 'v2.1.0',
* state: 'open'
* });
* ```
*/
getIssues(workspaceSlug: string, repoSlug: string, params?: Record<string, string | number>): Promise<BitbucketApiResponse<Issue>>;
/**
* Retrieves all issues from a repository (all pages) with optional filtering.
*
* This method automatically handles pagination to return all issues
* across multiple pages. Use this when you need a complete dataset
* for analysis, reporting, or bulk operations.
*
* @param workspaceSlug - Unique identifier for the workspace
* @param repoSlug - Unique identifier for the repository
* @param params - Optional query parameters for filtering issues
* @returns Promise resolving to array of all matching issues
* @throws {AuthenticationError} If not authenticated
* @throws {BitbucketApiError} If repository not found or request fails
*
* @example
* ```typescript
* // Get all issues for reporting
* const allIssues = await client.getAllIssues('workspace', 'repo');
*
* // Analyze issue distribution by component
* const issuesByComponent = allIssues.reduce((groups, issue) => {
* const component = issue.component?.name || 'Unassigned';
* groups[component] = (groups[component] || 0) + 1;
* return groups;
* }, {});
*
* // Get all resolved issues for release notes
* const resolvedIssues = await client.getAllIssues('workspace', 'repo', {
* state: 'resolved',
* version: 'v2.1.0'
* });
* ```
*/
getAllIssues(workspaceSlug: string, repoSlug: string, params?: Record<string, string | number>): Promise<Issue[]>;
/**
* Retrieves detailed information for a specific issue.
*
* Returns comprehensive issue data including title, description, state,
* priority, assignments, metadata, and related components. This is useful
* for displaying issue details or making workflow decisions.
*
* @param workspaceSlug - Unique identifier for the workspace
* @param repoSlug - Unique identifier for the repository
* @param issueId - Unique numeric identifier for the issue
* @returns Promise resolving to detailed issue information
* @throws {AuthenticationError} If not authenticated
* @throws {BitbucketApiError} If issue not found or request fails
*
* @example
* ```typescript
* // Get issue details for display
* const issue = await client.getIssue('workspace', 'repo', 42);
* console.log(`Issue #${issue.id}: ${issue.title}`);
* console.log(`State: ${issue.state}, Priority: ${issue.priority}`);
* console.log(`Assignee: ${issue.assignee?.display_name || 'Unassigned'}`);
* console.log(`Created: ${issue.created_on}`);
* console.log(`Votes: ${issue.votes}`);
* ```
*/
getIssue(workspaceSlug: string, repoSlug: string, issueId: number): Promise<Issue>;
/**
* Creates a new issue in the repository.
*
* Creates an issue with specified title, description, and metadata.
* Issues can be categorized using components, prioritized, assigned
* to team members, and associated with milestones and versions.
*
* @param workspaceSlug - Unique identifier for the workspace
* @param repoSlug - Unique identifier for the repository
* @param payload - Issue creation data
* @param payload.title - Issue title (required, max 255 characters)
* @param payload.content - Issue description in markdown format
* @param payload.kind - Issue type (bug, enhancement, proposal, task)
* @param payload.priority - Issue priority (trivial, minor, major, critical, blocker)
* @param payload.assignee - User to assign the issue to ({ username: 'user' })
* @param payload.component - Component for categorization ({ name: 'component' })
* @param payload.milestone - Milestone for project tracking ({ name: 'milestone' })
* @param payload.version - Version for release tracking ({ name: 'version' })
* @returns Promise resolving to the created issue details
* @throws {AuthenticationError} If not authenticated
* @throws {BitbucketApiError} If creation fails or validation errors occur
*
* @example
* ```typescript
* // Create a bug report
* const bug = await client.createIssue('workspace', 'repo', {
* title: 'Application crashes on startup',
* content: {
* raw: 'Steps to reproduce:\n1. Start app\n2. Click login\n3. App crashes',
* markup: 'markdown'
* },
* kind: 'bug',
* priority: 'major',
* component: { name: 'frontend' },
* assignee: { username: 'frontend-team-lead' }
* });
*
* // Create a feature request
* const feature = await client.createIssue('workspace', 'repo', {
* title: 'Add dark mode support',
* content: {
* raw: 'Users have requested dark mode for better accessibility',
* markup: 'markdown'
* },
* kind: 'enhancement',
* priority: 'minor',
* milestone: { name: 'v2.2.0' }
* });
* ```
*/
createIssue(workspaceSlug: string, repoSlug: string, payload: any): Promise<Issue>;
/**
* Updates an existing issue with new information or state changes.
*
* Allows modification of any issue field including title, description,
* state, priority, assignments, and metadata. Only specified fields
* will be updated, others remain unchanged.
*
* @param workspaceSlug - Unique identifier for the workspace
* @param repoSlug - Unique identifier for the repository
* @param issueId - Unique numeric identifier for the issue
* @param payload - Issue update data (only specified fields will be updated)
* @param payload.title - Updated issue title
* @param payload.content - Updated issue description
* @param payload.state - Updated state (new, open, resolved, closed, etc.)
* @param payload.kind - Updated issue type
* @param payload.priority - Updated priority level
* @param payload.assignee - Updated assignee
* @param payload.component - Updated component
* @param payload.milestone - Updated milestone
* @param payload.version - Updated version
* @returns Promise resolving to the updated issue data
* @throws {AuthenticationError} If not authenticated
* @throws {BitbucketApiError} If issue not found or update fails
*
* @example
* ```typescript
* // Update issue state and priority
* const updated = await client.updateIssue('workspace', 'repo', 42, {
* state: 'resolved',
* priority: 'minor'
* });
*
* // Reassign issue to different team member
* await client.updateIssue('workspace', 'repo', 42, {
* assignee: { username: 'new-developer' },
* title: 'Updated: Application crashes on startup'
* });
*
* // Close issue with resolution notes
* await client.updateIssue('workspace', 'repo', 42, {
* state: 'closed',
* content: {
* raw: 'Fixed in commit abc123. Root cause was null pointer exception.',
* markup: 'markdown'
* }
* });
* ```
*/
updateIssue(workspaceSlug: string, repoSlug: string, issueId: number, payload: any): Promise<Issue>;
/**
* Deletes an issue permanently from the repository.
*
* WARNING: This operation is irreversible and will delete all issue data
* including comments, vote history, and watch subscriptions. Consider
* closing the issue instead of deleting unless absolutely necessary.
*
* @param workspaceSlug - Unique identifier for the workspace
* @param repoSlug - Unique identifier for the repository
* @param issueId - Unique numeric identifier for the issue to delete
* @returns Promise that resolves when deletion is complete
* @throws {AuthenticationError} If not authenticated
* @throws {BitbucketApiError} If issue not found or deletion fails
*
* @example
* ```typescript
* // Delete a spam or duplicate issue
* await client.deleteIssue('workspace', 'repo', 42);
* console.log('Issue deleted permanently');
*
* // Better alternative: close instead of delete
* await client.updateIssue('workspace', 'repo', 42, {
* state: 'closed',
* content: { raw: 'Closed as duplicate of #35', markup: 'markdown' }
* });
* ```
*/
deleteIssue(workspaceSlug: string, repoSlug: string, issueId: number): Promise<void>;
/**
* Retrieves comments for a specific issue.
*
* Returns all comments associated with the issue in chronological order.
* Comments include author information, timestamps, and content in both
* raw and rendered formats.
*
* @param workspaceSlug - Unique identifier for the workspace
* @param repoSlug - Unique identifier for the repository
* @param issueId - Unique numeric identifier for the issue
* @param params - Optional query parameters for pagination
* @param params.limit - Maximum number of comments to return (1-100)
* @returns Promise resolving to paginated comment list
* @throws {AuthenticationError} If not authenticated
* @throws {BitbucketApiError} If issue not found or request fails
*
* @example
* ```typescript
* // Get comments for an issue
* const comments = await client.getIssueComments('workspace', 'repo', 42);
* console.log(`Found ${comments.values.length} comments`);
*
* // Display comment thread
* comments.values.forEach(comment => {
* console.log(`${comment.user.display_name} (${comment.created_on}):`);
* console.log(comment.content.raw);
* console.log('---');
* });
* ```
*/
getIssueComments(workspaceSlug: string, repoSlug: string, issueId: number, params?: Record<string, string | number>): Promise<BitbucketApiResponse<IssueComment>>;
/**
* Adds a new comment to an issue.
*
* Creates a comment with markdown content for team discussion,
* progress updates, or additional information. Comments support
* full markdown formatting including links, code blocks, and lists.
*
* @param workspaceSlug - Unique identifier for the workspace
* @param repoSlug - Unique identifier for the repository
* @param issueId - Unique numeric identifier for the issue
* @param content - Comment content in markdown format
* @returns Promise resolving to the created comment details
* @throws {AuthenticationError} If not authenticated
* @throws {BitbucketApiError} If issue not found or comment creation fails
*
* @example
* ```typescript
* // Add a progress update
* const comment = await client.addIssueComment('workspace', 'repo', 42,
* 'Investigation complete. Root cause identified in auth module.');
*
* // Add formatted comment with code
* await client.addIssueComment('workspace', 'repo', 42, `
* ## Fix Applied
*
* Updated the validation logic:
*
* \`\`\`javascript
* if (user && user.isValid()) {
* return user.authenticate();
* }
* \`\`\`
*
* This should resolve the crash reported in the issue.
* `);
* ```
*/
addIssueComment(workspaceSlug: string, repoSlug: string, issueId: number, content: string): Promise<IssueComment>;
/**
* Retrieves all components configured for the repository.
*
* Components are used to categorize issues by functional area,
* team responsibility, or system module. They help organize
* and filter issues for better project management.
*
* @param workspaceSlug - Unique identifier for the workspace
* @param repoSlug - Unique identifier for the repository
* @returns Promise resolving to paginated component list
* @throws {AuthenticationError} If not authenticated
* @throws {BitbucketApiError} If repository not found or request fails
*
* @example
* ```typescript
* // Get all components for issue categorization
* const components = await client.getComponents('workspace', 'repo');
*
* console.log('Available components:');
* components.values.forEach(component => {
* console.log(`- ${component.name}: ${component.description || 'No description'}`);
* });
*
* // Use component in issue creation
* const frontendComponent = components.values.find(c => c.name === 'frontend');
* ```
*/
getComponents(workspaceSlug: string, repoSlug: string): Promise<BitbucketApiResponse<Component>>;
/**
* Retrieves milestones configured for the repository.
*
* Milestones represent project goals, release targets, or time-based
* objectives. They help track progress and organize issues by
* project phases or release cycles.
*
* @param workspaceSlug - Unique identifier for the workspace
* @param repoSlug - Unique identifier for the repository
* @param params - Optional query parameters for filtering
* @param params.state - Filter by milestone state (open, closed)
* @returns Promise resolving to paginated milestone list
* @throws {AuthenticationError} If not authenticated
* @throws {BitbucketApiError} If repository not found or request fails
*
* @example
* ```typescript
* // Get active milestones
* const milestones = await client.getMilestones('workspace', 'repo', {
* state: 'open'
* });
*
* console.log('Active milestones:');
* milestones.values.forEach(milestone => {
* console.log(`- ${milestone.name}: ${milestone.description}`);
* console.log(` Due: ${milestone.due_on || 'No due date'}`);
* });
*
* // Use milestone in issue creation
* const currentMilestone = milestones.values[0];
* ```
*/
getMilestones(workspaceSlug: string, repoSlug: string, params?: Record<string, string>): Promise<BitbucketApiResponse<Milestone>>;
/**
* Retrieves versions configured for the repository.
*
* Versions represent software releases or deployment targets.
* They help track which issues are resolved in specific releases
* and plan future development cycles.
*
* @param workspaceSlug - Unique identifier for the workspace
* @param repoSlug - Unique identifier for the repository
* @param params - Optional query parameters for filtering
* @param params.released - Filter by release status (true for released, false for unreleased)
* @returns Promise resolving to paginated version list
* @throws {AuthenticationError} If not authenticated
* @throws {BitbucketApiError} If repository not found or request fails
*
* @example
* ```typescript
* // Get unreleased versions for planning
* const unreleased = await client.getVersions('workspace', 'repo', {
* released: false
* });
*
* console.log('Planned releases:');
* unreleased.values.forEach(version => {
* console.log(`- ${version.name}: ${version.description}`);
* console.log(` Release date: ${version.release_date || 'TBD'}`);
* });
*
* // Get all released versions for changelog
* const released = await client.getVersions('workspace', 'repo', {
* released: true
* });
* ```
*/
getVersions(workspaceSlug: string, repoSlug: string, params?: Record<string, string | boolean>): Promise<BitbucketApiResponse<Version>>;
/**
* Assigns an issue to a specific user for resolution.
*
* Updates the issue's assignee field to designate responsibility
* for investigation and resolution. The assignee will receive
* notifications about issue updates and changes.
*
* @param workspaceSlug - Unique identifier for the workspace
* @param repoSlug - Unique identifier for the repository
* @param issueId - Unique numeric identifier for the issue
* @param assignee - Username of the user to assign the issue to
* @returns Promise resolving to the updated issue data
* @throws {AuthenticationError} If not authenticated
* @throws {BitbucketApiError} If issue not found or assignment fails
*
* @example
* ```typescript
* // Assign bug to frontend specialist
* const assignedIssue = await client.assignIssue('workspace', 'repo', 42, 'frontend-dev');
* console.log(`Issue assigned to ${assignedIssue.assignee.display_name}`);
*
* // Reassign to team lead for escalation
* await client.assignIssue('workspace', 'repo', 42, 'team-lead');
* ```
*/
assignIssue(workspaceSlug: string, repoSlug: string, issueId: number, assignee: string): Promise<Issue>;
/**
* Votes on an issue to show interest and support.
*
* Adds the authenticated user's vote to the issue, indicating
* interest or priority. Vote counts help prioritize issues
* and gauge community interest in features or bug fixes.
*
* @param workspaceSlug - Unique identifier for the workspace
* @param repoSlug - Unique identifier for the repository
* @param issueId - Unique numeric identifier for the issue
* @returns Promise that resolves when vote is recorded
* @throws {AuthenticationError} If not authenticated
* @throws {BitbucketApiError} If issue not found or voting fails
*
* @example
* ```typescript
* // Vote for a feature request
* await client.voteIssue('workspace', 'repo', 42);
* console.log('Vote added - this will help prioritize the issue');
*
* // Check vote count after voting
* const issue = await client.getIssue('workspace', 'repo', 42);
* console.log(`Issue now has ${issue.votes} votes`);
* ```
*/
voteIssue(workspaceSlug: string, repoSlug: string, issueId: number): Promise<void>;
/**
* Watches or unwatches an issue for notifications about changes.
*
* Subscribes the authenticated user to receive notifications
* when the issue is updated, commented on, or state changes.
* This helps stakeholders stay informed about issue progress.
*
* @param workspaceSlug - Unique identifier for the workspace
* @param repoSlug - Unique identifier for the repository
* @param issueId - Unique numeric identifier for the issue
* @param watch - Whether to watch (true) or unwatch (false) the issue
* @returns Promise that resolves when watch status is updated
* @throws {AuthenticationError} If not authenticated
* @throws {BitbucketApiError} If issue not found or watch operation fails
*
* @example
* ```typescript
* // Start watching a critical issue
* await client.watchIssue('workspace', 'repo', 42, true);
* console.log('Now watching issue - you will receive notifications');
*
* // Stop watching resolved issue
* await client.watchIssue('workspace', 'repo', 42, false);
* console.log('No longer watching issue');
*
* // Default behavior is to watch
* await client.watchIssue('workspace', 'repo', 42);
* ```
*/
watchIssue(workspaceSlug: string, repoSlug: string, issueId: number, watch?: boolean): Promise<void>;
}
//# sourceMappingURL=issue-client.d.ts.map