fix(mcp-inject): git-bash 路径多位置探测——修复 Scoop 安装 Git 时 claude CLI 调用全挂
All checks were successful
Push & PR Check / check (push) Successful in 1m32s
All checks were successful
Push & PR Check / check (push) Successful in 1m32s
迁移实测发现:CLAUDE_CODE_GIT_BASH_PATH 回退路径硬编码 C:\Program Files\Git\bin\bash.exe,Scoop 安装的 Git 不在该位置, 导致 claude mcp add/remove 全部非零退出(存量 bug,组级时代同样存在)。 - find_git_bash():env(校验存在)→ Program Files / Scoop → where git.exe 推导 - try_register_globally 返回 bool;同名 already exists(exit 1)视为成功, 不再每次 inject 刷 warn 日志 - migrate_to_single_server 标记位改以注册成功为条件——CLI 链路不通时 不落标记,下次启动重试(幂等)
This commit is contained in:
parent
01eb941ab9
commit
0d1427f4e9
@ -112,13 +112,47 @@ fn find_claude_bin() -> Option<String> {
|
||||
None
|
||||
}
|
||||
|
||||
fn claude_git_bash() -> String {
|
||||
std::env::var("CLAUDE_CODE_GIT_BASH_PATH")
|
||||
.unwrap_or_else(|_| r"C:\Program Files\Git\bin\bash.exe".to_string())
|
||||
/// 查找 git-bash 路径(claude CLI 在 Windows 上必需)。
|
||||
/// 顺序:环境变量(校验存在)→ 常见安装位置(Program Files / Scoop)→ 从 git.exe 位置推导
|
||||
fn find_git_bash() -> Option<String> {
|
||||
if let Ok(p) = std::env::var("CLAUDE_CODE_GIT_BASH_PATH") {
|
||||
if std::path::Path::new(&p).exists() {
|
||||
return Some(p);
|
||||
}
|
||||
}
|
||||
|
||||
let home = std::env::var("USERPROFILE").unwrap_or_default();
|
||||
let scoop = std::env::var("SCOOP").unwrap_or_else(|_| format!(r"{}\scoop", home));
|
||||
let candidates = [
|
||||
r"C:\Program Files\Git\bin\bash.exe".to_string(),
|
||||
format!(r"{}\apps\git\current\bin\bash.exe", scoop),
|
||||
];
|
||||
for c in &candidates {
|
||||
if std::path::Path::new(c).exists() {
|
||||
return Some(c.clone());
|
||||
}
|
||||
}
|
||||
|
||||
// 从 git.exe 推导:<root>\cmd\git.exe / <root>\mingw64\bin\git.exe → <root>\bin\bash.exe
|
||||
if let Ok(out) = std::process::Command::new("where").arg("git.exe").output() {
|
||||
if out.status.success() {
|
||||
for line in String::from_utf8_lossy(&out.stdout).lines() {
|
||||
let git = std::path::Path::new(line.trim());
|
||||
if let Some(root) = git.parent().and_then(|d| d.parent()) {
|
||||
let bash = root.join("bin").join("bash.exe");
|
||||
if bash.exists() {
|
||||
return Some(bash.to_string_lossy().to_string());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
None
|
||||
}
|
||||
|
||||
/// 将单一全局 lian-jing 服务器注册到 Claude 全局配置(~/.claude.json),best-effort,失败仅记录日志
|
||||
fn try_register_globally(port: u16) {
|
||||
/// 将单一全局 lian-jing 服务器注册到 Claude 全局配置(~/.claude.json)。
|
||||
/// best-effort,失败仅记录日志;返回是否成功(同名已存在视为成功,作为 CLI 链路健康信号)
|
||||
fn try_register_globally(port: u16) -> bool {
|
||||
let server_url = format!("http://127.0.0.1:{}/mcp", port);
|
||||
|
||||
let Some(claude_bin) = find_claude_bin() else {
|
||||
@ -128,10 +162,17 @@ fn try_register_globally(port: u16) {
|
||||
"claude CLI 未找到,跳过全局 MCP 注册",
|
||||
None,
|
||||
);
|
||||
return;
|
||||
return false;
|
||||
};
|
||||
let Some(git_bash) = find_git_bash() else {
|
||||
db::log_event(
|
||||
"mcp_inject",
|
||||
"warn",
|
||||
"git-bash 未找到(claude CLI 依赖),跳过全局 MCP 注册",
|
||||
None,
|
||||
);
|
||||
return false;
|
||||
};
|
||||
|
||||
let git_bash = claude_git_bash();
|
||||
|
||||
match std::process::Command::new(&claude_bin)
|
||||
.args([
|
||||
@ -149,13 +190,25 @@ fn try_register_globally(port: u16) {
|
||||
{
|
||||
Ok(out) if out.status.success() => {
|
||||
db::log_event("mcp_inject", "info", "全局 MCP 注册成功", Some(MCP_KEY));
|
||||
true
|
||||
}
|
||||
Ok(out) => {
|
||||
let msg = format!(
|
||||
"claude mcp add 非零退出: {}",
|
||||
let combined = format!(
|
||||
"{}{}",
|
||||
String::from_utf8_lossy(&out.stdout),
|
||||
String::from_utf8_lossy(&out.stderr)
|
||||
);
|
||||
db::log_event("mcp_inject", "warn", &msg, Some(MCP_KEY));
|
||||
// 同名已存在(exit 1)不是故障——CLI 链路健康,注册目标已达成
|
||||
if combined.contains("already exists") {
|
||||
return true;
|
||||
}
|
||||
db::log_event(
|
||||
"mcp_inject",
|
||||
"warn",
|
||||
&format!("claude mcp add 非零退出: {}", combined),
|
||||
Some(MCP_KEY),
|
||||
);
|
||||
false
|
||||
}
|
||||
Err(e) => {
|
||||
db::log_event(
|
||||
@ -164,6 +217,7 @@ fn try_register_globally(port: u16) {
|
||||
&format!("执行 claude mcp add 失败: {}", e),
|
||||
Some(MCP_KEY),
|
||||
);
|
||||
false
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -175,6 +229,10 @@ pub fn cleanup_legacy_global_registrations() -> Vec<String> {
|
||||
db::log_event("mcp_inject", "warn", "claude CLI 未找到,跳过旧注册清理", None);
|
||||
return Vec::new();
|
||||
};
|
||||
let Some(git_bash) = find_git_bash() else {
|
||||
db::log_event("mcp_inject", "warn", "git-bash 未找到,跳过旧注册清理", None);
|
||||
return Vec::new();
|
||||
};
|
||||
let Ok(conn) = db::pool().get() else {
|
||||
return Vec::new();
|
||||
};
|
||||
@ -186,7 +244,6 @@ pub fn cleanup_legacy_global_registrations() -> Vec<String> {
|
||||
})
|
||||
.unwrap_or_default();
|
||||
|
||||
let git_bash = claude_git_bash();
|
||||
let mut removed = Vec::new();
|
||||
for gid in &group_ids {
|
||||
let mut names = vec![format!("lian-jing-{}", gid)];
|
||||
@ -316,22 +373,25 @@ pub fn migrate_to_single_server() {
|
||||
|
||||
let errors = reinject_all_mcp();
|
||||
let removed = cleanup_legacy_global_registrations();
|
||||
let register_ok = try_register_globally(crate::mcp_server::read_port());
|
||||
|
||||
let summary = format!(
|
||||
"单一服务器迁移完成:重注入失败 {} 个,移除旧全局注册 {} 条{}",
|
||||
"单一服务器迁移完成:重注入失败 {} 个,移除旧全局注册 {} 条,全局注册 {}{}",
|
||||
errors.len(),
|
||||
removed.len(),
|
||||
if register_ok { "成功" } else { "失败" },
|
||||
if errors.is_empty() {
|
||||
String::new()
|
||||
} else {
|
||||
format!(";失败详情: {}", errors.join("; "))
|
||||
}
|
||||
);
|
||||
let level = if errors.is_empty() { "info" } else { "warn" };
|
||||
let level = if errors.is_empty() && register_ok { "info" } else { "warn" };
|
||||
db::log_event("mcp_inject", level, &summary, None);
|
||||
|
||||
// claude CLI 不在时旧全局注册无法清理——不落标记位,等下次启动重试(整个流程幂等)
|
||||
if find_claude_bin().is_none() {
|
||||
// 全局注册失败说明 claude CLI 链路不通(CLI 缺失/git-bash 缺失/命令报错),
|
||||
// 此时旧注册也清不掉——不落标记位,等下次启动重试(整个流程幂等)
|
||||
if !register_ok {
|
||||
return;
|
||||
}
|
||||
if let Ok(conn) = db::pool().get() {
|
||||
|
||||
Loading…
Reference in New Issue
Block a user