Skip to main content
Glama
README.md
# Sentinel MCP

**Safe, allowlisted tool execution for AI agents.**

[![CI](https://github.com/JureJan/sentinel/actions/workflows/ci.yml/badge.svg)](https://github.com/JureJan/sentinel/actions/workflows/ci.yml)
[![License: MIT](https://img.shields.io/badge/License-MIT-emerald.svg)](LICENSE)
[![MCP](https://img.shields.io/badge/MCP-stdio-0ea5e9.svg)](https://modelcontextprotocol.io/)

Sentinel is a production-minded [Model Context Protocol](https://modelcontextprotocol.io/) server that lets Cursor (and other MCP clients) call a **tiny set of harmless tools** — only against hosts you put on an **explicit allowlist**.

> Safety over power. No shell. No scanners. No surprises.

<p align="center">
  <img alt="Sentinel architecture" src="docs/architecture.svg" width="720" />
</p>

## Why Sentinel?

Most “give the AI tools” demos hand the model a shell. That scales poorly with trust.

Sentinel keeps the useful pattern (agent → tools → results) and hardens the middle:

| Control | What it does |
|---------|----------------|
| **Target allowlist** | Only listed IPs / CIDRs / domains |
| **Arg sanitisation** | Blocks shell metacharacters & path tricks |
| **No `shell=True`** | Structured argv only |
| **Rate limit** | Sliding window per minute |
| **Timeouts** | Per-tool hard caps |
| **Audit log** | JSONL of every invocation |
| **Container hardening** | non-root, `cap_drop: ALL`, read-only FS |

Read the story in [ABOUT.md](ABOUT.md).

## Tools (intentionally boring)

| Tool | Purpose |
|------|---------|
| `echo_message` | Connectivity check |
| `get_datetime` | UTC clock |
| `hash_text` | Local SHA/BLAKE2 digest |
| `run_dig` | DNS lookup (allowlisted) |
| `run_curl` | **GET-only** HTTP (allowlisted) |
| `run_whois` | WHOIS (allowlisted) |
| `list_allowed_targets` | Show policy |
| `server_status` | Health + rate limit |

If a tool would be useful for attacking systems, it does **not** belong in this repo.

## Quick start

### Local (Python 3.11+)

```bash
git clone https://github.com/JureJan/sentinel.git
cd sentinel
python3 -m venv .venv && source .venv/bin/activate
pip install -r requirements.txt
cp .env.example .env
python server.py   # stdio MCP server
```

### Docker

```bash
docker compose up --build
```

### Cursor MCP config

Add to your MCP settings (see [docs/cursor-setup.md](docs/cursor-setup.md)):

```json
{
  "mcpServers": {
    "sentinel": {
      "command": "python3",
      "args": ["/absolute/path/to/sentinel/server.py"],
      "env": {
        "ALLOWED_TARGETS": "127.0.0.1,example.com"
      }
    }
  }
}
```

## Configuration

| Variable | Default | Meaning |
|----------|---------|---------|
| `ALLOWED_TARGETS` | `127.0.0.1,example.com` | Comma-separated allowlist |
| `RATE_LIMIT_PER_MINUTE` | `30` | Max tool calls / minute |
| `LOG_DIR` | `/tmp/sentinel-mcp` | Audit JSONL directory |
| `TIMEOUT_CURL` / `DIG` / `WHOIS` | `20` / `15` / `15` | Seconds |

## Tests

```bash
pytest
```

## Project layout

```
sentinel/
├── server.py           # entire MCP server (~400 lines)
├── ABOUT.md            # product story
├── SECURITY.md         # disclosure policy
├── docs/               # setup + architecture
├── tests/              # allowlist & sanitisation tests
├── Dockerfile          # python:slim + dig/curl/whois
└── docker-compose.yml  # hardened runtime
```

## Star history / support

If Sentinel helps you ship safer agent tooling, a ⭐ on GitHub helps others find it.

Issues and PRs that improve **safety, docs, or tests** are welcome — see [CONTRIBUTING.md](CONTRIBUTING.md).

## License

[MIT](LICENSE) © JureJan