local-mysql
# local-mysql MCP サーバー
FO MySQL データベースを VSCode(および Copilot CLI)に公開する、ローカル開発用 MCP サーバーです。`query`(SELECT 専用)と `execute`(INSERT / UPDATE 専用)の 2 つのツールを提供します。
**本サーバーはローカル開発専用です。本番環境にデプロイしたり、本番 DB に接続したりしないでください。**
## 接続設定
デフォルト値は `src/main/resources/application.yml` と揃えています。
| 項目 | デフォルト | 環境変数での上書き |
| -------- | ----------- | ---------------- |
| host | `localhost` | `FO_DB_HOST` |
| port | `3306` | `FO_DB_PORT` |
| user | `root` | `FO_DB_USER` |
| password | `admin` | `FO_DB_PASS` |
コネクションプールは **スキーマ非依存** で、デフォルトのデータベースにはバインドしません。呼び出しごとに `schema` パラメータでスキーマを指定するか、`oa.t_xxx` のような完全修飾名を使用してください。許可されているスキーマ: `fo`、`oa`、`bo`、`cm`、`nepro`。
## インストールとビルド
```bash
cd mcp-server
npm install
npm run build
```
ビルド後は、MCP クライアント(VSCode / Copilot CLI)を再起動して設定を読み直してください。
再ビルド不要で反復開発したい場合:
```bash
npm run dev
```
## ツール
### `query` — 読み取り専用 SELECT
```jsonc
{
"sql": "SELECT id, name FROM m_article WHERE id = ?",
"params": [123],
"schema": "fo" // 省略可
}
```
戻り値:
```json
{
"schema": "fo",
"rowCount": 1,
"truncated": false,
"maxRows": 1000,
"fields": [{ "name": "id", "type": 3 }, { "name": "name", "type": 253 }],
"rows": [{ "id": 123, "name": "..." }]
}
```
制約事項:
- 単一ステートメントのみ(複数ステートメントは拒否)
- `SELECT` で始まる必要あり(v1 では CTE / `WITH` は未対応)
- 結果の上限: **1000 行**。`truncated: true` の場合は、それ以上の行が存在することを示します
### `execute` — INSERT または UPDATE
```json
{
"sql": "UPDATE m_article SET name = ? WHERE id = ?",
"params": ["new name", 123],
"schema": "fo"
}
```
戻り値:
```json
{
"schema": "fo",
"affectedRows": 1,
"insertId": 0,
"changedRows": 1,
"warningStatus": 0
}
```
制約事項:
- 単一ステートメントのみ
- `INSERT` または `UPDATE` で始まる必要あり
- `DELETE`、`DROP`、`ALTER`、`CREATE`、`TRUNCATE`、`RENAME`、`GRANT`、`REVOKE`、`REPLACE`、`MERGE`、`CALL`、`LOAD`、`HANDLER`、`LOCK`、`UNLOCK`、`SET`、`USE`、`START`、`BEGIN`、`COMMIT`、`ROLLBACK`、`SAVEPOINT` — すべて拒否
## 組み込み方
本サーバーを利用するプロジェクトと並ぶ位置にこのリポジトリをクローンし、以下のディレクトリ構成にしてください:
```
parent/
├── mcp-local-mysql/ ← このリポジトリ
└── your-project/
└── .vscode/mcp.json (Copilot CLI の場合は .mcp.json)
```
### VSCode
プロジェクトのルートに `.vscode/mcp.json` を追加します。ルートキーは `servers` です:
```json
{
"servers": {
"local-mysql": {
"command": "node",
"args": ["../mcp-local-mysql/dist/index.js"],
"env": {}
}
}
}
```
ワークスペースごとに認証情報を上書きしたい場合は、`env` オブジェクトを編集します。例:
```json
"env": { "FO_DB_USER": "devuser", "FO_DB_PASS": "devpass" }
```
また、VSCode が `.vscode/mcp.json` を認識できるように、`.vscode/settings.json` で MCP ディスカバリを有効にしておいてください:
```json
{
"chat.mcp.discovery.enabled": true
}
```
### Copilot CLI
プロジェクトのルートに `.mcp.json` を追加します。ルートキーは `mcpServers` です:
```json
{
"mcpServers": {
"local-mysql": {
"command": "node",
"args": ["../mcp-local-mysql/dist/index.js"],
"env": {}
}
}
}
```
## セキュリティに関する注意
- ドライバレベルで `multipleStatements: false` を設定(バリデータに加えた多層防御)
- すべてのクエリはパラメータ化されています — 値は必ず `params` 経由で渡し、SQL 文字列に直接埋め込まないでください
- スキーマ名はホワイトリストと照合した上で `` USE `...` `` に埋め込まれます
- サーバーのログは **stderr** のみに出力されます。stdout は MCP プロトコルのフレーム専用です
TDQS
Scored across 2 tools
The two tools have clearly distinct purposes: 'execute' handles write operations (INSERT/UPDATE only), while 'query' handles read operations (SELECT only). Their descriptions explicitly define non-overlapping scopes with specific allowed statement types, leaving no ambiguity for an agent to misselect between them.
Both tools follow a consistent, simple verb-based naming pattern ('execute' and 'query') that clearly indicates their action-oriented functions. The naming is uniform without any mixing of conventions, making it predictable and easy to understand at a glance.
With only two tools, this server feels severely under-scoped for a MySQL database interface. While the tools cover basic read and limited write operations, the lack of tools for schema management, data definition, or broader CRUD operations (e.g., DELETE, CREATE TABLE) makes it incomplete for typical database workflows, suggesting the count is too low for the domain.
The tool surface has significant gaps for a MySQL server. It only supports SELECT, INSERT, and UPDATE, missing essential operations like DELETE, DDL (CREATE/ALTER/DROP), and other CRUD lifecycle functions. This will likely cause agent failures when trying to perform common database tasks, as the coverage is severely incomplete for the implied domain.