13#include <nlohmann/json.hpp>
33static std::pair<std::string, int>
run_git(
34 const std::string& repo_dir,
35 const std::string& git_args) {
37 std::string full_cmd =
38 "git -C " + repo_dir +
" " + git_args +
" 2>&1";
40 FILE* pipe = popen(full_cmd.c_str(),
"r");
41 if (pipe ==
nullptr) {
42 return {
"Failed to open git process", -1};
46 std::array<char, 4096> buf{};
47 while (fgets(buf.data(), buf.size(), pipe) !=
nullptr) {
51 int status = pclose(pipe);
52 int exit_code = WEXITSTATUS(status);
53 logger->info(
"Git: '{}' exit={}, {} chars",
54 git_args, exit_code, output.size());
55 return {output, exit_code};
67 const std::string& output,
int exit_code) {
69 nlohmann::json result;
70 result[
"exit_code"] = exit_code;
71 result[
"output"] = output;
72 return {result.dump(), {}};
92 :
ToolBase(std::move(def)), server_(server) {}
114 server_.
repo_dir().string(),
"status --short");
115 logger->info(
"[git.status] exit={}", rc);
140 :
ToolBase(std::move(def)), server_(server) {}
160 auto args = nlohmann::json::parse(args_json);
161 std::string cmd =
"diff";
162 if (args.value(
"staged",
false)) {
165 if (args.contains(
"file")) {
166 cmd +=
" " + args[
"file"].get<std::string>();
169 logger->info(
"[git.diff] exit={}", rc);
194 :
ToolBase(std::move(def)), server_(server) {}
214 auto args = nlohmann::json::parse(args_json);
215 int count = args.value(
"count", 10);
216 std::string cmd =
"log -" + std::to_string(count);
217 if (args.value(
"oneline",
false)) {
221 logger->info(
"[git.log] exit={}", rc);
246 :
ToolBase(std::move(def)), server_(server) {}
256 auto args = nlohmann::json::parse(args_json);
257 auto repo = server_.
repo_dir().string();
259 if (args.value(
"add_all",
false)) {
260 auto [out, rc] =
run_git(repo,
"add -A");
262 logger->error(
"[git.commit] add -A failed: {}", out);
267 std::string msg = args.at(
"message").get<std::string>();
268 std::string cmd =
"commit -m \"" + msg +
"\"";
269 auto [out, rc] =
run_git(repo, cmd);
270 logger->info(
"[git.commit] exit={}", rc);
295 :
ToolBase(std::move(def)), server_(server) {}
305 auto args = nlohmann::json::parse(args_json);
306 std::string cmd =
"branch -a";
307 if (args.contains(
"create")) {
309 + args[
"create"].get<std::string>();
312 logger->info(
"[git.branch] exit={}", rc);
337 :
ToolBase(std::move(def)), server_(server) {}
347 auto args = nlohmann::json::parse(args_json);
348 std::string target = args.at(
"target").get<std::string>();
349 std::string cmd =
"checkout " + target;
351 logger->info(
"[git.checkout] target='{}' exit={}", target, rc);
376 :
ToolBase(std::move(def)), server_(server) {}
386 auto args = nlohmann::json::parse(args_json);
387 std::string files = args.at(
"files").get<std::string>();
388 std::string cmd =
"add " + files;
390 logger->info(
"[git.add] files='{}' exit={}", files, rc);
415 :
ToolBase(std::move(def)), server_(server) {}
425 auto args = nlohmann::json::parse(args_json);
426 std::string cmd =
"reset HEAD";
427 if (args.contains(
"files")) {
428 cmd +=
" " + args[
"files"].get<std::string>();
431 logger->info(
"[git.reset] exit={}", rc);
449 const std::filesystem::path& repo_dir,
450 const std::string& data_dir)
452 , repo_dir_(repo_dir) {
454 create_git_tools(data_dir +
"/tools");
455 register_git_tools();
457 logger->info(
"GitServer initialized: repo='{}'",
467void GitServer::create_git_tools(
const std::string& tools_dir) {
468 status_ = std::make_unique<GitStatusTool>(
470 diff_ = std::make_unique<GitDiffTool>(
472 log_ = std::make_unique<GitLogTool>(
474 commit_ = std::make_unique<GitCommitTool>(
476 branch_ = std::make_unique<GitBranchTool>(
478 checkout_ = std::make_unique<GitCheckoutTool>(
480 add_ = std::make_unique<GitAddTool>(
482 reset_ = std::make_unique<GitResetTool>(
491void GitServer::register_git_tools() {
518 logger->info(
"Repo directory set to: {}", path);
Git MCP server for version control operations.
GitServer(const std::filesystem::path &repo_dir, const std::string &data_dir)
Construct with repo directory and data dir.
~GitServer() override
Destructor.
bool set_working_dir(const std::string &path) override
Set working directory (repo root).
const std::filesystem::path & repo_dir() const
Get repo directory.
Concrete base class for MCP servers (80% logic).
void register_tool(ToolBase *tool)
Register a tool with this server.
Git MCP server — version control operations.
spdlog initialization and logger access.
ENTROPIC_EXPORT std::shared_ptr< spdlog::logger > get(const std::string &name)
Get or create a named logger.
Activate model on GPU (WARM → ACTIVE).
ToolDefinition load_tool_definition(const std::string &tool_name, const std::string &server_prefix, const std::string &data_dir)
Load a tool definition from a JSON file.
static ServerResponse make_git_response(const std::string &output, int exit_code)
Format a git result as JSON ServerResponse.
MCPAccessLevel
MCP tool access level for per-identity authorization.
@ READ
Read-only operations (e.g., read_file, list_directory)
static std::pair< std::string, int > run_git(const std::string &repo_dir, const std::string &git_args)
Run a git command in a given directory via popen.
MCPServerBase concrete base class + ServerResponse.
Structured result from tool execution.