import { WriteToProjectArgs, MCPError, ErrorCode } from '../models/types.js';
import { ProjectManager } from '../services/project_manager.js';
import { writeFile, mkdir, stat } from 'fs/promises';
import { join, dirname, isAbsolute } from 'path';
export async function writeToProject(args: WriteToProjectArgs): Promise<{
success: boolean;
fullPath: string;
action: 'created' | 'updated';
bytes: number;
}> {
const projectManager = new ProjectManager();
const project = await projectManager.getProject(args.projectId);
if (!project) {
throw new MCPError(ErrorCode.PROJECT_NOT_FOUND, `Project '${args.projectId}' not found`);
}
// Prevent directory traversal attacks
if (args.filePath.includes('..') || isAbsolute(args.filePath)) {
throw new MCPError(ErrorCode.INVALID_PATH, `Invalid file path: ${args.filePath}`);
}
const fullPath = join(project.rootPath, args.filePath);
// Check if file exists
let exists = false;
try {
await stat(fullPath);
exists = true;
} catch (e) {
exists = false;
}
if (exists && args.overwrite === false) {
throw new MCPError(
ErrorCode.FILE_ALREADY_EXISTS,
`File '${args.filePath}' already exists`,
"Set 'overwrite' to true to replace existing content."
);
}
// Create directories if requested
if (args.createDirs !== false) {
await mkdir(dirname(fullPath), { recursive: true });
}
try {
await writeFile(fullPath, args.content, 'utf-8');
const stats = await stat(fullPath);
// Update last accessed
// TODO: move this to project manager
project.lastAccessed = new Date().toISOString();
return {
success: true,
fullPath,
action: exists ? 'updated' : 'created',
bytes: stats.size
};
} catch (error: any) {
throw new MCPError(
ErrorCode.INTERNAL_ERROR,
`Failed to write file: ${error.message}`
);
}
}