Skip to main content

mcp_postgres/actions/
config.rs

1use serde_json::{json, Value};
2use tokio_postgres::Client;
3use crate::errors::Result as MCPResult;
4
5const MAX_SETTING_NAME_LEN: usize = 255;
6
7/// 31. Show all settings
8pub async fn show_all_settings(client: &Client, _params: &Option<&Value>) -> MCPResult<Value> {
9    let rows = client
10        .query(
11            "SELECT name, setting, unit, short_desc, context
12             FROM pg_settings
13             WHERE context NOT LIKE 'internal%'
14             ORDER BY name",
15            &[],
16        )
17        .await?;
18
19    let settings: Vec<Value> = rows
20        .iter()
21        .map(|row| {
22            json!({
23                "name": row.get::<_, String>(0),
24                "value": row.get::<_, Option<String>>(1),
25                "unit": row.get::<_, Option<String>>(2),
26                "description": row.get::<_, String>(3),
27                "context": row.get::<_, String>(4),
28            })
29        })
30        .collect();
31
32    Ok(json!({ "settings": settings }))
33}
34
35/// 32. Get setting
36pub async fn get_setting(client: &Client, params: &Option<&Value>) -> MCPResult<Value> {
37    let setting_name = params
38        .as_ref()
39        .and_then(|p| p.get("setting").and_then(|v| v.as_str()).map(|s| s.to_string()))
40        .ok_or_else(|| crate::errors::MCPError::InvalidParams("Missing 'setting' parameter".into()))?;
41
42    if setting_name.is_empty() || setting_name.len() > MAX_SETTING_NAME_LEN {
43        return Err(crate::errors::MCPError::InvalidParams(
44            format!("'setting' must be 1-{MAX_SETTING_NAME_LEN} characters")
45        ));
46    }
47
48    let rows = client
49        .query(
50            "SELECT name, setting, unit, short_desc, context, vartype, source
51             FROM pg_settings
52             WHERE name = $1",
53            &[&setting_name],
54        )
55        .await?;
56
57    if rows.is_empty() {
58        return Err(crate::errors::MCPError::InvalidParams(format!("Setting not found: {}", setting_name)));
59    }
60
61    let row = &rows[0];
62
63    Ok(json!({
64        "name": row.get::<_, String>(0),
65        "value": row.get::<_, Option<String>>(1),
66        "unit": row.get::<_, Option<String>>(2),
67        "description": row.get::<_, String>(3),
68        "context": row.get::<_, String>(4),
69        "type": row.get::<_, String>(5),
70        "source": row.get::<_, String>(6),
71    }))
72}
73
74/// 33. Show memory settings
75pub async fn show_memory_settings(client: &Client, _params: &Option<&Value>) -> MCPResult<Value> {
76    let rows = client
77        .query(
78            "SELECT name, setting, unit
79             FROM pg_settings
80             WHERE name IN ('shared_buffers', 'effective_cache_size', 'work_mem',
81                           'maintenance_work_mem', 'wal_buffers', 'random_page_cost',
82                           'effective_io_concurrency')
83             ORDER BY name",
84            &[],
85        )
86        .await?;
87
88    let settings: Vec<Value> = rows
89        .iter()
90        .map(|row| {
91            json!({
92                "name": row.get::<_, String>(0),
93                "value": row.get::<_, Option<String>>(1),
94                "unit": row.get::<_, Option<String>>(2),
95            })
96        })
97        .collect();
98
99    Ok(json!({ "memory_settings": settings }))
100}
101
102/// 34. Show performance settings
103pub async fn show_performance_settings(client: &Client, _params: &Option<&Value>) -> MCPResult<Value> {
104    let rows = client
105        .query(
106            "SELECT name, setting, unit
107             FROM pg_settings
108             WHERE name IN ('max_connections', 'checkpoint_timeout', 'checkpoint_completion_target',
109                           'wal_level', 'max_wal_senders', 'wal_keep_size', 'synchronous_commit',
110                           'constraint_exclusion')
111             ORDER BY name",
112            &[],
113        )
114        .await?;
115
116    let settings: Vec<Value> = rows
117        .iter()
118        .map(|row| {
119            json!({
120                "name": row.get::<_, String>(0),
121                "value": row.get::<_, Option<String>>(1),
122                "unit": row.get::<_, Option<String>>(2),
123            })
124        })
125        .collect();
126
127    Ok(json!({ "performance_settings": settings }))
128}
129
130/// 35. Show log settings
131pub async fn show_log_settings(client: &Client, _params: &Option<&Value>) -> MCPResult<Value> {
132    let rows = client
133        .query(
134            "SELECT name, setting, unit
135             FROM pg_settings
136             WHERE name LIKE 'log%'
137             ORDER BY name",
138            &[],
139        )
140        .await?;
141
142    let settings: Vec<Value> = rows
143        .iter()
144        .map(|row| {
145            json!({
146                "name": row.get::<_, String>(0),
147                "value": row.get::<_, Option<String>>(1),
148                "unit": row.get::<_, Option<String>>(2),
149            })
150        })
151        .collect();
152
153    Ok(json!({ "log_settings": settings }))
154}