Skip to main content
Glama

mcp-server-commands

by g0t4
exec-utils.ts3.57 kB
import { exec, ExecOptions } from "child_process"; import { ObjectEncodingOptions } from "fs"; type ExecResult = { // this is basically ExecException except I want my own type for it... // b/c I want this to represent all results // ... by the way throws put stdout/stderr on the error "result" object // hence I am replicating that here and in my promise reject calls stdout: string; stderr: string; // ONLY on errors: message?: string; // FYI redundant b/c message ~= `Command failed: ${cmd}\n${stderr}\n` code?: number; killed?: boolean; signal?: NodeJS.Signals | undefined; cmd?: string; // FYI redundant }; /** * Executes a file with the given arguments, piping input to stdin. * @param {string} interpreter - The file to execute. * @param {string} stdin - The string to pipe to stdin. * @returns {Promise<ExecResult>} */ function execFileWithInput( interpreter: string, stdin: string, options: ObjectEncodingOptions & ExecOptions ): Promise<ExecResult> { // FYI for now, using `exec()` so the interpreter can have cmd+args AIO // could switch to `execFile()` to pass args array separately // TODO starts with fish too? "fish -..." PRN use a library to parse the command and determine this? if (interpreter.split(" ")[0] === "fish") { // PRN also check error from fish and add possible clarification to error message though there are legit ways to trigger that same error message! i.e. `fish .` which is not the same issue! return fishWorkaround(interpreter, stdin, options); } return new Promise((resolve, reject) => { const child = exec(interpreter, options, (error, stdout, stderr) => { if (error) { // console.log("execFileWithInput ERROR:", error); // mirror ExecException used by throws error.stdout = stdout; error.stderr = stderr; reject(error); } else { // I assume RC==0 else would trigger error? resolve({ stdout, stderr }); } }); if (stdin) { if (child.stdin === null) { reject(new Error("Unexpected failure: child.stdin is null")); return; } child.stdin.write(stdin); child.stdin.end(); } }); } async function fishWorkaround( interpreter: string, stdin: string, options: ObjectEncodingOptions & ExecOptions ): Promise<ExecResult> { // fish right now chokes on piped input (STDIN) + node's exec/spawn/etc, so lets use a workaround to echo the input // base64 encode thee input, then decode in pipeline const base64stdin = Buffer.from(stdin).toString("base64"); const command = `${interpreter} -c "echo ${base64stdin} | base64 -d | fish"`; return new Promise((resolve, reject) => { // const child = ... // careful with refactoring not to return that unused child exec(command, options, (error, stdout, stderr) => { // I like this style of error vs success handling! it's beautiful-est (prommises are underrated) if (error) { // console.log("fishWorkaround ERROR:", error); // mirror ExecException used by throws error.stdout = stdout; error.stderr = stderr; reject(error); } else { resolve({ stdout, stderr }); } }); }); } export { execFileWithInput, ExecResult };

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/g0t4/mcp-server-commands'

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