Skip to main content

mcp_postgres/actions/
config.rs

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