llvmbot wrote:

<!--LLVM PR SUMMARY COMMENT-->

@llvm/pr-subscribers-lldb

Author: John Harrison (ashgti)

<details>
<summary>Changes</summary>

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.

---

Patch is 52.89 KiB, truncated to 20.00 KiB below, full version: 
https://github.com/llvm/llvm-project/pull/155460.diff


12 Files Affected:

- (modified) lldb/include/lldb/Protocol/MCP/Protocol.h (+227-61) 
- (modified) lldb/include/lldb/Protocol/MCP/Resource.h (+1-1) 
- (modified) lldb/include/lldb/Protocol/MCP/Server.h (+1-1) 
- (modified) lldb/include/lldb/Protocol/MCP/Tool.h (+2-1) 
- (modified) lldb/source/Plugins/Protocol/MCP/Resource.cpp (+7-8) 
- (modified) lldb/source/Plugins/Protocol/MCP/Resource.h (+9-6) 
- (modified) lldb/source/Plugins/Protocol/MCP/Tool.cpp (+6-6) 
- (modified) lldb/source/Plugins/Protocol/MCP/Tool.h (+4-4) 
- (modified) lldb/source/Protocol/MCP/Protocol.cpp (+172-40) 
- (modified) lldb/source/Protocol/MCP/Server.cpp (+34-39) 
- (modified) lldb/unittests/Protocol/ProtocolMCPServerTest.cpp (+60-52) 
- (modified) lldb/unittests/Protocol/ProtocolMCPTest.cpp (+25-38) 


``````````diff
diff --git a/lldb/include/lldb/Protocol/MCP/Protocol.h 
b/lldb/include/lldb/Protocol/MCP/Protocol.h
index 49f9490221755..cdbdd67263e69 100644
--- a/lldb/include/lldb/Protocol/MCP/Protocol.h
+++ b/lldb/include/lldb/Protocol/MCP/Protocol.h
@@ -18,6 +18,7 @@
 #include <optional>
 #include <string>
 #include <variant>
+#include <vector>
 
 namespace lldb_protocol::mcp {
 
@@ -30,6 +31,9 @@ static llvm::StringLiteral kProtocolVersion = "2024-11-05";
 using Id = std::variant<int64_t, std::string>;
 
 /// A request that expects a response.
+///
+/// See
+/// 
https://modelcontextprotocol.io/specification/2025-06-18/schema#jsonrpcrequest
 struct Request {
   /// The request id.
   Id id = 0;
@@ -38,11 +42,27 @@ struct Request {
   /// The method's params.
   std::optional<llvm::json::Value> params;
 };
-
 llvm::json::Value toJSON(const Request &);
 bool fromJSON(const llvm::json::Value &, Request &, llvm::json::Path);
 bool operator==(const Request &, const Request &);
+void PrintTo(const Request &req, std::ostream *os);
+
+enum ErrorCode : signed {
+  /// Invalid JSON was received by the server. An error occurred on the server
+  /// while parsing the JSON text.
+  eErrorCodeParseError = -32700,
+  /// The JSON sent is not a valid Request object.
+  eErrorCodeInvalidRequest = -32600,
+  /// The method does not exist / is not available.
+  eErrorCodeMethodNotFound = -32601,
+  /// Invalid method parameter(s).
+  eErrorCodeInvalidParams = -32602,
+  /// Internal JSON-RPC error.
+  eErrorCodeInternalError = -32603,
+};
 
+/// See
+/// 
https://modelcontextprotocol.io/specification/2025-06-18/schema#jsonrpcerror
 struct Error {
   /// The error type that occurred.
   int64_t code = 0;
@@ -52,14 +72,16 @@ struct Error {
   /// Additional information about the error. The value of this member is
   /// defined by the sender (e.g. detailed error information, nested errors
   /// etc.).
-  std::optional<llvm::json::Value> data;
+  std::optional<llvm::json::Value> data = std::nullopt;
 };
-
 llvm::json::Value toJSON(const Error &);
 bool fromJSON(const llvm::json::Value &, Error &, llvm::json::Path);
 bool operator==(const Error &, const Error &);
 
 /// A response to a request, either an error or a result.
+///
+/// See
+/// 
https://modelcontextprotocol.io/specification/2025-06-18/schema#jsonrpcrequest
 struct Response {
   /// The request id.
   Id id = 0;
@@ -67,22 +89,24 @@ struct Response {
   /// response.
   std::variant<Error, llvm::json::Value> result;
 };
-
 llvm::json::Value toJSON(const Response &);
 bool fromJSON(const llvm::json::Value &, Response &, llvm::json::Path);
 bool operator==(const Response &, const Response &);
+void PrintTo(const Response &resp, std::ostream *os);
 
 /// A notification which does not expect a response.
+/// See
+/// 
https://modelcontextprotocol.io/specification/2025-06-18/schema#jsonrpcnotification
 struct Notification {
   /// The method to be invoked.
   std::string method;
   /// The notification's params.
   std::optional<llvm::json::Value> params;
 };
-
 llvm::json::Value toJSON(const Notification &);
 bool fromJSON(const llvm::json::Value &, Notification &, llvm::json::Path);
 bool operator==(const Notification &, const Notification &);
+void PrintTo(const Notification &note, std::ostream *os);
 
 /// A general message as defined by the JSON-RPC 2.0 spec.
 using Message = std::variant<Request, Response, Notification>;
@@ -90,46 +114,13 @@ using Message = std::variant<Request, Response, 
Notification>;
 // not force it to be checked early here.
 static_assert(std::is_convertible_v<Message, Message>,
               "Message is not convertible to itself");
-
 bool fromJSON(const llvm::json::Value &, Message &, llvm::json::Path);
 llvm::json::Value toJSON(const Message &);
-
-struct ToolCapability {
-  /// Whether this server supports notifications for changes to the tool list.
-  bool listChanged = false;
-};
-
-llvm::json::Value toJSON(const ToolCapability &);
-bool fromJSON(const llvm::json::Value &, ToolCapability &, llvm::json::Path);
-
-struct ResourceCapability {
-  /// Whether this server supports notifications for changes to the resources
-  /// list.
-  bool listChanged = false;
-
-  ///  Whether subscriptions are supported.
-  bool subscribe = false;
-};
-
-llvm::json::Value toJSON(const ResourceCapability &);
-bool fromJSON(const llvm::json::Value &, ResourceCapability &,
-              llvm::json::Path);
-
-/// Capabilities that a server may support. Known capabilities are defined 
here,
-/// in this schema, but this is not a closed set: any server can define its 
own,
-/// additional capabilities.
-struct Capabilities {
-  /// Tool capabilities of the server.
-  ToolCapability tools;
-
-  /// Resource capabilities of the server.
-  ResourceCapability resources;
-};
-
-llvm::json::Value toJSON(const Capabilities &);
-bool fromJSON(const llvm::json::Value &, Capabilities &, llvm::json::Path);
+void PrintTo(const Message &message, std::ostream *os);
 
 /// A known resource that the server is capable of reading.
+///
+/// See 
https://modelcontextprotocol.io/specification/2025-06-18/schema#resource
 struct Resource {
   /// The URI of this resource.
   std::string uri;
@@ -138,17 +129,28 @@ struct Resource {
   std::string name;
 
   /// A description of what this resource represents.
-  std::string description;
+  std::string description = "";
 
   /// The MIME type of this resource, if known.
-  std::string mimeType;
+  std::string mimeType = "";
 };
 
 llvm::json::Value toJSON(const Resource &);
 bool fromJSON(const llvm::json::Value &, Resource &, llvm::json::Path);
 
+/// The server’s response to a resources/list request from the client.
+///
+/// See
+/// 
https://modelcontextprotocol.io/specification/2025-06-18/schema#listresourcesresult
+struct ListResourcesResult {
+  std::vector<Resource> resources;
+};
+llvm::json::Value toJSON(const ListResourcesResult &);
+bool fromJSON(const llvm::json::Value &, ListResourcesResult &,
+              llvm::json::Path);
+
 /// The contents of a specific resource or sub-resource.
-struct ResourceContents {
+struct TextResourceContents {
   /// The URI of this resource.
   std::string uri;
 
@@ -160,34 +162,45 @@ struct ResourceContents {
   std::string mimeType;
 };
 
-llvm::json::Value toJSON(const ResourceContents &);
-bool fromJSON(const llvm::json::Value &, ResourceContents &, llvm::json::Path);
+llvm::json::Value toJSON(const TextResourceContents &);
+bool fromJSON(const llvm::json::Value &, TextResourceContents &,
+              llvm::json::Path);
 
-/// The server's response to a resources/read request from the client.
-struct ResourceResult {
-  std::vector<ResourceContents> contents;
+/// Sent from the client to the server, to read a specific resource URI.
+///
+/// See
+/// 
https://modelcontextprotocol.io/specification/2025-06-18/schema#readresourcerequest
+struct ReadResourceParams {
+  /// The URI of the resource to read. The URI can use any protocol; it is up 
to
+  /// the server how to interpret it.
+  std::string uri;
 };
+llvm::json::Value toJSON(const ReadResourceParams &);
+bool fromJSON(const llvm::json::Value &, ReadResourceParams &,
+              llvm::json::Path);
 
-llvm::json::Value toJSON(const ResourceResult &);
-bool fromJSON(const llvm::json::Value &, ResourceResult &, llvm::json::Path);
+/// The server's response to a resources/read request from the client.
+struct ReadResourceResult {
+  std::vector<TextResourceContents> contents;
+};
+llvm::json::Value toJSON(const ReadResourceResult &);
+bool fromJSON(const llvm::json::Value &, ReadResourceResult &,
+              llvm::json::Path);
 
 /// Text provided to or from an LLM.
+///
+/// See
+/// https://modelcontextprotocol.io/specification/2025-06-18/schema#textcontent
 struct TextContent {
   /// The text content of the message.
   std::string text;
 };
-
 llvm::json::Value toJSON(const TextContent &);
 bool fromJSON(const llvm::json::Value &, TextContent &, llvm::json::Path);
 
-struct TextResult {
-  std::vector<TextContent> content;
-  bool isError = false;
-};
-
-llvm::json::Value toJSON(const TextResult &);
-bool fromJSON(const llvm::json::Value &, TextResult &, llvm::json::Path);
-
+/// Definition for a tool the client can call.
+///
+/// See https://modelcontextprotocol.io/specification/2025-06-18/schema#tool
 struct ToolDefinition {
   /// Unique identifier for the tool.
   std::string name;
@@ -198,12 +211,165 @@ struct ToolDefinition {
   // JSON Schema for the tool's parameters.
   std::optional<llvm::json::Value> inputSchema;
 };
-
 llvm::json::Value toJSON(const ToolDefinition &);
 bool fromJSON(const llvm::json::Value &, ToolDefinition &, llvm::json::Path);
 
 using ToolArguments = std::variant<std::monostate, llvm::json::Value>;
 
+/// Describes the name and version of an MCP implementation, with an optional
+/// title for UI representation.
+///
+/// see
+/// 
https://modelcontextprotocol.io/specification/2025-06-18/schema#implementation
+struct Implementation {
+  /// Intended for programmatic or logical use, but used as a display name in
+  /// past specs or fallback (if title isn’t present).
+  std::string name;
+
+  std::string version;
+
+  /// Intended for UI and end-user contexts — optimized to be human-readable 
and
+  /// easily understood, even by those unfamiliar with domain-specific
+  /// terminology.
+  ///
+  /// If not provided, the name should be used for display (except for Tool,
+  /// where annotations.title should be given precedence over using name, if
+  /// present).
+  std::string title = "";
+};
+llvm::json::Value toJSON(const Implementation &);
+bool fromJSON(const llvm::json::Value &, Implementation &, llvm::json::Path);
+
+/// Capabilities a client may support. Known capabilities are defined here, in
+/// this schema, but this is not a closed set: any client can define its own,
+/// additional capabilities.
+///
+/// See
+/// 
https://modelcontextprotocol.io/specification/2025-06-18/schema#clientcapabilities
+struct ClientCapabilities {};
+llvm::json::Value toJSON(const ClientCapabilities &);
+bool fromJSON(const llvm::json::Value &, ClientCapabilities &,
+              llvm::json::Path);
+
+/// Capabilities that a server may support. Known capabilities are defined 
here,
+/// in this schema, but this is not a closed set: any server can define its 
own,
+/// additional capabilities.
+///
+/// See
+/// 
https://modelcontextprotocol.io/specification/2025-06-18/schema#servercapabilities
+struct ServerCapabilities {
+  bool supportsToolsList = false;
+  bool supportsResourcesList = false;
+  bool supportsResourcesSubscribe = false;
+
+  /// Utilities.
+  bool supportsCompletions = false;
+  bool supportsLogging = false;
+};
+llvm::json::Value toJSON(const ServerCapabilities &);
+bool fromJSON(const llvm::json::Value &, ServerCapabilities &,
+              llvm::json::Path);
+
+/// Initialization
+
+/// This request is sent from the client to the server when it first connects,
+/// asking it to begin initialization.
+///
+/// See
+/// 
https://modelcontextprotocol.io/specification/2025-06-18/schema#initializerequest
+struct InitializeParams {
+  /// The latest version of the Model Context Protocol that the client 
supports.
+  /// The client MAY decide to support older versions as well.
+  std::string protocolVersion;
+
+  ClientCapabilities capabilities;
+
+  Implementation clientInfo;
+};
+llvm::json::Value toJSON(const InitializeParams &);
+bool fromJSON(const llvm::json::Value &, InitializeParams &, llvm::json::Path);
+
+/// After receiving an initialize request from the client, the server sends 
this
+/// response.
+///
+/// See
+/// 
https://modelcontextprotocol.io/specification/2025-06-18/schema#initializeresult
+struct InitializeResult {
+  /// The version of the Model Context Protocol that the server wants to use.
+  /// This may not match the version that the client requested. If the client
+  /// cannot support this version, it MUST disconnect.
+  std::string protocolVersion;
+
+  ServerCapabilities capabilities;
+  Implementation serverInfo;
+
+  /// Instructions describing how to use the server and its features.
+  ///
+  /// This can be used by clients to improve the LLM's understanding of
+  /// available tools, resources, etc. It can be thought of like a "hint" to 
the
+  /// model. For example, this information MAY be added to the system prompt.
+  std::string instructions = "";
+};
+llvm::json::Value toJSON(const InitializeResult &);
+bool fromJSON(const llvm::json::Value &, InitializeResult &, llvm::json::Path);
+
+/// Special case parameter or result that has no value.
+using Void = std::monostate;
+llvm::json::Value toJSON(const Void &);
+bool fromJSON(const llvm::json::Value &, Void &, llvm::json::Path);
+
+/// The server's response to a `tools/list` request from the client.
+///
+/// See
+/// 
https://modelcontextprotocol.io/specification/2025-06-18/schema#listtoolsresult
+struct ListToolsResult {
+  std::vector<ToolDefinition> tools;
+};
+llvm::json::Value toJSON(const ListToolsResult &);
+bool fromJSON(const llvm::json::Value &, ListToolsResult &, llvm::json::Path);
+
+/// Supported content types, currently only TextContent, but the spec includes
+/// additional content types.
+using ContentBlock = TextContent;
+
+/// Used by the client to invoke a tool provided by the server.
+struct CallToolParams {
+  std::string name;
+  std::optional<llvm::json::Value> arguments;
+};
+llvm::json::Value toJSON(const CallToolParams &);
+bool fromJSON(const llvm::json::Value &, CallToolParams &, llvm::json::Path);
+
+/// The server’s response to a tool call.
+///
+/// See
+/// 
https://modelcontextprotocol.io/specification/2025-06-18/schema#calltoolresult
+struct CallToolResult {
+  /// A list of content objects that represent the unstructured result of the
+  /// tool call.
+  std::vector<ContentBlock> content;
+
+  /// Whether the tool call ended in an error.
+  ///
+  /// If not set, this is assumed to be false (the call was successful).
+  ///
+  /// Any errors that originate from the tool SHOULD be reported inside the
+  /// result object, with `isError` set to true, not as an MCP protocol-level
+  /// error response. Otherwise, the LLM would not be able to see that an error
+  /// occurred and self-correct.
+  ///
+  /// However, any errors in finding the tool, an error indicating that the
+  /// server does not support tool calls, or any other exceptional conditions,
+  /// should be reported as an MCP error response.
+  bool isError = false;
+
+  /// An optional JSON object that represents the structured result of the tool
+  /// call.
+  std::optional<llvm::json::Value> structuredContent = std::nullopt;
+};
+llvm::json::Value toJSON(const CallToolResult &);
+bool fromJSON(const llvm::json::Value &, CallToolResult &, llvm::json::Path);
+
 } // namespace lldb_protocol::mcp
 
 #endif
diff --git a/lldb/include/lldb/Protocol/MCP/Resource.h 
b/lldb/include/lldb/Protocol/MCP/Resource.h
index 4835d340cd4c6..158cffc71ea10 100644
--- a/lldb/include/lldb/Protocol/MCP/Resource.h
+++ b/lldb/include/lldb/Protocol/MCP/Resource.h
@@ -20,7 +20,7 @@ class ResourceProvider {
   virtual ~ResourceProvider() = default;
 
   virtual std::vector<lldb_protocol::mcp::Resource> GetResources() const = 0;
-  virtual llvm::Expected<lldb_protocol::mcp::ResourceResult>
+  virtual llvm::Expected<lldb_protocol::mcp::ReadResourceResult>
   ReadResource(llvm::StringRef uri) const = 0;
 };
 
diff --git a/lldb/include/lldb/Protocol/MCP/Server.h 
b/lldb/include/lldb/Protocol/MCP/Server.h
index 2b9e919329752..aa5714e45755e 100644
--- a/lldb/include/lldb/Protocol/MCP/Server.h
+++ b/lldb/include/lldb/Protocol/MCP/Server.h
@@ -58,7 +58,7 @@ class Server : public MCPTransport::MessageHandler {
   llvm::Error Run();
 
 protected:
-  Capabilities GetCapabilities();
+  ServerCapabilities GetCapabilities();
 
   using RequestHandler =
       std::function<llvm::Expected<Response>(const Request &)>;
diff --git a/lldb/include/lldb/Protocol/MCP/Tool.h 
b/lldb/include/lldb/Protocol/MCP/Tool.h
index 96669d1357166..6c9f05161f8e7 100644
--- a/lldb/include/lldb/Protocol/MCP/Tool.h
+++ b/lldb/include/lldb/Protocol/MCP/Tool.h
@@ -10,6 +10,7 @@
 #define LLDB_PROTOCOL_MCP_TOOL_H
 
 #include "lldb/Protocol/MCP/Protocol.h"
+#include "llvm/Support/Error.h"
 #include "llvm/Support/JSON.h"
 #include <string>
 
@@ -20,7 +21,7 @@ class Tool {
   Tool(std::string name, std::string description);
   virtual ~Tool() = default;
 
-  virtual llvm::Expected<lldb_protocol::mcp::TextResult>
+  virtual llvm::Expected<lldb_protocol::mcp::CallToolResult>
   Call(const lldb_protocol::mcp::ToolArguments &args) = 0;
 
   virtual std::optional<llvm::json::Value> GetSchema() const {
diff --git a/lldb/source/Plugins/Protocol/MCP/Resource.cpp 
b/lldb/source/Plugins/Protocol/MCP/Resource.cpp
index e94d2cdd65e07..581424510d4cf 100644
--- a/lldb/source/Plugins/Protocol/MCP/Resource.cpp
+++ b/lldb/source/Plugins/Protocol/MCP/Resource.cpp
@@ -8,7 +8,6 @@
 #include "lldb/Core/Debugger.h"
 #include "lldb/Core/Module.h"
 #include "lldb/Protocol/MCP/MCPError.h"
-#include "lldb/Target/Platform.h"
 
 using namespace lldb_private;
 using namespace lldb_private::mcp;
@@ -124,7 +123,7 @@ DebuggerResourceProvider::GetResources() const {
   return resources;
 }
 
-llvm::Expected<lldb_protocol::mcp::ResourceResult>
+llvm::Expected<lldb_protocol::mcp::ReadResourceResult>
 DebuggerResourceProvider::ReadResource(llvm::StringRef uri) const {
 
   auto [protocol, path] = uri.split("://");
@@ -161,7 +160,7 @@ DebuggerResourceProvider::ReadResource(llvm::StringRef uri) 
const {
   return ReadDebuggerResource(uri, debugger_idx);
 }
 
-llvm::Expected<lldb_protocol::mcp::ResourceResult>
+llvm::Expected<lldb_protocol::mcp::ReadResourceResult>
 DebuggerResourceProvider::ReadDebuggerResource(llvm::StringRef uri,
                                                lldb::user_id_t debugger_id) {
   lldb::DebuggerSP debugger_sp = Debugger::FindDebuggerWithID(debugger_id);
@@ -173,17 +172,17 @@ 
DebuggerResourceProvider::ReadDebuggerResource(llvm::StringRef uri,
   debugger_resource.name = debugger_sp->GetInstanceName();
   debugger_resource.num_targets = debugger_sp->GetTargetList().GetNumTargets();
 
-  lldb_protocol::mcp::ResourceContents contents;
+  lldb_protocol::mcp::TextResourceContents contents;
   contents.uri = uri;
   contents.mimeType = kMimeTypeJSON;
   contents.text = llvm::formatv("{0}", toJSON(debugger_resource));
 
-  lldb_protocol::mcp::ResourceResult result;
+  lldb_protocol::mcp::ReadResourceResult result;
   result.contents.push_back(contents);
   return result;
 }
 
-llvm::Expected<lldb_protocol::mcp::ResourceResult>
+llvm::Expected<lldb_protocol::mcp::ReadResourceResult>
 DebuggerResourceProvider::ReadTargetResource(llvm::StringRef uri,
                                              lldb::user_id_t debugger_id,
                                              size_t target_idx) {
@@ -209,12 +208,12 @@ 
DebuggerResourceProvider::ReadTargetResource(llvm::StringRef uri,
   if (lldb::PlatformSP platform_sp = target_sp->GetPlatform())
     target_resource.platform = platform_sp->GetName();
 
-  lldb_protocol::mcp::ResourceContents contents;
+  lldb_protocol::mcp::TextResourceContents contents;
   contents.uri = uri;
   contents.mimeType = kMimeTypeJSON;
   contents.text = llvm::formatv("{0}", toJSON(target_resource));
 
-  lldb_protocol::mcp::ResourceResult result;
+  lldb_protocol::mcp::ReadResourceResult result;
   result.contents.push_back(contents);
   return result;
 }
diff --git a/lldb/source/Plugins/Protocol/MCP/Resource.h 
b/lldb/source/Plugins/Protocol/MCP/Resource.h
index e2382a74f796b..0c6576602905e 100644
--- a/lldb/source/Plugins/Protocol/MCP/Resource.h
+++ b/lldb/source/Plugins/Protocol/MCP/Resource.h
@@ -11,7 +11,11 @@
 
 #include "lldb/Protocol/MCP/Protocol.h"
 #include "lldb/Protocol/MCP/Resource.h"
-#include "lldb/lldb-private.h"
+#include "lldb/lldb-forward.h"
+#include "lldb/lldb-types.h"
+#include "llvm/ADT/StringRef.h"
+#include "llvm/Support/Error.h"
+#include <cstddef>
 #include <vector>
 
 namespace lldb_private::mcp {
@@ -21,9 +25,8 @@ class DebuggerResourceProvider : public 
lldb_protocol::mcp::ResourceProvider {
   using ResourceProvider::ResourceProvider;
   virtual ~DebuggerResourceProvider() = default;
 
-  virtual std::vector<lldb_protocol::mcp::Resource>
-  GetResources() const override;
-  virtual llvm::Expected<lldb_protocol::mcp::ResourceResult>
+  std::vector<lldb_...
[truncated]

``````````

</details>


https://github.com/llvm/llvm-project/pull/155460
_______________________________________________
lldb-commits mailing list
lldb-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits

Reply via email to