Port (default 47821) and bearer token now persist to mcp.json with OS-picked fallback if the port is taken; new Regenerate button in the panel rotates the token and restarts the running server. rmcp's DNS-rebinding host allowlist is disabled so WSL gateway IPs can connect (bearer-auth handles the gatekeeping); the auth middleware only enforces on /mcp paths so OAuth-discovery clients don't see a Bearer challenge on /.well-known/* probes. Claude Code's HTTP-MCP client currently tries OAuth and ignores static `headers` auth (anthropics/claude-code#17152, #46879), so the panel + README config snippet now uses `npx mcp-remote` as a stdio shim that proxies the HTTP endpoint with the bearer baked in.
67 lines
2.4 KiB
Rust
67 lines
2.4 KiB
Rust
//! Library entry point. `main.rs` calls `run()`.
|
|
|
|
mod commands;
|
|
mod creds;
|
|
mod hosts;
|
|
mod mcp;
|
|
mod pty;
|
|
|
|
use std::sync::Arc;
|
|
|
|
use crate::mcp::{McpServerHandle, McpState};
|
|
use crate::pty::PtyManager;
|
|
|
|
pub fn run() {
|
|
let _ = tracing_subscriber::fmt()
|
|
.with_env_filter(
|
|
tracing_subscriber::EnvFilter::try_from_default_env()
|
|
.unwrap_or_else(|_| tracing_subscriber::EnvFilter::new("info")),
|
|
)
|
|
.with_writer(std::io::stderr)
|
|
.try_init();
|
|
|
|
// keyring-core 1.x requires explicit store registration before any
|
|
// Entry::new() call. We're Windows-only so the Credential Manager
|
|
// backend is the only choice. Failure here means SSH passwords won't
|
|
// be retrievable — log and continue (host configs still work without
|
|
// saved passwords; users just see the prompt and type it manually).
|
|
match windows_native_keyring_store::Store::new() {
|
|
Ok(store) => keyring_core::set_default_store(store),
|
|
Err(e) => tracing::warn!("keyring store init failed: {e}"),
|
|
}
|
|
|
|
// PtyManager and McpState are shared with the MCP server, so register
|
|
// them as Arc<T> rather than the plain T. Tauri commands access them
|
|
// via `tauri::State<'_, Arc<T>>` and deref / clone as needed.
|
|
let ptys: Arc<PtyManager> = Arc::new(PtyManager::new());
|
|
let mcp_state: Arc<tokio::sync::RwLock<McpState>> =
|
|
Arc::new(tokio::sync::RwLock::new(McpState::default()));
|
|
|
|
tauri::Builder::default()
|
|
.plugin(tauri_plugin_clipboard_manager::init())
|
|
.plugin(tauri_plugin_opener::init())
|
|
.manage(ptys)
|
|
.manage(mcp_state)
|
|
.manage(McpServerHandle::default())
|
|
.invoke_handler(tauri::generate_handler![
|
|
commands::list_distros,
|
|
commands::spawn_pane,
|
|
commands::write_to_pane,
|
|
commands::resize_pane,
|
|
commands::kill_pane,
|
|
commands::save_workspace,
|
|
commands::load_workspace,
|
|
commands::list_ssh_hosts,
|
|
commands::save_ssh_hosts,
|
|
commands::set_host_password,
|
|
commands::delete_host_password,
|
|
commands::has_host_password,
|
|
commands::mcp_start,
|
|
commands::mcp_stop,
|
|
commands::mcp_status,
|
|
commands::mcp_regenerate_token,
|
|
commands::mcp_update_state,
|
|
])
|
|
.run(tauri::generate_context!())
|
|
.expect("error while running tauri application");
|
|
}
|