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,283 @@
|
|
|
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
|
+
"""Hash 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, Union
|
|
17
|
+
from valkey.exceptions import ValkeyError
|
|
18
|
+
|
|
19
|
+
|
|
20
|
+
@mcp.tool()
|
|
21
|
+
async def hash_set(key: str, field: str, value: Any) -> str:
|
|
22
|
+
"""Set field in hash.
|
|
23
|
+
|
|
24
|
+
Args:
|
|
25
|
+
key: The name of the key
|
|
26
|
+
field: The field name
|
|
27
|
+
value: The value to set
|
|
28
|
+
|
|
29
|
+
Returns:
|
|
30
|
+
Success message or error message
|
|
31
|
+
"""
|
|
32
|
+
try:
|
|
33
|
+
r = ValkeyConnectionManager.get_connection()
|
|
34
|
+
r.hset(key, field, value)
|
|
35
|
+
return f"Successfully set field '{field}' in hash '{key}'"
|
|
36
|
+
except ValkeyError as e:
|
|
37
|
+
return f"Error setting hash field in '{key}': {str(e)}"
|
|
38
|
+
|
|
39
|
+
|
|
40
|
+
@mcp.tool()
|
|
41
|
+
async def hash_set_multiple(key: str, mapping: Dict[str, Any]) -> str:
|
|
42
|
+
"""Set multiple fields in hash.
|
|
43
|
+
|
|
44
|
+
Args:
|
|
45
|
+
key: The name of the key
|
|
46
|
+
mapping: Dictionary of field-value pairs
|
|
47
|
+
|
|
48
|
+
Returns:
|
|
49
|
+
Success message or error message
|
|
50
|
+
"""
|
|
51
|
+
try:
|
|
52
|
+
r = ValkeyConnectionManager.get_connection()
|
|
53
|
+
result = r.hset(key, mapping=mapping)
|
|
54
|
+
return f"Successfully set {result} fields in hash '{key}'"
|
|
55
|
+
except ValkeyError as e:
|
|
56
|
+
return f"Error setting multiple hash fields in '{key}': {str(e)}"
|
|
57
|
+
|
|
58
|
+
|
|
59
|
+
@mcp.tool()
|
|
60
|
+
async def hash_set_if_not_exists(key: str, field: str, value: Any) -> str:
|
|
61
|
+
"""Set field in hash only if it does not exist.
|
|
62
|
+
|
|
63
|
+
Args:
|
|
64
|
+
key: The name of the key
|
|
65
|
+
field: The field name
|
|
66
|
+
value: The value to set
|
|
67
|
+
|
|
68
|
+
Returns:
|
|
69
|
+
Success message or error message
|
|
70
|
+
"""
|
|
71
|
+
try:
|
|
72
|
+
r = ValkeyConnectionManager.get_connection()
|
|
73
|
+
result = r.hsetnx(key, field, value)
|
|
74
|
+
if result:
|
|
75
|
+
return f"Successfully set field '{field}' in hash '{key}'"
|
|
76
|
+
return f"Field '{field}' already exists in hash '{key}'"
|
|
77
|
+
except ValkeyError as e:
|
|
78
|
+
return f"Error setting hash field in '{key}': {str(e)}"
|
|
79
|
+
|
|
80
|
+
|
|
81
|
+
@mcp.tool()
|
|
82
|
+
async def hash_get(key: str, field: str) -> str:
|
|
83
|
+
"""Get field from hash.
|
|
84
|
+
|
|
85
|
+
Args:
|
|
86
|
+
key: The name of the key
|
|
87
|
+
field: The field name
|
|
88
|
+
|
|
89
|
+
Returns:
|
|
90
|
+
Field value or error message
|
|
91
|
+
"""
|
|
92
|
+
try:
|
|
93
|
+
r = ValkeyConnectionManager.get_connection()
|
|
94
|
+
result = r.hget(key, field)
|
|
95
|
+
if result is None:
|
|
96
|
+
return f"Field '{field}' not found in hash '{key}'"
|
|
97
|
+
return str(result)
|
|
98
|
+
except ValkeyError as e:
|
|
99
|
+
return f"Error getting hash field from '{key}': {str(e)}"
|
|
100
|
+
|
|
101
|
+
|
|
102
|
+
@mcp.tool()
|
|
103
|
+
async def hash_get_all(key: str) -> str:
|
|
104
|
+
"""Get all fields and values from hash.
|
|
105
|
+
|
|
106
|
+
Args:
|
|
107
|
+
key: The name of the key
|
|
108
|
+
|
|
109
|
+
Returns:
|
|
110
|
+
Dictionary of field-value pairs or error message
|
|
111
|
+
"""
|
|
112
|
+
try:
|
|
113
|
+
r = ValkeyConnectionManager.get_connection()
|
|
114
|
+
result = r.hgetall(key)
|
|
115
|
+
if not result:
|
|
116
|
+
return f"No fields found in hash '{key}'"
|
|
117
|
+
return str(result)
|
|
118
|
+
except ValkeyError as e:
|
|
119
|
+
return f"Error getting all hash fields from '{key}': {str(e)}"
|
|
120
|
+
|
|
121
|
+
|
|
122
|
+
@mcp.tool()
|
|
123
|
+
async def hash_exists(key: str, field: str) -> str:
|
|
124
|
+
"""Check if field exists in hash.
|
|
125
|
+
|
|
126
|
+
Args:
|
|
127
|
+
key: The name of the key
|
|
128
|
+
field: The field name
|
|
129
|
+
|
|
130
|
+
Returns:
|
|
131
|
+
Boolean result or error message
|
|
132
|
+
"""
|
|
133
|
+
try:
|
|
134
|
+
r = ValkeyConnectionManager.get_connection()
|
|
135
|
+
result = r.hexists(key, field)
|
|
136
|
+
return str(result).lower()
|
|
137
|
+
except ValkeyError as e:
|
|
138
|
+
return f"Error checking hash field existence in '{key}': {str(e)}"
|
|
139
|
+
|
|
140
|
+
|
|
141
|
+
@mcp.tool()
|
|
142
|
+
async def hash_increment(key: str, field: str, amount: Union[int, float] = 1) -> str:
|
|
143
|
+
"""Increment field value in hash.
|
|
144
|
+
|
|
145
|
+
Args:
|
|
146
|
+
key: The name of the key
|
|
147
|
+
field: The field name
|
|
148
|
+
amount: Amount to increment by (default: 1)
|
|
149
|
+
|
|
150
|
+
Returns:
|
|
151
|
+
New value or error message
|
|
152
|
+
"""
|
|
153
|
+
try:
|
|
154
|
+
r = ValkeyConnectionManager.get_connection()
|
|
155
|
+
if isinstance(amount, int):
|
|
156
|
+
result = r.hincrby(key, field, amount)
|
|
157
|
+
else:
|
|
158
|
+
result = r.hincrbyfloat(key, field, amount)
|
|
159
|
+
return str(result)
|
|
160
|
+
except ValkeyError as e:
|
|
161
|
+
return f"Error incrementing hash field in '{key}': {str(e)}"
|
|
162
|
+
|
|
163
|
+
|
|
164
|
+
@mcp.tool()
|
|
165
|
+
async def hash_keys(key: str) -> str:
|
|
166
|
+
"""Get all field names from hash.
|
|
167
|
+
|
|
168
|
+
Args:
|
|
169
|
+
key: The name of the key
|
|
170
|
+
|
|
171
|
+
Returns:
|
|
172
|
+
List of field names or error message
|
|
173
|
+
"""
|
|
174
|
+
try:
|
|
175
|
+
r = ValkeyConnectionManager.get_connection()
|
|
176
|
+
result = r.hkeys(key)
|
|
177
|
+
if not result:
|
|
178
|
+
return f"No fields found in hash '{key}'"
|
|
179
|
+
return str(result)
|
|
180
|
+
except ValkeyError as e:
|
|
181
|
+
return f"Error getting hash field names from '{key}': {str(e)}"
|
|
182
|
+
|
|
183
|
+
|
|
184
|
+
@mcp.tool()
|
|
185
|
+
async def hash_length(key: str) -> str:
|
|
186
|
+
"""Get number of fields in hash.
|
|
187
|
+
|
|
188
|
+
Args:
|
|
189
|
+
key: The name of the key
|
|
190
|
+
|
|
191
|
+
Returns:
|
|
192
|
+
Number of fields or error message
|
|
193
|
+
"""
|
|
194
|
+
try:
|
|
195
|
+
r = ValkeyConnectionManager.get_connection()
|
|
196
|
+
result = r.hlen(key)
|
|
197
|
+
return str(result)
|
|
198
|
+
except ValkeyError as e:
|
|
199
|
+
return f"Error getting hash length from '{key}': {str(e)}"
|
|
200
|
+
|
|
201
|
+
|
|
202
|
+
@mcp.tool()
|
|
203
|
+
async def hash_random_field(key: str, count: Optional[int] = None) -> str:
|
|
204
|
+
"""Get random field(s) from hash.
|
|
205
|
+
|
|
206
|
+
Args:
|
|
207
|
+
key: The name of the key
|
|
208
|
+
count: Number of fields to return (optional)
|
|
209
|
+
|
|
210
|
+
Returns:
|
|
211
|
+
Random field(s) or error message
|
|
212
|
+
"""
|
|
213
|
+
try:
|
|
214
|
+
r = ValkeyConnectionManager.get_connection()
|
|
215
|
+
if count:
|
|
216
|
+
result = r.hrandfield(key, count)
|
|
217
|
+
else:
|
|
218
|
+
result = r.hrandfield(key)
|
|
219
|
+
if not result:
|
|
220
|
+
return f"No fields found in hash '{key}'"
|
|
221
|
+
return str(result)
|
|
222
|
+
except ValkeyError as e:
|
|
223
|
+
return f"Error getting random hash field from '{key}': {str(e)}"
|
|
224
|
+
|
|
225
|
+
|
|
226
|
+
@mcp.tool()
|
|
227
|
+
async def hash_random_field_with_values(key: str, count: int) -> str:
|
|
228
|
+
"""Get random field(s) with their values from hash.
|
|
229
|
+
|
|
230
|
+
Args:
|
|
231
|
+
key: The name of the key
|
|
232
|
+
count: Number of field-value pairs to return
|
|
233
|
+
|
|
234
|
+
Returns:
|
|
235
|
+
Random field-value pairs or error message
|
|
236
|
+
"""
|
|
237
|
+
try:
|
|
238
|
+
r = ValkeyConnectionManager.get_connection()
|
|
239
|
+
result = r.hrandfield(key, count, withvalues=True)
|
|
240
|
+
if not result:
|
|
241
|
+
return f"No fields found in hash '{key}'"
|
|
242
|
+
return str(result)
|
|
243
|
+
except ValkeyError as e:
|
|
244
|
+
return f"Error getting random hash field-value pairs from '{key}': {str(e)}"
|
|
245
|
+
|
|
246
|
+
|
|
247
|
+
@mcp.tool()
|
|
248
|
+
async def hash_strlen(key: str, field: str) -> str:
|
|
249
|
+
"""Get length of field value in hash.
|
|
250
|
+
|
|
251
|
+
Args:
|
|
252
|
+
key: The name of the key
|
|
253
|
+
field: The field name
|
|
254
|
+
|
|
255
|
+
Returns:
|
|
256
|
+
Length of field value or error message
|
|
257
|
+
"""
|
|
258
|
+
try:
|
|
259
|
+
r = ValkeyConnectionManager.get_connection()
|
|
260
|
+
result = r.hstrlen(key, field)
|
|
261
|
+
return str(result)
|
|
262
|
+
except ValkeyError as e:
|
|
263
|
+
return f"Error getting hash field value length from '{key}': {str(e)}"
|
|
264
|
+
|
|
265
|
+
|
|
266
|
+
@mcp.tool()
|
|
267
|
+
async def hash_values(key: str) -> str:
|
|
268
|
+
"""Get all values from hash.
|
|
269
|
+
|
|
270
|
+
Args:
|
|
271
|
+
key: The name of the key
|
|
272
|
+
|
|
273
|
+
Returns:
|
|
274
|
+
List of values or error message
|
|
275
|
+
"""
|
|
276
|
+
try:
|
|
277
|
+
r = ValkeyConnectionManager.get_connection()
|
|
278
|
+
result = r.hvals(key)
|
|
279
|
+
if not result:
|
|
280
|
+
return f"No values found in hash '{key}'"
|
|
281
|
+
return str(result)
|
|
282
|
+
except ValkeyError as e:
|
|
283
|
+
return f"Error getting hash values from '{key}': {str(e)}"
|
|
@@ -0,0 +1,58 @@
|
|
|
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
|
+
"""HyperLogLog 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 valkey.exceptions import ValkeyError
|
|
17
|
+
|
|
18
|
+
|
|
19
|
+
@mcp.tool()
|
|
20
|
+
async def hll_add(key: str, element: str) -> str:
|
|
21
|
+
"""Add one element to a HyperLogLog.
|
|
22
|
+
|
|
23
|
+
Args:
|
|
24
|
+
key: The name of the HyperLogLog key
|
|
25
|
+
element: One element to add
|
|
26
|
+
|
|
27
|
+
Returns:
|
|
28
|
+
Success message or error message
|
|
29
|
+
"""
|
|
30
|
+
try:
|
|
31
|
+
if not element:
|
|
32
|
+
return 'Error: an element is required'
|
|
33
|
+
|
|
34
|
+
r = ValkeyConnectionManager.get_connection()
|
|
35
|
+
result = r.pfadd(key, element)
|
|
36
|
+
if result:
|
|
37
|
+
return f"Added 1 element to '{key}'"
|
|
38
|
+
return f"No new element added to '{key}' (already existed)"
|
|
39
|
+
except ValkeyError as e:
|
|
40
|
+
return f"Error adding element to '{key}': {str(e)}"
|
|
41
|
+
|
|
42
|
+
|
|
43
|
+
@mcp.tool()
|
|
44
|
+
async def hll_count(key: str) -> str:
|
|
45
|
+
"""Get the estimated cardinality of a HyperLogLog.
|
|
46
|
+
|
|
47
|
+
Args:
|
|
48
|
+
key: The name of the HyperLogLog key
|
|
49
|
+
|
|
50
|
+
Returns:
|
|
51
|
+
Estimated cardinality or error message
|
|
52
|
+
"""
|
|
53
|
+
try:
|
|
54
|
+
r = ValkeyConnectionManager.get_connection()
|
|
55
|
+
count = r.pfcount(key)
|
|
56
|
+
return f"Estimated unique elements in '{key}': {count}"
|
|
57
|
+
except ValkeyError as e:
|
|
58
|
+
return f"Error getting count from '{key}': {str(e)}"
|