Skip to main content
Glama

Formula One MCP Server

dynamicRegistry.ts4.86 kB
// Dynamic Registry Service - Auto-loads tool schemas from f1-mcp-config.json // Provides Cursor-compatible schema format with watch capabilities import { SchemaType } from '@google/generative-ai'; import type { FunctionDeclaration } from '@google/generative-ai'; export interface ToolSchema { name: string; description: string; parameters: { type: SchemaType.OBJECT; properties: Record<string, any>; required: string[]; }; } export class DynamicRegistry { private static schemas: FunctionDeclaration[] = []; private static lastLoadTime = 0; private static loadInterval = 60000; // 60 seconds private static isWatching = false; /** * Load schemas from f1-mcp-config.json */ static async loadSchemas(): Promise<FunctionDeclaration[]> { const now = Date.now(); // Return cached schemas if within interval if (this.schemas.length > 0 && (now - this.lastLoadTime) < this.loadInterval) { return this.schemas; } try { // In a real implementation, this would fetch from the config file // For now, we'll use the existing F1_TOOL_SCHEMAS as fallback const schemas = await this.fetchSchemasFromConfig(); this.schemas = schemas; this.lastLoadTime = now; console.log(`✅ Loaded ${schemas.length} tool schemas from registry`); return schemas; } catch (error) { console.error('❌ Failed to load schemas from registry:', error); // Return existing schemas as fallback return this.schemas; } } /** * Start watching for schema changes */ static startWatching(): void { if (this.isWatching) return; this.isWatching = true; setInterval(() => { this.loadSchemas().catch(console.error); }, this.loadInterval); console.log('🔍 Started watching for schema changes'); } /** * Stop watching for schema changes */ static stopWatching(): void { this.isWatching = false; console.log('⏹️ Stopped watching for schema changes'); } /** * Fetch schemas from f1-mcp-config.json */ private static async fetchSchemasFromConfig(): Promise<FunctionDeclaration[]> { try { // In a real implementation, this would read the JSON file // For now, we'll return the existing schemas const { F1_TOOL_SCHEMAS } = await import('./f1ToolSchemas'); return F1_TOOL_SCHEMAS; } catch (error) { console.error('Failed to fetch schemas from config:', error); throw error; } } /** * Get schema for specific tool */ static async getToolSchema(toolName: string): Promise<FunctionDeclaration | null> { const schemas = await this.loadSchemas(); return schemas.find(schema => schema.name === toolName) || null; } /** * Check if tool exists in registry */ static async hasTool(toolName: string): Promise<boolean> { const schema = await this.getToolSchema(toolName); return schema !== null; } /** * Get all available tool names */ static async getToolNames(): Promise<string[]> { const schemas = await this.loadSchemas(); return schemas.map(schema => schema.name); } /** * Validate tool arguments against schema */ static async validateArguments( toolName: string, args: Record<string, any> ): Promise<{ valid: boolean; errors: string[] }> { const schema = await this.getToolSchema(toolName); if (!schema) { return { valid: false, errors: [`Tool '${toolName}' not found in registry`] }; } const errors: string[] = []; const required = schema.parameters?.required || []; const properties = schema.parameters?.properties || {}; // Check required parameters for (const requiredParam of required) { if (!(requiredParam in args)) { errors.push(`Missing required parameter: ${requiredParam}`); } } // Check parameter types for (const [paramName, paramValue] of Object.entries(args)) { const paramSchema = properties[paramName]; if (paramSchema) { const expectedType = paramSchema.type; const actualType = typeof paramValue; if (expectedType === SchemaType.NUMBER && actualType !== 'number') { errors.push(`Parameter '${paramName}' must be a number, got ${actualType}`); } else if (expectedType === SchemaType.STRING && actualType !== 'string') { errors.push(`Parameter '${paramName}' must be a string, got ${actualType}`); } } } return { valid: errors.length === 0, errors }; } /** * Get registry status */ static getStatus(): { schemasLoaded: number; lastLoadTime: number; isWatching: boolean } { return { schemasLoaded: this.schemas.length, lastLoadTime: this.lastLoadTime, isWatching: this.isWatching }; } }

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/notsedano/f1-mcp-server'

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