Skip to main content

boost/tools/
config.rs

1//! `get-config` — read named config values.
2
3use async_trait::async_trait;
4use serde_json::{json, Value};
5
6use crate::protocol::CallToolResult;
7use crate::tool::{Context, Tool};
8
9pub struct GetConfig;
10
11#[async_trait]
12impl Tool for GetConfig {
13    fn name(&self) -> &'static str {
14        "get-config"
15    }
16    fn description(&self) -> &'static str {
17        "Read named application config values: `app.*`, `session.*`, `mail.*`, `queue.*`, `db.*`. Omit `key` to dump all known config sections (secrets are redacted)."
18    }
19    fn input_schema(&self) -> Value {
20        json!({
21            "type": "object",
22            "properties": {
23                "key": { "type": "string", "description": "Dot-path like `app.env`. Optional." }
24            }
25        })
26    }
27
28    async fn call(&self, ctx: &Context, args: Value) -> CallToolResult {
29        let key = args.get("key").and_then(|v| v.as_str()).unwrap_or("");
30        let full = dump_all(ctx);
31        if key.is_empty() {
32            return CallToolResult::json(&full);
33        }
34        let mut value = &full;
35        for segment in key.split('.') {
36            match value.get(segment) {
37                Some(v) => value = v,
38                None => {
39                    return CallToolResult::error(format!("unknown config key: {key}"));
40                }
41            }
42        }
43        CallToolResult::json(value)
44    }
45}
46
47fn dump_all(ctx: &Context) -> Value {
48    let inner = &ctx.container;
49    let app = inner.app();
50    json!({
51        "app": {
52            "name": app.name,
53            "env": app.env,
54            "url": app.url,
55            "debug": app.debug,
56            "key": redact(&app.key),
57        },
58        "database": {
59            "driver": format!("{:?}", inner.driver()),
60        },
61    })
62}
63
64fn redact(s: &str) -> Value {
65    if s.is_empty() {
66        json!("(unset)")
67    } else {
68        json!(format!("(set, {} chars)", s.len()))
69    }
70}