Skip to content
Merged
12 changes: 12 additions & 0 deletions lldb/include/lldb/Protocol/MCP/Server.h
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand Down
15 changes: 7 additions & 8 deletions lldb/source/Commands/CommandObjectProtocolServer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand All @@ -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);
}
Expand All @@ -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);
Expand Down
47 changes: 44 additions & 3 deletions lldb/source/Plugins/Protocol/MCP/ProtocolServerMCP.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -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");
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Let's add this to HostInfo. Getting the MCP directory might be a bit too specific, but ~/.lldb seems generally useful. Looks like we have a few more uses of that in PlatformProperties for example.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Added new things to HostInfo, I might need to double check some more platforms as well.

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([=] {
Expand All @@ -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(); });
Expand Down
1 change: 1 addition & 0 deletions lldb/source/Plugins/Protocol/MCP/ProtocolServerMCP.h
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down
12 changes: 12 additions & 0 deletions lldb/source/Protocol/MCP/Server.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down
Loading