Sentinel
by JureJan
README.md
# Sentinel MCP
**Safe, allowlisted tool execution for AI agents.**
[](https://github.com/JureJan/sentinel/actions/workflows/ci.yml)
[](LICENSE)
[](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
This server cannot be deployed
Maintenance
ActivitySlowing
ResponsivenessResponsive