Skip to content

LeandroPG19/cuba-exec

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

5 Commits
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

🚀 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.

About

Advanced shell command execution MCP server — process lifecycle, bounded output, POSIX signals

Topics

Resources

License

Contributing

Stars

Watchers

Forks

Releases

No releases published

Packages

 
 
 

Contributors

Languages