MCP server path fixes for rules command

This commit is contained in:
Joe Danziger
2025-06-04 18:28:13 -04:00
parent e0c53d92f0
commit 8250b5cad3
6 changed files with 78 additions and 44 deletions

View File

@@ -136,10 +136,14 @@ export async function rulesDirect(args, log, context = {}) {
const profileRulesDir = path.join(projectRoot, rulesDir); const profileRulesDir = path.join(projectRoot, rulesDir);
const profileDir = profileConfig.profileDir; const profileDir = profileConfig.profileDir;
const mcpConfig = profileConfig.mcpConfig !== false; const mcpConfig = profileConfig.mcpConfig !== false;
const mcpPath = path.join(projectRoot, profileConfig.mcpConfigPath); const mcpPath =
mcpConfig && profileConfig.mcpConfigPath
? path.join(projectRoot, profileConfig.mcpConfigPath)
: null;
// Check what was created // Check what was created
const mcpConfigCreated = mcpConfig ? fs.existsSync(mcpPath) : undefined; const mcpConfigCreated =
mcpConfig && mcpPath ? fs.existsSync(mcpPath) : undefined;
const rulesDirCreated = fs.existsSync(profileRulesDir); const rulesDirCreated = fs.existsSync(profileRulesDir);
const profileFolderCreated = fs.existsSync( const profileFolderCreated = fs.existsSync(
path.join(projectRoot, profileDir) path.join(projectRoot, profileDir)

View File

@@ -4,8 +4,9 @@ import fs from 'fs';
import { isSilentMode, log } from '../modules/utils.js'; import { isSilentMode, log } from '../modules/utils.js';
// Lifecycle functions for Claude Code profile // Lifecycle functions for Claude Code profile
function onAddRulesProfile(targetDir) { function onAddRulesProfile(targetDir, assetsDir) {
const sourceFile = path.join(process.cwd(), 'assets', 'AGENTS.md'); // Use the provided assets directory to find the source file
const sourceFile = path.join(assetsDir, 'AGENTS.md');
const destFile = path.join(targetDir, 'CLAUDE.md'); const destFile = path.join(targetDir, 'CLAUDE.md');
if (fs.existsSync(sourceFile)) { if (fs.existsSync(sourceFile)) {
@@ -13,29 +14,25 @@ function onAddRulesProfile(targetDir) {
fs.copyFileSync(sourceFile, destFile); fs.copyFileSync(sourceFile, destFile);
log('debug', `[Claude] Copied AGENTS.md to ${destFile}`); log('debug', `[Claude] Copied AGENTS.md to ${destFile}`);
} catch (err) { } catch (err) {
log('debug', `[Claude] Failed to copy AGENTS.md: ${err.message}`); log('error', `[Claude] Failed to copy AGENTS.md: ${err.message}`);
} }
} else {
log('debug', `[Claude] AGENTS.md not found at ${sourceFile}`);
} }
} }
function onRemoveRulesProfile(targetDir) { function onRemoveRulesProfile(targetDir) {
log('debug', `[Claude] onRemoveRulesProfile called for ${targetDir}`);
const claudeFile = path.join(targetDir, 'CLAUDE.md'); const claudeFile = path.join(targetDir, 'CLAUDE.md');
if (fs.existsSync(claudeFile)) { if (fs.existsSync(claudeFile)) {
try { try {
fs.rmSync(claudeFile, { force: true }); fs.rmSync(claudeFile, { force: true });
log('debug', `[Claude] Removed CLAUDE.md from ${targetDir}`); log('debug', `[Claude] Removed CLAUDE.md from ${claudeFile}`);
} catch (err) { } catch (err) {
log('debug', `[Claude] Failed to remove CLAUDE.md: ${err.message}`); log('error', `[Claude] Failed to remove CLAUDE.md: ${err.message}`);
} }
} }
log('debug', `[Claude] onRemoveRulesProfile completed for ${targetDir}`);
} }
function onPostConvertRulesProfile(targetDir) { function onPostConvertRulesProfile(targetDir, assetsDir) {
onAddRulesProfile(targetDir); onAddRulesProfile(targetDir, assetsDir);
} }
// Simple filename function // Simple filename function

View File

@@ -4,8 +4,9 @@ import fs from 'fs';
import { isSilentMode, log } from '../modules/utils.js'; import { isSilentMode, log } from '../modules/utils.js';
// Lifecycle functions for Codex profile // Lifecycle functions for Codex profile
function onAddRulesProfile(targetDir) { function onAddRulesProfile(targetDir, assetsDir) {
const sourceFile = path.join(process.cwd(), 'assets', 'AGENTS.md'); // Use the provided assets directory to find the source file
const sourceFile = path.join(assetsDir, 'AGENTS.md');
const destFile = path.join(targetDir, 'AGENTS.md'); const destFile = path.join(targetDir, 'AGENTS.md');
if (fs.existsSync(sourceFile)) { if (fs.existsSync(sourceFile)) {
@@ -13,29 +14,25 @@ function onAddRulesProfile(targetDir) {
fs.copyFileSync(sourceFile, destFile); fs.copyFileSync(sourceFile, destFile);
log('debug', `[Codex] Copied AGENTS.md to ${destFile}`); log('debug', `[Codex] Copied AGENTS.md to ${destFile}`);
} catch (err) { } catch (err) {
log('debug', `[Codex] Failed to copy AGENTS.md: ${err.message}`); log('error', `[Codex] Failed to copy AGENTS.md: ${err.message}`);
} }
} else {
log('debug', `[Codex] AGENTS.md not found at ${sourceFile}`);
} }
} }
function onRemoveRulesProfile(targetDir) { function onRemoveRulesProfile(targetDir) {
log('debug', `[Codex] onRemoveRulesProfile called for ${targetDir}`);
const agentsFile = path.join(targetDir, 'AGENTS.md'); const agentsFile = path.join(targetDir, 'AGENTS.md');
if (fs.existsSync(agentsFile)) { if (fs.existsSync(agentsFile)) {
try { try {
fs.rmSync(agentsFile, { force: true }); fs.rmSync(agentsFile, { force: true });
log('debug', `[Codex] Removed AGENTS.md from ${targetDir}`); log('debug', `[Codex] Removed AGENTS.md from ${agentsFile}`);
} catch (err) { } catch (err) {
log('debug', `[Codex] Failed to remove AGENTS.md: ${err.message}`); log('error', `[Codex] Failed to remove AGENTS.md: ${err.message}`);
} }
} }
log('debug', `[Codex] onRemoveRulesProfile completed for ${targetDir}`);
} }
function onPostConvertRulesProfile(targetDir) { function onPostConvertRulesProfile(targetDir, assetsDir) {
onAddRulesProfile(targetDir); onAddRulesProfile(targetDir, assetsDir);
} }
// Simple filename function // Simple filename function

View File

@@ -6,9 +6,17 @@ import { createProfile, COMMON_TOOL_MAPPINGS } from './base-profile.js';
import { ROO_MODES } from '../../src/constants/profiles.js'; import { ROO_MODES } from '../../src/constants/profiles.js';
// Lifecycle functions for Roo profile // Lifecycle functions for Roo profile
function onAddRulesProfile(targetDir) { function onAddRulesProfile(targetDir, assetsDir) {
const sourceDir = path.join(process.cwd(), 'assets', 'roocode'); // Use the provided assets directory to find the roocode directory
const sourceDir = path.join(assetsDir, 'roocode');
if (!fs.existsSync(sourceDir)) {
log('error', `[Roo] Source directory does not exist: ${sourceDir}`);
return;
}
copyRecursiveSync(sourceDir, targetDir); copyRecursiveSync(sourceDir, targetDir);
log('debug', `[Roo] Copied roocode directory to ${targetDir}`);
const rooModesDir = path.join(sourceDir, '.roo'); const rooModesDir = path.join(sourceDir, '.roo');
@@ -20,10 +28,8 @@ function onAddRulesProfile(targetDir) {
fs.copyFileSync(roomodesSrc, roomodesDest); fs.copyFileSync(roomodesSrc, roomodesDest);
log('debug', `[Roo] Copied .roomodes to ${roomodesDest}`); log('debug', `[Roo] Copied .roomodes to ${roomodesDest}`);
} catch (err) { } catch (err) {
log('debug', `[Roo] Failed to copy .roomodes: ${err.message}`); log('error', `[Roo] Failed to copy .roomodes: ${err.message}`);
} }
} else {
log('debug', `[Roo] .roomodes not found at ${roomodesSrc}`);
} }
for (const mode of ROO_MODES) { for (const mode of ROO_MODES) {
@@ -34,12 +40,10 @@ function onAddRulesProfile(targetDir) {
const destDir = path.dirname(dest); const destDir = path.dirname(dest);
if (!fs.existsSync(destDir)) fs.mkdirSync(destDir, { recursive: true }); if (!fs.existsSync(destDir)) fs.mkdirSync(destDir, { recursive: true });
fs.copyFileSync(src, dest); fs.copyFileSync(src, dest);
log('debug', `[Roo] Copied ${src} to ${dest}`); log('debug', `[Roo] Copied ${mode}-rules to ${dest}`);
} catch (err) { } catch (err) {
log('debug', `[Roo] Failed to copy ${src} to ${dest}: ${err.message}`); log('error', `[Roo] Failed to copy ${src} to ${dest}: ${err.message}`);
} }
} else {
log('debug', `[Roo] Roo rule file not found for mode '${mode}': ${src}`);
} }
} }
} }
@@ -62,14 +66,13 @@ function copyRecursiveSync(src, dest) {
} }
function onRemoveRulesProfile(targetDir) { function onRemoveRulesProfile(targetDir) {
log('debug', `[Roo] onRemoveRulesProfile called for ${targetDir}`);
const roomodesPath = path.join(targetDir, '.roomodes'); const roomodesPath = path.join(targetDir, '.roomodes');
if (fs.existsSync(roomodesPath)) { if (fs.existsSync(roomodesPath)) {
try { try {
fs.rmSync(roomodesPath, { force: true }); fs.rmSync(roomodesPath, { force: true });
log('debug', `[Roo] Removed .roomodes from ${targetDir}`); log('debug', `[Roo] Removed .roomodes from ${roomodesPath}`);
} catch (err) { } catch (err) {
log('debug', `[Roo] Failed to remove .roomodes: ${err.message}`); log('error', `[Roo] Failed to remove .roomodes: ${err.message}`);
} }
} }
@@ -80,26 +83,25 @@ function onRemoveRulesProfile(targetDir) {
const modeDir = path.join(rooDir, entry); const modeDir = path.join(rooDir, entry);
try { try {
fs.rmSync(modeDir, { recursive: true, force: true }); fs.rmSync(modeDir, { recursive: true, force: true });
log('debug', `[Roo] Removed ${modeDir}`); log('debug', `[Roo] Removed ${entry} directory from ${modeDir}`);
} catch (err) { } catch (err) {
log('debug', `[Roo] Failed to remove ${modeDir}: ${err.message}`); log('error', `[Roo] Failed to remove ${modeDir}: ${err.message}`);
} }
} }
}); });
if (fs.readdirSync(rooDir).length === 0) { if (fs.readdirSync(rooDir).length === 0) {
try { try {
fs.rmSync(rooDir, { recursive: true, force: true }); fs.rmSync(rooDir, { recursive: true, force: true });
log('debug', '[Roo] Removed empty .roo directory'); log('debug', `[Roo] Removed empty .roo directory from ${rooDir}`);
} catch (err) { } catch (err) {
log('debug', `[Roo] Failed to remove .roo directory: ${err.message}`); log('error', `[Roo] Failed to remove .roo directory: ${err.message}`);
} }
} }
} }
log('debug', `[Roo] onRemoveRulesProfile completed for ${targetDir}`);
} }
function onPostConvertRulesProfile(targetDir) { function onPostConvertRulesProfile(targetDir, assetsDir) {
onAddRulesProfile(targetDir); onAddRulesProfile(targetDir, assetsDir);
} }
// Create and export roo profile using the base factory // Create and export roo profile using the base factory

View File

@@ -26,6 +26,15 @@ function formatJSONWithTabs(obj) {
// Structure matches project conventions (see scripts/init.js) // Structure matches project conventions (see scripts/init.js)
export function setupMCPConfiguration(projectDir, mcpConfigPath) { export function setupMCPConfiguration(projectDir, mcpConfigPath) {
// Handle null mcpConfigPath (e.g., for Claude/Codex profiles)
if (!mcpConfigPath) {
log(
'debug',
'[MCP Config] No mcpConfigPath provided, skipping MCP configuration setup'
);
return;
}
// Build the full path to the MCP config file // Build the full path to the MCP config file
const mcpPath = path.join(projectDir, mcpConfigPath); const mcpPath = path.join(projectDir, mcpConfigPath);
const configDir = path.dirname(mcpPath); const configDir = path.dirname(mcpPath);
@@ -136,6 +145,17 @@ export function setupMCPConfiguration(projectDir, mcpConfigPath) {
* @returns {Object} Result object with success status and details * @returns {Object} Result object with success status and details
*/ */
export function removeTaskMasterMCPConfiguration(projectDir, mcpConfigPath) { export function removeTaskMasterMCPConfiguration(projectDir, mcpConfigPath) {
// Handle null mcpConfigPath (e.g., for Claude/Codex profiles)
if (!mcpConfigPath) {
return {
success: true,
removed: false,
deleted: false,
error: null,
hasOtherServers: false
};
}
const mcpPath = path.join(projectDir, mcpConfigPath); const mcpPath = path.join(projectDir, mcpConfigPath);
let result = { let result = {

View File

@@ -199,6 +199,19 @@ export function convertRuleToProfileRule(sourcePath, targetPath, profile) {
* Convert all Cursor rules to profile rules for a specific profile * Convert all Cursor rules to profile rules for a specific profile
*/ */
export function convertAllRulesToProfileRules(projectDir, profile) { export function convertAllRulesToProfileRules(projectDir, profile) {
// Handle simple profiles (Claude, Codex) that just copy files to root
const isSimpleProfile = Object.keys(profile.fileMap).length === 0;
if (isSimpleProfile) {
// For simple profiles, just call their post-processing hook and return
const __filename = fileURLToPath(import.meta.url);
const __dirname = path.dirname(__filename);
const assetsDir = path.join(__dirname, '..', '..', 'assets');
if (typeof profile.onPostConvertRulesProfile === 'function') {
profile.onPostConvertRulesProfile(projectDir, assetsDir);
}
return { success: 1, failed: 0 };
}
const __filename = fileURLToPath(import.meta.url); const __filename = fileURLToPath(import.meta.url);
const __dirname = path.dirname(__filename); const __dirname = path.dirname(__filename);
const sourceDir = path.join(__dirname, '..', '..', 'assets', 'rules'); const sourceDir = path.join(__dirname, '..', '..', 'assets', 'rules');
@@ -271,7 +284,8 @@ export function convertAllRulesToProfileRules(projectDir, profile) {
// Call post-processing hook if defined (e.g., for Roo's rules-*mode* folders) // Call post-processing hook if defined (e.g., for Roo's rules-*mode* folders)
if (typeof profile.onPostConvertRulesProfile === 'function') { if (typeof profile.onPostConvertRulesProfile === 'function') {
profile.onPostConvertRulesProfile(projectDir); const assetsDir = path.join(__dirname, '..', '..', 'assets');
profile.onPostConvertRulesProfile(projectDir, assetsDir);
} }
return { success, failed }; return { success, failed };