Skip to content

Commit ed294c2

Browse files
authored
[lldb] Move MCP protocol into its own library (NFC) (#152059)
This PR moves the MCP protocol code into its own library (`lldbProtocolMCP`) so the code can be shared between the `ProtocolServerMCP` plugin in LLDB as well as `lldb-mcp`. The goal is to do the same thing for DAP (which, for now, would be used exclusively from `lldb-dap`). To make it clear that it's neither part of the `lldb` nor the `lldb_private` namespace, I created a new `lldb_protocol` namespace. Depending on how much code would be reused by lldb-dap, we may move more code into the protocol library.
1 parent 1b651bf commit ed294c2

File tree

19 files changed

+167
-140
lines changed

19 files changed

+167
-140
lines changed

lldb/source/Plugins/Protocol/MCP/Protocol.h renamed to lldb/include/lldb/Protocol/MCP/Protocol.h

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -11,15 +11,15 @@
1111
//
1212
//===----------------------------------------------------------------------===//
1313

14-
#ifndef LLDB_PLUGINS_PROTOCOL_MCP_PROTOCOL_H
15-
#define LLDB_PLUGINS_PROTOCOL_MCP_PROTOCOL_H
14+
#ifndef LLDB_PROTOCOL_MCP_PROTOCOL_H
15+
#define LLDB_PROTOCOL_MCP_PROTOCOL_H
1616

1717
#include "llvm/Support/JSON.h"
1818
#include <optional>
1919
#include <string>
2020
#include <variant>
2121

22-
namespace lldb_private::mcp::protocol {
22+
namespace lldb_protocol::mcp {
2323

2424
static llvm::StringLiteral kVersion = "2024-11-05";
2525

@@ -183,6 +183,6 @@ llvm::json::Value toJSON(const Message &);
183183

184184
using ToolArguments = std::variant<std::monostate, llvm::json::Value>;
185185

186-
} // namespace lldb_private::mcp::protocol
186+
} // namespace lldb_protocol::mcp
187187

188188
#endif

lldb/source/CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ add_subdirectory(Host)
1010
add_subdirectory(Initialization)
1111
add_subdirectory(Interpreter)
1212
add_subdirectory(Plugins)
13+
add_subdirectory(Protocol)
1314
add_subdirectory(Symbol)
1415
add_subdirectory(Target)
1516
add_subdirectory(Utility)

lldb/source/Plugins/Protocol/MCP/CMakeLists.txt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,5 @@
11
add_lldb_library(lldbPluginProtocolServerMCP PLUGIN
22
MCPError.cpp
3-
Protocol.cpp
43
ProtocolServerMCP.cpp
54
Resource.cpp
65
Tool.cpp
@@ -10,5 +9,6 @@ add_lldb_library(lldbPluginProtocolServerMCP PLUGIN
109

1110
LINK_LIBS
1211
lldbHost
12+
lldbProtocolMCP
1313
lldbUtility
1414
)

lldb/source/Plugins/Protocol/MCP/MCPError.cpp

Lines changed: 3 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@
1111
#include "llvm/Support/raw_ostream.h"
1212
#include <system_error>
1313

14-
namespace lldb_private::mcp {
14+
using namespace lldb_private::mcp;
1515

1616
char MCPError::ID;
1717
char UnsupportedURI::ID;
@@ -25,8 +25,8 @@ std::error_code MCPError::convertToErrorCode() const {
2525
return llvm::inconvertibleErrorCode();
2626
}
2727

28-
protocol::Error MCPError::toProtcolError() const {
29-
protocol::Error error;
28+
lldb_protocol::mcp::Error MCPError::toProtcolError() const {
29+
lldb_protocol::mcp::Error error;
3030
error.error.code = m_error_code;
3131
error.error.message = m_message;
3232
return error;
@@ -41,5 +41,3 @@ void UnsupportedURI::log(llvm::raw_ostream &OS) const {
4141
std::error_code UnsupportedURI::convertToErrorCode() const {
4242
return llvm::inconvertibleErrorCode();
4343
}
44-
45-
} // namespace lldb_private::mcp

lldb/source/Plugins/Protocol/MCP/MCPError.h

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@
66
//
77
//===----------------------------------------------------------------------===//
88

9-
#include "Protocol.h"
9+
#include "lldb/Protocol/MCP/Protocol.h"
1010
#include "llvm/Support/Error.h"
1111
#include "llvm/Support/FormatVariadic.h"
1212
#include <string>
@@ -24,7 +24,7 @@ class MCPError : public llvm::ErrorInfo<MCPError> {
2424

2525
const std::string &getMessage() const { return m_message; }
2626

27-
protocol::Error toProtcolError() const;
27+
lldb_protocol::mcp::Error toProtcolError() const;
2828

2929
static constexpr int64_t kResourceNotFound = -32002;
3030
static constexpr int64_t kInternalError = -32603;

lldb/source/Plugins/Protocol/MCP/ProtocolServerMCP.cpp

Lines changed: 48 additions & 42 deletions
Original file line numberDiff line numberDiff line change
@@ -42,10 +42,11 @@ ProtocolServerMCP::ProtocolServerMCP() : ProtocolServer() {
4242
AddRequestHandler("resources/read",
4343
std::bind(&ProtocolServerMCP::ResourcesReadHandler, this,
4444
std::placeholders::_1));
45-
AddNotificationHandler(
46-
"notifications/initialized", [](const protocol::Notification &) {
47-
LLDB_LOG(GetLog(LLDBLog::Host), "MCP initialization complete");
48-
});
45+
AddNotificationHandler("notifications/initialized",
46+
[](const lldb_protocol::mcp::Notification &) {
47+
LLDB_LOG(GetLog(LLDBLog::Host),
48+
"MCP initialization complete");
49+
});
4950

5051
AddTool(
5152
std::make_unique<CommandTool>("lldb_command", "Run an lldb command."));
@@ -72,11 +73,11 @@ llvm::StringRef ProtocolServerMCP::GetPluginDescriptionStatic() {
7273
return "MCP Server.";
7374
}
7475

75-
llvm::Expected<protocol::Response>
76-
ProtocolServerMCP::Handle(protocol::Request request) {
76+
llvm::Expected<lldb_protocol::mcp::Response>
77+
ProtocolServerMCP::Handle(lldb_protocol::mcp::Request request) {
7778
auto it = m_request_handlers.find(request.method);
7879
if (it != m_request_handlers.end()) {
79-
llvm::Expected<protocol::Response> response = it->second(request);
80+
llvm::Expected<lldb_protocol::mcp::Response> response = it->second(request);
8081
if (!response)
8182
return response;
8283
response->id = request.id;
@@ -87,7 +88,7 @@ ProtocolServerMCP::Handle(protocol::Request request) {
8788
llvm::formatv("no handler for request: {0}", request.method).str());
8889
}
8990

90-
void ProtocolServerMCP::Handle(protocol::Notification notification) {
91+
void ProtocolServerMCP::Handle(lldb_protocol::mcp::Notification notification) {
9192
auto it = m_notification_handlers.find(notification.method);
9293
if (it != m_notification_handlers.end()) {
9394
it->second(notification);
@@ -133,7 +134,7 @@ llvm::Error ProtocolServerMCP::ReadCallback(Client &client) {
133134

134135
for (std::string::size_type pos;
135136
(pos = client.buffer.find('\n')) != std::string::npos;) {
136-
llvm::Expected<std::optional<protocol::Message>> message =
137+
llvm::Expected<std::optional<lldb_protocol::mcp::Message>> message =
137138
HandleData(StringRef(client.buffer.data(), pos));
138139
client.buffer = client.buffer.erase(0, pos + 1);
139140
if (!message)
@@ -208,19 +209,19 @@ llvm::Error ProtocolServerMCP::Stop() {
208209
return llvm::Error::success();
209210
}
210211

211-
llvm::Expected<std::optional<protocol::Message>>
212+
llvm::Expected<std::optional<lldb_protocol::mcp::Message>>
212213
ProtocolServerMCP::HandleData(llvm::StringRef data) {
213-
auto message = llvm::json::parse<protocol::Message>(/*JSON=*/data);
214+
auto message = llvm::json::parse<lldb_protocol::mcp::Message>(/*JSON=*/data);
214215
if (!message)
215216
return message.takeError();
216217

217-
if (const protocol::Request *request =
218-
std::get_if<protocol::Request>(&(*message))) {
219-
llvm::Expected<protocol::Response> response = Handle(*request);
218+
if (const lldb_protocol::mcp::Request *request =
219+
std::get_if<lldb_protocol::mcp::Request>(&(*message))) {
220+
llvm::Expected<lldb_protocol::mcp::Response> response = Handle(*request);
220221

221222
// Handle failures by converting them into an Error message.
222223
if (!response) {
223-
protocol::Error protocol_error;
224+
lldb_protocol::mcp::Error protocol_error;
224225
llvm::handleAllErrors(
225226
response.takeError(),
226227
[&](const MCPError &err) { protocol_error = err.toProtcolError(); },
@@ -235,23 +236,23 @@ ProtocolServerMCP::HandleData(llvm::StringRef data) {
235236
return *response;
236237
}
237238

238-
if (const protocol::Notification *notification =
239-
std::get_if<protocol::Notification>(&(*message))) {
239+
if (const lldb_protocol::mcp::Notification *notification =
240+
std::get_if<lldb_protocol::mcp::Notification>(&(*message))) {
240241
Handle(*notification);
241242
return std::nullopt;
242243
}
243244

244-
if (std::get_if<protocol::Error>(&(*message)))
245+
if (std::get_if<lldb_protocol::mcp::Error>(&(*message)))
245246
return llvm::createStringError("unexpected MCP message: error");
246247

247-
if (std::get_if<protocol::Response>(&(*message)))
248+
if (std::get_if<lldb_protocol::mcp::Response>(&(*message)))
248249
return llvm::createStringError("unexpected MCP message: response");
249250

250251
llvm_unreachable("all message types handled");
251252
}
252253

253-
protocol::Capabilities ProtocolServerMCP::GetCapabilities() {
254-
protocol::Capabilities capabilities;
254+
lldb_protocol::mcp::Capabilities ProtocolServerMCP::GetCapabilities() {
255+
lldb_protocol::mcp::Capabilities capabilities;
255256
capabilities.tools.listChanged = true;
256257
// FIXME: Support sending notifications when a debugger/target are
257258
// added/removed.
@@ -288,20 +289,22 @@ void ProtocolServerMCP::AddNotificationHandler(llvm::StringRef method,
288289
m_notification_handlers[method] = std::move(handler);
289290
}
290291

291-
llvm::Expected<protocol::Response>
292-
ProtocolServerMCP::InitializeHandler(const protocol::Request &request) {
293-
protocol::Response response;
292+
llvm::Expected<lldb_protocol::mcp::Response>
293+
ProtocolServerMCP::InitializeHandler(
294+
const lldb_protocol::mcp::Request &request) {
295+
lldb_protocol::mcp::Response response;
294296
response.result.emplace(llvm::json::Object{
295-
{"protocolVersion", protocol::kVersion},
297+
{"protocolVersion", lldb_protocol::mcp::kVersion},
296298
{"capabilities", GetCapabilities()},
297299
{"serverInfo",
298300
llvm::json::Object{{"name", kName}, {"version", kVersion}}}});
299301
return response;
300302
}
301303

302-
llvm::Expected<protocol::Response>
303-
ProtocolServerMCP::ToolsListHandler(const protocol::Request &request) {
304-
protocol::Response response;
304+
llvm::Expected<lldb_protocol::mcp::Response>
305+
ProtocolServerMCP::ToolsListHandler(
306+
const lldb_protocol::mcp::Request &request) {
307+
lldb_protocol::mcp::Response response;
305308

306309
llvm::json::Array tools;
307310
for (const auto &tool : m_tools)
@@ -312,9 +315,10 @@ ProtocolServerMCP::ToolsListHandler(const protocol::Request &request) {
312315
return response;
313316
}
314317

315-
llvm::Expected<protocol::Response>
316-
ProtocolServerMCP::ToolsCallHandler(const protocol::Request &request) {
317-
protocol::Response response;
318+
llvm::Expected<lldb_protocol::mcp::Response>
319+
ProtocolServerMCP::ToolsCallHandler(
320+
const lldb_protocol::mcp::Request &request) {
321+
lldb_protocol::mcp::Response response;
318322

319323
if (!request.params)
320324
return llvm::createStringError("no tool parameters");
@@ -335,11 +339,11 @@ ProtocolServerMCP::ToolsCallHandler(const protocol::Request &request) {
335339
if (it == m_tools.end())
336340
return llvm::createStringError(llvm::formatv("no tool \"{0}\"", tool_name));
337341

338-
protocol::ToolArguments tool_args;
342+
lldb_protocol::mcp::ToolArguments tool_args;
339343
if (const json::Value *args = param_obj->get("arguments"))
340344
tool_args = *args;
341345

342-
llvm::Expected<protocol::TextResult> text_result =
346+
llvm::Expected<lldb_protocol::mcp::TextResult> text_result =
343347
it->second->Call(tool_args);
344348
if (!text_result)
345349
return text_result.takeError();
@@ -349,16 +353,17 @@ ProtocolServerMCP::ToolsCallHandler(const protocol::Request &request) {
349353
return response;
350354
}
351355

352-
llvm::Expected<protocol::Response>
353-
ProtocolServerMCP::ResourcesListHandler(const protocol::Request &request) {
354-
protocol::Response response;
356+
llvm::Expected<lldb_protocol::mcp::Response>
357+
ProtocolServerMCP::ResourcesListHandler(
358+
const lldb_protocol::mcp::Request &request) {
359+
lldb_protocol::mcp::Response response;
355360

356361
llvm::json::Array resources;
357362

358363
std::lock_guard<std::mutex> guard(m_server_mutex);
359364
for (std::unique_ptr<ResourceProvider> &resource_provider_up :
360365
m_resource_providers) {
361-
for (const protocol::Resource &resource :
366+
for (const lldb_protocol::mcp::Resource &resource :
362367
resource_provider_up->GetResources())
363368
resources.push_back(resource);
364369
}
@@ -368,9 +373,10 @@ ProtocolServerMCP::ResourcesListHandler(const protocol::Request &request) {
368373
return response;
369374
}
370375

371-
llvm::Expected<protocol::Response>
372-
ProtocolServerMCP::ResourcesReadHandler(const protocol::Request &request) {
373-
protocol::Response response;
376+
llvm::Expected<lldb_protocol::mcp::Response>
377+
ProtocolServerMCP::ResourcesReadHandler(
378+
const lldb_protocol::mcp::Request &request) {
379+
lldb_protocol::mcp::Response response;
374380

375381
if (!request.params)
376382
return llvm::createStringError("no resource parameters");
@@ -390,7 +396,7 @@ ProtocolServerMCP::ResourcesReadHandler(const protocol::Request &request) {
390396
std::lock_guard<std::mutex> guard(m_server_mutex);
391397
for (std::unique_ptr<ResourceProvider> &resource_provider_up :
392398
m_resource_providers) {
393-
llvm::Expected<protocol::ResourceResult> result =
399+
llvm::Expected<lldb_protocol::mcp::ResourceResult> result =
394400
resource_provider_up->ReadResource(uri_str);
395401
if (result.errorIsA<UnsupportedURI>()) {
396402
llvm::consumeError(result.takeError());
@@ -399,7 +405,7 @@ ProtocolServerMCP::ResourcesReadHandler(const protocol::Request &request) {
399405
if (!result)
400406
return result.takeError();
401407

402-
protocol::Response response;
408+
lldb_protocol::mcp::Response response;
403409
response.result.emplace(std::move(*result));
404410
return response;
405411
}

lldb/source/Plugins/Protocol/MCP/ProtocolServerMCP.h

Lines changed: 20 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -9,12 +9,12 @@
99
#ifndef LLDB_PLUGINS_PROTOCOL_MCP_PROTOCOLSERVERMCP_H
1010
#define LLDB_PLUGINS_PROTOCOL_MCP_PROTOCOLSERVERMCP_H
1111

12-
#include "Protocol.h"
1312
#include "Resource.h"
1413
#include "Tool.h"
1514
#include "lldb/Core/ProtocolServer.h"
1615
#include "lldb/Host/MainLoop.h"
1716
#include "lldb/Host/Socket.h"
17+
#include "lldb/Protocol/MCP/Protocol.h"
1818
#include "llvm/ADT/StringMap.h"
1919
#include <thread>
2020

@@ -41,10 +41,11 @@ class ProtocolServerMCP : public ProtocolServer {
4141
Socket *GetSocket() const override { return m_listener.get(); }
4242

4343
protected:
44-
using RequestHandler = std::function<llvm::Expected<protocol::Response>(
45-
const protocol::Request &)>;
44+
using RequestHandler =
45+
std::function<llvm::Expected<lldb_protocol::mcp::Response>(
46+
const lldb_protocol::mcp::Request &)>;
4647
using NotificationHandler =
47-
std::function<void(const protocol::Notification &)>;
48+
std::function<void(const lldb_protocol::mcp::Notification &)>;
4849

4950
void AddTool(std::unique_ptr<Tool> tool);
5051
void AddResourceProvider(std::unique_ptr<ResourceProvider> resource_provider);
@@ -56,26 +57,27 @@ class ProtocolServerMCP : public ProtocolServer {
5657
private:
5758
void AcceptCallback(std::unique_ptr<Socket> socket);
5859

59-
llvm::Expected<std::optional<protocol::Message>>
60+
llvm::Expected<std::optional<lldb_protocol::mcp::Message>>
6061
HandleData(llvm::StringRef data);
6162

62-
llvm::Expected<protocol::Response> Handle(protocol::Request request);
63-
void Handle(protocol::Notification notification);
63+
llvm::Expected<lldb_protocol::mcp::Response>
64+
Handle(lldb_protocol::mcp::Request request);
65+
void Handle(lldb_protocol::mcp::Notification notification);
6466

65-
llvm::Expected<protocol::Response>
66-
InitializeHandler(const protocol::Request &);
67+
llvm::Expected<lldb_protocol::mcp::Response>
68+
InitializeHandler(const lldb_protocol::mcp::Request &);
6769

68-
llvm::Expected<protocol::Response>
69-
ToolsListHandler(const protocol::Request &);
70-
llvm::Expected<protocol::Response>
71-
ToolsCallHandler(const protocol::Request &);
70+
llvm::Expected<lldb_protocol::mcp::Response>
71+
ToolsListHandler(const lldb_protocol::mcp::Request &);
72+
llvm::Expected<lldb_protocol::mcp::Response>
73+
ToolsCallHandler(const lldb_protocol::mcp::Request &);
7274

73-
llvm::Expected<protocol::Response>
74-
ResourcesListHandler(const protocol::Request &);
75-
llvm::Expected<protocol::Response>
76-
ResourcesReadHandler(const protocol::Request &);
75+
llvm::Expected<lldb_protocol::mcp::Response>
76+
ResourcesListHandler(const lldb_protocol::mcp::Request &);
77+
llvm::Expected<lldb_protocol::mcp::Response>
78+
ResourcesReadHandler(const lldb_protocol::mcp::Request &);
7779

78-
protocol::Capabilities GetCapabilities();
80+
lldb_protocol::mcp::Capabilities GetCapabilities();
7981

8082
llvm::StringLiteral kName = "lldb-mcp";
8183
llvm::StringLiteral kVersion = "0.1.0";

0 commit comments

Comments
 (0)