humanus.cpp/tool/shell.h

129 lines
4.7 KiB
C++

#ifndef HUMANUS_TOOL_BASH_H
#define HUMANUS_TOOL_BASH_H
#include "base.h"
#include "mcp_stdio_client.h"
#include "toml.hpp"
#include "config.h"
#include <filesystem>
namespace humanus {
// A tool for executing shell commands using MCP shell server
// https://github.com/kevinwatt/shell-mcp.git
struct Shell : BaseMCPTool {
inline static const std::string name_ = "shell";
inline static const std::string description_ = "Execute a shell command in the terminal.";
inline static const json parameters_ = json::parse(R"json({
"type": "object",
"properties": {
"command": {
"type": "string",
"description": "Command to execute. Available commands:\n- ls: List directory contents\n- cat: Concatenate and display file contents\n- pwd: Show current working directory\n- df: Show disk usage\n- echo: Display text\n- ps: Show process status\n- free: Show memory usage\n- uptime: Show system uptime\n- date: Show system date and time\n- grep: Search text patterns in files\n- w: Show who is logged on and what they are doing\n- whois: Query WHOIS domain registration information\n- find: Search for files in a directory hierarchy\n- netstat: Network connection information\n- lspci: List PCI devices\n- lsusb: List USB devices\n- dig: DNS lookup utility\n- nslookup: Query DNS records\n- ip: Show / manipulate routing, network devices, interfaces and tunnels\n- whereis: Locate the binary, source, and manual page files for a command",
"enum": [
"ls",
"cat",
"pwd",
"df",
"echo",
"ps",
"free",
"uptime",
"date",
"grep",
"w",
"whois",
"find",
"netstat",
"lspci",
"lsusb",
"dig",
"nslookup",
"ip",
"whereis"
]
},
"args": {
"type": "array",
"description": "Additional arguments to pass to the command"
},
"timeout": {
"type": "number",
"description": "Execution timeout in ms"
}
},
"required": ["command"]
})json");
inline static std::set<std::string> allowed_commands = {
"ls",
"cat",
"pwd",
"df",
// "echo", // Not working now
"ps",
"free",
"uptime",
"date",
"grep",
"w",
"whois",
"find",
"netstat",
"lspci",
"lsusb",
"dig",
"nslookup",
"ip",
"whereis"
};
Shell() : BaseMCPTool(name_, description_, parameters_) {}
ToolResult execute(const json& args) override {
try {
// Ensure client is initialized
if (!_client) {
return ToolError("Failed to initialize shell client");
}
std::string command;
if (args.contains("command")) {
if (args["command"].is_string()) {
command = args["command"].get<std::string>();
} else {
return ToolError("Invalid command format");
}
} else {
return ToolError("'command' is required");
}
if (allowed_commands.find(command) == allowed_commands.end()) {
return ToolError("Unknown command '" + command + "'. Please use one of the following commands: " +
std::accumulate(allowed_commands.begin(), allowed_commands.end(), std::string(),
[](const std::string& a, const std::string& b) {
return a + (a.empty() ? "" : ", ") + b;
}));
}
// Call shell tool
json result = _client->call_tool("shell_" + command, args);
bool is_error = result.value("isError", false);
// Return different ToolResult based on whether there is an error
if (is_error) {
return ToolError(result.value("content", json::array()));
} else {
return ToolResult(result.value("content", json::array()));
}
} catch (const std::exception& e) {
return ToolError("Error executing shell command: " + std::string(e.what()));
}
}
};
}
#endif // HUMANUS_TOOL_BASH_H