Skip to main content
Glama
portel-dev

NCP - Natural Context Provider

by portel-dev
schema-cache.ts4.43 kB
/** * Schema Cache * * Caches MCP configuration schemas for reuse across add/repair/import commands * Stores in JSON files alongside CSV cache */ import fs from 'fs'; import path from 'path'; import { ConfigurationSchema } from '../services/config-schema-reader.js'; import { logger } from '../utils/logger.js'; export class SchemaCache { private cacheDir: string; constructor(cacheDir: string) { this.cacheDir = path.join(cacheDir, 'schemas'); this.ensureCacheDir(); } /** * Ensure cache directory exists */ private ensureCacheDir(): void { if (!fs.existsSync(this.cacheDir)) { fs.mkdirSync(this.cacheDir, { recursive: true }); } } /** * Save configuration schema to cache */ save(mcpName: string, schema: ConfigurationSchema): void { try { const filepath = this.getSchemaPath(mcpName); const data = { mcpName, schema, cachedAt: new Date().toISOString(), version: '1.0' }; fs.writeFileSync(filepath, JSON.stringify(data, null, 2), 'utf-8'); logger.debug(`Cached configuration schema for ${mcpName}`); } catch (error: any) { logger.error(`Failed to cache schema for ${mcpName}:`, error.message); } } /** * Load configuration schema from cache */ get(mcpName: string): ConfigurationSchema | null { try { const filepath = this.getSchemaPath(mcpName); if (!fs.existsSync(filepath)) { return null; } const data = JSON.parse(fs.readFileSync(filepath, 'utf-8')); logger.debug(`Loaded cached schema for ${mcpName}`); return data.schema as ConfigurationSchema; } catch (error: any) { logger.error(`Failed to load cached schema for ${mcpName}:`, error.message); return null; } } /** * Check if schema is cached */ has(mcpName: string): boolean { const filepath = this.getSchemaPath(mcpName); return fs.existsSync(filepath); } /** * Delete cached schema */ delete(mcpName: string): void { try { const filepath = this.getSchemaPath(mcpName); if (fs.existsSync(filepath)) { fs.unlinkSync(filepath); logger.debug(`Deleted cached schema for ${mcpName}`); } } catch (error: any) { logger.error(`Failed to delete cached schema for ${mcpName}:`, error.message); } } /** * Clear all cached schemas */ clear(): void { try { if (fs.existsSync(this.cacheDir)) { const files = fs.readdirSync(this.cacheDir); for (const file of files) { if (file.endsWith('.schema.json')) { fs.unlinkSync(path.join(this.cacheDir, file)); } } logger.debug('Cleared all cached schemas'); } } catch (error: any) { logger.error('Failed to clear schema cache:', error.message); } } /** * Get all cached schemas */ listAll(): Array<{ mcpName: string; cachedAt: string }> { try { if (!fs.existsSync(this.cacheDir)) { return []; } const files = fs.readdirSync(this.cacheDir); const schemas: Array<{ mcpName: string; cachedAt: string }> = []; for (const file of files) { if (file.endsWith('.schema.json')) { const filepath = path.join(this.cacheDir, file); const data = JSON.parse(fs.readFileSync(filepath, 'utf-8')); schemas.push({ mcpName: data.mcpName, cachedAt: data.cachedAt }); } } return schemas; } catch (error: any) { logger.error('Failed to list cached schemas:', error.message); return []; } } /** * Get file path for schema */ private getSchemaPath(mcpName: string): string { // Sanitize MCP name for filename const safeName = mcpName.replace(/[^a-zA-Z0-9-_]/g, '_'); return path.join(this.cacheDir, `${safeName}.schema.json`); } /** * Get cache statistics */ getStats(): { total: number; oldestCache: string | null; newestCache: string | null } { const all = this.listAll(); if (all.length === 0) { return { total: 0, oldestCache: null, newestCache: null }; } const sorted = all.sort((a, b) => new Date(a.cachedAt).getTime() - new Date(b.cachedAt).getTime() ); return { total: all.length, oldestCache: sorted[0].cachedAt, newestCache: sorted[sorted.length - 1].cachedAt }; } }

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/portel-dev/ncp'

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