# Directory Structure
```
├── .gitignore
├── pom.xml
├── README.md
└── src
    └── main
        ├── java
        │   └── com
        │       └── redis
        │           └── mcp
        │               ├── config
        │               │   └── RedisMcpServerConfiguration.java
        │               ├── RedisMcpServerApplication.java
        │               └── service
        │                   └── RedisToolService.java
        └── resources
            └── application.properties
```
# Files
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
```
 1 | HELP.md
 2 | target/
 3 | !.mvn/wrapper/maven-wrapper.jar
 4 | !**/src/main/**/target/
 5 | !**/src/test/**/target/
 6 | 
 7 | ### STS ###
 8 | .apt_generated
 9 | .classpath
10 | .factorypath
11 | .project
12 | .settings
13 | .springBeans
14 | .sts4-cache
15 | 
16 | ### IntelliJ IDEA ###
17 | .idea
18 | *.iws
19 | *.iml
20 | *.ipr
21 | 
22 | ### NetBeans ###
23 | /nbproject/private/
24 | /nbbuild/
25 | /dist/
26 | /nbdist/
27 | /.nb-gradle/
28 | build/
29 | !**/src/main/**/build/
30 | !**/src/test/**/build/
31 | 
32 | ### VS Code ###
33 | .vscode/
34 | 
```
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
```markdown
 1 | # Redis MCP Server
 2 | 
 3 | A Redis Management and Control Protocol (MCP) server implementation using Spring Boot and Spring AI.
 4 | 
 5 | ## Description
 6 | 
 7 | This project implements a Redis MCP server that provides a set of tools for Redis operations. It uses `spring-ai-mcp-server-webmvc-spring-boot-starter` to implement MCP Server-Sent Events (SSE) functionality.
 8 | 
 9 | ## Prerequisites
10 | 
11 | - JDK 17 or higher
12 | - Maven 3.6 or higher
13 | - Redis server
14 | 
15 | ## Components
16 | 
17 | - Spring Boot
18 | - Spring AI
19 | - Spring Data Redis
20 | - Lettuce Redis Client
21 | - Jackson
22 | - spring-ai-mcp-server-webmvc-spring-boot-starter
23 | 
24 | ## Features
25 | 
26 | - Redis key-value operations (set, get, delete)
27 | - Pattern-based key listing
28 | - Optional key expiration time
29 | - SSE-based MCP implementation
30 | 
31 | ## Configuration
32 | 
33 | ### Server Configuration
34 | 
35 | The Redis connection can be configured using the `redis.url` system property. Default value is `redis://localhost:6379`.
36 | 
37 | Example:
38 | ```bash
39 | java -Dredis.url=redis://your-redis-host:6379 -jar your-app.jar
40 | ```
41 | 
42 | ### Cursor Tool Configuration
43 | 
44 | To use this MCP server in Cursor, add the following configuration to your Cursor settings:
45 | 
46 | ```json
47 | {
48 |   "redis-mcp-server": {
49 |     "url": "http://localhost:8080/sse",
50 |     "enabled": true
51 |   }
52 | }
53 | ```
54 | 
55 | ## Building
56 | 
57 | ```bash
58 | mvn clean package
59 | ```
60 | 
61 | ## Running
62 | 
63 | ```bash
64 | java -jar target/redis-mcp-server-{version}.jar
65 | ```
66 | 
67 | ## API Endpoints
68 | 
69 | The server exposes the following MCP tools:
70 | 
71 | - `set`: Set a Redis key-value pair with optional expiration time
72 | - `get`: Get value from Redis by key
73 | - `delete`: Delete one or multiple keys from Redis
74 | - `list`: List Redis keys matching a pattern
75 | 
76 | ## License
77 | 
78 | This project is licensed under the MIT License. 
```
--------------------------------------------------------------------------------
/src/main/resources/application.properties:
--------------------------------------------------------------------------------
```
1 | server.port=8080
2 | spring.application.name=redis-mcp-server
3 | spring.main.bannerMode=off
4 | logging.pattern.console=
5 | server.servlet.encoding.charset=utf-8
```
--------------------------------------------------------------------------------
/src/main/java/com/redis/mcp/RedisMcpServerApplication.java:
--------------------------------------------------------------------------------
```java
 1 | package com.redis.mcp;
 2 | 
 3 | import com.redis.mcp.service.RedisToolService;
 4 | import org.springframework.ai.tool.ToolCallbackProvider;
 5 | import org.springframework.ai.tool.method.MethodToolCallbackProvider;
 6 | import org.springframework.boot.SpringApplication;
 7 | import org.springframework.boot.autoconfigure.SpringBootApplication;
 8 | import org.springframework.context.annotation.Bean;
 9 | 
10 | /**
11 |  * Main application class for Redis MCP Server
12 |  * @author yue9527
13 |  */
14 | @SpringBootApplication
15 | public class RedisMcpServerApplication {
16 | 
17 |     /**
18 |      * Main method to start the Spring Boot application
19 |      * @param args Command line arguments
20 |      */
21 |     public static void main(String[] args) {
22 |         SpringApplication.run(RedisMcpServerApplication.class, args);
23 |     }
24 | 
25 |     /**
26 |      * Creates a ToolCallbackProvider bean for Redis tools
27 |      * @param redisToolService RedisToolService instance
28 |      * @return Configured ToolCallbackProvider
29 |      */
30 |     @Bean
31 |     public ToolCallbackProvider redisTools(RedisToolService redisToolService) {
32 |         return MethodToolCallbackProvider.builder().toolObjects(redisToolService).build();
33 |     }
34 | 
35 | }
36 | 
```
--------------------------------------------------------------------------------
/src/main/java/com/redis/mcp/config/RedisMcpServerConfiguration.java:
--------------------------------------------------------------------------------
```java
 1 | package com.redis.mcp.config;
 2 | 
 3 | import org.springframework.context.annotation.Bean;
 4 | import org.springframework.context.annotation.Configuration;
 5 | import org.springframework.data.redis.connection.RedisStandaloneConfiguration;
 6 | import org.springframework.data.redis.connection.lettuce.LettuceConnectionFactory;
 7 | import org.springframework.data.redis.core.StringRedisTemplate;
 8 | import org.springframework.data.redis.serializer.StringRedisSerializer;
 9 | 
10 | /**
11 |  * Configuration class for Redis MCP Server
12 |  * @author yue9527
13 |  */
14 | @Configuration
15 | public class RedisMcpServerConfiguration {
16 | 
17 |     /**
18 |      * Creates a LettuceConnectionFactory bean for Redis connection
19 |      * @return Configured LettuceConnectionFactory
20 |      */
21 |     @Bean
22 |     public LettuceConnectionFactory redisConnectionFactory() {
23 |         String redisUrl = System.getProperty("redis.url", "redis://localhost:6379");
24 |         String[] parts = redisUrl.replace("redis://", "").split(":");
25 |         String host = parts[0];
26 |         int port = Integer.parseInt(parts[1]);
27 |         RedisStandaloneConfiguration config = new RedisStandaloneConfiguration(host, port);
28 |         return new LettuceConnectionFactory(config);
29 |     }
30 | 
31 |     /**
32 |      * Creates a StringRedisTemplate bean for Redis operations
33 |      * @param redisConnectionFactory LettuceConnectionFactory instance
34 |      * @return Configured StringRedisTemplate
35 |      */
36 |     @Bean
37 |     public StringRedisTemplate redisTemplate(LettuceConnectionFactory redisConnectionFactory) {
38 |         StringRedisTemplate template = new StringRedisTemplate();
39 |         template.setConnectionFactory(redisConnectionFactory);
40 |         template.setKeySerializer(new StringRedisSerializer());
41 |         template.setValueSerializer(new StringRedisSerializer());
42 |         return template;
43 |     }
44 | 
45 | }    
```
--------------------------------------------------------------------------------
/pom.xml:
--------------------------------------------------------------------------------
```
 1 | <?xml version="1.0" encoding="UTF-8"?>
 2 | <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
 3 |          xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
 4 |     <modelVersion>4.0.0</modelVersion>
 5 |     <parent>
 6 |         <groupId>org.springframework.boot</groupId>
 7 |         <artifactId>spring-boot-starter-parent</artifactId>
 8 |         <version>3.2.0</version>
 9 |         <relativePath/> <!-- lookup parent from repository -->
10 |     </parent>
11 |     <groupId>com.redis</groupId>
12 |     <artifactId>redis-mcp-server</artifactId>
13 |     <version>0.0.1-SNAPSHOT</version>
14 |     <name>redis-mcp-server</name>
15 |     <description>redis-mcp-server</description>
16 |     <url/>
17 |     <licenses>
18 |         <license/>
19 |     </licenses>
20 |     <developers>
21 |         <developer/>
22 |     </developers>
23 |     <scm>
24 |         <connection/>
25 |         <developerConnection/>
26 |         <tag/>
27 |         <url/>
28 |     </scm>
29 |     <properties>
30 |         <java.version>17</java.version>
31 |         <mcp.version>1.0.0-M6</mcp.version>
32 |     </properties>
33 |     <dependencies>
34 |         <dependency>
35 |             <groupId>org.springframework.boot</groupId>
36 |             <artifactId>spring-boot-starter-web</artifactId>
37 |         </dependency>
38 | 
39 |     
40 |         <dependency>
41 |             <groupId>org.springframework.ai</groupId>
42 |             <artifactId>spring-ai-mcp-server-webmvc-spring-boot-starter</artifactId>
43 |             <version>1.0.0-M6</version>
44 |         </dependency>
45 |         <dependency>
46 |             <groupId>org.springframework.boot</groupId>
47 |             <artifactId>spring-boot-starter-data-redis</artifactId>
48 |         </dependency>
49 |         
50 |         <dependency>
51 |             <groupId>com.alibaba</groupId>
52 |             <artifactId>fastjson</artifactId>
53 |             <version>2.0.43</version> 
54 |         </dependency>
55 |         <!-- Logging -->
56 |         <dependency>
57 |             <groupId>org.slf4j</groupId>
58 |             <artifactId>slf4j-api</artifactId>
59 |         </dependency>
60 |         <dependency>
61 |             <groupId>ch.qos.logback</groupId>
62 |             <artifactId>logback-classic</artifactId>
63 |         </dependency>
64 |         <dependency>
65 |             <groupId>org.projectlombok</groupId>
66 |             <artifactId>lombok</artifactId>
67 |             <optional>true</optional>
68 |         </dependency>
69 |         <dependency>
70 |             <groupId>cn.hutool</groupId>
71 |             <artifactId>hutool-all</artifactId>
72 |             <version>5.8.8</version>
73 |         </dependency>
74 | 
75 |         <dependency>
76 |             <groupId>org.springframework.boot</groupId>
77 |             <artifactId>spring-boot-starter-test</artifactId>
78 |             <scope>test</scope>
79 |         </dependency>
80 |     </dependencies>
81 | 
82 |     <build>
83 |         <plugins>
84 |             <plugin>
85 |                 <groupId>org.springframework.boot</groupId>
86 |                 <artifactId>spring-boot-maven-plugin</artifactId>
87 |             </plugin>
88 |         </plugins>
89 |     </build>
90 | 
91 | </project>
92 | 
```
--------------------------------------------------------------------------------
/src/main/java/com/redis/mcp/service/RedisToolService.java:
--------------------------------------------------------------------------------
```java
  1 | package com.redis.mcp.service;
  2 | 
  3 | import java.io.IOException;
  4 | import java.util.HashMap;
  5 | import java.util.List;
  6 | import java.util.Map;
  7 | import java.util.stream.Collectors;
  8 | 
  9 | import com.fasterxml.jackson.databind.ObjectMapper;
 10 | import org.springframework.ai.tool.annotation.Tool;
 11 | import org.springframework.data.redis.core.StringRedisTemplate;
 12 | import org.springframework.stereotype.Service;
 13 | import org.springframework.util.StringUtils;
 14 | 
 15 | /**
 16 |  * Redis Tool Service for handling Redis operations
 17 |  * @author yue9527
 18 |  */
 19 | @Service
 20 | public class RedisToolService {
 21 | 
 22 |     private final StringRedisTemplate redisTemplate;
 23 |     private final ObjectMapper objectMapper;
 24 | 
 25 |     /**
 26 |      * Constructor for RedisToolService
 27 |      * @param redisTemplate StringRedisTemplate instance
 28 |      * @param objectMapper ObjectMapper instance
 29 |      */
 30 |     public RedisToolService(StringRedisTemplate redisTemplate, ObjectMapper objectMapper) {
 31 |         this.redisTemplate = redisTemplate;
 32 |         this.objectMapper = objectMapper;
 33 |     }
 34 | 
 35 |     /**
 36 |      * Set a key-value pair in Redis with optional expiration time
 37 |      * @param jsonArgs JSON string containing key, value and optional expireSeconds
 38 |      * @return Operation result message
 39 |      */
 40 |     @Tool(name = "set", description = "Set a Redis key-value pair with optional expiration time")
 41 |     public String setValue(String jsonArgs) {
 42 |         try {
 43 |             Map<String, Object> args = objectMapper.readValue(jsonArgs, Map.class);
 44 |             String key = (String) args.get("key");
 45 |             String value = (String) args.get("value");
 46 |             Integer expireSeconds = (Integer) args.get("expireSeconds");
 47 |             if (expireSeconds != null) {
 48 |                 redisTemplate.opsForValue().set(key, value, expireSeconds);
 49 |             } else {
 50 |                 redisTemplate.opsForValue().set(key, value);
 51 |             }
 52 |             return "Successfully set key: " + key;
 53 |         } catch (IOException e) {
 54 |             return "Error parsing JSON arguments: " + e.getMessage();
 55 |         }
 56 |     }
 57 | 
 58 |     /**
 59 |      * Get value from Redis by key
 60 |      * @param jsonArgs JSON string containing the key
 61 |      * @return Retrieved value or error message
 62 |      */
 63 |     @Tool(name = "get", description = "Get value from Redis by key")
 64 |     public String getValue(String jsonArgs) {
 65 |         try {
 66 |             Map<String, Object> args = objectMapper.readValue(jsonArgs, Map.class);
 67 |             String key = (String) args.get("keys");
 68 |             String result = redisTemplate.opsForValue().get(key);
 69 |             if (result == null) {
 70 |                 return "Key not found: " + key;
 71 |             }
 72 |             return result;
 73 |         } catch (Exception e) {
 74 |             return "Error parsing JSON arguments: " + e.getMessage();
 75 |         }
 76 |     }
 77 | 
 78 |     /**
 79 |      * Delete one or multiple keys from Redis
 80 |      * @param jsonArgs JSON string containing key(s) to delete
 81 |      * @return Operation result message
 82 |      */
 83 |     @Tool(name = "delete", description = "Delete one or multiple keys from Redis")
 84 |     public String deleteValue(String jsonArgs) {
 85 |         try {
 86 |             Map<String, Object> args = objectMapper.readValue(jsonArgs, Map.class);
 87 |             Object keyObj = args.get("keys");
 88 |             if (keyObj instanceof List) {
 89 |                 List<String> keys = (List<String>) keyObj;
 90 |                 redisTemplate.delete(keys);
 91 |                 return "Successfully deleted " + keys.size() + " keys";
 92 |             } else {
 93 |                 String key = (String) keyObj;
 94 |                 redisTemplate.delete(key);
 95 |                 return "Successfully deleted key: " + key;
 96 |             }
 97 |         } catch (IOException e) {
 98 |             return "Error parsing JSON arguments: " + e.getMessage();
 99 |         }
100 |     }
101 | 
102 |     /**
103 |      * List Redis keys matching a pattern
104 |      * @param jsonArgs JSON string containing optional pattern
105 |      * @return List of matching keys or error message
106 |      */
107 |     @Tool(name = "list", description = "List Redis keys matching a pattern")
108 |     public String listKeys(String jsonArgs) {
109 |         try {
110 |             Map<String, Object> args = new HashMap<>();
111 |             if (StringUtils.hasLength(jsonArgs)) {
112 |                 args = objectMapper.readValue(jsonArgs, Map.class);
113 |             }
114 |             String pattern = (String) args.getOrDefault("pattern", "*");
115 |             List<String> keys = redisTemplate.keys(pattern).stream().collect(Collectors.toList());
116 |             return keys.size() > 0 ? "Found keys:\n" + String.join("\n", keys) : "No keys found matching the pattern";
117 |         } catch (IOException e) {
118 |             return "Error parsing JSON arguments: " + e.getMessage();
119 |         }
120 |     }
121 | }    
```