Skip to main content
Glama
README.md
# mysql-mcp

MySQL MCP Server for **OpenAI Codex** — Create, Read, Update only. No destructive operations.

## Directory Tree

```
mysql-mcp/
├── .codex/
│   └── config.toml          ← Codex MCP registration
├── src/
│   ├── server/
│   │   ├── index.ts         ← MCP server entry (stdio transport)
│   │   ├── db.ts            ← mysql2 connection pool + query helpers
│   │   └── tools/
│   │       ├── schema.ts    ← mysql_list_databases, mysql_list_tables, mysql_describe_table
│   │       ├── read.ts      ← mysql_query  (SELECT only)
│   │       └── write.ts     ← mysql_insert, mysql_update  (no DELETE/DROP)
│   └── client/
│       └── index.ts         ← Test client — launches server + runs all tools
├── .env.example             ← Copy to .env with your credentials
├── .gitignore
├── package.json
└── tsconfig.json
```

## Tools

| Tool | Operation | readOnly | destructive |
|---|---|---|---|
| `mysql_list_databases` | SHOW DATABASES | ✅ | ❌ |
| `mysql_list_tables` | information_schema | ✅ | ❌ |
| `mysql_describe_table` | SHOW COLUMNS + SHOW INDEX | ✅ | ❌ |
| `mysql_query` | SELECT (guarded) | ✅ | ❌ |
| `mysql_insert` | INSERT / INSERT IGNORE | ❌ | ❌ |
| `mysql_update` | UPDATE (WHERE required) | ❌ | ❌ |

## Setup

```bash
# 1. Install dependencies
npm install

# 2. Configure credentials
cp .env.example .env
# edit .env with your MySQL details

# 3. Run the test client (launches server automatically)
npm run client

# 4. Or run server standalone
npm run server
```

## Registering with Codex

Edit `.codex/config.toml` with your credentials — Codex will auto-launch the server.

Or register via CLI:
```bash
codex mcp add mysql \
  --env MYSQL_HOST=localhost \
  --env MYSQL_USER=mcp_user \
  --env MYSQL_PASSWORD=secret \
  --env MYSQL_DATABASE=mydb \
  -- npx tsx /path/to/mysql-mcp/src/server/index.ts
```

Verify in Codex TUI: `/mcp`

## Safety Guardrails

- `mysql_query` blocks INSERT/UPDATE/DELETE/DROP/TRUNCATE even if embedded in a SELECT
- `mysql_update` **requires** a WHERE clause — updates without a condition are rejected
- `mysql_update` supports `dry_run: true` to preview affected rows before committing
- All identifiers (table/column names) are sanitized against injection
- All values use `?` prepared statement placeholders — never string interpolation
- No DELETE, TRUNCATE, DROP, or ALTER tools exist