2025-03-16 17:17:01 +08:00
# ifndef HUMANUS_TOOL_BASH_H
# define HUMANUS_TOOL_BASH_H
# include "base.h"
2025-03-19 18:44:54 +08:00
# include "mcp_stdio_client.h"
# include "toml.hpp"
# include "config.h"
2025-03-16 17:17:01 +08:00
# include <filesystem>
namespace humanus {
// A tool for executing shell commands using MCP shell server
2025-03-20 01:12:15 +08:00
// https://github.com/kevinwatt/shell-mcp.git
2025-03-16 17:17:01 +08:00
struct Shell : BaseTool {
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 "
2025-03-20 01:12:15 +08:00
]
2025-03-16 17:17:01 +08:00
} ,
" args " : {
" type " : " array " ,
" description " : " Additional arguments to pass to the command "
} ,
" timeout " : {
" type " : " number " ,
" description " : " Execution timeout in ms "
}
} ,
" required " : [ " command " ]
} ) json " );
2025-03-20 01:12:15 +08:00
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 "
} ;
2025-03-16 22:56:03 +08:00
Shell ( ) : BaseTool ( name_ , description_ , parameters_ ) { }
2025-03-16 17:17:01 +08:00
ToolResult execute ( const json & args ) override {
try {
2025-03-17 16:35:11 +08:00
// Ensure client is initialized
2025-03-16 17:17:01 +08:00
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 {
2025-03-20 01:12:15 +08:00
return ToolError ( " 'command' is required " ) ;
2025-03-16 17:17:01 +08:00
}
2025-03-20 01:12:15 +08:00
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 ;
} ) ) ;
}
2025-03-16 17:17:01 +08:00
2025-03-17 16:35:11 +08:00
// Call shell tool
2025-03-20 01:12:15 +08:00
json result = _client - > call_tool ( " shell_ " + command , args ) ;
2025-03-16 17:17:01 +08:00
bool is_error = result . value ( " isError " , false ) ;
2025-03-17 16:35:11 +08:00
// Return different ToolResult based on whether there is an error
2025-03-16 17:17:01 +08:00
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