164 lines
4.7 KiB
C++
164 lines
4.7 KiB
C++
|
/**
|
||
|
* @file mcp_tool.cpp
|
||
|
* @brief Implementation of the MCP tools
|
||
|
*
|
||
|
* This file implements the tool-related functionality for the MCP protocol.
|
||
|
* Follows the 2024-11-05 basic protocol specification.
|
||
|
*/
|
||
|
|
||
|
#include "mcp_tool.h"
|
||
|
#include <random>
|
||
|
#include <sstream>
|
||
|
|
||
|
namespace mcp {
|
||
|
|
||
|
// Implementation for tool_registry
|
||
|
void tool_registry::register_tool(const tool& tool, tool_handler handler) {
|
||
|
std::lock_guard<std::mutex> lock(mutex_);
|
||
|
tools_[tool.name] = std::make_pair(tool, handler);
|
||
|
}
|
||
|
|
||
|
bool tool_registry::unregister_tool(const std::string& tool_name) {
|
||
|
std::lock_guard<std::mutex> lock(mutex_);
|
||
|
return tools_.erase(tool_name) > 0;
|
||
|
}
|
||
|
|
||
|
std::pair<tool, tool_handler>* tool_registry::get_tool(const std::string& tool_name) {
|
||
|
std::lock_guard<std::mutex> lock(mutex_);
|
||
|
auto it = tools_.find(tool_name);
|
||
|
if (it != tools_.end()) {
|
||
|
return &(it->second);
|
||
|
}
|
||
|
return nullptr;
|
||
|
}
|
||
|
|
||
|
std::vector<tool> tool_registry::get_all_tools() const {
|
||
|
std::lock_guard<std::mutex> lock(mutex_);
|
||
|
std::vector<tool> result;
|
||
|
for (const auto& [name, tool_pair] : tools_) {
|
||
|
result.push_back(tool_pair.first);
|
||
|
}
|
||
|
return result;
|
||
|
}
|
||
|
|
||
|
json tool_registry::call_tool(const std::string& tool_name, const json& parameters) {
|
||
|
std::lock_guard<std::mutex> lock(mutex_);
|
||
|
|
||
|
auto it = tools_.find(tool_name);
|
||
|
if (it == tools_.end()) {
|
||
|
throw mcp_exception(error_code::method_not_found, "Tool not found: " + tool_name);
|
||
|
}
|
||
|
|
||
|
try {
|
||
|
return it->second.second(parameters);
|
||
|
} catch (const std::exception& e) {
|
||
|
throw mcp_exception(error_code::internal_error,
|
||
|
"Tool execution failed: " + std::string(e.what()));
|
||
|
}
|
||
|
}
|
||
|
|
||
|
// Implementation for tool_builder
|
||
|
tool_builder::tool_builder(const std::string& name)
|
||
|
: name_(name) {
|
||
|
}
|
||
|
|
||
|
tool_builder& tool_builder::with_description(const std::string& description) {
|
||
|
description_ = description;
|
||
|
return *this;
|
||
|
}
|
||
|
|
||
|
tool_builder& tool_builder::add_param(const std::string& name,
|
||
|
const std::string& description,
|
||
|
const std::string& type,
|
||
|
bool required) {
|
||
|
json param = {
|
||
|
{"type", type},
|
||
|
{"description", description}
|
||
|
};
|
||
|
|
||
|
parameters_["properties"][name] = param;
|
||
|
|
||
|
if (required) {
|
||
|
required_params_.push_back(name);
|
||
|
}
|
||
|
|
||
|
return *this;
|
||
|
}
|
||
|
|
||
|
tool_builder& tool_builder::with_string_param(const std::string& name,
|
||
|
const std::string& description,
|
||
|
bool required) {
|
||
|
return add_param(name, description, "string", required);
|
||
|
}
|
||
|
|
||
|
tool_builder& tool_builder::with_number_param(const std::string& name,
|
||
|
const std::string& description,
|
||
|
bool required) {
|
||
|
return add_param(name, description, "number", required);
|
||
|
}
|
||
|
|
||
|
tool_builder& tool_builder::with_boolean_param(const std::string& name,
|
||
|
const std::string& description,
|
||
|
bool required) {
|
||
|
return add_param(name, description, "boolean", required);
|
||
|
}
|
||
|
|
||
|
tool_builder& tool_builder::with_array_param(const std::string& name,
|
||
|
const std::string& description,
|
||
|
const std::string& item_type,
|
||
|
bool required) {
|
||
|
json param = {
|
||
|
{"type", "array"},
|
||
|
{"description", description},
|
||
|
{"items", {
|
||
|
{"type", item_type}
|
||
|
}}
|
||
|
};
|
||
|
|
||
|
parameters_["properties"][name] = param;
|
||
|
|
||
|
if (required) {
|
||
|
required_params_.push_back(name);
|
||
|
}
|
||
|
|
||
|
return *this;
|
||
|
}
|
||
|
|
||
|
tool_builder& tool_builder::with_object_param(const std::string& name,
|
||
|
const std::string& description,
|
||
|
const json& properties,
|
||
|
bool required) {
|
||
|
json param = {
|
||
|
{"type", "object"},
|
||
|
{"description", description},
|
||
|
{"properties", properties}
|
||
|
};
|
||
|
|
||
|
parameters_["properties"][name] = param;
|
||
|
|
||
|
if (required) {
|
||
|
required_params_.push_back(name);
|
||
|
}
|
||
|
|
||
|
return *this;
|
||
|
}
|
||
|
|
||
|
tool tool_builder::build() const {
|
||
|
tool t;
|
||
|
t.name = name_;
|
||
|
t.description = description_;
|
||
|
|
||
|
// Create the parameters schema
|
||
|
json schema = parameters_;
|
||
|
schema["type"] = "object";
|
||
|
|
||
|
if (!required_params_.empty()) {
|
||
|
schema["required"] = required_params_;
|
||
|
}
|
||
|
|
||
|
t.parameters_schema = schema;
|
||
|
|
||
|
return t;
|
||
|
}
|
||
|
|
||
|
} // namespace mcp
|