database_mcp_server/
tools.rs1use database_mcp_backend::error::AppError;
7use rmcp::model::ErrorData;
8use serde::Serialize;
9use serde_json::Value;
10use tracing::info;
11
12use crate::map_error;
13
14pub async fn list_databases(list_fn: impl Future<Output = Result<Vec<String>, AppError>>) -> Result<String, ErrorData> {
20 info!("TOOL: list_databases called");
21 let db_list = list_fn.await.map_err(map_error)?;
22 info!("TOOL: list_databases completed. Databases found: {}", db_list.len());
23 serde_json::to_string_pretty(&db_list).map_err(map_error)
24}
25
26pub async fn list_tables(
32 list_fn: impl Future<Output = Result<Vec<String>, AppError>>,
33 database_name: &str,
34) -> Result<String, ErrorData> {
35 info!("TOOL: list_tables called. database_name={database_name}");
36 let table_list = list_fn.await.map_err(map_error)?;
37 info!("TOOL: list_tables completed. Tables found: {}", table_list.len());
38 serde_json::to_string_pretty(&table_list).map_err(map_error)
39}
40
41pub async fn get_table_schema(
47 schema_fn: impl Future<Output = Result<impl Serialize, AppError>>,
48 database_name: &str,
49 table_name: &str,
50) -> Result<String, ErrorData> {
51 info!("TOOL: get_table_schema called. database_name={database_name}, table_name={table_name}");
52 let schema = schema_fn.await.map_err(map_error)?;
53 info!("TOOL: get_table_schema completed");
54 serde_json::to_string_pretty(&schema).map_err(map_error)
55}
56
57pub async fn read_query(
66 query_fn: impl Future<Output = Result<Value, AppError>>,
67 sql_query: &str,
68 database_name: &str,
69 validate: impl FnOnce(&str) -> Result<(), AppError>,
70) -> Result<String, ErrorData> {
71 info!(
72 "TOOL: execute_sql called. database_name={database_name}, sql_query={}",
73 &sql_query[..sql_query.len().min(100)]
74 );
75
76 validate(sql_query).map_err(map_error)?;
77
78 let results = query_fn.await.map_err(map_error)?;
79 let row_count = results.as_array().map_or(0, Vec::len);
80 info!("TOOL: execute_sql completed. Rows returned: {row_count}");
81 serde_json::to_string_pretty(&results).map_err(map_error)
82}
83
84pub async fn write_query(
90 query_fn: impl Future<Output = Result<Value, AppError>>,
91 sql_query: &str,
92 database_name: &str,
93) -> Result<String, ErrorData> {
94 info!(
95 "TOOL: execute_sql called. database_name={database_name}, sql_query={}",
96 &sql_query[..sql_query.len().min(100)]
97 );
98
99 let results = query_fn.await.map_err(map_error)?;
100 let row_count = results.as_array().map_or(0, Vec::len);
101 info!("TOOL: execute_sql completed. Rows returned: {row_count}");
102 serde_json::to_string_pretty(&results).map_err(map_error)
103}
104
105pub async fn create_database(
111 create_fn: impl Future<Output = Result<Value, AppError>>,
112 database_name: &str,
113) -> Result<String, ErrorData> {
114 info!("TOOL: create_database called for database: '{database_name}'");
115 let result = create_fn.await.map_err(map_error)?;
116 info!("TOOL: create_database completed");
117 serde_json::to_string_pretty(&result).map_err(map_error)
118}
119
120#[must_use]
122pub fn resolve_database(name: &str) -> Option<&str> {
123 if name.is_empty() { None } else { Some(name) }
124}