cpp-mcp/include/mcp_tool.h

239 lines
7.5 KiB
C++

/**
* @file mcp_tool.h
* @brief Tool definitions and helper functions for MCP
*
* This file provides tool-related functionality and abstractions for the MCP protocol.
*/
#ifndef MCP_TOOL_H
#define MCP_TOOL_H
#include "mcp_message.h"
#include <functional>
#include <string>
#include <vector>
#include <map>
#include <memory>
namespace mcp {
// Tool handler function type
using tool_handler = std::function<json(const json&)>;
// MCP Tool definition
struct tool {
std::string name;
std::string description;
json parameters_schema;
// Convert to JSON for API documentation
json to_json() const {
return {
{"name", name},
{"description", description},
{"parameters", parameters_schema}
};
}
};
/**
* @class tool_registry
* @brief Registry for MCP tools
*
* The tool_registry class provides a centralized registry for tools that can
* be used by agents and clients.
*/
class tool_registry {
public:
/**
* @brief Get the singleton instance
* @return Reference to the singleton registry
*/
static tool_registry& instance() {
static tool_registry instance;
return instance;
}
/**
* @brief Register a tool
* @param tool The tool to register
* @param handler The function to call when the tool is invoked
*/
void register_tool(const tool& tool, tool_handler handler);
/**
* @brief Unregister a tool
* @param tool_name The name of the tool to unregister
* @return True if the tool was found and unregistered
*/
bool unregister_tool(const std::string& tool_name);
/**
* @brief Get a tool by name
* @param tool_name The name of the tool
* @return A pair containing the tool definition and handler, or nullptr if not found
*/
std::pair<tool, tool_handler>* get_tool(const std::string& tool_name);
/**
* @brief Get all registered tools
* @return A vector of all registered tools
*/
std::vector<tool> get_all_tools() const;
/**
* @brief Call a tool
* @param tool_name The name of the tool to call
* @param parameters The parameters to pass to the tool
* @return The result of the tool call
* @throws mcp_exception if the tool doesn't exist or execution fails
*/
json call_tool(const std::string& tool_name, const json& parameters);
private:
// Private constructor for singleton
tool_registry() {}
// Mapping of tool names to their definitions and handlers
std::map<std::string, std::pair<tool, tool_handler>> tools_;
// Mutex for thread safety
mutable std::mutex mutex_;
};
/**
* @class tool_builder
* @brief Utility class for building tools with a fluent API
*
* The tool_builder class provides a simple way to create tools with
* a fluent (chain-based) API.
*/
class tool_builder {
public:
/**
* @brief Constructor
* @param name The name of the tool
*/
explicit tool_builder(const std::string& name);
/**
* @brief Set the tool description
* @param description The description
* @return Reference to this builder
*/
tool_builder& with_description(const std::string& description);
/**
* @brief Add a string parameter
* @param name The parameter name
* @param description The parameter description
* @param required Whether the parameter is required
* @return Reference to this builder
*/
tool_builder& with_string_param(const std::string& name,
const std::string& description,
bool required = true);
/**
* @brief Add a number parameter
* @param name The parameter name
* @param description The parameter description
* @param required Whether the parameter is required
* @return Reference to this builder
*/
tool_builder& with_number_param(const std::string& name,
const std::string& description,
bool required = true);
/**
* @brief Add a boolean parameter
* @param name The parameter name
* @param description The parameter description
* @param required Whether the parameter is required
* @return Reference to this builder
*/
tool_builder& with_boolean_param(const std::string& name,
const std::string& description,
bool required = true);
/**
* @brief Add an array parameter
* @param name The parameter name
* @param description The parameter description
* @param item_type The type of the array items ("string", "number", "object", etc.)
* @param required Whether the parameter is required
* @return Reference to this builder
*/
tool_builder& with_array_param(const std::string& name,
const std::string& description,
const std::string& item_type,
bool required = true);
/**
* @brief Add an object parameter
* @param name The parameter name
* @param description The parameter description
* @param properties JSON schema for the object properties
* @param required Whether the parameter is required
* @return Reference to this builder
*/
tool_builder& with_object_param(const std::string& name,
const std::string& description,
const json& properties,
bool required = true);
/**
* @brief Build the tool
* @return The constructed tool
*/
tool build() const;
private:
std::string name_;
std::string description_;
json parameters_;
std::vector<std::string> required_params_;
// Helper to add a parameter of any type
tool_builder& add_param(const std::string& name,
const std::string& description,
const std::string& type,
bool required);
};
/**
* @brief Create a simple tool with a function-based approach
* @param name Tool name
* @param description Tool description
* @param handler Function to handle tool invocations
* @param parameter_definitions A vector of parameter definitions as {name, description, type, required}
* @return The created tool
*/
inline tool create_tool(
const std::string& name,
const std::string& description,
const std::vector<std::tuple<std::string, std::string, std::string, bool>>& parameter_definitions) {
tool_builder builder(name);
builder.with_description(description);
for (const auto& [param_name, param_desc, param_type, required] : parameter_definitions) {
if (param_type == "string") {
builder.with_string_param(param_name, param_desc, required);
} else if (param_type == "number") {
builder.with_number_param(param_name, param_desc, required);
} else if (param_type == "boolean") {
builder.with_boolean_param(param_name, param_desc, required);
} else if (param_type == "array") {
builder.with_array_param(param_name, param_desc, "string", required);
} else if (param_type == "object") {
builder.with_object_param(param_name, param_desc, json::object(), required);
}
}
return builder.build();
}
} // namespace mcp
#endif // MCP_TOOL_H