Skip to main content
Glama

validate_markdown

Read-onlyIdempotent

Pre-validate markdown to catch malformed tables, unclosed code fences, and broken task lists before conversion, returning a safety status and detected features.

Instructions

Pre-flight markdown validation BEFORE conversion. Catches malformed tables (mismatched pipes), unclosed code fences, broken task lists, and unsupported syntax. Returns a green/amber/red status plus the detected markdown features.

CALL THIS PROACTIVELY when:

  • The user is about to convert a long document (>5 pages) — validating first is cheap; running a doomed conversion costs credits

  • The user reports a previous conversion produced broken output

  • You generated the markdown yourself and want to verify it's clean before spending credits

Returns: status (green=safe, amber=minor issues, red=will likely break), detected features (tables, code blocks, task lists, math), and a human-readable message.

Input Schema

TableJSON Schema
NameRequiredDescriptionDefault
contentYesMarkdown content to validate
filenameNoOptional filename label for the response (defaults to 'content.md')

Output Schema

TableJSON Schema
NameRequiredDescriptionDefault
filenameNoFilename label echoed back
statusYesValidation verdict
messageYesHuman-readable explanation of any issues
inputFormatNoDetected markdown flavour (e.g. gfm, commonmark)
additionalPandocFlagsNoPandoc flags that will be applied
detectedFeaturesNoMap of markdown features found in the content

Implementation Reference

  • Main handler function for the validate_markdown tool. Validates markdown content via the API client, interprets the result (green/amber/red status), and returns a formatted human-readable response with recommendations.
    export async function handleValidateMarkdown(
      apiClient: MDMagicApiClient,
      args: any
    ): Promise<CallToolResult> {
      try {
        const input = validateMarkdownSchema.parse(args);
        console.error(`[validate_markdown] Validating ${input.content.length} bytes...`);
    
        const result = await apiClient.validateMarkdownContent(input.content, input.filename);
    
        const emoji = STATUS_EMOJI[result.status] || '❓';
        const detectedList = Object.entries(result.detectedFeatures || {})
          .filter(([, v]) => v)
          .map(([k]) => k);
    
        const lines = [
          `${emoji} **Markdown validation: ${result.status.toUpperCase()}**`,
          '',
          `**File**: ${result.filename}`,
          `**Detected format**: ${result.inputFormat || 'unknown'}`,
          `**Message**: ${result.message}`,
        ];
    
        if (detectedList.length > 0) {
          lines.push('', `**Features detected**: ${detectedList.join(', ')}`);
        }
    
        if (result.status === 'red') {
          lines.push('', '⚠️ **Recommendation**: Fix the issues above before calling `convert_document` — a red status usually produces broken output and still costs credits.');
        } else if (result.status === 'amber') {
          lines.push('', 'ℹ️ Conversion will work but may have minor rendering issues. Safe to proceed.');
        } else {
          lines.push('', '✅ Ready for conversion. Call `convert_document` next.');
        }
    
        return {
          content: [{ type: 'text', text: lines.join('\n') }]
        };
      } catch (error: any) {
        console.error('[validate_markdown] Error:', error.message);
        throw error;
      }
    }
  • Zod schema defining the input for validate_markdown: content (required string) and filename (optional string).
    export const validateMarkdownSchema = z.object({
      content: z.string().describe('Markdown content to validate'),
      filename: z.string().optional().describe('Optional filename for the response label')
    });
  • API client method validateMarkdownContent that POSTs the content to /api/validate-markdown/content endpoint and returns the validation result (status, message, inputFormat, detectedFeatures, etc.).
    async validateMarkdownContent(content: string, filename?: string): Promise<{
      filename: string;
      status: 'green' | 'amber' | 'red' | string;
      message: string;
      inputFormat: string | null;
      additionalPandocFlags: string[];
      detectedFeatures: Record<string, any>;
    }> {
      const response: AxiosResponse = await this._client.post('/api/validate-markdown/content', {
        content,
        filename: filename || 'content.md'
      });
      return response.data;
    }
  • Registration of validate_markdown in the unified tool dispatcher switch-case, routing requests to handleValidateMarkdown.
    case 'validate_markdown':
      return await handleValidateMarkdown(apiClient, request.params.arguments);
  • src/index.ts:297-332 (registration)
    Tool registration metadata including name, description (with proactive usage guidance), annotations, inputSchema, and outputSchema for the MCP server capabilities listing.
    {
      name: "validate_markdown",
      description: "Pre-flight markdown validation BEFORE conversion. Catches malformed tables (mismatched pipes), unclosed code fences, broken task lists, and unsupported syntax. Returns a green/amber/red status plus the detected markdown features.\n\nCALL THIS PROACTIVELY when:\n- The user is about to convert a long document (>5 pages) — validating first is cheap; running a doomed conversion costs credits\n- The user reports a previous conversion produced broken output\n- You generated the markdown yourself and want to verify it's clean before spending credits\n\nReturns: status (green=safe, amber=minor issues, red=will likely break), detected features (tables, code blocks, task lists, math), and a human-readable message.",
      annotations: {
        title: "Validate markdown before conversion",
        readOnlyHint: true,
        destructiveHint: false,
        idempotentHint: true,
        openWorldHint: false
      },
      inputSchema: {
        type: "object" as const,
        properties: {
          content: {
            type: "string",
            description: "Markdown content to validate"
          },
          filename: {
            type: "string",
            description: "Optional filename label for the response (defaults to 'content.md')"
          }
        },
        required: ["content"]
      },
      outputSchema: {
        type: "object" as const,
        properties: {
          filename: { type: "string", description: "Filename label echoed back" },
          status: { type: "string", enum: ["green", "amber", "red"], description: "Validation verdict" },
          message: { type: "string", description: "Human-readable explanation of any issues" },
          inputFormat: { type: ["string", "null"], description: "Detected markdown flavour (e.g. gfm, commonmark)" },
          additionalPandocFlags: { type: "array", items: { type: "string" }, description: "Pandoc flags that will be applied" },
          detectedFeatures: { type: "object", description: "Map of markdown features found in the content" }
        },
        required: ["status", "message"]
      }
Behavior5/5

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

Beyond annotations (readOnly, idempotent), the description reveals that validation is cheap, returns a green/amber/red status plus detected features, and helps avoid costly conversion failures. No contradictions with annotations.

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

Conciseness4/5

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

The description is well-structured with a clear opening, bulleted usage guidelines, and a return summary. It is appropriately sized but could be slightly more concise without losing value.

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

Completeness5/5

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

For a simple validation tool with full schema coverage and an output schema, the description covers purpose, when to use, what it detects, and what it returns. No missing critical information.

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 coverage is 100%, so the description adds minimal extra meaning to parameters. It does not elaborate on the content or filename beyond what the schema already specifies, but the return value description compensates slightly.

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 'Pre-flight markdown validation BEFORE conversion' and lists specific issues caught (malformed tables, unclosed code fences, etc.). It distinguishes itself from sibling tools like convert_document, which performs the actual conversion.

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

Usage Guidelines5/5

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

The description explicitly provides three scenarios when to call the tool proactively: before converting a long document, after broken output, and when verifying self-generated markdown. It contrasts with the cost of a failed conversion, offering clear guidance.

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/MDMagic-MCP/mdmagic-mcp-server'

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