Skip to content

Commit a67257b

Browse files
authored
[lldb] Adding structured types for existing MCP calls. (#155460)
This adds or renames existing types to match the names of the types on https://modelcontextprotocol.io/specification/2025-06-18/schema for the existing calls. The new types are used in the unit tests and server implementation to remove the need for crafting various `llvm::json::Object` values by hand.
1 parent 7d26150 commit a67257b

File tree

13 files changed

+529
-261
lines changed

13 files changed

+529
-261
lines changed

lldb/include/lldb/Protocol/MCP/Protocol.h

Lines changed: 179 additions & 61 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@
1818
#include <optional>
1919
#include <string>
2020
#include <variant>
21+
#include <vector>
2122

2223
namespace lldb_protocol::mcp {
2324

@@ -38,11 +39,24 @@ struct Request {
3839
/// The method's params.
3940
std::optional<llvm::json::Value> params;
4041
};
41-
4242
llvm::json::Value toJSON(const Request &);
4343
bool fromJSON(const llvm::json::Value &, Request &, llvm::json::Path);
4444
bool operator==(const Request &, const Request &);
4545

46+
enum ErrorCode : signed {
47+
/// Invalid JSON was received by the server. An error occurred on the server
48+
/// while parsing the JSON text.
49+
eErrorCodeParseError = -32700,
50+
/// The JSON sent is not a valid Request object.
51+
eErrorCodeInvalidRequest = -32600,
52+
/// The method does not exist / is not available.
53+
eErrorCodeMethodNotFound = -32601,
54+
/// Invalid method parameter(s).
55+
eErrorCodeInvalidParams = -32602,
56+
/// Internal JSON-RPC error.
57+
eErrorCodeInternalError = -32603,
58+
};
59+
4660
struct Error {
4761
/// The error type that occurred.
4862
int64_t code = 0;
@@ -52,9 +66,8 @@ struct Error {
5266
/// Additional information about the error. The value of this member is
5367
/// defined by the sender (e.g. detailed error information, nested errors
5468
/// etc.).
55-
std::optional<llvm::json::Value> data;
69+
std::optional<llvm::json::Value> data = std::nullopt;
5670
};
57-
5871
llvm::json::Value toJSON(const Error &);
5972
bool fromJSON(const llvm::json::Value &, Error &, llvm::json::Path);
6073
bool operator==(const Error &, const Error &);
@@ -67,7 +80,6 @@ struct Response {
6780
/// response.
6881
std::variant<Error, llvm::json::Value> result;
6982
};
70-
7183
llvm::json::Value toJSON(const Response &);
7284
bool fromJSON(const llvm::json::Value &, Response &, llvm::json::Path);
7385
bool operator==(const Response &, const Response &);
@@ -79,7 +91,6 @@ struct Notification {
7991
/// The notification's params.
8092
std::optional<llvm::json::Value> params;
8193
};
82-
8394
llvm::json::Value toJSON(const Notification &);
8495
bool fromJSON(const llvm::json::Value &, Notification &, llvm::json::Path);
8596
bool operator==(const Notification &, const Notification &);
@@ -90,45 +101,9 @@ using Message = std::variant<Request, Response, Notification>;
90101
// not force it to be checked early here.
91102
static_assert(std::is_convertible_v<Message, Message>,
92103
"Message is not convertible to itself");
93-
94104
bool fromJSON(const llvm::json::Value &, Message &, llvm::json::Path);
95105
llvm::json::Value toJSON(const Message &);
96106

97-
struct ToolCapability {
98-
/// Whether this server supports notifications for changes to the tool list.
99-
bool listChanged = false;
100-
};
101-
102-
llvm::json::Value toJSON(const ToolCapability &);
103-
bool fromJSON(const llvm::json::Value &, ToolCapability &, llvm::json::Path);
104-
105-
struct ResourceCapability {
106-
/// Whether this server supports notifications for changes to the resources
107-
/// list.
108-
bool listChanged = false;
109-
110-
/// Whether subscriptions are supported.
111-
bool subscribe = false;
112-
};
113-
114-
llvm::json::Value toJSON(const ResourceCapability &);
115-
bool fromJSON(const llvm::json::Value &, ResourceCapability &,
116-
llvm::json::Path);
117-
118-
/// Capabilities that a server may support. Known capabilities are defined here,
119-
/// in this schema, but this is not a closed set: any server can define its own,
120-
/// additional capabilities.
121-
struct Capabilities {
122-
/// Tool capabilities of the server.
123-
ToolCapability tools;
124-
125-
/// Resource capabilities of the server.
126-
ResourceCapability resources;
127-
};
128-
129-
llvm::json::Value toJSON(const Capabilities &);
130-
bool fromJSON(const llvm::json::Value &, Capabilities &, llvm::json::Path);
131-
132107
/// A known resource that the server is capable of reading.
133108
struct Resource {
134109
/// The URI of this resource.
@@ -138,17 +113,25 @@ struct Resource {
138113
std::string name;
139114

140115
/// A description of what this resource represents.
141-
std::string description;
116+
std::string description = "";
142117

143118
/// The MIME type of this resource, if known.
144-
std::string mimeType;
119+
std::string mimeType = "";
145120
};
146121

147122
llvm::json::Value toJSON(const Resource &);
148123
bool fromJSON(const llvm::json::Value &, Resource &, llvm::json::Path);
149124

125+
/// The server’s response to a resources/list request from the client.
126+
struct ListResourcesResult {
127+
std::vector<Resource> resources;
128+
};
129+
llvm::json::Value toJSON(const ListResourcesResult &);
130+
bool fromJSON(const llvm::json::Value &, ListResourcesResult &,
131+
llvm::json::Path);
132+
150133
/// The contents of a specific resource or sub-resource.
151-
struct ResourceContents {
134+
struct TextResourceContents {
152135
/// The URI of this resource.
153136
std::string uri;
154137

@@ -160,34 +143,37 @@ struct ResourceContents {
160143
std::string mimeType;
161144
};
162145

163-
llvm::json::Value toJSON(const ResourceContents &);
164-
bool fromJSON(const llvm::json::Value &, ResourceContents &, llvm::json::Path);
146+
llvm::json::Value toJSON(const TextResourceContents &);
147+
bool fromJSON(const llvm::json::Value &, TextResourceContents &,
148+
llvm::json::Path);
165149

166-
/// The server's response to a resources/read request from the client.
167-
struct ResourceResult {
168-
std::vector<ResourceContents> contents;
150+
/// Sent from the client to the server, to read a specific resource URI.
151+
struct ReadResourceParams {
152+
/// The URI of the resource to read. The URI can use any protocol; it is up to
153+
/// the server how to interpret it.
154+
std::string uri;
169155
};
156+
llvm::json::Value toJSON(const ReadResourceParams &);
157+
bool fromJSON(const llvm::json::Value &, ReadResourceParams &,
158+
llvm::json::Path);
170159

171-
llvm::json::Value toJSON(const ResourceResult &);
172-
bool fromJSON(const llvm::json::Value &, ResourceResult &, llvm::json::Path);
160+
/// The server's response to a resources/read request from the client.
161+
struct ReadResourceResult {
162+
std::vector<TextResourceContents> contents;
163+
};
164+
llvm::json::Value toJSON(const ReadResourceResult &);
165+
bool fromJSON(const llvm::json::Value &, ReadResourceResult &,
166+
llvm::json::Path);
173167

174168
/// Text provided to or from an LLM.
175169
struct TextContent {
176170
/// The text content of the message.
177171
std::string text;
178172
};
179-
180173
llvm::json::Value toJSON(const TextContent &);
181174
bool fromJSON(const llvm::json::Value &, TextContent &, llvm::json::Path);
182175

183-
struct TextResult {
184-
std::vector<TextContent> content;
185-
bool isError = false;
186-
};
187-
188-
llvm::json::Value toJSON(const TextResult &);
189-
bool fromJSON(const llvm::json::Value &, TextResult &, llvm::json::Path);
190-
176+
/// Definition for a tool the client can call.
191177
struct ToolDefinition {
192178
/// Unique identifier for the tool.
193179
std::string name;
@@ -198,12 +184,144 @@ struct ToolDefinition {
198184
// JSON Schema for the tool's parameters.
199185
std::optional<llvm::json::Value> inputSchema;
200186
};
201-
202187
llvm::json::Value toJSON(const ToolDefinition &);
203188
bool fromJSON(const llvm::json::Value &, ToolDefinition &, llvm::json::Path);
204189

205190
using ToolArguments = std::variant<std::monostate, llvm::json::Value>;
206191

192+
/// Describes the name and version of an MCP implementation, with an optional
193+
/// title for UI representation.
194+
struct Implementation {
195+
/// Intended for programmatic or logical use, but used as a display name in
196+
/// past specs or fallback (if title isn’t present).
197+
std::string name;
198+
199+
std::string version;
200+
201+
/// Intended for UI and end-user contexts — optimized to be human-readable and
202+
/// easily understood, even by those unfamiliar with domain-specific
203+
/// terminology.
204+
///
205+
/// If not provided, the name should be used for display (except for Tool,
206+
/// where annotations.title should be given precedence over using name, if
207+
/// present).
208+
std::string title = "";
209+
};
210+
llvm::json::Value toJSON(const Implementation &);
211+
bool fromJSON(const llvm::json::Value &, Implementation &, llvm::json::Path);
212+
213+
/// Capabilities a client may support. Known capabilities are defined here, in
214+
/// this schema, but this is not a closed set: any client can define its own,
215+
/// additional capabilities.
216+
struct ClientCapabilities {};
217+
llvm::json::Value toJSON(const ClientCapabilities &);
218+
bool fromJSON(const llvm::json::Value &, ClientCapabilities &,
219+
llvm::json::Path);
220+
221+
/// Capabilities that a server may support. Known capabilities are defined here,
222+
/// in this schema, but this is not a closed set: any server can define its own,
223+
/// additional capabilities.
224+
struct ServerCapabilities {
225+
bool supportsToolsList = false;
226+
bool supportsResourcesList = false;
227+
bool supportsResourcesSubscribe = false;
228+
229+
/// Utilities.
230+
bool supportsCompletions = false;
231+
bool supportsLogging = false;
232+
};
233+
llvm::json::Value toJSON(const ServerCapabilities &);
234+
bool fromJSON(const llvm::json::Value &, ServerCapabilities &,
235+
llvm::json::Path);
236+
237+
/// Initialization
238+
239+
/// This request is sent from the client to the server when it first connects,
240+
/// asking it to begin initialization.
241+
struct InitializeParams {
242+
/// The latest version of the Model Context Protocol that the client supports.
243+
/// The client MAY decide to support older versions as well.
244+
std::string protocolVersion;
245+
246+
ClientCapabilities capabilities;
247+
248+
Implementation clientInfo;
249+
};
250+
llvm::json::Value toJSON(const InitializeParams &);
251+
bool fromJSON(const llvm::json::Value &, InitializeParams &, llvm::json::Path);
252+
253+
/// After receiving an initialize request from the client, the server sends this
254+
/// response.
255+
struct InitializeResult {
256+
/// The version of the Model Context Protocol that the server wants to use.
257+
/// This may not match the version that the client requested. If the client
258+
/// cannot support this version, it MUST disconnect.
259+
std::string protocolVersion;
260+
261+
ServerCapabilities capabilities;
262+
Implementation serverInfo;
263+
264+
/// Instructions describing how to use the server and its features.
265+
///
266+
/// This can be used by clients to improve the LLM's understanding of
267+
/// available tools, resources, etc. It can be thought of like a "hint" to the
268+
/// model. For example, this information MAY be added to the system prompt.
269+
std::string instructions = "";
270+
};
271+
llvm::json::Value toJSON(const InitializeResult &);
272+
bool fromJSON(const llvm::json::Value &, InitializeResult &, llvm::json::Path);
273+
274+
/// Special case parameter or result that has no value.
275+
using Void = std::monostate;
276+
llvm::json::Value toJSON(const Void &);
277+
bool fromJSON(const llvm::json::Value &, Void &, llvm::json::Path);
278+
279+
/// The server's response to a `tools/list` request from the client.
280+
struct ListToolsResult {
281+
std::vector<ToolDefinition> tools;
282+
};
283+
llvm::json::Value toJSON(const ListToolsResult &);
284+
bool fromJSON(const llvm::json::Value &, ListToolsResult &, llvm::json::Path);
285+
286+
/// Supported content types, currently only TextContent, but the spec includes
287+
/// additional content types.
288+
using ContentBlock = TextContent;
289+
290+
/// Used by the client to invoke a tool provided by the server.
291+
struct CallToolParams {
292+
std::string name;
293+
std::optional<llvm::json::Value> arguments;
294+
};
295+
llvm::json::Value toJSON(const CallToolParams &);
296+
bool fromJSON(const llvm::json::Value &, CallToolParams &, llvm::json::Path);
297+
298+
/// The server’s response to a tool call.
299+
struct CallToolResult {
300+
/// A list of content objects that represent the unstructured result of the
301+
/// tool call.
302+
std::vector<ContentBlock> content;
303+
304+
/// Whether the tool call ended in an error.
305+
///
306+
/// If not set, this is assumed to be false (the call was successful).
307+
///
308+
/// Any errors that originate from the tool SHOULD be reported inside the
309+
/// result object, with `isError` set to true, not as an MCP protocol-level
310+
/// error response. Otherwise, the LLM would not be able to see that an error
311+
/// occurred and self-correct.
312+
///
313+
/// However, any errors in finding the tool, an error indicating that the
314+
/// server does not support tool calls, or any other exceptional conditions,
315+
/// should be reported as an MCP error response.
316+
bool isError = false;
317+
318+
/// An optional JSON object that represents the structured result of the tool
319+
/// call.
320+
std::optional<llvm::json::Value> structuredContent = std::nullopt;
321+
};
322+
llvm::json::Value toJSON(const CallToolResult &);
323+
bool fromJSON(const llvm::json::Value &, CallToolResult &, llvm::json::Path);
324+
207325
} // namespace lldb_protocol::mcp
208326

209327
#endif

lldb/include/lldb/Protocol/MCP/Resource.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@ class ResourceProvider {
2020
virtual ~ResourceProvider() = default;
2121

2222
virtual std::vector<lldb_protocol::mcp::Resource> GetResources() const = 0;
23-
virtual llvm::Expected<lldb_protocol::mcp::ResourceResult>
23+
virtual llvm::Expected<lldb_protocol::mcp::ReadResourceResult>
2424
ReadResource(llvm::StringRef uri) const = 0;
2525
};
2626

lldb/include/lldb/Protocol/MCP/Server.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -58,7 +58,7 @@ class Server : public MCPTransport::MessageHandler {
5858
llvm::Error Run();
5959

6060
protected:
61-
Capabilities GetCapabilities();
61+
ServerCapabilities GetCapabilities();
6262

6363
using RequestHandler =
6464
std::function<llvm::Expected<Response>(const Request &)>;

lldb/include/lldb/Protocol/MCP/Tool.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@
1010
#define LLDB_PROTOCOL_MCP_TOOL_H
1111

1212
#include "lldb/Protocol/MCP/Protocol.h"
13+
#include "llvm/Support/Error.h"
1314
#include "llvm/Support/JSON.h"
1415
#include <string>
1516

@@ -20,7 +21,7 @@ class Tool {
2021
Tool(std::string name, std::string description);
2122
virtual ~Tool() = default;
2223

23-
virtual llvm::Expected<lldb_protocol::mcp::TextResult>
24+
virtual llvm::Expected<lldb_protocol::mcp::CallToolResult>
2425
Call(const lldb_protocol::mcp::ToolArguments &args) = 0;
2526

2627
virtual std::optional<llvm::json::Value> GetSchema() const {

0 commit comments

Comments
 (0)