mysql-context-mcp
by velinussage
README.md
# mysql-context-mcp
Light stdio MCP server. A local binlog indexer records ROW-format MySQL
changes. Agents pull compact field diffs (`from` / `to`) into context. No UI.
License: MIT. Do not commit DSNs. See [SECURITY.md](SECURITY.md).
## Modes
| Mode | What you get | Deploy cost |
|---|---|---|
| **binlog** (default) | Real before/after from the binary log, served as field diffs | Replica grants + ROW binlog |
| **outbox** | Real before/after from table triggers | One extra table + 3 triggers per watched table |
| **watermark** | Current rows newer than `updated_at` (no before-image) | Config only. Not a diff. |
`recent_changes` in binlog mode returns the field `diff` only. Pass `full: true`
or call `get_diff` when you need the whole before/after images.
## MySQL setup (binlog)
```
[mysqld]
server-id = 1
log_bin = mysql-bin
binlog_format = ROW
binlog_row_image = FULL
binlog_row_metadata = FULL
```
```sql
GRANT REPLICATION SLAVE, REPLICATION CLIENT, SELECT ON *.* TO 'agent'@'%';
```
`binlog_row_image=FULL` is what makes UPDATE events carry a before image.
MINIMAL/NOBLOB will index inserts and deletes, but updates will look like
partial rows.
Check the server, then run the MCP:
```bash
git clone https://github.com/velinussage/mysql-context-mcp.git
cd mysql-context-mcp
npm install
cp config.example.yaml mysql-context.yaml
export MYSQL_CONTEXT_DSN='mysql://agent@127.0.0.1:3306/app'
export MYSQL_CONTEXT_PASSWORD # set in the environment, not in this file
npx tsx src/install.ts # preflight: log_bin / ROW / FULL
npx tsx src/server.ts
```
The indexer writes a local event log under the process home directory
(`~/.mysql-context/<database>-binlog/`). Override with `MYSQL_CONTEXT_INDEX`.
The MCP process tails the binlog while it is running. You can also run
`npx tsx src/indexer.ts` as a long-lived tailer and keep the MCP read-only
against the same index directory.
## Tools
| Tool | Use |
|---|---|
| `recent_changes` | Unacked field diffs, capped JSON. Optional `table`, `full`. |
| `get_diff` | One change, including before/after images. |
| `ack_changes` | Mark seen so they leave the next pull. |
There is no `execute_sql` and no install tool on the MCP server.
## Attach to a harness
```json
{
"mcpServers": {
"mysql-context": {
"command": "npx",
"args": ["tsx", "src/server.ts"],
"cwd": ".",
"env": {
"MYSQL_CONTEXT_CONFIG": "./mysql-context.yaml",
"MYSQL_CONTEXT_DSN": "${MYSQL_CONTEXT_DSN}",
"MYSQL_CONTEXT_PASSWORD": "${MYSQL_CONTEXT_PASSWORD}"
}
}
}
}
```
Set `cwd` to the clone. Keep credentials in the process environment.
Claude Agent SDK:
```ts
import { query } from "@anthropic-ai/claude-agent-sdk";
for await (const message of query({
prompt: "What changed in MySQL? Use recent_changes and cite the field diffs.",
options: {
mcpServers: {
"mysql-context": {
command: "npx",
args: ["tsx", "src/server.ts"],
env: {
MYSQL_CONTEXT_CONFIG: "./mysql-context.yaml",
MYSQL_CONTEXT_DSN: process.env.MYSQL_CONTEXT_DSN!,
MYSQL_CONTEXT_PASSWORD: process.env.MYSQL_CONTEXT_PASSWORD!,
},
},
},
allowedTools: [
"mcp__mysql-context__recent_changes",
"mcp__mysql-context__get_diff",
"mcp__mysql-context__ack_changes",
],
},
})) {
// ...
}
```
## Skill
Copy `skill/mysql-context/SKILL.md` into the project skills dir so the agent
calls `recent_changes` and treats `diff` as the change, not the live row.
## When this is the wrong tool
Use something else when you need:
| Need | Why not this | Use instead |
|---|---|---|
| Current table rows (“what is in `orders` now?”) | This indexes *changes*, not live state. Watermark mode is a last-resort SELECT and is not a diff. | A read-only SQL MCP, or query MySQL yourself |
| Arbitrary SQL, writes, or schema changes | There is no `execute_sql` on purpose. | A separate, tightly scoped SQL tool |
| A UI, search page, or ops dashboard | This is stdio MCP + a local event log only. | dbtrail or a CDC product with a UI |
| A warehouse, Kafka stream, or analytics replica | The index is a short, local, single-agent tail. It is not a pipeline. | Debezium, Maxwell, or a managed CDC replica |
| Forever history of every row, many consumers | The local index caps and drops acked events. | A binlog consumer that writes to durable storage |
| Statement-based or MIXED binlog, or no replica grants | ROW + FULL row image and `REPLICATION SLAVE`/`CLIENT` are required for real before/after. | Outbox mode (triggers) if you can install them; otherwise do not pretend you have diffs |
This server cannot be deployed
Maintenance
ActivityMaintained
ResponsivenessNo issues