@@ -26,24 +26,10 @@ using namespace llvm;
2626
2727LLDB_PLUGIN_DEFINE (ProtocolServerMCP)
2828
29- static constexpr size_t kChunkSize = 1024;
3029static constexpr llvm::StringLiteral kName = "lldb-mcp";
3130static constexpr llvm::StringLiteral kVersion = " 0.1.0" ;
3231
33- ProtocolServerMCP::ProtocolServerMCP ()
34- : ProtocolServer(),
35- lldb_protocol::mcp::Server(std::string(kName ), std::string(kVersion )) {
36- AddNotificationHandler (" notifications/initialized" ,
37- [](const lldb_protocol::mcp::Notification &) {
38- LLDB_LOG (GetLog (LLDBLog::Host),
39- " MCP initialization complete" );
40- });
41-
42- AddTool (
43- std::make_unique<CommandTool>(" lldb_command" , " Run an lldb command." ));
44-
45- AddResourceProvider (std::make_unique<DebuggerResourceProvider>());
46- }
32+ ProtocolServerMCP::ProtocolServerMCP () : ProtocolServer() {}
4733
4834ProtocolServerMCP::~ProtocolServerMCP () { llvm::consumeError (Stop ()); }
4935
@@ -64,57 +50,37 @@ llvm::StringRef ProtocolServerMCP::GetPluginDescriptionStatic() {
6450 return " MCP Server." ;
6551}
6652
53+ void ProtocolServerMCP::Extend (lldb_protocol::mcp::Server &server) const {
54+ server.AddNotificationHandler (" notifications/initialized" ,
55+ [](const lldb_protocol::mcp::Notification &) {
56+ LLDB_LOG (GetLog (LLDBLog::Host),
57+ " MCP initialization complete" );
58+ });
59+ server.AddTool (
60+ std::make_unique<CommandTool>(" lldb_command" , " Run an lldb command." ));
61+ server.AddResourceProvider (std::make_unique<DebuggerResourceProvider>());
62+ }
63+
6764void ProtocolServerMCP::AcceptCallback (std::unique_ptr<Socket> socket) {
68- LLDB_LOG (GetLog (LLDBLog::Host), " New MCP client ({0}) connected" ,
69- m_clients.size () + 1 );
65+ Log *log = GetLog (LLDBLog::Host);
66+ std::string client_name = llvm::formatv (" client_{0}" , m_instances.size () + 1 );
67+ LLDB_LOG (log, " New MCP client connected: {0}" , client_name);
7068
7169 lldb::IOObjectSP io_sp = std::move (socket);
72- auto client_up = std::make_unique<Client>();
73- client_up->io_sp = io_sp;
74- Client *client = client_up.get ();
75-
76- Status status;
77- auto read_handle_up = m_loop.RegisterReadObject (
78- io_sp,
79- [this , client](MainLoopBase &loop) {
80- if (llvm::Error error = ReadCallback (*client)) {
81- LLDB_LOG_ERROR (GetLog (LLDBLog::Host), std::move (error), " {0}" );
82- client->read_handle_up .reset ();
83- }
84- },
85- status);
86- if (status.Fail ())
70+ auto transport_up = std::make_unique<lldb_protocol::mcp::MCPTransport>(
71+ io_sp, io_sp, std::move (client_name), [&](llvm::StringRef message) {
72+ LLDB_LOG (GetLog (LLDBLog::Host), " {0}" , message);
73+ });
74+ auto instance_up = std::make_unique<lldb_protocol::mcp::Server>(
75+ std::string (kName ), std::string (kVersion ), std::move (transport_up),
76+ m_loop);
77+ Extend (*instance_up);
78+ llvm::Error error = instance_up->Run ();
79+ if (error) {
80+ LLDB_LOG_ERROR (log, std::move (error), " Failed to run MCP server: {0}" );
8781 return ;
88-
89- client_up->read_handle_up = std::move (read_handle_up);
90- m_clients.emplace_back (std::move (client_up));
91- }
92-
93- llvm::Error ProtocolServerMCP::ReadCallback (Client &client) {
94- char chunk[kChunkSize ];
95- size_t bytes_read = sizeof (chunk);
96- if (Status status = client.io_sp ->Read (chunk, bytes_read); status.Fail ())
97- return status.takeError ();
98- client.buffer .append (chunk, bytes_read);
99-
100- for (std::string::size_type pos;
101- (pos = client.buffer .find (' \n ' )) != std::string::npos;) {
102- llvm::Expected<std::optional<lldb_protocol::mcp::Message>> message =
103- HandleData (StringRef (client.buffer .data (), pos));
104- client.buffer = client.buffer .erase (0 , pos + 1 );
105- if (!message)
106- return message.takeError ();
107-
108- if (*message) {
109- std::string Output;
110- llvm::raw_string_ostream OS (Output);
111- OS << llvm::formatv (" {0}" , toJSON (**message)) << ' \n ' ;
112- size_t num_bytes = Output.size ();
113- return client.io_sp ->Write (Output.data (), num_bytes).takeError ();
114- }
11582 }
116-
117- return llvm::Error::success ();
83+ m_instances.push_back (std::move (instance_up));
11884}
11985
12086llvm::Error ProtocolServerMCP::Start (ProtocolServer::Connection connection) {
@@ -158,27 +124,11 @@ llvm::Error ProtocolServerMCP::Stop() {
158124
159125 // Stop the main loop.
160126 m_loop.AddPendingCallback (
161- [](MainLoopBase &loop) { loop.RequestTermination (); });
127+ [](lldb_private:: MainLoopBase &loop) { loop.RequestTermination (); });
162128
163129 // Wait for the main loop to exit.
164130 if (m_loop_thread.joinable ())
165131 m_loop_thread.join ();
166132
167- {
168- std::lock_guard<std::mutex> guard (m_mutex);
169- m_listener.reset ();
170- m_listen_handlers.clear ();
171- m_clients.clear ();
172- }
173-
174133 return llvm::Error::success ();
175134}
176-
177- lldb_protocol::mcp::Capabilities ProtocolServerMCP::GetCapabilities () {
178- lldb_protocol::mcp::Capabilities capabilities;
179- capabilities.tools .listChanged = true ;
180- // FIXME: Support sending notifications when a debugger/target are
181- // added/removed.
182- capabilities.resources .listChanged = false ;
183- return capabilities;
184- }
0 commit comments