summaryrefslogtreecommitdiff
path: root/lldb/source/Plugins/Protocol/MCP/ProtocolServerMCP.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'lldb/source/Plugins/Protocol/MCP/ProtocolServerMCP.cpp')
-rw-r--r--lldb/source/Plugins/Protocol/MCP/ProtocolServerMCP.cpp129
1 files changed, 49 insertions, 80 deletions
diff --git a/lldb/source/Plugins/Protocol/MCP/ProtocolServerMCP.cpp b/lldb/source/Plugins/Protocol/MCP/ProtocolServerMCP.cpp
index c359663239dc..dc18c8e06803 100644
--- a/lldb/source/Plugins/Protocol/MCP/ProtocolServerMCP.cpp
+++ b/lldb/source/Plugins/Protocol/MCP/ProtocolServerMCP.cpp
@@ -10,14 +10,15 @@
#include "Resource.h"
#include "Tool.h"
#include "lldb/Core/PluginManager.h"
-#include "lldb/Protocol/MCP/MCPError.h"
-#include "lldb/Protocol/MCP/Tool.h"
+#include "lldb/Host/FileSystem.h"
+#include "lldb/Host/HostInfo.h"
+#include "lldb/Protocol/MCP/Server.h"
#include "lldb/Utility/LLDBLog.h"
#include "lldb/Utility/Log.h"
#include "llvm/ADT/StringExtras.h"
+#include "llvm/Support/Error.h"
#include "llvm/Support/Threading.h"
#include <thread>
-#include <variant>
using namespace lldb_private;
using namespace lldb_private::mcp;
@@ -26,24 +27,10 @@ using namespace llvm;
LLDB_PLUGIN_DEFINE(ProtocolServerMCP)
-static constexpr size_t kChunkSize = 1024;
static constexpr llvm::StringLiteral kName = "lldb-mcp";
static constexpr llvm::StringLiteral kVersion = "0.1.0";
-ProtocolServerMCP::ProtocolServerMCP()
- : ProtocolServer(),
- lldb_protocol::mcp::Server(std::string(kName), std::string(kVersion)) {
- AddNotificationHandler("notifications/initialized",
- [](const lldb_protocol::mcp::Notification &) {
- LLDB_LOG(GetLog(LLDBLog::Host),
- "MCP initialization complete");
- });
-
- AddTool(
- std::make_unique<CommandTool>("lldb_command", "Run an lldb command."));
-
- AddResourceProvider(std::make_unique<DebuggerResourceProvider>());
-}
+ProtocolServerMCP::ProtocolServerMCP() : ProtocolServer() {}
ProtocolServerMCP::~ProtocolServerMCP() { llvm::consumeError(Stop()); }
@@ -53,6 +40,8 @@ void ProtocolServerMCP::Initialize() {
}
void ProtocolServerMCP::Terminate() {
+ if (llvm::Error error = ProtocolServer::Terminate())
+ LLDB_LOG_ERROR(GetLog(LLDBLog::Host), std::move(error), "{0}");
PluginManager::UnregisterPlugin(CreateInstance);
}
@@ -64,57 +53,37 @@ llvm::StringRef ProtocolServerMCP::GetPluginDescriptionStatic() {
return "MCP Server.";
}
+void ProtocolServerMCP::Extend(lldb_protocol::mcp::Server &server) const {
+ server.AddNotificationHandler("notifications/initialized",
+ [](const lldb_protocol::mcp::Notification &) {
+ LLDB_LOG(GetLog(LLDBLog::Host),
+ "MCP initialization complete");
+ });
+ server.AddTool(
+ std::make_unique<CommandTool>("lldb_command", "Run an lldb command."));
+ server.AddResourceProvider(std::make_unique<DebuggerResourceProvider>());
+}
+
void ProtocolServerMCP::AcceptCallback(std::unique_ptr<Socket> socket) {
- LLDB_LOG(GetLog(LLDBLog::Host), "New MCP client ({0}) connected",
- m_clients.size() + 1);
+ Log *log = GetLog(LLDBLog::Host);
+ std::string client_name = llvm::formatv("client_{0}", m_instances.size() + 1);
+ LLDB_LOG(log, "New MCP client connected: {0}", client_name);
lldb::IOObjectSP io_sp = std::move(socket);
- auto client_up = std::make_unique<Client>();
- client_up->io_sp = io_sp;
- Client *client = client_up.get();
-
- Status status;
- auto read_handle_up = m_loop.RegisterReadObject(
- io_sp,
- [this, client](MainLoopBase &loop) {
- if (llvm::Error error = ReadCallback(*client)) {
- LLDB_LOG_ERROR(GetLog(LLDBLog::Host), std::move(error), "{0}");
- client->read_handle_up.reset();
- }
- },
- status);
- if (status.Fail())
+ auto transport_up = std::make_unique<lldb_protocol::mcp::Transport>(
+ io_sp, io_sp, [client_name](llvm::StringRef message) {
+ LLDB_LOG(GetLog(LLDBLog::Host), "{0}: {1}", client_name, message);
+ });
+ auto instance_up = std::make_unique<lldb_protocol::mcp::Server>(
+ std::string(kName), std::string(kVersion), std::move(transport_up),
+ m_loop);
+ Extend(*instance_up);
+ llvm::Error error = instance_up->Run();
+ if (error) {
+ LLDB_LOG_ERROR(log, std::move(error), "Failed to run MCP server: {0}");
return;
-
- client_up->read_handle_up = std::move(read_handle_up);
- m_clients.emplace_back(std::move(client_up));
-}
-
-llvm::Error ProtocolServerMCP::ReadCallback(Client &client) {
- char chunk[kChunkSize];
- size_t bytes_read = sizeof(chunk);
- if (Status status = client.io_sp->Read(chunk, bytes_read); status.Fail())
- return status.takeError();
- client.buffer.append(chunk, bytes_read);
-
- for (std::string::size_type pos;
- (pos = client.buffer.find('\n')) != std::string::npos;) {
- llvm::Expected<std::optional<lldb_protocol::mcp::Message>> message =
- HandleData(StringRef(client.buffer.data(), pos));
- client.buffer = client.buffer.erase(0, pos + 1);
- if (!message)
- return message.takeError();
-
- if (*message) {
- std::string Output;
- llvm::raw_string_ostream OS(Output);
- OS << llvm::formatv("{0}", toJSON(**message)) << '\n';
- size_t num_bytes = Output.size();
- return client.io_sp->Write(Output.data(), num_bytes).takeError();
- }
}
-
- return llvm::Error::success();
+ m_instances.push_back(std::move(instance_up));
}
llvm::Error ProtocolServerMCP::Start(ProtocolServer::Connection connection) {
@@ -138,7 +107,19 @@ llvm::Error ProtocolServerMCP::Start(ProtocolServer::Connection connection) {
if (llvm::Error error = handles.takeError())
return error;
+ auto listening_uris = m_listener->GetListeningConnectionURI();
+ if (listening_uris.empty())
+ return createStringError("failed to get listening connections");
+ std::string address =
+ llvm::join(m_listener->GetListeningConnectionURI(), ", ");
+
+ ServerInfo info{listening_uris[0]};
+ llvm::Expected<ServerInfoHandle> handle = ServerInfo::Write(info);
+ if (!handle)
+ return handle.takeError();
+
m_running = true;
+ m_server_info_handle = std::move(*handle);
m_listen_handlers = std::move(*handles);
m_loop_thread = std::thread([=] {
llvm::set_thread_name("protocol-server.mcp");
@@ -158,27 +139,15 @@ llvm::Error ProtocolServerMCP::Stop() {
// Stop the main loop.
m_loop.AddPendingCallback(
- [](MainLoopBase &loop) { loop.RequestTermination(); });
+ [](lldb_private::MainLoopBase &loop) { loop.RequestTermination(); });
// Wait for the main loop to exit.
if (m_loop_thread.joinable())
m_loop_thread.join();
- {
- std::lock_guard<std::mutex> guard(m_mutex);
- m_listener.reset();
- m_listen_handlers.clear();
- m_clients.clear();
- }
+ m_listen_handlers.clear();
+ m_server_info_handle = ServerInfoHandle();
+ m_instances.clear();
return llvm::Error::success();
}
-
-lldb_protocol::mcp::Capabilities ProtocolServerMCP::GetCapabilities() {
- lldb_protocol::mcp::Capabilities capabilities;
- capabilities.tools.listChanged = true;
- // FIXME: Support sending notifications when a debugger/target are
- // added/removed.
- capabilities.resources.listChanged = false;
- return capabilities;
-}