@gohcltech/bitbucket-mcp
Version:
Bitbucket integration for Claude via Model Context Protocol
249 lines • 9.66 kB
JavaScript
/**
* @fileoverview Consolidated commit management tool for v2.1.
*
* Replaces v2.0 tools: list_commits, get_commit, get_commit_diff, get_commit_patch
* Consolidates 4 tools into 1 with action-based routing.
*/
import { ConsolidatedBaseTool } from './consolidated-base-tool.js';
import { ToolCategory } from '../auth-capabilities.js';
import { QueryCommitsArgsSchema, } from '../types/consolidated-tools.js';
import { validateWithSchemaOrThrow, validateRequired, validateCommitHash, } from '../utils/index.js';
/**
* Consolidated commit management tool for v2.1.
*
* Provides unified commit query and analysis operations with action-based routing.
*
* **Replaces v2.0 tools:**
* - list_commits
* - get_commit
* - get_commit_diff
* - get_commit_patch
*
* **Actions:**
* - `list`: List commits in a repository with optional filtering
* - `get`: Get detailed information about a specific commit
* - `get_diff`: Get the diff showing changes introduced by a commit
* - `get_patch`: Generate a Git-compatible patch for a commit
*
* @example
* ```typescript
* // List commits on a branch
* const response = await tool.execute({
* action: 'list',
* workspaceSlug: 'my-workspace',
* repoSlug: 'my-repo',
* branch: 'develop'
* });
*
* // Get specific commit details
* const response = await tool.execute({
* action: 'get',
* workspaceSlug: 'my-workspace',
* repoSlug: 'my-repo',
* commitHash: 'abc123def456abc123def456abc123def456abc1'
* });
*
* // Get commit diff
* const response = await tool.execute({
* action: 'get_diff',
* workspaceSlug: 'my-workspace',
* repoSlug: 'my-repo',
* commitHash: 'abc123def456abc123def456abc123def456abc1'
* });
* ```
*/
export class QueryCommitsTool extends ConsolidatedBaseTool {
getTools() {
return [
{
name: 'query_commits',
description: 'Query commits in a repository: list commits, get commit details, diffs, or patches',
inputSchema: {
type: 'object',
properties: {
action: {
type: 'string',
enum: ['list', 'get', 'get_diff', 'get_patch'],
description: 'Action to perform: list commits, get details, get diff, or get patch',
},
workspaceSlug: {
type: 'string',
description: 'Workspace slug (required)',
},
repoSlug: {
type: 'string',
description: 'Repository slug (required)',
},
branch: {
type: 'string',
description: 'Branch name to list commits from (optional, for list action)',
},
include: {
type: 'string',
description: 'Include commits reachable from this branch/commit (optional, for list action)',
},
exclude: {
type: 'string',
description: 'Exclude commits reachable from this branch/commit (optional, for list action)',
},
commitHash: {
type: 'string',
description: 'Commit SHA-1 hash (40 hex characters, required for get/get_diff/get_patch)',
},
path: {
type: 'string',
description: 'Filter diff to specific file path (optional, for get_diff action)',
},
context: {
type: 'number',
description: 'Number of context lines in diff (optional, for get_diff action)',
},
},
required: ['action', 'workspaceSlug', 'repoSlug'],
},
},
];
}
getToolCategory() {
return ToolCategory.REPOSITORY;
}
getActionHandler(action) {
const actionHandlers = {
'list': this.handleListCommits.bind(this),
'get': this.handleGetCommit.bind(this),
'get_diff': this.handleGetCommitDiff.bind(this),
'get_patch': this.handleGetCommitPatch.bind(this),
};
return actionHandlers[action] || null;
}
validateActionParams(action, args) {
// All actions require workspace and repo
validateRequired(args, ['workspaceSlug', 'repoSlug'], `query_commits.${action}`);
switch (action) {
case 'list':
// Optional: branch, include, exclude
break;
case 'get':
case 'get_diff':
case 'get_patch':
validateRequired(args, ['commitHash'], `query_commits.${action}`);
validateCommitHash(args.commitHash, 'commitHash');
break;
}
}
/**
* Handler for listing commits in a repository.
*
* @param args - Tool arguments (workspace, repo, optional branch filters)
* @returns List of commits with metadata
*/
async handleListCommits(args) {
return this.createToolResponse(async () => {
const typedArgs = args;
// Build query parameters from optional filters
const params = {};
if (typedArgs.branch) {
params.include = typedArgs.branch;
}
else if (typedArgs.include) {
params.include = typedArgs.include;
}
if (typedArgs.exclude) {
params.exclude = typedArgs.exclude;
}
// Fetch commits with filters
const result = await this.client.getCommits(typedArgs.workspaceSlug || '', typedArgs.repoSlug || '', params);
return {
commits: result.values,
count: result.values.length,
page: result.page || 1,
pageLen: result.pagelen || result.values.length,
nextUrl: result.next,
};
}, {
toolName: 'query_commits',
operationName: 'list_commits',
args,
});
}
/**
* Handler for getting detailed information about a specific commit.
*
* @param args - Tool arguments (must include commitHash)
* @returns Detailed commit information
*/
async handleGetCommit(args) {
return this.createToolResponse(async () => {
// Validate arguments
validateWithSchemaOrThrow(QueryCommitsArgsSchema, args, 'query_commits.get');
const typedArgs = args;
// Fetch commit details
const commit = await this.client.getCommit(typedArgs.workspaceSlug, typedArgs.repoSlug, typedArgs.commitHash);
return commit;
}, {
toolName: 'query_commits',
operationName: 'get_commit',
args,
});
}
/**
* Handler for getting the diff of a specific commit.
*
* @param args - Tool arguments (must include commitHash, optional path and context)
* @returns Commit diff with file changes
*/
async handleGetCommitDiff(args) {
return this.createToolResponse(async () => {
// Validate arguments
validateWithSchemaOrThrow(QueryCommitsArgsSchema, args, 'query_commits.get_diff');
const typedArgs = args;
// Build diff parameters
const params = {};
const path = typedArgs.path;
if (path && typeof path === 'string') {
params.path = path;
}
const context = typedArgs.context;
if (context !== undefined && context !== null) {
params.context = String(context);
}
// Ensure workspace, repo, and commit hash are strings
const workspaceSlug = String(typedArgs.workspaceSlug || '');
const repoSlug = String(typedArgs.repoSlug || '');
const commitHash = String(typedArgs.commitHash || '');
// Fetch commit diff
const diff = await this.client.getCommitDiff(workspaceSlug, repoSlug, commitHash, params);
return diff;
}, {
toolName: 'query_commits',
operationName: 'get_commit_diff',
args,
});
}
/**
* Handler for generating a Git patch for a specific commit.
*
* @param args - Tool arguments (must include commitHash)
* @returns Git-compatible patch format string
*/
async handleGetCommitPatch(args) {
return this.createToolResponse(async () => {
// Validate arguments
validateWithSchemaOrThrow(QueryCommitsArgsSchema, args, 'query_commits.get_patch');
const typedArgs = args;
// Fetch commit patch
const patch = await this.client.getCommitPatch(typedArgs.workspaceSlug, typedArgs.repoSlug, typedArgs.commitHash);
// Return patch as text
return {
patch,
format: 'git-patch',
commitHash: typedArgs.commitHash,
};
}, {
toolName: 'query_commits',
operationName: 'get_commit_patch',
args,
});
}
}
//# sourceMappingURL=commit-tools.js.map