Skip to main content
Glama
toml-loader.ts3.66 kB
/** * TOML configuration loader * Loads and validates OssHub configuration from TOML files */ import { readFileSync, existsSync } from "fs"; import { parse as parseToml } from "@iarna/toml"; import type { TomlConfig, SourceConfig, ToolConfig } from "../types/config.js"; /** * Load configuration from a TOML file */ export function loadTomlConfig(configPath: string): TomlConfig { if (!existsSync(configPath)) { throw new Error(`Configuration file not found: ${configPath}`); } const content = readFileSync(configPath, "utf-8"); const parsed = parseToml(content) as any; // Validate and transform sources const sources: SourceConfig[] = []; if (parsed.sources && Array.isArray(parsed.sources)) { for (const source of parsed.sources) { sources.push(validateSource(source)); } } // Validate and transform tools const tools: ToolConfig[] = []; if (parsed.tools && Array.isArray(parsed.tools)) { for (const tool of parsed.tools) { tools.push(validateTool(tool, sources)); } } return { sources, tools }; } /** * Validate a source configuration */ function validateSource(source: any): SourceConfig { if (!source.id || typeof source.id !== "string") { throw new Error("Source configuration requires an 'id' field (string)"); } if (!source.type || typeof source.type !== "string") { throw new Error(`Source '${source.id}': 'type' field is required (obs, oss, s3, cos, minio)`); } if (!source.endpoint || typeof source.endpoint !== "string") { throw new Error(`Source '${source.id}': 'endpoint' field is required`); } if (!source.access_key || typeof source.access_key !== "string") { throw new Error(`Source '${source.id}': 'access_key' field is required`); } if (!source.secret_key || typeof source.secret_key !== "string") { throw new Error(`Source '${source.id}': 'secret_key' field is required`); } return { id: source.id, type: source.type, endpoint: source.endpoint, access_key: source.access_key, secret_key: source.secret_key, region: source.region, default_bucket: source.default_bucket, connection_timeout: source.connection_timeout, security_token: source.security_token, ssl: source.ssl, path_style: source.path_style, }; } /** * Validate a tool configuration */ function validateTool(tool: any, sources: SourceConfig[]): ToolConfig { if (!tool.name || typeof tool.name !== "string") { throw new Error("Tool configuration requires a 'name' field"); } if (!tool.source || typeof tool.source !== "string") { throw new Error(`Tool '${tool.name}': 'source' field is required`); } // Validate source exists const sourceExists = sources.some((s) => s.id === tool.source); if (!sourceExists) { throw new Error( `Tool '${tool.name}': source '${tool.source}' not found. Available sources: ${sources.map((s) => s.id).join(", ")}` ); } return tool as ToolConfig; } /** * Find configuration file in common locations */ export function findConfigFile(explicitPath?: string): string | null { // Check explicit path first if (explicitPath) { if (existsSync(explicitPath)) { return explicitPath; } throw new Error(`Configuration file not found: ${explicitPath}`); } // Check common locations const locations = [ "./osshub.toml", "./config/osshub.toml", "~/.osshub/config.toml", ]; for (const location of locations) { const expandedPath = location.replace("~", process.env.HOME || process.env.USERPROFILE || ""); if (existsSync(expandedPath)) { return expandedPath; } } 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/zq940222/OssHub'

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