awslabs.valkey-mcp-server 0.1.1__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- awslabs/__init__.py +13 -0
- awslabs/valkey_mcp_server/__init__.py +14 -0
- awslabs/valkey_mcp_server/common/__init__.py +20 -0
- awslabs/valkey_mcp_server/common/config.py +85 -0
- awslabs/valkey_mcp_server/common/connection.py +97 -0
- awslabs/valkey_mcp_server/common/server.py +23 -0
- awslabs/valkey_mcp_server/main.py +84 -0
- awslabs/valkey_mcp_server/tools/__init__.py +28 -0
- awslabs/valkey_mcp_server/tools/bitmap.py +148 -0
- awslabs/valkey_mcp_server/tools/hash.py +283 -0
- awslabs/valkey_mcp_server/tools/hyperloglog.py +58 -0
- awslabs/valkey_mcp_server/tools/json.py +422 -0
- awslabs/valkey_mcp_server/tools/list.py +376 -0
- awslabs/valkey_mcp_server/tools/misc.py +104 -0
- awslabs/valkey_mcp_server/tools/server_management.py +54 -0
- awslabs/valkey_mcp_server/tools/set.py +182 -0
- awslabs/valkey_mcp_server/tools/sorted_set.py +359 -0
- awslabs/valkey_mcp_server/tools/stream.py +343 -0
- awslabs/valkey_mcp_server/tools/string.py +228 -0
- awslabs/valkey_mcp_server/version.py +12 -0
- awslabs_valkey_mcp_server-0.1.1.dist-info/METADATA +164 -0
- awslabs_valkey_mcp_server-0.1.1.dist-info/RECORD +26 -0
- awslabs_valkey_mcp_server-0.1.1.dist-info/WHEEL +4 -0
- awslabs_valkey_mcp_server-0.1.1.dist-info/entry_points.txt +2 -0
- awslabs_valkey_mcp_server-0.1.1.dist-info/licenses/LICENSE +175 -0
- awslabs_valkey_mcp_server-0.1.1.dist-info/licenses/NOTICE +2 -0
|
@@ -0,0 +1,376 @@
|
|
|
1
|
+
# Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
|
|
2
|
+
#
|
|
3
|
+
# Licensed under the Apache License, Version 2.0 (the "License"). You may not use this file except in compliance
|
|
4
|
+
# with the License. A copy of the License is located at
|
|
5
|
+
#
|
|
6
|
+
# http://www.apache.org/licenses/LICENSE-2.0
|
|
7
|
+
#
|
|
8
|
+
# or in the 'license' file accompanying this file. This file is distributed on an 'AS IS' BASIS, WITHOUT WARRANTIES
|
|
9
|
+
# OR CONDITIONS OF ANY KIND, express or implied. See the License for the specific language governing permissions
|
|
10
|
+
# and limitations under the License.
|
|
11
|
+
|
|
12
|
+
"""List operations for Valkey MCP Server."""
|
|
13
|
+
|
|
14
|
+
from awslabs.valkey_mcp_server.common.connection import ValkeyConnectionManager
|
|
15
|
+
from awslabs.valkey_mcp_server.common.server import mcp
|
|
16
|
+
from typing import Any, Optional
|
|
17
|
+
from typing import List as PyList
|
|
18
|
+
from valkey.exceptions import ValkeyError
|
|
19
|
+
|
|
20
|
+
|
|
21
|
+
@mcp.tool()
|
|
22
|
+
async def list_append(key: str, value: Any) -> str:
|
|
23
|
+
"""Append value to list.
|
|
24
|
+
|
|
25
|
+
Args:
|
|
26
|
+
key: The name of the key
|
|
27
|
+
value: The value to append
|
|
28
|
+
|
|
29
|
+
Returns:
|
|
30
|
+
Success message or error message
|
|
31
|
+
"""
|
|
32
|
+
try:
|
|
33
|
+
r = ValkeyConnectionManager.get_connection()
|
|
34
|
+
result = r.rpush(key, value)
|
|
35
|
+
return f"Successfully appended value to list '{key}', new length: {result}"
|
|
36
|
+
except ValkeyError as e:
|
|
37
|
+
return f"Error appending to list '{key}': {str(e)}"
|
|
38
|
+
|
|
39
|
+
|
|
40
|
+
@mcp.tool()
|
|
41
|
+
async def list_prepend(key: str, value: Any) -> str:
|
|
42
|
+
"""Prepend value to list.
|
|
43
|
+
|
|
44
|
+
Args:
|
|
45
|
+
key: The name of the key
|
|
46
|
+
value: The value to prepend
|
|
47
|
+
|
|
48
|
+
Returns:
|
|
49
|
+
Success message or error message
|
|
50
|
+
"""
|
|
51
|
+
try:
|
|
52
|
+
r = ValkeyConnectionManager.get_connection()
|
|
53
|
+
result = r.lpush(key, value)
|
|
54
|
+
return f"Successfully prepended value to list '{key}', new length: {result}"
|
|
55
|
+
except ValkeyError as e:
|
|
56
|
+
return f"Error prepending to list '{key}': {str(e)}"
|
|
57
|
+
|
|
58
|
+
|
|
59
|
+
@mcp.tool()
|
|
60
|
+
async def list_append_multiple(key: str, values: PyList[Any]) -> str:
|
|
61
|
+
"""Append multiple values to list.
|
|
62
|
+
|
|
63
|
+
Args:
|
|
64
|
+
key: The name of the key
|
|
65
|
+
values: List of values to append
|
|
66
|
+
|
|
67
|
+
Returns:
|
|
68
|
+
Success message or error message
|
|
69
|
+
"""
|
|
70
|
+
try:
|
|
71
|
+
r = ValkeyConnectionManager.get_connection()
|
|
72
|
+
result = r.rpush(key, *values)
|
|
73
|
+
return f"Successfully appended {len(values)} values to list '{key}', new length: {result}"
|
|
74
|
+
except ValkeyError as e:
|
|
75
|
+
return f"Error appending multiple values to list '{key}': {str(e)}"
|
|
76
|
+
|
|
77
|
+
|
|
78
|
+
@mcp.tool()
|
|
79
|
+
async def list_prepend_multiple(key: str, values: PyList[Any]) -> str:
|
|
80
|
+
"""Prepend multiple values to list.
|
|
81
|
+
|
|
82
|
+
Args:
|
|
83
|
+
key: The name of the key
|
|
84
|
+
values: List of values to prepend
|
|
85
|
+
|
|
86
|
+
Returns:
|
|
87
|
+
Success message or error message
|
|
88
|
+
"""
|
|
89
|
+
try:
|
|
90
|
+
r = ValkeyConnectionManager.get_connection()
|
|
91
|
+
result = r.lpush(key, *values)
|
|
92
|
+
return f"Successfully prepended {len(values)} values to list '{key}', new length: {result}"
|
|
93
|
+
except ValkeyError as e:
|
|
94
|
+
return f"Error prepending multiple values to list '{key}': {str(e)}"
|
|
95
|
+
|
|
96
|
+
|
|
97
|
+
@mcp.tool()
|
|
98
|
+
async def list_get(key: str, index: int) -> str:
|
|
99
|
+
"""Get value at index from list.
|
|
100
|
+
|
|
101
|
+
Args:
|
|
102
|
+
key: The name of the key
|
|
103
|
+
index: The index (0-based, negative indices supported)
|
|
104
|
+
|
|
105
|
+
Returns:
|
|
106
|
+
Value or error message
|
|
107
|
+
"""
|
|
108
|
+
try:
|
|
109
|
+
r = ValkeyConnectionManager.get_connection()
|
|
110
|
+
result = r.lindex(key, index)
|
|
111
|
+
if result is None:
|
|
112
|
+
return f"No value found at index {index} in list '{key}'"
|
|
113
|
+
return str(result)
|
|
114
|
+
except ValkeyError as e:
|
|
115
|
+
return f"Error getting value from list '{key}': {str(e)}"
|
|
116
|
+
|
|
117
|
+
|
|
118
|
+
@mcp.tool()
|
|
119
|
+
async def list_set(key: str, index: int, value: Any) -> str:
|
|
120
|
+
"""Set value at index in list.
|
|
121
|
+
|
|
122
|
+
Args:
|
|
123
|
+
key: The name of the key
|
|
124
|
+
index: The index (0-based, negative indices supported)
|
|
125
|
+
value: The value to set
|
|
126
|
+
|
|
127
|
+
Returns:
|
|
128
|
+
Success message or error message
|
|
129
|
+
"""
|
|
130
|
+
try:
|
|
131
|
+
r = ValkeyConnectionManager.get_connection()
|
|
132
|
+
r.lset(key, index, value)
|
|
133
|
+
return f"Successfully set value at index {index} in list '{key}'"
|
|
134
|
+
except ValkeyError as e:
|
|
135
|
+
return f"Error setting value in list '{key}': {str(e)}"
|
|
136
|
+
|
|
137
|
+
|
|
138
|
+
@mcp.tool()
|
|
139
|
+
async def list_range(key: str, start: int = 0, stop: int = -1) -> str:
|
|
140
|
+
"""Get range of values from list.
|
|
141
|
+
|
|
142
|
+
Args:
|
|
143
|
+
key: The name of the key
|
|
144
|
+
start: Start index (inclusive, default 0)
|
|
145
|
+
stop: Stop index (inclusive, default -1 for end)
|
|
146
|
+
|
|
147
|
+
Returns:
|
|
148
|
+
List of values or error message
|
|
149
|
+
"""
|
|
150
|
+
try:
|
|
151
|
+
r = ValkeyConnectionManager.get_connection()
|
|
152
|
+
result = r.lrange(key, start, stop)
|
|
153
|
+
if not result:
|
|
154
|
+
return f"No values found in range [{start}, {stop}] in list '{key}'"
|
|
155
|
+
return str(result)
|
|
156
|
+
except ValkeyError as e:
|
|
157
|
+
return f"Error getting range from list '{key}': {str(e)}"
|
|
158
|
+
|
|
159
|
+
|
|
160
|
+
@mcp.tool()
|
|
161
|
+
async def list_trim(key: str, start: int, stop: int) -> str:
|
|
162
|
+
"""Trim list to specified range.
|
|
163
|
+
|
|
164
|
+
Args:
|
|
165
|
+
key: The name of the key
|
|
166
|
+
start: Start index (inclusive)
|
|
167
|
+
stop: Stop index (inclusive)
|
|
168
|
+
|
|
169
|
+
Returns:
|
|
170
|
+
Success message or error message
|
|
171
|
+
"""
|
|
172
|
+
try:
|
|
173
|
+
r = ValkeyConnectionManager.get_connection()
|
|
174
|
+
r.ltrim(key, start, stop)
|
|
175
|
+
return f"Successfully trimmed list '{key}' to range [{start}, {stop}]"
|
|
176
|
+
except ValkeyError as e:
|
|
177
|
+
return f"Error trimming list '{key}': {str(e)}"
|
|
178
|
+
|
|
179
|
+
|
|
180
|
+
@mcp.tool()
|
|
181
|
+
async def list_length(key: str) -> str:
|
|
182
|
+
"""Get length of list.
|
|
183
|
+
|
|
184
|
+
Args:
|
|
185
|
+
key: The name of the key
|
|
186
|
+
|
|
187
|
+
Returns:
|
|
188
|
+
Length or error message
|
|
189
|
+
"""
|
|
190
|
+
try:
|
|
191
|
+
r = ValkeyConnectionManager.get_connection()
|
|
192
|
+
result = r.llen(key)
|
|
193
|
+
return str(result)
|
|
194
|
+
except ValkeyError as e:
|
|
195
|
+
return f"Error getting list length for '{key}': {str(e)}"
|
|
196
|
+
|
|
197
|
+
|
|
198
|
+
@mcp.tool()
|
|
199
|
+
async def list_pop_left(key: str, count: Optional[int] = None) -> str:
|
|
200
|
+
"""Pop value(s) from left of list.
|
|
201
|
+
|
|
202
|
+
Args:
|
|
203
|
+
key: The name of the key
|
|
204
|
+
count: Number of values to pop (optional)
|
|
205
|
+
|
|
206
|
+
Returns:
|
|
207
|
+
Value(s) or error message
|
|
208
|
+
"""
|
|
209
|
+
try:
|
|
210
|
+
r = ValkeyConnectionManager.get_connection()
|
|
211
|
+
if count:
|
|
212
|
+
result = r.lpop(key, count)
|
|
213
|
+
else:
|
|
214
|
+
result = r.lpop(key)
|
|
215
|
+
if result is None:
|
|
216
|
+
return f"List '{key}' is empty"
|
|
217
|
+
return str(result)
|
|
218
|
+
except ValkeyError as e:
|
|
219
|
+
return f"Error popping from left of list '{key}': {str(e)}"
|
|
220
|
+
|
|
221
|
+
|
|
222
|
+
@mcp.tool()
|
|
223
|
+
async def list_pop_right(key: str, count: Optional[int] = None) -> str:
|
|
224
|
+
"""Pop value(s) from right of list.
|
|
225
|
+
|
|
226
|
+
Args:
|
|
227
|
+
key: The name of the key
|
|
228
|
+
count: Number of values to pop (optional)
|
|
229
|
+
|
|
230
|
+
Returns:
|
|
231
|
+
Value(s) or error message
|
|
232
|
+
"""
|
|
233
|
+
try:
|
|
234
|
+
r = ValkeyConnectionManager.get_connection()
|
|
235
|
+
if count:
|
|
236
|
+
result = r.rpop(key, count)
|
|
237
|
+
else:
|
|
238
|
+
result = r.rpop(key)
|
|
239
|
+
if result is None:
|
|
240
|
+
return f"List '{key}' is empty"
|
|
241
|
+
return str(result)
|
|
242
|
+
except ValkeyError as e:
|
|
243
|
+
return f"Error popping from right of list '{key}': {str(e)}"
|
|
244
|
+
|
|
245
|
+
|
|
246
|
+
@mcp.tool()
|
|
247
|
+
async def list_position(
|
|
248
|
+
key: str,
|
|
249
|
+
value: Any,
|
|
250
|
+
rank: Optional[int] = None,
|
|
251
|
+
count: Optional[int] = None,
|
|
252
|
+
maxlen: Optional[int] = None,
|
|
253
|
+
) -> str:
|
|
254
|
+
"""Find position(s) of value in list.
|
|
255
|
+
|
|
256
|
+
Args:
|
|
257
|
+
key: The name of the key
|
|
258
|
+
value: Value to search for
|
|
259
|
+
rank: Match the Nth occurrence (optional)
|
|
260
|
+
count: Return this many matches (optional)
|
|
261
|
+
maxlen: Limit search to first N elements (optional)
|
|
262
|
+
|
|
263
|
+
Returns:
|
|
264
|
+
Position(s) or error message
|
|
265
|
+
"""
|
|
266
|
+
try:
|
|
267
|
+
r = ValkeyConnectionManager.get_connection()
|
|
268
|
+
options = {}
|
|
269
|
+
if rank is not None:
|
|
270
|
+
options['rank'] = rank
|
|
271
|
+
if count is not None:
|
|
272
|
+
options['count'] = count
|
|
273
|
+
if maxlen is not None:
|
|
274
|
+
options['maxlen'] = maxlen
|
|
275
|
+
|
|
276
|
+
result = r.lpos(key, value, **options)
|
|
277
|
+
if result is None:
|
|
278
|
+
return f"Value not found in list '{key}'"
|
|
279
|
+
return str(result)
|
|
280
|
+
except ValkeyError as e:
|
|
281
|
+
return f"Error finding position in list '{key}': {str(e)}"
|
|
282
|
+
|
|
283
|
+
|
|
284
|
+
@mcp.tool()
|
|
285
|
+
async def list_move(
|
|
286
|
+
source: str, destination: str, wherefrom: str = 'LEFT', whereto: str = 'RIGHT'
|
|
287
|
+
) -> str:
|
|
288
|
+
"""Move element from one list to another.
|
|
289
|
+
|
|
290
|
+
Args:
|
|
291
|
+
source: Source list key
|
|
292
|
+
destination: Destination list key
|
|
293
|
+
wherefrom: Where to pop from ("LEFT" or "RIGHT")
|
|
294
|
+
whereto: Where to push to ("LEFT" or "RIGHT")
|
|
295
|
+
|
|
296
|
+
Returns:
|
|
297
|
+
Moved value or error message
|
|
298
|
+
"""
|
|
299
|
+
try:
|
|
300
|
+
r = ValkeyConnectionManager.get_connection()
|
|
301
|
+
wherefrom = wherefrom.upper()
|
|
302
|
+
whereto = whereto.upper()
|
|
303
|
+
|
|
304
|
+
if wherefrom not in ['LEFT', 'RIGHT'] or whereto not in ['LEFT', 'RIGHT']:
|
|
305
|
+
return "Error: wherefrom and whereto must be either 'LEFT' or 'RIGHT'"
|
|
306
|
+
|
|
307
|
+
result = r.lmove(source, destination, wherefrom, whereto)
|
|
308
|
+
if result is None:
|
|
309
|
+
return f"Source list '{source}' is empty"
|
|
310
|
+
return f"Successfully moved value '{result}' from {wherefrom} of '{source}' to {whereto} of '{destination}'"
|
|
311
|
+
except ValkeyError as e:
|
|
312
|
+
return f'Error moving value between lists: {str(e)}'
|
|
313
|
+
|
|
314
|
+
|
|
315
|
+
@mcp.tool()
|
|
316
|
+
async def list_insert_before(key: str, pivot: Any, value: Any) -> str:
|
|
317
|
+
"""Insert value before pivot in list.
|
|
318
|
+
|
|
319
|
+
Args:
|
|
320
|
+
key: The name of the key
|
|
321
|
+
pivot: The pivot value
|
|
322
|
+
value: The value to insert
|
|
323
|
+
|
|
324
|
+
Returns:
|
|
325
|
+
Success message or error message
|
|
326
|
+
"""
|
|
327
|
+
try:
|
|
328
|
+
r = ValkeyConnectionManager.get_connection()
|
|
329
|
+
result = r.linsert(key, 'BEFORE', pivot, value)
|
|
330
|
+
if result == -1:
|
|
331
|
+
return f"Pivot value not found in list '{key}'"
|
|
332
|
+
return f"Successfully inserted value before pivot in list '{key}', new length: {result}"
|
|
333
|
+
except ValkeyError as e:
|
|
334
|
+
return f"Error inserting before pivot in list '{key}': {str(e)}"
|
|
335
|
+
|
|
336
|
+
|
|
337
|
+
@mcp.tool()
|
|
338
|
+
async def list_insert_after(key: str, pivot: Any, value: Any) -> str:
|
|
339
|
+
"""Insert value after pivot in list.
|
|
340
|
+
|
|
341
|
+
Args:
|
|
342
|
+
key: The name of the key
|
|
343
|
+
pivot: The pivot value
|
|
344
|
+
value: The value to insert
|
|
345
|
+
|
|
346
|
+
Returns:
|
|
347
|
+
Success message or error message
|
|
348
|
+
"""
|
|
349
|
+
try:
|
|
350
|
+
r = ValkeyConnectionManager.get_connection()
|
|
351
|
+
result = r.linsert(key, 'AFTER', pivot, value)
|
|
352
|
+
if result == -1:
|
|
353
|
+
return f"Pivot value not found in list '{key}'"
|
|
354
|
+
return f"Successfully inserted value after pivot in list '{key}', new length: {result}"
|
|
355
|
+
except ValkeyError as e:
|
|
356
|
+
return f"Error inserting after pivot in list '{key}': {str(e)}"
|
|
357
|
+
|
|
358
|
+
|
|
359
|
+
@mcp.tool()
|
|
360
|
+
async def list_remove(key: str, value: Any, count: int = 0) -> str:
|
|
361
|
+
"""Remove occurrences of value from list.
|
|
362
|
+
|
|
363
|
+
Args:
|
|
364
|
+
key: The name of the key
|
|
365
|
+
value: Value to remove
|
|
366
|
+
count: Number of occurrences to remove (0 for all, positive for left-to-right, negative for right-to-left)
|
|
367
|
+
|
|
368
|
+
Returns:
|
|
369
|
+
Success message or error message
|
|
370
|
+
"""
|
|
371
|
+
try:
|
|
372
|
+
r = ValkeyConnectionManager.get_connection()
|
|
373
|
+
result = r.lrem(key, count, value)
|
|
374
|
+
return f"Successfully removed {result} occurrence(s) of value from list '{key}'"
|
|
375
|
+
except ValkeyError as e:
|
|
376
|
+
return f"Error removing value from list '{key}': {str(e)}"
|
|
@@ -0,0 +1,104 @@
|
|
|
1
|
+
# Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
|
|
2
|
+
#
|
|
3
|
+
# Licensed under the Apache License, Version 2.0 (the "License"). You may not use this file except in compliance
|
|
4
|
+
# with the License. A copy of the License is located at
|
|
5
|
+
#
|
|
6
|
+
# http://www.apache.org/licenses/LICENSE-2.0
|
|
7
|
+
#
|
|
8
|
+
# or in the 'license' file accompanying this file. This file is distributed on an 'AS IS' BASIS, WITHOUT WARRANTIES
|
|
9
|
+
# OR CONDITIONS OF ANY KIND, express or implied. See the License for the specific language governing permissions
|
|
10
|
+
# and limitations under the License.
|
|
11
|
+
|
|
12
|
+
from awslabs.valkey_mcp_server.common.connection import ValkeyConnectionManager
|
|
13
|
+
from awslabs.valkey_mcp_server.common.server import mcp
|
|
14
|
+
from typing import Any, Dict
|
|
15
|
+
from valkey.exceptions import ValkeyError as RedisError
|
|
16
|
+
|
|
17
|
+
|
|
18
|
+
@mcp.tool()
|
|
19
|
+
async def delete(key: str) -> str:
|
|
20
|
+
"""Delete a Valkey key.
|
|
21
|
+
|
|
22
|
+
Args:
|
|
23
|
+
key (str): The key to delete.
|
|
24
|
+
|
|
25
|
+
Returns:
|
|
26
|
+
str: Confirmation message or an error message.
|
|
27
|
+
"""
|
|
28
|
+
try:
|
|
29
|
+
r = ValkeyConnectionManager.get_connection()
|
|
30
|
+
result = r.delete(key)
|
|
31
|
+
return f'Successfully deleted {key}' if result else f'Key {key} not found'
|
|
32
|
+
except RedisError as e:
|
|
33
|
+
return f'Error deleting key {key}: {str(e)}'
|
|
34
|
+
|
|
35
|
+
|
|
36
|
+
@mcp.tool()
|
|
37
|
+
async def type(key: str) -> Dict[str, Any]:
|
|
38
|
+
"""Returns the string representation of the type of the value stored at key.
|
|
39
|
+
|
|
40
|
+
Args:
|
|
41
|
+
key (str): The key to check.
|
|
42
|
+
|
|
43
|
+
Returns:
|
|
44
|
+
str: The type of key, or none when key doesn't exist
|
|
45
|
+
"""
|
|
46
|
+
try:
|
|
47
|
+
r = ValkeyConnectionManager.get_connection()
|
|
48
|
+
key_type = r.type(key)
|
|
49
|
+
info = {'key': key, 'type': key_type, 'ttl': r.ttl(key)}
|
|
50
|
+
|
|
51
|
+
return info
|
|
52
|
+
except RedisError as e:
|
|
53
|
+
return {'error': str(e)}
|
|
54
|
+
|
|
55
|
+
|
|
56
|
+
@mcp.tool()
|
|
57
|
+
async def expire(name: str, expire_seconds: int) -> str:
|
|
58
|
+
"""Set an expiration time for a Redis key.
|
|
59
|
+
|
|
60
|
+
Args:
|
|
61
|
+
name: The Redis key.
|
|
62
|
+
expire_seconds: Time in seconds after which the key should expire.
|
|
63
|
+
|
|
64
|
+
Returns:
|
|
65
|
+
A success message or an error message.
|
|
66
|
+
"""
|
|
67
|
+
try:
|
|
68
|
+
r = ValkeyConnectionManager.get_connection()
|
|
69
|
+
success = r.expire(name, expire_seconds)
|
|
70
|
+
return (
|
|
71
|
+
f"Expiration set to {expire_seconds} seconds for '{name}'."
|
|
72
|
+
if success
|
|
73
|
+
else f"Key '{name}' does not exist."
|
|
74
|
+
)
|
|
75
|
+
except RedisError as e:
|
|
76
|
+
return f"Error setting expiration for key '{name}': {str(e)}"
|
|
77
|
+
|
|
78
|
+
|
|
79
|
+
@mcp.tool()
|
|
80
|
+
async def rename(old_key: str, new_key: str) -> Dict[str, Any]:
|
|
81
|
+
"""Renames a Redis key from old_key to new_key.
|
|
82
|
+
|
|
83
|
+
Args:
|
|
84
|
+
old_key (str): The current name of the Redis key to rename.
|
|
85
|
+
new_key (str): The new name to assign to the key.
|
|
86
|
+
|
|
87
|
+
Returns:
|
|
88
|
+
Dict[str, Any]: A dictionary containing the result of the operation.
|
|
89
|
+
On success: {"status": "success", "message": "..."}
|
|
90
|
+
On error: {"error": "..."}
|
|
91
|
+
"""
|
|
92
|
+
try:
|
|
93
|
+
r = ValkeyConnectionManager.get_connection()
|
|
94
|
+
|
|
95
|
+
# Check if the old key exists
|
|
96
|
+
if not r.exists(old_key):
|
|
97
|
+
return {'error': f"Key '{old_key}' does not exist."}
|
|
98
|
+
|
|
99
|
+
# Rename the key
|
|
100
|
+
r.rename(old_key, new_key)
|
|
101
|
+
return {'status': 'success', 'message': f"Renamed key '{old_key}' to '{new_key}'"}
|
|
102
|
+
|
|
103
|
+
except RedisError as e:
|
|
104
|
+
return {'error': str(e)}
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
# Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
|
|
2
|
+
#
|
|
3
|
+
# Licensed under the Apache License, Version 2.0 (the "License"). You may not use this file except in compliance
|
|
4
|
+
# with the License. A copy of the License is located at
|
|
5
|
+
#
|
|
6
|
+
# http://www.apache.org/licenses/LICENSE-2.0
|
|
7
|
+
#
|
|
8
|
+
# or in the 'license' file accompanying this file. This file is distributed on an 'AS IS' BASIS, WITHOUT WARRANTIES
|
|
9
|
+
# OR CONDITIONS OF ANY KIND, express or implied. See the License for the specific language governing permissions
|
|
10
|
+
# and limitations under the License.
|
|
11
|
+
|
|
12
|
+
from awslabs.valkey_mcp_server.common.connection import ValkeyConnectionManager
|
|
13
|
+
from awslabs.valkey_mcp_server.common.server import mcp
|
|
14
|
+
from valkey.exceptions import ValkeyError
|
|
15
|
+
|
|
16
|
+
|
|
17
|
+
@mcp.tool()
|
|
18
|
+
async def dbsize() -> str:
|
|
19
|
+
"""Get the number of keys stored in the Valkey database."""
|
|
20
|
+
try:
|
|
21
|
+
r = ValkeyConnectionManager.get_connection()
|
|
22
|
+
result = r.dbsize()
|
|
23
|
+
return str(result)
|
|
24
|
+
except ValkeyError as e:
|
|
25
|
+
raise RuntimeError(f'Error getting database size: {str(e)}')
|
|
26
|
+
|
|
27
|
+
|
|
28
|
+
@mcp.tool()
|
|
29
|
+
async def info(section: str = 'default') -> str:
|
|
30
|
+
"""Get Valkey server information and statistics.
|
|
31
|
+
|
|
32
|
+
Args:
|
|
33
|
+
section: The section of the info command (default, memory, cpu, etc.).
|
|
34
|
+
|
|
35
|
+
Returns:
|
|
36
|
+
A dictionary of server information or an error message.
|
|
37
|
+
"""
|
|
38
|
+
try:
|
|
39
|
+
r = ValkeyConnectionManager.get_connection()
|
|
40
|
+
info = r.info(section)
|
|
41
|
+
return str(info)
|
|
42
|
+
except ValkeyError as e:
|
|
43
|
+
raise RuntimeError(f'Error retrieving Redis info: {str(e)}')
|
|
44
|
+
|
|
45
|
+
|
|
46
|
+
@mcp.tool()
|
|
47
|
+
async def client_list() -> str:
|
|
48
|
+
"""Get a list of connected clients to the Valkey server."""
|
|
49
|
+
try:
|
|
50
|
+
r = ValkeyConnectionManager.get_connection()
|
|
51
|
+
clients = r.client_list()
|
|
52
|
+
return str(clients)
|
|
53
|
+
except ValkeyError as e:
|
|
54
|
+
raise RuntimeError(f'Error retrieving client list: {str(e)}')
|