Skip to main content
Glama
veritiana

MCP MySQL Sentinel

by veritiana
README.md
<div align="center">

# MCP MySQL Sentinel

### Controlled database access for AI agents.

**Connect agents to MySQL without turning database access into an unrestricted capability.**

A practical, self-hosted MCP reference implementation combining token authentication, role-based SQL permissions, statement checks, bounded query results, and an audit trail.

**A Veritiana open-source AI integration reference** · [Explore Veritiana](https://github.com/veritiana) · [Website](https://www.veritiana.com)

`Python 3.11+` · `FastMCP / MCP 1.30.0` · `Streamable HTTP` · `MySQL` · `PyMySQL` · `Apache-2.0`

</div>

![MCP MySQL architecture: request, authentication, SQL guard, execution and audit](docs/images/architecture.png)

## The problem

AI agents are useful when they can work with real information. But connecting an agent directly to a database raises difficult questions:

- Who is requesting this operation?
- Which SQL statements should that identity be allowed to execute?
- How do we prevent an agent with a read-only task from receiving broad database privileges?
- How can operators inspect successful, rejected, and failed requests?

**MCP MySQL demonstrates one explicit answer: put a policy-aware MCP interface between the agent and MySQL.** Instead of treating an agent as an all-powerful database user, the service authenticates each request, applies a configured role policy, checks the requested SQL, executes it through a dedicated database account, and writes an audit record.

The goal is not to make an LLM a database administrator. The goal is to make access **visible, constrained, and understandable**.

## See it in action

| Scenario | Expected behavior |
| --- | --- |
| An analyst agent runs `SELECT * FROM orders LIMIT 10` as `readonly` | Statement passes the role's SQL guard and is executed with result limits |
| The same agent requests `DELETE FROM orders` | Rejected before database execution |
| A `developer` identity submits an allowed `UPDATE` | Statement proceeds to MySQL **only if** the database account also permits it |
| An administrator calls `admin_list_users()` | Returns configured identities and roles without exposing token hashes |
| An operator reviews the audit log | Sees `allowed`, `denied`, and `error` query outcomes |

These are **behavior examples**, not an online demo. Never run write-operation demonstrations against valuable production data.

## What makes this project useful

| Capability | Why it matters |
| --- | --- |
| **MCP-native interface** | Exposes database operations as tools for MCP-compatible clients |
| **Identity-aware access** | Bearer tokens are checked against configured SHA-256 token hashes |
| **Role-based policy** | `readonly`, `developer`, and `migrator` demonstrate different SQL permission sets |
| **Deterministic SQL guard** | Applies a statement-type allowlist, blocked keywords and phrases, and a single-statement rule |
| **Bounded execution** | Uses query timeouts and configured result row limits |
| **Operational audit** | Appends query decisions and errors to JSONL for later inspection |
| **Administrative controls** | Supports introspection and configuration reload through admin-gated tools |

## Architecture: five controlled stages

1. **Agent / MCP client** — invokes an exposed tool, such as `query(sql)`.
2. **MCP transport** — FastMCP exposes a Streamable HTTP endpoint.
3. **Identity and policy** — the server authenticates the bearer token and resolves the user's role from YAML configuration.
4. **SQL guard** — deterministic checks decide whether the submitted statement is admissible under that role.
5. **Database execution** — PyMySQL sends permitted SQL to MySQL, subject to the database user's actual grants. Results are returned as structured data; outcomes are audited.

> **Defense in depth, not a sandbox.** The guard uses lexical SQL checks, **not a complete SQL parser**. It must never replace least-privilege MySQL accounts, network restrictions, encrypted transport, review of SQL privileges, and security testing. Its read/write role names describe application-level policy, not independently enforced MySQL identities.

## Available MCP tools

| Tool | Purpose |
| --- | --- |
| `query(sql)` | Execute one SQL statement subject to role checks, query limits, and MySQL permissions |
| `whoami()` | Show current identity, role, allowed statement types, and row limit |
| `admin_list_users()` | Inspect configured users, roles and blocked statements; admin only |
| `admin_reload_config()` | Reload role configuration without restarting the service; admin only |

## Who should explore it?

**AI agent developers** looking for a concrete database integration pattern; **backend engineers** adding MCP to existing MySQL-backed applications; **software architects** studying authorization and execution boundaries; and **DevOps / security engineers** experimenting with traceable self-hosted agent tools.

This is especially useful as a **reference architecture to inspect, modify, and test**. It is not advertised as a turnkey enterprise security gateway.

## Quick start

**Prerequisites:** Python 3.11+, access to a MySQL server, and a dedicated database account with the least privileges needed for your demonstration.

```bash
python3 -m venv .venv
source .venv/bin/activate
python -m pip install --upgrade pip
python -m pip install -e '.[dev]'
```

Prepare local settings and access control:

```bash
mkdir -p "$HOME/.config/mcp-mysql"
cp .env.example "$HOME/.config/mcp-mysql/.env"
cp config/roles.example.yaml "$HOME/.config/mcp-mysql/roles.yaml"
chmod 600 "$HOME/.config/mcp-mysql/.env" "$HOME/.config/mcp-mysql/roles.yaml"
```

Edit `.env` and set your real MySQL connection settings and writable paths:

```dotenv
MYSQL_HOST=127.0.0.1
MYSQL_PORT=3306
MYSQL_USER=mcp
MYSQL_PASSWORD=change-me
MYSQL_DATABASE=app
MYSQL_TIMEOUT_MS=10000
MCP_HOST=127.0.0.1
MCP_PORT=8000
MCP_PUBLIC_URL=http://127.0.0.1:8000
MCP_ROLES_FILE=/home/YOUR_USER/.config/mcp-mysql/roles.yaml
MCP_AUDIT_FILE=/home/YOUR_USER/.config/mcp-mysql/audit.jsonl
```

**Replace `YOUR_USER`, credentials, and paths before starting.** The original example `.env` contains deployment-style `/etc` and `/var/log` paths; those need appropriate permissions if retained.

Generate a token and store its hash in your role configuration:

```bash
mcp-mysql-token
```

The command prints a bearer token and its SHA-256 digest. Store the **digest** under the desired user's `token_sha256` in `roles.yaml`; deliver the raw bearer token privately to its intended user. The sample file contains placeholders and is not runnable unchanged.

Run the server:

```bash
mcp-mysql
```

The service starts a **Streamable HTTP** MCP endpoint on the configured host and port. Connect with a compatible MCP client configured with the server URL and bearer authorization. Client-specific JSON varies by client; do not assume one universal client configuration.

## Example policy

The repository includes `config/roles.example.yaml`:

```yaml
roles:
  readonly:
    allow: [SELECT, WITH, SHOW, DESCRIBE, EXPLAIN]
    max_rows: 200
  developer:
    allow: [SELECT, WITH, SHOW, DESCRIBE, EXPLAIN, INSERT, UPDATE, DELETE]
    max_rows: 200
  migrator:
    allow: [SELECT, SHOW, DESCRIBE, CREATE, ALTER]
    max_rows: 50
```

These are **sample application roles**; the actual MySQL login configured through `MYSQL_USER` is shared by server-side execution. MySQL privileges must be configured separately and can be more restrictive than these example policies.

## Security boundary and limitations

This project deliberately makes its trade-offs visible:

- **SQL inspection is lexical.** Prefix verbs and word/phrase checks can miss database-specific semantics; do not treat them as authoritative SQL parsing or full read-only proof.
- **Database privileges remain decisive.** Use a separate limited-privilege MySQL account, avoid administrative grants, and isolate demonstration environments.
- **Treat credentials as secrets.** Never commit `.env`, `roles.yaml` with real token hashes, raw tokens, or audit records containing sensitive SQL.
- **Audit can contain SQL text.** Control log access, rotation, retention and redaction according to your environment.
- **Transport needs deployment security.** Bind locally for development; do not expose the example service publicly without a properly secured TLS/reverse-proxy and network policy.
- **The reference is not a security certification.** Review and test it before any production deployment. Database data returned through tools must be treated as untrusted content rather than instructions to the agent.

## Project layout

```text
mcp-mysql/
├── README.md
├── docs/
│   └── images/
│       └── architecture.png
├── config/
│   └── roles.example.yaml
├── src/mcp_mysql/
│   ├── server.py         # MCP transport and tools
│   ├── auth.py           # Bearer-token verification
│   ├── config.py         # Environment and role loading
│   ├── sql_guard.py      # Lexical policy checks
│   ├── db.py             # MySQL execution and bounds
│   ├── audit.py          # JSONL audit writer
│   └── make_token.py     # Token generator
├── tests/
│   └── test_sql_guard.py
├── .env.example
└── pyproject.toml
```

## Validate the implementation

```bash
python -m pytest
```

This repository includes SQL-guard unit tests; passing them does not constitute penetration testing or end-to-end production assurance.

## Part of Veritiana

**Veritiana builds practical, inspectable implementations of AI systems architecture.** Across agent workflows, simulation, memory systems, and integrations, the emphasis is on explicit boundaries, real code, and repeatable experimentation.

MCP MySQL contributes a focused **AI Integration Pattern: controlled MCP access to relational data**.

Explore related work:

- [Claude Agent Development Kit](https://github.com/veritiana/Claude-Agent-Development-Kit) — structured Claude Code agent workflows.
- [Claude Chief of Staff](https://github.com/veritiana/Claude-Chief-of-Staff) — read-only agent with source validation and auditable output.
- [Agent Glasses Memory Core](https://github.com/veritiana/agent-glasses-memory-core) — event processing and structured agent memory.
- [CouncilMind CE](https://github.com/veritiana/councilmind-ce) — local-first multi-agent orchestration.
- [AURA](https://github.com/veritiana/aura-agent-sim) — autonomous multi-agent simulation.
- [BabyGPT Engine](https://github.com/veritiana/babygpt-engine) — browser-native Transformer experimentation.
- [Tenrec](https://github.com/veritiana/tenrec) — persistent agent runtime.

**Veritiana:** [GitHub](https://github.com/veritiana) · [Website](https://www.veritiana.com)

## Project status

**Initial reference implementation.** It is suited to learning, local experimentation, and evaluation in controlled environments. Before public production deployment, extend validation, threat modeling, SQL parsing/policy enforcement, logging safeguards, and operational hardening.

## License

Licensed under the **Apache License, Version 2.0**. See [LICENSE](LICENSE) for the full terms. You may use, modify, and distribute this project under the conditions of that license.