UNPKG

@boundless-oss/atlas

Version:

Atlas - MCP Server for comprehensive startup project management

116 lines (97 loc) 3.93 kB
import { describe, it, expect } from 'vitest'; import { promises as fs } from 'fs'; import path from 'path'; interface Tool { name: string; description: string; inputSchema?: { type: string; properties?: Record<string, any>; required?: string[]; }; } describe('Tool Schema Validation', () => { it('should have required field for all tools with properties in inputSchema', async () => { const toolsWithMissingRequired: Array<{ file: string; tool: string; line?: number }> = []; // Read all module files and find tool definitions const modulesDir = path.join(process.cwd(), 'src/modules'); const moduleFiles = await fs.readdir(modulesDir, { recursive: true }); for (const file of moduleFiles) { if (typeof file === 'string' && file.endsWith('index.ts') && !file.includes('__tests__')) { const filePath = path.join(modulesDir, file); const content = await fs.readFile(filePath, 'utf-8'); const lines = content.split('\n'); // Find tool definitions for (let i = 0; i < lines.length; i++) { const line = lines[i]; // Look for tool definitions if (line.includes('name:') && line.includes("'") && i > 0 && lines[i-1].includes('{')) { const toolNameMatch = line.match(/name:\s*['"]([^'"]+)['"]/); if (toolNameMatch) { const toolName = toolNameMatch[1]; // Look for inputSchema let j = i + 1; let hasInputSchema = false; let hasProperties = false; let hasRequired = false; let braceCount = 1; while (j < lines.length && braceCount > 0) { const currentLine = lines[j]; if (currentLine.includes('inputSchema:')) { hasInputSchema = true; } if (hasInputSchema && currentLine.includes('properties:')) { hasProperties = true; } if (hasInputSchema && currentLine.includes('required:')) { hasRequired = true; } // Count braces to know when tool definition ends braceCount += (currentLine.match(/\{/g) || []).length; braceCount -= (currentLine.match(/\}/g) || []).length; j++; } if (hasInputSchema && hasProperties && !hasRequired) { toolsWithMissingRequired.push({ file: file, tool: toolName, line: i + 1 }); } } } } } } // This test should fail initially, showing which tools are missing the required field if (toolsWithMissingRequired.length > 0) { console.log('\nTools missing required field:'); toolsWithMissingRequired.forEach(({ file, tool, line }) => { console.log(` - ${file}: ${tool} (line ~${line})`); }); } expect(toolsWithMissingRequired).toHaveLength(0); }); it('should be able to reproduce the JSON Schema validation error', () => { // Example of a schema that would fail validation const invalidSchema = { type: 'object', properties: { name: { type: 'string' }, age: { type: 'number' } } // Missing required field }; const validSchema = { type: 'object', properties: { name: { type: 'string' }, age: { type: 'number' } }, required: [] // Even empty array is valid }; // This demonstrates the issue - schemas with properties should have required field expect(invalidSchema).not.toHaveProperty('required'); expect(validSchema).toHaveProperty('required'); }); });