Skip to main content
Glama

Git MCP Server

#!/usr/bin/env node /** * @fileoverview Utility script to make files executable (chmod +x) on Unix-like systems. * @module scripts/make-executable * On Windows, this script does nothing but exits successfully. * Useful for CLI applications where built output needs executable permissions. * Default target (if no args): dist/index.js. * Ensures output paths are within the project directory for security. * * @example * // Add to package.json build script: * // "build": "tsc && ts-node --esm scripts/make-executable.ts dist/index.js" * * @example * // Run directly with custom files: * // ts-node --esm scripts/make-executable.ts path/to/script1 path/to/script2 */ import fs from "fs/promises"; import os from "os"; import path from "path"; const isUnix = os.platform() !== "win32"; const projectRoot = process.cwd(); const EXECUTABLE_MODE = 0o755; // rwxr-xr-x /** * Represents the result of an attempt to make a file executable. * @property file - The relative path of the file targeted. * @property status - The outcome of the operation ('success', 'error', or 'skipped'). * @property reason - If status is 'error' or 'skipped', an explanation. */ interface ExecutableResult { file: string; status: "success" | "error" | "skipped"; reason?: string; } /** * Main function to make specified files executable. * Skips operation on Windows. Processes command-line arguments for target files * or defaults to 'dist/index.js'. Reports status for each file. */ const makeExecutable = async (): Promise<void> => { try { const targetFiles: string[] = process.argv.slice(2).length > 0 ? process.argv.slice(2) : ["dist/index.js"]; if (!isUnix) { console.log( "Skipping chmod operation: Script is running on Windows (not applicable).", ); return; } console.log( `Attempting to make files executable: ${targetFiles.join(", ")}`, ); const results = await Promise.allSettled( targetFiles.map(async (targetFile): Promise<ExecutableResult> => { const normalizedPath = path.resolve(projectRoot, targetFile); if ( !normalizedPath.startsWith(projectRoot + path.sep) && normalizedPath !== projectRoot ) { return { file: targetFile, status: "error", reason: `Path resolves outside project boundary: ${normalizedPath}`, }; } try { await fs.access(normalizedPath); // Check if file exists await fs.chmod(normalizedPath, EXECUTABLE_MODE); return { file: targetFile, status: "success" }; } catch (error) { const err = error as NodeJS.ErrnoException; if (err.code === "ENOENT") { return { file: targetFile, status: "error", reason: "File not found", }; } console.error( `Error setting executable permission for ${targetFile}: ${err.message}`, ); return { file: targetFile, status: "error", reason: err.message }; } }), ); let hasErrors = false; results.forEach((result) => { if (result.status === "fulfilled") { const { file, status, reason } = result.value; if (status === "success") { console.log(`Successfully made executable: ${file}`); } else if (status === "error") { console.error(`Error for ${file}: ${reason}`); hasErrors = true; } else if (status === "skipped") { // This status is not currently generated by the mapAsync logic but kept for future flexibility console.warn(`Skipped ${file}: ${reason}`); } } else { console.error( `Unexpected failure for one of the files: ${result.reason}`, ); hasErrors = true; } }); if (hasErrors) { console.error( "One or more files could not be made executable. Please check the errors above.", ); // process.exit(1); // Uncomment to exit with error if any file fails } else { console.log("All targeted files processed successfully."); } } catch (error) { console.error( "A fatal error occurred during the make-executable script:", error instanceof Error ? error.message : error, ); process.exit(1); } }; makeExecutable();

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/cyanheads/git-mcp-server'

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