Skip to main content
Glama
clpi

CLP MCP - DevOps Infrastructure Server

Official
by clpi
index.ts13.2 kB
import { z } from "zod"; import { exec } from "child_process"; import { promisify } from "util"; const execAsync = promisify(exec); /** * Git repository management tools */ export const gitCloneTool = { name: "git_clone", description: "Clone a git repository", inputSchema: z.object({ url: z.string().describe("URL of the repository to clone"), destination: z.string().describe("Destination directory for the clone"), branch: z.string().optional().describe("Specific branch to clone"), depth: z.number().optional().describe("Depth for shallow clone"), }), }; export const gitStatusTool = { name: "git_status", description: "Get git repository status", inputSchema: z.object({ repoPath: z.string().describe("Path to git repository"), showAll: z.boolean().default(false).describe("Show all files including untracked"), }), }; export const gitCommitTool = { name: "git_commit", description: "Commit changes to git repository", inputSchema: z.object({ repoPath: z.string().describe("Path to git repository"), message: z.string().describe("Commit message"), addAll: z.boolean().default(false).describe("Add all changes before committing"), }), }; export const gitPushTool = { name: "git_push", description: "Push commits to remote repository", inputSchema: z.object({ repoPath: z.string().describe("Path to git repository"), remote: z.string().default("origin").describe("Remote name"), branch: z.string().optional().describe("Branch to push (defaults to current branch)"), force: z.boolean().default(false).describe("Force push"), }), }; export const gitPullTool = { name: "git_pull", description: "Pull changes from remote repository", inputSchema: z.object({ repoPath: z.string().describe("Path to git repository"), remote: z.string().default("origin").describe("Remote name"), branch: z.string().optional().describe("Branch to pull (defaults to current branch)"), }), }; export const gitBranchTool = { name: "git_branch", description: "Manage git branches", inputSchema: z.object({ repoPath: z.string().describe("Path to git repository"), operation: z.enum(["list", "create", "delete", "switch"]).describe("Branch operation"), branchName: z.string().optional().describe("Branch name (required for create/delete/switch)"), }), }; export const gitLogTool = { name: "git_log", description: "View git commit history", inputSchema: z.object({ repoPath: z.string().describe("Path to git repository"), maxCount: z.number().default(10).describe("Maximum number of commits to show"), format: z.enum(["oneline", "full", "short"]).default("oneline").describe("Log format"), }), }; export const gitDiffTool = { name: "git_diff", description: "Show changes in git repository", inputSchema: z.object({ repoPath: z.string().describe("Path to git repository"), staged: z.boolean().default(false).describe("Show staged changes only"), file: z.string().optional().describe("Specific file to diff"), }), }; export const gitAddTool = { name: "git_add", description: "Stage files for commit", inputSchema: z.object({ repoPath: z.string().describe("Path to git repository"), files: z.array(z.string()).describe("Files to stage"), all: z.boolean().default(false).describe("Stage all changes"), }), }; export const gitInitTool = { name: "git_init", description: "Initialize a new git repository", inputSchema: z.object({ repoPath: z.string().describe("Path where repository should be initialized"), bare: z.boolean().default(false).describe("Create a bare repository"), }), }; // Tool handlers export async function handleGitClone(args: z.infer<typeof gitCloneTool.inputSchema>) { try { let command = `git clone ${args.url} ${args.destination}`; if (args.branch) { command += ` -b ${args.branch}`; } if (args.depth) { command += ` --depth ${args.depth}`; } const { stdout, stderr } = await execAsync(command); return { content: [ { type: "text" as const, text: JSON.stringify({ success: true, url: args.url, destination: args.destination, output: stdout || stderr, }, null, 2), }, ], }; } catch (error: any) { return { content: [ { type: "text" as const, text: JSON.stringify({ success: false, error: error.message, stderr: error.stderr, }, null, 2), }, ], isError: true, }; } } export async function handleGitStatus(args: z.infer<typeof gitStatusTool.inputSchema>) { try { const command = args.showAll ? `cd ${args.repoPath} && git status -u` : `cd ${args.repoPath} && git status`; const { stdout } = await execAsync(command); return { content: [ { type: "text" as const, text: JSON.stringify({ success: true, repoPath: args.repoPath, status: stdout, }, null, 2), }, ], }; } catch (error: any) { return { content: [ { type: "text" as const, text: JSON.stringify({ success: false, error: error.message, repoPath: args.repoPath, }, null, 2), }, ], isError: true, }; } } export async function handleGitCommit(args: z.infer<typeof gitCommitTool.inputSchema>) { try { let command = `cd ${args.repoPath}`; if (args.addAll) { command += ` && git add -A`; } command += ` && git commit -m "${args.message.replace(/"/g, '\\"')}"`; const { stdout } = await execAsync(command); return { content: [ { type: "text" as const, text: JSON.stringify({ success: true, repoPath: args.repoPath, message: args.message, output: stdout, }, null, 2), }, ], }; } catch (error: any) { return { content: [ { type: "text" as const, text: JSON.stringify({ success: false, error: error.message, repoPath: args.repoPath, }, null, 2), }, ], isError: true, }; } } export async function handleGitPush(args: z.infer<typeof gitPushTool.inputSchema>) { try { let command = `cd ${args.repoPath} && git push ${args.remote}`; if (args.branch) { command += ` ${args.branch}`; } if (args.force) { command += ` --force`; } const { stdout, stderr } = await execAsync(command); return { content: [ { type: "text" as const, text: JSON.stringify({ success: true, repoPath: args.repoPath, remote: args.remote, output: stdout || stderr, }, null, 2), }, ], }; } catch (error: any) { return { content: [ { type: "text" as const, text: JSON.stringify({ success: false, error: error.message, repoPath: args.repoPath, }, null, 2), }, ], isError: true, }; } } export async function handleGitPull(args: z.infer<typeof gitPullTool.inputSchema>) { try { let command = `cd ${args.repoPath} && git pull ${args.remote}`; if (args.branch) { command += ` ${args.branch}`; } const { stdout } = await execAsync(command); return { content: [ { type: "text" as const, text: JSON.stringify({ success: true, repoPath: args.repoPath, remote: args.remote, output: stdout, }, null, 2), }, ], }; } catch (error: any) { return { content: [ { type: "text" as const, text: JSON.stringify({ success: false, error: error.message, repoPath: args.repoPath, }, null, 2), }, ], isError: true, }; } } export async function handleGitBranch(args: z.infer<typeof gitBranchTool.inputSchema>) { try { let command = `cd ${args.repoPath} && `; switch (args.operation) { case "list": command += "git branch -a"; break; case "create": if (!args.branchName) throw new Error("branchName required for create operation"); command += `git branch ${args.branchName}`; break; case "delete": if (!args.branchName) throw new Error("branchName required for delete operation"); command += `git branch -d ${args.branchName}`; break; case "switch": if (!args.branchName) throw new Error("branchName required for switch operation"); command += `git checkout ${args.branchName}`; break; } const { stdout } = await execAsync(command); return { content: [ { type: "text" as const, text: JSON.stringify({ success: true, repoPath: args.repoPath, operation: args.operation, output: stdout, }, null, 2), }, ], }; } catch (error: any) { return { content: [ { type: "text" as const, text: JSON.stringify({ success: false, error: error.message, repoPath: args.repoPath, }, null, 2), }, ], isError: true, }; } } export async function handleGitLog(args: z.infer<typeof gitLogTool.inputSchema>) { try { const formatMap = { oneline: "--oneline", full: "--format=fuller", short: "--format=short", }; const command = `cd ${args.repoPath} && git log ${formatMap[args.format]} -n ${args.maxCount}`; const { stdout } = await execAsync(command); return { content: [ { type: "text" as const, text: JSON.stringify({ success: true, repoPath: args.repoPath, log: stdout, }, null, 2), }, ], }; } catch (error: any) { return { content: [ { type: "text" as const, text: JSON.stringify({ success: false, error: error.message, repoPath: args.repoPath, }, null, 2), }, ], isError: true, }; } } export async function handleGitDiff(args: z.infer<typeof gitDiffTool.inputSchema>) { try { let command = `cd ${args.repoPath} && git diff`; if (args.staged) { command += " --staged"; } if (args.file) { command += ` ${args.file}`; } const { stdout } = await execAsync(command); return { content: [ { type: "text" as const, text: JSON.stringify({ success: true, repoPath: args.repoPath, diff: stdout || "No changes", }, null, 2), }, ], }; } catch (error: any) { return { content: [ { type: "text" as const, text: JSON.stringify({ success: false, error: error.message, repoPath: args.repoPath, }, null, 2), }, ], isError: true, }; } } export async function handleGitAdd(args: z.infer<typeof gitAddTool.inputSchema>) { try { let command = `cd ${args.repoPath} && git add`; if (args.all) { command += " -A"; } else { command += ` ${args.files.join(" ")}`; } const { stdout } = await execAsync(command); return { content: [ { type: "text" as const, text: JSON.stringify({ success: true, repoPath: args.repoPath, output: stdout || "Files staged successfully", }, null, 2), }, ], }; } catch (error: any) { return { content: [ { type: "text" as const, text: JSON.stringify({ success: false, error: error.message, repoPath: args.repoPath, }, null, 2), }, ], isError: true, }; } } export async function handleGitInit(args: z.infer<typeof gitInitTool.inputSchema>) { try { let command = `git init ${args.repoPath}`; if (args.bare) { command += " --bare"; } const { stdout } = await execAsync(command); return { content: [ { type: "text" as const, text: JSON.stringify({ success: true, repoPath: args.repoPath, output: stdout, }, null, 2), }, ], }; } catch (error: any) { return { content: [ { type: "text" as const, text: JSON.stringify({ success: false, error: error.message, repoPath: args.repoPath, }, null, 2), }, ], isError: true, }; } }

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/clpi/clp-mcp'

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