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 sqlx::PgPool;
|
||||
use sqlx::Row;
|
||||
use std::fs;
|
||||
use std::sync::Arc;
|
||||
use tauri::{AppHandle, Manager, State};
|
||||
|
||||
fn get_connections_path(app: &AppHandle) -> TuskResult<std::path::PathBuf> {
|
||||
@@ -50,7 +51,7 @@ pub async fn save_connection(app: AppHandle, config: ConnectionConfig) -> TuskRe
|
||||
#[tauri::command]
|
||||
pub async fn delete_connection(
|
||||
app: AppHandle,
|
||||
state: State<'_, AppState>,
|
||||
state: State<'_, Arc<AppState>>,
|
||||
id: String,
|
||||
) -> TuskResult<()> {
|
||||
let path = get_connections_path(&app)?;
|
||||
@@ -91,7 +92,7 @@ pub async fn test_connection(config: ConnectionConfig) -> TuskResult<String> {
|
||||
}
|
||||
|
||||
#[tauri::command]
|
||||
pub async fn connect(state: State<'_, AppState>, config: ConnectionConfig) -> TuskResult<()> {
|
||||
pub async fn connect(state: State<'_, Arc<AppState>>, config: ConnectionConfig) -> TuskResult<()> {
|
||||
let pool = PgPool::connect(&config.connection_url())
|
||||
.await
|
||||
.map_err(TuskError::Database)?;
|
||||
@@ -113,7 +114,7 @@ pub async fn connect(state: State<'_, AppState>, config: ConnectionConfig) -> Tu
|
||||
|
||||
#[tauri::command]
|
||||
pub async fn switch_database(
|
||||
state: State<'_, AppState>,
|
||||
state: State<'_, Arc<AppState>>,
|
||||
config: ConnectionConfig,
|
||||
database: String,
|
||||
) -> TuskResult<()> {
|
||||
@@ -139,7 +140,7 @@ pub async fn switch_database(
|
||||
}
|
||||
|
||||
#[tauri::command]
|
||||
pub async fn disconnect(state: State<'_, AppState>, id: String) -> TuskResult<()> {
|
||||
pub async fn disconnect(state: State<'_, Arc<AppState>>, id: String) -> TuskResult<()> {
|
||||
let mut pools = state.pools.write().await;
|
||||
if let Some(pool) = pools.remove(&id) {
|
||||
pool.close().await;
|
||||
@@ -153,7 +154,7 @@ pub async fn disconnect(state: State<'_, AppState>, id: String) -> TuskResult<()
|
||||
|
||||
#[tauri::command]
|
||||
pub async fn set_read_only(
|
||||
state: State<'_, AppState>,
|
||||
state: State<'_, Arc<AppState>>,
|
||||
connection_id: String,
|
||||
read_only: bool,
|
||||
) -> TuskResult<()> {
|
||||
@@ -164,7 +165,7 @@ pub async fn set_read_only(
|
||||
|
||||
#[tauri::command]
|
||||
pub async fn get_read_only(
|
||||
state: State<'_, AppState>,
|
||||
state: State<'_, Arc<AppState>>,
|
||||
connection_id: String,
|
||||
) -> TuskResult<bool> {
|
||||
Ok(state.is_read_only(&connection_id).await)
|
||||
|
||||
Reference in New Issue
Block a user