vibe-coder-mcp
Version:
Production-ready MCP server with complete agent integration, multi-transport support, and comprehensive development automation tools for AI-assisted workflows.
85 lines (84 loc) • 3.76 kB
JavaScript
import path from 'path';
import logger from '../../../logger.js';
import { UnifiedSecurityEngine, createDefaultSecurityConfig } from '../core/unified-security-engine.js';
export class PathResolver {
static instance;
securityEngine = null;
constructor() { }
static getInstance() {
if (!PathResolver.instance) {
PathResolver.instance = new PathResolver();
}
return PathResolver.instance;
}
async getSecurityEngine() {
if (!this.securityEngine) {
const config = createDefaultSecurityConfig();
this.securityEngine = UnifiedSecurityEngine.getInstance(config);
await this.securityEngine.initialize();
}
return this.securityEngine;
}
resolveProjectRootPath(providedPath, contextId) {
if (providedPath && providedPath !== '/' && providedPath.length > 1) {
logger.debug({ providedPath, contextId }, 'Using provided project path');
return path.resolve(providedPath);
}
const envProjectPath = process.env.VIBE_TASK_MANAGER_READ_DIR;
if (envProjectPath && envProjectPath !== '/' && envProjectPath.length > 1) {
logger.debug({ envProjectPath, contextId }, 'Using environment project path');
return path.resolve(envProjectPath);
}
const cwd = process.cwd();
logger.debug({ cwd, contextId }, 'Using current working directory as project path');
return cwd;
}
resolveProjectPathFromContext(context) {
return this.resolveProjectRootPath(context.projectPath, context.sessionId);
}
getReadDirectory() {
return this.resolveProjectRootPath();
}
getOutputDirectory() {
const outputDir = process.env.VIBE_CODER_OUTPUT_DIR;
if (outputDir) {
return path.resolve(outputDir);
}
const projectRoot = this.resolveProjectRootPath();
return path.join(projectRoot, 'VibeCoderOutput');
}
async createSecureReadPath(relativePath) {
const readDir = this.getReadDirectory();
const resolvedPath = path.resolve(readDir, relativePath);
const securityEngine = await this.getSecurityEngine();
const validationResponse = await securityEngine.validatePath(resolvedPath, 'read');
if (!validationResponse.success) {
throw new Error(`Path validation failed: ${validationResponse.error?.message || 'Unknown error'}`);
}
const validationResult = validationResponse.data;
if (!validationResult.isValid) {
throw new Error(`Path validation failed: ${validationResult.error || 'Path validation failed'}`);
}
return validationResult.normalizedPath || resolvedPath;
}
async createSecureOutputPath(relativePath) {
const outputDir = this.getOutputDirectory();
const resolvedPath = path.resolve(outputDir, relativePath);
const securityEngine = await this.getSecurityEngine();
const validationResponse = await securityEngine.validatePath(resolvedPath, 'write');
if (!validationResponse.success) {
throw new Error(`Path validation failed: ${validationResponse.error?.message || 'Unknown error'}`);
}
const validationResult = validationResponse.data;
if (!validationResult.isValid) {
throw new Error(`Path validation failed: ${validationResult.error || 'Path validation failed'}`);
}
return validationResult.normalizedPath || resolvedPath;
}
}
export function getPathResolver() {
return PathResolver.getInstance();
}
export function resolveProjectPath(providedPath, contextId) {
return getPathResolver().resolveProjectRootPath(providedPath, contextId);
}