feat: implement local-only command checkers for cli and mcp (#1426)

This commit is contained in:
Ralph Khreish
2025-11-19 22:08:04 +01:00
committed by GitHub
parent 99d9179522
commit 4049f34d5a
57 changed files with 2676 additions and 482 deletions

View File

@@ -3,15 +3,11 @@
* Tool for adding a dependency to a task
*/
import { createErrorResponse, handleApiResult, withToolContext } from '@tm/mcp';
import { z } from 'zod';
import {
handleApiResult,
createErrorResponse,
withNormalizedProjectRoot
} from './utils.js';
import { resolveTag } from '../../../scripts/modules/utils.js';
import { addDependencyDirect } from '../core/task-master-core.js';
import { findTasksPath } from '../core/utils/path-utils.js';
import { resolveTag } from '../../../scripts/modules/utils.js';
/**
* Register the addDependency tool with the MCP server
@@ -37,62 +33,65 @@ export function registerAddDependencyTool(server) {
.describe('The directory of the project. Must be an absolute path.'),
tag: z.string().optional().describe('Tag context to operate on')
}),
execute: withNormalizedProjectRoot(async (args, { log, session }) => {
try {
log.info(
`Adding dependency for task ${args.id} to depend on ${args.dependsOn}`
);
const resolvedTag = resolveTag({
projectRoot: args.projectRoot,
tag: args.tag
});
let tasksJsonPath;
execute: withToolContext(
'add-dependency',
async (args, { log, session }) => {
try {
tasksJsonPath = findTasksPath(
{ projectRoot: args.projectRoot, file: args.file },
log
log.info(
`Adding dependency for task ${args.id} to depend on ${args.dependsOn}`
);
} catch (error) {
log.error(`Error finding tasks.json: ${error.message}`);
return createErrorResponse(
`Failed to find tasks.json: ${error.message}`
);
}
const resolvedTag = resolveTag({
projectRoot: args.projectRoot,
tag: args.tag
});
let tasksJsonPath;
try {
tasksJsonPath = findTasksPath(
{ projectRoot: args.projectRoot, file: args.file },
log
);
} catch (error) {
log.error(`Error finding tasks.json: ${error.message}`);
return createErrorResponse(
`Failed to find tasks.json: ${error.message}`
);
}
// Call the direct function with the resolved path
const result = await addDependencyDirect(
{
// Pass the explicitly resolved path
tasksJsonPath: tasksJsonPath,
// Pass other relevant args
id: args.id,
dependsOn: args.dependsOn,
// Call the direct function with the resolved path
const result = await addDependencyDirect(
{
// Pass the explicitly resolved path
tasksJsonPath: tasksJsonPath,
// Pass other relevant args
id: args.id,
dependsOn: args.dependsOn,
projectRoot: args.projectRoot,
tag: resolvedTag
},
log
// Remove context object
);
// Log result
if (result.success) {
log.info(`Successfully added dependency: ${result.data.message}`);
} else {
log.error(`Failed to add dependency: ${result.error.message}`);
}
// Use handleApiResult to format the response
return handleApiResult({
result,
log,
errorPrefix: 'Error adding dependency',
projectRoot: args.projectRoot,
tag: resolvedTag
},
log
// Remove context object
);
// Log result
if (result.success) {
log.info(`Successfully added dependency: ${result.data.message}`);
} else {
log.error(`Failed to add dependency: ${result.error.message}`);
});
} catch (error) {
log.error(`Error in addDependency tool: ${error.message}`);
return createErrorResponse(error.message);
}
// Use handleApiResult to format the response
return handleApiResult(
result,
log,
'Error adding dependency',
undefined,
args.projectRoot
);
} catch (error) {
log.error(`Error in addDependency tool: ${error.message}`);
return createErrorResponse(error.message);
}
})
)
});
}

View File

@@ -8,7 +8,7 @@ import {
handleApiResult,
createErrorResponse,
withNormalizedProjectRoot
} from './utils.js';
} from '@tm/mcp';
import { addSubtaskDirect } from '../core/task-master-core.js';
import { findTasksPath } from '../core/utils/path-utils.js';
import { resolveTag } from '../../../scripts/modules/utils.js';

View File

@@ -8,7 +8,7 @@ import {
createErrorResponse,
handleApiResult,
withNormalizedProjectRoot
} from './utils.js';
} from '@tm/mcp';
import { addTagDirect } from '../core/task-master-core.js';
import { findTasksPath } from '../core/utils/path-utils.js';

View File

@@ -8,7 +8,7 @@ import {
createErrorResponse,
handleApiResult,
withNormalizedProjectRoot
} from './utils.js';
} from '@tm/mcp';
import { addTaskDirect } from '../core/task-master-core.js';
import { findTasksPath } from '../core/utils/path-utils.js';
import { resolveTag } from '../../../scripts/modules/utils.js';

View File

@@ -10,7 +10,7 @@ import {
handleApiResult,
createErrorResponse,
withNormalizedProjectRoot
} from './utils.js';
} from '@tm/mcp';
import { analyzeTaskComplexityDirect } from '../core/task-master-core.js'; // Assuming core functions are exported via task-master-core.js
import { findTasksPath } from '../core/utils/path-utils.js';
import { resolveTag } from '../../../scripts/modules/utils.js';

View File

@@ -4,11 +4,7 @@
*/
import { z } from 'zod';
import {
handleApiResult,
createErrorResponse,
withNormalizedProjectRoot
} from './utils.js';
import { handleApiResult, createErrorResponse, withToolContext } from '@tm/mcp';
import { clearSubtasksDirect } from '../core/task-master-core.js';
import { findTasksPath } from '../core/utils/path-utils.js';
import { resolveTag } from '../../../scripts/modules/utils.js';
@@ -43,9 +39,11 @@ export function registerClearSubtasksTool(server) {
message: "Either 'id' or 'all' parameter must be provided",
path: ['id', 'all']
}),
execute: withNormalizedProjectRoot(async (args, { log, session }) => {
execute: withToolContext('clear-subtasks', async (args, context) => {
try {
log.info(`Clearing subtasks with args: ${JSON.stringify(args)}`);
context.log.info(
`Clearing subtasks with args: ${JSON.stringify(args)}`
);
const resolvedTag = resolveTag({
projectRoot: args.projectRoot,
@@ -57,10 +55,10 @@ export function registerClearSubtasksTool(server) {
try {
tasksJsonPath = findTasksPath(
{ projectRoot: args.projectRoot, file: args.file },
log
context.log
);
} catch (error) {
log.error(`Error finding tasks.json: ${error.message}`);
context.log.error(`Error finding tasks.json: ${error.message}`);
return createErrorResponse(
`Failed to find tasks.json: ${error.message}`
);
@@ -75,25 +73,29 @@ export function registerClearSubtasksTool(server) {
projectRoot: args.projectRoot,
tag: resolvedTag
},
log,
{ session }
context.log,
{ session: context.session }
);
if (result.success) {
log.info(`Subtasks cleared successfully: ${result.data.message}`);
context.log.info(
`Subtasks cleared successfully: ${result.data.message}`
);
} else {
log.error(`Failed to clear subtasks: ${result.error.message}`);
context.log.error(
`Failed to clear subtasks: ${result.error.message}`
);
}
return handleApiResult(
result,
log,
context.log,
'Error clearing subtasks',
undefined,
args.projectRoot
);
} catch (error) {
log.error(`Error in clearSubtasks tool: ${error.message}`);
context.log.error(`Error in clearSubtasks tool: ${error.message}`);
return createErrorResponse(error.message);
}
})

View File

@@ -8,7 +8,7 @@ import {
handleApiResult,
createErrorResponse,
withNormalizedProjectRoot
} from './utils.js';
} from '@tm/mcp';
import { complexityReportDirect } from '../core/task-master-core.js';
import { COMPLEXITY_REPORT_FILE } from '../../../src/constants/paths.js';
import { findComplexityReportPath } from '../core/utils/path-utils.js';

View File

@@ -8,7 +8,7 @@ import {
createErrorResponse,
handleApiResult,
withNormalizedProjectRoot
} from './utils.js';
} from '@tm/mcp';
import { copyTagDirect } from '../core/task-master-core.js';
import { findTasksPath } from '../core/utils/path-utils.js';

View File

@@ -8,7 +8,7 @@ import {
createErrorResponse,
handleApiResult,
withNormalizedProjectRoot
} from './utils.js';
} from '@tm/mcp';
import { deleteTagDirect } from '../core/task-master-core.js';
import { findTasksPath } from '../core/utils/path-utils.js';

View File

@@ -8,7 +8,7 @@ import {
handleApiResult,
createErrorResponse,
withNormalizedProjectRoot
} from './utils.js';
} from '@tm/mcp';
import { expandAllTasksDirect } from '../core/task-master-core.js';
import {
findTasksPath,

View File

@@ -8,7 +8,7 @@ import {
handleApiResult,
createErrorResponse,
withNormalizedProjectRoot
} from './utils.js';
} from '@tm/mcp';
import { expandTaskDirect } from '../core/task-master-core.js';
import {
findTasksPath,

View File

@@ -4,14 +4,11 @@
*/
import { z } from 'zod';
import {
handleApiResult,
createErrorResponse,
withNormalizedProjectRoot
} from './utils.js';
import { handleApiResult, createErrorResponse, withToolContext } from '@tm/mcp';
import { fixDependenciesDirect } from '../core/task-master-core.js';
import { findTasksPath } from '../core/utils/path-utils.js';
import { resolveTag } from '../../../scripts/modules/utils.js';
/**
* Register the fixDependencies tool with the MCP server
* @param {Object} server - FastMCP server instance
@@ -27,9 +24,11 @@ export function registerFixDependenciesTool(server) {
.describe('The directory of the project. Must be an absolute path.'),
tag: z.string().optional().describe('Tag context to operate on')
}),
execute: withNormalizedProjectRoot(async (args, { log, session }) => {
execute: withToolContext('fix-dependencies', async (args, context) => {
try {
log.info(`Fixing dependencies with args: ${JSON.stringify(args)}`);
context.log.info(
`Fixing dependencies with args: ${JSON.stringify(args)}`
);
const resolvedTag = resolveTag({
projectRoot: args.projectRoot,
@@ -41,10 +40,10 @@ export function registerFixDependenciesTool(server) {
try {
tasksJsonPath = findTasksPath(
{ projectRoot: args.projectRoot, file: args.file },
log
context.log
);
} catch (error) {
log.error(`Error finding tasks.json: ${error.message}`);
context.log.error(`Error finding tasks.json: ${error.message}`);
return createErrorResponse(
`Failed to find tasks.json: ${error.message}`
);
@@ -56,24 +55,28 @@ export function registerFixDependenciesTool(server) {
projectRoot: args.projectRoot,
tag: resolvedTag
},
log
context.log
);
if (result.success) {
log.info(`Successfully fixed dependencies: ${result.data.message}`);
context.log.info(
`Successfully fixed dependencies: ${result.data.message}`
);
} else {
log.error(`Failed to fix dependencies: ${result.error.message}`);
context.log.error(
`Failed to fix dependencies: ${result.error.message}`
);
}
return handleApiResult(
result,
log,
context.log,
'Error fixing dependencies',
undefined,
args.projectRoot
);
} catch (error) {
log.error(`Error in fixDependencies tool: ${error.message}`);
context.log.error(`Error in fixDependencies tool: ${error.message}`);
return createErrorResponse(error.message);
}
})

View File

@@ -1,6 +1,6 @@
// mcp-server/src/tools/get-operation-status.js
import { z } from 'zod';
import { createErrorResponse, createContentResponse } from './utils.js'; // Assuming these utils exist
import { createErrorResponse, createContentResponse } from '@tm/mcp'; // Assuming these utils exist
/**
* Register the get_operation_status tool.

View File

@@ -3,7 +3,7 @@ import {
createErrorResponse,
handleApiResult,
withNormalizedProjectRoot
} from './utils.js';
} from '@tm/mcp';
import { initializeProjectDirect } from '../core/task-master-core.js';
import { RULE_PROFILES } from '../../../src/constants/profiles.js';

View File

@@ -8,7 +8,7 @@ import {
createErrorResponse,
handleApiResult,
withNormalizedProjectRoot
} from './utils.js';
} from '@tm/mcp';
import { listTagsDirect } from '../core/task-master-core.js';
import { findTasksPath } from '../core/utils/path-utils.js';

View File

@@ -4,11 +4,7 @@
*/
import { z } from 'zod';
import {
handleApiResult,
createErrorResponse,
withNormalizedProjectRoot
} from './utils.js';
import { handleApiResult, createErrorResponse, withToolContext } from '@tm/mcp';
import { modelsDirect } from '../core/task-master-core.js';
/**
@@ -83,26 +79,28 @@ export function registerModelsTool(server) {
'Custom base URL for providers that support it (e.g., https://api.example.com/v1).'
)
}),
execute: withNormalizedProjectRoot(async (args, { log, session }) => {
execute: withToolContext('models', async (args, context) => {
try {
log.info(`Starting models tool with args: ${JSON.stringify(args)}`);
context.log.info(
`Starting models tool with args: ${JSON.stringify(args)}`
);
// Use args.projectRoot directly (guaranteed by withNormalizedProjectRoot)
const result = await modelsDirect(
{ ...args, projectRoot: args.projectRoot },
log,
{ session }
context.log,
{ session: context.session }
);
return handleApiResult(
result,
log,
context.log,
'Error managing models',
undefined,
args.projectRoot
);
} catch (error) {
log.error(`Error in models tool: ${error.message}`);
context.log.error(`Error in models tool: ${error.message}`);
return createErrorResponse(error.message);
}
})

View File

@@ -8,7 +8,7 @@ import {
handleApiResult,
createErrorResponse,
withNormalizedProjectRoot
} from './utils.js';
} from '@tm/mcp';
import {
moveTaskDirect,
moveTaskCrossTagDirect

View File

@@ -8,7 +8,7 @@ import {
createErrorResponse,
handleApiResult,
withNormalizedProjectRoot
} from './utils.js';
} from '@tm/mcp';
import { nextTaskDirect } from '../core/task-master-core.js';
import {
resolveTasksPath,

View File

@@ -9,7 +9,7 @@ import {
withNormalizedProjectRoot,
createErrorResponse,
checkProgressCapability
} from './utils.js';
} from '@tm/mcp';
import { parsePRDDirect } from '../core/task-master-core.js';
import {
PRD_FILE,

View File

@@ -3,15 +3,11 @@
* Tool for removing a dependency from a task
*/
import { createErrorResponse, handleApiResult, withToolContext } from '@tm/mcp';
import { z } from 'zod';
import {
handleApiResult,
createErrorResponse,
withNormalizedProjectRoot
} from './utils.js';
import { resolveTag } from '../../../scripts/modules/utils.js';
import { removeDependencyDirect } from '../core/task-master-core.js';
import { findTasksPath } from '../core/utils/path-utils.js';
import { resolveTag } from '../../../scripts/modules/utils.js';
/**
* Register the removeDependency tool with the MCP server
@@ -35,25 +31,25 @@ export function registerRemoveDependencyTool(server) {
.describe('The directory of the project. Must be an absolute path.'),
tag: z.string().optional().describe('Tag context to operate on')
}),
execute: withNormalizedProjectRoot(async (args, { log, session }) => {
execute: withToolContext('remove-dependency', async (args, context) => {
try {
const resolvedTag = resolveTag({
projectRoot: args.projectRoot,
tag: args.tag
});
log.info(
context.log.info(
`Removing dependency for task ${args.id} from ${args.dependsOn} with args: ${JSON.stringify(args)}`
);
// Use args.projectRoot directly (guaranteed by withNormalizedProjectRoot)
// Use args.projectRoot directly (guaranteed by withToolContext)
let tasksJsonPath;
try {
tasksJsonPath = findTasksPath(
{ projectRoot: args.projectRoot, file: args.file },
log
context.log
);
} catch (error) {
log.error(`Error finding tasks.json: ${error.message}`);
context.log.error(`Error finding tasks.json: ${error.message}`);
return createErrorResponse(
`Failed to find tasks.json: ${error.message}`
);
@@ -67,24 +63,28 @@ export function registerRemoveDependencyTool(server) {
projectRoot: args.projectRoot,
tag: resolvedTag
},
log
context.log
);
if (result.success) {
log.info(`Successfully removed dependency: ${result.data.message}`);
context.log.info(
`Successfully removed dependency: ${result.data.message}`
);
} else {
log.error(`Failed to remove dependency: ${result.error.message}`);
context.log.error(
`Failed to remove dependency: ${result.error.message}`
);
}
return handleApiResult(
result,
log,
context.log,
'Error removing dependency',
undefined,
args.projectRoot
);
} catch (error) {
log.error(`Error in removeDependency tool: ${error.message}`);
context.log.error(`Error in removeDependency tool: ${error.message}`);
return createErrorResponse(error.message);
}
})

View File

@@ -8,7 +8,7 @@ import {
handleApiResult,
createErrorResponse,
withNormalizedProjectRoot
} from './utils.js';
} from '@tm/mcp';
import { removeSubtaskDirect } from '../core/task-master-core.js';
import { findTasksPath } from '../core/utils/path-utils.js';
import { resolveTag } from '../../../scripts/modules/utils.js';

View File

@@ -8,7 +8,7 @@ import {
handleApiResult,
createErrorResponse,
withNormalizedProjectRoot
} from './utils.js';
} from '@tm/mcp';
import { removeTaskDirect } from '../core/task-master-core.js';
import { findTasksPath } from '../core/utils/path-utils.js';
import { resolveTag } from '../../../scripts/modules/utils.js';

View File

@@ -8,7 +8,7 @@ import {
createErrorResponse,
handleApiResult,
withNormalizedProjectRoot
} from './utils.js';
} from '@tm/mcp';
import { renameTagDirect } from '../core/task-master-core.js';
import { findTasksPath } from '../core/utils/path-utils.js';

View File

@@ -8,7 +8,7 @@ import {
createErrorResponse,
handleApiResult,
withNormalizedProjectRoot
} from './utils.js';
} from '@tm/mcp';
import { researchDirect } from '../core/task-master-core.js';
import { resolveTag } from '../../../scripts/modules/utils.js';

View File

@@ -3,7 +3,7 @@ import {
createErrorResponse,
handleApiResult,
withNormalizedProjectRoot
} from './utils.js';
} from '@tm/mcp';
import { responseLanguageDirect } from '../core/direct-functions/response-language.js';
export function registerResponseLanguageTool(server) {
@@ -36,7 +36,12 @@ export function registerResponseLanguageTool(server) {
log,
{ session }
);
return handleApiResult(result, log, 'Error setting response language');
return handleApiResult({
result,
log,
errorPrefix: 'Error setting response language',
projectRoot: args.projectRoot
});
} catch (error) {
log.error(`Error in response-language tool: ${error.message}`);
return createErrorResponse(error.message);

View File

@@ -8,7 +8,7 @@ import {
createErrorResponse,
handleApiResult,
withNormalizedProjectRoot
} from './utils.js';
} from '@tm/mcp';
import { rulesDirect } from '../core/direct-functions/rules.js';
import { RULE_PROFILES } from '../../../src/constants/profiles.js';
@@ -49,7 +49,11 @@ export function registerRulesTool(server) {
`[rules tool] Executing action: ${args.action} for profiles: ${args.profiles.join(', ')} in ${args.projectRoot}`
);
const result = await rulesDirect(args, log, { session });
return handleApiResult(result, log);
return handleApiResult({
result,
log,
projectRoot: args.projectRoot
});
} catch (error) {
log.error(`[rules tool] Error: ${error.message}`);
return createErrorResponse(error.message, { details: error.stack });

View File

@@ -8,7 +8,7 @@ import {
createErrorResponse,
handleApiResult,
withNormalizedProjectRoot
} from './utils.js';
} from '@tm/mcp';
import { scopeDownDirect } from '../core/task-master-core.js';
import { findTasksPath } from '../core/utils/path-utils.js';
import { resolveTag } from '../../../scripts/modules/utils.js';

View File

@@ -8,7 +8,7 @@ import {
createErrorResponse,
handleApiResult,
withNormalizedProjectRoot
} from './utils.js';
} from '@tm/mcp';
import { scopeUpDirect } from '../core/task-master-core.js';
import { findTasksPath } from '../core/utils/path-utils.js';
import { resolveTag } from '../../../scripts/modules/utils.js';

View File

@@ -8,7 +8,7 @@ import {
handleApiResult,
createErrorResponse,
withNormalizedProjectRoot
} from './utils.js';
} from '@tm/mcp';
import {
setTaskStatusDirect,
nextTaskDirect

View File

@@ -8,7 +8,7 @@ import {
handleApiResult,
createErrorResponse,
withNormalizedProjectRoot
} from './utils.js';
} from '@tm/mcp';
import { updateSubtaskByIdDirect } from '../core/task-master-core.js';
import { findTasksPath } from '../core/utils/path-utils.js';
import { resolveTag } from '../../../scripts/modules/utils.js';

View File

@@ -8,7 +8,7 @@ import {
handleApiResult,
createErrorResponse,
withNormalizedProjectRoot
} from './utils.js';
} from '@tm/mcp';
import { updateTaskByIdDirect } from '../core/task-master-core.js';
import { findTasksPath } from '../core/utils/path-utils.js';
import { resolveTag } from '../../../scripts/modules/utils.js';

View File

@@ -8,7 +8,7 @@ import {
handleApiResult,
createErrorResponse,
withNormalizedProjectRoot
} from './utils.js';
} from '@tm/mcp';
import { updateTasksDirect } from '../core/task-master-core.js';
import { findTasksPath } from '../core/utils/path-utils.js';
import { resolveTag } from '../../../scripts/modules/utils.js';

View File

@@ -8,7 +8,7 @@ import {
createErrorResponse,
handleApiResult,
withNormalizedProjectRoot
} from './utils.js';
} from '@tm/mcp';
import { useTagDirect } from '../core/task-master-core.js';
import { findTasksPath } from '../core/utils/path-utils.js';

View File

@@ -3,15 +3,11 @@
* Tool for validating task dependencies
*/
import { createErrorResponse, handleApiResult, withToolContext } from '@tm/mcp';
import { z } from 'zod';
import {
handleApiResult,
createErrorResponse,
withNormalizedProjectRoot
} from './utils.js';
import { resolveTag } from '../../../scripts/modules/utils.js';
import { validateDependenciesDirect } from '../core/task-master-core.js';
import { findTasksPath } from '../core/utils/path-utils.js';
import { resolveTag } from '../../../scripts/modules/utils.js';
/**
* Register the validateDependencies tool with the MCP server
@@ -29,56 +25,63 @@ export function registerValidateDependenciesTool(server) {
.describe('The directory of the project. Must be an absolute path.'),
tag: z.string().optional().describe('Tag context to operate on')
}),
execute: withNormalizedProjectRoot(async (args, { log, session }) => {
try {
const resolvedTag = resolveTag({
projectRoot: args.projectRoot,
tag: args.tag
});
log.info(`Validating dependencies with args: ${JSON.stringify(args)}`);
// Use args.projectRoot directly (guaranteed by withNormalizedProjectRoot)
let tasksJsonPath;
execute: withToolContext(
'validate-dependencies',
async (args, { log, session }) => {
try {
tasksJsonPath = findTasksPath(
{ projectRoot: args.projectRoot, file: args.file },
const resolvedTag = resolveTag({
projectRoot: args.projectRoot,
tag: args.tag
});
log.info(
`Validating dependencies with args: ${JSON.stringify(args)}`
);
// Use args.projectRoot directly (guaranteed by withToolContext)
let tasksJsonPath;
try {
tasksJsonPath = findTasksPath(
{ projectRoot: args.projectRoot, file: args.file },
log
);
} catch (error) {
log.error(`Error finding tasks.json: ${error.message}`);
return createErrorResponse(
`Failed to find tasks.json: ${error.message}`
);
}
const result = await validateDependenciesDirect(
{
tasksJsonPath: tasksJsonPath,
projectRoot: args.projectRoot,
tag: resolvedTag
},
log
);
} catch (error) {
log.error(`Error finding tasks.json: ${error.message}`);
return createErrorResponse(
`Failed to find tasks.json: ${error.message}`
);
}
const result = await validateDependenciesDirect(
{
tasksJsonPath: tasksJsonPath,
if (result.success) {
log.info(
`Successfully validated dependencies: ${result.data.message}`
);
} else {
log.error(
`Failed to validate dependencies: ${result.error.message}`
);
}
return handleApiResult({
result,
log,
errorPrefix: 'Error validating dependencies',
projectRoot: args.projectRoot,
tag: resolvedTag
},
log
);
if (result.success) {
log.info(
`Successfully validated dependencies: ${result.data.message}`
);
} else {
log.error(`Failed to validate dependencies: ${result.error.message}`);
});
} catch (error) {
log.error(`Error in validateDependencies tool: ${error.message}`);
return createErrorResponse(error.message);
}
return handleApiResult(
result,
log,
'Error validating dependencies',
undefined,
args.projectRoot
);
} catch (error) {
log.error(`Error in validateDependencies tool: ${error.message}`);
return createErrorResponse(error.message);
}
})
)
});
}