Cuba-Exec
Advanced shell command execution for AI agents — a Model Context Protocol (MCP) server with security policy engine, process lifecycle management, bounded output capture, POSIX signals, and token-efficient responses.
README
🚀 Cuba-Exec
Advanced shell command execution for AI agents — A Model Context Protocol (MCP) server with security policy engine, process lifecycle management, bounded output capture, POSIX signals, and token-efficient responses.
6 tools. Zero configuration. POSIX-native. Security by default.
Why Cuba-Exec?
Existing command execution MCPs are thin wrappers over subprocess.run. Cuba-Exec solves the real problems:
| Problem | Existing MCPs | Cuba-Exec |
|---|---|---|
| Output overflow (cat /dev/urandom) | ❌ OOM crash | ✅ 64KB bounded |
| Background processes | ❌ Sync only | ✅ Start/status/signal |
| Kill child processes (npm run dev) | ❌ Orphaned children | ✅ Process group kill (setsid) |
| Send stdin (REPLs, prompts) | ❌ Not supported | ✅ Full stdin pipe |
| POSIX signals (SIGTERM, SIGKILL) | ❌ Not supported | ✅ 5 signals + graceful shutdown |
| Command allowlist/blocklist | ⚠️ Some | ✅ Both + shell operator validation |
| Directory restriction | ⚠️ Rare | ✅ Path-resolved anti-traversal |
| Audit logging | ❌ None | ✅ Structured JSON to stderr |
| Token-efficient output | ❌ Verbose JSON | ✅ TOON compact format |
| Idle process cleanup | ❌ Resource leak | ✅ 1-hour TTL auto-cleanup |
| Fork bomb protection | ❌ None | ✅ Semaphore(20) |
| Process discovery | ❌ None | ✅ List all managed processes |
Quick Start
1. Prerequisites
- Python 3.14+
- Linux/macOS (POSIX required for process groups)
2. Install
git clone https://github.com/LeandroPG19/cuba-exec.git
cd cuba-exec
uv venv && uv pip install -e .
3. Configure your AI editor
{
"mcpServers": {
"cuba-exec": {
"command": "/path/to/cuba-exec/.venv/bin/python",
"args": ["-m", "cuba_exec"]
}
}
}
Zero environment variables needed. Zero configuration files. It just works — with 25 dangerous commands blocked by default.
The 6 Tools
run — Execute and wait
run(command="ls -la", cwd="/tmp", timeout_ms=5000)
| Parameter | Type | Default | Description |
|---|---|---|---|
command |
string | required | Shell command |
cwd |
string | None | Working directory |
env |
dict | None | Environment variables (merged with current) |
timeout_ms |
int | 30000 | Timeout in milliseconds |
max_output |
int | 65536 | Output buffer size (bytes) |
shell |
string | /bin/sh | Shell executable |
Response:
[exit:0 time:12ms trunc:no]
total 156
drwxrwxrwt 22 root root 4096 Mar 8 2026 .
...
start — Background process
start(command="npm run dev", cwd="/app")
Response:
[pid:12345 state:running]
Background process started. Use status(12345) to check output.
status — Check background process
status(pid=12345, tail_bytes=4096)
Response:
[pid:12345 state:running exit:- time:5432ms bytes:8192 trunc:no]
Server running on http://localhost:3000
send_signal — POSIX signals
send_signal(pid=12345, sig="SIGTERM")
SIGTERM triggers graceful shutdown: SIGTERM → wait 5s → SIGKILL.
Valid signals: SIGTERM, SIGKILL, SIGINT, SIGHUP, SIGQUIT.
send_input — stdin pipe
send_input(pid=12345, stdin="print('hello')\n")
For interactive processes (Python REPL, bash prompt, etc.).
list_processes — Process discovery
list_processes()
Response:
[processes:2]
pid:12345 state:running exit:- time:5432ms bytes:8192 cmd:npm run dev
pid:12346 state:completed exit:0 time:1200ms bytes:256 cmd:echo done
🛡️ Security Policy Engine
Cuba-Exec includes a multi-layer security engine — the most comprehensive of any MCP command server.
Security Layers
| Layer | Description | Config |
|---|---|---|
| Command Allowlist | Only listed commands can execute | CUBA_EXEC_ALLOWED_COMMANDS |
| Command Blocklist | Dangerous commands always rejected | CUBA_EXEC_BLOCKED_COMMANDS |
| Shell Operator Validation | Validates each sub-command after ;, &&, ||, | |
Automatic |
| Directory Restriction | Restrict cwd to allowed paths (anti-traversal) |
CUBA_EXEC_ALLOWED_DIRS |
| Audit Logging | Structured JSON log of every execution | CUBA_EXEC_AUDIT |
Default Behavior (Zero Config)
Out of the box, Cuba-Exec blocks 25 dangerous commands:
rm, dd, mkfs, shutdown, reboot, halt, poweroff, init, systemctl,
passwd, chown, chmod, chgrp, mount, umount, fdisk, parted,
iptables, nft, ip6tables, crontab, at, useradd, userdel,
groupadd, groupdel, visudo
Production Hardening
export CUBA_EXEC_ALLOWED_COMMANDS="ls,cat,echo,grep,find,head,tail,wc,git,python3,node,npm"
export CUBA_EXEC_BLOCKED_COMMANDS="rm,dd,mkfs,shutdown"
export CUBA_EXEC_ALLOWED_DIRS="/home/user/project,/tmp"
export CUBA_EXEC_AUDIT=1
Shell Operator Bypass Prevention
ls && rm -rf / — the rm after && is validated against blocklist/allowlist too.
Operators parsed: ;, &&, ||, | — each sub-command checked independently.
Audit Log (stderr)
{"ts":"2026-03-08T15:00:00-0600","event":"exec","command":"ls -la","pid":12345,"exit":0,"ms":12,"ok":true}
Output Format (TOON)
All responses use Token-Oriented Object Notation — compact headers that save ~200 tokens per tool call vs verbose JSON.
[exit:0 time:1543ms trunc:no]
...output...
Error Codes
| Error | Exit Code | Field | Example |
|---|---|---|---|
| Command not found | 127 | ENOENT |
nonexistent_binary |
| Permission denied | 126 | EACCES |
cat /etc/shadow |
| Timeout | -1 | TIMEOUT |
sleep 60 with 1s timeout |
| Signal killed | -9 | SIGKILL |
Process killed by signal |
| Blocked by policy | — | BLOCKED |
rm -rf / |
Head+Tail Output Buffer — Shannon (1948)
Command output has high entropy at the extremes (preamble + results/errors) and low entropy in the middle (progress bars, repetitive logs).
┌─────────────┬───────────────────────────────┬──────────────────────────────────────────┐
│ Head (25%) │ Truncated middle │ Tail (75%) │
│ ~16KB │ [... N bytes truncated ...] │ ~48KB (ring buffer) │
└─────────────┴───────────────────────────────┴──────────────────────────────────────────┘
- Head: First 25% of buffer — captures headers, version info
- Tail: Last 75% via ring buffer — captures results, errors (highest entropy)
- Ring buffer: O(1) write, O(C) memory (Cormen et al., CLRS 4th ed.)
- Default: 64KB per process. Max memory: 20 × 64KB = 1.28MB
POSIX Process Groups — IEEE Std 1003.1
npm run dev spawns child processes. Sending SIGTERM to the parent doesn't kill children.
Cuba-Exec creates process groups via setsid:
asyncio.create_subprocess_exec(..., start_new_session=True)
os.killpg(os.getpgid(pid), signal.SIGTERM) # Kills entire tree
Graceful Shutdown
SIGTERM → wait 5s → SIGKILL (if still alive)
Two-phase shutdown (Stevens & Rago, 2013): SIGTERM allows cleanup, SIGKILL is uncatchable.
Configuration
All defaults work out of the box. Override via environment variables:
| Setting | Default | Env Var |
|---|---|---|
| Max concurrent processes | 20 | CUBA_EXEC_MAX_PROCS |
| Output buffer size | 64KB | CUBA_EXEC_BUFFER_SIZE |
| Idle process TTL | 1 hour | CUBA_EXEC_TTL |
| Shutdown timeout | 5s | CUBA_EXEC_SHUTDOWN_TIMEOUT |
| Allowed commands | — (all) | CUBA_EXEC_ALLOWED_COMMANDS |
| Blocked commands | 25 defaults | CUBA_EXEC_BLOCKED_COMMANDS |
| Allowed directories | — (all) | CUBA_EXEC_ALLOWED_DIRS |
| Audit logging | off | CUBA_EXEC_AUDIT |
Architecture
cuba-exec/
├── pyproject.toml # 1 dependency: fastmcp
└── src/
└── cuba_exec/
├── __init__.py
├── __main__.py # Entry point
├── server.py # FastMCP 6 tool definitions (~105 LOC)
├── security.py # SecurityPolicy engine (~135 LOC)
├── process_manager.py # Lifecycle FSM + signals + TTL (~520 LOC)
└── output_buffer.py # Head+Tail ring buffer (~110 LOC)
Total: ~880 LOC. FastMCP SDK handles protocol boilerplate.
Dependencies (1 total)
| Package | Purpose |
|---|---|
fastmcp |
MCP protocol server — auto tool schemas from type hints, Pydantic validation |
Everything else is Python stdlib: asyncio, os, signal, time, json, re, pathlib.
Part of the Cuba Ecosystem
| Project | Purpose |
|---|---|
| Cuba-Memorys | Persistent memory — knowledge graph, Hebbian learning |
| Cuba-Thinking | Sequential reasoning — cognitive engine, NLI, MCTS |
| Cuba-Search | Web search — research, scraping, validation, documentation lookup |
| Cuba-Exec | Shell execution — process lifecycle, security, bounded output, POSIX signals |
Together: memory + reasoning + search + execution — the four pillars of capable AI agents.
Academic References
| # | Citation | Used For |
|---|---|---|
| 1 | Yang et al. (2024). "SWE-agent: Agent-Computer Interfaces." NeurIPS | ACI design, output truncation, guardrails |
| 2 | Shannon (1948). "A Mathematical Theory of Communication" | Information-theoretic output strategy |
| 3 | IEEE Std 1003.1-2024. "POSIX.1: System Interfaces" | Process groups, setsid, signals |
| 4 | Cormen et al. (2022). "Introduction to Algorithms." 4th ed. | Ring buffer O(1) analysis |
| 5 | Dijkstra (1965). "Cooperating Sequential Processes" | Semaphore concurrency limiting |
| 6 | Stevens & Rago (2013). "APUE" 3rd ed. | Process lifecycle, graceful shutdown |
| 7 | TOON (2025). "Token-Oriented Object Notation" | 95-97% token reduction |
| 8 | OWASP (2025). "Top 10 for Agentic Applications" | Security policy design, allowlist/blocklist |
License
CC BY-NC 4.0 — Free to use and modify, not for commercial use.
Author
Leandro Pérez G.
- GitHub: @LeandroPG19
- Email: leandropatodo@gmail.com
推荐服务器
Baidu Map
百度地图核心API现已全面兼容MCP协议,是国内首家兼容MCP协议的地图服务商。
Playwright MCP Server
一个模型上下文协议服务器,它使大型语言模型能够通过结构化的可访问性快照与网页进行交互,而无需视觉模型或屏幕截图。
Magic Component Platform (MCP)
一个由人工智能驱动的工具,可以从自然语言描述生成现代化的用户界面组件,并与流行的集成开发环境(IDE)集成,从而简化用户界面开发流程。
Audiense Insights MCP Server
通过模型上下文协议启用与 Audiense Insights 账户的交互,从而促进营销洞察和受众数据的提取和分析,包括人口统计信息、行为和影响者互动。
VeyraX
一个单一的 MCP 工具,连接你所有喜爱的工具:Gmail、日历以及其他 40 多个工具。
graphlit-mcp-server
模型上下文协议 (MCP) 服务器实现了 MCP 客户端与 Graphlit 服务之间的集成。 除了网络爬取之外,还可以将任何内容(从 Slack 到 Gmail 再到播客订阅源)导入到 Graphlit 项目中,然后从 MCP 客户端检索相关内容。
Kagi MCP Server
一个 MCP 服务器,集成了 Kagi 搜索功能和 Claude AI,使 Claude 能够在回答需要最新信息的问题时执行实时网络搜索。
e2b-mcp-server
使用 MCP 通过 e2b 运行代码。
Neon MCP Server
用于与 Neon 管理 API 和数据库交互的 MCP 服务器
Exa MCP Server
模型上下文协议(MCP)服务器允许像 Claude 这样的 AI 助手使用 Exa AI 搜索 API 进行网络搜索。这种设置允许 AI 模型以安全和受控的方式获取实时的网络信息。