sales-db
by qualiteg
README.md
# 売上データベース MCP サーバー チュートリアル
「先月いちばん売れた GPU はどれ?」と**ふつうの日本語で聞くと、AI が自分で SQL を組み立てて
売上データベースに問い合わせ、集計結果まで答えてくれる**——それを実現する MCP サーバーのサンプルです。
Python + [FastMCP](https://github.com/jlowin/fastmcp) で書かれています。
解説記事は [Qualiteg Blog](https://blog.qualiteg.com/) に掲載しています。
## クイックスタート
```bash
git clone https://github.com/qualiteg/mcp-server-tutorial.git
cd mcp-server-tutorial
python -m pip install -r requirements.txt
python db_setup.py
```
`pip` ではなく `python -m pip` を使ってください。`pip` だと、MCP サーバーを起動する Python と
別の環境に入ってしまうことがあります。
`db_setup.py` は固定シードで架空のデータを生成します(実在の企業・人物・価格とは関係ありません)。
誰が実行しても同じデータになるので、記事の実行結果と一致します。
- customers … 顧客マスター 500 人
- products … 商品マスター 72 種類(PC パーツ 8 カテゴリ)
- sales_transactions … 売上明細 4,000 件(2024-01-01 〜 2026-12-31)
## Claude Code から使う
```bash
claude mcp add sales-db -- python /path/to/mcp-server-tutorial/mcp_server_sales.py
claude mcp list
```
`claude mcp list` に `✔ Connected` と出れば、AI からこのサーバーが見えています。
うまく繋がらないときは、Python とスクリプトを絶対パスで指定してください。仮想環境を使っている場合は、
その中の Python を指す必要があります。
```bash
claude -p "職業別の売上トップ3を教えて"
```
- 「2025年に発売されたハイエンドGPUで、売上が多い順に並べて」
- 「月別の売上推移を出して、いちばん売れた月は?」
**stdio で使う場合、`python mcp_server_sales.py` を手動で起動しておく必要はありません。**
登録したコマンドは Claude Code が子プロセスとして起動します。サーバー単体の動きを確認したいときだけ
手動で起動してください。
## 提供しているツール
| ツール | 役割 |
|---|---|
| `get_database_stats` | テーブル構造・件数・データ期間・カテゴリ別売上の要約を返す |
| `execute_sql_query` | SELECT 文を実行して結果を返す |
業務ごとに「売上集計ツール」「顧客分析ツール」と関数を並べる設計もできますが、**SQL を書けるのは
AI 側**なので、汎用の SQL 実行ツールを 1 本渡すほうが応用が利きます。そのぶん安全側の手当てが
サーバーの責任になるので、役割の違う 3 つの安全弁を設けています。
1. **読み取り専用の接続**: SQLite を `mode=ro` で開く。書き込みは接続そのものが拒む
2. **SQL の補助フィルター**: SELECT 以外の文と書き換え系キーワードを早い段階で落とす
(構文解析ではないので、これは補助的な位置づけ)
3. **実行時間の上限**: 10 秒を超えるクエリを実時間で中断する(リソース保護のため)
あわせて、AI へ返す行数を 50 行までに制限しています。AI は平気で `SELECT * FROM sales_transactions`
を投げてくるので、返す量はサーバー側で決めます。ただし制限しているのは返却行数だけで、SQLite から
読み込む件数は制限していません。大規模データでは `fetchmany` や SQL 側の LIMIT を検討してください。
安全弁が効いているかは `verify.py` で確認できます。
```bash
python verify.py
```
## HTTP サーバーとして動かす
独立して常駐させ、ネットワーク経由で使う場合は Streamable HTTP で起動します。
```bash
python mcp_server_sales.py --http --port 9904
```
- MCP エンドポイント: `http://127.0.0.1:9904/mcp`
- ヘルスチェック: `http://127.0.0.1:9904/health`
**既定の待受は 127.0.0.1(ローカルのみ)です。** このサンプルには認証がありません。
`--host 0.0.0.0` や LAN 内の IP を指定すると、到達できる相手なら誰でも SQL を実行できてしまいます。
そのまま共有環境や外部へ公開しないでください(指定した場合は起動時に警告が出ます)。
外へ出すなら、HTTPS、認証と認可、接続元の制限、Origin 検証、監査ログを前段に置く前提になります。
## 既存の REST API を MCP 化する(OpenAPI 統合)
MCP サーバーをゼロから書くのではなく、**社内にすでにある REST API を MCP サーバーに変換する**サンプルです。
FastMCP の OpenAPI 統合(`FastMCP.from_openapi`)を使うと、ツールの実装コードを書かずに
OpenAPI スキーマから MCP ツールを自動生成できます。
| ファイル | 役割 |
|---|---|
| `sales_api.py` | 「社内にすでにある REST API」役の FastAPI アプリ(売上DBを返す・ポート 9905) |
| `mcp_sales_api.py` | その API の OpenAPI スキーマを読み込んで MCP サーバー化する |
```bash
# 1. 既存 API 役を起動しておく
python sales_api.py
# 2. 別ターミナルで MCP サーバーとして登録
claude mcp add sales-api -- python /path/to/mcp-server-tutorial/mcp_sales_api.py
claude -p "2025年でいちばん売れたGPUはどれ?"
```
`mcp_sales_api.py` は RouteMap で **GET のエンドポイントだけ**をツールにしています。
書き込み系(POST / DELETE)は AI からは存在ごと見えません。
## Web 版の ChatGPT・Claude から使いたい場合
ChatGPT や Claude は、構成によっては認証なしのリモート MCP にも接続できます。ただし、社内データベースへ
到達するサーバーを無認証で公開する構成は採用できません。解説記事の後編では、MCP Authorization 仕様に
沿った OAuth 認証を使う方法を紹介しています。
## 動作環境
- Python 3.10 以降
- FastMCP 3.4.5 以上 4 未満
- FastAPI・uvicorn・httpx(OpenAPI 統合サンプル `sales_api.py` / `mcp_sales_api.py` で使用)
このサンプルは仕組みを理解するための最小構成です。複数人が同時に使う場面では、同期的な DB 処理を
スレッドへ逃がす、同時実行数を絞る、DB 側のタイムアウトを設けるといった手当てが別に要ります。
## ライセンス
MIT License. サンプルコードなので自由に改変してお使いください。
This server cannot be deployed
Maintenance
ActivitySlowing
ResponsivenessNo issues