Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
27 changes: 26 additions & 1 deletion src/redis/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,31 @@

A Model Context Protocol server that provides access to Redis databases. This server enables LLMs to interact with Redis key-value stores through a set of standardized tools.

## Prerequisites

1. Redis server must be installed and running
- [Download Redis](https://redis.io/download)
- For Windows users: Use [Windows Subsystem for Linux (WSL)](https://redis.io/docs/getting-started/installation/install-redis-on-windows/) or [Memurai](https://www.memurai.com/) (Redis-compatible Windows server)
- Default port: 6379

## Common Issues & Solutions

### Connection Errors

**ECONNREFUSED**
- **Cause**: Redis server is not running or unreachable
- **Solution**:
- Verify Redis is running: `redis-cli ping` should return "PONG"
- Check Redis service status: `systemctl status redis` (Linux) or `brew services list` (macOS)
- Ensure correct port (default 6379) is not blocked by firewall
- Verify Redis URL format: `redis://hostname:port`

### Server Behavior

- The server implements exponential backoff with a maximum of 5 retries
- Initial retry delay: 1 second, maximum delay: 30 seconds
- Server will exit after max retries to prevent infinite reconnection loops

## Components

### Tools
Expand Down Expand Up @@ -77,4 +102,4 @@ docker build -t mcp/redis -f src/redis/Dockerfile .

## License

This MCP server is licensed under the MIT License. This means you are free to use, modify, and distribute the software, subject to the terms and conditions of the MIT License. For more details, please see the LICENSE file in the project repository.
This MCP server is licensed under the MIT License. This means you are free to use, modify, and distribute the software, subject to the terms and conditions of the MIT License. For more details, please see the LICENSE file in the project repository.
66 changes: 58 additions & 8 deletions src/redis/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,10 +7,26 @@ import {
import { z } from "zod";
import { createClient } from 'redis';

// Get Redis URL from command line args or use default
// Configuration
const REDIS_URL = process.argv[2] || "redis://localhost:6379";
const MAX_RETRIES = 5;
const MIN_RETRY_DELAY = 1000; // 1 second
const MAX_RETRY_DELAY = 30000; // 30 seconds

// Create Redis client with retry strategy
const redisClient = createClient({
url: REDIS_URL
url: REDIS_URL,
socket: {
reconnectStrategy: (retries) => {
if (retries >= MAX_RETRIES) {
console.error(`Maximum retries (${MAX_RETRIES}) reached. Giving up.`);
return new Error('Max retries reached');
}
const delay = Math.min(Math.pow(2, retries) * MIN_RETRY_DELAY, MAX_RETRY_DELAY);
console.error(`Reconnection attempt ${retries + 1}/${MAX_RETRIES} in ${delay}ms`);
return delay;
}
}
});

// Define Zod schemas for validation
Expand All @@ -36,7 +52,12 @@ const ListArgumentsSchema = z.object({
const server = new Server(
{
name: "redis",
version: "1.0.0"
version: "0.0.1"
},
{
capabilities: {
tools: {}
}
}
);

Expand Down Expand Up @@ -215,22 +236,51 @@ server.setRequestHandler(CallToolRequestSchema, async (request) => {
// Start the server
async function main() {
try {
// Set up Redis event handlers
redisClient.on('error', (err: Error) => {
console.error('Redis Client Error:', err);
});

redisClient.on('connect', () => {
console.error(`Connected to Redis at ${REDIS_URL}`);
});

redisClient.on('reconnecting', () => {
console.error('Attempting to reconnect to Redis...');
});

redisClient.on('end', () => {
console.error('Redis connection closed');
});

// Connect to Redis
redisClient.on('error', (err: Error) => console.error('Redis Client Error', err));
await redisClient.connect();
console.error(`Connected to Redis successfully at ${REDIS_URL}`);

// Set up MCP server
const transport = new StdioServerTransport();
await server.connect(transport);
console.error("Redis MCP Server running on stdio");
} catch (error) {
console.error("Error during startup:", error);
await cleanup();
}
}

// Cleanup function
async function cleanup() {
try {
await redisClient.quit();
process.exit(1);
} catch (error) {
console.error("Error during cleanup:", error);
}
process.exit(1);
}

// Handle process termination
process.on('SIGINT', cleanup);
process.on('SIGTERM', cleanup);

main().catch((error) => {
console.error("Fatal error in main():", error);
redisClient.quit().finally(() => process.exit(1));
});
cleanup();
});