Skip to main content
Glama

Unrestricted Development MCP Server

redis.ts•40.2 kB
import { z } from 'zod'; import { Redis } from 'ioredis'; // Type for Redis client instances type RedisClient = Redis; interface ToolResponse { content: Array<{ type: "text"; text: string; }>; isError?: boolean; } // Connection pool management const connectionPool: Map<string, RedisClient> = new Map(); /** * Get or create a Redis client connection */ async function getRedisClient(url: string): Promise<RedisClient> { if (connectionPool.has(url)) { const client = connectionPool.get(url)!; // Verify connection is still alive try { await client.ping(); return client; } catch (error) { // Connection is dead, remove from pool connectionPool.delete(url); } } // Create new connection const client = new Redis(url, { connectTimeout: 5000, maxRetriesPerRequest: 3, lazyConnect: true, }); await client.connect(); connectionPool.set(url, client); return client; } // ==================== Schemas ==================== export const redisConnectSchema = z.object({ url: z.string().describe('Redis connection string (e.g., redis://localhost:6379 or redis://user:pass@host:port/db)'), cwd: z.string().optional().describe('Working directory') }); export const redisGetSchema = z.object({ url: z.string().describe('Redis connection string'), key: z.string().describe('Key to retrieve'), cwd: z.string().optional().describe('Working directory') }); export const redisSetSchema = z.object({ url: z.string().describe('Redis connection string'), key: z.string().describe('Key to set'), value: z.string().describe('Value to store'), ex: z.number().optional().describe('Expiration in seconds (optional)'), cwd: z.string().optional().describe('Working directory') }); export const redisDelSchema = z.object({ url: z.string().describe('Redis connection string'), keys: z.union([z.string(), z.array(z.string())]).describe('Key(s) to delete'), cwd: z.string().optional().describe('Working directory') }); export const redisExistsSchema = z.object({ url: z.string().describe('Redis connection string'), keys: z.union([z.string(), z.array(z.string())]).describe('Key(s) to check'), cwd: z.string().optional().describe('Working directory') }); export const redisKeysSchema = z.object({ url: z.string().describe('Redis connection string'), pattern: z.string().describe('Pattern to match keys (e.g., "user:*", "*session*")'), cwd: z.string().optional().describe('Working directory') }); export const redisTtlSchema = z.object({ url: z.string().describe('Redis connection string'), key: z.string().describe('Key to check TTL'), cwd: z.string().optional().describe('Working directory') }); export const redisExpireSchema = z.object({ url: z.string().describe('Redis connection string'), key: z.string().describe('Key to set expiration'), seconds: z.number().describe('Expiration time in seconds'), cwd: z.string().optional().describe('Working directory') }); export const redisHsetSchema = z.object({ url: z.string().describe('Redis connection string'), key: z.string().describe('Hash key'), field: z.string().describe('Field name'), value: z.string().describe('Field value'), cwd: z.string().optional().describe('Working directory') }); export const redisHgetSchema = z.object({ url: z.string().describe('Redis connection string'), key: z.string().describe('Hash key'), field: z.string().describe('Field name'), cwd: z.string().optional().describe('Working directory') }); export const redisHgetallSchema = z.object({ url: z.string().describe('Redis connection string'), key: z.string().describe('Hash key'), cwd: z.string().optional().describe('Working directory') }); export const redisHdelSchema = z.object({ url: z.string().describe('Redis connection string'), key: z.string().describe('Hash key'), fields: z.union([z.string(), z.array(z.string())]).describe('Field(s) to delete'), cwd: z.string().optional().describe('Working directory') }); export const redisLpushSchema = z.object({ url: z.string().describe('Redis connection string'), key: z.string().describe('List key'), values: z.union([z.string(), z.array(z.string())]).describe('Value(s) to push'), cwd: z.string().optional().describe('Working directory') }); export const redisRpushSchema = z.object({ url: z.string().describe('Redis connection string'), key: z.string().describe('List key'), values: z.union([z.string(), z.array(z.string())]).describe('Value(s) to push'), cwd: z.string().optional().describe('Working directory') }); export const redisLrangeSchema = z.object({ url: z.string().describe('Redis connection string'), key: z.string().describe('List key'), start: z.number().describe('Start index (0-based, use -1 for last element)'), stop: z.number().describe('Stop index (0-based, use -1 for last element)'), cwd: z.string().optional().describe('Working directory') }); export const redisLpopSchema = z.object({ url: z.string().describe('Redis connection string'), key: z.string().describe('List key'), count: z.number().optional().describe('Number of elements to pop (default: 1)'), cwd: z.string().optional().describe('Working directory') }); export const redisSaddSchema = z.object({ url: z.string().describe('Redis connection string'), key: z.string().describe('Set key'), members: z.union([z.string(), z.array(z.string())]).describe('Member(s) to add'), cwd: z.string().optional().describe('Working directory') }); export const redisSmembersSchema = z.object({ url: z.string().describe('Redis connection string'), key: z.string().describe('Set key'), cwd: z.string().optional().describe('Working directory') }); export const redisSremSchema = z.object({ url: z.string().describe('Redis connection string'), key: z.string().describe('Set key'), members: z.union([z.string(), z.array(z.string())]).describe('Member(s) to remove'), cwd: z.string().optional().describe('Working directory') }); export const redisIncrSchema = z.object({ url: z.string().describe('Redis connection string'), key: z.string().describe('Counter key'), cwd: z.string().optional().describe('Working directory') }); export const redisDecrSchema = z.object({ url: z.string().describe('Redis connection string'), key: z.string().describe('Counter key'), cwd: z.string().optional().describe('Working directory') }); export const redisFlushdbSchema = z.object({ url: z.string().describe('Redis connection string'), cwd: z.string().optional().describe('Working directory') }); export const redisInfoSchema = z.object({ url: z.string().describe('Redis connection string'), section: z.string().optional().describe('Info section (server, clients, memory, stats, replication, etc.)'), cwd: z.string().optional().describe('Working directory') }); export const redisDbsizeSchema = z.object({ url: z.string().describe('Redis connection string'), cwd: z.string().optional().describe('Working directory') }); // ==================== Tool Implementations ==================== export async function redisConnect(args: z.infer<typeof redisConnectSchema>): Promise<ToolResponse> { try { const client = await getRedisClient(args.url); // Test connection const pong = await client.ping(); // Get server info const info = await client.info('server'); const versionMatch = info.match(/redis_version:([^\r\n]+)/); const version = versionMatch ? versionMatch[1] : 'unknown'; // Get database size const dbsize = await client.dbsize(); return { content: [{ type: "text" as const, text: JSON.stringify({ success: true, connected: pong === 'PONG', server: { version, ping: pong }, dbsize, message: 'Connected to Redis server' }, null, 2) }] }; } catch (error: any) { return { content: [{ type: "text" as const, text: JSON.stringify({ success: false, connected: false, error: error.message, hint: error.message.includes('ECONNREFUSED') ? 'Redis server is not running or not accessible' : error.message.includes('Authentication') ? 'Invalid password - check credentials' : 'Check connection string format and network connectivity' }, null, 2) }], isError: true }; } } export async function redisGet(args: z.infer<typeof redisGetSchema>): Promise<ToolResponse> { try { const client = await getRedisClient(args.url); const value = await client.get(args.key); return { content: [{ type: "text" as const, text: JSON.stringify({ success: true, key: args.key, value, found: value !== null, message: value !== null ? 'Key retrieved successfully' : 'Key does not exist' }, null, 2) }] }; } catch (error: any) { return { content: [{ type: "text" as const, text: JSON.stringify({ success: false, error: error.message, key: args.key }, null, 2) }], isError: true }; } } export async function redisSet(args: z.infer<typeof redisSetSchema>): Promise<ToolResponse> { try { const client = await getRedisClient(args.url); let result: string | null; if (args.ex) { result = await client.set(args.key, args.value, 'EX', args.ex); } else { result = await client.set(args.key, args.value); } return { content: [{ type: "text" as const, text: JSON.stringify({ success: true, key: args.key, value: args.value, expiration: args.ex ? `${args.ex} seconds` : 'none', result, message: 'Key set successfully' }, null, 2) }] }; } catch (error: any) { return { content: [{ type: "text" as const, text: JSON.stringify({ success: false, error: error.message, key: args.key }, null, 2) }], isError: true }; } } export async function redisDel(args: z.infer<typeof redisDelSchema>): Promise<ToolResponse> { try { const client = await getRedisClient(args.url); const keys = Array.isArray(args.keys) ? args.keys : [args.keys]; const count = await client.del(...keys); return { content: [{ type: "text" as const, text: JSON.stringify({ success: true, keys, deletedCount: count, message: `${count} key(s) deleted` }, null, 2) }] }; } catch (error: any) { return { content: [{ type: "text" as const, text: JSON.stringify({ success: false, error: error.message, keys: args.keys }, null, 2) }], isError: true }; } } export async function redisExists(args: z.infer<typeof redisExistsSchema>): Promise<ToolResponse> { try { const client = await getRedisClient(args.url); const keys = Array.isArray(args.keys) ? args.keys : [args.keys]; const count = await client.exists(...keys); return { content: [{ type: "text" as const, text: JSON.stringify({ success: true, keys, existsCount: count, allExist: count === keys.length, message: `${count} of ${keys.length} key(s) exist` }, null, 2) }] }; } catch (error: any) { return { content: [{ type: "text" as const, text: JSON.stringify({ success: false, error: error.message, keys: args.keys }, null, 2) }], isError: true }; } } export async function redisKeys(args: z.infer<typeof redisKeysSchema>): Promise<ToolResponse> { try { const client = await getRedisClient(args.url); const keys = await client.keys(args.pattern); return { content: [{ type: "text" as const, text: JSON.stringify({ success: true, pattern: args.pattern, count: keys.length, keys, message: `Found ${keys.length} key(s) matching pattern` }, null, 2) }] }; } catch (error: any) { return { content: [{ type: "text" as const, text: JSON.stringify({ success: false, error: error.message, pattern: args.pattern, hint: 'Use patterns like "user:*" or "*session*" to match keys' }, null, 2) }], isError: true }; } } export async function redisTtl(args: z.infer<typeof redisTtlSchema>): Promise<ToolResponse> { try { const client = await getRedisClient(args.url); const ttl = await client.ttl(args.key); let message: string; if (ttl === -2) { message = 'Key does not exist'; } else if (ttl === -1) { message = 'Key exists but has no expiration'; } else { message = `Key expires in ${ttl} seconds`; } return { content: [{ type: "text" as const, text: JSON.stringify({ success: true, key: args.key, ttl, exists: ttl !== -2, hasExpiration: ttl > 0, message }, null, 2) }] }; } catch (error: any) { return { content: [{ type: "text" as const, text: JSON.stringify({ success: false, error: error.message, key: args.key }, null, 2) }], isError: true }; } } export async function redisExpire(args: z.infer<typeof redisExpireSchema>): Promise<ToolResponse> { try { const client = await getRedisClient(args.url); const result = await client.expire(args.key, args.seconds); return { content: [{ type: "text" as const, text: JSON.stringify({ success: true, key: args.key, seconds: args.seconds, applied: result === 1, message: result === 1 ? `Expiration set to ${args.seconds} seconds` : 'Key does not exist' }, null, 2) }] }; } catch (error: any) { return { content: [{ type: "text" as const, text: JSON.stringify({ success: false, error: error.message, key: args.key }, null, 2) }], isError: true }; } } export async function redisHset(args: z.infer<typeof redisHsetSchema>): Promise<ToolResponse> { try { const client = await getRedisClient(args.url); const result = await client.hset(args.key, args.field, args.value); return { content: [{ type: "text" as const, text: JSON.stringify({ success: true, key: args.key, field: args.field, value: args.value, created: result === 1, message: result === 1 ? 'Field created' : 'Field updated' }, null, 2) }] }; } catch (error: any) { return { content: [{ type: "text" as const, text: JSON.stringify({ success: false, error: error.message, key: args.key }, null, 2) }], isError: true }; } } export async function redisHget(args: z.infer<typeof redisHgetSchema>): Promise<ToolResponse> { try { const client = await getRedisClient(args.url); const value = await client.hget(args.key, args.field); return { content: [{ type: "text" as const, text: JSON.stringify({ success: true, key: args.key, field: args.field, value, found: value !== null, message: value !== null ? 'Field retrieved successfully' : 'Field does not exist' }, null, 2) }] }; } catch (error: any) { return { content: [{ type: "text" as const, text: JSON.stringify({ success: false, error: error.message, key: args.key }, null, 2) }], isError: true }; } } export async function redisHgetall(args: z.infer<typeof redisHgetallSchema>): Promise<ToolResponse> { try { const client = await getRedisClient(args.url); const hash = await client.hgetall(args.key); const fields = Object.keys(hash); return { content: [{ type: "text" as const, text: JSON.stringify({ success: true, key: args.key, fieldCount: fields.length, hash, message: `Retrieved ${fields.length} field(s)` }, null, 2) }] }; } catch (error: any) { return { content: [{ type: "text" as const, text: JSON.stringify({ success: false, error: error.message, key: args.key }, null, 2) }], isError: true }; } } export async function redisHdel(args: z.infer<typeof redisHdelSchema>): Promise<ToolResponse> { try { const client = await getRedisClient(args.url); const fields = Array.isArray(args.fields) ? args.fields : [args.fields]; const count = await client.hdel(args.key, ...fields); return { content: [{ type: "text" as const, text: JSON.stringify({ success: true, key: args.key, fields, deletedCount: count, message: `${count} field(s) deleted` }, null, 2) }] }; } catch (error: any) { return { content: [{ type: "text" as const, text: JSON.stringify({ success: false, error: error.message, key: args.key }, null, 2) }], isError: true }; } } export async function redisLpush(args: z.infer<typeof redisLpushSchema>): Promise<ToolResponse> { try { const client = await getRedisClient(args.url); const values = Array.isArray(args.values) ? args.values : [args.values]; const length = await client.lpush(args.key, ...values); return { content: [{ type: "text" as const, text: JSON.stringify({ success: true, key: args.key, values, listLength: length, message: `Pushed ${values.length} value(s) to left, list now has ${length} elements` }, null, 2) }] }; } catch (error: any) { return { content: [{ type: "text" as const, text: JSON.stringify({ success: false, error: error.message, key: args.key }, null, 2) }], isError: true }; } } export async function redisRpush(args: z.infer<typeof redisRpushSchema>): Promise<ToolResponse> { try { const client = await getRedisClient(args.url); const values = Array.isArray(args.values) ? args.values : [args.values]; const length = await client.rpush(args.key, ...values); return { content: [{ type: "text" as const, text: JSON.stringify({ success: true, key: args.key, values, listLength: length, message: `Pushed ${values.length} value(s) to right, list now has ${length} elements` }, null, 2) }] }; } catch (error: any) { return { content: [{ type: "text" as const, text: JSON.stringify({ success: false, error: error.message, key: args.key }, null, 2) }], isError: true }; } } export async function redisLrange(args: z.infer<typeof redisLrangeSchema>): Promise<ToolResponse> { try { const client = await getRedisClient(args.url); const values = await client.lrange(args.key, args.start, args.stop); return { content: [{ type: "text" as const, text: JSON.stringify({ success: true, key: args.key, start: args.start, stop: args.stop, count: values.length, values, message: `Retrieved ${values.length} element(s) from list` }, null, 2) }] }; } catch (error: any) { return { content: [{ type: "text" as const, text: JSON.stringify({ success: false, error: error.message, key: args.key }, null, 2) }], isError: true }; } } export async function redisLpop(args: z.infer<typeof redisLpopSchema>): Promise<ToolResponse> { try { const client = await getRedisClient(args.url); const value = args.count ? await client.lpop(args.key, args.count) : await client.lpop(args.key); return { content: [{ type: "text" as const, text: JSON.stringify({ success: true, key: args.key, count: args.count || 1, value, found: value !== null, message: value !== null ? `Popped ${args.count || 1} element(s) from left` : 'List is empty or does not exist' }, null, 2) }] }; } catch (error: any) { return { content: [{ type: "text" as const, text: JSON.stringify({ success: false, error: error.message, key: args.key }, null, 2) }], isError: true }; } } export async function redisSadd(args: z.infer<typeof redisSaddSchema>): Promise<ToolResponse> { try { const client = await getRedisClient(args.url); const members = Array.isArray(args.members) ? args.members : [args.members]; const added = await client.sadd(args.key, ...members); return { content: [{ type: "text" as const, text: JSON.stringify({ success: true, key: args.key, members, addedCount: added, message: `${added} new member(s) added to set` }, null, 2) }] }; } catch (error: any) { return { content: [{ type: "text" as const, text: JSON.stringify({ success: false, error: error.message, key: args.key }, null, 2) }], isError: true }; } } export async function redisSmembers(args: z.infer<typeof redisSmembersSchema>): Promise<ToolResponse> { try { const client = await getRedisClient(args.url); const members = await client.smembers(args.key); return { content: [{ type: "text" as const, text: JSON.stringify({ success: true, key: args.key, count: members.length, members, message: `Set contains ${members.length} member(s)` }, null, 2) }] }; } catch (error: any) { return { content: [{ type: "text" as const, text: JSON.stringify({ success: false, error: error.message, key: args.key }, null, 2) }], isError: true }; } } export async function redisSrem(args: z.infer<typeof redisSremSchema>): Promise<ToolResponse> { try { const client = await getRedisClient(args.url); const members = Array.isArray(args.members) ? args.members : [args.members]; const removed = await client.srem(args.key, ...members); return { content: [{ type: "text" as const, text: JSON.stringify({ success: true, key: args.key, members, removedCount: removed, message: `${removed} member(s) removed from set` }, null, 2) }] }; } catch (error: any) { return { content: [{ type: "text" as const, text: JSON.stringify({ success: false, error: error.message, key: args.key }, null, 2) }], isError: true }; } } export async function redisIncr(args: z.infer<typeof redisIncrSchema>): Promise<ToolResponse> { try { const client = await getRedisClient(args.url); const value = await client.incr(args.key); return { content: [{ type: "text" as const, text: JSON.stringify({ success: true, key: args.key, value, message: `Counter incremented to ${value}` }, null, 2) }] }; } catch (error: any) { return { content: [{ type: "text" as const, text: JSON.stringify({ success: false, error: error.message, key: args.key, hint: 'Make sure the value is an integer or the key does not exist' }, null, 2) }], isError: true }; } } export async function redisDecr(args: z.infer<typeof redisDecrSchema>): Promise<ToolResponse> { try { const client = await getRedisClient(args.url); const value = await client.decr(args.key); return { content: [{ type: "text" as const, text: JSON.stringify({ success: true, key: args.key, value, message: `Counter decremented to ${value}` }, null, 2) }] }; } catch (error: any) { return { content: [{ type: "text" as const, text: JSON.stringify({ success: false, error: error.message, key: args.key, hint: 'Make sure the value is an integer or the key does not exist' }, null, 2) }], isError: true }; } } export async function redisFlushdb(args: z.infer<typeof redisFlushdbSchema>): Promise<ToolResponse> { try { const client = await getRedisClient(args.url); const result = await client.flushdb(); return { content: [{ type: "text" as const, text: JSON.stringify({ success: true, result, message: 'Database cleared successfully' }, null, 2) }] }; } catch (error: any) { return { content: [{ type: "text" as const, text: JSON.stringify({ success: false, error: error.message, hint: 'This operation clears all keys in the current database' }, null, 2) }], isError: true }; } } export async function redisInfo(args: z.infer<typeof redisInfoSchema>): Promise<ToolResponse> { try { const client = await getRedisClient(args.url); const info = args.section ? await client.info(args.section) : await client.info(); // Parse info into object const lines = info.split('\r\n').filter((line: string) => line && !line.startsWith('#')); const parsed: Record<string, string> = {}; for (const line of lines) { const [key, value] = line.split(':'); if (key && value) { parsed[key] = value; } } return { content: [{ type: "text" as const, text: JSON.stringify({ success: true, section: args.section || 'default', info: parsed, rawInfo: info, message: 'Server info retrieved successfully' }, null, 2) }] }; } catch (error: any) { return { content: [{ type: "text" as const, text: JSON.stringify({ success: false, error: error.message, hint: 'Valid sections: server, clients, memory, persistence, stats, replication, cpu, commandstats, cluster, keyspace' }, null, 2) }], isError: true }; } } export async function redisDbsize(args: z.infer<typeof redisDbsizeSchema>): Promise<ToolResponse> { try { const client = await getRedisClient(args.url); const size = await client.dbsize(); return { content: [{ type: "text" as const, text: JSON.stringify({ success: true, keyCount: size, message: `Database contains ${size} key(s)` }, null, 2) }] }; } catch (error: any) { return { content: [{ type: "text" as const, text: JSON.stringify({ success: false, error: error.message }, null, 2) }], isError: true }; } } // ==================== Tool Metadata ==================== export const redisTools = [ { name: 'redis_connect', description: 'Connect to Redis server and verify connection. Returns server version and database size.', inputSchema: { type: 'object', properties: { url: { type: 'string', description: 'Redis connection string (e.g., redis://localhost:6379)' }, cwd: { type: 'string', description: 'Working directory' } }, required: ['url'] } }, { name: 'redis_get', description: 'Get value by key. Returns null if key does not exist.', inputSchema: { type: 'object', properties: { url: { type: 'string', description: 'Redis connection string' }, key: { type: 'string', description: 'Key to retrieve' }, cwd: { type: 'string', description: 'Working directory' } }, required: ['url', 'key'] } }, { name: 'redis_set', description: 'Set key-value pair with optional expiration in seconds.', inputSchema: { type: 'object', properties: { url: { type: 'string', description: 'Redis connection string' }, key: { type: 'string', description: 'Key to set' }, value: { type: 'string', description: 'Value to store' }, ex: { type: 'number', description: 'Expiration in seconds (optional)' }, cwd: { type: 'string', description: 'Working directory' } }, required: ['url', 'key', 'value'] } }, { name: 'redis_del', description: 'Delete one or more keys. Returns count of deleted keys.', inputSchema: { type: 'object', properties: { url: { type: 'string', description: 'Redis connection string' }, keys: { oneOf: [ { type: 'string' }, { type: 'array', items: { type: 'string' } } ], description: 'Key(s) to delete' }, cwd: { type: 'string', description: 'Working directory' } }, required: ['url', 'keys'] } }, { name: 'redis_exists', description: 'Check if one or more keys exist. Returns count of existing keys.', inputSchema: { type: 'object', properties: { url: { type: 'string', description: 'Redis connection string' }, keys: { oneOf: [ { type: 'string' }, { type: 'array', items: { type: 'string' } } ], description: 'Key(s) to check' }, cwd: { type: 'string', description: 'Working directory' } }, required: ['url', 'keys'] } }, { name: 'redis_keys', description: 'Find keys matching a pattern. Use "user:*" or "*session*" patterns. WARNING: Slow on large databases.', inputSchema: { type: 'object', properties: { url: { type: 'string', description: 'Redis connection string' }, pattern: { type: 'string', description: 'Pattern to match keys (e.g., "user:*", "*session*")' }, cwd: { type: 'string', description: 'Working directory' } }, required: ['url', 'pattern'] } }, { name: 'redis_ttl', description: 'Get time-to-live for a key in seconds. Returns -1 if no expiration, -2 if key does not exist.', inputSchema: { type: 'object', properties: { url: { type: 'string', description: 'Redis connection string' }, key: { type: 'string', description: 'Key to check TTL' }, cwd: { type: 'string', description: 'Working directory' } }, required: ['url', 'key'] } }, { name: 'redis_expire', description: 'Set expiration time for a key in seconds.', inputSchema: { type: 'object', properties: { url: { type: 'string', description: 'Redis connection string' }, key: { type: 'string', description: 'Key to set expiration' }, seconds: { type: 'number', description: 'Expiration time in seconds' }, cwd: { type: 'string', description: 'Working directory' } }, required: ['url', 'key', 'seconds'] } }, { name: 'redis_hset', description: 'Set field in hash. Hashes are like objects/dictionaries.', inputSchema: { type: 'object', properties: { url: { type: 'string', description: 'Redis connection string' }, key: { type: 'string', description: 'Hash key' }, field: { type: 'string', description: 'Field name' }, value: { type: 'string', description: 'Field value' }, cwd: { type: 'string', description: 'Working directory' } }, required: ['url', 'key', 'field', 'value'] } }, { name: 'redis_hget', description: 'Get field from hash.', inputSchema: { type: 'object', properties: { url: { type: 'string', description: 'Redis connection string' }, key: { type: 'string', description: 'Hash key' }, field: { type: 'string', description: 'Field name' }, cwd: { type: 'string', description: 'Working directory' } }, required: ['url', 'key', 'field'] } }, { name: 'redis_hgetall', description: 'Get all fields and values from hash.', inputSchema: { type: 'object', properties: { url: { type: 'string', description: 'Redis connection string' }, key: { type: 'string', description: 'Hash key' }, cwd: { type: 'string', description: 'Working directory' } }, required: ['url', 'key'] } }, { name: 'redis_hdel', description: 'Delete one or more fields from hash.', inputSchema: { type: 'object', properties: { url: { type: 'string', description: 'Redis connection string' }, key: { type: 'string', description: 'Hash key' }, fields: { oneOf: [ { type: 'string' }, { type: 'array', items: { type: 'string' } } ], description: 'Field(s) to delete' }, cwd: { type: 'string', description: 'Working directory' } }, required: ['url', 'key', 'fields'] } }, { name: 'redis_lpush', description: 'Push value(s) to left (head) of list. Creates list if it does not exist.', inputSchema: { type: 'object', properties: { url: { type: 'string', description: 'Redis connection string' }, key: { type: 'string', description: 'List key' }, values: { oneOf: [ { type: 'string' }, { type: 'array', items: { type: 'string' } } ], description: 'Value(s) to push' }, cwd: { type: 'string', description: 'Working directory' } }, required: ['url', 'key', 'values'] } }, { name: 'redis_rpush', description: 'Push value(s) to right (tail) of list. Creates list if it does not exist.', inputSchema: { type: 'object', properties: { url: { type: 'string', description: 'Redis connection string' }, key: { type: 'string', description: 'List key' }, values: { oneOf: [ { type: 'string' }, { type: 'array', items: { type: 'string' } } ], description: 'Value(s) to push' }, cwd: { type: 'string', description: 'Working directory' } }, required: ['url', 'key', 'values'] } }, { name: 'redis_lrange', description: 'Get range of elements from list. Use 0 for start, -1 for end to get all elements.', inputSchema: { type: 'object', properties: { url: { type: 'string', description: 'Redis connection string' }, key: { type: 'string', description: 'List key' }, start: { type: 'number', description: 'Start index (0-based, use -1 for last)' }, stop: { type: 'number', description: 'Stop index (0-based, use -1 for last)' }, cwd: { type: 'string', description: 'Working directory' } }, required: ['url', 'key', 'start', 'stop'] } }, { name: 'redis_lpop', description: 'Pop (remove and return) element(s) from left (head) of list.', inputSchema: { type: 'object', properties: { url: { type: 'string', description: 'Redis connection string' }, key: { type: 'string', description: 'List key' }, count: { type: 'number', description: 'Number of elements to pop (default: 1)' }, cwd: { type: 'string', description: 'Working directory' } }, required: ['url', 'key'] } }, { name: 'redis_sadd', description: 'Add member(s) to set. Sets are unordered collections of unique strings.', inputSchema: { type: 'object', properties: { url: { type: 'string', description: 'Redis connection string' }, key: { type: 'string', description: 'Set key' }, members: { oneOf: [ { type: 'string' }, { type: 'array', items: { type: 'string' } } ], description: 'Member(s) to add' }, cwd: { type: 'string', description: 'Working directory' } }, required: ['url', 'key', 'members'] } }, { name: 'redis_smembers', description: 'Get all members from set.', inputSchema: { type: 'object', properties: { url: { type: 'string', description: 'Redis connection string' }, key: { type: 'string', description: 'Set key' }, cwd: { type: 'string', description: 'Working directory' } }, required: ['url', 'key'] } }, { name: 'redis_srem', description: 'Remove member(s) from set.', inputSchema: { type: 'object', properties: { url: { type: 'string', description: 'Redis connection string' }, key: { type: 'string', description: 'Set key' }, members: { oneOf: [ { type: 'string' }, { type: 'array', items: { type: 'string' } } ], description: 'Member(s) to remove' }, cwd: { type: 'string', description: 'Working directory' } }, required: ['url', 'key', 'members'] } }, { name: 'redis_incr', description: 'Increment counter by 1. Creates key with value 1 if it does not exist. Atomic operation.', inputSchema: { type: 'object', properties: { url: { type: 'string', description: 'Redis connection string' }, key: { type: 'string', description: 'Counter key' }, cwd: { type: 'string', description: 'Working directory' } }, required: ['url', 'key'] } }, { name: 'redis_decr', description: 'Decrement counter by 1. Creates key with value -1 if it does not exist. Atomic operation.', inputSchema: { type: 'object', properties: { url: { type: 'string', description: 'Redis connection string' }, key: { type: 'string', description: 'Counter key' }, cwd: { type: 'string', description: 'Working directory' } }, required: ['url', 'key'] } }, { name: 'redis_flushdb', description: 'Clear all keys in current database. WARNING: This cannot be undone!', inputSchema: { type: 'object', properties: { url: { type: 'string', description: 'Redis connection string' }, cwd: { type: 'string', description: 'Working directory' } }, required: ['url'] } }, { name: 'redis_info', description: 'Get Redis server information. Optionally specify section: server, clients, memory, stats, replication, etc.', inputSchema: { type: 'object', properties: { url: { type: 'string', description: 'Redis connection string' }, section: { type: 'string', description: 'Info section (optional)' }, cwd: { type: 'string', description: 'Working directory' } }, required: ['url'] } }, { name: 'redis_dbsize', description: 'Get number of keys in current database.', inputSchema: { type: 'object', properties: { url: { type: 'string', description: 'Redis connection string' }, cwd: { type: 'string', description: 'Working directory' } }, required: ['url'] } } ];

Latest Blog Posts

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/ConnorBoetig-dev/mcp2'

If you have feedback or need assistance with the MCP directory API, please join our Discord server