| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140 |
- package data
- import (
- "context"
- "fmt"
- "strings"
- "github.com/mark3labs/mcp-go/mcp"
- "github.com/mark3labs/mcp-go/server"
- "fwh-toolbox-server/cache/redisx"
- "fwh-toolbox-server/cmd/mcp/tools/helper"
- )
- func registerRedisTools(s *server.MCPServer) {
- s.AddTool(
- mcp.NewTool("data_redis_get",
- mcp.WithDescription("读取 Redis 中指定 key 的值(只读,仅支持 string 和 hash 类型)"),
- mcp.WithString("key", mcp.Required(), mcp.Description("Redis key")),
- mcp.WithString("type", mcp.Description("key 的数据类型:string(默认)、hash、list、set")),
- ),
- handleRedisGet,
- )
- s.AddTool(
- mcp.NewTool("data_redis_exists",
- mcp.WithDescription("检查 Redis key 是否存在,并返回 TTL 信息"),
- mcp.WithString("key", mcp.Required(), mcp.Description("Redis key")),
- ),
- handleRedisExists,
- )
- }
- func handleRedisGet(ctx context.Context, req mcp.CallToolRequest) (*mcp.CallToolResult, error) {
- key, err := req.RequireString("key")
- if err != nil {
- return helper.ParamError("key"), nil
- }
- keyType := req.GetString("type", "string")
- switch keyType {
- case "string":
- val, err := redisx.Get(ctx, key)
- if err != nil {
- return helper.EmptyResult(fmt.Sprintf("key 不存在或读取失败: %s (%v)", key, err)), nil
- }
- return helper.JSONResultOrFileAuto(map[string]any{
- "key": key,
- "type": "string",
- "value": val,
- }), nil
- case "hash":
- val, err := redisx.HGetAll(ctx, key)
- if err != nil {
- return helper.ServiceError("读取Redis hash", err), nil
- }
- if len(val) == 0 {
- return helper.EmptyResult(fmt.Sprintf("key 不存在或为空: %s", key)), nil
- }
- return helper.JSONResultOrFileAuto(map[string]any{
- "key": key,
- "type": "hash",
- "value": val,
- }), nil
- case "list":
- val, err := redisx.LRange(ctx, key, 0, 99)
- if err != nil {
- return helper.ServiceError("读取Redis list", err), nil
- }
- if len(val) == 0 {
- return helper.EmptyResult(fmt.Sprintf("key 不存在或为空: %s", key)), nil
- }
- return helper.JSONResultOrFileAuto(map[string]any{
- "key": key,
- "type": "list",
- "count": len(val),
- "value": val,
- }), nil
- case "set":
- val, err := redisx.SMembers(ctx, key)
- if err != nil {
- return helper.ServiceError("读取Redis set", err), nil
- }
- if len(val) == 0 {
- return helper.EmptyResult(fmt.Sprintf("key 不存在或为空: %s", key)), nil
- }
- return helper.JSONResultOrFileAuto(map[string]any{
- "key": key,
- "type": "set",
- "count": len(val),
- "value": val,
- }), nil
- default:
- return helper.ParamInvalidError("type", "可选值: string, hash, list, set"), nil
- }
- }
- func handleRedisExists(ctx context.Context, req mcp.CallToolRequest) (*mcp.CallToolResult, error) {
- key, err := req.RequireString("key")
- if err != nil {
- return helper.ParamError("key"), nil
- }
- // 安全检查:不允许通配符
- if strings.Contains(key, "*") {
- return helper.ParamInvalidError("key", "不支持通配符,请提供精确 key"), nil
- }
- exists, err := redisx.Exists(ctx, key)
- if err != nil {
- return helper.ServiceError("检查Redis key", err), nil
- }
- if !exists {
- return helper.EmptyResult(fmt.Sprintf("key 不存在: %s", key)), nil
- }
- ttl, err := redisx.TTL(ctx, key)
- if err != nil {
- return helper.ServiceError("获取TTL", err), nil
- }
- ttlStr := "永不过期"
- if ttl > 0 {
- ttlStr = ttl.String()
- } else if ttl == -2 {
- ttlStr = "key 不存在"
- }
- return helper.JSONResultOrFileAuto(map[string]any{
- "key": key,
- "exists": true,
- "ttl": ttlStr,
- }), nil
- }
|