Skip to main content
Glama

convert_task_markdown

Convert markdown task files to Claude Code MCP-compatible JSON format for execution by AI agents in the MeshSeeks distributed network.

Instructions

Converts markdown task files into Claude Code MCP-compatible JSON format. Returns an array of tasks that can be executed using the claude_code tool.

Input Schema

TableJSON Schema
NameRequiredDescriptionDefault
markdownPathYesPath to the markdown task file to convert.
outputPathNoOptional path where to save the JSON output. If not provided, returns the JSON directly.

Implementation Reference

  • MCP tool handler for 'convert_task_markdown'. Extracts parameters, executes task_converter.py Python script via spawnAsync, processes output/errors, returns JSON tasks or error.
    if (toolName === 'convert_task_markdown') {
      const toolArguments = args.params.arguments;
      
      // Extract markdownPath (required)
      let markdownPath: string;
      if (
        toolArguments &&
        typeof toolArguments === 'object' &&
        'markdownPath' in toolArguments &&
        typeof toolArguments.markdownPath === 'string'
      ) {
        markdownPath = toolArguments.markdownPath;
      } else {
        throw new McpError(ErrorCode.InvalidParams, 'Missing or invalid required parameter: markdownPath for convert_task_markdown tool');
      }
      
      // Extract outputPath (optional)
      let outputPath: string | undefined;
      if (toolArguments.outputPath && typeof toolArguments.outputPath === 'string') {
        outputPath = toolArguments.outputPath;
      }
      
      debugLog(`[Debug] Converting markdown task file: ${markdownPath}`);
      
      let stderr = '';
      
      try {
        // Prepare command to run task_converter.py
        const pythonPath = 'python3';
        const converterPath = pathResolve(__dirname, '../docs/task_converter.py');
        
        // Use --json-output flag to get JSON to stdout
        const args = ['--json-output', markdownPath];
        
        const result = await spawnAsync(pythonPath, [converterPath, ...args], {
          cwd: homedir(),
          timeout: 30000 // 30 seconds timeout
        });
        
        const stdout = result.stdout;
        stderr = result.stderr;
        
        // Extract progress messages and actual errors
        const stderrLines = stderr.split('\n');
        const progressMessages = stderrLines.filter(line => line.includes('[Progress]'));
        const errorMessages = stderrLines.filter(line => !line.includes('[Progress]') && line.trim());
        
        // Log progress messages
        progressMessages.forEach(msg => {
          console.error(msg); // Send to client
          debugLog(msg);
        });
        
        if (errorMessages.length > 0) {
          stderr = errorMessages.join('\n');
          debugLog(`[Debug] Task converter stderr: ${stderr}`);
        }
        
        // Check if there was an error from the converter
        if (stderr && stderr.includes('Markdown format validation failed')) {
          // Return validation error as a structured response
          const validationError = {
            status: 'error',
            error: 'Markdown format validation failed',
            details: stderr,
            helpUrl: 'https://github.com/grahama1970/claude-code-mcp/blob/main/README.md#markdown-task-file-format'
          };
          
          this.activeRequests.delete(requestId);
          return { content: [{ type: 'text', text: JSON.stringify(validationError, null, 2) }] };
        }
        
        // Parse the JSON output
        const tasks = JSON.parse(stdout);
        
        // If outputPath is provided, also save to file
        if (outputPath) {
          await fs.writeFile(outputPath, JSON.stringify(tasks, null, 2));
          debugLog(`[Debug] Saved converted tasks to: ${outputPath}`);
        }
        
        // Return the converted tasks
        const response = {
          status: 'success',
          tasksCount: tasks.length,
          outputPath: outputPath || 'none',
          tasks: tasks
        };
        
        this.activeRequests.delete(requestId);
        return { content: [{ type: 'text', text: JSON.stringify(response, null, 2) }] };
        
      } catch (error) {
        this.activeRequests.delete(requestId);
        const errorMessage = error instanceof Error ? error.message : String(error);
        
        // Check if this is a JSON parsing error (indicating validation failure)
        if (errorMessage.includes('JSON') && stderr) {
          const validationError = {
            status: 'error',
            error: 'Task conversion failed',
            details: stderr || errorMessage,
            helpUrl: 'https://github.com/grahama1970/claude-code-mcp/blob/main/README.md#markdown-task-file-format'
          };
          return { content: [{ type: 'text', text: JSON.stringify(validationError, null, 2) }] };
        }
        
        throw new McpError(ErrorCode.InternalError, `Failed to convert markdown tasks: ${errorMessage}`);
      }
    }
  • src/server.ts:299-316 (registration)
    Registers the 'convert_task_markdown' tool in the ListTools response, including description and input schema.
    {
      name: 'convert_task_markdown',
      description: 'Converts markdown task files into Claude Code MCP-compatible JSON format. Returns an array of tasks that can be executed using the claude_code tool.',
      inputSchema: {
        type: 'object',
        properties: {
          markdownPath: {
            type: 'string',
            description: 'Path to the markdown task file to convert.',
          },
          outputPath: {
            type: 'string',
            description: 'Optional path where to save the JSON output. If not provided, returns the JSON directly.',
          },
        },
        required: ['markdownPath'],
      },
    },
  • Input schema definition for the convert_task_markdown tool, specifying markdownPath as required and outputPath as optional.
    inputSchema: {
      type: 'object',
      properties: {
        markdownPath: {
          type: 'string',
          description: 'Path to the markdown task file to convert.',
        },
        outputPath: {
          type: 'string',
          description: 'Optional path where to save the JSON output. If not provided, returns the JSON directly.',
        },
      },
      required: ['markdownPath'],
    },
  • Core helper function that parses markdown task file, validates structure, extracts sections (title, objective, requirements, validation tasks), builds prompts using build_validation_prompt, and formats into MCP-compatible task list.
    def process_markdown(input_file: str, progress_callback: Optional[callable] = None) -> List[Dict[str, Any]]:
        """
        Process a markdown file and extract validation tasks.
        
        Args:
            input_file: Path to the markdown file
            progress_callback: Optional callback for progress updates
            
        Returns:
            List of tasks in Claude Code MCP format
            
        Raises:
            ValueError: If markdown format is invalid or missing required sections
        """
        if progress_callback:
            progress_callback("Loading task file...")
        
        md = load_file(input_file)
        
        if progress_callback:
            progress_callback("Validating markdown structure...")
        
        # Validate markdown structure
        validation_errors = []
        
        # Extract and validate title
        title = extract_title(md)
        if title == "Untitled Task":
            validation_errors.append("Missing required title. Format: '# Task NNN: Title'")
        
        # Extract and validate objective
        objective = extract_objective(md)
        if not objective:
            validation_errors.append("Missing required 'Objective' section. Format: '## Objective\\nDescription'")
        
        # Extract and validate requirements
        requirements = extract_requirements(md)
        if not requirements:
            validation_errors.append("Missing or empty 'Requirements' section. Format: '## Requirements\\n1. [ ] Requirement'")
        
        # Extract and validate tasks
        validation_tasks = extract_validation_tasks(md)
        if not validation_tasks:
            validation_errors.append("No validation tasks found. Format: '- [ ] Validate `module.py`' with indented steps")
        
        # Check for task steps
        empty_tasks = []
        for module, block in validation_tasks:
            steps = extract_steps(block)
            if not steps:
                empty_tasks.append(module)
        
        if empty_tasks:
            validation_errors.append(f"Tasks without steps: {', '.join(empty_tasks)}. Each task needs indented steps")
        
        # If there are validation errors, raise exception with helpful message
        if validation_errors:
            error_msg = "Markdown format validation failed:\n"
            error_msg += "\n".join(f"  - {error}" for error in validation_errors)
            error_msg += "\n\nRequired markdown format:\n"
            error_msg += "# Task NNN: Title\n"
            error_msg += "## Objective\n"
            error_msg += "Clear description\n"
            error_msg += "## Requirements\n"
            error_msg += "1. [ ] First requirement\n"
            error_msg += "## Task Section\n"
            error_msg += "- [ ] Validate `file.py`\n"
            error_msg += "   - [ ] Step 1\n"
            error_msg += "   - [ ] Step 2\n"
            raise ValueError(error_msg)
        
        if progress_callback:
            progress_callback(f"Converting {len(validation_tasks)} validation tasks...")
        
        prompts = []
        for i, (module, block) in enumerate(validation_tasks, 1):
            if progress_callback:
                progress_callback(f"Task {i}/{len(validation_tasks)}: Converting {module}")
            
            steps = extract_steps(block)
            if not steps:
                continue  # skip if no steps found (already reported in validation)
            
            prompt = build_validation_prompt(title, objective, module, steps, requirements)
            prompts.append(prompt)
        
        if progress_callback:
            progress_callback("Conversion complete!")
        
        return format_tasks_for_mcp(prompts)
  • Entry point for the task_converter.py script. Handles --json-output mode for MCP integration by calling process_markdown and printing JSON to stdout, with progress to stderr.
    def main():
        """Main function to execute the script from command line."""
        # Check for --json-output flag for MCP integration
        json_output_mode = '--json-output' in sys.argv
        
        if json_output_mode:
            # Remove the flag from argv for processing
            sys.argv.remove('--json-output')
            
            # Expect only input file
            if len(sys.argv) != 2:
                print("Usage: python task_converter.py --json-output <input_markdown>", file=sys.stderr)
                sys.exit(1)
                
            input_file = sys.argv[1]
            
            # Validate input file
            if not os.path.isfile(input_file):
                print(f"Error: Input file '{input_file}' does not exist.", file=sys.stderr)
                sys.exit(1)
                
            try:
                # Process markdown and output JSON to stdout
                def progress_to_stderr(msg):
                    print(f"[Progress] {msg}", file=sys.stderr)
                
                tasks = process_markdown(input_file, progress_callback=progress_to_stderr)
                # Output JSON to stdout for MCP consumption
                print(json.dumps(tasks, indent=2))
                sys.exit(0)
            except Exception as e:
                print(f"Error during conversion: {str(e)}", file=sys.stderr)
                sys.exit(1)
        
        else:
            # Original file-based mode
            if len(sys.argv) < 3:
                print("Usage: python task_converter.py <input_markdown> <output_json>")
                print("   or: python task_converter.py --json-output <input_markdown>")
                sys.exit(1)
            
            input_file = sys.argv[1]
            output_file = sys.argv[2]
            
            success = convert_tasks(input_file, output_file)
            
            if success:
                print("\nJSON structure is compatible with Claude Code MCP format.")
                
                # Show example of how to use the output
                print("\nTo use this file with Claude Code MCP:")
                print("1. Configure your MCP server to use this JSON file")
                print("2. Start your MCP server with the command:")
                print(f"   claude mcp add arangodb-validation -- node /path/to/server.js '{output_file}'")
                print("3. The tasks will be available to Claude through the MCP server")
            else:
                print("\nTask conversion failed.")
                sys.exit(1)
Install Server

Other Tools

Latest Blog Posts

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/twalichiewicz/meshseeks'

If you have feedback or need assistance with the MCP directory API, please join our Discord server