@bniladridas/cursor 0.1.7
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.clang-tidy +28 -0
- package/.dockerignore +56 -0
- package/.env.example +29 -0
- package/.github/CODEOWNERS +2 -0
- package/.github/ISSUE_TEMPLATE/blank.md +27 -0
- package/.github/ISSUE_TEMPLATE/bug_report.md +33 -0
- package/.github/ISSUE_TEMPLATE/feature_request.md +24 -0
- package/.github/SECURITY.md +24 -0
- package/.github/codeql/codeql-config.yml +8 -0
- package/.github/dependabot.yml +14 -0
- package/.github/labeler.yml +50 -0
- package/.github/packaging/brand-cursor.png +0 -0
- package/.github/packaging/database/init.sql +48 -0
- package/.github/packaging/docker/Dockerfile +111 -0
- package/.github/packaging/docker/docker-compose.yml +56 -0
- package/.github/packaging/scripts/preflight.sh +413 -0
- package/.github/packaging/scripts/prepare-release.sh +141 -0
- package/.github/packaging/scripts/release.sh +22 -0
- package/.github/packaging/scripts/setup-git-hooks.sh +73 -0
- package/.github/pull_request_template.md +31 -0
- package/.github/signed.json +9 -0
- package/.github/workflows/README.md +23 -0
- package/.github/workflows/ci.yml +181 -0
- package/.github/workflows/cla.yml +33 -0
- package/.github/workflows/formula-sha.yml +63 -0
- package/.github/workflows/issue-response.yml +44 -0
- package/.github/workflows/labeler.yml +42 -0
- package/.github/workflows/pr-body.yml +49 -0
- package/.github/workflows/release.yml +176 -0
- package/.github/workflows/security.yml +94 -0
- package/.github/workflows/stale.yml +38 -0
- package/AGENTS.md +49 -0
- package/CHANGELOG.md +3 -0
- package/CMakeLists.txt +646 -0
- package/Formula/cursor.rb +46 -0
- package/LICENSE +201 -0
- package/Makefile +28 -0
- package/README.md +46 -0
- package/cli.js +16 -0
- package/include/agent.h +86 -0
- package/include/agent_mode.h +17 -0
- package/include/memory_manager.h +102 -0
- package/include/services/ai_service.h +31 -0
- package/include/services/auth_service.h +87 -0
- package/include/services/checkpoint_service.h +69 -0
- package/include/services/codebase_service.h +38 -0
- package/include/services/command_service.h +23 -0
- package/include/services/context_service.h +74 -0
- package/include/services/database_service.h +56 -0
- package/include/services/error_service.h +106 -0
- package/include/services/file_service.h +51 -0
- package/include/services/git_service.h +29 -0
- package/include/services/github_service.h +85 -0
- package/include/services/mcp_service.h +85 -0
- package/include/services/multi_file_service.h +93 -0
- package/include/services/sandbox_service.h +96 -0
- package/include/services/theme_service.h +67 -0
- package/include/services/web_service.h +52 -0
- package/include/utils/config.h +68 -0
- package/include/utils/memory_utils.h +79 -0
- package/include/utils/platform.h +56 -0
- package/include/utils/ui.h +43 -0
- package/include/utils/validation.h +63 -0
- package/include/utils/version.h.in +17 -0
- package/install.js +49 -0
- package/package.json +16 -0
- package/release/checksums.txt +3 -0
- package/release/cursor-linux/cursor_v0.1.7_linux_amd64.tar.gz +0 -0
- package/release/cursor-macos/cursor_v0.1.7_darwin_arm64.tar.gz +0 -0
- package/release/cursor-windows/cursor__windows_amd64.zip +0 -0
- package/src/agent.cpp +2026 -0
- package/src/main.cpp +97 -0
- package/src/memory_manager.cpp +814 -0
- package/src/services/ai_service.cpp +366 -0
- package/src/services/auth_service.cpp +779 -0
- package/src/services/checkpoint_service.cpp +465 -0
- package/src/services/codebase_service.cpp +233 -0
- package/src/services/command_service.cpp +82 -0
- package/src/services/context_service.cpp +348 -0
- package/src/services/database_service.cpp +148 -0
- package/src/services/error_service.cpp +438 -0
- package/src/services/file_service.cpp +349 -0
- package/src/services/git_service.cpp +148 -0
- package/src/services/github_service.cpp +435 -0
- package/src/services/mcp_service.cpp +481 -0
- package/src/services/multi_file_service.cpp +591 -0
- package/src/services/sandbox_service.cpp +678 -0
- package/src/services/theme_service.cpp +429 -0
- package/src/services/web_service.cpp +532 -0
- package/src/utils/config.cpp +77 -0
- package/src/utils/memory_utils.cpp +93 -0
- package/src/utils/ui.cpp +307 -0
- package/src/utils/validation.cpp +306 -0
- package/src/utils/version.cpp +175 -0
- package/tests/e2e/docker-compose.yml +195 -0
- package/tests/e2e/run_e2e_tests.sh +70 -0
- package/tests/e2e/run_tests_in_docker.sh +115 -0
- package/tests/main_test.cpp +16 -0
- package/tests/mocks/mock_ollama.py +98 -0
- package/tests/mocks/start_nginx.sh +64 -0
|
@@ -0,0 +1,481 @@
|
|
|
1
|
+
#include "services/mcp_service.h"
|
|
2
|
+
#include <cstdlib>
|
|
3
|
+
#include <filesystem>
|
|
4
|
+
#include <fstream>
|
|
5
|
+
#include <iostream>
|
|
6
|
+
#include <sstream>
|
|
7
|
+
#ifdef _WIN32
|
|
8
|
+
#include <process.h>
|
|
9
|
+
#include <windows.h>
|
|
10
|
+
#else
|
|
11
|
+
#include <signal.h>
|
|
12
|
+
#include <sys/wait.h>
|
|
13
|
+
#include <unistd.h>
|
|
14
|
+
#endif
|
|
15
|
+
|
|
16
|
+
namespace Services {
|
|
17
|
+
|
|
18
|
+
std::map<std::string, MCPServer> MCPService::servers;
|
|
19
|
+
|
|
20
|
+
std::string MCPService::get_mcp_config_path() {
|
|
21
|
+
return "data/mcp_servers.json";
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
void MCPService::ensure_mcp_directory() {
|
|
25
|
+
std::filesystem::create_directories("data");
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
nlohmann::json MCPService::create_mcp_request(const std::string &method,
|
|
29
|
+
const nlohmann::json ¶ms) {
|
|
30
|
+
static int request_id = 1;
|
|
31
|
+
nlohmann::json request;
|
|
32
|
+
request["jsonrpc"] = "2.0";
|
|
33
|
+
request["id"] = request_id++;
|
|
34
|
+
request["method"] = method;
|
|
35
|
+
request["params"] = params;
|
|
36
|
+
return request;
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
nlohmann::json MCPService::send_mcp_request(const std::string &server_name,
|
|
40
|
+
const nlohmann::json &request) {
|
|
41
|
+
// For now, implement a basic JSON-RPC over stdio communication
|
|
42
|
+
// In a full implementation, this would handle the actual IPC with the MCP
|
|
43
|
+
// server
|
|
44
|
+
|
|
45
|
+
auto it = servers.find(server_name);
|
|
46
|
+
if (it == servers.end() || !it->second.is_running) {
|
|
47
|
+
nlohmann::json error_response;
|
|
48
|
+
error_response["error"] = "Server not found or not running";
|
|
49
|
+
return error_response;
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
// Simulate MCP communication - in real implementation this would:
|
|
53
|
+
// 1. Send JSON-RPC request to server's stdin
|
|
54
|
+
// 2. Read JSON-RPC response from server's stdout
|
|
55
|
+
// 3. Handle errors and timeouts
|
|
56
|
+
|
|
57
|
+
nlohmann::json response;
|
|
58
|
+
response["jsonrpc"] = "2.0";
|
|
59
|
+
response["id"] = request["id"];
|
|
60
|
+
|
|
61
|
+
// Mock responses for demonstration
|
|
62
|
+
std::string method = request["method"];
|
|
63
|
+
if (method == "resources/list") {
|
|
64
|
+
response["result"] = nlohmann::json::array();
|
|
65
|
+
} else if (method == "tools/list") {
|
|
66
|
+
response["result"] = nlohmann::json::array();
|
|
67
|
+
} else if (method == "prompts/list") {
|
|
68
|
+
response["result"] = nlohmann::json::array();
|
|
69
|
+
} else if (method == "ping") {
|
|
70
|
+
response["result"] = "pong";
|
|
71
|
+
} else {
|
|
72
|
+
response["error"] =
|
|
73
|
+
nlohmann::json{{"code", -32601}, {"message", "Method not found"}};
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
return response;
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
bool MCPService::start_mcp_server(const std::string &server_name) {
|
|
80
|
+
auto it = servers.find(server_name);
|
|
81
|
+
if (it == servers.end()) {
|
|
82
|
+
return false;
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
MCPServer &server = it->second;
|
|
86
|
+
if (server.is_running) {
|
|
87
|
+
return true; // Already running
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
try {
|
|
91
|
+
// In a full implementation, this would:
|
|
92
|
+
// 1. Fork a new process
|
|
93
|
+
// 2. Execute the MCP server with proper stdio redirection
|
|
94
|
+
// 3. Set up JSON-RPC communication channels
|
|
95
|
+
// 4. Handle process management
|
|
96
|
+
|
|
97
|
+
// For now, simulate server startup
|
|
98
|
+
server.is_running = true;
|
|
99
|
+
#ifdef _WIN32
|
|
100
|
+
server.process_id = _getpid(); // Use _getpid() on Windows
|
|
101
|
+
#else
|
|
102
|
+
server.process_id = getpid(); // Use getpid() on Unix-like systems
|
|
103
|
+
#endif
|
|
104
|
+
|
|
105
|
+
std::cout << "Started MCP server: " << server_name << std::endl;
|
|
106
|
+
return true;
|
|
107
|
+
|
|
108
|
+
} catch (const std::exception &e) {
|
|
109
|
+
std::cerr << "Failed to start MCP server " << server_name << ": "
|
|
110
|
+
<< e.what() << std::endl;
|
|
111
|
+
return false;
|
|
112
|
+
}
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
bool MCPService::stop_mcp_server(const std::string &server_name) {
|
|
116
|
+
auto it = servers.find(server_name);
|
|
117
|
+
if (it == servers.end() || !it->second.is_running) {
|
|
118
|
+
return false;
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
MCPServer &server = it->second;
|
|
122
|
+
|
|
123
|
+
try {
|
|
124
|
+
// In a full implementation, this would:
|
|
125
|
+
// 1. Send shutdown signal to the process
|
|
126
|
+
// 2. Wait for graceful shutdown
|
|
127
|
+
// 3. Force kill if necessary
|
|
128
|
+
// 4. Clean up resources
|
|
129
|
+
|
|
130
|
+
server.is_running = false;
|
|
131
|
+
server.process_id = -1;
|
|
132
|
+
|
|
133
|
+
std::cout << "Stopped MCP server: " << server_name << std::endl;
|
|
134
|
+
return true;
|
|
135
|
+
|
|
136
|
+
} catch (const std::exception &e) {
|
|
137
|
+
std::cerr << "Failed to stop MCP server " << server_name << ": " << e.what()
|
|
138
|
+
<< std::endl;
|
|
139
|
+
return false;
|
|
140
|
+
}
|
|
141
|
+
}
|
|
142
|
+
|
|
143
|
+
bool MCPService::register_mcp_server(const MCPServer &server) {
|
|
144
|
+
servers[server.name] = server;
|
|
145
|
+
save_server_config();
|
|
146
|
+
return true;
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
bool MCPService::unregister_mcp_server(const std::string &server_name) {
|
|
150
|
+
auto it = servers.find(server_name);
|
|
151
|
+
if (it == servers.end()) {
|
|
152
|
+
return false;
|
|
153
|
+
}
|
|
154
|
+
|
|
155
|
+
if (it->second.is_running) {
|
|
156
|
+
stop_mcp_server(server_name);
|
|
157
|
+
}
|
|
158
|
+
|
|
159
|
+
servers.erase(it);
|
|
160
|
+
save_server_config();
|
|
161
|
+
return true;
|
|
162
|
+
}
|
|
163
|
+
|
|
164
|
+
std::vector<std::string> MCPService::list_mcp_servers() {
|
|
165
|
+
std::vector<std::string> server_names;
|
|
166
|
+
for (const auto &pair : servers) {
|
|
167
|
+
server_names.push_back(pair.first);
|
|
168
|
+
}
|
|
169
|
+
return server_names;
|
|
170
|
+
}
|
|
171
|
+
|
|
172
|
+
MCPServer MCPService::get_mcp_server(const std::string &server_name) {
|
|
173
|
+
auto it = servers.find(server_name);
|
|
174
|
+
if (it != servers.end()) {
|
|
175
|
+
return it->second;
|
|
176
|
+
}
|
|
177
|
+
return MCPServer{}; // Return empty server if not found
|
|
178
|
+
}
|
|
179
|
+
|
|
180
|
+
bool MCPService::is_server_running(const std::string &server_name) {
|
|
181
|
+
auto it = servers.find(server_name);
|
|
182
|
+
return (it != servers.end() && it->second.is_running);
|
|
183
|
+
}
|
|
184
|
+
|
|
185
|
+
std::vector<MCPResource>
|
|
186
|
+
MCPService::list_resources(const std::string &server_name) {
|
|
187
|
+
std::vector<MCPResource> resources;
|
|
188
|
+
|
|
189
|
+
if (!is_server_running(server_name)) {
|
|
190
|
+
if (!start_mcp_server(server_name)) {
|
|
191
|
+
return resources;
|
|
192
|
+
}
|
|
193
|
+
}
|
|
194
|
+
|
|
195
|
+
nlohmann::json request = create_mcp_request("resources/list");
|
|
196
|
+
nlohmann::json response = send_mcp_request(server_name, request);
|
|
197
|
+
|
|
198
|
+
if (response.contains("result") && response["result"].is_array()) {
|
|
199
|
+
for (const auto &resource_json : response["result"]) {
|
|
200
|
+
MCPResource resource;
|
|
201
|
+
resource.uri = resource_json.value("uri", "");
|
|
202
|
+
resource.name = resource_json.value("name", "");
|
|
203
|
+
resource.description = resource_json.value("description", "");
|
|
204
|
+
resource.mime_type = resource_json.value("mimeType", "");
|
|
205
|
+
if (resource_json.contains("metadata")) {
|
|
206
|
+
resource.metadata = resource_json["metadata"];
|
|
207
|
+
}
|
|
208
|
+
resources.push_back(resource);
|
|
209
|
+
}
|
|
210
|
+
}
|
|
211
|
+
|
|
212
|
+
return resources;
|
|
213
|
+
}
|
|
214
|
+
|
|
215
|
+
std::string MCPService::read_resource(const std::string &server_name,
|
|
216
|
+
const std::string &uri) {
|
|
217
|
+
if (!is_server_running(server_name)) {
|
|
218
|
+
if (!start_mcp_server(server_name)) {
|
|
219
|
+
return "Error: Server not available";
|
|
220
|
+
}
|
|
221
|
+
}
|
|
222
|
+
|
|
223
|
+
nlohmann::json params;
|
|
224
|
+
params["uri"] = uri;
|
|
225
|
+
|
|
226
|
+
nlohmann::json request = create_mcp_request("resources/read", params);
|
|
227
|
+
nlohmann::json response = send_mcp_request(server_name, request);
|
|
228
|
+
|
|
229
|
+
if (response.contains("result") && response["result"].contains("contents")) {
|
|
230
|
+
auto contents = response["result"]["contents"];
|
|
231
|
+
if (contents.is_array() && !contents.empty()) {
|
|
232
|
+
return contents[0].value("text", "");
|
|
233
|
+
}
|
|
234
|
+
}
|
|
235
|
+
|
|
236
|
+
return "Error: Failed to read resource";
|
|
237
|
+
}
|
|
238
|
+
|
|
239
|
+
std::vector<MCPTool> MCPService::list_tools(const std::string &server_name) {
|
|
240
|
+
std::vector<MCPTool> tools;
|
|
241
|
+
|
|
242
|
+
if (!is_server_running(server_name)) {
|
|
243
|
+
if (!start_mcp_server(server_name)) {
|
|
244
|
+
return tools;
|
|
245
|
+
}
|
|
246
|
+
}
|
|
247
|
+
|
|
248
|
+
nlohmann::json request = create_mcp_request("tools/list");
|
|
249
|
+
nlohmann::json response = send_mcp_request(server_name, request);
|
|
250
|
+
|
|
251
|
+
if (response.contains("result") && response["result"].contains("tools") &&
|
|
252
|
+
response["result"]["tools"].is_array()) {
|
|
253
|
+
for (const auto &tool_json : response["result"]["tools"]) {
|
|
254
|
+
MCPTool tool;
|
|
255
|
+
tool.name = tool_json.value("name", "");
|
|
256
|
+
tool.description = tool_json.value("description", "");
|
|
257
|
+
if (tool_json.contains("inputSchema")) {
|
|
258
|
+
tool.input_schema = tool_json["inputSchema"];
|
|
259
|
+
}
|
|
260
|
+
tools.push_back(tool);
|
|
261
|
+
}
|
|
262
|
+
}
|
|
263
|
+
|
|
264
|
+
return tools;
|
|
265
|
+
}
|
|
266
|
+
|
|
267
|
+
nlohmann::json MCPService::call_tool(const std::string &server_name,
|
|
268
|
+
const std::string &tool_name,
|
|
269
|
+
const nlohmann::json &arguments) {
|
|
270
|
+
if (!is_server_running(server_name)) {
|
|
271
|
+
if (!start_mcp_server(server_name)) {
|
|
272
|
+
return nlohmann::json{{"error", "Server not available"}};
|
|
273
|
+
}
|
|
274
|
+
}
|
|
275
|
+
|
|
276
|
+
nlohmann::json params;
|
|
277
|
+
params["name"] = tool_name;
|
|
278
|
+
params["arguments"] = arguments;
|
|
279
|
+
|
|
280
|
+
nlohmann::json request = create_mcp_request("tools/call", params);
|
|
281
|
+
nlohmann::json response = send_mcp_request(server_name, request);
|
|
282
|
+
|
|
283
|
+
if (response.contains("result")) {
|
|
284
|
+
return response["result"];
|
|
285
|
+
}
|
|
286
|
+
|
|
287
|
+
return nlohmann::json{{"error", "Tool call failed"}};
|
|
288
|
+
}
|
|
289
|
+
|
|
290
|
+
std::vector<MCPPrompt>
|
|
291
|
+
MCPService::list_prompts(const std::string &server_name) {
|
|
292
|
+
std::vector<MCPPrompt> prompts;
|
|
293
|
+
|
|
294
|
+
if (!is_server_running(server_name)) {
|
|
295
|
+
if (!start_mcp_server(server_name)) {
|
|
296
|
+
return prompts;
|
|
297
|
+
}
|
|
298
|
+
}
|
|
299
|
+
|
|
300
|
+
nlohmann::json request = create_mcp_request("prompts/list");
|
|
301
|
+
nlohmann::json response = send_mcp_request(server_name, request);
|
|
302
|
+
|
|
303
|
+
if (response.contains("result") && response["result"].contains("prompts") &&
|
|
304
|
+
response["result"]["prompts"].is_array()) {
|
|
305
|
+
for (const auto &prompt_json : response["result"]["prompts"]) {
|
|
306
|
+
MCPPrompt prompt;
|
|
307
|
+
prompt.name = prompt_json.value("name", "");
|
|
308
|
+
prompt.description = prompt_json.value("description", "");
|
|
309
|
+
if (prompt_json.contains("arguments") &&
|
|
310
|
+
prompt_json["arguments"].is_array()) {
|
|
311
|
+
for (const auto &arg : prompt_json["arguments"]) {
|
|
312
|
+
if (arg.contains("name")) {
|
|
313
|
+
prompt.arguments.push_back(arg["name"]);
|
|
314
|
+
}
|
|
315
|
+
}
|
|
316
|
+
}
|
|
317
|
+
prompts.push_back(prompt);
|
|
318
|
+
}
|
|
319
|
+
}
|
|
320
|
+
|
|
321
|
+
return prompts;
|
|
322
|
+
}
|
|
323
|
+
|
|
324
|
+
std::string MCPService::get_prompt(const std::string &server_name,
|
|
325
|
+
const std::string &prompt_name,
|
|
326
|
+
const nlohmann::json &arguments) {
|
|
327
|
+
if (!is_server_running(server_name)) {
|
|
328
|
+
if (!start_mcp_server(server_name)) {
|
|
329
|
+
return "Error: Server not available";
|
|
330
|
+
}
|
|
331
|
+
}
|
|
332
|
+
|
|
333
|
+
nlohmann::json params;
|
|
334
|
+
params["name"] = prompt_name;
|
|
335
|
+
params["arguments"] = arguments;
|
|
336
|
+
|
|
337
|
+
nlohmann::json request = create_mcp_request("prompts/get", params);
|
|
338
|
+
nlohmann::json response = send_mcp_request(server_name, request);
|
|
339
|
+
|
|
340
|
+
if (response.contains("result") && response["result"].contains("messages")) {
|
|
341
|
+
std::string prompt_text;
|
|
342
|
+
for (const auto &message : response["result"]["messages"]) {
|
|
343
|
+
if (message.contains("content") && message["content"].contains("text")) {
|
|
344
|
+
prompt_text += message["content"]["text"].get<std::string>() + "\n";
|
|
345
|
+
}
|
|
346
|
+
}
|
|
347
|
+
return prompt_text;
|
|
348
|
+
}
|
|
349
|
+
|
|
350
|
+
return "Error: Failed to get prompt";
|
|
351
|
+
}
|
|
352
|
+
|
|
353
|
+
bool MCPService::load_server_config() {
|
|
354
|
+
try {
|
|
355
|
+
std::string config_path = get_mcp_config_path();
|
|
356
|
+
if (!std::filesystem::exists(config_path)) {
|
|
357
|
+
add_default_servers();
|
|
358
|
+
return true;
|
|
359
|
+
}
|
|
360
|
+
|
|
361
|
+
std::ifstream file(config_path);
|
|
362
|
+
nlohmann::json config;
|
|
363
|
+
file >> config;
|
|
364
|
+
|
|
365
|
+
servers.clear();
|
|
366
|
+
|
|
367
|
+
if (config.contains("servers") && config["servers"].is_object()) {
|
|
368
|
+
for (const auto &[name, server_json] : config["servers"].items()) {
|
|
369
|
+
MCPServer server;
|
|
370
|
+
server.name = name;
|
|
371
|
+
server.executable = server_json.value("executable", "");
|
|
372
|
+
server.working_directory = server_json.value("working_directory", ".");
|
|
373
|
+
|
|
374
|
+
if (server_json.contains("args") && server_json["args"].is_array()) {
|
|
375
|
+
for (const auto &arg : server_json["args"]) {
|
|
376
|
+
server.args.push_back(arg.get<std::string>());
|
|
377
|
+
}
|
|
378
|
+
}
|
|
379
|
+
|
|
380
|
+
if (server_json.contains("env") && server_json["env"].is_object()) {
|
|
381
|
+
for (const auto &[key, value] : server_json["env"].items()) {
|
|
382
|
+
server.env_vars[key] = value.get<std::string>();
|
|
383
|
+
}
|
|
384
|
+
}
|
|
385
|
+
|
|
386
|
+
servers[name] = server;
|
|
387
|
+
}
|
|
388
|
+
}
|
|
389
|
+
|
|
390
|
+
return true;
|
|
391
|
+
|
|
392
|
+
} catch (const std::exception &e) {
|
|
393
|
+
std::cerr << "Failed to load MCP server config: " << e.what() << std::endl;
|
|
394
|
+
add_default_servers();
|
|
395
|
+
return false;
|
|
396
|
+
}
|
|
397
|
+
}
|
|
398
|
+
|
|
399
|
+
bool MCPService::save_server_config() {
|
|
400
|
+
try {
|
|
401
|
+
ensure_mcp_directory();
|
|
402
|
+
|
|
403
|
+
nlohmann::json config;
|
|
404
|
+
config["servers"] = nlohmann::json::object();
|
|
405
|
+
|
|
406
|
+
for (const auto &[name, server] : servers) {
|
|
407
|
+
nlohmann::json server_json;
|
|
408
|
+
server_json["executable"] = server.executable;
|
|
409
|
+
server_json["working_directory"] = server.working_directory;
|
|
410
|
+
server_json["args"] = server.args;
|
|
411
|
+
server_json["env"] = server.env_vars;
|
|
412
|
+
|
|
413
|
+
config["servers"][name] = server_json;
|
|
414
|
+
}
|
|
415
|
+
|
|
416
|
+
std::ofstream file(get_mcp_config_path());
|
|
417
|
+
file << config.dump(2);
|
|
418
|
+
|
|
419
|
+
return true;
|
|
420
|
+
|
|
421
|
+
} catch (const std::exception &e) {
|
|
422
|
+
std::cerr << "Failed to save MCP server config: " << e.what() << std::endl;
|
|
423
|
+
return false;
|
|
424
|
+
}
|
|
425
|
+
}
|
|
426
|
+
|
|
427
|
+
void MCPService::add_default_servers() {
|
|
428
|
+
// Add some example MCP servers
|
|
429
|
+
MCPServer filesystem_server;
|
|
430
|
+
filesystem_server.name = "filesystem";
|
|
431
|
+
filesystem_server.executable = "npx";
|
|
432
|
+
filesystem_server.args = {"@modelcontextprotocol/server-filesystem", "."};
|
|
433
|
+
filesystem_server.working_directory = ".";
|
|
434
|
+
servers["filesystem"] = filesystem_server;
|
|
435
|
+
|
|
436
|
+
MCPServer git_server;
|
|
437
|
+
git_server.name = "git";
|
|
438
|
+
git_server.executable = "npx";
|
|
439
|
+
git_server.args = {"@modelcontextprotocol/server-git", "."};
|
|
440
|
+
git_server.working_directory = ".";
|
|
441
|
+
servers["git"] = git_server;
|
|
442
|
+
|
|
443
|
+
save_server_config();
|
|
444
|
+
}
|
|
445
|
+
|
|
446
|
+
bool MCPService::ping_server(const std::string &server_name) {
|
|
447
|
+
if (!is_server_running(server_name)) {
|
|
448
|
+
return false;
|
|
449
|
+
}
|
|
450
|
+
|
|
451
|
+
nlohmann::json request = create_mcp_request("ping");
|
|
452
|
+
nlohmann::json response = send_mcp_request(server_name, request);
|
|
453
|
+
|
|
454
|
+
return response.contains("result") && response["result"] == "pong";
|
|
455
|
+
}
|
|
456
|
+
|
|
457
|
+
std::string MCPService::get_server_status(const std::string &server_name) {
|
|
458
|
+
auto it = servers.find(server_name);
|
|
459
|
+
if (it == servers.end()) {
|
|
460
|
+
return "Not registered";
|
|
461
|
+
}
|
|
462
|
+
|
|
463
|
+
if (!it->second.is_running) {
|
|
464
|
+
return "Stopped";
|
|
465
|
+
}
|
|
466
|
+
|
|
467
|
+
if (ping_server(server_name)) {
|
|
468
|
+
return "Running";
|
|
469
|
+
}
|
|
470
|
+
return "Unresponsive";
|
|
471
|
+
}
|
|
472
|
+
|
|
473
|
+
void MCPService::cleanup_dead_servers() {
|
|
474
|
+
for (auto &[name, server] : servers) {
|
|
475
|
+
if (server.is_running && !ping_server(name)) {
|
|
476
|
+
server.is_running = false;
|
|
477
|
+
server.process_id = -1;
|
|
478
|
+
}
|
|
479
|
+
}
|
|
480
|
+
}
|
|
481
|
+
} // namespace Services
|