Skip to main content
Glama
auto-discovery.tsβ€’5.67 kB
/** * Auto-discovery module for automatic attribute mapping updates */ import { getObjectAttributes, getAvailableObjects, } from '../cli/commands/attributes.js'; import { loadMappingConfig, writeMappingConfig, MappingConfig, } from './config-loader.js'; // Simple logging for auto-discovery - disabled for MCP protocol compatibility const log = { info: ( // eslint-disable-next-line @typescript-eslint/no-unused-vars _message: string, // eslint-disable-next-line @typescript-eslint/no-unused-vars _data?: Record<string, unknown> ) => { /* Silent for MCP protocol compatibility */ }, warn: ( // eslint-disable-next-line @typescript-eslint/no-unused-vars _message: string, // eslint-disable-next-line @typescript-eslint/no-unused-vars _data?: Record<string, unknown> ) => { /* Silent for MCP protocol compatibility */ }, error: ( // eslint-disable-next-line @typescript-eslint/no-unused-vars _message: string, // eslint-disable-next-line @typescript-eslint/no-unused-vars _error?: Record<string, unknown> ) => { /* Silent for MCP protocol compatibility */ }, }; /** * Configuration for auto-discovery */ export interface AutoDiscoveryConfig { enabled: boolean; runOnStartup: boolean; intervalMinutes?: number; outputPath?: string; } /** * Default configuration for auto-discovery */ const DEFAULT_CONFIG: AutoDiscoveryConfig = { enabled: true, runOnStartup: true, intervalMinutes: 60, // Run every hour by default outputPath: 'configs/runtime/mappings/user.json', }; let discoveryInterval: NodeJS.Timeout | null = null; /** * Run attribute discovery for all objects */ export async function runDiscovery( apiKey: string, outputPath?: string ): Promise<void> { log.info('Starting automatic attribute discovery...'); try { // Load existing config or create new one let config: MappingConfig; try { config = loadMappingConfig(); } catch { // Failed to load existing configuration log.warn('Failed to load existing configuration, creating new one...'); config = { version: '1.0', metadata: { generated: new Date().toISOString(), description: 'Generated by automatic discovery', }, mappings: { attributes: { common: {}, objects: {}, custom: {}, }, objects: {}, lists: {}, relationships: {}, }, }; } // Get all available objects const objects = await getAvailableObjects(apiKey); log.info(`Found ${objects.length} objects in Attio workspace`); // Process each object for (const objectSlug of objects) { try { const attributeMappings = await getObjectAttributes(objectSlug, apiKey); const attributeCount = Object.keys(attributeMappings).length; if (attributeCount > 0) { if (!config.mappings.attributes.objects[objectSlug]) { config.mappings.attributes.objects[objectSlug] = {}; } // Merge with existing mappings config.mappings.attributes.objects[objectSlug] = { ...config.mappings.attributes.objects[objectSlug], ...attributeMappings, }; log.info(`Discovered ${attributeCount} attributes for ${objectSlug}`); } } catch (error: unknown) { log.error( `Error discovering attributes for ${objectSlug}:`, error as Record<string, unknown> ); } } // Update metadata config.metadata = { ...config.metadata, generated: new Date().toISOString(), lastDiscovery: new Date().toISOString(), autoDiscovery: true, }; // Write the updated config await writeMappingConfig(config, outputPath || DEFAULT_CONFIG.outputPath); log.info('Automatic attribute discovery completed successfully'); } catch (error: unknown) { log.error( 'Failed to complete automatic discovery:', error as Record<string, unknown> ); throw error; } } /** * Start automatic discovery with optional periodic updates */ export async function startAutoDiscovery( apiKey: string, config: Partial<AutoDiscoveryConfig> = {} ): Promise<void> { const settings = { ...DEFAULT_CONFIG, ...config }; if (!settings.enabled) { log.info('Auto-discovery is disabled'); return; } // Run on startup if configured if (settings.runOnStartup) { try { await runDiscovery(apiKey, settings.outputPath); } catch (error: unknown) { log.error( 'Failed to run discovery on startup:', error as Record<string, unknown> ); // Don't fail the server startup, just log the error } } // Set up periodic discovery if configured if (settings.intervalMinutes && settings.intervalMinutes > 0) { const intervalMs = settings.intervalMinutes * 60 * 1000; discoveryInterval = setInterval(async () => { log.info('Running scheduled attribute discovery...'); try { await runDiscovery(apiKey, settings.outputPath); } catch (error: unknown) { log.error( 'Failed to run scheduled discovery:', error as Record<string, unknown> ); } }, intervalMs); log.info( `Scheduled attribute discovery every ${settings.intervalMinutes} minutes` ); } } /** * Stop automatic discovery */ export function stopAutoDiscovery(): void { if (discoveryInterval) { clearInterval(discoveryInterval); discoveryInterval = null; log.info('Stopped automatic attribute discovery'); } }

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/kesslerio/attio-mcp-server'

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