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)
Behavior3/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

With no annotations provided, the description carries the full burden. It discloses that the tool returns an array of tasks and can save output to a file or return JSON directly, which adds useful behavioral context. However, it lacks details on error handling, file format requirements, or performance aspects like rate limits.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is front-loaded and concise, consisting of two sentences that efficiently convey the tool's purpose and output usage. Every sentence earns its place by providing essential information without redundancy or unnecessary details.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

Given the tool's moderate complexity (file conversion with two parameters) and no output schema, the description is mostly complete. It explains the conversion process and output format, but could benefit from mentioning potential errors or input validation. The lack of annotations means it adequately covers the basics but leaves some behavioral gaps.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is 100%, so the schema already documents both parameters thoroughly. The description adds no additional meaning beyond what the schema provides, such as examples or constraints on file paths. The baseline score of 3 is appropriate as the schema does the heavy lifting.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description clearly states the specific action ('Converts markdown task files') and the target format ('Claude Code MCP-compatible JSON format'), distinguishing it from sibling tools like 'claude_code' (which executes tasks) and 'health' (likely a status check). It uses precise verbs and identifies the resource being transformed.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The description provides clear context for usage by mentioning that the output can be used with 'claude_code', implying this tool prepares data for execution. However, it does not explicitly state when not to use it or name alternatives, such as whether other tools handle different file formats or if direct JSON input is possible.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

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