Skip to main content
Glama

validate_documentation_metadata

Verify that documentation files include mandatory metadata fields by specifying the file path and required fields. Ensures compliance and completeness in document management.

Instructions

Ensure all documents have required metadata fields.

Input Schema

NameRequiredDescriptionDefault
basePathNo
pathNo
requiredFieldsNo

Input Schema (JSON Schema)

{ "$schema": "http://json-schema.org/draft-07/schema#", "additionalProperties": false, "properties": { "basePath": { "default": "", "type": "string" }, "path": { "type": "string" }, "requiredFields": { "items": { "type": "string" }, "type": "array" } }, "type": "object" }

Implementation Reference

  • The core handler method in DocumentHandler class that implements the tool logic: validates metadata in documentation files by parsing frontmatter and checking for required fields.
    async validateMetadata( basePath = "", requiredFields?: string[] ): Promise<ToolResponse> { try { const validBasePath = await this.validatePath(basePath || this.docsDir); // Default required fields if not specified const fields = requiredFields || ["title", "description", "status"]; // Find all markdown files const files = await glob("**/*.md", { cwd: validBasePath }); const missingMetadata: Array<{ file: string; missingFields: string[]; }> = []; // Check each file for metadata for (const file of files) { const filePath = path.join(validBasePath, file); const content = await fs.readFile(filePath, "utf-8"); // Parse frontmatter const { frontmatter } = parseFrontmatter(content); // Check for required fields const missing = fields.filter((field) => !frontmatter[field]); if (missing.length > 0) { missingMetadata.push({ file: path.relative(this.docsDir, filePath), missingFields: missing, }); } } // Calculate completeness percentage const totalFields = files.length * fields.length; const missingFields = missingMetadata.reduce( (sum, item) => sum + item.missingFields.length, 0 ); const completenessPercentage = totalFields > 0 ? Math.round(((totalFields - missingFields) / totalFields) * 100) : 100; return { content: [ { type: "text", text: missingMetadata.length > 0 ? `Found ${missingMetadata.length} files with missing metadata. Completeness: ${completenessPercentage}%` : `All ${files.length} files have complete metadata. Completeness: 100%`, }, ], metadata: { missingMetadata, filesChecked: files.length, requiredFields: fields, completenessPercentage, basePath: path.relative(this.docsDir, validBasePath), }, }; } catch (error) { const errorMessage = error instanceof Error ? error.message : String(error); return { content: [ { type: "text", text: `Error validating metadata: ${errorMessage}` }, ], isError: true, }; }
  • Zod schema defining the input parameters for the validate_documentation_metadata tool: basePath and optional requiredFields array.
    export const ValidateMetadataSchema = ToolInputSchema.extend({ basePath: z.string().optional().default(""), requiredFields: z.array(z.string()).optional(), });
  • src/index.ts:291-294 (registration)
    Tool registration in the ListToolsRequestHandler, specifying name, description, and input schema.
    name: "validate_documentation_metadata", description: "Ensure all documents have required metadata fields.", inputSchema: zodToJsonSchema(ValidateMetadataSchema) as any, },
  • src/index.ts:483-494 (registration)
    Dispatch case in CallToolRequestHandler that parses input with schema and calls the documentHandler.validateMetadata method.
    case "validate_documentation_metadata": { const parsed = ValidateMetadataSchema.safeParse(args); if (!parsed.success) { throw new Error( `Invalid arguments for validate_metadata: ${parsed.error}` ); } return await documentHandler.validateMetadata( parsed.data.basePath, parsed.data.requiredFields ); }
  • Helper function used by validateMetadata to parse YAML frontmatter from markdown files.
    export function parseFrontmatter(content: string): { frontmatter: Record<string, any>; content: string; } { const frontmatterRegex = /^---\s*\n([\s\S]*?)\n---\s*\n/; const match = content.match(frontmatterRegex); if (!match) { return { frontmatter: {}, content }; } const frontmatterStr = match[1]; const contentWithoutFrontmatter = content.slice(match[0].length); // Parse frontmatter as key-value pairs const frontmatter: Record<string, any> = {}; const lines = frontmatterStr.split("\n"); for (const line of lines) { const colonIndex = line.indexOf(":"); if (colonIndex !== -1) { const key = line.slice(0, colonIndex).trim(); let value = line.slice(colonIndex + 1).trim(); // Handle quoted values if (value.startsWith('"') && value.endsWith('"')) { value = value.slice(1, -1); } // Handle arrays if (value.startsWith("[") && value.endsWith("]")) { try { value = JSON.parse(value); } catch { // Keep as string if parsing fails } } frontmatter[key] = value; } } return { frontmatter, content: contentWithoutFrontmatter }; }

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/alekspetrov/mcp-docs-service'

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