Files
claude-task-master/docs/MCP_INTEGRATION.md

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