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,343 @@
|
|
|
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
|
+
"""Stream 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, Dict, Optional
|
|
17
|
+
from valkey.exceptions import ValkeyError
|
|
18
|
+
|
|
19
|
+
|
|
20
|
+
@mcp.tool()
|
|
21
|
+
async def stream_add(
|
|
22
|
+
key: str,
|
|
23
|
+
field_dict: Dict[str, Any],
|
|
24
|
+
id: str = '*',
|
|
25
|
+
maxlen: Optional[int] = None,
|
|
26
|
+
approximate: bool = True,
|
|
27
|
+
) -> str:
|
|
28
|
+
"""Add entry to stream.
|
|
29
|
+
|
|
30
|
+
Args:
|
|
31
|
+
key: The name of the key
|
|
32
|
+
field_dict: Dictionary of field-value pairs
|
|
33
|
+
id: Entry ID (default "*" for auto-generation)
|
|
34
|
+
maxlen: Maximum length of stream (optional)
|
|
35
|
+
approximate: Whether maxlen is approximate
|
|
36
|
+
|
|
37
|
+
Returns:
|
|
38
|
+
Success message or error message
|
|
39
|
+
"""
|
|
40
|
+
try:
|
|
41
|
+
r = ValkeyConnectionManager.get_connection()
|
|
42
|
+
options = {}
|
|
43
|
+
if maxlen is not None:
|
|
44
|
+
if approximate:
|
|
45
|
+
options['maxlen'] = '~' + str(maxlen)
|
|
46
|
+
else:
|
|
47
|
+
options['maxlen'] = maxlen
|
|
48
|
+
|
|
49
|
+
result = r.xadd(key, field_dict, id=id, **options)
|
|
50
|
+
return f"Successfully added entry with ID '{result}' to stream '{key}'"
|
|
51
|
+
except ValkeyError as e:
|
|
52
|
+
return f"Error adding to stream '{key}': {str(e)}"
|
|
53
|
+
|
|
54
|
+
|
|
55
|
+
@mcp.tool()
|
|
56
|
+
async def stream_delete(key: str, id: str) -> str:
|
|
57
|
+
"""Delete entries from stream.
|
|
58
|
+
|
|
59
|
+
Args:
|
|
60
|
+
key: The name of the key
|
|
61
|
+
id: Entry ID to delete
|
|
62
|
+
|
|
63
|
+
Returns:
|
|
64
|
+
Success message or error message
|
|
65
|
+
"""
|
|
66
|
+
try:
|
|
67
|
+
r = ValkeyConnectionManager.get_connection()
|
|
68
|
+
result = r.xdel(key, id)
|
|
69
|
+
return f"Successfully deleted {result} entries from stream '{key}'"
|
|
70
|
+
except ValkeyError as e:
|
|
71
|
+
return f"Error deleting from stream '{key}': {str(e)}"
|
|
72
|
+
|
|
73
|
+
|
|
74
|
+
@mcp.tool()
|
|
75
|
+
async def stream_trim(key: str, maxlen: int, approximate: bool = True) -> str:
|
|
76
|
+
"""Trim stream to specified length.
|
|
77
|
+
|
|
78
|
+
Args:
|
|
79
|
+
key: The name of the key
|
|
80
|
+
maxlen: Maximum length to trim to
|
|
81
|
+
approximate: Whether maxlen is approximate
|
|
82
|
+
|
|
83
|
+
Returns:
|
|
84
|
+
Success message or error message
|
|
85
|
+
"""
|
|
86
|
+
try:
|
|
87
|
+
r = ValkeyConnectionManager.get_connection()
|
|
88
|
+
result = r.xtrim(key, maxlen=maxlen, approximate=approximate)
|
|
89
|
+
return f"Successfully trimmed stream '{key}', removed {result} entries"
|
|
90
|
+
except ValkeyError as e:
|
|
91
|
+
return f"Error trimming stream '{key}': {str(e)}"
|
|
92
|
+
|
|
93
|
+
|
|
94
|
+
@mcp.tool()
|
|
95
|
+
async def stream_length(key: str) -> str:
|
|
96
|
+
"""Get length of stream.
|
|
97
|
+
|
|
98
|
+
Args:
|
|
99
|
+
key: The name of the key
|
|
100
|
+
|
|
101
|
+
Returns:
|
|
102
|
+
Length or error message
|
|
103
|
+
"""
|
|
104
|
+
try:
|
|
105
|
+
r = ValkeyConnectionManager.get_connection()
|
|
106
|
+
result = r.xlen(key)
|
|
107
|
+
return str(result)
|
|
108
|
+
except ValkeyError as e:
|
|
109
|
+
return f"Error getting stream length for '{key}': {str(e)}"
|
|
110
|
+
|
|
111
|
+
|
|
112
|
+
@mcp.tool()
|
|
113
|
+
async def stream_range(
|
|
114
|
+
key: str, start: str = '-', end: str = '+', count: Optional[int] = None, reverse: bool = False
|
|
115
|
+
) -> str:
|
|
116
|
+
"""Get range of entries from stream.
|
|
117
|
+
|
|
118
|
+
Args:
|
|
119
|
+
key: The name of the key
|
|
120
|
+
start: Start ID (default "-" for beginning)
|
|
121
|
+
end: End ID (default "+" for end)
|
|
122
|
+
count: Maximum number of entries to return
|
|
123
|
+
reverse: Return entries in reverse order
|
|
124
|
+
|
|
125
|
+
Returns:
|
|
126
|
+
List of entries or error message
|
|
127
|
+
"""
|
|
128
|
+
try:
|
|
129
|
+
r = ValkeyConnectionManager.get_connection()
|
|
130
|
+
result = (
|
|
131
|
+
r.xrevrange(key, end, start, count=count)
|
|
132
|
+
if reverse
|
|
133
|
+
else r.xrange(key, start, end, count=count)
|
|
134
|
+
)
|
|
135
|
+
if not result:
|
|
136
|
+
return f"No entries found in range for stream '{key}'"
|
|
137
|
+
return str(result)
|
|
138
|
+
except ValkeyError as e:
|
|
139
|
+
return f"Error getting range from stream '{key}': {str(e)}"
|
|
140
|
+
|
|
141
|
+
|
|
142
|
+
@mcp.tool()
|
|
143
|
+
async def stream_read(
|
|
144
|
+
key: str, count: Optional[int] = None, block: Optional[int] = None, last_id: str = '$'
|
|
145
|
+
) -> str:
|
|
146
|
+
"""Read entries from stream.
|
|
147
|
+
|
|
148
|
+
Args:
|
|
149
|
+
key: The name of the key
|
|
150
|
+
count: Maximum number of entries to return
|
|
151
|
+
block: Milliseconds to block (optional)
|
|
152
|
+
last_id: Last ID received (default "$" for new entries only)
|
|
153
|
+
|
|
154
|
+
Returns:
|
|
155
|
+
List of entries or error message
|
|
156
|
+
"""
|
|
157
|
+
try:
|
|
158
|
+
r = ValkeyConnectionManager.get_connection()
|
|
159
|
+
streams = {key: last_id}
|
|
160
|
+
result = r.xread(streams, count=count, block=block)
|
|
161
|
+
if not result:
|
|
162
|
+
return f"No new entries in stream '{key}'"
|
|
163
|
+
return str(result)
|
|
164
|
+
except ValkeyError as e:
|
|
165
|
+
return f"Error reading from stream '{key}': {str(e)}"
|
|
166
|
+
|
|
167
|
+
|
|
168
|
+
@mcp.tool()
|
|
169
|
+
async def stream_group_create(
|
|
170
|
+
key: str, group_name: str, id: str = '$', mkstream: bool = False
|
|
171
|
+
) -> str:
|
|
172
|
+
"""Create consumer group.
|
|
173
|
+
|
|
174
|
+
Args:
|
|
175
|
+
key: The name of the key
|
|
176
|
+
group_name: Name of consumer group
|
|
177
|
+
id: ID to start reading from (default "$" for new entries only)
|
|
178
|
+
mkstream: Create stream if it doesn't exist
|
|
179
|
+
|
|
180
|
+
Returns:
|
|
181
|
+
Success message or error message
|
|
182
|
+
"""
|
|
183
|
+
try:
|
|
184
|
+
r = ValkeyConnectionManager.get_connection()
|
|
185
|
+
r.xgroup_create(key, group_name, id=id, mkstream=mkstream)
|
|
186
|
+
return f"Successfully created consumer group '{group_name}' for stream '{key}'"
|
|
187
|
+
except ValkeyError as e:
|
|
188
|
+
return f'Error creating consumer group: {str(e)}'
|
|
189
|
+
|
|
190
|
+
|
|
191
|
+
@mcp.tool()
|
|
192
|
+
async def stream_group_destroy(key: str, group_name: str) -> str:
|
|
193
|
+
"""Destroy consumer group.
|
|
194
|
+
|
|
195
|
+
Args:
|
|
196
|
+
key: The name of the key
|
|
197
|
+
group_name: Name of consumer group
|
|
198
|
+
|
|
199
|
+
Returns:
|
|
200
|
+
Success message or error message
|
|
201
|
+
"""
|
|
202
|
+
try:
|
|
203
|
+
r = ValkeyConnectionManager.get_connection()
|
|
204
|
+
result = r.xgroup_destroy(key, group_name)
|
|
205
|
+
if result:
|
|
206
|
+
return f"Successfully destroyed consumer group '{group_name}' from stream '{key}'"
|
|
207
|
+
return f"Consumer group '{group_name}' not found in stream '{key}'"
|
|
208
|
+
except ValkeyError as e:
|
|
209
|
+
return f'Error destroying consumer group: {str(e)}'
|
|
210
|
+
|
|
211
|
+
|
|
212
|
+
@mcp.tool()
|
|
213
|
+
async def stream_group_set_id(key: str, group_name: str, id: str) -> str:
|
|
214
|
+
"""Set consumer group's last delivered ID.
|
|
215
|
+
|
|
216
|
+
Args:
|
|
217
|
+
key: The name of the key
|
|
218
|
+
group_name: Name of consumer group
|
|
219
|
+
id: ID to set as last delivered
|
|
220
|
+
|
|
221
|
+
Returns:
|
|
222
|
+
Success message or error message
|
|
223
|
+
"""
|
|
224
|
+
try:
|
|
225
|
+
r = ValkeyConnectionManager.get_connection()
|
|
226
|
+
r.xgroup_setid(key, group_name, id)
|
|
227
|
+
return f"Successfully set last delivered ID for group '{group_name}' in stream '{key}'"
|
|
228
|
+
except ValkeyError as e:
|
|
229
|
+
return f'Error setting group ID: {str(e)}'
|
|
230
|
+
|
|
231
|
+
|
|
232
|
+
@mcp.tool()
|
|
233
|
+
async def stream_group_delete_consumer(key: str, group_name: str, consumer_name: str) -> str:
|
|
234
|
+
"""Delete consumer from group.
|
|
235
|
+
|
|
236
|
+
Args:
|
|
237
|
+
key: The name of the key
|
|
238
|
+
group_name: Name of consumer group
|
|
239
|
+
consumer_name: Name of consumer to delete
|
|
240
|
+
|
|
241
|
+
Returns:
|
|
242
|
+
Success message or error message
|
|
243
|
+
"""
|
|
244
|
+
try:
|
|
245
|
+
r = ValkeyConnectionManager.get_connection()
|
|
246
|
+
result = r.xgroup_delconsumer(key, group_name, consumer_name)
|
|
247
|
+
return f"Successfully deleted consumer '{consumer_name}' from group '{group_name}', {result} pending entries"
|
|
248
|
+
except ValkeyError as e:
|
|
249
|
+
return f'Error deleting consumer: {str(e)}'
|
|
250
|
+
|
|
251
|
+
|
|
252
|
+
@mcp.tool()
|
|
253
|
+
async def stream_read_group(
|
|
254
|
+
key: str,
|
|
255
|
+
group_name: str,
|
|
256
|
+
consumer_name: str,
|
|
257
|
+
count: Optional[int] = None,
|
|
258
|
+
block: Optional[int] = None,
|
|
259
|
+
noack: bool = False,
|
|
260
|
+
) -> str:
|
|
261
|
+
"""Read entries from stream as part of consumer group.
|
|
262
|
+
|
|
263
|
+
Args:
|
|
264
|
+
key: The name of the key
|
|
265
|
+
group_name: Name of consumer group
|
|
266
|
+
consumer_name: Name of this consumer
|
|
267
|
+
count: Maximum number of entries to return
|
|
268
|
+
block: Milliseconds to block (optional)
|
|
269
|
+
noack: Don't require acknowledgment
|
|
270
|
+
|
|
271
|
+
Returns:
|
|
272
|
+
List of entries or error message
|
|
273
|
+
"""
|
|
274
|
+
try:
|
|
275
|
+
r = ValkeyConnectionManager.get_connection()
|
|
276
|
+
streams = {key: '>'} # ">" means read undelivered entries
|
|
277
|
+
result = r.xreadgroup(
|
|
278
|
+
group_name, consumer_name, streams, count=count, block=block, noack=noack
|
|
279
|
+
)
|
|
280
|
+
if not result:
|
|
281
|
+
return f"No new entries for consumer '{consumer_name}' in group '{group_name}'"
|
|
282
|
+
return str(result)
|
|
283
|
+
except ValkeyError as e:
|
|
284
|
+
return f'Error reading from group: {str(e)}'
|
|
285
|
+
|
|
286
|
+
|
|
287
|
+
@mcp.tool()
|
|
288
|
+
async def stream_info(key: str) -> str:
|
|
289
|
+
"""Get information about stream.
|
|
290
|
+
|
|
291
|
+
Args:
|
|
292
|
+
key: The name of the key
|
|
293
|
+
|
|
294
|
+
Returns:
|
|
295
|
+
Stream information or error message
|
|
296
|
+
"""
|
|
297
|
+
try:
|
|
298
|
+
r = ValkeyConnectionManager.get_connection()
|
|
299
|
+
result = r.xinfo_stream(key)
|
|
300
|
+
return str(result)
|
|
301
|
+
except ValkeyError as e:
|
|
302
|
+
return f"Error getting stream info for '{key}': {str(e)}"
|
|
303
|
+
|
|
304
|
+
|
|
305
|
+
@mcp.tool()
|
|
306
|
+
async def stream_info_groups(key: str) -> str:
|
|
307
|
+
"""Get information about consumer groups.
|
|
308
|
+
|
|
309
|
+
Args:
|
|
310
|
+
key: The name of the key
|
|
311
|
+
|
|
312
|
+
Returns:
|
|
313
|
+
Consumer groups information or error message
|
|
314
|
+
"""
|
|
315
|
+
try:
|
|
316
|
+
r = ValkeyConnectionManager.get_connection()
|
|
317
|
+
result = r.xinfo_groups(key)
|
|
318
|
+
if not result:
|
|
319
|
+
return f"No consumer groups found for stream '{key}'"
|
|
320
|
+
return str(result)
|
|
321
|
+
except ValkeyError as e:
|
|
322
|
+
return f"Error getting consumer groups info for '{key}': {str(e)}"
|
|
323
|
+
|
|
324
|
+
|
|
325
|
+
@mcp.tool()
|
|
326
|
+
async def stream_info_consumers(key: str, group_name: str) -> str:
|
|
327
|
+
"""Get information about consumers in group.
|
|
328
|
+
|
|
329
|
+
Args:
|
|
330
|
+
key: The name of the key
|
|
331
|
+
group_name: Name of consumer group
|
|
332
|
+
|
|
333
|
+
Returns:
|
|
334
|
+
Consumers information or error message
|
|
335
|
+
"""
|
|
336
|
+
try:
|
|
337
|
+
r = ValkeyConnectionManager.get_connection()
|
|
338
|
+
result = r.xinfo_consumers(key, group_name)
|
|
339
|
+
if not result:
|
|
340
|
+
return f"No consumers found in group '{group_name}'"
|
|
341
|
+
return str(result)
|
|
342
|
+
except ValkeyError as e:
|
|
343
|
+
return f'Error getting consumers info: {str(e)}'
|
|
@@ -0,0 +1,228 @@
|
|
|
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
|
+
"""String 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 valkey.exceptions import ValkeyError
|
|
18
|
+
|
|
19
|
+
|
|
20
|
+
@mcp.tool()
|
|
21
|
+
async def string_set(
|
|
22
|
+
key: str,
|
|
23
|
+
value: Any,
|
|
24
|
+
ex: Optional[int] = None,
|
|
25
|
+
px: Optional[int] = None,
|
|
26
|
+
nx: bool = False,
|
|
27
|
+
xx: bool = False,
|
|
28
|
+
keepttl: bool = False,
|
|
29
|
+
) -> str:
|
|
30
|
+
"""Set string value.
|
|
31
|
+
|
|
32
|
+
Args:
|
|
33
|
+
key: The name of the key
|
|
34
|
+
value: The value to set
|
|
35
|
+
ex: Expire time in seconds
|
|
36
|
+
px: Expire time in milliseconds
|
|
37
|
+
nx: Only set if key does not exist
|
|
38
|
+
xx: Only set if key exists
|
|
39
|
+
keepttl: Retain the time to live associated with the key
|
|
40
|
+
|
|
41
|
+
Returns:
|
|
42
|
+
Success message or error message
|
|
43
|
+
"""
|
|
44
|
+
try:
|
|
45
|
+
r = ValkeyConnectionManager.get_connection()
|
|
46
|
+
result = r.set(key, value, ex=ex, px=px, nx=nx, xx=xx, keepttl=keepttl)
|
|
47
|
+
if result is None:
|
|
48
|
+
return f"Failed to set value for key '{key}' (condition not met)"
|
|
49
|
+
return f"Successfully set value for key '{key}'"
|
|
50
|
+
except ValkeyError as e:
|
|
51
|
+
return f"Error setting string value for '{key}': {str(e)}"
|
|
52
|
+
|
|
53
|
+
|
|
54
|
+
@mcp.tool()
|
|
55
|
+
async def string_get(key: str) -> str:
|
|
56
|
+
"""Get string value.
|
|
57
|
+
|
|
58
|
+
Args:
|
|
59
|
+
key: The name of the key
|
|
60
|
+
|
|
61
|
+
Returns:
|
|
62
|
+
Value or error message
|
|
63
|
+
"""
|
|
64
|
+
try:
|
|
65
|
+
r = ValkeyConnectionManager.get_connection()
|
|
66
|
+
result = r.get(key)
|
|
67
|
+
if result is None:
|
|
68
|
+
return f"Key '{key}' not found"
|
|
69
|
+
return str(result)
|
|
70
|
+
except ValkeyError as e:
|
|
71
|
+
return f"Error getting string value from '{key}': {str(e)}"
|
|
72
|
+
|
|
73
|
+
|
|
74
|
+
@mcp.tool()
|
|
75
|
+
async def string_append(key: str, value: str) -> str:
|
|
76
|
+
"""Append to string value.
|
|
77
|
+
|
|
78
|
+
Args:
|
|
79
|
+
key: The name of the key
|
|
80
|
+
value: String to append
|
|
81
|
+
|
|
82
|
+
Returns:
|
|
83
|
+
Success message or error message
|
|
84
|
+
"""
|
|
85
|
+
try:
|
|
86
|
+
r = ValkeyConnectionManager.get_connection()
|
|
87
|
+
result = r.append(key, value)
|
|
88
|
+
return f"Successfully appended to key '{key}', new length: {result}"
|
|
89
|
+
except ValkeyError as e:
|
|
90
|
+
return f"Error appending to string '{key}': {str(e)}"
|
|
91
|
+
|
|
92
|
+
|
|
93
|
+
@mcp.tool()
|
|
94
|
+
async def string_get_range(key: str, start: int, end: int) -> str:
|
|
95
|
+
"""Get substring.
|
|
96
|
+
|
|
97
|
+
Args:
|
|
98
|
+
key: The name of the key
|
|
99
|
+
start: Start index (inclusive)
|
|
100
|
+
end: End index (inclusive)
|
|
101
|
+
|
|
102
|
+
Returns:
|
|
103
|
+
Substring or error message
|
|
104
|
+
"""
|
|
105
|
+
try:
|
|
106
|
+
r = ValkeyConnectionManager.get_connection()
|
|
107
|
+
result = r.getrange(key, start, end)
|
|
108
|
+
if not result:
|
|
109
|
+
return f"No characters found in range [{start}, {end}] for key '{key}'"
|
|
110
|
+
return str(result)
|
|
111
|
+
except ValkeyError as e:
|
|
112
|
+
return f"Error getting range from string '{key}': {str(e)}"
|
|
113
|
+
|
|
114
|
+
|
|
115
|
+
@mcp.tool()
|
|
116
|
+
async def string_get_set(key: str, value: Any) -> str:
|
|
117
|
+
"""Set new value and return old value.
|
|
118
|
+
|
|
119
|
+
Args:
|
|
120
|
+
key: The name of the key
|
|
121
|
+
value: New value to set
|
|
122
|
+
|
|
123
|
+
Returns:
|
|
124
|
+
Old value or error message
|
|
125
|
+
"""
|
|
126
|
+
try:
|
|
127
|
+
r = ValkeyConnectionManager.get_connection()
|
|
128
|
+
result = r.getset(key, value)
|
|
129
|
+
if result is None:
|
|
130
|
+
return f"No previous value found for key '{key}'"
|
|
131
|
+
return str(result)
|
|
132
|
+
except ValkeyError as e:
|
|
133
|
+
return f"Error getting and setting string '{key}': {str(e)}"
|
|
134
|
+
|
|
135
|
+
|
|
136
|
+
@mcp.tool()
|
|
137
|
+
async def string_increment(key: str, amount: int = 1) -> str:
|
|
138
|
+
"""Increment integer value.
|
|
139
|
+
|
|
140
|
+
Args:
|
|
141
|
+
key: The name of the key
|
|
142
|
+
amount: Amount to increment by (default 1)
|
|
143
|
+
|
|
144
|
+
Returns:
|
|
145
|
+
New value or error message
|
|
146
|
+
"""
|
|
147
|
+
try:
|
|
148
|
+
r = ValkeyConnectionManager.get_connection()
|
|
149
|
+
result = r.incrby(key, amount)
|
|
150
|
+
return str(result)
|
|
151
|
+
except ValkeyError as e:
|
|
152
|
+
return f"Error incrementing string '{key}': {str(e)}"
|
|
153
|
+
|
|
154
|
+
|
|
155
|
+
@mcp.tool()
|
|
156
|
+
async def string_increment_float(key: str, amount: float) -> str:
|
|
157
|
+
"""Increment float value.
|
|
158
|
+
|
|
159
|
+
Args:
|
|
160
|
+
key: The name of the key
|
|
161
|
+
amount: Amount to increment by
|
|
162
|
+
|
|
163
|
+
Returns:
|
|
164
|
+
New value or error message
|
|
165
|
+
"""
|
|
166
|
+
try:
|
|
167
|
+
r = ValkeyConnectionManager.get_connection()
|
|
168
|
+
result = r.incrbyfloat(key, amount)
|
|
169
|
+
return str(result)
|
|
170
|
+
except ValkeyError as e:
|
|
171
|
+
return f"Error incrementing float string '{key}': {str(e)}"
|
|
172
|
+
|
|
173
|
+
|
|
174
|
+
@mcp.tool()
|
|
175
|
+
async def string_decrement(key: str, amount: int = 1) -> str:
|
|
176
|
+
"""Decrement integer value.
|
|
177
|
+
|
|
178
|
+
Args:
|
|
179
|
+
key: The name of the key
|
|
180
|
+
amount: Amount to decrement by (default 1)
|
|
181
|
+
|
|
182
|
+
Returns:
|
|
183
|
+
New value or error message
|
|
184
|
+
"""
|
|
185
|
+
try:
|
|
186
|
+
r = ValkeyConnectionManager.get_connection()
|
|
187
|
+
result = r.decrby(key, amount)
|
|
188
|
+
return str(result)
|
|
189
|
+
except ValkeyError as e:
|
|
190
|
+
return f"Error decrementing string '{key}': {str(e)}"
|
|
191
|
+
|
|
192
|
+
|
|
193
|
+
@mcp.tool()
|
|
194
|
+
async def string_length(key: str) -> str:
|
|
195
|
+
"""Get string length.
|
|
196
|
+
|
|
197
|
+
Args:
|
|
198
|
+
key: The name of the key
|
|
199
|
+
|
|
200
|
+
Returns:
|
|
201
|
+
Length or error message
|
|
202
|
+
"""
|
|
203
|
+
try:
|
|
204
|
+
r = ValkeyConnectionManager.get_connection()
|
|
205
|
+
result = r.strlen(key)
|
|
206
|
+
return str(result)
|
|
207
|
+
except ValkeyError as e:
|
|
208
|
+
return f"Error getting string length for '{key}': {str(e)}"
|
|
209
|
+
|
|
210
|
+
|
|
211
|
+
@mcp.tool()
|
|
212
|
+
async def string_set_range(key: str, offset: int, value: str) -> str:
|
|
213
|
+
"""Overwrite part of string.
|
|
214
|
+
|
|
215
|
+
Args:
|
|
216
|
+
key: The name of the key
|
|
217
|
+
offset: Position to start overwriting
|
|
218
|
+
value: String to write
|
|
219
|
+
|
|
220
|
+
Returns:
|
|
221
|
+
Success message or error message
|
|
222
|
+
"""
|
|
223
|
+
try:
|
|
224
|
+
r = ValkeyConnectionManager.get_connection()
|
|
225
|
+
result = r.setrange(key, offset, value)
|
|
226
|
+
return f"Successfully set range in string '{key}', new length: {result}"
|
|
227
|
+
except ValkeyError as e:
|
|
228
|
+
return f"Error setting range in string '{key}': {str(e)}"
|
|
@@ -0,0 +1,12 @@
|
|
|
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
|
+
__version__ = '0.1.0'
|