feat: add embedded MCP server and Makefile
Add an MCP (Model Context Protocol) server that starts on 127.0.0.1:9427 at app launch, sharing connection pools with the Tauri IPC layer. This lets Claude (or any MCP client) query PostgreSQL through Tusk's existing connections. MCP tools: list_connections, execute_query, list_schemas, list_tables, describe_table. Also add a Makefile with targets for dev, build (cross-platform), install/uninstall, lint, and formatting. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -4,6 +4,7 @@ use crate::state::AppState;
|
||||
use serde_json::Value;
|
||||
use sqlx::postgres::PgRow;
|
||||
use sqlx::{Column, Row, TypeInfo};
|
||||
use std::sync::Arc;
|
||||
use std::time::Instant;
|
||||
use tauri::State;
|
||||
|
||||
@@ -68,18 +69,17 @@ pub fn pg_value_to_json(row: &PgRow, index: usize) -> Value {
|
||||
}
|
||||
}
|
||||
|
||||
#[tauri::command]
|
||||
pub async fn execute_query(
|
||||
state: State<'_, AppState>,
|
||||
connection_id: String,
|
||||
sql: String,
|
||||
pub async fn execute_query_core(
|
||||
state: &AppState,
|
||||
connection_id: &str,
|
||||
sql: &str,
|
||||
) -> TuskResult<QueryResult> {
|
||||
let read_only = state.is_read_only(&connection_id).await;
|
||||
let read_only = state.is_read_only(connection_id).await;
|
||||
|
||||
let pools = state.pools.read().await;
|
||||
let pool = pools
|
||||
.get(&connection_id)
|
||||
.ok_or(TuskError::NotConnected(connection_id))?;
|
||||
.get(connection_id)
|
||||
.ok_or_else(|| TuskError::NotConnected(connection_id.to_string()))?;
|
||||
|
||||
let start = Instant::now();
|
||||
let rows = if read_only {
|
||||
@@ -88,14 +88,14 @@ pub async fn execute_query(
|
||||
.execute(&mut *tx)
|
||||
.await
|
||||
.map_err(TuskError::Database)?;
|
||||
let result = sqlx::query(&sql)
|
||||
let result = sqlx::query(sql)
|
||||
.fetch_all(&mut *tx)
|
||||
.await
|
||||
.map_err(TuskError::Database);
|
||||
tx.rollback().await.map_err(TuskError::Database)?;
|
||||
result?
|
||||
} else {
|
||||
sqlx::query(&sql)
|
||||
sqlx::query(sql)
|
||||
.fetch_all(pool)
|
||||
.await
|
||||
.map_err(TuskError::Database)?
|
||||
@@ -127,3 +127,12 @@ pub async fn execute_query(
|
||||
execution_time_ms,
|
||||
})
|
||||
}
|
||||
|
||||
#[tauri::command]
|
||||
pub async fn execute_query(
|
||||
state: State<'_, Arc<AppState>>,
|
||||
connection_id: String,
|
||||
sql: String,
|
||||
) -> TuskResult<QueryResult> {
|
||||
execute_query_core(&state, &connection_id, &sql).await
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user