cpp-mcp/src/mcp_tool.cpp

164 lines
4.7 KiB
C++
Raw Normal View History

2025-03-08 22:49:19 +08:00
/**
* @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