Skip to main content
Glama
cli_lib.ts3.8 kB
// src/lib/cli_lib.ts import { URL } from "url"; import * as path from "node:path"; import { CliConfig } from "./cli.js"; import { extractDomain } from "./utils.js"; import { logger } from "./logger.js"; export interface ParsedNameUrl { name: string; urlValue: string; } /** * Parse a string into a name-value pair using the specified delimiter */ export function parseNameValuePair( input: string, delimiter = ":" ): ParsedNameUrl | null { const parts = input.split(delimiter); if (parts.length < 2) { logger.error( `Invalid format: '${input}'. Expected 'name${delimiter}value'. Skipping.` ); return null; } const name = parts[0].trim(); const urlValue = parts.slice(1).join(delimiter).trim(); if (!name || !urlValue) { logger.error( `Invalid format: '${input}'. Name or value part is empty. Skipping.` ); return null; } return { name, urlValue }; } /** * Validate and add a URL or file path to the target record */ export function validateAndAddSource( target: Record<string, string>, name: string, urlValue: string, sourceOrigin: string ): void { try { new URL(urlValue); target[name] = urlValue; } catch (e) { // Handle local file paths if (urlValue.startsWith("/") || urlValue.startsWith(".")) { const absolutePath = path.resolve(urlValue); target[name] = absolutePath; } else { logger.error( `(${sourceOrigin}) Invalid URL or Path format for '${name}': '${urlValue}'. Skipping. Error: ${ e instanceof Error ? e.message : e }` ); } } } /** * Process a list of space-separated items using the provided processor function */ export function processSpaceSeparatedItems<T>( input: string | undefined, processor: (item: string) => T | null, errorPrefix: string ): T[] { const results: T[] = []; if (!input) return results; const items = input.split(/\\s+/); for (const item of items) { if (!item.trim()) continue; const result = processor(item.trim()); if (result) { results.push(result); } } return results; } /** * Process multiple items using the provided processor function */ export function processMultipleItems<T>( items: string[] | undefined, processor: (item: string) => T | null, errorPrefix: string ): T[] { const results: T[] = []; if (!items || items.length === 0) return results; for (const item of items) { const result = processor(item); if (result) { results.push(result); } } return results; } /** * Add a parsed source to the target record */ export function addParsedSourceToTarget( source: ParsedNameUrl, target: Record<string, string>, origin: string ): void { validateAndAddSource(target, source.name, source.urlValue, origin); } /** * Normalize and add a domain to the target set */ export function normalizeAndAddDomain( domain: string, target: Set<string>, origin: string ): void { const extractedDomain = extractDomain(domain.trim()); if (extractedDomain) { target.add(extractedDomain); logger.info(`Added domain ${extractedDomain} from ${origin}`); } } /** * Log the configuration summary if in appropriate mode */ export function logConfigSummary(config: CliConfig): void { logger.info("\n--- SushiMCP Configuration Summary ---"); logger.info( `Documentation Sources: ${JSON.stringify(config.docSources, null, 2)}` ); logger.info( `OpenAPI Specs: ${JSON.stringify(config.openApiSpecs, null, 2)}` ); logger.info( `Allowed Fetch Domains: ${ [...config.allowedDomains].join(", ") || "(None - local only?)" }` ); logger.info("------------------------------------\n"); } // Copyright (C) 2025 Christopher White // SPDX-License-Identifier: AGPL-3.0-or-later

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/maverickg59/sushimcp'

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