Skip to content

Commit b25d732

Browse files
committed
new defaults for vector tools, added rename key tool, README docs
1 parent 15fc830 commit b25d732

File tree

5 files changed

+93
-36
lines changed

5 files changed

+93
-36
lines changed

README.md

Lines changed: 25 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,12 @@
11
# Redis MCP Server
22

33
## Overview
4-
The Redis MCP Server is a **natural language interface** designed for agentic applications to efficiently manage and search data in Redis. It integrates seamlessly with **MCP (Model Content Protocol) clients**, enabling AI-driven workflows to interact with structured and unstructured data in Redis.
4+
The Redis MCP Server is a **natural language interface** designed for agentic applications to efficiently manage and search data in Redis. It integrates seamlessly with **MCP (Model Content Protocol) clients**, enabling AI-driven workflows to interact with structured and unstructured data in Redis. Using this MCP Server, you can ask questions like:
5+
6+
- "Store the entire conversation in a stream"
7+
- "Cache this item"
8+
- "Store the session with an expiration time"
9+
- "Index and search this vector"
510

611
## Features
712
- **Natural Language Queries**: Enables AI agents to query and update Redis using natural language.
@@ -10,6 +15,25 @@ The Redis MCP Server is a **natural language interface** designed for agentic ap
1015
- **Search & Filtering**: Supports efficient data retrieval and searching in Redis.
1116
- **Scalable & Lightweight**: Designed for **high-performance** data operations.
1217

18+
## Tools
19+
20+
This MCP Server provides tools to manage the data stored in Redis.
21+
22+
- `string` tools to set, get strings with expiration. Useful for storing simple configuration values, session data, or caching responses.
23+
- `hash` tools to store field-value pairs within a single key. The hash can store vector embeddings. Useful for representing objects with multiple attributes, user profiles, or product information where fields can be accessed individually.
24+
- `list` tools with common operations to append and pop items. Useful for queues, message brokers, or maintaining a list of most recent actions.
25+
- `set` tools to add, remove and list set members. Useful for tracking unique values like user IDs or tags, and for performing set operations like intersection.
26+
- `sorted set` tools to manage data for e.g. leaderboards, priority queues, or time-based analytics with score-based ordering.
27+
- `pub/sub` functionality to publish messages to channels and subscribe to receive them. Useful for real-time notifications, chat applications, or distributing updates to multiple clients.
28+
- `streams` tools to add, read, and delete from data streams. Useful for event sourcing, activity feeds, or sensor data logging with consumer groups support.
29+
- `JSON` tools to store, retrieve, and manipulate JSON documents in Redis. Useful for complex nested data structures, document databases, or configuration management with path-based access.
30+
31+
Additional tools.
32+
33+
- `query engine` tools to manage vector indexes and perform vector search
34+
- `server management` tool to retrieve information about the database
35+
36+
1337
## Installation
1438
```sh
1539
# Clone the repository

src/tools/hash.py

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -100,12 +100,12 @@ async def hexists(name: str, key: str) -> bool:
100100
return f"Error checking existence of field '{key}' in hash '{name}': {str(e)}"
101101

102102
@mcp.tool()
103-
async def set_vector_in_hash(name: str, key: str, vector: list) -> bool:
103+
async def set_vector_in_hash(name: str, vector: list, vector_field: str = "vector") -> bool:
104104
"""Store a vector as a field in a Redis hash.
105105
106106
Args:
107107
name: The Redis hash key.
108-
key: The field name inside the hash.
108+
vector_field: The field name inside the hash. Unless specifically required, use the default field name
109109
vector: The vector (list of numbers) to store in the hash.
110110
111111
Returns:
@@ -118,19 +118,19 @@ async def set_vector_in_hash(name: str, key: str, vector: list) -> bool:
118118
vector_array = np.array(vector, dtype=np.float32)
119119
binary_blob = vector_array.tobytes()
120120

121-
r.hset(name, key, binary_blob)
121+
r.hset(name, vector_field, binary_blob)
122122
return True
123123
except RedisError as e:
124-
return f"Error storing vector in hash '{name}' with key '{key}': {str(e)}"
124+
return f"Error storing vector in hash '{name}' with field '{vector_field}': {str(e)}"
125125

126126

127127
@mcp.tool()
128-
async def get_vector_from_hash(name: str, key: str):
128+
async def get_vector_from_hash(name: str, vector_field: str = "vector"):
129129
"""Retrieve a vector from a Redis hash and convert it back from binary blob.
130130
131131
Args:
132132
name: The Redis hash key.
133-
key: The field name inside the hash.
133+
vector_field: The field name inside the hash. Unless specifically required, use the default field name
134134
135135
Returns:
136136
The vector as a list of floats, or an error message if retrieval fails.
@@ -139,14 +139,14 @@ async def get_vector_from_hash(name: str, key: str):
139139
r = RedisConnectionManager.get_connection(decode_responses=False)
140140

141141
# Retrieve the binary blob stored in the hash
142-
binary_blob = r.hget(name, key)
142+
binary_blob = r.hget(name, vector_field)
143143

144144
if binary_blob:
145145
# Convert the binary blob back to a NumPy array (assuming it's stored as float32)
146146
vector_array = np.frombuffer(binary_blob, dtype=np.float32)
147147
return vector_array.tolist()
148148
else:
149-
return f"Field '{key}' not found in hash '{name}'."
149+
return f"Field '{vector_field}' not found in hash '{name}'."
150150

151151
except RedisError as e:
152152
return f"Error retrieving vector from hash '{name}' with key '{key}': {str(e)}"

src/tools/misc.py

Lines changed: 52 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,4 +17,55 @@ async def get_key_info(key: str) -> Dict[str, Any]:
1717

1818
return info
1919
except RedisError as e:
20-
return {'error': str(e)}
20+
return {'error': str(e)}
21+
22+
23+
@mcp.tool()
24+
async def expire(name: str, expire_seconds: int) -> str:
25+
"""Set an expiration time for a Redis key.
26+
27+
Args:
28+
name: The Redis key.
29+
expire_seconds: Time in seconds after which the key should expire.
30+
31+
Returns:
32+
A success message or an error message.
33+
"""
34+
try:
35+
r = RedisConnectionManager.get_connection()
36+
success = r.expire(name, expire_seconds)
37+
return f"Expiration set to {expire_seconds} seconds for '{name}'." if success else f"Key '{name}' does not exist."
38+
except RedisError as e:
39+
return f"Error setting expiration for key '{name}': {str(e)}"
40+
41+
42+
@mcp.tool()
43+
async def rename_key(old_key: str, new_key: str) -> Dict[str, Any]:
44+
"""
45+
Renames a Redis key from old_key to new_key.
46+
47+
Args:
48+
old_key (str): The current name of the Redis key to rename.
49+
new_key (str): The new name to assign to the key.
50+
51+
Returns:
52+
Dict[str, Any]: A dictionary containing the result of the operation.
53+
On success: {"status": "success", "message": "..."}
54+
On error: {"error": "..."}
55+
"""
56+
try:
57+
r = RedisConnectionManager.get_connection()
58+
59+
# Check if the old key exists
60+
if not r.exists(old_key):
61+
return {"error": f"Key '{old_key}' does not exist."}
62+
63+
# Rename the key
64+
r.rename(old_key, new_key)
65+
return {
66+
"status": "success",
67+
"message": f"Renamed key '{old_key}' to '{new_key}'"
68+
}
69+
70+
except RedisError as e:
71+
return {"error": str(e)}

src/tools/redis_query_engine.py

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -53,7 +53,7 @@ async def get_indexed_keys_number(index_name: str) -> str:
5353

5454

5555
@mcp.tool()
56-
async def create_vector_index_hash(index_name: str,
56+
async def create_vector_index_hash(index_name: str = "vector_index",
5757
prefix: str = "doc:",
5858
vector_field: str = "vector",
5959
dim: int = 1536,
@@ -65,9 +65,9 @@ async def create_vector_index_hash(index_name: str,
6565
search using the HNSW algorithm and float32 vector embeddings.
6666
6767
Args:
68-
index_name: The name of the Redis index to create.
69-
prefix: The key prefix used to identify documents to index (e.g., 'doc:').
70-
vector_field: The name of the vector field to be indexed for similarity search.
68+
index_name: The name of the Redis index to create. Unless specifically required, use the default name for the index.
69+
prefix: The key prefix used to identify documents to index (e.g., 'doc:'). Unless specifically required, use the default prefix.
70+
vector_field: The name of the vector field to be indexed for similarity search. Unless specifically required, use the default field name
7171
dim: The dimensionality of the vectors stored under the vector_field.
7272
distance_metric: The distance function to use (e.g., 'COSINE', 'L2', 'IP').
7373
@@ -97,18 +97,18 @@ async def create_vector_index_hash(index_name: str,
9797

9898

9999
@mcp.tool()
100-
async def vector_search_hash(index_name: str,
101-
query_vector: list,
100+
async def vector_search_hash(query_vector: list,
101+
index_name: str = "vector_index",
102102
vector_field: str = "vector",
103103
k: int = 5,
104104
return_fields: list = None) -> list:
105105
"""
106106
Perform a KNN vector similarity search using Redis 8 or later version on vectors stored in hash data structures.
107107
108108
Args:
109-
index_name: Name of the Redis index.
110-
vector_field: Name of the indexed vector field.
111109
query_vector: List of floats to use as the query vector.
110+
index_name: Name of the Redis index. Unless specifically specified, use the default index name.
111+
vector_field: Name of the indexed vector field. Unless specifically required, use the default field name
112112
k: Number of nearest neighbors to return.
113113
return_fields: List of fields to return (optional).
114114

src/tools/set.py

Lines changed: 0 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -64,21 +64,3 @@ async def smembers(name: str) -> list:
6464
except RedisError as e:
6565
return f"Error retrieving members of set '{name}': {str(e)}"
6666

67-
68-
@mcp.tool()
69-
async def sexpire(name: str, expire_seconds: int) -> str:
70-
"""Set an expiration time for a Redis set.
71-
72-
Args:
73-
name: The Redis set key.
74-
expire_seconds: Time in seconds after which the set should expire.
75-
76-
Returns:
77-
A success message or an error message.
78-
"""
79-
try:
80-
r = RedisConnectionManager.get_connection()
81-
success = r.expire(name, expire_seconds)
82-
return f"Expiration set to {expire_seconds} seconds for set '{name}'." if success else f"Set '{name}' does not exist."
83-
except RedisError as e:
84-
return f"Error setting expiration for set '{name}': {str(e)}"

0 commit comments

Comments
 (0)