git-codereview
Version:
An MCP server that allows AI to review your changes before pushing
98 lines (97 loc) • 3.07 kB
JavaScript
import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
import { z } from "zod";
import { simpleGit } from "simple-git";
const git = (repoPath) => {
return simpleGit({
baseDir: repoPath,
});
};
// Create server instance
const server = new McpServer({
name: "git-codereview",
version: "0.0.1",
});
server.registerTool("get_staged_files", {
title: "Get Staged Files",
description: "Retrieve the list of staged files in a git repository",
inputSchema: {
repoPath: z.string().describe("Full path to the git repository."),
},
}, async ({ repoPath }) => {
try {
const g = git(repoPath);
const stagedFiles = await g.diff(['--cached', '--name-only']);
return {
content: [
{
type: "text",
text: stagedFiles,
}
]
};
}
catch (error) {
console.error("Error initializing git: ", error);
throw new Error("Invalid repository path or git not initialized");
}
});
server.registerTool("get_diff", {
title: "Get Diff",
description: "Retrieve the diff of staged files in a git repository",
inputSchema: {
repoPath: z.string().describe("Full path to the git repository."),
},
}, async ({ repoPath }) => {
try {
const g = git(repoPath);
const diff = await g.diff(['--cached', '--diff-filter=AM', '--ignore-space-change']);
return {
content: [
{
type: "text",
text: diff,
}
]
};
}
catch (error) {
console.error("Error getting diff: ", error);
throw new Error("Invalid repository path or git not initialized");
}
});
server.registerTool("get_file_content", {
title: "Get File Content",
description: "Retrieve the content of a file in a git repository. Use it when the diff doesn't provide enough context.",
inputSchema: {
repoPath: z.string().describe("Full path to the git repository."),
filePath: z.string().describe("Relative path to the file within the repository"),
},
}, async ({ repoPath, filePath }) => {
try {
const g = git(repoPath);
const fileContent = await g.show([`HEAD:${filePath}`]);
return {
content: [
{
type: "text",
text: fileContent,
}
]
};
}
catch (error) {
console.error("Error getting file content: ", error);
throw new Error("Invalid repository path, file path, or git not initialized");
}
});
async function main() {
const transport = new StdioServerTransport();
await server.connect(transport);
console.error("MCP Server is running on stdio...");
}
main().catch((error) => {
console.error("Fatal error in main(): ", error);
process.exit(1);
});