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
| Name | Required | Description | Default |
|---|---|---|---|
| markdownPath | Yes | Path to the markdown task file to convert. | |
| outputPath | No | Optional path where to save the JSON output. If not provided, returns the JSON directly. |
Implementation Reference
- src/server.ts:458-567 (handler)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'], }, },
- src/server.ts:302-315 (schema)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'], },
- docs/task_converter.py:260-349 (helper)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)
- docs/task_converter.py:545-603 (helper)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)