Skip to main content
Glama
loader.ts4.73 kB
/** * Configuration loader for PartnerCore Proxy */ import { config as dotenvConfig } from 'dotenv'; import * as path from 'path'; import * as fs from 'fs'; import { ProxyConfig, ALConfig } from './types.js'; /** * Environment endpoints */ const ENDPOINTS = { production: 'https://partnercore-mcp-prod.agreeablebush-0fe29c4e.eastus.azurecontainerapps.io', uat: 'https://partnercore-mcp-uat.happysand-4085830a.eastus.azurecontainerapps.io', } as const; type Environment = 'production' | 'uat'; /** * Get the cloud URL based on environment */ function getCloudUrl(): string { // Explicit URL takes precedence const cloudUrl = process.env['CLOUD_URL'] || process.env['PARTNERCORE_CLOUD_URL']; if (cloudUrl) { return cloudUrl; } // Check for environment setting const env = (process.env['PARTNERCORE_ENV'] || 'production').toLowerCase() as Environment; if (env === 'uat') { return ENDPOINTS.uat; } return ENDPOINTS.production; } /** * Load configuration from environment variables and defaults */ export function loadConfig(): ProxyConfig { // Load .env file if present dotenvConfig(); const al = loadALConfig(); // Get API key from environment (customer/resource looked up from Azure Tables) const apiKey = process.env['API_KEY'] || ''; return { cloudUrl: getCloudUrl(), apiKey, port: parseInt(process.env['PROXY_PORT'] || '3100', 10), logLevel: (process.env['LOG_LEVEL'] as ProxyConfig['logLevel']) || 'info', al, }; } /** * Find AL workspace root by walking up the directory tree looking for app.json * Similar to how VS Code and other tools detect workspace roots */ export function findALWorkspace(startDir?: string): string | null { let currentDir = path.resolve(startDir || process.cwd()); const root = path.parse(currentDir).root; // Walk up the directory tree while (currentDir !== root) { const appJsonPath = path.join(currentDir, 'app.json'); if (fs.existsSync(appJsonPath)) { return currentDir; } // Move up one directory const parentDir = path.dirname(currentDir); if (parentDir === currentDir) { break; // Reached root } currentDir = parentDir; } return null; } /** * Load AL-specific configuration */ function loadALConfig(): ALConfig { // Use explicit workspace root if provided, otherwise auto-detect let workspaceRoot: string; if (process.env['AL_WORKSPACE_ROOT']) { workspaceRoot = path.resolve(process.env['AL_WORKSPACE_ROOT']); } else { // Auto-detect workspace by walking up from current directory const detected = findALWorkspace(); workspaceRoot = detected || process.cwd(); } const extensionCachePath = path.join( process.env['HOME'] || process.env['USERPROFILE'] || '.', '.partnercore', 'al-extension' ); return { extensionVersion: process.env['AL_EXTENSION_VERSION'] || 'latest', workspaceRoot, extensionPath: process.env['AL_EXTENSION_PATH'], extensionCachePath, }; } /** * Validate configuration * Note: Workspace validation is lenient - workspace can be detected lazily when tools are used */ export function validateConfig(config: ProxyConfig): { valid: boolean; errors: string[]; warnings: string[] } { const errors: string[] = []; const warnings: string[] = []; // API key is required for the MCP server to function if (!config.apiKey) { errors.push('API_KEY is required. Set the API_KEY environment variable.'); } // Validate workspace root exists if (!fs.existsSync(config.al.workspaceRoot)) { warnings.push(`AL workspace root does not exist: ${config.al.workspaceRoot}`); } else { // Check for app.json in workspace const appJsonPath = path.join(config.al.workspaceRoot, 'app.json'); if (!fs.existsSync(appJsonPath)) { // Try to auto-detect workspace const detected = findALWorkspace(config.al.workspaceRoot); if (detected) { warnings.push(`app.json not found in ${config.al.workspaceRoot}, but detected workspace at: ${detected}`); } else { warnings.push(`app.json not found in workspace: ${appJsonPath}. Workspace will be auto-detected when tools are used.`); } } } return { valid: errors.length === 0, errors, warnings, }; } /** * Find app.json in workspace and return its contents */ export function loadAppJson(workspaceRoot: string): Record<string, unknown> | null { const appJsonPath = path.join(workspaceRoot, 'app.json'); if (!fs.existsSync(appJsonPath)) { return null; } try { const content = fs.readFileSync(appJsonPath, 'utf-8'); return JSON.parse(content) as Record<string, unknown>; } catch { return null; } }

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/ciellosinc/partnercore-proxy'

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