@@ -27,25 +27,12 @@ using namespace llvm;
2727LLDB_PLUGIN_DEFINE (ProtocolServerMCP)
2828
2929static constexpr size_t kChunkSize = 1024;
30+ static constexpr llvm::StringLiteral kName = " lldb-mcp" ;
31+ static constexpr llvm::StringLiteral kVersion = " 0.1.0" ;
3032
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 )) {
4936 AddNotificationHandler (" notifications/initialized" ,
5037 [](const lldb_protocol::mcp::Notification &) {
5138 LLDB_LOG (GetLog (LLDBLog::Host),
@@ -77,32 +64,6 @@ llvm::StringRef ProtocolServerMCP::GetPluginDescriptionStatic() {
7764 return " MCP Server." ;
7865}
7966
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-
10667void ProtocolServerMCP::AcceptCallback (std::unique_ptr<Socket> socket) {
10768 LLDB_LOG (GetLog (LLDBLog::Host), " New MCP client ({0}) connected" ,
10869 m_clients.size () + 1 );
@@ -157,7 +118,7 @@ llvm::Error ProtocolServerMCP::ReadCallback(Client &client) {
157118}
158119
159120llvm::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 );
161122
162123 if (m_running)
163124 return llvm::createStringError (" the MCP server is already running" );
@@ -189,7 +150,7 @@ llvm::Error ProtocolServerMCP::Start(ProtocolServer::Connection connection) {
189150
190151llvm::Error ProtocolServerMCP::Stop () {
191152 {
192- std::lock_guard<std::mutex> guard (m_server_mutex );
153+ std::lock_guard<std::mutex> guard (m_mutex );
193154 if (!m_running)
194155 return createStringError (" the MCP sever is not running" );
195156 m_running = false ;
@@ -204,7 +165,7 @@ llvm::Error ProtocolServerMCP::Stop() {
204165 m_loop_thread.join ();
205166
206167 {
207- std::lock_guard<std::mutex> guard (m_server_mutex );
168+ std::lock_guard<std::mutex> guard (m_mutex );
208169 m_listener.reset ();
209170 m_listen_handlers.clear ();
210171 m_clients.clear ();
@@ -213,48 +174,6 @@ llvm::Error ProtocolServerMCP::Stop() {
213174 return llvm::Error::success ();
214175}
215176
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-
258177lldb_protocol::mcp::Capabilities ProtocolServerMCP::GetCapabilities () {
259178 lldb_protocol::mcp::Capabilities capabilities;
260179 capabilities.tools .listChanged = true ;
@@ -263,158 +182,3 @@ lldb_protocol::mcp::Capabilities ProtocolServerMCP::GetCapabilities() {
263182 capabilities.resources .listChanged = false ;
264183 return capabilities;
265184}
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