Community-maintained Python implementation. Not affiliated with or endorsed by the OliveTin project.
A hardened MCP server that exposes OliveTin actions as tools, with built-in human-in-the-loop approval for destructive operations.
claude mcp add olivetin -e OLIVETIN_URL=http://localhost:1337 -- uvx --from git+https://github.com/vaddisrinivas/olivetin-mcp.git olivetin-mcpAI agents (Claude, GPT, etc.) are increasingly capable of running shell commands and managing infrastructure. But there's a fundamental trust gap:
- Without approval gates, an agent can
rm -rf /, restart production, or leak secrets — and you only find out after the damage is done. - Without action discovery, agents guess at commands instead of using your pre-defined, parameterized, tested actions.
- Without audit trails, you can't answer "what did the agent do and why?"
Giving an AI agent a raw shell is like giving a new hire root access on day one. You wouldn't do it. Instead, you'd give them a runbook of approved actions and require sign-off for anything destructive. That's exactly what this project does.
OliveTin is the runbook — safe, parameterized shell actions with a web UI. olivetin-mcp is the bridge that lets AI agents use that runbook, with human approval built in.
OliveTin lets you define shell commands as safe, parameterized actions with a web UI. olivetin-mcp bridges those actions into the Model Context Protocol so Claude (or any MCP client) can discover and execute them — with automatic human approval gates for anything destructive.
Without this bridge: Claude can't see or trigger your OliveTin actions. You'd need to manually copy-paste commands or build custom integrations.
With this bridge: Claude discovers all your actions automatically, validates arguments, and asks for human approval before running anything dangerous.
| Approach | Pros | Cons |
|---|---|---|
| Direct shell via Claude | Simple, no setup | No action discovery, no approval gates, no audit trail |
| OliveTin Web UI alone | Built-in approval UI | No AI integration, manual operation only |
| OliveTin API directly | Full control | Manual auth, no MCP schema, no standardized discovery |
| olivetin-mcp (this) | Auto-discovery, approval chain, hardened container, MCP standard | Requires MCP client + OliveTin |
┌──────────────┐ SSE ┌──────────────────┐ REST API ┌──────────────┐
│ MCP Client │ <──────────────> │ olivetin-mcp │ ──────────────────> │ OliveTin │
│ (Claude, etc)│ port 9003 │ (this server) │ port 1337 │ (host) │
└──────────────┘ └──────────────────┘ └──────────────┘
│
v
┌──────────────┐
│ Approval UI │
│ /pending/:tok │
└──────────────┘
- Discovers OliveTin actions and registers each as an MCP tool
- Classifies actions as read-only or destructive based on naming conventions
- Gates destructive actions behind a two-step approval chain:
- MCP native elicitation (inline dialog in Claude Code / Claude Desktop)
- URL-based approval (human visits
/pending/<token>to approve or deny)
- Executes approved actions via the OliveTin REST API
- Exposes resources for action catalogs, execution logs, and pending approvals
- Comprehensive OliveTin API coverage (actions, logs, execution status, kill)
- Three authentication modes (reverse-proxy headers, JWT, HTTP Basic)
- Built-in static tools:
brave_search,render_diagram,render_chart - Rate limiting per action
- Structured logging with
structlog - Retry with exponential backoff via
tenacity - Security headers on all HTML responses
/healthzhealth check endpoint
- Python 3.11+
- OliveTin running and accessible — Installation guide | GitHub | Discord
claude mcp add olivetin -e OLIVETIN_URL=http://localhost:1337 -- uvx --from git+https://github.com/vaddisrinivas/olivetin-mcp.git olivetin-mcpThis installs and runs via stdio transport. For SSE (Docker), see below.
docker build -t olivetin-mcp .
docker run -d \
-p 9003:9003 \
-e OLIVETIN_URL=http://host.docker.internal:1337 \
olivetin-mcpA docker-compose.yml is included for running olivetin-mcp alongside OliveTin:
docker compose up -dpip install olivetin-mcp
python -m maingit clone https://github.com/vaddisrinivas/olivetin-mcp.git
cd olivetin-mcp
pip install -e ".[test]"
python main.py # stdio (for claude mcp add)
python main.py --sse # SSE server on port 9003 (for Docker)# Via uvx (no install needed):
claude mcp add olivetin -e OLIVETIN_URL=http://localhost:1337 -- uvx --from git+https://github.com/vaddisrinivas/olivetin-mcp.git olivetin-mcp
# Or if installed locally:
claude mcp add olivetin -- olivetin-mcpFor SSE mode (Docker), add to your claude_desktop_config.json:
{
"mcpServers": {
"olivetin": {
"url": "http://localhost:9003/sse"
}
}
}claude mcp add olivetin --transport sse http://localhost:9003/sseAll configuration is via environment variables. Copy .env.example to .env to get started.
| Variable | Default | Description |
|---|---|---|
HOST_BRIDGE_PORT |
9003 |
MCP SSE server port |
OLIVETIN_URL |
http://host.docker.internal:1337 |
OliveTin API URL |
APPROVAL_TIMEOUT_SECS |
120 |
Seconds to wait for approval decision |
APPROVAL_BASE_URL |
"" |
Public URL for approval links (e.g. https://bridge.example.com) |
ELICITATION_TIMEOUT_SECS |
30 |
MCP elicitation dialog timeout |
SECRETS_DIR |
/run/secrets |
Docker secrets mount path |
ACTION_REFRESH_INTERVAL_SECS |
300 |
Action catalog refresh interval |
Pick one mode depending on your OliveTin setup:
Reverse-proxy headers (e.g. Authelia, Authentik):
OLIVETIN_REMOTE_USER=serviceaccount
OLIVETIN_REMOTE_GROUPS=admins,operators
OLIVETIN_USER_HEADER=X-Remote-User # optional, default shown
OLIVETIN_GROUPS_HEADER=X-Remote-Groups # optional, default shownJWT bearer token:
OLIVETIN_JWT_TOKEN=eyJhbGci...
# or mount as /run/secrets/olivetin_jwt_tokenHTTP Basic auth:
OLIVETIN_BASIC_USER=admin
OLIVETIN_BASIC_PASS=changemeThis project is designed to be run as a hardened container:
- Non-root user (
bridge:10001) with no login shell - Stripped attack surface: all shells, network tools, and compilers removed
- No runtime pip: package manager removed after build
- Read-only filesystem: designed for
read_only: truein Docker Compose - Dropped capabilities: all Linux capabilities can be dropped
- Human-in-the-loop: destructive actions require explicit approval
- XSS protection: Jinja2
autoescape=Trueon all templates - Cryptographic tokens: approval tokens via
secrets.token_urlsafe(16) - Security headers:
X-Frame-Options,CSP,X-Content-Type-Optionson all HTML responses - SSRF protection: diagram specs checked for disallowed URI schemes
See SECURITY.md for vulnerability reporting and threat model.
Each OliveTin action is registered as an MCP tool. Read-only actions (prefixed with [read-only] or ro_ binding ID) execute immediately. All others go through the approval chain.
| Tool | Description |
|---|---|
list_olivetin_actions |
List all actions with schemas and approval status |
get_execution_logs |
Recent execution history |
get_execution_status |
Status of a running execution |
kill_action |
Kill a running execution |
reload_actions |
Force refresh the action catalog |
list_pending_approvals |
Show pending approval queue |
brave_search |
Web search via Brave Search API |
render_diagram |
Render Mermaid/PlantUML/D2 diagrams |
render_chart |
Render charts via QuickChart |
| URI | Description |
|---|---|
olivetin://actions |
Full action catalog (JSON) |
olivetin://actions/{id}/help |
Detailed action documentation |
olivetin://logs |
Recent execution history |
olivetin://logs/{id} |
Action-specific logs |
olivetin://pending |
Pending approval queue |
Here's how OliveTin actions map to MCP tools:
# In your OliveTin config.yaml
actions:
# This action executes immediately (no approval) because of [read-only] prefix
- title: "[read-only] Get Service Status"
shell: docker ps --format 'table {{.Names}}\t{{.Status}}'
# This action requires human approval before execution
- title: Deploy Service
shell: cd /srv/{{ service }} && docker compose pull && docker compose up -d
arguments:
- name: service
type: ascii_identifier
choices:
- value: api
- value: web
- value: workerQ: Claude shows the action but gets "Could not reach OliveTin"
- Verify OliveTin is running:
curl http://your-olivetin:1337/api/GetDashboard -X POST -d '{}' - If using Docker, ensure network connectivity (use
http://host.docker.internal:1337on Docker Desktop, or the container network name in Docker Compose) - Check
OLIVETIN_URLenv var
Q: Actions require approval but I want some to be read-only
Prefix the action title with [read-only] or the binding ID with ro_ in your OliveTin config. The bridge automatically classifies these as safe.
Q: Approval links don't work / show "Not Found"
Set APPROVAL_BASE_URL to the publicly reachable URL of the bridge (e.g. http://192.168.1.10:9003). The default localhost only works when the browser is on the same machine.
Q: MCP client times out waiting for approval
The default approval timeout is 120 seconds. Increase APPROVAL_TIMEOUT_SECS if needed. The elicitation dialog (inline in Claude) times out after 30 seconds (ELICITATION_TIMEOUT_SECS) before falling back to URL-based approval.
Q: Actions aren't showing up in Claude
- Check the bridge logs for
actions_loaded— it should show the count - Run the
reload_actionstool to force a refresh - Verify OliveTin has actions configured and they aren't marked
hidden: true
Q: How do I use Brave Search?
Mount the API key as a Docker secret at /run/secrets/brave_api_key, or set BRAVE_API_KEY in your environment. Get a key at brave.com/search/api.
- Single maintainer: Bus factor of 1. See GOVERNANCE.md for co-maintainer path.
- No end-to-end encryption: Communication between this bridge and OliveTin is HTTP by default. Use HTTPS in production or keep them on the same host/network.
- Approval UI is basic: The URL-based approval page has no authentication beyond the cryptographic token. Anyone with the link can approve/deny. Keep approval URLs private.
- Not a security boundary: This bridge adds an approval layer, but it trusts OliveTin's API. If OliveTin is compromised, the bridge can't protect you.
- Young project: This is v0.1.0. Expect rough edges. File issues.
- OliveTin — The automation platform this bridge connects to. Written in Go by James Read. Docs | Discord
- Model Context Protocol — The open standard for AI tool integration. Spec | GitHub
- FastMCP — The Python MCP framework this server is built on.
- OpenClaw — Another approach to AI agent orchestration (different architecture).
The motivation: routing AI agents through OliveTin's pre-defined, parameterized actions is fundamentally safer than giving agents raw shell access. The approval chain ensures a human is always in the loop for anything destructive.
# Install all extras
make install
# Run all CI checks locally
make ci
# Or individually:
make test # pytest with coverage
make lint # ruff check
make type # mypy
make format # auto-formatSee CONTRIBUTING.md for more details, and ARCHITECTURE.md for codebase overview.