LLDB mainline
Plugins/Protocol/MCP/Tool.cpp
Go to the documentation of this file.
1//===- Tool.cpp -----------------------------------------------------------===//
2//
3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4// See https://llvm.org/LICENSE.txt for license information.
5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6//
7//===----------------------------------------------------------------------===//
8
9#include "Tool.h"
13
14using namespace lldb_private;
15using namespace lldb_protocol;
16using namespace lldb_private::mcp;
17using namespace llvm;
18
19namespace {
20struct CommandToolArguments {
21 uint64_t debugger_id;
22 std::string arguments;
23};
24
25bool fromJSON(const llvm::json::Value &V, CommandToolArguments &A,
26 llvm::json::Path P) {
27 llvm::json::ObjectMapper O(V, P);
28 return O && O.map("debugger_id", A.debugger_id) &&
29 O.mapOptional("arguments", A.arguments);
30}
31
32/// Helper function to create a CallToolResult from a string output.
34createTextResult(std::string output, bool is_error = false) {
36 text_result.content.emplace_back(
37 lldb_protocol::mcp::TextContent{{std::move(output)}});
38 text_result.isError = is_error;
39 return text_result;
40}
41
42} // namespace
43
44llvm::Expected<lldb_protocol::mcp::CallToolResult>
46 if (!std::holds_alternative<json::Value>(args))
47 return createStringError("CommandTool requires arguments");
48
49 json::Path::Root root;
50
51 CommandToolArguments arguments;
52 if (!fromJSON(std::get<json::Value>(args), arguments, root))
53 return root.getError();
54
55 lldb::DebuggerSP debugger_sp =
56 Debugger::FindDebuggerWithID(arguments.debugger_id);
57 if (!debugger_sp)
58 return createStringError(
59 llvm::formatv("no debugger with id {0}", arguments.debugger_id));
60
61 // FIXME: Disallow certain commands and their aliases.
62 CommandReturnObject result(/*colors=*/false);
63 debugger_sp->GetCommandInterpreter().HandleCommand(
64 arguments.arguments.c_str(), eLazyBoolYes, result);
65
66 std::string output;
67 llvm::StringRef output_str = result.GetOutputString();
68 if (!output_str.empty())
69 output += output_str.str();
70
71 std::string err_str = result.GetErrorString();
72 if (!err_str.empty()) {
73 if (!output.empty())
74 output += '\n';
75 output += err_str;
76 }
77
78 return createTextResult(output, !result.Succeeded());
79}
80
81std::optional<llvm::json::Value> CommandTool::GetSchema() const {
82 llvm::json::Object id_type{{"type", "number"}};
83 llvm::json::Object str_type{{"type", "string"}};
84 llvm::json::Object properties{{"debugger_id", std::move(id_type)},
85 {"arguments", std::move(str_type)}};
86 llvm::json::Array required{"debugger_id"};
87 llvm::json::Object schema{{"type", "object"},
88 {"properties", std::move(properties)},
89 {"required", std::move(required)}};
90 return schema;
91}
static llvm::Error createStringError(const char *format, Args &&...args)
Definition Resource.cpp:59
std::string GetErrorString(bool with_diagnostics=true) const
Return the errors as a string.
llvm::StringRef GetOutputString() const
static lldb::DebuggerSP FindDebuggerWithID(lldb::user_id_t id)
std::optional< llvm::json::Value > GetSchema() const override
llvm::Expected< lldb_protocol::mcp::CallToolResult > Call(const lldb_protocol::mcp::ToolArguments &args) override
A class that represents a running process on the host machine.
bool fromJSON(const llvm::json::Value &value, TraceSupportedResponse &info, llvm::json::Path path)
std::variant< std::monostate, llvm::json::Value > ToolArguments
Definition Protocol.h:190
std::shared_ptr< lldb_private::Debugger > DebuggerSP
The server’s response to a tool call.
Definition Protocol.h:299
std::vector< ContentBlock > content
A list of content objects that represent the unstructured result of the tool call.
Definition Protocol.h:302
bool isError
Whether the tool call ended in an error.
Definition Protocol.h:316
Text provided to or from an LLM.
Definition Protocol.h:169