Files
claude-task-master/context/MCP_INTEGRATION.md
2025-04-09 00:30:05 +02:00

7.8 KiB

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:

/**
 * 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:

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

// 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

// 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

// In mcp-server/src/tools/utils.js
const commandMap = {
	// ... existing mappings
	'new-feature': 'newFeature'
};

Tool Implementation

// 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

// 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:

// 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