https://github.com/ashgti updated https://github.com/llvm/llvm-project/pull/155714
>From 831a505e3e8368cf2ee5cae995b8920fbc8d2365 Mon Sep 17 00:00:00 2001 From: John Harrison <harj...@google.com> Date: Wed, 27 Aug 2025 15:58:04 -0700 Subject: [PATCH] [lldb] Adjust ProtocolServer connection defaults. This adjusts the ProtocolServer command to default to create a new connection listening on `localhost:0` and adds a new `ServerMetadata` details to `~/.lldb/mcp/lldb-<pid>.json` to record information about the current MCP server. This can be consumed by the lldb-mcp binary to establish a connection from an LLM client. --- lldb/include/lldb/Protocol/MCP/Server.h | 12 +++++ .../Commands/CommandObjectProtocolServer.cpp | 15 +++--- .../Protocol/MCP/ProtocolServerMCP.cpp | 47 +++++++++++++++++-- .../Plugins/Protocol/MCP/ProtocolServerMCP.h | 1 + lldb/source/Protocol/MCP/Server.cpp | 12 +++++ 5 files changed, 76 insertions(+), 11 deletions(-) diff --git a/lldb/include/lldb/Protocol/MCP/Server.h b/lldb/include/lldb/Protocol/MCP/Server.h index 009c574fde92f..54f004b17546e 100644 --- a/lldb/include/lldb/Protocol/MCP/Server.h +++ b/lldb/include/lldb/Protocol/MCP/Server.h @@ -14,11 +14,23 @@ #include "lldb/Protocol/MCP/Resource.h" #include "lldb/Protocol/MCP/Tool.h" #include "lldb/Protocol/MCP/Transport.h" +#include "lldb/lldb-types.h" #include "llvm/ADT/StringMap.h" #include "llvm/Support/Error.h" +#include "llvm/Support/JSON.h" namespace lldb_protocol::mcp { +/// Metadata about this instance of lldb's MCP server for lldb-mcp to use to +/// coordinate connecting an lldb-mcp client. +struct ServerMetadata { + std::string connection_uri; + lldb::pid_t pid; +}; +llvm::json::Value toJSON(const ServerMetadata &SM); +bool fromJSON(const llvm::json::Value &V, ServerMetadata &SM, + llvm::json::Path P); + class Server : public Transport::MessageHandler { public: Server(std::string name, std::string version, diff --git a/lldb/source/Commands/CommandObjectProtocolServer.cpp b/lldb/source/Commands/CommandObjectProtocolServer.cpp index f11e27f01c8a8..81c97614b8fe3 100644 --- a/lldb/source/Commands/CommandObjectProtocolServer.cpp +++ b/lldb/source/Commands/CommandObjectProtocolServer.cpp @@ -15,6 +15,7 @@ #include "lldb/Utility/UriParser.h" #include "llvm/ADT/STLExtras.h" #include "llvm/Support/FormatAdapters.h" +#include <string> using namespace llvm; using namespace lldb; @@ -28,7 +29,7 @@ class CommandObjectProtocolServerStart : public CommandObjectParsed { CommandObjectProtocolServerStart(CommandInterpreter &interpreter) : CommandObjectParsed(interpreter, "protocol-server start", "start protocol server", - "protocol-server start <protocol> <connection>") { + "protocol-server start <protocol> [<connection>]") { AddSimpleArgumentList(lldb::eArgTypeProtocol, eArgRepeatPlain); AddSimpleArgumentList(lldb::eArgTypeConnectURL, eArgRepeatPlain); } @@ -51,15 +52,13 @@ class CommandObjectProtocolServerStart : public CommandObjectParsed { return; } - if (args.GetArgumentCount() < 2) { - result.AppendError("no connection specified"); - return; - } - llvm::StringRef connection_uri = args.GetArgumentAtIndex(1); + std::string connection_uri = "listen://[localhost]:0"; + if (args.GetArgumentCount() > 2) + connection_uri = args.GetArgumentAtIndex(1); const char *connection_error = - "unsupported connection specifier, expected 'accept:///path' or " - "'listen://[host]:port', got '{0}'."; + "unsupported connection specifier, expected 'accept:///path' " + "or 'listen://[host]:port', got '{0}'."; auto uri = lldb_private::URI::Parse(connection_uri); if (!uri) { result.AppendErrorWithFormatv(connection_error, connection_uri); diff --git a/lldb/source/Plugins/Protocol/MCP/ProtocolServerMCP.cpp b/lldb/source/Plugins/Protocol/MCP/ProtocolServerMCP.cpp index a9c4164313a6d..9068ff92a9aab 100644 --- a/lldb/source/Plugins/Protocol/MCP/ProtocolServerMCP.cpp +++ b/lldb/source/Plugins/Protocol/MCP/ProtocolServerMCP.cpp @@ -10,14 +10,14 @@ #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/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; @@ -104,6 +104,43 @@ 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 list listening connections"); + std::string address = + llvm::join(m_listener->GetListeningConnectionURI(), ", "); + + llvm::SmallString<128> user_home_dir; + FileSystem::Instance().GetHomeDirectory(user_home_dir); + FileSpec mcp_registry_dir = FileSpec(user_home_dir.c_str()); + mcp_registry_dir.AppendPathComponent(".lldb"); + mcp_registry_dir.AppendPathComponent("mcp"); + + Status error(llvm::sys::fs::create_directory(mcp_registry_dir.GetPath())); + if (error.Fail()) + return error.takeError(); + + m_mcp_registry_entry_path = mcp_registry_dir.CopyByAppendingPathComponent( + formatv("lldb-{0}.json", getpid()).str()); + + const File::OpenOptions flags = File::eOpenOptionWriteOnly | + File::eOpenOptionCanCreate | + File::eOpenOptionTruncate; + llvm::Expected<lldb::FileUP> file = + FileSystem::Instance().Open(m_mcp_registry_entry_path, flags, + lldb::eFilePermissionsFileDefault, false); + if (!file) + return file.takeError(); + + ServerMetadata metadata; + metadata.connection_uri = listening_uris[0]; + metadata.pid = getpid(); + + std::string buf = formatv("{0}", toJSON(metadata)).str(); + size_t num_bytes = buf.size(); + if (llvm::Error error = (*file)->Write(buf.data(), num_bytes).takeError()) + return error; + m_running = true; m_listen_handlers = std::move(*handles); m_loop_thread = std::thread([=] { @@ -122,6 +159,10 @@ llvm::Error ProtocolServerMCP::Stop() { m_running = false; } + if (!m_mcp_registry_entry_path.GetPath().empty()) + FileSystem::Instance().RemoveFile(m_mcp_registry_entry_path); + m_mcp_registry_entry_path.Clear(); + // Stop the main loop. m_loop.AddPendingCallback( [](lldb_private::MainLoopBase &loop) { loop.RequestTermination(); }); diff --git a/lldb/source/Plugins/Protocol/MCP/ProtocolServerMCP.h b/lldb/source/Plugins/Protocol/MCP/ProtocolServerMCP.h index fc650ffe0dfa7..004fa3c2d05a8 100644 --- a/lldb/source/Plugins/Protocol/MCP/ProtocolServerMCP.h +++ b/lldb/source/Plugins/Protocol/MCP/ProtocolServerMCP.h @@ -48,6 +48,7 @@ class ProtocolServerMCP : public ProtocolServer { bool m_running = false; + FileSpec m_mcp_registry_entry_path; lldb_private::MainLoop m_loop; std::thread m_loop_thread; std::mutex m_mutex; diff --git a/lldb/source/Protocol/MCP/Server.cpp b/lldb/source/Protocol/MCP/Server.cpp index fb317083b015e..47cfb1a6114b4 100644 --- a/lldb/source/Protocol/MCP/Server.cpp +++ b/lldb/source/Protocol/MCP/Server.cpp @@ -14,6 +14,18 @@ using namespace lldb_protocol::mcp; using namespace llvm; +llvm::json::Value toJSON(const ServerMetadata &SM) { + return llvm::json::Object{{"connection_uri", SM.connection_uri}, + {"pid", SM.pid}}; +} + +bool fromJSON(const llvm::json::Value &V, ServerMetadata &SM, + llvm::json::Path P) { + llvm::json::ObjectMapper O(V, P); + return O && O.map("connection_uri", SM.connection_uri) && + O.map("pid", SM.pid); +} + Server::Server(std::string name, std::string version, std::unique_ptr<Transport> transport_up, lldb_private::MainLoop &loop) _______________________________________________ lldb-commits mailing list lldb-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits