View Javadoc
1   package fr.tiogars.chat.domains.mcp.services;
2   
3   import fr.tiogars.chat.domains.mcp.models.McpActionRequest;
4   import fr.tiogars.chat.domains.mcp.models.McpActionResponse;
5   import fr.tiogars.chat.domains.mcp.models.McpResource;
6   import fr.tiogars.chat.domains.mcp.models.McpServiceConfig;
7   import org.springframework.stereotype.Service;
8   
9   import java.time.Duration;
10  import java.time.Instant;
11  import java.util.List;
12  import java.util.Map;
13  import java.util.concurrent.ConcurrentHashMap;
14  
15  /**
16   * Service for managing MCP services and executing actions.
17   */
18  @Service
19  public class McpService {
20  
21      private final Map<String, McpServiceConfig> serviceConfigs = new ConcurrentHashMap<>();
22  
23      public McpService() {
24          // Initialize with some default MCP services
25          registerDefaultServices();
26      }
27  
28      private void registerDefaultServices() {
29          // Filesystem MCP server
30          McpServiceConfig filesystemConfig = new McpServiceConfig(
31                  "filesystem",
32                  "File System Access",
33                  "Access to local file system operations",
34                  "npx @modelcontextprotocol/server-filesystem",
35                  Map.of(),
36                  true,
37                  30
38          );
39          serviceConfigs.put(filesystemConfig.id(), filesystemConfig);
40  
41          // Process MCP server
42          McpServiceConfig processConfig = new McpServiceConfig(
43                  "process",
44                  "Process Management",
45                  "Execute system processes and commands",
46                  "npx @modelcontextprotocol/server-process",
47                  Map.of(),
48                  true,
49                  30
50          );
51          serviceConfigs.put(processConfig.id(), processConfig);
52  
53          // HTTP MCP server
54          McpServiceConfig httpConfig = new McpServiceConfig(
55                  "http",
56                  "HTTP Requests",
57                  "Make HTTP requests to external services",
58                  "npx @modelcontextprotocol/server-http",
59                  Map.of(),
60                  true,
61                  60
62          );
63          serviceConfigs.put(httpConfig.id(), httpConfig);
64      }
65  
66      /**
67       * Get all registered MCP service configurations.
68       *
69       * @return list of all MCP service configs
70       */
71      public List<McpServiceConfig> getAllServices() {
72          return serviceConfigs.values().stream().toList();
73      }
74  
75      /**
76       * Get a specific MCP service configuration by ID.
77       *
78       * @param serviceId the service ID
79       * @return the service configuration or null if not found
80       */
81      public McpServiceConfig getService(String serviceId) {
82          return serviceConfigs.get(serviceId);
83      }
84  
85      /**
86       * Register a new MCP service.
87       *
88       * @param config the service configuration
89       * @return the registered configuration
90       */
91      public McpServiceConfig registerService(McpServiceConfig config) {
92          serviceConfigs.put(config.id(), config);
93          return config;
94      }
95  
96      /**
97       * Execute an action on an MCP service.
98       * This is a simplified implementation that simulates MCP calls.
99       * In a real implementation, this would connect to the actual MCP server.
100      *
101      * @param request the action request
102      * @return the action response
103      */
104     public McpActionResponse executeAction(McpActionRequest request) {
105         Instant start = Instant.now();
106         McpServiceConfig config = serviceConfigs.get(request.serviceId());
107 
108         if (config == null || !config.enabled()) {
109             Instant end = Instant.now();
110             return new McpActionResponse(
111                     false,
112                     Map.of(),
113                     List.of(),
114                     "Service not found or disabled: " + request.serviceId(),
115                     Duration.between(start, end).toMillis()
116             );
117         }
118 
119         // Simulate action execution based on service type
120         McpActionResponse response = switch (request.serviceId()) {
121             case "filesystem" -> executeFilesystemAction(request);
122             case "process" -> executeProcessAction(request);
123             case "http" -> executeHttpAction(request);
124             default -> executeGenericAction(request, config);
125         };
126 
127         Instant end = Instant.now();
128         return new McpActionResponse(
129                 response.success(),
130                 response.data(),
131                 response.resources(),
132                 response.error(),
133                 Duration.between(start, end).toMillis()
134         );
135     }
136 
137     private McpActionResponse executeFilesystemAction(McpActionRequest request) {
138         String action = request.action();
139         Map<String, Object> params = request.parameters() != null ? request.parameters() : Map.of();
140 
141         if ("list_resources".equals(action)) {
142             String path = (String) params.getOrDefault("path", ".");
143             // Simulate listing files
144             McpResource resource1 = new McpResource(
145                     "file://" + path + "/file1.txt",
146                     "file1.txt",
147                     "file",
148                     "text/plain",
149                     1024L
150             );
151             McpResource resource2 = new McpResource(
152                     "file://" + path + "/file2.txt",
153                     "file2.txt",
154                     "file",
155                     "text/plain",
156                     2048L
157             );
158             return new McpActionResponse(true, Map.of("path", path), List.of(resource1, resource2), null, 0);
159         } else if ("read_resource".equals(action)) {
160             String uri = (String) params.get("uri");
161             if (uri != null) {
162                 return new McpActionResponse(
163                         true,
164                         Map.of("uri", uri, "content", "Sample content from " + uri),
165                         List.of(),
166                         null,
167                         0
168                 );
169             }
170         }
171 
172         return new McpActionResponse(false, Map.of(), List.of(), "Unknown action: " + action, 0);
173     }
174 
175     private McpActionResponse executeProcessAction(McpActionRequest request) {
176         String action = request.action();
177         if ("list_processes".equals(action)) {
178             return new McpActionResponse(
179                     true,
180                     Map.of("count", 3),
181                     List.of(),
182                     null,
183                     0
184             );
185         }
186         return new McpActionResponse(false, Map.of(), List.of(), "Unknown action: " + action, 0);
187     }
188 
189     private McpActionResponse executeHttpAction(McpActionRequest request) {
190         String action = request.action();
191         if ("get".equals(action)) {
192             String url = (String) request.parameters().get("url");
193             return new McpActionResponse(
194                     true,
195                     Map.of("url", url, "status", 200, "body", "Sample response"),
196                     List.of(),
197                     null,
198                     0
199             );
200         }
201         return new McpActionResponse(false, Map.of(), List.of(), "Unknown action: " + action, 0);
202     }
203 
204     private McpActionResponse executeGenericAction(McpActionRequest request, McpServiceConfig config) {
205         return new McpActionResponse(
206                 true,
207                 Map.of("service", config.name(), "action", request.action()),
208                 List.of(),
209                 null,
210                 0
211         );
212     }
213 }