feat(settings): add MCP server status check

This commit is contained in:
t8y2 committed 2026-06-02 00:14:03 +08:00
1 parent 088eaccecc
commit 17504be027
11 files changed
+422 -1

No files matched your search

+105
View File
@@ -0,0 +1,105 @@
use std::process::Command;
use std::time::Duration;
use serde::{Deserialize, Serialize};
const MCP_PACKAGE_NAME: &str = "@dbx-app/mcp-server";
const MCP_LATEST_URL: &str = "https://registry.npmjs.org/@dbx-app%2fmcp-server/latest";
#[derive(Debug, Serialize)]
pub struct McpServerStatus {
pub installed: bool,
pub npm_available: bool,
pub node_version: Option<String>,
pub current_version: Option<String>,
pub latest_version: Option<String>,
pub update_available: bool,
pub bin_path: Option<String>,
pub install_command: String,
pub update_command: String,
pub error: Option<String>,
}
#[derive(Debug, Deserialize)]
struct NpmLatestPackage {
version: String,
}
#[tauri::command]
pub async fn check_mcp_server_status() -> Result<McpServerStatus, String> {
let npm_available = command_success("npm", &["--version"]);
let node_version = command_stdout("node", &["--version"]).ok().and_then(first_non_empty_line);
let current_version = if npm_available { installed_mcp_version() } else { None };
let bin_path = locate_mcp_bin();
let latest_version = fetch_latest_mcp_version().await.ok();
let update_available = current_version
.as_deref()
.zip(latest_version.as_deref())
.is_some_and(|(current, latest)| dbx_core::update::is_newer_version(latest, current));
let error = if npm_available { None } else { Some("npm is not available in PATH.".to_string()) };
Ok(McpServerStatus {
installed: current_version.is_some() || bin_path.is_some(),
npm_available,
node_version,
current_version,
latest_version,
update_available,
bin_path,
install_command: format!("npm install -g {MCP_PACKAGE_NAME}@latest"),
update_command: format!("npm install -g {MCP_PACKAGE_NAME}@latest"),
error,
})
}
async fn fetch_latest_mcp_version() -> Result<String, String> {
let mut builder = reqwest::Client::builder().timeout(Duration::from_secs(10)).user_agent("dbx-mcp-status-checker");
if let Some(proxy_url) = dbx_core::update::system_proxy_url() {
let proxy = reqwest::Proxy::all(&proxy_url).map_err(|e| format!("Invalid system proxy URL: {e}"))?;
builder = builder.proxy(proxy);
}
let client = builder.build().map_err(|e| format!("Failed to create HTTP client: {e}"))?;
let package = client
.get(MCP_LATEST_URL)
.send()
.await
.and_then(|r| r.error_for_status())
.map_err(|e| format!("Failed to check MCP Server updates: {e}"))?
.json::<NpmLatestPackage>()
.await
.map_err(|e| format!("Failed to parse MCP Server update response: {e}"))?;
Ok(package.version)
}
fn installed_mcp_version() -> Option<String> {
let stdout = command_stdout("npm", &["list", "-g", MCP_PACKAGE_NAME, "--json", "--depth=0"]).ok()?;
let value = serde_json::from_str::<serde_json::Value>(&stdout).ok()?;
value
.get("dependencies")
.and_then(|dependencies| dependencies.get(MCP_PACKAGE_NAME))
.and_then(|package| package.get("version"))
.and_then(|version| version.as_str())
.map(ToOwned::to_owned)
}
fn locate_mcp_bin() -> Option<String> {
let (command, args): (&str, &[&str]) =
if cfg!(windows) { ("where", &["dbx-mcp-server"]) } else { ("which", &["dbx-mcp-server"]) };
command_stdout(command, args).ok().and_then(first_non_empty_line)
}
fn command_success(command: &str, args: &[&str]) -> bool {
Command::new(command).args(args).output().is_ok_and(|output| output.status.success())
}
fn command_stdout(command: &str, args: &[&str]) -> Result<String, String> {
let output = Command::new(command).args(args).output().map_err(|e| e.to_string())?;
if !output.status.success() {
return Err(String::from_utf8_lossy(&output.stderr).trim().to_string());
}
Ok(String::from_utf8_lossy(&output.stdout).trim().to_string())
}
fn first_non_empty_line(value: String) -> Option<String> {
value.lines().map(str::trim).find(|line| !line.is_empty()).map(ToOwned::to_owned)
}
+1
View File
@@ -12,6 +12,7 @@ pub mod deep_link;
pub mod external_db;
pub mod external_sql;
pub mod history;
pub mod mcp;
pub mod mcp_bridge;
pub mod mongo_cmd;
pub mod plugins;