This commit refactors how the MCP server determines the project root directory, prioritizing the path provided by the client session (e.g., Cursor) for increased reliability and simplification. Previously, project root discovery relied on a complex chain of fallbacks (environment variables, CWD searching, package path checks) within `findTasksJsonPath`. This could be brittle and less accurate when running within an integrated environment like Cursor. Key changes: - **Prioritize Session Roots:** MCP tools (`add-task`, `add-dependency`, etc.) now first attempt to extract the project root URI directly from `session.roots[0].uri`. - **New Utility `getProjectRootFromSession`:** Added a utility function in `mcp-server/src/tools/utils.js` to encapsulate the logic for extracting and decoding the root URI from the session object. - **Refactor MCP Tools:** Updated tools (`add-task.js`, `add-dependency.js`) to use `getProjectRootFromSession`. - **Simplify `findTasksJsonPath`:** Prioritized `args.projectRoot`, removed checks for `TASK_MASTER_PROJECT_ROOT` env var and package directory fallback. Retained CWD search and cache check for CLI compatibility. - **Fix `reportProgress` Usage:** Corrected parameters in `add-dependency.js`. This change makes project root determination more robust for the MCP server while preserving discovery mechanisms for the standalone CLI.
65 lines
2.3 KiB
JavaScript
65 lines
2.3 KiB
JavaScript
/**
|
|
* tools/add-dependency.js
|
|
* Tool for adding a dependency to a task
|
|
*/
|
|
|
|
import { z } from "zod";
|
|
import {
|
|
handleApiResult,
|
|
createErrorResponse,
|
|
getProjectRootFromSession
|
|
} from "./utils.js";
|
|
import { addDependencyDirect } from "../core/task-master-core.js";
|
|
|
|
/**
|
|
* Register the addDependency tool with the MCP server
|
|
* @param {Object} server - FastMCP server instance
|
|
*/
|
|
export function registerAddDependencyTool(server) {
|
|
server.addTool({
|
|
name: "add_dependency",
|
|
description: "Add a dependency relationship between two tasks",
|
|
parameters: z.object({
|
|
id: z.string().describe("ID of task that will depend on another task"),
|
|
dependsOn: z.string().describe("ID of task that will become a dependency"),
|
|
file: z.string().optional().describe("Path to the tasks file (default: tasks/tasks.json)"),
|
|
projectRoot: z.string().optional().describe("Root directory of the project (default: current working directory)")
|
|
}),
|
|
execute: async (args, { log, session, reportProgress }) => {
|
|
try {
|
|
log.info(`Adding dependency for task ${args.id} to depend on ${args.dependsOn}`);
|
|
reportProgress({ progress: 0 });
|
|
|
|
// Get project root using the utility function
|
|
let rootFolder = getProjectRootFromSession(session, log);
|
|
|
|
// Fallback to args.projectRoot if session didn't provide one
|
|
if (!rootFolder && args.projectRoot) {
|
|
rootFolder = args.projectRoot;
|
|
log.info(`Using project root from args as fallback: ${rootFolder}`);
|
|
}
|
|
|
|
// Call the direct function with the resolved rootFolder
|
|
const result = await addDependencyDirect({
|
|
projectRoot: rootFolder,
|
|
...args
|
|
}, log);
|
|
|
|
reportProgress({ progress: 100 });
|
|
|
|
// 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, 'Error adding dependency');
|
|
} catch (error) {
|
|
log.error(`Error in addDependency tool: ${error.message}`);
|
|
return createErrorResponse(error.message);
|
|
}
|
|
},
|
|
});
|
|
}
|