feat(mcp): Refactor MCP tools for direct function calls & add docs

This commit introduces a major refactoring of the MCP server implementation to prioritize direct function calls over CLI execution, enhancing performance and reliability. It also includes substantial updates to documentation for consistency and interlinking.

**MCP Server & Core Logic Refactoring:**

1.  **Introduce Direct Function Wrappers ():**
    *   Created  to house direct wrappers for core Task Master functions (imported from ).
    *   Implemented  as the first wrapper, calling .
    *   Added  utility within  to centralize  file location logic, removing duplication.
    *   Established the  map for registering these wrappers.

2.  **Enhance MCP Utilities ():**
    *   Added : A primary utility function to streamline MCP tool  methods. It handles logging, argument processing (incl. project root normalization), calling the direct action function (e.g., ), processing results via , and formatting the final MCP response.
    *   Added : Standardizes processing of  objects returned by direct function wrappers.
    *   Added : Filters sensitive/large fields (like , ) from responses sent to the MCP client.
    *   Added , ,  to support the new workflow.
    *   Refactored  to use  internally, simplifying its usage (though it's now primarily a fallback).

3.  **Update MCP Tools (, ):**
    *   Refactored  to use  with , significantly simplifying the tool's  method.
    *   Updated  (initially) to use the improved  (Note: further refactoring to use a direct wrapper for  would follow the  pattern).

**Documentation Enhancements:**

4.  **Comprehensive Interlinking:** Added  links across rule files (, , , , , ) to connect related guidelines, improving navigation.

5.  **Standardize CLI Syntax ():** Removed legacy ℹ️ Initialized Perplexity client with OpenAI compatibility layer examples, reinforcing ℹ️ Initialized Perplexity client with OpenAI compatibility layer
  _____         _      __  __           _
 |_   _|_ _ ___| | __ |  \/  | __ _ ___| |_ ___ _ __
   | |/ _` / __| |/ / | |\/| |/ _` / __| __/ _ \ '__|
   | | (_| \__ \   <  | |  | | (_| \__ \ ||  __/ |
   |_|\__,_|___/_|\_\ |_|  |_|\__,_|___/\__\___|_|

by https://x.com/eyaltoledano
╭────────────────────────────────────────────╮
│                                            │
│   Version: 0.9.30   Project: Task Master   │
│                                            │
╰────────────────────────────────────────────╯

╭─────────────────────╮
│                     │
│   Task Master CLI   │
│                     │
╰─────────────────────╯

╭───────────────────╮
│  Task Generation  │
╰───────────────────╯
    parse-prd                 --input=<file.txt> [--tasks=10]          Generate tasks from a PRD document
    generate                                                           Create individual task files from tasks…

╭───────────────────╮
│  Task Management  │
╰───────────────────╯
    list                      [--status=<status>] [--with-subtas…      List all tasks with their status
    set-status                --id=<id> --status=<status>              Update task status (done, pending, etc.)
    update                    --from=<id> --prompt="<context>"         Update tasks based on new requirements
    add-task                  --prompt="<text>" [--dependencies=…      Add a new task using AI
    add-dependency            --id=<id> --depends-on=<id>              Add a dependency to a task
    remove-dependency         --id=<id> --depends-on=<id>              Remove a dependency from a task

╭──────────────────────────╮
│  Task Analysis & Detail  │
╰──────────────────────────╯
    analyze-complexity        [--research] [--threshold=5]             Analyze tasks and generate expansion re…
    complexity-report         [--file=<path>]                          Display the complexity analysis report
    expand                    --id=<id> [--num=5] [--research] […      Break down tasks into detailed subtasks
    expand --all              [--force] [--research]                   Expand all pending tasks with subtasks
    clear-subtasks            --id=<id>                                Remove subtasks from specified tasks

╭─────────────────────────────╮
│  Task Navigation & Viewing  │
╰─────────────────────────────╯
    next                                                               Show the next task to work on based on …
    show                      <id>                                     Display detailed information about a sp…

╭─────────────────────────╮
│  Dependency Management  │
╰─────────────────────────╯
    validate-dependenci…                                               Identify invalid dependencies without f…
    fix-dependencies                                                   Fix invalid dependencies automatically

╭─────────────────────────╮
│  Environment Variables  │
╰─────────────────────────╯
    ANTHROPIC_API_KEY              Your Anthropic API key                             Required
    MODEL                          Claude model to use                                Default: claude-3-7-sonn…
    MAX_TOKENS                     Maximum tokens for responses                       Default: 4000
    TEMPERATURE                    Temperature for model responses                    Default: 0.7
    PERPLEXITY_API_KEY             Perplexity API key for research                    Optional
    PERPLEXITY_MODEL               Perplexity model to use                            Default: sonar-pro
    DEBUG                          Enable debug logging                               Default: false
    LOG_LEVEL                      Console output level (debug,info,warn,error)       Default: info
    DEFAULT_SUBTASKS               Default number of subtasks to generate             Default: 3
    DEFAULT_PRIORITY               Default task priority                              Default: medium
    PROJECT_NAME                   Project name displayed in UI                       Default: Task Master

  _____         _      __  __           _
 |_   _|_ _ ___| | __ |  \/  | __ _ ___| |_ ___ _ __
   | |/ _` / __| |/ / | |\/| |/ _` / __| __/ _ \ '__|
   | | (_| \__ \   <  | |  | | (_| \__ \ ||  __/ |
   |_|\__,_|___/_|\_\ |_|  |_|\__,_|___/\__\___|_|

by https://x.com/eyaltoledano
╭────────────────────────────────────────────╮
│                                            │
│   Version: 0.9.30   Project: Task Master   │
│                                            │
╰────────────────────────────────────────────╯

╭─────────────────────╮
│                     │
│   Task Master CLI   │
│                     │
╰─────────────────────╯

╭───────────────────╮
│  Task Generation  │
╰───────────────────╯
    parse-prd                 --input=<file.txt> [--tasks=10]          Generate tasks from a PRD document
    generate                                                           Create individual task files from tasks…

╭───────────────────╮
│  Task Management  │
╰───────────────────╯
    list                      [--status=<status>] [--with-subtas…      List all tasks with their status
    set-status                --id=<id> --status=<status>              Update task status (done, pending, etc.)
    update                    --from=<id> --prompt="<context>"         Update tasks based on new requirements
    add-task                  --prompt="<text>" [--dependencies=…      Add a new task using AI
    add-dependency            --id=<id> --depends-on=<id>              Add a dependency to a task
    remove-dependency         --id=<id> --depends-on=<id>              Remove a dependency from a task

╭──────────────────────────╮
│  Task Analysis & Detail  │
╰──────────────────────────╯
    analyze-complexity        [--research] [--threshold=5]             Analyze tasks and generate expansion re…
    complexity-report         [--file=<path>]                          Display the complexity analysis report
    expand                    --id=<id> [--num=5] [--research] […      Break down tasks into detailed subtasks
    expand --all              [--force] [--research]                   Expand all pending tasks with subtasks
    clear-subtasks            --id=<id>                                Remove subtasks from specified tasks

╭─────────────────────────────╮
│  Task Navigation & Viewing  │
╰─────────────────────────────╯
    next                                                               Show the next task to work on based on …
    show                      <id>                                     Display detailed information about a sp…

╭─────────────────────────╮
│  Dependency Management  │
╰─────────────────────────╯
    validate-dependenci…                                               Identify invalid dependencies without f…
    fix-dependencies                                                   Fix invalid dependencies automatically

╭─────────────────────────╮
│  Environment Variables  │
╰─────────────────────────╯
    ANTHROPIC_API_KEY              Your Anthropic API key                             Required
    MODEL                          Claude model to use                                Default: claude-3-7-sonn…
    MAX_TOKENS                     Maximum tokens for responses                       Default: 4000
    TEMPERATURE                    Temperature for model responses                    Default: 0.7
    PERPLEXITY_API_KEY             Perplexity API key for research                    Optional
    PERPLEXITY_MODEL               Perplexity model to use                            Default: sonar-pro
    DEBUG                          Enable debug logging                               Default: false
    LOG_LEVEL                      Console output level (debug,info,warn,error)       Default: info
    DEFAULT_SUBTASKS               Default number of subtasks to generate             Default: 3
    DEFAULT_PRIORITY               Default task priority                              Default: medium
    PROJECT_NAME                   Project name displayed in UI                       Default: Task Master       as the primary CLI.

6.  **Add MCP Architecture & Workflow Sections:** Added detailed sections in  and  explaining MCP server structure and the workflow for adding new MCP tool integrations using the direct function pattern.

7.  **Clarify MCP Role:** Updated  and  to better explain the MCP server's role and its specific utilities.

Overall, this establishes a cleaner, more performant, and maintainable pattern for integrating Task Master functionality with the MCP server, supported by improved documentation.
This commit is contained in:
Eyal Toledano
2025-03-30 00:29:12 -04:00
parent a5370ebdb7
commit cd4f4e66d7
13 changed files with 2932 additions and 97 deletions

View File

@@ -0,0 +1,191 @@
/**
* Integration test for direct function imports in MCP server
*/
import { jest } from '@jest/globals';
import path from 'path';
import fs from 'fs';
import { fileURLToPath } from 'url';
import { dirname } from 'path';
// Get the current module's directory
const __filename = fileURLToPath(import.meta.url);
const __dirname = dirname(__filename);
// Import the direct functions
import { listTasksDirect } from '../../../mcp-server/src/core/task-master-core.js';
// Mock logger
const mockLogger = {
info: jest.fn(),
error: jest.fn(),
debug: jest.fn(),
warn: jest.fn()
};
// Test file paths
const testProjectRoot = path.join(__dirname, '../../fixtures/test-project');
const testTasksPath = path.join(testProjectRoot, 'tasks.json');
describe('MCP Server Direct Functions', () => {
// Create test data before tests
beforeAll(() => {
// Create test directory if it doesn't exist
if (!fs.existsSync(testProjectRoot)) {
fs.mkdirSync(testProjectRoot, { recursive: true });
}
// Create a sample tasks.json file for testing
const sampleTasks = {
meta: {
projectName: 'Test Project',
version: '1.0.0'
},
tasks: [
{
id: 1,
title: 'Task 1',
description: 'First task',
status: 'done',
dependencies: [],
priority: 'high'
},
{
id: 2,
title: 'Task 2',
description: 'Second task',
status: 'in-progress',
dependencies: [1],
priority: 'medium',
subtasks: [
{
id: 1,
title: 'Subtask 2.1',
description: 'First subtask',
status: 'done'
},
{
id: 2,
title: 'Subtask 2.2',
description: 'Second subtask',
status: 'pending'
}
]
},
{
id: 3,
title: 'Task 3',
description: 'Third task',
status: 'pending',
dependencies: [1, 2],
priority: 'low'
}
]
};
fs.writeFileSync(testTasksPath, JSON.stringify(sampleTasks, null, 2));
});
// Clean up after tests
afterAll(() => {
// Remove test tasks file
if (fs.existsSync(testTasksPath)) {
fs.unlinkSync(testTasksPath);
}
// Try to remove the directory (will only work if empty)
try {
fs.rmdirSync(testProjectRoot);
} catch (error) {
// Ignore errors if the directory isn't empty
}
});
// Reset mocks before each test
beforeEach(() => {
jest.clearAllMocks();
});
describe('listTasksDirect', () => {
test('should return all tasks when no filter is provided', async () => {
// Arrange
const args = {
projectRoot: testProjectRoot,
file: testTasksPath
};
// Act
const result = await listTasksDirect(args, mockLogger);
// Assert
expect(result.success).toBe(true);
expect(result.data.tasks.length).toBe(3);
expect(result.data.stats.total).toBe(3);
expect(result.data.stats.completed).toBe(1);
expect(result.data.stats.inProgress).toBe(1);
expect(result.data.stats.pending).toBe(1);
expect(mockLogger.info).toHaveBeenCalled();
});
test('should filter tasks by status', async () => {
// Arrange
const args = {
projectRoot: testProjectRoot,
file: testTasksPath,
status: 'pending'
};
// Act
const result = await listTasksDirect(args, mockLogger);
// Assert
expect(result.success).toBe(true);
expect(result.data.tasks.length).toBe(1);
expect(result.data.tasks[0].id).toBe(3);
expect(result.data.filter).toBe('pending');
});
test('should include subtasks when requested', async () => {
// Arrange
const args = {
projectRoot: testProjectRoot,
file: testTasksPath,
withSubtasks: true
};
// Act
const result = await listTasksDirect(args, mockLogger);
// Assert
expect(result.success).toBe(true);
// Verify subtasks are included
const taskWithSubtasks = result.data.tasks.find(t => t.id === 2);
expect(taskWithSubtasks.subtasks).toBeDefined();
expect(taskWithSubtasks.subtasks.length).toBe(2);
// Verify subtask details
expect(taskWithSubtasks.subtasks[0].id).toBe(1);
expect(taskWithSubtasks.subtasks[0].title).toBe('Subtask 2.1');
expect(taskWithSubtasks.subtasks[0].status).toBe('done');
});
test('should handle errors gracefully', async () => {
// Arrange
const args = {
projectRoot: testProjectRoot,
file: 'non-existent-file.json'
};
// Act
const result = await listTasksDirect(args, mockLogger);
// Assert
expect(result.success).toBe(false);
expect(result.error).toBeDefined();
expect(result.error.code).toBeDefined();
expect(result.error.message).toBeDefined();
expect(mockLogger.error).toHaveBeenCalled();
});
});
});