fix(mcp): disambiguate same-name connections

This commit is contained in:
Abeautifulsnow authored and GitHub committed 2026-07-10 14:44:40 +08:00
1 parent 3b1a9cb98b
commit 0674433eea
7 files changed
+483 -90

No files matched your search

+45 -33
View File
@@ -15,6 +15,7 @@ const MCP_BRIDGE_PORT_FILE: &str = "mcp-bridge-port";
#[derive(Deserialize)]
struct OpenTableRequest {
connection_name: String,
connection_id: Option<String>,
database: Option<String>,
schema: Option<String>,
table: String,
@@ -23,6 +24,7 @@ struct OpenTableRequest {
#[derive(Deserialize)]
struct ExecuteQueryRequest {
connection_name: String,
connection_id: Option<String>,
database: Option<String>,
sql: String,
schema: Option<String>,
@@ -33,6 +35,7 @@ struct ExecuteQueryRequest {
#[derive(Deserialize)]
struct ListTablesRequest {
connection_name: String,
connection_id: Option<String>,
database: Option<String>,
schema: Option<String>,
}
@@ -40,6 +43,7 @@ struct ListTablesRequest {
#[derive(Deserialize)]
struct DescribeTableRequest {
connection_name: String,
connection_id: Option<String>,
database: Option<String>,
schema: Option<String>,
table: String,
@@ -48,6 +52,7 @@ struct DescribeTableRequest {
#[derive(Deserialize)]
struct MongoFindDocumentsRequest {
connection_name: String,
connection_id: Option<String>,
database: Option<String>,
collection: String,
skip: Option<u64>,
@@ -60,12 +65,14 @@ struct MongoFindDocumentsRequest {
#[derive(Deserialize)]
struct MongoServerVersionRequest {
connection_name: String,
connection_id: Option<String>,
database: Option<String>,
}
#[derive(Deserialize)]
struct MongoCollectionStatsRequest {
connection_name: String,
connection_id: Option<String>,
database: Option<String>,
collection: String,
scale: Option<serde_json::Number>,
@@ -74,6 +81,7 @@ struct MongoCollectionStatsRequest {
#[derive(Deserialize)]
struct MongoAggregateDocumentsRequest {
connection_name: String,
connection_id: Option<String>,
database: Option<String>,
collection: String,
pipeline_json: String,
@@ -83,6 +91,7 @@ struct MongoAggregateDocumentsRequest {
#[derive(Deserialize)]
struct MongoCreateIndexRequest {
connection_name: String,
connection_id: Option<String>,
database: Option<String>,
collection: String,
keys_json: String,
@@ -92,6 +101,7 @@ struct MongoCreateIndexRequest {
#[derive(Deserialize)]
struct MongoDropIndexesRequest {
connection_name: String,
connection_id: Option<String>,
database: Option<String>,
collection: String,
indexes_json: Option<String>,
@@ -101,6 +111,7 @@ struct MongoDropIndexesRequest {
#[derive(Deserialize)]
struct MongoDropCollectionRequest {
connection_name: String,
connection_id: Option<String>,
database: Option<String>,
collection: String,
}
@@ -108,6 +119,7 @@ struct MongoDropCollectionRequest {
#[derive(Deserialize)]
struct MongoInsertDocumentsRequest {
connection_name: String,
connection_id: Option<String>,
database: Option<String>,
collection: String,
docs_json: String,
@@ -116,6 +128,7 @@ struct MongoInsertDocumentsRequest {
#[derive(Deserialize)]
struct MongoUpdateDocumentsRequest {
connection_name: String,
connection_id: Option<String>,
database: Option<String>,
collection: String,
filter_json: String,
@@ -126,6 +139,7 @@ struct MongoUpdateDocumentsRequest {
#[derive(Deserialize)]
struct MongoDeleteDocumentsRequest {
connection_name: String,
connection_id: Option<String>,
database: Option<String>,
collection: String,
filter_json: String,
@@ -135,6 +149,7 @@ struct MongoDeleteDocumentsRequest {
#[derive(Deserialize)]
struct RedisCommandRequest {
connection_name: String,
connection_id: Option<String>,
db: u32,
command: String,
skip_safety_check: Option<bool>,
@@ -295,17 +310,21 @@ async fn respond_error(stream: &mut tokio::net::TcpStream, status: &str, message
async fn resolve_connection(
state: &Arc<AppState>,
connection_id: Option<&str>,
connection_name: &str,
) -> Result<crate::models::connection::ConnectionConfig, String> {
let configs = state.storage.load_connections().await.map_err(|e| e.to_string())?;
let config =
find_config_by_name(&configs, connection_name).ok_or_else(|| "Connection not found".to_string())?.clone();
let config = if let Some(id) = connection_id.filter(|s| !s.is_empty()) {
configs.iter().find(|c| c.id == id).ok_or_else(|| format!("Connection with id '{}' not found", id))?
} else {
find_config_by_name(&configs, connection_name).ok_or_else(|| "Connection not found".to_string())?
};
let mut state_configs = state.configs.write().await;
if !state_configs.contains_key(&config.id) {
state_configs.insert(config.id.clone(), config.clone());
}
drop(state_configs);
Ok(config)
Ok(config.clone())
}
fn check_visible_database(config: &crate::models::connection::ConnectionConfig, database: &str) -> Result<(), String> {
@@ -319,11 +338,12 @@ fn check_visible_database(config: &crate::models::connection::ConnectionConfig,
async fn resolve_mongo_pool_key(
state: &Arc<AppState>,
connection_id: Option<&str>,
connection_name: &str,
database: Option<String>,
stream: &mut tokio::net::TcpStream,
) -> Option<(String, String, String)> {
let config = match resolve_connection(state, connection_name).await {
let config = match resolve_connection(state, connection_id, connection_name).await {
Ok(c) => c,
Err(e) => {
respond_error(stream, "404 Not Found", &e).await;
@@ -350,17 +370,13 @@ async fn handle_open_table(app: &AppHandle, state: &Arc<AppState>, body: &str, s
return;
}
};
let configs = match state.storage.load_connections().await {
let config = match resolve_connection(state, req.connection_id.as_deref(), &req.connection_name).await {
Ok(c) => c,
Err(_) => {
respond(stream, "500 Internal Server Error", "").await;
Err(e) => {
respond(stream, "404 Not Found", &e).await;
return;
}
};
let Some(config) = find_config_by_name(&configs, &req.connection_name) else {
respond(stream, "404 Not Found", "Connection not found").await;
return;
};
let event = McpOpenTableEvent {
connection_id: config.id.clone(),
database: req.database.unwrap_or_else(|| config.database.clone().unwrap_or_default()),
@@ -379,17 +395,13 @@ async fn handle_execute_query(app: &AppHandle, state: &Arc<AppState>, body: &str
return;
}
};
let configs = match state.storage.load_connections().await {
let config = match resolve_connection(state, req.connection_id.as_deref(), &req.connection_name).await {
Ok(c) => c,
Err(_) => {
respond(stream, "500 Internal Server Error", "").await;
Err(e) => {
respond(stream, "404 Not Found", &e).await;
return;
}
};
let Some(config) = find_config_by_name(&configs, &req.connection_name) else {
respond(stream, "404 Not Found", "Connection not found").await;
return;
};
let event = McpExecuteQueryEvent {
connection_id: config.id.clone(),
database: req.database.unwrap_or_else(|| config.database.clone().unwrap_or_default()),
@@ -409,7 +421,7 @@ async fn handle_list_tables_data(state: &Arc<AppState>, body: &str, stream: &mut
return;
}
};
let config = match resolve_connection(state, &req.connection_name).await {
let config = match resolve_connection(state, req.connection_id.as_deref(), &req.connection_name).await {
Ok(c) => c,
Err(e) => {
respond_error(stream, "404 Not Found", &e).await;
@@ -436,7 +448,7 @@ async fn handle_describe_table_data(state: &Arc<AppState>, body: &str, stream: &
return;
}
};
let config = match resolve_connection(state, &req.connection_name).await {
let config = match resolve_connection(state, req.connection_id.as_deref(), &req.connection_name).await {
Ok(c) => c,
Err(e) => {
respond_error(stream, "404 Not Found", &e).await;
@@ -464,7 +476,7 @@ async fn handle_mongo_list_collections_data(state: &Arc<AppState>, body: &str, s
}
};
let Some((pool_key, database, _connection_id)) =
resolve_mongo_pool_key(state, &req.connection_name, req.database, stream).await
resolve_mongo_pool_key(state, req.connection_id.as_deref(), &req.connection_name, req.database, stream).await
else {
return;
};
@@ -483,7 +495,7 @@ async fn handle_mongo_find_documents_data(state: &Arc<AppState>, body: &str, str
}
};
let Some((pool_key, database, _connection_id)) =
resolve_mongo_pool_key(state, &req.connection_name, req.database, stream).await
resolve_mongo_pool_key(state, req.connection_id.as_deref(), &req.connection_name, req.database, stream).await
else {
return;
};
@@ -514,7 +526,7 @@ async fn handle_mongo_server_version_data(state: &Arc<AppState>, body: &str, str
}
};
let Some((pool_key, database, _connection_id)) =
resolve_mongo_pool_key(state, &req.connection_name, req.database, stream).await
resolve_mongo_pool_key(state, req.connection_id.as_deref(), &req.connection_name, req.database, stream).await
else {
return;
};
@@ -533,7 +545,7 @@ async fn handle_mongo_collection_stats_data(state: &Arc<AppState>, body: &str, s
}
};
let Some((pool_key, database, _connection_id)) =
resolve_mongo_pool_key(state, &req.connection_name, req.database, stream).await
resolve_mongo_pool_key(state, req.connection_id.as_deref(), &req.connection_name, req.database, stream).await
else {
return;
};
@@ -554,7 +566,7 @@ async fn handle_mongo_aggregate_documents_data(state: &Arc<AppState>, body: &str
}
};
let Some((pool_key, database, _connection_id)) =
resolve_mongo_pool_key(state, &req.connection_name, req.database, stream).await
resolve_mongo_pool_key(state, req.connection_id.as_deref(), &req.connection_name, req.database, stream).await
else {
return;
};
@@ -582,7 +594,7 @@ async fn handle_mongo_create_index_data(state: &Arc<AppState>, body: &str, strea
}
};
let Some((pool_key, database, connection_id)) =
resolve_mongo_pool_key(state, &req.connection_name, req.database, stream).await
resolve_mongo_pool_key(state, req.connection_id.as_deref(), &req.connection_name, req.database, stream).await
else {
return;
};
@@ -614,7 +626,7 @@ async fn handle_mongo_drop_indexes_data(state: &Arc<AppState>, body: &str, strea
}
};
let Some((pool_key, database, connection_id)) =
resolve_mongo_pool_key(state, &req.connection_name, req.database, stream).await
resolve_mongo_pool_key(state, req.connection_id.as_deref(), &req.connection_name, req.database, stream).await
else {
return;
};
@@ -646,7 +658,7 @@ async fn handle_mongo_drop_collection_data(state: &Arc<AppState>, body: &str, st
}
};
let Some((pool_key, database, connection_id)) =
resolve_mongo_pool_key(state, &req.connection_name, req.database, stream).await
resolve_mongo_pool_key(state, req.connection_id.as_deref(), &req.connection_name, req.database, stream).await
else {
return;
};
@@ -669,7 +681,7 @@ async fn handle_mongo_insert_documents_data(state: &Arc<AppState>, body: &str, s
}
};
let Some((pool_key, database, connection_id)) =
resolve_mongo_pool_key(state, &req.connection_name, req.database, stream).await
resolve_mongo_pool_key(state, req.connection_id.as_deref(), &req.connection_name, req.database, stream).await
else {
return;
};
@@ -694,7 +706,7 @@ async fn handle_mongo_update_documents_data(state: &Arc<AppState>, body: &str, s
}
};
let Some((pool_key, database, connection_id)) =
resolve_mongo_pool_key(state, &req.connection_name, req.database, stream).await
resolve_mongo_pool_key(state, req.connection_id.as_deref(), &req.connection_name, req.database, stream).await
else {
return;
};
@@ -727,7 +739,7 @@ async fn handle_mongo_delete_documents_data(state: &Arc<AppState>, body: &str, s
}
};
let Some((pool_key, database, connection_id)) =
resolve_mongo_pool_key(state, &req.connection_name, req.database, stream).await
resolve_mongo_pool_key(state, req.connection_id.as_deref(), &req.connection_name, req.database, stream).await
else {
return;
};
@@ -758,7 +770,7 @@ async fn handle_redis_execute_command_data(state: &Arc<AppState>, body: &str, st
return;
}
};
let config = match resolve_connection(state, &req.connection_name).await {
let config = match resolve_connection(state, req.connection_id.as_deref(), &req.connection_name).await {
Ok(c) => c,
Err(e) => {
respond_error(stream, "404 Not Found", &e).await;
@@ -809,7 +821,7 @@ async fn handle_execute_query_data(state: &Arc<AppState>, body: &str, stream: &m
return;
}
};
let config = match resolve_connection(state, &req.connection_name).await {
let config = match resolve_connection(state, req.connection_id.as_deref(), &req.connection_name).await {
Ok(c) => c,
Err(e) => {
respond_error(stream, "404 Not Found", &e).await;