tree-ast-grep-mcp
Version:
Simple, direct ast-grep wrapper for AI coding agents. Zero abstractions, maximum performance.
127 lines • 4.16 kB
JavaScript
import { PathResolver } from './path-resolver.js';
import { ParameterValidator } from './validator.js';
import { ValidationError } from '../types/errors.js';
/**
* Provides shared validation and path handling utilities for MCP tools.
*/
export class BaseTool {
workspaceManager;
binaryManager;
pathResolver;
validator;
/**
* Create a tool with workspace context and binary access.
*/
constructor(workspaceManager, binaryManager) {
this.workspaceManager = workspaceManager;
this.binaryManager = binaryManager;
this.pathResolver = new PathResolver(workspaceManager.getWorkspaceRoot());
this.validator = new ParameterValidator(workspaceManager.getWorkspaceRoot());
}
/**
* Resolve provided paths and ensure they are accessible within the workspace.
*/
async resolveAndValidatePaths(paths) {
const resolved = await this.pathResolver.resolvePaths(paths);
if (resolved.errors.length > 0) {
throw new ValidationError('Path resolution failed', {
errors: resolved.errors,
workspace: resolved.workspace,
requestedPaths: paths
});
}
return resolved;
}
/**
* Resolve paths synchronously when asynchronous access is unnecessary.
*/
resolveAndValidatePathsSync(paths) {
const resolved = this.pathResolver.resolvePathsSync(paths);
if (resolved.errors.length > 0) {
throw new ValidationError('Path resolution failed', {
errors: resolved.errors,
workspace: resolved.workspace,
requestedPaths: paths
});
}
return resolved;
}
/**
* Construct ast-grep arguments that apply to all tool executions.
*/
buildCommonArgs(params) {
const args = [];
// Consistent parameter handling across all tools
if (params.threads) {
args.push('--threads', String(params.threads));
}
if (params.follow) {
args.push('--follow');
}
if (params.noIgnore) {
args.push('--no-ignore', 'hidden');
args.push('--no-ignore', 'dot');
args.push('--no-ignore', 'vcs');
}
// Add include patterns using globs
if (params.include && params.include.length > 0) {
for (const pattern of params.include) {
args.push('--globs', pattern);
}
}
// Add exclude patterns (ast-grep uses --globs with ! prefix for exclusion)
if (params.exclude && params.exclude.length > 0) {
for (const pattern of params.exclude) {
args.push('--globs', `!${pattern}`);
}
}
// Root/workdir controls (if provided)
if (params.root) {
args.push('--root', params.root);
}
if (params.workdir) {
args.push('--workdir', params.workdir);
}
// Add ignore path options
if (params.ignorePath && params.ignorePath.length > 0) {
for (const ig of params.ignorePath) {
args.push('--ignore-path', ig);
}
}
return args;
}
/**
* Add language hint flags when one is provided by the caller.
*/
buildLanguageArgs(language) {
const args = [];
if (language) {
args.push('--lang', language);
}
return args;
}
/**
* Request JSON output in the format expected by downstream parsers.
*/
buildJsonArgs(jsonStyle) {
const args = [];
args.push(`--json=${jsonStyle || 'stream'}`);
return args;
}
/**
* Normalize file paths for consistent display
*/
normalizePath(filePath, relativePaths) {
if (relativePaths && filePath) {
return this.pathResolver.getRelativePath(filePath);
}
return filePath;
}
/**
* Get workspace root for context
*/
getWorkspaceRoot() {
return this.workspaceManager.getWorkspaceRoot();
}
}
//# sourceMappingURL=tool-base.js.map