Skip to main content
Glama
version-manager.ts3.5 kB
import { existsSync } from 'node:fs'; import { readdir } from 'node:fs/promises'; import { join } from 'node:path'; export class VersionManager { private static readonly DATA_DIR = join(process.cwd(), 'data'); private static readonly DIST_DIR = process.cwd(); /** * Get the directory for storing/reading hnswlib files * In development: ./data/ * In production (bundled): ./dist/ (current working directory) */ static getStorageDir(): string { // Check if we're running from source (data directory exists) if (existsSync(VersionManager.DATA_DIR)) { return VersionManager.DATA_DIR; } // Otherwise assume we're running from bundled dist return VersionManager.DIST_DIR; } /** * Get the path for a version's HNSWlib database */ static getVersionDbPath(version: string): string { return join(VersionManager.getStorageDir(), version, 'vector'); } /** * Get the path for a version's MD cache directory */ static getVersionMdPath(version: string): string { return join(VersionManager.getStorageDir(), version, 'md'); } /** * Check if a version is available locally */ static isVersionAvailable(version: string): boolean { const dbPath = VersionManager.getVersionDbPath(version); return existsSync(dbPath); } /** * Get all available versions locally */ static async getAvailableVersions(): Promise<string[]> { try { const storageDir = VersionManager.getStorageDir(); if (!existsSync(storageDir)) { return []; } const files = await readdir(storageDir); // Get directories that contain vector subdirectory const versions: string[] = []; for (const dir of files) { const vectorPath = join(storageDir, dir, 'vector'); if (existsSync(vectorPath)) { versions.push(dir); } } return versions .sort((a, b) => { // Sort versions with latest first, then numerical order if (a === 'latest') return -1; if (b === 'latest') return 1; const aNum = parseInt(a.replace('v', '')); const bNum = parseInt(b.replace('v', '')); return bNum - aNum; // Descending order }); } catch (error) { console.warn('Warning: Could not read available versions:', error); return []; } } /** * Generate error message for missing version */ static async getMissingVersionError(requestedVersion: string): Promise<string> { const available = await VersionManager.getAvailableVersions(); let message = `Expo SDK ${requestedVersion} documentation is not available in this MCP server.\n\n`; if (available.length > 0) { message += `Available versions: ${available.join(', ')}\n\n`; message += `Please use one of the available versions or check for an updated version of this MCP server.`; } else { message += 'No documentation versions are currently bundled with this MCP server.\n'; message += 'Please check for an updated version of this MCP server.'; } return message; } /** * Validate version format */ static isValidVersionFormat(version: string): boolean { return /^(v\d+|latest)$/.test(version); } /** * Check if MD cache exists for a version */ static isMdCacheAvailable(version: string): boolean { const mdPath = VersionManager.getVersionMdPath(version); return existsSync(mdPath); } }

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/jaksm/expo-docs-mcp'

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