Cuba-Exec

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.

Category
Visit Server

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.

Recommended Servers

playwright-mcp

playwright-mcp

A Model Context Protocol server that enables LLMs to interact with web pages through structured accessibility snapshots without requiring vision models or screenshots.

Official
Featured
TypeScript
Magic Component Platform (MCP)

Magic Component Platform (MCP)

An AI-powered tool that generates modern UI components from natural language descriptions, integrating with popular IDEs to streamline UI development workflow.

Official
Featured
Local
TypeScript
Audiense Insights MCP Server

Audiense Insights MCP Server

Enables interaction with Audiense Insights accounts via the Model Context Protocol, facilitating the extraction and analysis of marketing insights and audience data including demographics, behavior, and influencer engagement.

Official
Featured
Local
TypeScript
VeyraX MCP

VeyraX MCP

Single MCP tool to connect all your favorite tools: Gmail, Calendar and 40 more.

Official
Featured
Local
graphlit-mcp-server

graphlit-mcp-server

The Model Context Protocol (MCP) Server enables integration between MCP clients and the Graphlit service. Ingest anything from Slack to Gmail to podcast feeds, in addition to web crawling, into a Graphlit project - and then retrieve relevant contents from the MCP client.

Official
Featured
TypeScript
Kagi MCP Server

Kagi MCP Server

An MCP server that integrates Kagi search capabilities with Claude AI, enabling Claude to perform real-time web searches when answering questions that require up-to-date information.

Official
Featured
Python
E2B

E2B

Using MCP to run code via e2b.

Official
Featured
Neon Database

Neon Database

MCP server for interacting with Neon Management API and databases

Official
Featured
Exa Search

Exa Search

A Model Context Protocol (MCP) server lets AI assistants like Claude use the Exa AI Search API for web searches. This setup allows AI models to get real-time web information in a safe and controlled way.

Official
Featured
Qdrant Server

Qdrant Server

This repository is an example of how to create a MCP server for Qdrant, a vector search engine.

Official
Featured