database_mcp_postgres/
tools.rs1use super::types::DropTableRequest;
8use database_mcp_server::types::{
9 CreateDatabaseRequest, DropDatabaseRequest, ExplainQueryRequest, GetTableSchemaRequest, ListDatabasesResponse,
10 ListTablesRequest, ListTablesResponse, MessageResponse, QueryRequest, QueryResponse, TableSchemaResponse,
11};
12use rmcp::handler::server::tool::ToolRouter;
13use rmcp::handler::server::wrapper::{Json, Parameters};
14use rmcp::model::ErrorData;
15use rmcp::tool;
16
17use super::PostgresAdapter;
18
19impl PostgresAdapter {
20 const WRITE_TOOL_NAMES: &[&str] = &["write_query", "create_database", "drop_database", "drop_table"];
22
23 #[must_use]
25 pub fn build_tool_router(&self) -> ToolRouter<Self> {
26 let mut router = Self::tool_router();
27 if self.config.read_only {
28 for name in Self::WRITE_TOOL_NAMES {
29 router.remove_route(name);
30 }
31 }
32 router
33 }
34}
35
36#[rmcp::tool_router]
37impl PostgresAdapter {
38 #[tool(
41 name = "list_databases",
42 annotations(
43 read_only_hint = true,
44 destructive_hint = false,
45 idempotent_hint = true,
46 open_world_hint = false
47 )
48 )]
49 pub async fn tool_list_databases(&self) -> Result<Json<ListDatabasesResponse>, ErrorData> {
50 Ok(Json(self.list_databases().await?))
51 }
52
53 #[tool(
55 name = "create_database",
56 annotations(
57 read_only_hint = false,
58 destructive_hint = false,
59 idempotent_hint = false,
60 open_world_hint = false
61 )
62 )]
63 pub async fn tool_create_database(
64 &self,
65 Parameters(request): Parameters<CreateDatabaseRequest>,
66 ) -> Result<Json<MessageResponse>, ErrorData> {
67 Ok(Json(self.create_database(&request).await?))
68 }
69
70 #[tool(
72 name = "drop_database",
73 annotations(
74 read_only_hint = false,
75 destructive_hint = true,
76 idempotent_hint = false,
77 open_world_hint = false
78 )
79 )]
80 pub async fn tool_drop_database(
81 &self,
82 Parameters(request): Parameters<DropDatabaseRequest>,
83 ) -> Result<Json<MessageResponse>, ErrorData> {
84 Ok(Json(self.drop_database(&request).await?))
85 }
86
87 #[tool(
90 name = "list_tables",
91 annotations(
92 read_only_hint = true,
93 destructive_hint = false,
94 idempotent_hint = true,
95 open_world_hint = false
96 )
97 )]
98 pub async fn tool_list_tables(
99 &self,
100 Parameters(request): Parameters<ListTablesRequest>,
101 ) -> Result<Json<ListTablesResponse>, ErrorData> {
102 Ok(Json(self.list_tables(&request).await?))
103 }
104
105 #[tool(
108 name = "get_table_schema",
109 annotations(
110 read_only_hint = true,
111 destructive_hint = false,
112 idempotent_hint = true,
113 open_world_hint = false
114 )
115 )]
116 pub async fn tool_get_table_schema(
117 &self,
118 Parameters(request): Parameters<GetTableSchemaRequest>,
119 ) -> Result<Json<TableSchemaResponse>, ErrorData> {
120 Ok(Json(self.get_table_schema(&request).await?))
121 }
122
123 #[tool(
126 name = "drop_table",
127 annotations(
128 read_only_hint = false,
129 destructive_hint = true,
130 idempotent_hint = false,
131 open_world_hint = false
132 )
133 )]
134 pub async fn tool_drop_table(
135 &self,
136 Parameters(request): Parameters<DropTableRequest>,
137 ) -> Result<Json<MessageResponse>, ErrorData> {
138 Ok(Json(self.drop_table(&request).await?))
139 }
140
141 #[tool(
143 name = "read_query",
144 annotations(
145 read_only_hint = true,
146 destructive_hint = false,
147 idempotent_hint = true,
148 open_world_hint = true
149 )
150 )]
151 pub async fn tool_read_query(
152 &self,
153 Parameters(request): Parameters<QueryRequest>,
154 ) -> Result<Json<QueryResponse>, ErrorData> {
155 Ok(Json(self.read_query(&request).await?))
156 }
157
158 #[tool(
160 name = "write_query",
161 annotations(
162 read_only_hint = false,
163 destructive_hint = true,
164 idempotent_hint = false,
165 open_world_hint = true
166 )
167 )]
168 pub async fn tool_write_query(
169 &self,
170 Parameters(request): Parameters<QueryRequest>,
171 ) -> Result<Json<QueryResponse>, ErrorData> {
172 Ok(Json(self.write_query(&request).await?))
173 }
174
175 #[tool(
177 name = "explain_query",
178 annotations(
179 read_only_hint = true,
180 destructive_hint = false,
181 idempotent_hint = true,
182 open_world_hint = true
183 )
184 )]
185 pub async fn tool_explain_query(
186 &self,
187 Parameters(request): Parameters<ExplainQueryRequest>,
188 ) -> Result<Json<QueryResponse>, ErrorData> {
189 Ok(Json(self.explain_query(&request).await?))
190 }
191}