Skip to main content
Glama

RS.ge Waybill MCP Server

config.tsโ€ข5.86 kB
/** * Configuration Loader * * This module: * 1. Loads configuration from environment variables * 2. Provides sensible defaults * 3. Validates configuration against Zod schema * 4. Provides type-safe access to configuration * * ๐ŸŽ“ TEACHING: Why environment-only approach? * - Simplicity: Single source of truth (environment variables) * - Security: No config files with credentials * - MCP-friendly: Works with Claude Desktop's env config * - Validation: Catches configuration errors at startup * - Type Safety: TypeScript knows the structure */ import { config as loadEnv } from 'dotenv'; import { ConfigSchema, type Config } from './config.schema.js'; /** * Load .env file if it exists */ loadEnv(); /** * Parse integer from environment variable with default */ function parseEnvInt(key: string, defaultValue: number): number { const value = process.env[key]; if (!value) return defaultValue; const parsed = parseInt(value, 10); return isNaN(parsed) ? defaultValue : parsed; } /** * Load and validate configuration from environment variables * * @returns Validated configuration object * @throws Error if configuration is invalid or required values are missing */ export function loadConfig(): Config { // Build config from environment variables const rawConfig = { server: { name: process.env.MCP_SERVER_NAME || 'rs-waybill-mcp', version: process.env.MCP_SERVER_VERSION || '1.0.0', description: process.env.MCP_SERVER_DESCRIPTION || 'MCP server for RS.ge Waybill SOAP API', }, api: { baseUrl: process.env.API_BASE_URL || 'https://services.rs.ge/WayBillService/WayBillService.asmx', timeout: parseEnvInt('API_TIMEOUT', 30000), retries: parseEnvInt('API_RETRIES', 3), retryDelay: parseEnvInt('API_RETRY_DELAY', 2000), }, credentials: { serviceUser: process.env.RS_SERVICE_USER, servicePassword: process.env.RS_SERVICE_PASSWORD, }, logging: { level: (process.env.LOG_LEVEL as 'error' | 'warn' | 'info' | 'debug') || 'info', file: process.env.LOG_FILE || 'logs/mcp-server.log', console: false, // CRITICAL: Must be false for MCP - stdio is used for JSON protocol maxSize: process.env.LOG_MAX_SIZE || '10m', maxFiles: parseEnvInt('LOG_MAX_FILES', 7), }, features: { getWaybills: process.env.FEATURE_GET_WAYBILLS !== 'false', saveWaybill: process.env.FEATURE_SAVE_WAYBILL !== 'false', sendWaybill: process.env.FEATURE_SEND_WAYBILL !== 'false', closeWaybill: process.env.FEATURE_CLOSE_WAYBILL !== 'false', confirmWaybill: process.env.FEATURE_CONFIRM_WAYBILL !== 'false', rejectWaybill: process.env.FEATURE_REJECT_WAYBILL !== 'false', getErrorCodes: process.env.FEATURE_GET_ERROR_CODES !== 'false', getAkcizCodes: process.env.FEATURE_GET_AKCIZ_CODES !== 'false', getNameFromTin: process.env.FEATURE_GET_NAME_FROM_TIN !== 'false', }, customization: { dateFormat: process.env.DATE_FORMAT || 'YYYY-MM-DD', soapNamespace: process.env.SOAP_NAMESPACE || 'http://tempuri.org/', }, }; try { // Validate with Zod schema const validatedConfig = ConfigSchema.parse(rawConfig); // Don't log to console - breaks MCP JSON protocol return validatedConfig; } catch (error) { throw new Error( `Configuration validation failed:\n${error}\n\n` + `Please check your environment variables in .env file or Claude Desktop config` ); } } /** * Get credentials from config * * @throws Error if credentials are not set */ export function getCredentials(config: Config): { user: string; password: string } { const user = config.credentials?.serviceUser; const password = config.credentials?.servicePassword; if (!user || !password) { throw new Error( 'RS.ge credentials not configured.\n\n' + 'Please set RS_SERVICE_USER and RS_SERVICE_PASSWORD environment variables.\n\n' + 'Example (.env file):\n' + ' RS_SERVICE_USER=4053098841:405309884\n' + ' RS_SERVICE_PASSWORD=YourPasswordHere\n\n' + 'For Claude Desktop, add to claude_desktop_config.json:\n' + ' "env": {\n' + ' "RS_SERVICE_USER": "4053098841:405309884",\n' + ' "RS_SERVICE_PASSWORD": "YourPasswordHere"\n' + ' }\n\n' + 'See claude_desktop_config.example.json for full example.' ); } return { user, password }; } /** * Get logging configuration with defaults */ export function getLoggingConfig(config: Config): Required<Config['logging']> { return { level: config.logging?.level || 'info', file: config.logging?.file || 'logs/mcp-server.log', console: false, // CRITICAL: Always false for MCP servers - stdio is for JSON protocol only maxSize: config.logging?.maxSize || '10m', maxFiles: config.logging?.maxFiles || 7, }; } /** * Get features configuration with defaults */ export function getFeaturesConfig(config: Config): Required<Config['features']> { return { getWaybills: config.features?.getWaybills ?? true, saveWaybill: config.features?.saveWaybill ?? true, sendWaybill: config.features?.sendWaybill ?? true, closeWaybill: config.features?.closeWaybill ?? true, confirmWaybill: config.features?.confirmWaybill ?? true, rejectWaybill: config.features?.rejectWaybill ?? true, getErrorCodes: config.features?.getErrorCodes ?? true, getAkcizCodes: config.features?.getAkcizCodes ?? true, getNameFromTin: config.features?.getNameFromTin ?? true, }; } /** * Get customization configuration with defaults */ export function getCustomizationConfig(config: Config): Required<Config['customization']> { return { dateFormat: config.customization?.dateFormat || 'YYYY-MM-DD', soapNamespace: config.customization?.soapNamespace || 'http://tempuri.org/', }; }

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/BorisSolomonia/MCPWaybill'

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