Skip to main content
Glama
Nicolas-Gong

Redis CRUD MCP Server

by Nicolas-Gong
index.ts26.5 kB
#!/usr/bin/env node /** * Redis CRUD MCP 服务器 * 提供用于 Redis 数据库操作的工具:SET、GET、DEL、EXISTS */ import { Server } from "@modelcontextprotocol/sdk/server/index.js"; import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js"; import { createClient, RedisClientType } from 'redis'; import { CallToolRequestSchema, ListToolsRequestSchema, ErrorCode, McpError, } from "@modelcontextprotocol/sdk/types.js"; // Redis 客户端 let redisClient: RedisClientType; /** * 获取 Redis 连接配置 */ function getRedisConfig() { const host = process.env.REDIS_HOST || '127.0.0.1'; const port = parseInt(process.env.REDIS_PORT || '6379'); const password = process.env.REDIS_PASSWORD; if (!password) { throw new Error( `Redis CRUD MCP 服务器需要配置密码。\n\n` + `请按照以下步骤配置:\n\n` + `1. 复制项目中的 cline_mcp_settings.example.json 文件\n` + `2. 编辑其中的 Redis 配置信息\n` + `3. 将配置添加到您的 cline_mcp_settings.json 文件中\n\n` + `配置位置: %APPDATA%\\Code\\User\\globalStorage\\saoudrizwan.claude-dev\\settings\\cline_mcp_settings.json\n\n` + `必需的环境变量:\n` + `- REDIS_HOST: Redis 服务器主机地址 (默认: 127.0.0.1)\n` + `- REDIS_PORT: Redis 服务器端口 (默认: 6379)\n` + `- REDIS_PASSWORD: Redis 密码 (必需)\n\n` + `配置示例:\n` + `"env": {\n` + ` "REDIS_HOST": "127.0.0.1",\n` + ` "REDIS_PORT": "6379",\n` + ` "REDIS_PASSWORD": "your_password"\n` + `}` ); } return { host, port, password, }; } /** * 初始化 Redis 连接 */ async function initializeRedis() { try { const config = getRedisConfig(); redisClient = createClient({ url: `redis://:${config.password}@${config.host}:${config.port}` }); redisClient.on('error', (err) => console.error('Redis 连接错误:', err)); await redisClient.connect(); console.error('Redis 连接成功'); } catch (error) { console.error('初始化 Redis 连接失败:', error); throw error; } } /** * 验证 Redis 操作参数 */ function validateRedisArgs(args: any): args is { key: string; value?: string; field?: string; fields?: string[]; values?: string[]; members?: string[]; member?: string; score?: number; start?: number; stop?: number; min?: number; max?: number; } { return ( typeof args === 'object' && args !== null && typeof args.key === 'string' && (args.value === undefined || typeof args.value === 'string') && (args.field === undefined || typeof args.field === 'string') && (args.fields === undefined || Array.isArray(args.fields)) && (args.values === undefined || Array.isArray(args.values)) && (args.members === undefined || Array.isArray(args.members)) && (args.member === undefined || typeof args.member === 'string') && (args.score === undefined || typeof args.score === 'number') && (args.start === undefined || typeof args.start === 'number') && (args.stop === undefined || typeof args.stop === 'number') && (args.min === undefined || typeof args.min === 'number') && (args.max === undefined || typeof args.max === 'number') ); } /** * 执行 SET 操作 */ async function executeSet(key: string, value: string): Promise<string | null> { return await redisClient.set(key, value); } /** * 执行 GET 操作 */ async function executeGet(key: string): Promise<string | null> { return await redisClient.get(key); } /** * 执行 DEL 操作 */ async function executeDel(key: string): Promise<number> { return await redisClient.del(key); } /** * 执行 EXISTS 操作 */ async function executeExists(key: string): Promise<number> { return await redisClient.exists(key); } /** * 执行 LPUSH 操作 (列表左侧推入) */ async function executeLPush(key: string, values: string[]): Promise<number> { return await redisClient.lPush(key, values); } /** * 执行 RPUSH 操作 (列表右侧推入) */ async function executeRPush(key: string, values: string[]): Promise<number> { return await redisClient.rPush(key, values); } /** * 执行 LPOP 操作 (列表左侧弹出) */ async function executeLPop(key: string): Promise<string | null> { return await redisClient.lPop(key); } /** * 执行 RPOP 操作 (列表右侧弹出) */ async function executeRPop(key: string): Promise<string | null> { return await redisClient.rPop(key); } /** * 执行 LRANGE 操作 (获取列表范围) */ async function executeLRange(key: string, start: number, stop: number): Promise<string[]> { return await redisClient.lRange(key, start, stop); } /** * 执行 LLEN 操作 (获取列表长度) */ async function executeLLen(key: string): Promise<number> { return await redisClient.lLen(key); } /** * 执行 SADD 操作 (集合添加成员) */ async function executeSAdd(key: string, members: string[]): Promise<number> { return await redisClient.sAdd(key, members); } /** * 执行 SREM 操作 (集合移除成员) */ async function executeSRem(key: string, members: string[]): Promise<number> { return await redisClient.sRem(key, members); } /** * 执行 SMEMBERS 操作 (获取集合所有成员) */ async function executeSMembers(key: string): Promise<string[]> { return await redisClient.sMembers(key); } /** * 执行 SISMEMBER 操作 (检查成员是否在集合中) */ async function executeSIsMember(key: string, member: string): Promise<boolean> { return await redisClient.sIsMember(key, member); } /** * 执行 HSET 操作 (哈希设置字段) */ async function executeHSet(key: string, field: string, value: string): Promise<number> { return await redisClient.hSet(key, field, value); } /** * 执行 HGET 操作 (哈希获取字段) */ async function executeHGet(key: string, field: string): Promise<string | undefined> { return await redisClient.hGet(key, field); } /** * 执行 HGETALL 操作 (获取哈希所有字段和值) */ async function executeHGetAll(key: string): Promise<Record<string, string>> { return await redisClient.hGetAll(key); } /** * 执行 HDEL 操作 (哈希删除字段) */ async function executeHDel(key: string, fields: string[]): Promise<number> { return await redisClient.hDel(key, fields); } /** * 执行 ZADD 操作 (有序集合添加成员) */ async function executeZAdd(key: string, score: number, member: string): Promise<number> { return await redisClient.zAdd(key, { score, value: member }); } /** * 执行 ZREM 操作 (有序集合移除成员) */ async function executeZRem(key: string, members: string[]): Promise<number> { return await redisClient.zRem(key, members); } /** * 执行 ZRANGE 操作 (有序集合范围查询) */ async function executeZRange(key: string, min: number, max: number): Promise<string[]> { return await redisClient.zRange(key, min, max); } /** * 创建带有 Redis CRUD 操作工具的 MCP 服务器 */ const server = new Server( { name: "redis-crud-server", version: "0.1.0", }, { capabilities: { tools: {}, }, } ); /** * 列出可用 Redis CRUD 工具的处理器 */ server.setRequestHandler(ListToolsRequestSchema, async () => { return { tools: [ // 字符串操作 { name: "redis_set", description: "在 Redis 数据库中设置字符串键值对", inputSchema: { type: "object", properties: { key: { type: "string", description: "要设置的键" }, value: { type: "string", description: "要设置的值" } }, required: ["key", "value"] } }, { name: "redis_get", description: "从 Redis 数据库中获取字符串键的值", inputSchema: { type: "object", properties: { key: { type: "string", description: "要获取的键" } }, required: ["key"] } }, // 通用操作 { name: "redis_del", description: "从 Redis 数据库中删除键", inputSchema: { type: "object", properties: { key: { type: "string", description: "要删除的键" } }, required: ["key"] } }, { name: "redis_exists", description: "检查 Redis 数据库中键是否存在", inputSchema: { type: "object", properties: { key: { type: "string", description: "要检查的键" } }, required: ["key"] } }, // 列表操作 { name: "redis_lpush", description: "从列表左侧推入元素", inputSchema: { type: "object", properties: { key: { type: "string", description: "列表键" }, values: { type: "array", items: { type: "string" }, description: "要推入的值数组" } }, required: ["key", "values"] } }, { name: "redis_rpush", description: "从列表右侧推入元素", inputSchema: { type: "object", properties: { key: { type: "string", description: "列表键" }, values: { type: "array", items: { type: "string" }, description: "要推入的值数组" } }, required: ["key", "values"] } }, { name: "redis_lpop", description: "从列表左侧弹出元素", inputSchema: { type: "object", properties: { key: { type: "string", description: "列表键" } }, required: ["key"] } }, { name: "redis_rpop", description: "从列表右侧弹出元素", inputSchema: { type: "object", properties: { key: { type: "string", description: "列表键" } }, required: ["key"] } }, { name: "redis_lrange", description: "获取列表指定范围的元素", inputSchema: { type: "object", properties: { key: { type: "string", description: "列表键" }, start: { type: "number", description: "起始索引", default: 0 }, stop: { type: "number", description: "结束索引", default: -1 } }, required: ["key"] } }, { name: "redis_llen", description: "获取列表长度", inputSchema: { type: "object", properties: { key: { type: "string", description: "列表键" } }, required: ["key"] } }, // 集合操作 { name: "redis_sadd", description: "向集合添加成员", inputSchema: { type: "object", properties: { key: { type: "string", description: "集合键" }, members: { type: "array", items: { type: "string" }, description: "要添加的成员数组" } }, required: ["key", "members"] } }, { name: "redis_srem", description: "从集合移除成员", inputSchema: { type: "object", properties: { key: { type: "string", description: "集合键" }, members: { type: "array", items: { type: "string" }, description: "要移除的成员数组" } }, required: ["key", "members"] } }, { name: "redis_smembers", description: "获取集合的所有成员", inputSchema: { type: "object", properties: { key: { type: "string", description: "集合键" } }, required: ["key"] } }, { name: "redis_sismember", description: "检查成员是否在集合中", inputSchema: { type: "object", properties: { key: { type: "string", description: "集合键" }, member: { type: "string", description: "要检查的成员" } }, required: ["key", "member"] } }, // 哈希操作 { name: "redis_hset", description: "设置哈希字段的值", inputSchema: { type: "object", properties: { key: { type: "string", description: "哈希键" }, field: { type: "string", description: "字段名" }, value: { type: "string", description: "字段值" } }, required: ["key", "field", "value"] } }, { name: "redis_hget", description: "获取哈希字段的值", inputSchema: { type: "object", properties: { key: { type: "string", description: "哈希键" }, field: { type: "string", description: "字段名" } }, required: ["key", "field"] } }, { name: "redis_hgetall", description: "获取哈希的所有字段和值", inputSchema: { type: "object", properties: { key: { type: "string", description: "哈希键" } }, required: ["key"] } }, { name: "redis_hdel", description: "删除哈希字段", inputSchema: { type: "object", properties: { key: { type: "string", description: "哈希键" }, fields: { type: "array", items: { type: "string" }, description: "要删除的字段数组" } }, required: ["key", "fields"] } }, // 有序集合操作 { name: "redis_zadd", description: "向有序集合添加成员", inputSchema: { type: "object", properties: { key: { type: "string", description: "有序集合键" }, score: { type: "number", description: "成员分数" }, member: { type: "string", description: "成员值" } }, required: ["key", "score", "member"] } }, { name: "redis_zrem", description: "从有序集合移除成员", inputSchema: { type: "object", properties: { key: { type: "string", description: "有序集合键" }, members: { type: "array", items: { type: "string" }, description: "要移除的成员数组" } }, required: ["key", "members"] } }, { name: "redis_zrange", description: "获取有序集合指定分数范围的成员", inputSchema: { type: "object", properties: { key: { type: "string", description: "有序集合键" }, min: { type: "number", description: "最小分数", default: "-inf" }, max: { type: "number", description: "最大分数", default: "+inf" } }, required: ["key"] } } ] }; }); /** * Redis CRUD 工具调用的处理器 */ server.setRequestHandler(CallToolRequestSchema, async (request) => { if (!validateRedisArgs(request.params.arguments)) { throw new McpError( ErrorCode.InvalidParams, '无效的参数。必需参数:key (字符串),其他参数根据操作类型而定' ); } const args = request.params.arguments; const { key } = args; try { let result: any; switch (request.params.name) { // 字符串操作 case "redis_set": if (!args.value) { throw new McpError( ErrorCode.InvalidParams, 'SET 操作需要提供 value 参数' ); } result = await executeSet(key, args.value); return { content: [ { type: "text", text: `SET 执行成功。键: ${key}, 值: ${args.value}, 结果: ${result}` } ] }; case "redis_get": result = await executeGet(key); return { content: [ { type: "text", text: `GET 执行成功。键: ${key}, 值: ${result !== null ? result : 'null'}` } ] }; // 通用操作 case "redis_del": result = await executeDel(key); return { content: [ { type: "text", text: `DEL 执行成功。键: ${key}, 删除的键数量: ${result}` } ] }; case "redis_exists": result = await executeExists(key); return { content: [ { type: "text", text: `EXISTS 执行成功。键: ${key}, 存在: ${result > 0 ? '是' : '否'}` } ] }; // 列表操作 case "redis_lpush": if (!args.values) { throw new McpError( ErrorCode.InvalidParams, 'LPUSH 操作需要提供 values 参数' ); } result = await executeLPush(key, args.values); return { content: [ { type: "text", text: `LPUSH 执行成功。键: ${key}, 添加的元素数量: ${result}` } ] }; case "redis_rpush": if (!args.values) { throw new McpError( ErrorCode.InvalidParams, 'RPUSH 操作需要提供 values 参数' ); } result = await executeRPush(key, args.values); return { content: [ { type: "text", text: `RPUSH 执行成功。键: ${key}, 添加的元素数量: ${result}` } ] }; case "redis_lpop": result = await executeLPop(key); return { content: [ { type: "text", text: `LPOP 执行成功。键: ${key}, 弹出的元素: ${result !== null ? result : 'null'}` } ] }; case "redis_rpop": result = await executeRPop(key); return { content: [ { type: "text", text: `RPOP 执行成功。键: ${key}, 弹出的元素: ${result !== null ? result : 'null'}` } ] }; case "redis_lrange": const start = args.start || 0; const stop = args.stop || -1; result = await executeLRange(key, start, stop); return { content: [ { type: "text", text: `LRANGE 执行成功。键: ${key}, 范围: [${start}, ${stop}], 结果: [${result.join(', ')}]` } ] }; case "redis_llen": result = await executeLLen(key); return { content: [ { type: "text", text: `LLEN 执行成功。键: ${key}, 长度: ${result}` } ] }; // 集合操作 case "redis_sadd": if (!args.members) { throw new McpError( ErrorCode.InvalidParams, 'SADD 操作需要提供 members 参数' ); } result = await executeSAdd(key, args.members); return { content: [ { type: "text", text: `SADD 执行成功。键: ${key}, 添加的成员数量: ${result}` } ] }; case "redis_srem": if (!args.members) { throw new McpError( ErrorCode.InvalidParams, 'SREM 操作需要提供 members 参数' ); } result = await executeSRem(key, args.members); return { content: [ { type: "text", text: `SREM 执行成功。键: ${key}, 移除的成员数量: ${result}` } ] }; case "redis_smembers": result = await executeSMembers(key); return { content: [ { type: "text", text: `SMEMBERS 执行成功。键: ${key}, 成员: [${result.join(', ')}]` } ] }; case "redis_sismember": if (!args.member) { throw new McpError( ErrorCode.InvalidParams, 'SISMEMBER 操作需要提供 member 参数' ); } result = await executeSIsMember(key, args.member); return { content: [ { type: "text", text: `SISMEMBER 执行成功。键: ${key}, 成员: ${args.member}, 是否存在: ${result ? '是' : '否'}` } ] }; // 哈希操作 case "redis_hset": if (!args.field || !args.value) { throw new McpError( ErrorCode.InvalidParams, 'HSET 操作需要提供 field 和 value 参数' ); } result = await executeHSet(key, args.field, args.value); return { content: [ { type: "text", text: `HSET 执行成功。键: ${key}, 字段: ${args.field}, 值: ${args.value}, 结果: ${result}` } ] }; case "redis_hget": if (!args.field) { throw new McpError( ErrorCode.InvalidParams, 'HGET 操作需要提供 field 参数' ); } result = await executeHGet(key, args.field); return { content: [ { type: "text", text: `HGET 执行成功。键: ${key}, 字段: ${args.field}, 值: ${result !== undefined ? result : 'undefined'}` } ] }; case "redis_hgetall": result = await executeHGetAll(key); return { content: [ { type: "text", text: `HGETALL 执行成功。键: ${key}, 数据: ${JSON.stringify(result)}` } ] }; case "redis_hdel": if (!args.fields) { throw new McpError( ErrorCode.InvalidParams, 'HDEL 操作需要提供 fields 参数' ); } result = await executeHDel(key, args.fields); return { content: [ { type: "text", text: `HDEL 执行成功。键: ${key}, 删除的字段数量: ${result}` } ] }; // 有序集合操作 case "redis_zadd": if (args.score === undefined || !args.member) { throw new McpError( ErrorCode.InvalidParams, 'ZADD 操作需要提供 score 和 member 参数' ); } result = await executeZAdd(key, args.score, args.member); return { content: [ { type: "text", text: `ZADD 执行成功。键: ${key}, 分数: ${args.score}, 成员: ${args.member}, 结果: ${result}` } ] }; case "redis_zrem": if (!args.members) { throw new McpError( ErrorCode.InvalidParams, 'ZREM 操作需要提供 members 参数' ); } result = await executeZRem(key, args.members); return { content: [ { type: "text", text: `ZREM 执行成功。键: ${key}, 移除的成员数量: ${result}` } ] }; case "redis_zrange": const min = args.min || 0; const max = args.max || -1; result = await executeZRange(key, min, max); return { content: [ { type: "text", text: `ZRANGE 执行成功。键: ${key}, 范围: [${min}, ${max}], 结果: [${result.join(', ')}]` } ] }; default: throw new McpError( ErrorCode.MethodNotFound, `未知工具: ${request.params.name}` ); } } catch (error) { console.error(`Redis 操作失败:`, error); return { content: [ { type: "text", text: `Redis 操作失败: ${error instanceof Error ? error.message : String(error)}` } ], isError: true }; } }); /** * 使用 stdio 传输启动服务器 */ async function main() { try { await initializeRedis(); const transport = new StdioServerTransport(); await server.connect(transport); console.error('Redis CRUD MCP 服务器正在 stdio 上运行'); } catch (error) { console.error('启动服务器失败:', error); process.exit(1); } } main().catch((error) => { console.error("服务器错误:", error); process.exit(1); });

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/Nicolas-Gong/redis-crud-mcp-server'

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