1
1
"""Storage-related tools for the MCP server (buckets, tables, etc.)."""
2
2
3
3
import logging
4
- from typing import Annotated , Any , Dict , List , Optional , cast
4
+ from typing import Annotated , Any , Dict , List , Optional , Union , cast
5
5
6
6
from mcp .server .fastmcp import Context , FastMCP
7
7
from pydantic import AliasChoices , BaseModel , Field , model_validator
@@ -18,6 +18,8 @@ def add_storage_tools(mcp: FastMCP) -> None:
18
18
mcp .add_tool (get_bucket_metadata )
19
19
mcp .add_tool (list_bucket_tables )
20
20
mcp .add_tool (get_table_metadata )
21
+ mcp .add_tool (update_bucket_description )
22
+ mcp .add_tool (update_table_description )
21
23
22
24
logger .info ("Component tools added to the MCP server." )
23
25
@@ -131,6 +133,26 @@ def set_description(cls, values):
131
133
return values
132
134
133
135
136
+ class UpdateBucketDescriptionSuccessResponse (BaseModel ):
137
+ success : bool = True
138
+ data : List [dict ]
139
+
140
+
141
+ class UpdateBucketDescriptionErrorResponse (BaseModel ):
142
+ success : bool = False
143
+ error : str
144
+
145
+
146
+ class UpdateTableDescriptionSuccessResponse (BaseModel ):
147
+ success : bool = True
148
+ data : List [dict ]
149
+
150
+
151
+ class UpdateTableDescriptionErrorResponse (BaseModel ):
152
+ success : bool = False
153
+ error : str
154
+
155
+
134
156
async def get_bucket_metadata (
135
157
bucket_id : Annotated [str , Field (description = "Unique ID of the bucket." )], ctx : Context
136
158
) -> BucketInfo :
@@ -183,3 +205,85 @@ async def list_bucket_tables(
183
205
raw_tables = cast (List [Dict [str , Any ]], client .storage_client .buckets .list_tables (bucket_id ))
184
206
185
207
return [TableDetail (** raw_table ) for raw_table in raw_tables ]
208
+
209
+
210
+ async def update_bucket_description (
211
+ bucket_id : Annotated [str , Field (description = "The ID of the bucket to update." )],
212
+ description : Annotated [str , Field (description = "The new description for the bucket." )],
213
+ ctx : Context ,
214
+ ):
215
+ """
216
+ Update the description for a given Keboola bucket.
217
+
218
+ Args:
219
+ bucket_id: The ID of the bucket to update.
220
+ description: The new description for the bucket.
221
+
222
+ Returns:
223
+ The response from the API.
224
+ """
225
+ client = KeboolaClient .from_state (ctx .session .state )
226
+ metadata_endpoint = f"buckets/{ bucket_id } /metadata"
227
+
228
+ data = {"provider" : "user" , "metadata" : [{"key" : "KBC.description" , "value" : description }]}
229
+
230
+ response = await client .post (metadata_endpoint , data )
231
+ return response
232
+
233
+
234
+ async def update_bucket_description (
235
+ bucket_id : Annotated [str , Field (description = "The ID of the bucket to update." )],
236
+ description : Annotated [str , Field (description = "The new description for the bucket." )],
237
+ ctx : Context ,
238
+ ) -> Union [UpdateBucketDescriptionSuccessResponse , UpdateBucketDescriptionErrorResponse ]:
239
+ """
240
+ Update the description for a given Keboola bucket.
241
+
242
+ Args:
243
+ bucket_id: The ID of the bucket to update.
244
+ description: The new description for the bucket.
245
+
246
+ Returns:
247
+ UpdateBucketDescriptionSuccessResponse on success,
248
+ UpdateBucketDescriptionErrorResponse on failure.
249
+ """
250
+ client = KeboolaClient .from_state (ctx .session .state )
251
+ metadata_endpoint = f"buckets/{ bucket_id } /metadata"
252
+
253
+ data = {"provider" : "user" , "metadata" : [{"key" : "KBC.description" , "value" : description }]}
254
+
255
+ try :
256
+ response = await client .post (metadata_endpoint , data )
257
+ print (response )
258
+ return UpdateBucketDescriptionSuccessResponse (data = response )
259
+ except Exception as e :
260
+ return UpdateBucketDescriptionErrorResponse (error = str (e ))
261
+
262
+
263
+ async def update_table_description (
264
+ table_id : Annotated [str , Field (description = "The ID of the table to update." )],
265
+ description : Annotated [str , Field (description = "The new description for the table." )],
266
+ ctx : Context ,
267
+ ) -> Union [UpdateTableDescriptionSuccessResponse , UpdateTableDescriptionErrorResponse ]:
268
+ """
269
+ Update the description for a given Keboola table.
270
+
271
+ Args:
272
+ table_id: The ID of the table to update.
273
+ description: The new description for the table.
274
+
275
+ Returns:
276
+ UpdateTableDescriptionSuccessResponse on success,
277
+ UpdateTableDescriptionErrorResponse on failure.
278
+ """
279
+ client = KeboolaClient .from_state (ctx .session .state )
280
+ metadata_endpoint = f"tables/{ table_id } /metadata"
281
+
282
+ data = {"provider" : "user" , "metadata" : [{"key" : "KBC.description" , "value" : description }]}
283
+
284
+ try :
285
+ response = await client .post (metadata_endpoint , data )
286
+ print (response )
287
+ return UpdateTableDescriptionSuccessResponse (data = response ["metadata" ])
288
+ except Exception as e :
289
+ return UpdateTableDescriptionErrorResponse (error = str (e ))
0 commit comments