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
17
18 @Service
19 public class McpService {
20
21 private final Map<String, McpServiceConfig> serviceConfigs = new ConcurrentHashMap<>();
22
23 public McpService() {
24
25 registerDefaultServices();
26 }
27
28 private void registerDefaultServices() {
29
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
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
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
68
69
70
71 public List<McpServiceConfig> getAllServices() {
72 return serviceConfigs.values().stream().toList();
73 }
74
75
76
77
78
79
80
81 public McpServiceConfig getService(String serviceId) {
82 return serviceConfigs.get(serviceId);
83 }
84
85
86
87
88
89
90
91 public McpServiceConfig registerService(McpServiceConfig config) {
92 serviceConfigs.put(config.id(), config);
93 return config;
94 }
95
96
97
98
99
100
101
102
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
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
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 }