Skip to main content
Glama
Khushboo-Mishra

SQL-MCP-101

SQL-MCP-101

MCPは初めてですか? インタラクティブチュートリアルから始めましょう。ツール、リソース、プロンプトをクリックして進み、機能がどれを使うべきかを判断する方法を学べます。

約1,100行のPythonで、Model Context Protocolの3つのプリミティブ(ツール、リソース、プロンプト)をすべて示す、コメントが充実した小さなMySQL用MCPサーバーです。さらに、それを探索するためのブラウザUIも含まれています。

このリポジトリは、実行するだけでなく読むために存在します。MCPについて言及されているのを見て、サーバーを構築することが実際に何を伴うのかを理解したいなら、これは一気に読めるほど小さな、完全で動作する例です。ファイルごとに1つのプリミティブ、何ではなくなぜを説明するコメント、そしておもちゃの問題ではなく実際の問題を見つけるための意図的な欠陥を持つデモデータベースがあります。

mcp_server/
├── database.py    read-only introspection; the only file not about MCP
├── execution.py   running queries and writes, plus every safety control
├── tools.py       6 TOOLS      inspect structure, cannot read or change a row
├── data_tools.py  6 TOOLS      read rows, and insert / update / delete / alter
├── resources.py   4 RESOURCES  content the APPLICATION attaches (+2 templates)
├── prompts.py     6 PROMPTS    workflows the USER invokes
└── server.py      wires them together, about 10 meaningful lines

サーバーは読み書き可能です。実際のクエリを実行してデータに関する質問に答え、データとスキーマを変更できます。使い捨てのデモデータベースに限定されており、それを安全にする制御はexecution.pyにあり、以下で説明します。その設計自体が教訓の一部です。


持ち帰るべき唯一の考え

ほとんどのMCPチュートリアルはツールのみを扱うため、MCPはツールであると誤解されがちです。実際には3つのプリミティブがあり、誰が制御するかによって異なります:

プリミティブ

誰が決定するか

いつ発生するか

たとえ

ツール

モデル

会話の途中で、自律的に

モデルが呼び出せる関数

リソース

アプリケーション

事前に、人間が選択

添付するファイル

プロンプト

ユーザー

明示的に、メニューから

保存された専門家の質問

同じデータが複数の形で現れることがあります。このリポジトリでは、get_table_ddlはツールであり、schema://table/{name}/ddlはリソースです。同じバイトが2つの異なる方法で到達されます。「モデルが必要と判断したときに取得する」と「人間が開始前に添付する」は、本当に異なるニーズだからです。


Related MCP server: mysql-mcp-server

クイックスタート

git clone https://github.com/Khushboo-Mishra/SQL-MCP-101.git
cd SQL-MCP-101
bash scripts/setup.sh

setup.shは前提条件を確認し、virtualenvを作成し、2つの依存関係をインストールし、デモデータベースを作成し、サーバーをエンドツーエンドで検証します。最初に欠けているものがあると、具体的なメッセージで停止します。

bash scripts/run_explorer.sh

要件

  • Python 3.10+

  • MySQL 8.x がローカルで実行されていること(brew services start mysql)

  • Node.js: オプション、MCP Inspectorのみ

  • Ollama: オプション、UIのチャットパネルのみ

デフォルトは127.0.0.1:3306のrootでパスワードなし、これはHomebrewのデフォルトなので、ほとんどの人は何も変更しません。それ以外の場合は、MYSQL_USER、MYSQL_PASSWORD、MYSQL_HOST、MYSQL_PORTをエクスポートしてください。


構築されるもの

12のツール、4つのリソース+2つのURIテンプレート、6つのプロンプトを、6テーブルのデモデータベース上に構築します。

ツール:モデルがこれらを呼び出す

サブシステムではなく影響範囲によって2つのファイルに分けています。これはコピーする価値のある意図的な設計選択です。リスクのある表面を小さく保ち、サーバーをレビューする人やデータベースのGRANTを書く人にとって明白にします。

tools.py:構造を検査します。行を読むことも、何かを変更することもできません。

ツール

目的

list_tables

すべてのテーブルとビュー、行数の見積もり付き

describe_table(table)

列、型、キー、インデックス、外部キー

get_table_ddl(table)

正確なCREATE TABLE

list_relationships

宣言されたすべての外部キー

find_sensitive_columns

名前がPIIや秘密を示唆する列

search_columns(keyword)

どのテーブルにあるか忘れたときに列を見つける

data_tools.py:行を読み取り、データを変更します。こちらが影響を伴う半分です。

ツール

目的

run_query(sql, limit)

SELECTを実行して行を取得します。これがデータの質問に答えるものです

execute_statement(sql)

INSERT / UPDATE / DELETE / CREATE / ALTER / DROP / TRUNCATE

insert_row(table, values)

構造化された挿入、値はバインドパラメータとして送信

update_rows(table, changes, where)

構造化された更新、where必須

delete_rows(table, where)

構造化された削除、where必須

show_audit_log(limit)

サーバーが実行したすべてのステートメント

なぜ一般的なexecute_statementと構造化ラッパーの両方があるのか? 構造化ツールはより安全です。引数は型付けされ、値はバインドされるため、モデルがSQLテキストを書くことはなく、不正なものを生成することはできません。しかし、それらはあなたが予期したことだけを行います。一般的なSQLドアはロングテールを処理します:ウィンドウ関数、予期しなかったALTERなど。ほとんどの実際のサーバーは、まさにその理由から両方を提供することになります。

リソース:アプリケーションがこれらを添付する

URI

型

内容

schema://tables

JSON

テーブル一覧

schema://ddl

SQL

スキーマ全体のDDL

schema://relationships

JSON

すべての外部キー

schema://overview

Markdown

人間が読める要約

schema://table/{name}

JSON

1つのテーブル(テンプレート化)

schema://table/{name}/ddl

SQL

1つのテーブルのDDL(テンプレート化)

静的リソースは固定URIを持ち、resources/listに表示されるため、クライアントはピッカーで表示できます。テンプレート化リソースは{placeholders}を持ち、代わりにresources/templates/listに表示されます。表示する固定リストがないため、クライアントが空白を埋めます。

プロンプト:ユーザーがこれらを呼び出す

プロンプト

引数

機能

audit_schema

なし

5段階のヘルスチェック:キー、リレーションシップ、PII、命名

explain_table

table

1つのテーブルを平易な言葉で説明

ask_data

question

クエリを書き、実行し、平易な言葉で回答

modify_data

request

変更のためのプレビュー→確認→適用→検証

document_schema

なし

リファレンスドキュメントを生成

onboarding_tour

role

ロールに合わせたガイド付きの最初の見学


決定:ツール、リソース、プロンプト?

人々が行き詰まる質問です。この順序で考えてみてください。

  1. アクションを実行するか、モデルが選択するものを取得するか? → ツール。 モデルが自分で決定できるものはすべて。

  2. 人間が開始前に合理的に添付するドキュメントか? → リソース。 参照資料、スキーマ全体のコンテキスト、安定したもの。

  3. **誰かが繰り返すタスクで、尋ね方が専門知識であるか?** → プロンプト。 再発見を期待するのではなく、良い質問を提供します。

残りの疑問のほとんどを解決する2つのヒューリスティック:

誰が開始するか? モデル→ツール。アプリケーション→リソース。ユーザー→プロンプト。

これをメニューに入れたいか? はいなら、それはプロンプトです。メニューは人のためのものであり、プロンプトだけがコマンドとして人に表示されます。

このリポジトリの実例

機能

選択

理由

1つのテーブルの構造を取得

ツール

モデルが推論の途中で予測不能に必要とする

スキーマ全体のDDL

両方

モデル用のツール、人間が事前に添付するリソース

スキーマ監査

プロンプト

何を尋ねるかを知ることが価値である反復可能なタスク

列の検索

ツール

呼び出し時にモデルが選択する引数を取る

Markdown概要

リソース

受動的な参照、決定不要

人々が間違えるところ

  • すべてをツールにする。 機能しますが、モデルは人間が一度添付できたコンテキストを取得するために呼び出しを消費し、ユーザーは発見可能なエントリポイントを得られません。

  • モデルが選ぶ引数を必要とするものにリソースを使う。 モデルがパラメータを決定するなら、それはツールです。

  • 作業を行うプロンプト。 プロンプトはテキストを返します。プロンプト内でデータベースにクエリを実行していることに気づいたら、それはツールが必要だったのです。


デモデータベース

mcp_demo、6つのテーブル、例が実際の問題を見つけるように意図的に不完全です:

テーブル

意図的な欠陥

CUSTOMERS

EMAIL、PHONE、機密列スキャンが発動

PRODUCTS

SKUはUNIQUEだがPKではない、議論に値する自然キー

ORDERS

(クリーン、参照例)

ORDER_ITEMS

PRODUCT_IDは外部キーのように見えるが制約がない

AUDIT_LOG

主キーがまったくない

legacy_notes

他がすべてUPPER_CASEなのにsnake_case

それに対してaudit_schemaを実行すると、それらのすべてが表面化するはずです。それがデモです:ツールはおもちゃの問題ではなく、本物の問題を見つけます。


実行方法

エクスプローラー:すべてのプリミティブを一度に

bash scripts/run_explorer.sh

initializeハンドシェイクを出力し、ツール、リソース(静的およびテンプレート化)、プロンプトを一覧表示して実行します。これを最初に実行すると、セットアップが機能することを確認し、プロトコル全体を1画面で表示します。

Web UI:ブラウザで3つのプリミティブすべて

bash scripts/run_ui.sh          # http://127.0.0.1:8000
PORT=9000 bash scripts/run_ui.sh

4つのパネル、それぞれ表示する価値のあるもの:

パネル

デモ内容

チャット

平易な英語で質問;モデルが選択したすべてのツールが回答の上にインラインで表示

ツール

全12個、影響範囲でグループ化、各フォームから呼び出し可能

リソース

静的およびテンプレート化、その場で読み取り可能

プロンプト

展開してテキストを表示、またはチャットに直接送信

下部のライブアクティビティストリップは、その下にある実際のJSON-RPC、tools/call、resources/read、prompts/getを表示するため、プロトコルが常に表示されます。

このページはそれ自体がMCPクライアントです。独自のMySQLへのアクセスはありません。画面上のすべては、Claude Desktopが使用するのと同じプロトコルを通じて到着します。

チャットにはOllamaを介したローカルLLMが必要です。無料で、APIキーは不要で、マシンから何も出ません:

brew install ollama && ollama serve
ollama pull qwen2.5:7b

代わりにANTHROPIC_API_KEYを設定すると、自動的にClaude APIに切り替わります。ツール、リソース、プロンプトのパネルはLLMなしで動作します。

MCP Inspector:Anthropicの独自クライアント

bash scripts/run_inspector.sh

表示された http://localhost:6274?... URL を開きます。トークンが必要です。Tools、Resources、Prompts のタブが分かれており、3つすべてを示す最も説得力のある方法です。どれも私たちのコードではないので、Inspector がサーバーを駆動できるなら、サーバーは本当に仕様準拠です。

おすすめのツアー: ツール → describe_table を ORDERS で; リソース → schema://overview; プロンプト → audit_schema。

Claude Desktop / Claude Code

bash scripts/add_to_claude_desktop.sh    # Claude Desktop, run from Terminal.app
bash scripts/install_claude.sh           # Claude Code, safe to run anywhere

add_to_claude_desktop.sh は設定をバックアップし、すでに登録されているサーバーを保持し、JSON を検証し、正確な起動コマンドをスモークテストし、アプリを再起動します。完了すると推奨デモスクリプトを出力します。

次に、"このデータベースを監査して" と尋ねるか、メニューから audit_schema プロンプトを使用します。ここでプロンプトがようやく表示されます。

--desktop は Claude Desktop 内からではなく、Terminal.app から実行する必要があります。 Claude Desktop は設定をメモリに保持し、そのコピーからファイルを書き換えるため、実行中に行った編集は静かに破棄されます。スクリプトはアプリを終了し、編集し、再起動するため、起動元のセッションが終了します。


コードを読む

全体でおよそ1時間。この順序は前方参照なしで積み上がります:

1. mcp_server/server.py: ここから始めます。意味のある10行で、アーキテクチャ全体が1画面に収まります: サーバーを作成し、3つのプリミティブを登録し、実行します。それ以外はすべて詳細です。

2. mcp_server/database.py: MCP がまったく含まれていない普通の MySQL コードです。MCP レイヤーが実際にどれほど薄いかを示すため、早い段階で読む価値があります: すでにデータアクセスレイヤーがあるなら、ほとんど完成しています。

safe_identifier をよく見てください。MySQL ではテーブル名をパラメータとしてバインドできません(SHOW CREATE TABLE %s は有効な SQL ではないため)、識別子は文字列に補間する必要があります。これは本当のインジェクションリスクであり、この小さな関数がそれを安全にしているのです。

3. mcp_server/tools.py: @mcp.tool() デコレータと、プロジェクト全体で最も多くの作業を行うアイデア: docstring がプロンプトです。モデルがツールを呼ぶかどうかを判断するときに読む唯一のものなので、ソースを読む人間ではなくモデル向けに書かれています。

4. mcp_server/resources.py: 静的 URI とテンプレート化された URI、そして get_table_ddl がツールかつリソースとして存在する理由。その重複は意図的であり、誰が何を制御するかという考え方を最も明確に示しています。

5. mcp_server/prompts.py: プロンプトはデータではなくテキストを返します。テキストは通常、モデルにどのツールを使うかを指示する命令です。短いファイルで、ほとんどの人が見たことがないものです。

6. mcp_server/execution.py: 書き込みアクセスを安全にする方法を知りたいときに読んでください。5つの制御があり、それぞれに何を防ぐかのコメントが付いています。

7. examples/explore_server.py: プロトコルの反対側です。すべてを一覧表示して呼び出す最小限のクライアントで、実際に何がワイヤを越えるかを見ることができます。


さらに進める

このサーバーは例を短く保つために1つのデータベースにスコープされています。さらに進めるには:

  • 複数スキーマ: MYSQL_DEMO_SCHEMA を読む代わりに、schema をツール引数として受け取ります。エージェントが本番に到達できないように許可リストを追加します。

  • クエリ実行: run_query ツール。可能ですが、セキュリティの話が完全に変わります: サーバーはテーブルを読む資格情報を必要とし、結果がモデルのコンテキストに入ります。SELECT のみを強制し、LIMIT を注入し、読み取り専用のデータベースユーザーを使用します。

  • リモートトランスポート: mcp.run(transport="streamable-http")。同じツール、同じコード、異なるパイプ。公開する前に認証を追加します。

  • キャッシュ: describe_table は呼び出しごとにデータベースにアクセスします。モデルがループで呼び始めると、短い TTL キャッシュは価値があります。


セキュリティノート

このサーバーはデータを変更できます。これは意図的です: 「エージェントは私のデータベースに書き込めるか?」はすべてのチームが尋ねる質問であり、安全に行う方法の実用的な例は、その話題を避けるものより有用です。しかし、制御が重要であることを意味します。

5つの制御、すべて execution.py にあります

制御

防ぐもの

スキーマロック

すべてのステートメントはデモデータベースに固定された接続で実行され、他のデータベースへの参照は拒否されます

呼び出しごとに1つのステートメント

2番目のステートメントが正当なものに便乗できない

読み取り/書き込みドアの分離

run_query は書き込みを拒否し、execute_statement は読み取りを拒否するため、どちらも相手の仕事をさせられることはありません

行数上限

広範な SELECT がモデルのコンテキストをあふれさせない

監査ログ

すべてのステートメントが記録され、show_audit_log で読み取れます

拒否リストはまた、スキーマロックを逃れる、ファイルシステムに到達する、サーバー全体の状態を変更するステートメント、権限変更、ユーザー管理、ファイルのインポート/エクスポート、データベースレベルの操作を拒否します。

1つの微妙な点、繰り返しやすい間違いだからです: スキーマロックはパターンだけでは機能しません。SQL では、a.b は通常 alias.column(SELECT c.NAME FROM CUSTOMERS c)であり、schema.table ではないため、すべてのドット付き名前を拒否すると通常の結合が壊れます。これはまさに最初のバージョンにあったバグです。現在は各修飾子をサーバー上の実際のデータベースリストと比較します: 実際のデータベース名は拒否され、テーブルエイリアスはそのまま通過します。

制限されたユーザーに向ける

上記の制御は多層防御であり、防御そのものではありません。デモ以外では、公開する予定のスキーマのみをカバーする権限を持つ MySQL ユーザーとして接続します。資格情報が本番に到達できなければ、プロンプトインジェクションやモデルのミスも到達できません。

明確に述べる価値のある2つのこと:

  • テーブル名はバインドパラメータにできません。 SHOW CREATE TABLE %s は有効な SQL ではないため、識別子は補間する必要があり、これは本当のインジェクションシンクです。database.safe_identifier がそれを安全にしており、プロジェクトで最も重要な関数です。

  • 接続する MySQL ユーザーが本当の境界です。 公開する予定のスキーマにスコープされた読み取り専用の GRANT を与えます。コードの読み取り専用性は多層防御であり、防御そのものではありません。


ライセンス

MIT、LICENSE を参照してください。

Related MCP Connectors

Related MCP Servers

  • A
    license
    Not graded
    quality
    D
    maintenance
    Enables interaction with MySQL databases through MCP, supporting query execution, table operations (insert, update, delete), and schema inspection for natural language database management.
    202 npm
    MIT
  • A
    license
    Not graded
    quality
    D
    maintenance
    Enables MySQL database operations through MCP, including executing SQL queries, listing databases and tables, and describing table structures.
    730 npm
    5
    MIT
  • A
    license
    Not graded
    quality
    D
    maintenance
    Enables natural language interaction with MySQL databases through MCP, supporting SQL execution, schema exploration, and database management via tools, resources, and prompts.
    5
    MIT
  • A
    license
    Not graded
    quality
    C
    maintenance
    Enables natural language interaction with MySQL databases through MCP tools for querying, executing DDL/DML, listing databases/tables, and describing table schemas, with parameterized queries and read-only mode.
    730 npm
    MIT