fix(mcp): write bridge port to resolved data dir
This commit is contained in:
parent
23ab48bfb7
commit
a529344ac7
|
|
@ -1,6 +1,7 @@
|
|||
use serde::{Deserialize, Serialize};
|
||||
use std::path::{Path, PathBuf};
|
||||
use std::sync::Arc;
|
||||
use tauri::{AppHandle, Emitter, Manager};
|
||||
use tauri::{AppHandle, Emitter};
|
||||
use tokio::io::{AsyncReadExt, AsyncWriteExt};
|
||||
use tokio::net::TcpListener;
|
||||
|
||||
|
|
@ -9,6 +10,7 @@ use super::connection::AppState;
|
|||
use super::connection::ensure_connection_writable;
|
||||
|
||||
const BIND_ADDR: &str = "127.0.0.1:0";
|
||||
const MCP_BRIDGE_PORT_FILE: &str = "mcp-bridge-port";
|
||||
|
||||
#[derive(Deserialize)]
|
||||
struct OpenTableRequest {
|
||||
|
|
@ -131,7 +133,7 @@ pub struct McpExecuteQueryEvent {
|
|||
pub allow_dangerous: bool,
|
||||
}
|
||||
|
||||
pub fn start(app_handle: AppHandle, state: Arc<AppState>) {
|
||||
pub fn start(app_handle: AppHandle, state: Arc<AppState>, data_dir: PathBuf) {
|
||||
tauri::async_runtime::spawn(async move {
|
||||
let listener = match TcpListener::bind(BIND_ADDR).await {
|
||||
Ok(l) => l,
|
||||
|
|
@ -143,8 +145,9 @@ pub fn start(app_handle: AppHandle, state: Arc<AppState>) {
|
|||
log::info!("MCP bridge listening on {BIND_ADDR}");
|
||||
let actual_port = listener.local_addr().map(|a| a.port()).unwrap_or(0);
|
||||
log::info!("MCP bridge assigned port {actual_port}");
|
||||
if let Ok(dir) = app_handle.path().app_data_dir() {
|
||||
let _ = std::fs::write(dir.join("mcp-bridge-port"), actual_port.to_string());
|
||||
// Publish into DBX's resolved data dir so DBX_DATA_DIR and portable mode share the same discovery file.
|
||||
if let Err(err) = write_port_file(&data_dir, actual_port) {
|
||||
log::warn!("MCP bridge failed to write port file in {}: {err}", data_dir.display());
|
||||
}
|
||||
loop {
|
||||
let (mut stream, _) = match listener.accept().await {
|
||||
|
|
@ -202,6 +205,13 @@ pub fn start(app_handle: AppHandle, state: Arc<AppState>) {
|
|||
});
|
||||
}
|
||||
|
||||
fn write_port_file(data_dir: &Path, actual_port: u16) -> std::io::Result<PathBuf> {
|
||||
std::fs::create_dir_all(data_dir)?;
|
||||
let path = data_dir.join(MCP_BRIDGE_PORT_FILE);
|
||||
std::fs::write(&path, actual_port.to_string())?;
|
||||
Ok(path)
|
||||
}
|
||||
|
||||
fn find_config_by_name<'a>(
|
||||
configs: &'a [crate::models::connection::ConnectionConfig],
|
||||
name: &str,
|
||||
|
|
@ -209,6 +219,31 @@ fn find_config_by_name<'a>(
|
|||
configs.iter().find(|c| c.name.eq_ignore_ascii_case(name))
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::write_port_file;
|
||||
|
||||
#[test]
|
||||
fn writes_bridge_port_file_to_resolved_data_dir() {
|
||||
let root = std::env::temp_dir().join(format!(
|
||||
"dbx-mcp-bridge-port-test-{}-{}",
|
||||
std::process::id(),
|
||||
uuid::Uuid::new_v4()
|
||||
));
|
||||
let default_data_dir = root.join("default-app-data");
|
||||
let resolved_data_dir = root.join("resolved-data");
|
||||
std::fs::create_dir_all(&default_data_dir).unwrap();
|
||||
|
||||
let port_file = write_port_file(&resolved_data_dir, 49152).unwrap();
|
||||
|
||||
assert_eq!(port_file, resolved_data_dir.join("mcp-bridge-port"));
|
||||
assert_eq!(std::fs::read_to_string(port_file).unwrap(), "49152");
|
||||
assert!(!default_data_dir.join("mcp-bridge-port").exists());
|
||||
|
||||
let _ = std::fs::remove_dir_all(root);
|
||||
}
|
||||
}
|
||||
|
||||
async fn respond(stream: &mut tokio::net::TcpStream, status: &str, body: &str) {
|
||||
let resp = format!("HTTP/1.1 {status}\r\nContent-Length: {}\r\n\r\n{body}", body.len());
|
||||
let _ = stream.write_all(resp.as_bytes()).await;
|
||||
|
|
|
|||
|
|
@ -582,7 +582,7 @@ pub fn run() {
|
|||
open_connection_deep_links(app.handle(), startup_links);
|
||||
|
||||
let app_handle = app.handle().clone();
|
||||
commands::mcp_bridge::start(app_handle, state);
|
||||
commands::mcp_bridge::start(app_handle, state, data_dir);
|
||||
eprintln!("[STARTUP] setup complete in {:?} (total {:?})", setup_start.elapsed(), startup_begin.elapsed());
|
||||
|
||||
if let Some(decorations) = native_window_decorations_override(std::env::consts::OS) {
|
||||
|
|
|
|||
Loading…
Reference in New Issue