[RFC] Adding MCP support to LLDB (original) (raw)
Background & Motivation
In an attempt to better understand how developers use AI as part of their development, I’ve spent some time after hours playing around with Copilot in Visual Studio Code. My journey started with a lot of skepticism but with the right workflow I came to see its appeal and opportunities.
One such opportunities is using established, deterministic tools to augment the capabilities of the underlying models, as opposed to doing the opposite, where models are used to augment existing deterministic tools.
For example, I’m personally skeptical of using AI inside the debugger. I don’t see a way to reconcile that with our core principles that"the debugger never lies". However, I can see value in having the debugger serve as an input, where it can help the model figure out a bug. The key difference is the expectations of our users when they’re using the debugger versus when they’re using a AI chat bot in their IDE.
Proposal
To support the latter, I’m proposing to add support for MCP to LLDB. The Model Context Protocol (MCP) is an open protocol that standardizes how applications provide context to LLMs. MCP servers expose tools that can be invoked by language models. These tools (i.e. LLDB in this case) are controlled by the model, meaning that the language model can invoke the tool automatically based on its contextual understanding and the user’s prompts. The protocol supports other operations besides invoking tools, but that’s out of scope for this RFC.
The protocol uses JSON-RPC messages to communicate between clients (i.e. the model) and the server (i.e. lldb) over stdio [1], similar to the Debug Adapter Protocol (DAP).
Design & Implementation
I don’t want to go into too much detail about the protocol itself (for that I recommend the specification and the user guide), but I do want to highlight how these tools are used, as it impacts the design.
Both Claude Desktop and Visual Studio Code let you specify your own MCP server. You do this by specifying a binary and optional command line arguments. In its simplest form, that would be something like lldb-mpc
which acts as a wrapper around LLDB (again, similar to lldb-dap
). This is the approach I took for my initial prototype.
Because of its standalone nature, that means that the model, either autonomously, or through instructions from the user, is in charge of creating your debug session. An example of that would be:
Launch and debug /path/to/binary. Set a breakpoint on line 10 and then step through the loop and print the value of
sum
after every iteration.
A strictly more powerful approach however is to allow the MCP server to tap into an existing debug session. For example, I can start debugging my binary in VS Code and run to the breakpoint in the IDE, and then ask the model to do only the stepping part.
Step through the loop and print the value of
sum
after every iteration.
Once the model is done, I can resume debugging normally. This approach allows me to tap into the model where it makes sense, without giving up complete control. To support this use case, my proposal is to add the MCP server to LLDB itself, rather than implementing it on top.
Prototype
I have a working prototype that implements what I’ve described above. Here’s a demo of it in action:
Here’s the corresponding draft PR: [lldb] Add MCP support to LLDB (PoC) by JDevlieghere · Pull Request #143628 · llvm/llvm-project · GitHub
From within LLDB, you launch the MCP server with the new mcp
command:
(lldb) mcp start tcp://localhost:1234
This starts an MCP server that advertises one tool: lldb_command
. It takes an lldb command, executes it and responds with the result.
In Claude Desktop or Visual Studio Code, you use netcat
to talk over stdio and send the data over the socket to the server running under lldb.
{
"mcpServers": {
"tool": {
"command": "/usr/bin/nc",
"args": ["localhost", "1234"]
}
}
}
In the future, I imagine we’ll want to have a dedicated lldb-mcp
binary. For example, it could do auto-discovery of active connections or launch new ones to support the “standalone mode” I described earlier where the model control the debug session from start to end.
Next Step
First and foremost I’d like to get agreement on (1) supporting MCP in LLDB and (2) the approach of doing it in-process. I’ve made a case for why I think it’s important to do it this way, but I’d love to get input from the community. I’m by no means a domain expert and it’s likely there are folks here that have more experience in this realm.
After that, I think there are two pieces of work that need to be addressed after polishing my proof-of-concept:
- A lot of my code is based on code in
lldb-dap
which should be shared and reused rather than duplicated. I would propose to create a new library in LLDB (something like Protocol) that has the base protocol for MCP and DAP, and shared support classes for things like the transport. - Create an
lldb-mcp
binary and have some kind of discovery mechanism to find active LLDB MCP server instances. Maybe something like having a known location where sockets are created.
- Streamable HTTP is another transport mode. ↩︎