- Update subtask 23.10 with details on resource and resource template implementation - Add resource management section to architecture.mdc with proper directory structure - Create comprehensive resource implementation guide in mcp.mdc with examples and best practices - Document proper integration of resources in FastMCP server initialization
366 lines
21 KiB
Plaintext
366 lines
21 KiB
Plaintext
---
|
|
description: Guidelines for implementing and interacting with the Task Master MCP Server
|
|
globs: mcp-server/src/**/*, scripts/modules/**/*
|
|
alwaysApply: false
|
|
---
|
|
|
|
# Task Master MCP Server Guidelines
|
|
|
|
This document outlines the architecture and implementation patterns for the Task Master Model Context Protocol (MCP) server, designed for integration with tools like Cursor.
|
|
|
|
## Architecture Overview (See also: [`architecture.mdc`](mdc:.cursor/rules/architecture.mdc))
|
|
|
|
The MCP server acts as a bridge between external tools (like Cursor) and the core Task Master CLI logic. It leverages FastMCP for the server framework.
|
|
|
|
- **Flow**: `External Tool (Cursor)` <-> `FastMCP Server` <-> `MCP Tools` (`mcp-server/src/tools/*.js`) <-> `Core Logic Wrappers` (`mcp-server/src/core/task-master-core.js`) <-> `Core Modules` (`scripts/modules/*.js`)
|
|
- **Goal**: Provide a performant and reliable way for external tools to interact with Task Master functionality without directly invoking the CLI for every operation.
|
|
|
|
## Key Principles
|
|
|
|
- **Prefer Direct Function Calls**: For optimal performance and error handling, MCP tools should utilize direct function wrappers defined in [`task-master-core.js`](mdc:mcp-server/src/core/task-master-core.js). These wrappers call the underlying logic from the core modules (e.g., [`task-manager.js`](mdc:scripts/modules/task-manager.js)).
|
|
- **Standard Tool Execution Pattern**:
|
|
- The `execute` method within each MCP tool (in `mcp-server/src/tools/*.js`) should:
|
|
1. Call the corresponding `*Direct` function wrapper (e.g., `listTasksDirect`) from [`task-master-core.js`](mdc:mcp-server/src/core/task-master-core.js), passing necessary arguments and the logger.
|
|
2. Receive the result object (typically `{ success, data/error, fromCache }`).
|
|
3. Pass this result object to the `handleApiResult` utility (from [`tools/utils.js`](mdc:mcp-server/src/tools/utils.js)) for standardized response formatting and error handling.
|
|
4. Return the formatted response object provided by `handleApiResult`.
|
|
- **CLI Execution as Fallback**: The `executeTaskMasterCommand` utility in [`tools/utils.js`](mdc:mcp-server/src/tools/utils.js) allows executing commands via the CLI (`task-master ...`). This should **only** be used as a fallback if a direct function wrapper is not yet implemented or if a specific command intrinsically requires CLI execution.
|
|
- **Centralized Utilities** (See also: [`utilities.mdc`](mdc:.cursor/rules/utilities.mdc)):
|
|
- Use `findTasksJsonPath` (in [`task-master-core.js`](mdc:mcp-server/src/core/task-master-core.js)) *within direct function wrappers* to locate the `tasks.json` file consistently.
|
|
- **Leverage MCP Utilities**: The file [`tools/utils.js`](mdc:mcp-server/src/tools/utils.js) contains essential helpers for MCP tool implementation:
|
|
- `getProjectRoot`: Normalizes project paths.
|
|
- `handleApiResult`: Takes the raw result from a `*Direct` function and formats it into a standard MCP success or error response, automatically handling data processing via `processMCPResponseData`. This is called by the tool's `execute` method.
|
|
- `createContentResponse`/`createErrorResponse`: Used by `handleApiResult` to format successful/error MCP responses.
|
|
- `processMCPResponseData`: Filters/cleans data (e.g., removing `details`, `testStrategy`) before it's sent in the MCP response. Called by `handleApiResult`.
|
|
- `getCachedOrExecute`: **Used inside `*Direct` functions** in `task-master-core.js` to implement caching logic.
|
|
- `executeTaskMasterCommand`: Fallback for executing CLI commands.
|
|
- **Caching**: To improve performance for frequently called read operations (like `listTasks`, `showTask`, `nextTask`), a caching layer using `lru-cache` is implemented.
|
|
- **Caching logic resides *within* the direct function wrappers** in [`task-master-core.js`](mdc:mcp-server/src/core/task-master-core.js) using the `getCachedOrExecute` utility from [`tools/utils.js`](mdc:mcp-server/src/tools/utils.js).
|
|
- Generate unique cache keys based on function arguments that define a distinct call (e.g., file path, filters).
|
|
- The `getCachedOrExecute` utility handles checking the cache, executing the core logic function on a cache miss, storing the result, and returning the data along with a `fromCache` flag.
|
|
- Cache statistics can be monitored using the `cacheStats` MCP tool (implemented via `getCacheStatsDirect`).
|
|
- **Caching should generally be applied to read-only operations** that don't modify the `tasks.json` state. Commands like `set-status`, `add-task`, `update-task`, `parse-prd`, `add-dependency` should *not* be cached as they change the underlying data.
|
|
|
|
## Resources and Resource Templates
|
|
|
|
Resources and resource templates are an important part of the FastMCP architecture that allow for exposing data to LLM clients without needing to execute tools.
|
|
|
|
### Resource Implementation
|
|
|
|
- **Purpose**: Resources provide LLMs with static or dynamic data that can be referenced directly without executing a tool.
|
|
- **Current Implementation**: In [`mcp-server/src/index.js`](mdc:mcp-server/src/index.js), resources are currently initialized as empty objects:
|
|
```javascript
|
|
this.server.addResource({});
|
|
this.server.addResourceTemplate({});
|
|
```
|
|
|
|
- **Proper Implementation**: Resources should be implemented using the `@mcp.resource()` decorator pattern in a dedicated directory (e.g., `mcp-server/src/core/resources/`).
|
|
|
|
- **Resource Types for Task Master**:
|
|
- **Task Templates**: Predefined task structures that can be used as starting points
|
|
- **Workflow Definitions**: Reusable workflow patterns for common task sequences
|
|
- **Project Metadata**: Information about active projects and their attributes
|
|
- **User Preferences**: Stored user settings for task management
|
|
|
|
- **Resource Implementation Example**:
|
|
```javascript
|
|
// mcp-server/src/core/resources/task-templates.js
|
|
import { taskTemplates } from '../data/templates.js';
|
|
|
|
export function registerTaskTemplateResources(server) {
|
|
server.addResource({
|
|
name: "tasks://templates/{templateId}",
|
|
description: "Access predefined task templates",
|
|
parameters: {
|
|
templateId: {
|
|
type: "string",
|
|
description: "ID of the task template"
|
|
}
|
|
},
|
|
execute: async ({ templateId }) => {
|
|
const template = taskTemplates[templateId];
|
|
if (!template) {
|
|
return {
|
|
status: 404,
|
|
content: { error: `Template ${templateId} not found` }
|
|
};
|
|
}
|
|
return {
|
|
status: 200,
|
|
content: template
|
|
};
|
|
}
|
|
});
|
|
|
|
// Register all templates as a collection resource
|
|
server.addResource({
|
|
name: "tasks://templates",
|
|
description: "List all available task templates",
|
|
execute: async () => {
|
|
return {
|
|
status: 200,
|
|
content: Object.keys(taskTemplates).map(id => ({
|
|
id,
|
|
name: taskTemplates[id].name,
|
|
description: taskTemplates[id].description
|
|
}))
|
|
};
|
|
}
|
|
});
|
|
}
|
|
```
|
|
|
|
### Resource Templates Implementation
|
|
|
|
- **Purpose**: Resource templates allow for dynamic generation of resources based on patterns.
|
|
- **Implementation Example**:
|
|
```javascript
|
|
// mcp-server/src/core/resources/task-templates.js
|
|
export function registerTaskTemplateResourceTemplates(server) {
|
|
server.addResourceTemplate({
|
|
pattern: "tasks://create/{taskType}",
|
|
description: "Generate a task creation template based on task type",
|
|
parameters: {
|
|
taskType: {
|
|
type: "string",
|
|
description: "Type of task to create (e.g., 'feature', 'bug', 'docs')"
|
|
}
|
|
},
|
|
execute: async ({ taskType }) => {
|
|
// Generate a dynamic template based on taskType
|
|
const template = generateTemplateForTaskType(taskType);
|
|
|
|
if (!template) {
|
|
return {
|
|
status: 404,
|
|
content: { error: `No template available for task type: ${taskType}` }
|
|
};
|
|
}
|
|
|
|
return {
|
|
status: 200,
|
|
content: template
|
|
};
|
|
}
|
|
});
|
|
}
|
|
```
|
|
|
|
### Resource Registration in Server Initialization
|
|
|
|
Resources and resource templates should be registered during server initialization:
|
|
|
|
```javascript
|
|
// mcp-server/src/index.js
|
|
import { registerTaskTemplateResources, registerTaskTemplateResourceTemplates } from './core/resources/task-templates.js';
|
|
import { registerWorkflowResources } from './core/resources/workflow-definitions.js';
|
|
import { registerProjectMetadataResources } from './core/resources/project-metadata.js';
|
|
|
|
class TaskMasterMCPServer {
|
|
constructor() {
|
|
// ... existing constructor code ...
|
|
|
|
this.server = new FastMCP(this.options);
|
|
this.initialized = false;
|
|
|
|
// Resource registration will be done in init()
|
|
|
|
// ... rest of constructor ...
|
|
}
|
|
|
|
async init() {
|
|
if (this.initialized) return;
|
|
|
|
// Register resources before tools
|
|
registerTaskTemplateResources(this.server);
|
|
registerTaskTemplateResourceTemplates(this.server);
|
|
registerWorkflowResources(this.server);
|
|
registerProjectMetadataResources(this.server);
|
|
|
|
// Register Task Master tools
|
|
registerTaskMasterTools(this.server);
|
|
|
|
this.initialized = true;
|
|
return this;
|
|
}
|
|
|
|
// ... rest of class ...
|
|
}
|
|
```
|
|
|
|
### Best Practices for Resources
|
|
|
|
1. **Organization**: Create a dedicated `resources` directory with separate modules for each resource category.
|
|
2. **Validation**: Validate input parameters and return appropriate error responses.
|
|
3. **Caching**: Consider caching resource responses if they are expensive to generate.
|
|
4. **Documentation**: Include clear descriptions for all resources and their parameters.
|
|
5. **URI Structure**: Use consistent URI patterns (`resource-type://path/to/resource`) for all resources.
|
|
6. **Error Handling**: Return standard HTTP-like status codes (200, 404, etc.) for resource responses.
|
|
7. **Resource Registration**: Register resources before tools during server initialization.
|
|
|
|
Resources enable LLMs to access contextual information without needing to execute tools, which can significantly improve performance and user experience. Properly implemented resources complement tools to create a comprehensive MCP server.
|
|
|
|
## Implementing MCP Support for a Command
|
|
|
|
Follow these steps to add MCP support for an existing Task Master command (see [`new_features.mdc`](mdc:.cursor/rules/new_features.mdc) for more detail):
|
|
|
|
1. **Ensure Core Logic Exists**: Verify the core functionality is implemented and exported from the relevant module in `scripts/modules/`.
|
|
|
|
2. **Create Direct Function File in `mcp-server/src/core/direct-functions/`**:
|
|
- Create a new file (e.g., `your-command.js`) in the `direct-functions` directory using **kebab-case** for file naming.
|
|
- Import necessary core functions from Task Master modules (e.g., `../../../../scripts/modules/task-manager.js`).
|
|
- Import utilities: `findTasksJsonPath` from `../utils/path-utils.js` and `getCachedOrExecute` from `../../tools/utils.js` if needed.
|
|
- Implement `async function yourCommandDirect(args, log)` using **camelCase** with `Direct` suffix:
|
|
- Parse `args` and determine necessary inputs (e.g., `tasksPath` via `findTasksJsonPath`).
|
|
- **If Caching**:
|
|
- Generate a unique `cacheKey` based on arguments defining the operation.
|
|
- Define an `async` function `coreActionFn` containing the call to the core logic.
|
|
- Call `const result = await getCachedOrExecute({ cacheKey, actionFn: coreActionFn, log });`.
|
|
- **If Not Caching**:
|
|
- Directly call the core logic function within a try/catch block.
|
|
- Format the return as `{ success: true/false, data/error, fromCache: boolean }`.
|
|
- Export the wrapper function.
|
|
|
|
3. **Update `task-master-core.js` with Import/Export**:
|
|
- Import your direct function: `import { yourCommandDirect } from './direct-functions/your-command.js';`
|
|
- Re-export it in the exports section.
|
|
- Add it to the `directFunctions` map: `yourCommand: yourCommandDirect`.
|
|
|
|
4. **Create MCP Tool (`mcp-server/src/tools/`)**:
|
|
- Create a new file (e.g., `your-command.js`) using **kebab-case**.
|
|
- Import `z` for schema definition.
|
|
- Import `handleApiResult` from `./utils.js`.
|
|
- Import the `yourCommandDirect` wrapper function from `../core/task-master-core.js`.
|
|
- Implement `registerYourCommandTool(server)` using **camelCase** with `Tool` suffix.
|
|
- Define the tool `name` using **snake_case** (e.g., `your_command`).
|
|
|
|
5. **Register Tool**: Import and call `registerYourCommandTool` in `mcp-server/src/tools/index.js`.
|
|
|
|
6. **Update `mcp.json`**: Add the new tool definition to the `tools` array in `.cursor/mcp.json`.
|
|
|
|
## Handling Responses
|
|
|
|
- MCP tools should return the object generated by `handleApiResult`.
|
|
- `handleApiResult` uses `createContentResponse` or `createErrorResponse` internally.
|
|
- `handleApiResult` also uses `processMCPResponseData` by default to filter potentially large fields (`details`, `testStrategy`) from task data. Provide a custom processor function to `handleApiResult` if different filtering is needed.
|
|
- The final JSON response sent to the MCP client will include the `fromCache` boolean flag (obtained from the `*Direct` function's result) alongside the actual data (e.g., `{ "fromCache": true, "data": { ... } }` or `{ "fromCache": false, "data": { ... } }`).
|
|
|
|
## Parameter Type Handling
|
|
|
|
- **Prefer Direct Function Calls**: For optimal performance and error handling, MCP tools should utilize direct function wrappers defined in [`task-master-core.js`](mdc:mcp-server/src/core/task-master-core.js). These wrappers call the underlying logic from the core modules (e.g., [`task-manager.js`](mdc:scripts/modules/task-manager.js)).
|
|
- **Standard Tool Execution Pattern**:
|
|
- The `execute` method within each MCP tool (in `mcp-server/src/tools/*.js`) should:
|
|
1. Call the corresponding `*Direct` function wrapper (e.g., `listTasksDirect`) from [`task-master-core.js`](mdc:mcp-server/src/core/task-master-core.js), passing necessary arguments and the logger.
|
|
2. Receive the result object (typically `{ success, data/error, fromCache }`).
|
|
3. Pass this result object to the `handleApiResult` utility (from [`tools/utils.js`](mdc:mcp-server/src/tools/utils.js)) for standardized response formatting and error handling.
|
|
4. Return the formatted response object provided by `handleApiResult`.
|
|
- **CLI Execution as Fallback**: The `executeTaskMasterCommand` utility in [`tools/utils.js`](mdc:mcp-server/src/tools/utils.js) allows executing commands via the CLI (`task-master ...`). This should **only** be used as a fallback if a direct function wrapper is not yet implemented or if a specific command intrinsically requires CLI execution.
|
|
- **Centralized Utilities** (See also: [`utilities.mdc`](mdc:.cursor/rules/utilities.mdc)):
|
|
- Use `findTasksJsonPath` (in [`task-master-core.js`](mdc:mcp-server/src/core/task-master-core.js)) *within direct function wrappers* to locate the `tasks.json` file consistently.
|
|
- **Leverage MCP Utilities**: The file [`tools/utils.js`](mdc:mcp-server/src/tools/utils.js) contains essential helpers for MCP tool implementation:
|
|
- `getProjectRoot`: Normalizes project paths.
|
|
- `handleApiResult`: Takes the raw result from a `*Direct` function and formats it into a standard MCP success or error response, automatically handling data processing via `processMCPResponseData`. This is called by the tool's `execute` method.
|
|
- `createContentResponse`/`createErrorResponse`: Used by `handleApiResult` to format successful/error MCP responses.
|
|
- `processMCPResponseData`: Filters/cleans data (e.g., removing `details`, `testStrategy`) before it's sent in the MCP response. Called by `handleApiResult`.
|
|
- `getCachedOrExecute`: **Used inside `*Direct` functions** in `task-master-core.js` to implement caching logic.
|
|
- `executeTaskMasterCommand`: Fallback for executing CLI commands.
|
|
- **Caching**: To improve performance for frequently called read operations (like `listTasks`, `showTask`, `nextTask`), a caching layer using `lru-cache` is implemented.
|
|
- **Caching logic resides *within* the direct function wrappers** in [`task-master-core.js`](mdc:mcp-server/src/core/task-master-core.js) using the `getCachedOrExecute` utility from [`tools/utils.js`](mdc:mcp-server/src/tools/utils.js).
|
|
- Generate unique cache keys based on function arguments that define a distinct call (e.g., file path, filters).
|
|
- The `getCachedOrExecute` utility handles checking the cache, executing the core logic function on a cache miss, storing the result, and returning the data along with a `fromCache` flag.
|
|
- Cache statistics can be monitored using the `cacheStats` MCP tool (implemented via `getCacheStatsDirect`).
|
|
- **Caching should generally be applied to read-only operations** that don't modify the `tasks.json` state. Commands like `set-status`, `add-task`, `update-task`, `parse-prd`, `add-dependency` should *not* be cached as they change the underlying data.
|
|
|
|
**MCP Tool Implementation Checklist**:
|
|
|
|
1. **Core Logic Verification**:
|
|
- [ ] Confirm the core function is properly exported from its module (e.g., `task-manager.js`)
|
|
- [ ] Identify all required parameters and their types
|
|
|
|
2. **Direct Function Wrapper**:
|
|
- [ ] Create the `*Direct` function in `task-master-core.js`
|
|
- [ ] Handle all parameter validations and type conversions
|
|
- [ ] Implement path resolving for relative paths
|
|
- [ ] Add appropriate error handling with standardized error codes
|
|
- [ ] Add to `directFunctions` map
|
|
|
|
3. **MCP Tool Implementation**:
|
|
- [ ] Create new file in `mcp-server/src/tools/` with kebab-case naming
|
|
- [ ] Define zod schema for all parameters
|
|
- [ ] Implement the `execute` method following the standard pattern
|
|
- [ ] Register tool in `mcp-server/src/tools/index.js`
|
|
|
|
4. **Testing**:
|
|
- [ ] Write unit tests for the direct function wrapper
|
|
- [ ] Write integration tests for the MCP tool
|
|
|
|
## Standard Error Codes
|
|
|
|
- **Standard Error Codes**: Use consistent error codes across direct function wrappers
|
|
- `INPUT_VALIDATION_ERROR`: For missing or invalid required parameters
|
|
- `FILE_NOT_FOUND_ERROR`: For file system path issues
|
|
- `CORE_FUNCTION_ERROR`: For errors thrown by the core function
|
|
- `UNEXPECTED_ERROR`: For all other unexpected errors
|
|
|
|
- **Error Object Structure**:
|
|
```javascript
|
|
{
|
|
success: false,
|
|
error: {
|
|
code: 'ERROR_CODE',
|
|
message: 'Human-readable error message'
|
|
},
|
|
fromCache: false
|
|
}
|
|
```
|
|
|
|
- **MCP Tool Logging Pattern**:
|
|
- ✅ DO: Log the start of execution with arguments (sanitized if sensitive)
|
|
- ✅ DO: Log successful completion with result summary
|
|
- ✅ DO: Log all error conditions with appropriate log levels
|
|
- ✅ DO: Include the cache status in result logs
|
|
- ❌ DON'T: Log entire large data structures or sensitive information
|
|
|
|
- The MCP server integrates with Task Master core functions through three layers:
|
|
1. Tool Definitions (`mcp-server/src/tools/*.js`) - Define parameters and execute methods
|
|
2. Direct Function Wrappers (`task-master-core.js`) - Handle validation, path resolution, and caching
|
|
3. Core Logic Functions (various modules) - Implement actual functionality
|
|
|
|
- This layered approach provides:
|
|
- Clear separation of concerns
|
|
- Consistent parameter validation
|
|
- Centralized error handling
|
|
- Performance optimization through caching (for read operations)
|
|
- Standardized response formatting
|
|
|
|
## MCP Naming Conventions
|
|
|
|
- **Files and Directories**:
|
|
- ✅ DO: Use **kebab-case** for all file names: `list-tasks.js`, `set-task-status.js`
|
|
- ✅ DO: Use consistent directory structure: `mcp-server/src/tools/` for tool definitions, `mcp-server/src/core/direct-functions/` for direct function implementations
|
|
|
|
- **JavaScript Functions**:
|
|
- ✅ DO: Use **camelCase** with `Direct` suffix for direct function implementations: `listTasksDirect`, `setTaskStatusDirect`
|
|
- ✅ DO: Use **camelCase** with `Tool` suffix for tool registration functions: `registerListTasksTool`, `registerSetTaskStatusTool`
|
|
- ✅ DO: Use consistent action function naming inside direct functions: `coreActionFn` or similar descriptive name
|
|
|
|
- **MCP Tool Names**:
|
|
- ✅ DO: Use **snake_case** for tool names exposed to MCP clients: `list_tasks`, `set_task_status`, `parse_prd_document`
|
|
- ✅ DO: Include the core action in the tool name without redundant words: Use `list_tasks` instead of `list_all_tasks`
|
|
|
|
- **Examples**:
|
|
- File: `list-tasks.js`
|
|
- Direct Function: `listTasksDirect`
|
|
- Tool Registration: `registerListTasksTool`
|
|
- MCP Tool Name: `list_tasks`
|
|
|
|
- **Mapping**:
|
|
- The `directFunctions` map in `task-master-core.js` maps the core function name (in camelCase) to its direct implementation:
|
|
```javascript
|
|
export const directFunctions = {
|
|
list: listTasksDirect,
|
|
setStatus: setTaskStatusDirect,
|
|
// Add more functions as implemented
|
|
};
|
|
```
|