Skip to main content
Glama
velinussage

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 |