feat: support Bun as MCP server runtime
Tolaria's MCP server is pure ESM with only standard `node:fs|path|http|child_process` imports and pure-JS dependencies, so Bun can execute it identically to Node. Until now `find_node()` was the single entry point for spawning the WebSocket bridge and writing external AI tool config — users with Bun but no Node would hit "node not found in PATH or common install locations" and lose access to MCP tools entirely. Introduce `find_mcp_runtime()` which returns the first verifying runtime, preferring Node 18+ when present and falling back to Bun 1+. The generic PATH and login-shell lookup helpers (`find_on_path`, `find_in_user_shell`, `lookup_command`, `lookup_paths`) are now parameterised by command name so both runtimes share the same machinery. Bun candidates cover `~/.bun/bin/bun`, mise/asdf/proto shims, Homebrew, and `%USERPROFILE%\.bun\bin\bun.exe` on Windows. The Codex CLI and Windows .cmd-shim resolution paths keep using the strict `find_node()` since they specifically need Node. `spawn_ws_bridge_with_paths`, `mcp_config_snippet`, and `register_mcp` now resolve through `find_mcp_runtime` so the runtime that gets registered into `~/.claude.json`, `~/.gemini/settings.json`, `~/.cursor/mcp.json`, etc. matches the one actually present on the machine. Locale copy updated from "nodeRequirement" to "runtimeRequirement" across all 15 catalogs to reflect "Node.js 18+ or Bun 1+". Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -24,44 +24,108 @@ pub enum McpStatus {
|
||||
NotInstalled,
|
||||
}
|
||||
|
||||
/// Find the `node` binary path at runtime.
|
||||
pub(crate) fn find_node() -> Result<PathBuf, String> {
|
||||
let mut last_error = None;
|
||||
for path in node_binary_candidates() {
|
||||
match verify_node_version(&path) {
|
||||
Ok(()) => return Ok(path),
|
||||
Err(error) => last_error = Some(error),
|
||||
}
|
||||
}
|
||||
|
||||
Err(last_error.unwrap_or_else(|| "node not found in PATH or common install locations".into()))
|
||||
/// A resolved runtime that can execute the MCP server scripts.
|
||||
#[derive(Debug, Clone)]
|
||||
pub(crate) struct McpRuntime {
|
||||
pub(crate) kind: McpRuntimeKind,
|
||||
pub(crate) binary: PathBuf,
|
||||
}
|
||||
|
||||
fn node_binary_candidates() -> Vec<PathBuf> {
|
||||
let mut candidates = find_node_on_path();
|
||||
candidates.extend(find_node_in_user_shell());
|
||||
candidates.extend(fallback_node_paths());
|
||||
/// Which JS runtime was selected for the MCP server.
|
||||
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
|
||||
pub(crate) enum McpRuntimeKind {
|
||||
Node,
|
||||
Bun,
|
||||
}
|
||||
|
||||
impl McpRuntimeKind {
|
||||
fn binary_name(self) -> &'static str {
|
||||
match self {
|
||||
McpRuntimeKind::Node => node_binary_name(),
|
||||
McpRuntimeKind::Bun => bun_binary_name(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Find any supported MCP runtime, preferring Node over Bun.
|
||||
pub(crate) fn find_mcp_runtime() -> Result<McpRuntime, String> {
|
||||
let mut last_error = None;
|
||||
for kind in [McpRuntimeKind::Node, McpRuntimeKind::Bun] {
|
||||
if let Some(binary) = try_runtime(kind, &mut last_error) {
|
||||
return Ok(McpRuntime { kind, binary });
|
||||
}
|
||||
}
|
||||
Err(last_error.unwrap_or_else(|| {
|
||||
"No supported MCP runtime found. Install Node.js 18+ or Bun 1+ and ensure it's on PATH."
|
||||
.into()
|
||||
}))
|
||||
}
|
||||
|
||||
/// Find the `node` binary specifically. Used by Codex/CLI agent shims that
|
||||
/// require Node and cannot fall back to Bun.
|
||||
pub(crate) fn find_node() -> Result<PathBuf, String> {
|
||||
let mut last_error = None;
|
||||
if let Some(binary) = try_runtime(McpRuntimeKind::Node, &mut last_error) {
|
||||
return Ok(binary);
|
||||
}
|
||||
Err(last_error.unwrap_or_else(|| {
|
||||
format!(
|
||||
"{} not found in PATH or common install locations",
|
||||
McpRuntimeKind::Node.binary_name()
|
||||
)
|
||||
}))
|
||||
}
|
||||
|
||||
fn try_runtime(kind: McpRuntimeKind, last_error: &mut Option<String>) -> Option<PathBuf> {
|
||||
for path in runtime_binary_candidates(kind) {
|
||||
match verify_runtime_version(kind, &path) {
|
||||
Ok(()) => return Some(path),
|
||||
Err(error) => *last_error = Some(error),
|
||||
}
|
||||
}
|
||||
None
|
||||
}
|
||||
|
||||
fn runtime_binary_candidates(kind: McpRuntimeKind) -> Vec<PathBuf> {
|
||||
let command = kind.binary_name();
|
||||
let mut candidates = find_on_path(command);
|
||||
candidates.extend(find_in_user_shell(command));
|
||||
candidates.extend(fallback_paths_for(kind));
|
||||
candidates
|
||||
}
|
||||
|
||||
fn find_node_on_path() -> Vec<PathBuf> {
|
||||
node_lookup_command()
|
||||
fn fallback_paths_for(kind: McpRuntimeKind) -> Vec<PathBuf> {
|
||||
match kind {
|
||||
McpRuntimeKind::Node => fallback_node_paths(),
|
||||
McpRuntimeKind::Bun => fallback_bun_paths(),
|
||||
}
|
||||
}
|
||||
|
||||
fn verify_runtime_version(kind: McpRuntimeKind, path: &Path) -> Result<(), String> {
|
||||
match kind {
|
||||
McpRuntimeKind::Node => verify_node_version(path),
|
||||
McpRuntimeKind::Bun => verify_bun_version(path),
|
||||
}
|
||||
}
|
||||
|
||||
fn find_on_path(command: &str) -> Vec<PathBuf> {
|
||||
lookup_command(command)
|
||||
.output()
|
||||
.ok()
|
||||
.filter(|output| output.status.success())
|
||||
.map(|output| node_lookup_paths(&output.stdout))
|
||||
.map(|output| lookup_paths(&output.stdout))
|
||||
.unwrap_or_default()
|
||||
}
|
||||
|
||||
fn find_node_in_user_shell() -> Vec<PathBuf> {
|
||||
fn find_in_user_shell(command: &str) -> Vec<PathBuf> {
|
||||
user_shell_candidates()
|
||||
.into_iter()
|
||||
.filter(|shell| shell.exists())
|
||||
.filter_map(|shell| command_path_from_shell(&shell, "node"))
|
||||
.filter_map(|shell| command_path_from_shell(&shell, command))
|
||||
.collect()
|
||||
}
|
||||
|
||||
fn node_lookup_paths(stdout: &[u8]) -> Vec<PathBuf> {
|
||||
fn lookup_paths(stdout: &[u8]) -> Vec<PathBuf> {
|
||||
String::from_utf8_lossy(stdout)
|
||||
.lines()
|
||||
.map(str::trim)
|
||||
@@ -148,14 +212,14 @@ fn node_major_version(version: &str) -> Option<u32> {
|
||||
.and_then(|major| major.parse().ok())
|
||||
}
|
||||
|
||||
fn node_lookup_command() -> Command {
|
||||
fn lookup_command(command: &str) -> Command {
|
||||
#[cfg(windows)]
|
||||
let mut command = subprocess::command("where.exe");
|
||||
let mut cmd = subprocess::command("where.exe");
|
||||
#[cfg(not(windows))]
|
||||
let mut command = subprocess::command("which");
|
||||
let mut cmd = subprocess::command("which");
|
||||
|
||||
command.arg("node");
|
||||
command
|
||||
cmd.arg(command);
|
||||
cmd
|
||||
}
|
||||
|
||||
fn fallback_node_paths() -> Vec<PathBuf> {
|
||||
@@ -230,6 +294,82 @@ fn node_binary_name() -> &'static str {
|
||||
}
|
||||
}
|
||||
|
||||
fn fallback_bun_paths() -> Vec<PathBuf> {
|
||||
let mut candidates = vec![
|
||||
PathBuf::from("/opt/homebrew/bin/bun"),
|
||||
PathBuf::from("/usr/local/bin/bun"),
|
||||
];
|
||||
|
||||
#[cfg(windows)]
|
||||
{
|
||||
if let Some(profile) = std::env::var_os("USERPROFILE") {
|
||||
candidates.push(
|
||||
PathBuf::from(profile)
|
||||
.join(".bun")
|
||||
.join("bin")
|
||||
.join("bun.exe"),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
if let Some(home) = dirs::home_dir() {
|
||||
candidates.extend(bun_binary_candidates_for_home(&home));
|
||||
}
|
||||
|
||||
candidates
|
||||
.into_iter()
|
||||
.filter(|path| path.is_file())
|
||||
.collect()
|
||||
}
|
||||
|
||||
fn bun_binary_candidates_for_home(home: &Path) -> Vec<PathBuf> {
|
||||
vec![
|
||||
home.join(".bun").join("bin").join(bun_binary_name()),
|
||||
home.join(".local/share/mise/shims")
|
||||
.join(bun_binary_name()),
|
||||
home.join(".mise").join("shims").join(bun_binary_name()),
|
||||
home.join(".asdf").join("shims").join(bun_binary_name()),
|
||||
home.join(".proto").join("bin").join(bun_binary_name()),
|
||||
]
|
||||
}
|
||||
|
||||
fn bun_binary_name() -> &'static str {
|
||||
if cfg!(windows) {
|
||||
"bun.exe"
|
||||
} else {
|
||||
"bun"
|
||||
}
|
||||
}
|
||||
|
||||
fn verify_bun_version(bun: &Path) -> Result<(), String> {
|
||||
let output = subprocess::command(bun)
|
||||
.arg("--version")
|
||||
.output()
|
||||
.map_err(|e| format!("Failed to run {} --version: {e}", bun.display()))?;
|
||||
if !output.status.success() {
|
||||
return Err(format!(
|
||||
"{} --version failed; install Bun 1+ and make it available on PATH",
|
||||
bun.display()
|
||||
));
|
||||
}
|
||||
|
||||
let raw_version = String::from_utf8_lossy(&output.stdout);
|
||||
let Some(major) = node_major_version(&raw_version) else {
|
||||
return Err(format!(
|
||||
"Cannot parse Bun version from '{}'",
|
||||
raw_version.trim()
|
||||
));
|
||||
};
|
||||
if major < 1 {
|
||||
return Err(format!(
|
||||
"Bun 1+ is required for Tolaria MCP tools; found {}",
|
||||
raw_version.trim()
|
||||
));
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// Resolve the path to `mcp-server/`.
|
||||
///
|
||||
/// In dev mode, prefers `CARGO_MANIFEST_DIR` and falls back to runtime checkout ancestors.
|
||||
@@ -407,13 +547,13 @@ pub fn spawn_ws_bridge_with_paths(
|
||||
vault_path: impl AsRef<Path>,
|
||||
vault_paths: &[PathBuf],
|
||||
) -> Result<Child, String> {
|
||||
let node = find_node()?;
|
||||
let runtime = find_mcp_runtime()?;
|
||||
let server_dir = mcp_server_dir()?;
|
||||
let script = server_dir.join("ws-bridge.js");
|
||||
let vault_path = vault_path.as_ref();
|
||||
let active_vault_paths = active_vault_paths_json(vault_path, vault_paths);
|
||||
|
||||
let mut command = subprocess::command(node);
|
||||
let mut command = subprocess::command(&runtime.binary);
|
||||
let child = command
|
||||
.arg(&script)
|
||||
.env("VAULT_PATH", vault_path)
|
||||
@@ -427,8 +567,9 @@ pub fn spawn_ws_bridge_with_paths(
|
||||
.map_err(|e| format!("Failed to spawn ws-bridge: {e}"))?;
|
||||
|
||||
log::info!(
|
||||
"ws-bridge spawned (pid: {}, vault: {})",
|
||||
"ws-bridge spawned (pid: {}, runtime: {:?}, vault: {})",
|
||||
child.id(),
|
||||
runtime.kind,
|
||||
vault_path.display()
|
||||
);
|
||||
Ok(child)
|
||||
@@ -498,10 +639,10 @@ fn entry_has_ui_port(entry: &serde_json::Value) -> bool {
|
||||
}
|
||||
|
||||
/// Build the durable external MCP server entry JSON for an index.js path.
|
||||
fn build_mcp_entry(node_command: &str, index_js: &str) -> serde_json::Value {
|
||||
fn build_mcp_entry(runtime_command: &str, index_js: &str) -> serde_json::Value {
|
||||
serde_json::json!({
|
||||
"type": "stdio",
|
||||
"command": node_command,
|
||||
"command": runtime_command,
|
||||
"args": [index_js],
|
||||
"env": {
|
||||
"WS_UI_PORT": "9711"
|
||||
@@ -521,13 +662,15 @@ fn build_mcp_config_snippet(entry: &serde_json::Value) -> Result<String, String>
|
||||
/// Build the exact MCP config JSON users can copy into compatible tools.
|
||||
pub fn mcp_config_snippet(vault_path: &str) -> Result<String, String> {
|
||||
let _ = vault_path;
|
||||
let node = find_node().map_err(|e| {
|
||||
format!("Node.js 18+ is required on PATH before Tolaria can build MCP config: {e}")
|
||||
let runtime = find_mcp_runtime().map_err(|e| {
|
||||
format!(
|
||||
"Node.js 18+ or Bun 1+ is required on PATH before Tolaria can build MCP config: {e}"
|
||||
)
|
||||
})?;
|
||||
let server_dir = mcp_server_dir_for_registration()?;
|
||||
let index_js = server_dir.join("index.js").to_string_lossy().into_owned();
|
||||
let node_command = node.to_string_lossy().into_owned();
|
||||
let entry = build_mcp_entry(&node_command, &index_js);
|
||||
let runtime_command = runtime.binary.to_string_lossy().into_owned();
|
||||
let entry = build_mcp_entry(&runtime_command, &index_js);
|
||||
|
||||
build_mcp_config_snippet(&entry)
|
||||
}
|
||||
@@ -549,15 +692,17 @@ fn register_mcp_to_configs(entry: &serde_json::Value, config_paths: &[PathBuf])
|
||||
/// Register Tolaria as an MCP server in external AI tool config files.
|
||||
pub fn register_mcp(vault_path: &str) -> Result<String, String> {
|
||||
let _ = vault_path;
|
||||
let node = find_node().map_err(|e| {
|
||||
format!("Node.js 18+ is required on PATH before Tolaria can register MCP tools: {e}")
|
||||
let runtime = find_mcp_runtime().map_err(|e| {
|
||||
format!(
|
||||
"Node.js 18+ or Bun 1+ is required on PATH before Tolaria can register MCP tools: {e}"
|
||||
)
|
||||
})?;
|
||||
let server_dir = mcp_server_dir_for_registration()?;
|
||||
let index_js = server_dir.join("index.js").to_string_lossy().into_owned();
|
||||
let node_command = node.to_string_lossy().into_owned();
|
||||
let runtime_command = runtime.binary.to_string_lossy().into_owned();
|
||||
|
||||
let entry = build_mcp_entry(&node_command, &index_js);
|
||||
let opencode_entry = opencode::build_entry(&node_command, &index_js);
|
||||
let entry = build_mcp_entry(&runtime_command, &index_js);
|
||||
let opencode_entry = opencode::build_entry(&runtime_command, &index_js);
|
||||
if let Some(config_path) = opencode::config_path() {
|
||||
if let Err(e) = opencode::upsert_config(&config_path, &opencode_entry) {
|
||||
log::warn!("Failed to update {}: {}", config_path.display(), e);
|
||||
@@ -793,10 +938,10 @@ mod tests {
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn node_lookup_paths_keep_non_empty_lines_in_order() {
|
||||
fn lookup_paths_keep_non_empty_lines_in_order() {
|
||||
let stdout = b"\nC:\\Program Files\\nodejs\\node.exe\r\nC:\\Other\\node.exe\r\n";
|
||||
assert_eq!(
|
||||
node_lookup_paths(stdout),
|
||||
lookup_paths(stdout),
|
||||
vec![
|
||||
PathBuf::from("C:\\Program Files\\nodejs\\node.exe"),
|
||||
PathBuf::from("C:\\Other\\node.exe"),
|
||||
@@ -1143,6 +1288,63 @@ mod tests {
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn find_mcp_runtime_returns_valid_runtime() {
|
||||
let runtime = find_mcp_runtime().unwrap();
|
||||
assert!(
|
||||
runtime.binary.exists(),
|
||||
"runtime binary should exist at {:?}",
|
||||
runtime.binary
|
||||
);
|
||||
let expected = match runtime.kind {
|
||||
McpRuntimeKind::Node => "node",
|
||||
McpRuntimeKind::Bun => "bun",
|
||||
};
|
||||
assert!(
|
||||
runtime.binary.to_string_lossy().contains(expected),
|
||||
"path should contain '{expected}': {:?}",
|
||||
runtime.binary
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn bun_binary_candidates_include_shell_managed_installs() {
|
||||
let home = PathBuf::from("/Users/alex");
|
||||
let candidates = bun_binary_candidates_for_home(&home);
|
||||
let expected = [
|
||||
home.join(".bun/bin/bun"),
|
||||
home.join(".local/share/mise/shims/bun"),
|
||||
home.join(".mise/shims/bun"),
|
||||
home.join(".asdf/shims/bun"),
|
||||
home.join(".proto/bin/bun"),
|
||||
];
|
||||
|
||||
for candidate in expected {
|
||||
assert!(
|
||||
candidates.contains(&candidate),
|
||||
"missing {}",
|
||||
candidate.display()
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn verify_bun_version_accepts_real_bun_binary() {
|
||||
let Ok(bun) = find_bun_for_test() else {
|
||||
// Bun is optional on dev machines; skip when absent.
|
||||
return;
|
||||
};
|
||||
verify_bun_version(&bun).expect("installed bun should satisfy version requirement");
|
||||
}
|
||||
|
||||
fn find_bun_for_test() -> Result<PathBuf, String> {
|
||||
let mut last_error = None;
|
||||
if let Some(bin) = try_runtime(McpRuntimeKind::Bun, &mut last_error) {
|
||||
return Ok(bin);
|
||||
}
|
||||
Err(last_error.unwrap_or_else(|| "bun not present in test environment".into()))
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn mcp_server_dir_resolves_in_dev() {
|
||||
let dir = mcp_server_dir().unwrap();
|
||||
|
||||
@@ -196,7 +196,7 @@ export function McpSetupDialog({
|
||||
data-testid="mcp-setup-scroll-body"
|
||||
>
|
||||
<p>
|
||||
{t('mcp.setup.nodeRequirement')}
|
||||
{t('mcp.setup.runtimeRequirement')}
|
||||
</p>
|
||||
<p>
|
||||
{t('mcp.setup.writeEntryDescription', { entry: 'tolaria' })}
|
||||
|
||||
@@ -313,7 +313,7 @@
|
||||
"mcp.setup.disconnect": "Verbindung trennen",
|
||||
"mcp.setup.connecting": "Verbindung wird hergestellt …",
|
||||
"mcp.setup.disconnecting": "Verbindung wird getrennt …",
|
||||
"mcp.setup.nodeRequirement": "Für diese Einrichtung sind Node.js 18+ im PATH und ein MCP-kompatibles Desktop-Tool erforderlich. Tolaria prüft Node.js, bevor es die Konfiguration schreibt, damit das Tool nicht auf einen fehlerhaften Befehl verweist.",
|
||||
"mcp.setup.runtimeRequirement": "Für diese Einrichtung sind Node.js 18+ oder Bun 1+ im PATH und ein MCP-kompatibles Desktop-Tool erforderlich. Tolaria prüft die Laufzeitumgebung, bevor es die Konfiguration schreibt, damit das Tool nicht auf einen fehlerhaften Befehl verweist.",
|
||||
"mcp.setup.writeEntryDescription": "Wenn Sie diese Aktion bestätigen, wird der einzige {entry}-MCP-Eintrag von Tolaria geschrieben oder aktualisiert in:",
|
||||
"mcp.setup.clientPathsDescription": "Die Claude Code CLI liest ~/.claude.json, die Gemini CLI liest ~/.gemini/settings.json, Cursor liest ~/.cursor/mcp.json, und der allgemeine Pfad ~/.config/mcp/mcp.json wird von anderen MCP-kompatiblen Tools erkannt. Beim Schließen bleiben alle Dateien unverändert, es sei denn, Sie stellen eine Verbindung her oder trennen sie. Das Wiederherstellen der Verbindung ist idempotent, und das Trennen der Verbindung entfernt den Tolaria-Eintrag erneut.",
|
||||
"mcp.setup.geminiGuidanceDescription": "Für die Gemini-CLI sind eine eigene Installation und eine eigene Anmeldung erforderlich. Verwenden Sie „Restore Tolaria AI Guidance“, wenn Sie einen GEMINI.md-Kompatibilitäts-Shim für den Vault-Root benötigen, der Gemini zurück zu den gemeinsamen AGENTS.md-Anweisungen führt, ohne die benutzerdefinierte Anleitung zu überschreiben.",
|
||||
|
||||
@@ -313,7 +313,7 @@
|
||||
"mcp.setup.disconnect": "Disconnect",
|
||||
"mcp.setup.connecting": "Connecting…",
|
||||
"mcp.setup.disconnecting": "Disconnecting…",
|
||||
"mcp.setup.nodeRequirement": "This setup requires Node.js 18+ on PATH and an MCP-compatible desktop tool. Tolaria checks Node.js before writing config so the tool is not left pointing at a broken command.",
|
||||
"mcp.setup.runtimeRequirement": "This setup requires Node.js 18+ or Bun 1+ on PATH and an MCP-compatible desktop tool. Tolaria checks the runtime before writing config so the tool is not left pointing at a broken command.",
|
||||
"mcp.setup.writeEntryDescription": "Confirming this action will write or update Tolaria's single {entry} MCP entry in:",
|
||||
"mcp.setup.clientPathsDescription": "Claude Code CLI reads ~/.claude.json, Gemini CLI reads ~/.gemini/settings.json, Cursor reads ~/.cursor/mcp.json, and the generic ~/.config/mcp/mcp.json path is picked up by other MCP-compatible tools. Closing leaves all files untouched unless you connect or disconnect, reconnecting is idempotent, and disconnecting removes Tolaria's entry again.",
|
||||
"mcp.setup.geminiGuidanceDescription": "Gemini CLI needs its own install and sign-in. Use Restore Tolaria AI Guidance when you want a vault-root GEMINI.md compatibility shim that points Gemini back to the shared AGENTS.md instructions without overwriting custom guidance.",
|
||||
|
||||
@@ -313,7 +313,7 @@
|
||||
"mcp.setup.disconnect": "Desconectar",
|
||||
"mcp.setup.connecting": "Conectando…",
|
||||
"mcp.setup.disconnecting": "Desconectando…",
|
||||
"mcp.setup.nodeRequirement": "Esta configuración requiere Node.js 18 o superior en PATH y una herramienta de escritorio compatible con MCP. Tolaria verifica Node.js antes de escribir la configuración para que la herramienta no apunte a un comando que no funcione.",
|
||||
"mcp.setup.runtimeRequirement": "Esta configuración requiere Node.js 18+ o Bun 1+ en PATH y una herramienta de escritorio compatible con MCP. Tolaria verifica el runtime antes de escribir la configuración para que la herramienta no apunte a un comando que no funcione.",
|
||||
"mcp.setup.writeEntryDescription": "Al confirmar esta acción, se escribirá o actualizará la única entrada MCP de Tolaria ({entry}) en:",
|
||||
"mcp.setup.clientPathsDescription": "La CLI de Claude Code lee ~/.claude.json, la CLI de Gemini lee ~/.gemini/settings.json, Cursor lee ~/.cursor/mcp.json y otras herramientas compatibles con MCP leen la ruta genérica ~/.config/mcp/mcp.json. Al cerrar, todos los archivos permanecen intactos a menos que se conecte o se desconecte; la reconexión es idempotente y la desconexión vuelve a eliminar la entrada de Tolaria.",
|
||||
"mcp.setup.geminiGuidanceDescription": "La CLI de Gemini requiere su propia instalación e inicio de sesión. Utilice Restore Tolaria AI Guidance cuando desee un shim de compatibilidad con GEMINI.md en la raíz del vault que dirija a Gemini de nuevo a las instrucciones compartidas de AGENTS.md sin sobrescribir la guía personalizada.",
|
||||
|
||||
@@ -313,7 +313,7 @@
|
||||
"mcp.setup.disconnect": "Desconectar",
|
||||
"mcp.setup.connecting": "Conectando…",
|
||||
"mcp.setup.disconnecting": "Desconectando…",
|
||||
"mcp.setup.nodeRequirement": "Esta configuración requiere Node.js 18 o superior en PATH y una herramienta de escritorio compatible con MCP. Tolaria comprueba Node.js antes de escribir la configuración para que la herramienta no apunte a un comando que no funcione.",
|
||||
"mcp.setup.runtimeRequirement": "Esta configuración requiere Node.js 18+ o Bun 1+ en PATH y una herramienta de escritorio compatible con MCP. Tolaria comprueba el runtime antes de escribir la configuración para que la herramienta no apunte a un comando que no funcione.",
|
||||
"mcp.setup.writeEntryDescription": "Al confirmar esta acción, se escribirá o se actualizará la única entrada MCP de Tolaria ({entry}) en:",
|
||||
"mcp.setup.clientPathsDescription": "La CLI de Claude Code lee ~/.claude.json, la CLI de Gemini lee ~/.gemini/settings.json, Cursor lee ~/.cursor/mcp.json y otras herramientas compatibles con MCP leen la ruta genérica ~/.config/mcp/mcp.json. Al cerrar la aplicación, todos los archivos permanecen intactos a menos que te conectes o te desconectes; volver a conectarte es idempotente y, al desconectarte, se vuelve a eliminar la entrada de Tolaria.",
|
||||
"mcp.setup.geminiGuidanceDescription": "La CLI de Gemini requiere su propia instalación e inicio de sesión. Utiliza Restore Tolaria AI Guidance cuando quieras una capa de compatibilidad GEMINI.md en la raíz del almacén que redirija a Gemini a las instrucciones compartidas de AGENTS.md sin sobrescribir la guía personalizada.",
|
||||
|
||||
@@ -313,7 +313,7 @@
|
||||
"mcp.setup.disconnect": "Déconnecter",
|
||||
"mcp.setup.connecting": "Connexion en cours…",
|
||||
"mcp.setup.disconnecting": "Déconnexion en cours…",
|
||||
"mcp.setup.nodeRequirement": "Cette configuration nécessite Node.js 18 ou une version ultérieure dans le PATH et un outil de bureau compatible MCP. Tolaria vérifie Node.js avant d'écrire la configuration afin que l'outil ne pointe pas vers une commande défaillante.",
|
||||
"mcp.setup.runtimeRequirement": "Cette configuration nécessite Node.js 18+ ou Bun 1+ dans le PATH et un outil de bureau compatible MCP. Tolaria vérifie le runtime avant d'écrire la configuration afin que l'outil ne pointe pas vers une commande défaillante.",
|
||||
"mcp.setup.writeEntryDescription": "Si vous confirmez cette action, la seule entrée MCP {entry} de Tolaria sera écrite ou mise à jour dans :",
|
||||
"mcp.setup.clientPathsDescription": "La CLI de Claude Code lit ~/.claude.json, la CLI de Gemini lit ~/.gemini/settings.json, Cursor lit ~/.cursor/mcp.json, et le chemin générique ~/.config/mcp/mcp.json est pris en charge par d'autres outils compatibles MCP. Lorsque vous fermez Tolaria, tous les fichiers restent inchangés, sauf si vous vous connectez ou vous déconnectez ; la reconnexion est idempotente et la déconnexion supprime à nouveau l'entrée de Tolaria.",
|
||||
"mcp.setup.geminiGuidanceDescription": "La CLI Gemini nécessite sa propre installation et sa propre connexion. Utilisez Restore Tolaria AI Guidance lorsque vous souhaitez obtenir un calque de compatibilité GEMINI.md au niveau de la racine du coffre-fort, qui renvoie Gemini vers les instructions AGENTS.md partagées sans écraser les instructions personnalisées.",
|
||||
|
||||
@@ -313,7 +313,7 @@
|
||||
"mcp.setup.disconnect": "Disconnetti",
|
||||
"mcp.setup.connecting": "Connessione in corso…",
|
||||
"mcp.setup.disconnecting": "Disconnessione in corso…",
|
||||
"mcp.setup.nodeRequirement": "Per questa configurazione sono necessari Node.js 18 o versioni successive nel PATH e uno strumento desktop compatibile con MCP. Tolaria verifica Node.js prima di scrivere la configurazione, in modo che lo strumento non punti a un comando non funzionante.",
|
||||
"mcp.setup.runtimeRequirement": "Per questa configurazione sono necessari Node.js 18+ o Bun 1+ nel PATH e uno strumento desktop compatibile con MCP. Tolaria verifica il runtime prima di scrivere la configurazione, in modo che lo strumento non punti a un comando non funzionante.",
|
||||
"mcp.setup.writeEntryDescription": "Confermando questa azione, verrà scritta o aggiornata l'unica voce MCP {entry} di Tolaria in:",
|
||||
"mcp.setup.clientPathsDescription": "La CLI di Claude Code legge ~/.claude.json, la CLI di Gemini legge ~/.gemini/settings.json, Cursor legge ~/.cursor/mcp.json e il percorso generico ~/.config/mcp/mcp.json viene utilizzato da altri strumenti compatibili con MCP. Alla chiusura, tutti i file rimangono inalterati a meno che non ci si connetta o si disconnetta; la riconnessione è idempotente e la disconnessione rimuove nuovamente la voce di Tolaria.",
|
||||
"mcp.setup.geminiGuidanceDescription": "La CLI di Gemini richiede una propria installazione e un proprio accesso. Utilizza Restore Tolaria AI Guidance quando desideri uno shim di compatibilità GEMINI.md a livello di vault-root che reindirizzi Gemini alle istruzioni condivise di AGENTS.md senza sovrascrivere la guida personalizzata.",
|
||||
|
||||
@@ -313,7 +313,7 @@
|
||||
"mcp.setup.disconnect": "切断",
|
||||
"mcp.setup.connecting": "接続中…",
|
||||
"mcp.setup.disconnecting": "切断中…",
|
||||
"mcp.setup.nodeRequirement": "このセットアップには、PATH に Node.js 18 以上が設定されていること、および MCP 対応のデスクトップツールが必要です。Tolariaは、構成を書き込む前にNode.jsを確認するため、ツールが機能しないコマンドを指す状態になることはありません。",
|
||||
"mcp.setup.runtimeRequirement": "このセットアップには、PATH に Node.js 18+ または Bun 1+ が設定されていること、および MCP 対応のデスクトップツールが必要です。Tolaria は構成を書き込む前にランタイムを確認するため、ツールが機能しないコマンドを指す状態になることはありません。",
|
||||
"mcp.setup.writeEntryDescription": "このアクションを確認すると、Tolariaの単一の{entry} MCPエントリが次の場所に書き込まれるか、更新されます:",
|
||||
"mcp.setup.clientPathsDescription": "Claude Code CLI は ~/.claude.json を読み取り、Gemini CLI は ~/.gemini/settings.json を読み取り、Cursor は ~/.cursor/mcp.json を読み取ります。また、一般的なパス ~/.config/mcp/mcp.json は、他の MCP 互換ツールによって読み取られます。閉じても、接続または切断しない限り、すべてのファイルは変更されません。再接続は冪等性があり、切断すると Tolaria のエントリは再度削除されます。",
|
||||
"mcp.setup.geminiGuidanceDescription": "Gemini CLIは、独自のインストールとサインインが必要です。カスタムガイダンスを上書きせずに、Gemini を共有の AGENTS.md 指示に戻すための vault-root GEMINI.md 互換シムが必要な場合は、「Restore Tolaria AI Guidance」を使用します。",
|
||||
|
||||
@@ -313,7 +313,7 @@
|
||||
"mcp.setup.disconnect": "연결 해제",
|
||||
"mcp.setup.connecting": "연결 중…",
|
||||
"mcp.setup.disconnecting": "연결 해제 중…",
|
||||
"mcp.setup.nodeRequirement": "이 설정을 사용하려면 PATH에 Node.js 18 이상이 있어야 하며 MCP와 호환되는 데스크톱 도구가 필요합니다. Tolaria는 구성 파일을 작성하기 전에 Node.js를 확인하여 도구가 잘못된 명령어를 가리키지 않도록 합니다.",
|
||||
"mcp.setup.runtimeRequirement": "이 설정을 사용하려면 PATH에 Node.js 18+ 또는 Bun 1+가 있어야 하며 MCP와 호환되는 데스크톱 도구가 필요합니다. Tolaria는 구성 파일을 작성하기 전에 런타임을 확인하여 도구가 잘못된 명령어를 가리키지 않도록 합니다.",
|
||||
"mcp.setup.writeEntryDescription": "이 작업을 확인하면 Tolaria의 단일 {entry} MCP 항목이 다음 위치에 작성되거나 업데이트됩니다:",
|
||||
"mcp.setup.clientPathsDescription": "Claude Code CLI는 ~/.claude.json 파일을 읽고, Gemini CLI는 ~/.gemini/settings.json 파일을 읽고, Cursor는 ~/.cursor/mcp.json 파일을 읽으며, 일반 경로인 ~/.config/mcp/mcp.json은 다른 MCP 호환 도구에서 읽습니다. 종료 시 연결하거나 연결 해제하지 않는 한 모든 파일이 그대로 유지됩니다. 다시 연결하는 것은 멱등적이며, 연결 해제 시 Tolaria의 항목이 다시 제거됩니다.",
|
||||
"mcp.setup.geminiGuidanceDescription": "Gemini CLI는 별도의 설치 및 로그인이 필요합니다. 사용자 지정 가이드를 덮어쓰지 않고 Gemini를 공유 AGENTS.md 지침으로 다시 연결하는 볼트 루트 GEMINI.md 호환성 시름을 원할 경우, 'Restore Tolaria AI Guidance'를 사용하세요.",
|
||||
|
||||
@@ -313,7 +313,7 @@
|
||||
"mcp.setup.disconnect": "Rozłącz",
|
||||
"mcp.setup.connecting": "Łączenie…",
|
||||
"mcp.setup.disconnecting": "Rozłączanie…",
|
||||
"mcp.setup.nodeRequirement": "Ta konfiguracja wymaga Node.js 18+ w PATH i narzędzia kompatybilnego z MCP. Tolaria sprawdza Node.js przed zapisem konfiguracji, aby narzędzie nie wskazywało na uszkodzone polecenie.",
|
||||
"mcp.setup.runtimeRequirement": "Ta konfiguracja wymaga Node.js 18+ lub Bun 1+ w PATH oraz narzędzia kompatybilnego z MCP. Tolaria sprawdza środowisko uruchomieniowe przed zapisem konfiguracji, aby narzędzie nie wskazywało na uszkodzone polecenie.",
|
||||
"mcp.setup.writeEntryDescription": "Potwierdzenie tej akcji zapisze lub zaktualizuje pojedynczy wpis MCP {entry} Tolaria w:",
|
||||
"mcp.setup.clientPathsDescription": "Claude Code CLI czyta ~/.claude.json, Gemini CLI czyta ~/.gemini/settings.json, Cursor czyta ~/.cursor/mcp.json, a ogólna ścieżka ~/.config/mcp/mcp.json jest obsługiwana przez inne narzędzia kompatybilne z MCP. Zamknięcie pozostawia wszystkie pliki nietknięte, chyba że połączysz lub rozłączysz; ponowne połączenie jest idempotentne, a rozłączenie usuwa wpis Tolaria.",
|
||||
"mcp.setup.geminiGuidanceDescription": "Gemini CLI wymaga własnej instalacji i logowania. Użyj Przywróć wytyczne Tolaria AI, gdy chcesz plik GEMINI.md w katalogu głównym sejfu wskazujący na wspólne instrukcje AGENTS.md bez nadpisywania niestandardowych wytycznych.",
|
||||
|
||||
@@ -313,7 +313,7 @@
|
||||
"mcp.setup.disconnect": "Desconectar",
|
||||
"mcp.setup.connecting": "Conectando…",
|
||||
"mcp.setup.disconnecting": "Desconectando…",
|
||||
"mcp.setup.nodeRequirement": "Esta configuração requer o Node.js 18 ou superior no PATH e uma ferramenta de desktop compatível com MCP. O Tolaria verifica o Node.js antes de gravar a configuração para que a ferramenta não fique apontando para um comando inválido.",
|
||||
"mcp.setup.runtimeRequirement": "Esta configuração requer o Node.js 18+ ou o Bun 1+ no PATH e uma ferramenta de desktop compatível com MCP. O Tolaria verifica o runtime antes de gravar a configuração para que a ferramenta não fique apontando para um comando inválido.",
|
||||
"mcp.setup.writeEntryDescription": "Ao confirmar esta ação, a única entrada MCP {entry} do Tolaria será gravada ou atualizada em:",
|
||||
"mcp.setup.clientPathsDescription": "A CLI do Claude Code lê ~/.claude.json, a CLI do Gemini lê ~/.gemini/settings.json, o Cursor lê ~/.cursor/mcp.json e o caminho genérico ~/.config/mcp/mcp.json é usado por outras ferramentas compatíveis com MCP. Ao fechar o aplicativo, todos os arquivos permanecem inalterados, a menos que você se conecte ou se desconecte. A reconexão é idempotente, e a desconexão remove novamente a entrada do Tolaria.",
|
||||
"mcp.setup.geminiGuidanceDescription": "A CLI do Gemini precisa de instalação e login próprios. Use Restore Tolaria AI Guidance quando quiser um shim de compatibilidade com GEMINI.md na raiz do cofre que direcione o Gemini de volta para as instruções compartilhadas do AGENTS.md sem substituir a orientação personalizada.",
|
||||
|
||||
@@ -313,7 +313,7 @@
|
||||
"mcp.setup.disconnect": "Desligar",
|
||||
"mcp.setup.connecting": "A estabelecer ligação…",
|
||||
"mcp.setup.disconnecting": "A desligar…",
|
||||
"mcp.setup.nodeRequirement": "Esta configuração requer o Node.js 18 ou superior no PATH e uma ferramenta de desktop compatível com MCP. A Tolaria verifica o Node.js antes de escrever a configuração, para que a ferramenta não fique a apontar para um comando inválido.",
|
||||
"mcp.setup.runtimeRequirement": "Esta configuração requer o Node.js 18+ ou o Bun 1+ no PATH e uma ferramenta de desktop compatível com MCP. A Tolaria verifica o runtime antes de escrever a configuração, para que a ferramenta não fique a apontar para um comando inválido.",
|
||||
"mcp.setup.writeEntryDescription": "Ao confirmar esta ação, a única entrada MCP {entry} da Tolaria será escrita ou atualizada em:",
|
||||
"mcp.setup.clientPathsDescription": "A CLI do Claude Code lê ~/.claude.json, a CLI do Gemini lê ~/.gemini/settings.json, o Cursor lê ~/.cursor/mcp.json e o caminho genérico ~/.config/mcp/mcp.json é detetado por outras ferramentas compatíveis com MCP. Ao fechar, todos os ficheiros permanecem inalterados, a menos que estabeleça ou interrompa a ligação; a restabelecimento da ligação é idempotente e a interrupção da ligação remove novamente a entrada da Tolaria.",
|
||||
"mcp.setup.geminiGuidanceDescription": "A CLI do Gemini precisa da sua própria instalação e início de sessão. Utilize Restore Tolaria AI Guidance quando quiser uma camada de compatibilidade GEMINI.md na raiz do cofre que encaminhe o Gemini de volta para as instruções partilhadas do AGENTS.md sem substituir as orientações personalizadas.",
|
||||
|
||||
@@ -313,7 +313,7 @@
|
||||
"mcp.setup.disconnect": "Отключить",
|
||||
"mcp.setup.connecting": "Подключение…",
|
||||
"mcp.setup.disconnecting": "Отключение…",
|
||||
"mcp.setup.nodeRequirement": "Для этой настройки требуется Node.js 18+ в PATH и совместимый с MCP настольный инструмент. Tolaria проверяет Node.js перед записью конфигурации, чтобы инструмент не указывал на неработающую команду.",
|
||||
"mcp.setup.runtimeRequirement": "Для этой настройки требуется Node.js 18+ или Bun 1+ в PATH и совместимый с MCP настольный инструмент. Tolaria проверяет среду выполнения перед записью конфигурации, чтобы инструмент не указывал на неработающую команду.",
|
||||
"mcp.setup.writeEntryDescription": "При подтверждении этого действия будет записана или обновлена единственная запись Tolaria {entry} в MCP в:",
|
||||
"mcp.setup.clientPathsDescription": "CLI Claude Code считывает файл ~/.claude.json, CLI Gemini считывает файл ~/.gemini/settings.json, Cursor считывает файл ~/.cursor/mcp.json, а общий путь ~/.config/mcp/mcp.json используется другими MCP-совместимыми инструментами. При закрытии приложения все файлы остаются без изменений, если вы не подключаетесь или не отключаетесь. Повторное подключение является идемпотентным, а отключение снова удаляет запись Tolaria.",
|
||||
"mcp.setup.geminiGuidanceDescription": "Для Gemini CLI требуется отдельная установка и вход в систему. Используйте команду Restore Tolaria AI Guidance, если вам нужна оболочка совместимости GEMINI.md в корне хранилища, которая перенаправляет Gemini обратно к общим инструкциям AGENTS.md, не перезаписывая пользовательские инструкции.",
|
||||
|
||||
@@ -313,7 +313,7 @@
|
||||
"mcp.setup.disconnect": "Disconnect",
|
||||
"mcp.setup.connecting": "Connecting…",
|
||||
"mcp.setup.disconnecting": "Disconnecting…",
|
||||
"mcp.setup.nodeRequirement": "This setup requires Node.js 18+ on PATH and an MCP-compatible desktop tool. Tolaria checks Node.js before writing config so the tool is not left pointing at a broken command.",
|
||||
"mcp.setup.runtimeRequirement": "Thiết lập này yêu cầu Node.js 18+ hoặc Bun 1+ trong PATH và một công cụ máy tính tương thích MCP. Tolaria kiểm tra runtime trước khi ghi cấu hình để công cụ không trỏ đến một lệnh bị hỏng.",
|
||||
"mcp.setup.writeEntryDescription": "Confirming this action will write or update Tolaria's single {entry} MCP entry in:",
|
||||
"mcp.setup.clientPathsDescription": "Claude Code CLI reads ~/.claude.json, Gemini CLI reads ~/.gemini/settings.json, Cursor reads ~/.cursor/mcp.json, and the generic ~/.config/mcp/mcp.json path is picked up by other MCP-compatible tools. Closing leaves all files untouched unless you connect or disconnect, reconnecting is idempotent, and disconnecting removes Tolaria's entry again.",
|
||||
"mcp.setup.geminiGuidanceDescription": "Gemini CLI needs its own install and sign-in. Use Restore Tolaria AI Guidance when you want a vault-root GEMINI.md compatibility shim that points Gemini back to the shared AGENTS.md instructions without overwriting custom guidance.",
|
||||
|
||||
@@ -313,7 +313,7 @@
|
||||
"mcp.setup.disconnect": "断开连接",
|
||||
"mcp.setup.connecting": "正在连接…",
|
||||
"mcp.setup.disconnecting": "正在断开连接……",
|
||||
"mcp.setup.nodeRequirement": "此设置需要 PATH 中包含 Node.js 18+ 及以上版本,并需要一个与 MCP 兼容的桌面工具。Tolaria 会在写入配置之前检查 Node.js,以确保该工具不会指向无效的命令。",
|
||||
"mcp.setup.runtimeRequirement": "此设置需要 PATH 中包含 Node.js 18+ 或 Bun 1+,并需要一个与 MCP 兼容的桌面工具。Tolaria 会在写入配置之前检查运行时,以确保该工具不会指向无效的命令。",
|
||||
"mcp.setup.writeEntryDescription": "确认此操作将写入或更新 Tolaria 在以下位置的单个 {entry} MCP 条目:",
|
||||
"mcp.setup.clientPathsDescription": "Claude Code CLI 读取 ~/.claude.json,Gemini CLI 读取 ~/.gemini/settings.json,Cursor 读取 ~/.cursor/mcp.json,而通用路径 ~/.config/mcp/mcp.json 则由其他与 MCP 兼容的工具读取。关闭应用程序后,除非您连接或断开连接,否则所有文件都不会受到影响。重新连接是幂等操作,而断开连接会再次删除 Tolaria 的条目。",
|
||||
"mcp.setup.geminiGuidanceDescription": "Gemini CLI 需要单独安装并登录。如果您希望获得一个 Vault 根目录 GEMINI.md 兼容性 shim,使 Gemini 重新指向共享的 AGENTS.md 指南而不覆盖自定义指南,请使用“Restore Tolaria AI Guidance”。",
|
||||
|
||||
@@ -313,7 +313,7 @@
|
||||
"mcp.setup.disconnect": "中斷連線",
|
||||
"mcp.setup.connecting": "正在連線…",
|
||||
"mcp.setup.disconnecting": "正在中斷連線…",
|
||||
"mcp.setup.nodeRequirement": "此設定需要在 PATH 中設定 Node.js 18 以上版本,並使用與 MCP 相容的桌面工具。Tolaria 會在寫入設定之前檢查 Node.js,以確保工具不會指向無效的命令。",
|
||||
"mcp.setup.runtimeRequirement": "此設定需要在 PATH 中設定 Node.js 18+ 或 Bun 1+,並使用與 MCP 相容的桌面工具。Tolaria 會在寫入設定之前檢查執行階段,以確保工具不會指向無效的命令。",
|
||||
"mcp.setup.writeEntryDescription": "確認此操作將寫入或更新 Tolaria 在以下位置的單一 {entry} MCP 條目:",
|
||||
"mcp.setup.clientPathsDescription": "Claude Code CLI 會讀取 ~/.claude.json,Gemini CLI 會讀取 ~/.gemini/settings.json,Cursor 會讀取 ~/.cursor/mcp.json,而其他與 MCP 相容的工具則會讀取通用的 ~/.config/mcp/mcp.json 路徑。關閉後,除非您連線或中斷連線,否則所有檔案都不會受到影響。重新連線是等同於初始狀態的操作,而中斷連線會再次移除 Tolaria 的條目。",
|
||||
"mcp.setup.geminiGuidanceDescription": "Gemini CLI 需要單獨安裝並登入。當您希望有一個 Vault 根目錄的 GEMINI.md 相容性輔助層,能夠在不覆寫自訂指南的情況下將 Gemini 重新導向至共享的 AGENTS.md 指示時,請使用「Restore Tolaria AI Guidance」。",
|
||||
|
||||
Reference in New Issue
Block a user