Skip to main content
Glama

IT Tools MCP Server

index.ts•5.08 kB
import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; import { z } from "zod"; import yaml from "js-yaml"; export function registerValidateCompose(server: McpServer) { server.registerTool("validate_docker_compose", { description: "Validate Docker Compose files for syntax errors, compatibility issues, and best practices. Example: check YAML syntax, service configuration, network setup", inputSchema: { content: z.string().describe("Docker Compose file content to validate"), }, // VS Code compliance annotations annotations: { title: "Validate Docker Compose", description: "Validate Docker Compose syntax and configuration", readOnlyHint: false } }, async ({ content }) => { if (!content?.trim()) { return { content: [ { type: "text", text: "Please provide a Docker Compose file content to validate", }, ], }; } try { // Try to parse as YAML first let parsed: any; try { parsed = yaml.load(content); } catch (yamlError: any) { return { content: [ { type: "text", text: `YAML parsing error: ${yamlError.message}`, }, ], }; } if (!parsed || typeof parsed !== 'object') { return { content: [ { type: "text", text: "Invalid Docker Compose file: must be a valid YAML object", }, ], }; } const errors: string[] = []; // Basic Docker Compose validation if (!parsed.version && !parsed.services) { errors.push('Missing required "version" or "services" field'); } if (parsed.services && typeof parsed.services !== 'object') { errors.push('"services" field must be an object'); } if (parsed.services) { for (const [serviceName, service] of Object.entries(parsed.services)) { if (typeof service !== 'object' || service === null) { errors.push(`Service "${serviceName}" must be an object`); continue; } const serviceObj = service as any; // Check for common required fields or patterns if (!serviceObj.image && !serviceObj.build && !serviceObj.dockerfile) { errors.push(`Service "${serviceName}" must specify either "image", "build", or "dockerfile"`); } // Validate ports format if (serviceObj.ports) { if (!Array.isArray(serviceObj.ports)) { errors.push(`Service "${serviceName}": ports must be an array`); } else { for (const port of serviceObj.ports) { if (typeof port === 'string') { if (!/^\d+(:\d+)?$/.test(port.replace(/^["']|["']$/g, ''))) { errors.push(`Service "${serviceName}": invalid port format "${port}"`); } } else if (typeof port === 'object' && port !== null) { const portObj = port as any; if (!portObj.target && !portObj.published) { errors.push(`Service "${serviceName}": port object must have "target" or "published" field`); } } } } } // Validate volumes format if (serviceObj.volumes && !Array.isArray(serviceObj.volumes)) { errors.push(`Service "${serviceName}": volumes must be an array`); } // Validate environment format if (serviceObj.environment) { if (!Array.isArray(serviceObj.environment) && typeof serviceObj.environment !== 'object') { errors.push(`Service "${serviceName}": environment must be an array or object`); } } } } // Check for valid compose file versions if (parsed.version) { const validVersions = ['2', '2.0', '2.1', '2.2', '2.3', '2.4', '3', '3.0', '3.1', '3.2', '3.3', '3.4', '3.5', '3.6', '3.7', '3.8', '3.9']; if (!validVersions.includes(parsed.version.toString())) { errors.push(`Unknown Docker Compose version: ${parsed.version}`); } } const resultText = errors.length === 0 ? 'Docker Compose file is valid!' : `Validation errors found:\n${errors.map(error => `• ${error}`).join('\n')}`; return { content: [ { type: "text", text: resultText, }, ], }; } catch (error: any) { return { content: [ { type: "text", text: `Error validating Docker Compose file: ${error.message}`, }, ], }; } } ); }

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/wrenchpilot/it-tools-mcp'

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