[Lldb-commits] [lldb] [lldb] Adjust ProtocolServer connection defaults. (PR #155714)
via lldb-commits
lldb-commits at lists.llvm.org
Wed Aug 27 16:23:25 PDT 2025
llvmbot wrote:
<!--LLVM PR SUMMARY COMMENT-->
@llvm/pr-subscribers-lldb
Author: John Harrison (ashgti)
<details>
<summary>Changes</summary>
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.
---
Full diff: https://github.com/llvm/llvm-project/pull/155714.diff
5 Files Affected:
- (modified) lldb/include/lldb/Protocol/MCP/Server.h (+12)
- (modified) lldb/source/Commands/CommandObjectProtocolServer.cpp (+7-8)
- (modified) lldb/source/Plugins/Protocol/MCP/ProtocolServerMCP.cpp (+44-3)
- (modified) lldb/source/Plugins/Protocol/MCP/ProtocolServerMCP.h (+1)
- (modified) lldb/source/Protocol/MCP/Server.cpp (+12)
``````````diff
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)
``````````
</details>
https://github.com/llvm/llvm-project/pull/155714
More information about the lldb-commits
mailing list