Skip to main content
Glama
gilberth

MCP Cloudflare DNS Server

cli.js6.67 kB
#!/usr/bin/env node import { Command } from "commander"; import fs from "node:fs"; import path from "node:path"; import { dirname, resolve } from "path"; import { spawnPromise } from "spawn-rx"; import { fileURLToPath } from "url"; const __dirname = dirname(fileURLToPath(import.meta.url)); function handleError(error) { let message; if (error instanceof Error) { message = error.message; } else if (typeof error === "string") { message = error; } else { message = "Unknown error"; } console.error(message); process.exit(1); } function delay(ms) { return new Promise((resolve) => setTimeout(resolve, ms, true)); } async function runWebClient(args) { const inspectorServerPath = resolve(__dirname, "../../", "server", "build", "index.js"); // Path to the client entry point const inspectorClientPath = resolve(__dirname, "../../", "client", "bin", "client.js"); const CLIENT_PORT = process.env.CLIENT_PORT ?? "6274"; const SERVER_PORT = process.env.SERVER_PORT ?? "6277"; console.log("Starting MCP inspector..."); const abort = new AbortController(); let cancelled = false; process.on("SIGINT", () => { cancelled = true; abort.abort(); }); let server; let serverOk; try { server = spawnPromise("node", [ inspectorServerPath, ...(args.command ? [`--env`, args.command] : []), ...(args.args ? [`--args=${args.args.join(" ")}`] : []), ], { env: { ...process.env, PORT: SERVER_PORT, MCP_ENV_VARS: JSON.stringify(args.envArgs), }, signal: abort.signal, echoOutput: true, }); // Make sure server started before starting client serverOk = await Promise.race([server, delay(2 * 1000)]); } catch (error) { } if (serverOk) { try { await spawnPromise("node", [inspectorClientPath], { env: { ...process.env, PORT: CLIENT_PORT }, signal: abort.signal, echoOutput: true, }); } catch (e) { if (!cancelled || process.env.DEBUG) throw e; } } } async function runCli(args) { const projectRoot = resolve(__dirname, ".."); const cliPath = resolve(projectRoot, "build", "index.js"); const abort = new AbortController(); let cancelled = false; process.on("SIGINT", () => { cancelled = true; abort.abort(); }); try { await spawnPromise("node", [cliPath, args.command, ...args.args], { env: { ...process.env, ...args.envArgs }, signal: abort.signal, echoOutput: true, }); } catch (e) { if (!cancelled || process.env.DEBUG) { throw e; } } } function loadConfigFile(configPath, serverName) { try { const resolvedConfigPath = path.isAbsolute(configPath) ? configPath : path.resolve(process.cwd(), configPath); if (!fs.existsSync(resolvedConfigPath)) { throw new Error(`Config file not found: ${resolvedConfigPath}`); } const configContent = fs.readFileSync(resolvedConfigPath, "utf8"); const parsedConfig = JSON.parse(configContent); if (!parsedConfig.mcpServers || !parsedConfig.mcpServers[serverName]) { const availableServers = Object.keys(parsedConfig.mcpServers || {}).join(", "); throw new Error(`Server '${serverName}' not found in config file. Available servers: ${availableServers}`); } const serverConfig = parsedConfig.mcpServers[serverName]; return serverConfig; } catch (err) { if (err instanceof SyntaxError) { throw new Error(`Invalid JSON in config file: ${err.message}`); } throw err; } } function parseKeyValuePair(value, previous = {}) { const parts = value.split("="); const key = parts[0]; const val = parts.slice(1).join("="); if (val === undefined || val === "") { throw new Error(`Invalid parameter format: ${value}. Use key=value format.`); } return { ...previous, [key]: val }; } function parseArgs() { const program = new Command(); const argSeparatorIndex = process.argv.indexOf("--"); let preArgs = process.argv; let postArgs = []; if (argSeparatorIndex !== -1) { preArgs = process.argv.slice(0, argSeparatorIndex); postArgs = process.argv.slice(argSeparatorIndex + 1); } program .name("inspector-bin") .allowExcessArguments() .allowUnknownOption() .option("-e <env>", "environment variables in KEY=VALUE format", parseKeyValuePair, {}) .option("--config <path>", "config file path") .option("--server <n>", "server name from config file") .option("--cli", "enable CLI mode"); // Parse only the arguments before -- program.parse(preArgs); const options = program.opts(); const remainingArgs = program.args; // Add back any arguments that came after -- const finalArgs = [...remainingArgs, ...postArgs]; // Validate that config and server are provided together if ((options.config && !options.server) || (!options.config && options.server)) { throw new Error("Both --config and --server must be provided together. If you specify one, you must specify the other."); } // If config file is specified, load and use the options from the file. We must merge the args // from the command line and the file together, or we will miss the method options (--method, // etc.) if (options.config && options.server) { const config = loadConfigFile(options.config, options.server); return { command: config.command, args: [...(config.args || []), ...finalArgs], envArgs: { ...(config.env || {}), ...(options.e || {}) }, cli: options.cli || false, }; } // Otherwise use command line arguments const command = finalArgs[0] || ""; const args = finalArgs.slice(1); return { command, args, envArgs: options.e || {}, cli: options.cli || false, }; } async function main() { process.on("uncaughtException", (error) => { handleError(error); }); try { const args = parseArgs(); if (args.cli) { runCli(args); } else { await runWebClient(args); } } catch (error) { handleError(error); } } main();

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/gilberth/mcp-cloudflare'

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