269 lines
8.1 KiB
Markdown
269 lines
8.1 KiB
Markdown
# Task Master MCP Integration
|
|
|
|
This document outlines how Task Master CLI functionality is integrated with MCP (Master Control Program) architecture to provide both CLI and programmatic API access to features.
|
|
|
|
## Architecture Overview
|
|
|
|
The MCP integration uses a layered approach:
|
|
|
|
1. **Core Functions** - In `scripts/modules/` contain the main business logic
|
|
2. **Source Parameter** - Core functions check the `source` parameter to determine behavior
|
|
3. **Task Master Core** - In `mcp-server/src/core/task-master-core.js` provides direct function imports
|
|
4. **MCP Tools** - In `mcp-server/src/tools/` register the functions with the MCP server
|
|
|
|
```
|
|
┌─────────────────┐ ┌─────────────────┐
|
|
│ CLI User │ │ MCP User │
|
|
└────────┬────────┘ └────────┬────────┘
|
|
│ │
|
|
▼ ▼
|
|
┌────────────────┐ ┌────────────────────┐
|
|
│ commands.js │ │ MCP Tool API │
|
|
└────────┬───────┘ └──────────┬─────────┘
|
|
│ │
|
|
│ │
|
|
▼ ▼
|
|
┌───────────────────────────────────────────────┐
|
|
│ │
|
|
│ Core Modules (task-manager.js, etc.) │
|
|
│ │
|
|
└───────────────────────────────────────────────┘
|
|
```
|
|
|
|
## Core Function Pattern
|
|
|
|
Core functions should follow this pattern to support both CLI and MCP use:
|
|
|
|
```javascript
|
|
/**
|
|
* Example function with source parameter support
|
|
* @param {Object} options - Additional options including source
|
|
* @returns {Object|undefined} - Returns data when source is 'mcp'
|
|
*/
|
|
function exampleFunction(param1, param2, options = {}) {
|
|
try {
|
|
// Skip UI for MCP
|
|
if (options.source !== 'mcp') {
|
|
displayBanner();
|
|
console.log(chalk.blue('Processing operation...'));
|
|
}
|
|
|
|
// Do the core business logic
|
|
const result = doSomething(param1, param2);
|
|
|
|
// For MCP, return structured data
|
|
if (options.source === 'mcp') {
|
|
return {
|
|
success: true,
|
|
data: result
|
|
};
|
|
}
|
|
|
|
// For CLI, display output
|
|
console.log(chalk.green('Operation completed successfully!'));
|
|
} catch (error) {
|
|
// Handle errors based on source
|
|
if (options.source === 'mcp') {
|
|
return {
|
|
success: false,
|
|
error: error.message
|
|
};
|
|
}
|
|
|
|
// CLI error handling
|
|
console.error(chalk.red(`Error: ${error.message}`));
|
|
process.exit(1);
|
|
}
|
|
}
|
|
```
|
|
|
|
## Source-Adapter Utilities
|
|
|
|
For convenience, you can use the source adapter helpers in `scripts/modules/source-adapter.js`:
|
|
|
|
```javascript
|
|
import { adaptForMcp, sourceSplitFunction } from './source-adapter.js';
|
|
|
|
// Simple adaptation - just adds source parameter support
|
|
export const simpleFunction = adaptForMcp(originalFunction);
|
|
|
|
// Split implementation - completely different code paths for CLI vs MCP
|
|
export const complexFunction = sourceSplitFunction(
|
|
// CLI version with UI
|
|
function(param1, param2) {
|
|
displayBanner();
|
|
console.log(`Processing ${param1}...`);
|
|
// ... CLI implementation
|
|
},
|
|
// MCP version with structured return
|
|
function(param1, param2, options = {}) {
|
|
// ... MCP implementation
|
|
return { success: true, data };
|
|
}
|
|
);
|
|
```
|
|
|
|
## Adding New Features
|
|
|
|
When adding new features, follow these steps to ensure CLI and MCP compatibility:
|
|
|
|
1. **Implement Core Logic** in the appropriate module file
|
|
2. **Add Source Parameter Support** using the pattern above
|
|
3. **Add to task-master-core.js** to make it available for direct import
|
|
4. **Update Command Map** in `mcp-server/src/tools/utils.js`
|
|
5. **Create Tool Implementation** in `mcp-server/src/tools/`
|
|
6. **Register the Tool** in `mcp-server/src/tools/index.js`
|
|
|
|
### Core Function Implementation
|
|
|
|
```javascript
|
|
// In scripts/modules/task-manager.js
|
|
export async function newFeature(param1, param2, options = {}) {
|
|
try {
|
|
// Source-specific UI
|
|
if (options.source !== 'mcp') {
|
|
displayBanner();
|
|
console.log(chalk.blue('Running new feature...'));
|
|
}
|
|
|
|
// Shared core logic
|
|
const result = processFeature(param1, param2);
|
|
|
|
// Source-specific return handling
|
|
if (options.source === 'mcp') {
|
|
return {
|
|
success: true,
|
|
data: result
|
|
};
|
|
}
|
|
|
|
// CLI output
|
|
console.log(chalk.green('Feature completed successfully!'));
|
|
displayOutput(result);
|
|
} catch (error) {
|
|
// Error handling based on source
|
|
if (options.source === 'mcp') {
|
|
return {
|
|
success: false,
|
|
error: error.message
|
|
};
|
|
}
|
|
|
|
console.error(chalk.red(`Error: ${error.message}`));
|
|
process.exit(1);
|
|
}
|
|
}
|
|
```
|
|
|
|
### Task Master Core Update
|
|
|
|
```javascript
|
|
// In mcp-server/src/core/task-master-core.js
|
|
import { newFeature } from '../../../scripts/modules/task-manager.js';
|
|
|
|
// Add to exports
|
|
export default {
|
|
// ... existing functions
|
|
|
|
async newFeature(args = {}, options = {}) {
|
|
const { param1, param2 } = args;
|
|
return executeFunction(newFeature, [param1, param2], options);
|
|
}
|
|
};
|
|
```
|
|
|
|
### Command Map Update
|
|
|
|
```javascript
|
|
// In mcp-server/src/tools/utils.js
|
|
const commandMap = {
|
|
// ... existing mappings
|
|
'new-feature': 'newFeature'
|
|
};
|
|
```
|
|
|
|
### Tool Implementation
|
|
|
|
```javascript
|
|
// In mcp-server/src/tools/newFeature.js
|
|
import { z } from "zod";
|
|
import {
|
|
executeTaskMasterCommand,
|
|
createContentResponse,
|
|
createErrorResponse,
|
|
} from "./utils.js";
|
|
|
|
export function registerNewFeatureTool(server) {
|
|
server.addTool({
|
|
name: "newFeature",
|
|
description: "Run the new feature",
|
|
parameters: z.object({
|
|
param1: z.string().describe("First parameter"),
|
|
param2: z.number().optional().describe("Second parameter"),
|
|
file: z.string().optional().describe("Path to the tasks file"),
|
|
projectRoot: z.string().describe("Root directory of the project")
|
|
}),
|
|
execute: async (args, { log }) => {
|
|
try {
|
|
log.info(`Running new feature with args: ${JSON.stringify(args)}`);
|
|
|
|
const cmdArgs = [];
|
|
if (args.param1) cmdArgs.push(`--param1=${args.param1}`);
|
|
if (args.param2) cmdArgs.push(`--param2=${args.param2}`);
|
|
if (args.file) cmdArgs.push(`--file=${args.file}`);
|
|
|
|
const projectRoot = args.projectRoot;
|
|
|
|
// Execute the command
|
|
const result = await executeTaskMasterCommand(
|
|
"new-feature",
|
|
log,
|
|
cmdArgs,
|
|
projectRoot
|
|
);
|
|
|
|
if (!result.success) {
|
|
throw new Error(result.error);
|
|
}
|
|
|
|
return createContentResponse(result.stdout);
|
|
} catch (error) {
|
|
log.error(`Error in new feature: ${error.message}`);
|
|
return createErrorResponse(`Error in new feature: ${error.message}`);
|
|
}
|
|
},
|
|
});
|
|
}
|
|
```
|
|
|
|
### Tool Registration
|
|
|
|
```javascript
|
|
// In mcp-server/src/tools/index.js
|
|
import { registerNewFeatureTool } from "./newFeature.js";
|
|
|
|
export function registerTaskMasterTools(server) {
|
|
// ... existing registrations
|
|
registerNewFeatureTool(server);
|
|
}
|
|
```
|
|
|
|
## Testing
|
|
|
|
Always test your MCP-compatible features with both CLI and MCP interfaces:
|
|
|
|
```javascript
|
|
// Test CLI usage
|
|
node scripts/dev.js new-feature --param1=test --param2=123
|
|
|
|
// Test MCP usage
|
|
node mcp-server/tests/test-command.js newFeature
|
|
```
|
|
|
|
## Best Practices
|
|
|
|
1. **Keep Core Logic DRY** - Share as much logic as possible between CLI and MCP
|
|
2. **Structured Data for MCP** - Return clean JSON objects from MCP source functions
|
|
3. **Consistent Error Handling** - Standardize error formats for both interfaces
|
|
4. **Documentation** - Update MCP tool documentation when adding new features
|
|
5. **Testing** - Test both CLI and MCP interfaces for any new or modified feature |