refactor(mcp-server): Prioritize session roots for project path discovery

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.
This commit is contained in:
Eyal Toledano
2025-04-02 12:33:46 -04:00
parent 3af469b35f
commit e04c16cec6
7 changed files with 1621 additions and 61 deletions

View File

@@ -6,7 +6,8 @@
import { z } from "zod";
import {
handleApiResult,
createErrorResponse
createErrorResponse,
getProjectRootFromSession
} from "./utils.js";
import { addTaskDirect } from "../core/task-master-core.js";
@@ -25,19 +26,26 @@ export function registerAddTaskTool(server) {
file: z.string().optional().describe("Path to the tasks file"),
projectRoot: z.string().optional().describe("Root directory of the project (default: current working directory)")
}),
execute: async ({ prompt, dependencies, priority, file, projectRoot }, log) => {
execute: async (args, { log, reportProgress, session }) => {
try {
log.info(`MCP add_task called with prompt: "${prompt}"`);
log.info(`MCP add_task called with prompt: "${args.prompt}"`);
// 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 addTaskDirect({
prompt,
dependencies,
priority,
file,
projectRoot
projectRoot: rootFolder, // Pass the resolved root
...args
}, log);
return handleApiResult(result);
return handleApiResult(result, log);
} catch (error) {
log.error(`Error in add_task MCP tool: ${error.message}`);
return createErrorResponse(error.message, "ADD_TASK_ERROR");