#ifndef HUMANUS_TOOL_GOOGLE_SEARCH_H #define HUMANUS_TOOL_GOOGLE_SEARCH_H #include "../mcp/common/httplib.h" #include "base.h" namespace humanus { struct GoogleSearch : BaseTool { inline static const std::string name_ = "google_search"; inline static const std::string description_ = R"(Perform a Google search and return a list of relevant links. Use this tool when you need to find information on the web, get up-to-date data, or research specific topics. The tool returns a list of URLs that match the search query.)"; inline static const json parameters_ = json::parse(R"json( { "type": "object", "properties": { "query": { "type": "string", "description": "(required) The search query to submit to Google.", }, "num_results": { "type": "integer", "description": "(optional) The number of search results to return. Default is 10.", "default": 10, }, }, "required": ["query"], })json"); GoogleSearch() : BaseTool(name_, description_, parameters_) {} ToolResult execute(const json& args) override { try { std::string query = args["query"]; int num_results = args.value("num_results", 10); // 创建HTTP客户端连接到serper.dev API httplib::Client cli("https://api.serper.dev"); // 准备请求体 json request_body = { {"q", query}, {"num", num_results} }; // 设置请求头 const char* api_key = std::getenv("X_API_KEY"); if (!api_key) { return ToolError("X_API_KEY is not set"); } httplib::Headers headers = { {"Content-Type", "application/json"}, {"X-API-KEY", api_key} }; // 发送POST请求 auto res = cli.Post("/search", headers, request_body.dump(), "application/json"); if (!res) { return ToolError("Failed to connect to search API"); } if (res->status != 200) { return ToolError("Search API returned status code = " + std::to_string(res->status) + ", body = " + res->body); } // 解析响应 json response = json::parse(res->body); // 格式化结果 std::string result = "Search results for: " + query + "\n\n"; if (response.contains("organic") && response["organic"].is_array()) { for (size_t i = 0; i < response["organic"].size() && i < static_cast(num_results); ++i) { const auto& item = response["organic"][i]; result += std::to_string(i+1) + ". " + item.value("title", "No title") + "\n"; result += " URL: " + item.value("link", "No link") + "\n"; result += " Snippet: " + item.value("snippet", "No description") + "\n\n"; } } else { result += "No results found."; } return ToolResult(result); } catch (const std::exception& e) { return ToolResult("Error executing Google search: " + std::string(e.what())); } } }; } #endif // OPEMANUS_TOOL_GOOGLE_SEARCH_H