@@ -27,25 +27,12 @@ using namespace llvm;
27
27
LLDB_PLUGIN_DEFINE (ProtocolServerMCP)
28
28
29
29
static constexpr size_t kChunkSize = 1024;
30
+ static constexpr llvm::StringLiteral kName = " lldb-mcp" ;
31
+ static constexpr llvm::StringLiteral kVersion = " 0.1.0" ;
30
32
31
- ProtocolServerMCP::ProtocolServerMCP () : ProtocolServer() {
32
- AddRequestHandler (" initialize" ,
33
- std::bind (&ProtocolServerMCP::InitializeHandler, this ,
34
- std::placeholders::_1));
35
-
36
- AddRequestHandler (" tools/list" ,
37
- std::bind (&ProtocolServerMCP::ToolsListHandler, this ,
38
- std::placeholders::_1));
39
- AddRequestHandler (" tools/call" ,
40
- std::bind (&ProtocolServerMCP::ToolsCallHandler, this ,
41
- std::placeholders::_1));
42
-
43
- AddRequestHandler (" resources/list" ,
44
- std::bind (&ProtocolServerMCP::ResourcesListHandler, this ,
45
- std::placeholders::_1));
46
- AddRequestHandler (" resources/read" ,
47
- std::bind (&ProtocolServerMCP::ResourcesReadHandler, this ,
48
- std::placeholders::_1));
33
+ ProtocolServerMCP::ProtocolServerMCP ()
34
+ : ProtocolServer(),
35
+ lldb_protocol::mcp::Server(std::string(kName ), std::string(kVersion )) {
49
36
AddNotificationHandler (" notifications/initialized" ,
50
37
[](const lldb_protocol::mcp::Notification &) {
51
38
LLDB_LOG (GetLog (LLDBLog::Host),
@@ -77,32 +64,6 @@ llvm::StringRef ProtocolServerMCP::GetPluginDescriptionStatic() {
77
64
return " MCP Server." ;
78
65
}
79
66
80
- llvm::Expected<lldb_protocol::mcp::Response>
81
- ProtocolServerMCP::Handle (lldb_protocol::mcp::Request request) {
82
- auto it = m_request_handlers.find (request.method );
83
- if (it != m_request_handlers.end ()) {
84
- llvm::Expected<lldb_protocol::mcp::Response> response = it->second (request);
85
- if (!response)
86
- return response;
87
- response->id = request.id ;
88
- return *response;
89
- }
90
-
91
- return make_error<MCPError>(
92
- llvm::formatv (" no handler for request: {0}" , request.method ).str ());
93
- }
94
-
95
- void ProtocolServerMCP::Handle (lldb_protocol::mcp::Notification notification) {
96
- auto it = m_notification_handlers.find (notification.method );
97
- if (it != m_notification_handlers.end ()) {
98
- it->second (notification);
99
- return ;
100
- }
101
-
102
- LLDB_LOG (GetLog (LLDBLog::Host), " MPC notification: {0} ({1})" ,
103
- notification.method , notification.params );
104
- }
105
-
106
67
void ProtocolServerMCP::AcceptCallback (std::unique_ptr<Socket> socket) {
107
68
LLDB_LOG (GetLog (LLDBLog::Host), " New MCP client ({0}) connected" ,
108
69
m_clients.size () + 1 );
@@ -157,7 +118,7 @@ llvm::Error ProtocolServerMCP::ReadCallback(Client &client) {
157
118
}
158
119
159
120
llvm::Error ProtocolServerMCP::Start (ProtocolServer::Connection connection) {
160
- std::lock_guard<std::mutex> guard (m_server_mutex );
121
+ std::lock_guard<std::mutex> guard (m_mutex );
161
122
162
123
if (m_running)
163
124
return llvm::createStringError (" the MCP server is already running" );
@@ -189,7 +150,7 @@ llvm::Error ProtocolServerMCP::Start(ProtocolServer::Connection connection) {
189
150
190
151
llvm::Error ProtocolServerMCP::Stop () {
191
152
{
192
- std::lock_guard<std::mutex> guard (m_server_mutex );
153
+ std::lock_guard<std::mutex> guard (m_mutex );
193
154
if (!m_running)
194
155
return createStringError (" the MCP sever is not running" );
195
156
m_running = false ;
@@ -204,7 +165,7 @@ llvm::Error ProtocolServerMCP::Stop() {
204
165
m_loop_thread.join ();
205
166
206
167
{
207
- std::lock_guard<std::mutex> guard (m_server_mutex );
168
+ std::lock_guard<std::mutex> guard (m_mutex );
208
169
m_listener.reset ();
209
170
m_listen_handlers.clear ();
210
171
m_clients.clear ();
@@ -213,48 +174,6 @@ llvm::Error ProtocolServerMCP::Stop() {
213
174
return llvm::Error::success ();
214
175
}
215
176
216
- llvm::Expected<std::optional<lldb_protocol::mcp::Message>>
217
- ProtocolServerMCP::HandleData (llvm::StringRef data) {
218
- auto message = llvm::json::parse<lldb_protocol::mcp::Message>(/* JSON=*/ data);
219
- if (!message)
220
- return message.takeError ();
221
-
222
- if (const lldb_protocol::mcp::Request *request =
223
- std::get_if<lldb_protocol::mcp::Request>(&(*message))) {
224
- llvm::Expected<lldb_protocol::mcp::Response> response = Handle (*request);
225
-
226
- // Handle failures by converting them into an Error message.
227
- if (!response) {
228
- lldb_protocol::mcp::Error protocol_error;
229
- llvm::handleAllErrors (
230
- response.takeError (),
231
- [&](const MCPError &err) { protocol_error = err.toProtcolError (); },
232
- [&](const llvm::ErrorInfoBase &err) {
233
- protocol_error.error .code = MCPError::kInternalError ;
234
- protocol_error.error .message = err.message ();
235
- });
236
- protocol_error.id = request->id ;
237
- return protocol_error;
238
- }
239
-
240
- return *response;
241
- }
242
-
243
- if (const lldb_protocol::mcp::Notification *notification =
244
- std::get_if<lldb_protocol::mcp::Notification>(&(*message))) {
245
- Handle (*notification);
246
- return std::nullopt;
247
- }
248
-
249
- if (std::get_if<lldb_protocol::mcp::Error>(&(*message)))
250
- return llvm::createStringError (" unexpected MCP message: error" );
251
-
252
- if (std::get_if<lldb_protocol::mcp::Response>(&(*message)))
253
- return llvm::createStringError (" unexpected MCP message: response" );
254
-
255
- llvm_unreachable (" all message types handled" );
256
- }
257
-
258
177
lldb_protocol::mcp::Capabilities ProtocolServerMCP::GetCapabilities () {
259
178
lldb_protocol::mcp::Capabilities capabilities;
260
179
capabilities.tools .listChanged = true ;
@@ -263,158 +182,3 @@ lldb_protocol::mcp::Capabilities ProtocolServerMCP::GetCapabilities() {
263
182
capabilities.resources .listChanged = false ;
264
183
return capabilities;
265
184
}
266
-
267
- void ProtocolServerMCP::AddTool (std::unique_ptr<Tool> tool) {
268
- std::lock_guard<std::mutex> guard (m_server_mutex);
269
-
270
- if (!tool)
271
- return ;
272
- m_tools[tool->GetName ()] = std::move (tool);
273
- }
274
-
275
- void ProtocolServerMCP::AddResourceProvider (
276
- std::unique_ptr<ResourceProvider> resource_provider) {
277
- std::lock_guard<std::mutex> guard (m_server_mutex);
278
-
279
- if (!resource_provider)
280
- return ;
281
- m_resource_providers.push_back (std::move (resource_provider));
282
- }
283
-
284
- void ProtocolServerMCP::AddRequestHandler (llvm::StringRef method,
285
- RequestHandler handler) {
286
- std::lock_guard<std::mutex> guard (m_server_mutex);
287
- m_request_handlers[method] = std::move (handler);
288
- }
289
-
290
- void ProtocolServerMCP::AddNotificationHandler (llvm::StringRef method,
291
- NotificationHandler handler) {
292
- std::lock_guard<std::mutex> guard (m_server_mutex);
293
- m_notification_handlers[method] = std::move (handler);
294
- }
295
-
296
- llvm::Expected<lldb_protocol::mcp::Response>
297
- ProtocolServerMCP::InitializeHandler (
298
- const lldb_protocol::mcp::Request &request) {
299
- lldb_protocol::mcp::Response response;
300
- response.result .emplace (llvm::json::Object{
301
- {" protocolVersion" , lldb_protocol::mcp::kVersion },
302
- {" capabilities" , GetCapabilities ()},
303
- {" serverInfo" ,
304
- llvm::json::Object{{" name" , kName }, {" version" , kVersion }}}});
305
- return response;
306
- }
307
-
308
- llvm::Expected<lldb_protocol::mcp::Response>
309
- ProtocolServerMCP::ToolsListHandler (
310
- const lldb_protocol::mcp::Request &request) {
311
- lldb_protocol::mcp::Response response;
312
-
313
- llvm::json::Array tools;
314
- for (const auto &tool : m_tools)
315
- tools.emplace_back (toJSON (tool.second ->GetDefinition ()));
316
-
317
- response.result .emplace (llvm::json::Object{{" tools" , std::move (tools)}});
318
-
319
- return response;
320
- }
321
-
322
- llvm::Expected<lldb_protocol::mcp::Response>
323
- ProtocolServerMCP::ToolsCallHandler (
324
- const lldb_protocol::mcp::Request &request) {
325
- lldb_protocol::mcp::Response response;
326
-
327
- if (!request.params )
328
- return llvm::createStringError (" no tool parameters" );
329
-
330
- const json::Object *param_obj = request.params ->getAsObject ();
331
- if (!param_obj)
332
- return llvm::createStringError (" no tool parameters" );
333
-
334
- const json::Value *name = param_obj->get (" name" );
335
- if (!name)
336
- return llvm::createStringError (" no tool name" );
337
-
338
- llvm::StringRef tool_name = name->getAsString ().value_or (" " );
339
- if (tool_name.empty ())
340
- return llvm::createStringError (" no tool name" );
341
-
342
- auto it = m_tools.find (tool_name);
343
- if (it == m_tools.end ())
344
- return llvm::createStringError (llvm::formatv (" no tool \" {0}\" " , tool_name));
345
-
346
- lldb_protocol::mcp::ToolArguments tool_args;
347
- if (const json::Value *args = param_obj->get (" arguments" ))
348
- tool_args = *args;
349
-
350
- llvm::Expected<lldb_protocol::mcp::TextResult> text_result =
351
- it->second ->Call (tool_args);
352
- if (!text_result)
353
- return text_result.takeError ();
354
-
355
- response.result .emplace (toJSON (*text_result));
356
-
357
- return response;
358
- }
359
-
360
- llvm::Expected<lldb_protocol::mcp::Response>
361
- ProtocolServerMCP::ResourcesListHandler (
362
- const lldb_protocol::mcp::Request &request) {
363
- lldb_protocol::mcp::Response response;
364
-
365
- llvm::json::Array resources;
366
-
367
- std::lock_guard<std::mutex> guard (m_server_mutex);
368
- for (std::unique_ptr<ResourceProvider> &resource_provider_up :
369
- m_resource_providers) {
370
- for (const lldb_protocol::mcp::Resource &resource :
371
- resource_provider_up->GetResources ())
372
- resources.push_back (resource);
373
- }
374
- response.result .emplace (
375
- llvm::json::Object{{" resources" , std::move (resources)}});
376
-
377
- return response;
378
- }
379
-
380
- llvm::Expected<lldb_protocol::mcp::Response>
381
- ProtocolServerMCP::ResourcesReadHandler (
382
- const lldb_protocol::mcp::Request &request) {
383
- lldb_protocol::mcp::Response response;
384
-
385
- if (!request.params )
386
- return llvm::createStringError (" no resource parameters" );
387
-
388
- const json::Object *param_obj = request.params ->getAsObject ();
389
- if (!param_obj)
390
- return llvm::createStringError (" no resource parameters" );
391
-
392
- const json::Value *uri = param_obj->get (" uri" );
393
- if (!uri)
394
- return llvm::createStringError (" no resource uri" );
395
-
396
- llvm::StringRef uri_str = uri->getAsString ().value_or (" " );
397
- if (uri_str.empty ())
398
- return llvm::createStringError (" no resource uri" );
399
-
400
- std::lock_guard<std::mutex> guard (m_server_mutex);
401
- for (std::unique_ptr<ResourceProvider> &resource_provider_up :
402
- m_resource_providers) {
403
- llvm::Expected<lldb_protocol::mcp::ResourceResult> result =
404
- resource_provider_up->ReadResource (uri_str);
405
- if (result.errorIsA <UnsupportedURI>()) {
406
- llvm::consumeError (result.takeError ());
407
- continue ;
408
- }
409
- if (!result)
410
- return result.takeError ();
411
-
412
- lldb_protocol::mcp::Response response;
413
- response.result .emplace (std::move (*result));
414
- return response;
415
- }
416
-
417
- return make_error<MCPError>(
418
- llvm::formatv (" no resource handler for uri: {0}" , uri_str).str (),
419
- MCPError::kResourceNotFound );
420
- }
0 commit comments