MCP Local WP について
MCP Local WP は、Local by Flywheel で管理される WordPress データベースへの読み取り専用アクセスを AI アシスタントに提供する MCP サーバーです。MySQL クエリの実行とスキーマの確認ができ、WordPress 開発者が実際のテーブル構造を確認してから SQL を書けるようにします。
主な機能
- 01読み取り専用の MySQL クエリ実行
- 02テーブル、カラム、インデックスのスキーマ確認
- 03Local サイトと MySQL インスタンスの自動検出
- 04サイト名または ID によるサイト選択
- 05現在接続中のサイト情報の表示
活用シーン
- 01AI アシスタントによるテーブル構造の確認とクエリ作成
- 02LearnDash や WooCommerce などプラグインのカスタムテーブルの調査
- 03Claude Code や Cursor で作業ディレクトリに対応するサイトのデータベースへ接続
MCP 対応
本プロジェクトは MCP サーバーであり、mysql_query、mysql_schema、mysql_current_site、mysql_list_sites などのツールを MCP クライアントに公開します。
設定
ローカルサーバーの設定はどのクライアントでも共通です。コピーしてクライアントの MCP 設定ファイルに貼り付けてください。
ツール
4掲載時のツール一覧 · 2 週間前に更新
| パラメーター | 型 | 必須 | 説明 |
|---|---|---|---|
| sql | string | はい | SQL 文を 1 つ指定します。実行可能コメントは禁止です。 |
| params | array | いいえ | SQL プレースホルダー(?)に対応する値です。 |
詳細
MCP Server Local WP
🎯 AI アシスタントが実際に WordPress データベースを確認できるとしたら?
Claude や Cursor などの AI アシスタントに、Local by Flywheel の WordPress データベースへの読み取り専用アクセスを提供する Model Context Protocol(MCP)サーバーです。テーブル構造を推測する必要はもうありません。手探りで SQL クエリを書く必要もありません。AI が実際のデータを理解できるようになります。
2.0 へのアップグレード
バージョン 2.0 には Node.js 24 以降が必要で、MCP SDK v2 を使用します。既存のツール名とサイトセレクターは引き続き利用できます。クエリ結果は { "rows": [...] } になりました。スキーマ一覧の結果は { "tables": [...], "hasMore": false, "nextAfter": null } となり、テーブル名をページ単位で上限付きで返します。成功したツールは、対応する構造化結果と JSON テキスト結果を返します。失敗時は isError: true が設定されます。
データベースと Local の設定は遅延して解決されるため、サイトが起動していなくても MCP ツールを検出できます。明示的に MYSQL_HOST または MYSQL_SOCKET_PATH を指定すると、手動接続が選択されます。すべてのツール応答が届くまで stdin を開いたままにしてください。EOF によりセッションが終了します。親プロセスのウォッチドッグは、放置された stdio サーバーもクリーンアップします。
🤔 MCP サーバーとは?
MCP(Model Context Protocol)は、AI アシスタントと開発ツールをつなぐ安全なブリッジだと考えてください。データベースのスキーマやクエリ結果をコピー&ペーストする代わりに、MCP サーバーを使うと、完全な制御を維持しながら AI アシスタントがツールを直接操作できます。
MCP なし:「ねえ AI、wp_something というテーブルがあって、user_meta という名前かもしれないカラムがあると思うんだけど……クエリを書いてくれる?」
MCP あり:「ねえ AI、データベースの中身を確認して、必要なクエリを正確に書いて。」
💡 WordPress 開発者の悩み
こんな状況を想像してください。LearnDash の連携に関する問題をデバッグしています。クイズの結果が正しく同期されません。問題の診断を手伝ってもらうために Cursor を起動しますが、データベースにアクセスできないため、最先端の AI でもテーブル構造を推測するしかありません。
実際の影響
実際に対応したサポートチケットをご紹介します。タスクは単純で、LearnDash のテーブルからクイズのアクティビティデータを取得することでした。
❌ MCP サーバー導入前(AI は手探り)
AI は最善を尽くして、次のクエリを提案しました。
$quiz_activities = $wpdb->get_results(
$wpdb->prepare(
'SELECT post_id, activity_meta FROM ' . esc_sql( LDLMS_DB::get_table_name( 'user_activity' ) ) . '
WHERE user_id=%d AND activity_type=%s AND activity_status=1 AND activity_completed IS NOT NULL',
$user_id,
'quiz'
),
ARRAY_A
);
問題は? activity_meta カラムが存在しません!LearnDash はメタデータを、まったく別の構造を持つ別のテーブルに保存します。データベースにアクセスできなければ、AI はもっともらしいものの誤った推測をしてしまいます。その後の 20 分を、テーブル名の手動修正、リレーションシップの特定、クエリの書き直しに費やすことになります。
✅ MCP サーバー導入後(AI は X 線のように見通せる)
データベースにアクセスできると、AI は実際のテーブル構造をすぐに確認し、次のように書きました。
$quiz_activities = $wpdb->get_results(
$wpdb->prepare(
'SELECT ua.post_id, ua.activity_id, uam.activity_meta_key, uam.activity_meta_value
FROM ' . esc_sql( LDLMS_DB::get_table_name( 'user_activity' ) ) . ' ua
LEFT JOIN ' . esc_sql( LDLMS_DB::get_table_name( 'user_activity_meta' ) ) . ' uam
ON ua.activity_id = uam.activity_id
WHERE ua.user_id=%d AND ua.activity_type=%s AND ua.activity_completed IS NOT NULL
AND uam.activity_meta_key IN (%s, %s, %s)',
$user_id,
'quiz',
'percentage',
'points',
'total_points'
),
ARRAY_A
);
何が違うのでしょうか? AI はメタデータが別の user_activity_meta テーブルにあることを確認し、activity_id によるリレーションシップを理解して、利用できるメタキーを正確に把握できました。一発で完了。推測はゼロ。問題解決です。
🚀 これですべてが変わる理由
AI アシスタントがデータベースを読み取れると:
- スキーマを推測する必要がなくなります - 実際のテーブルとカラムを確認できます
- 正確な JOIN 操作 - テーブル間のリレーションシップを理解します
- 実データの検証 - クエリを提案する前にデータの有無を確認できます
- プラグインを考慮した開発 - あらゆるプラグインのカスタムテーブル(WooCommerce、LearnDash など)に対応します
- すばやいデバッグ - 「クイズ ID 42 を完了していないユーザーをすべて表示して」が 5 秒で完了します
🔧 解決した Local by Flywheel の課題
元の mcp-server-mysql を Local by Flywheel で使用する場合、開発者はいくつかの課題に直面します。
- 動的なパス:Local by Flywheel はサイトごとに一意の識別子(
lx97vbzE7など)を生成します。この識別子はサイトの再起動時に変わります。 - ソケットとポートの混同:Local は Unix ソケットと TCP ポートの両方を使用しますが、設定が複雑な場合があります。
- 設定のハードコード:多くのセットアップでは、Local の再起動のたびにパスを手動で更新する必要があります。
ソリューション
この MCP サーバーは、以下の方法でアクティブな Local by Flywheel MySQL インスタンスを自動的に検出します。
- プロセス検出:実行中のプロセスをスキャンして、アクティブな
mysqldインスタンスを見つけます。 - 設定の解析:アクティブな Local サイトから MySQL の設定を取得します。
- 動的な接続:正しいソケットパスまたはポートを自動的に使って接続します。
- フォールバック対応:Local 以外のセットアップでは、環境変数にフォールバックします。
複数サイトのサポート
複数の Local サイトがある場合、サーバーは優先順位に基づいてサイトを選択し、常に正しいデータベースに接続できるようにします。
選択の優先順位
SITE_ID環境変数 - サイト ID を直接指定(最優先)SITE_NAME環境変数 - 人が読みやすいサイト名から検索- 作業ディレクトリの検出 - cwd が Local サイトのパス内にある場合、そのサイトを使用
- プロセス検出 - 最初に見つかった実行中の Local mysqld
- ファイルシステムのフォールバック - 最終更新日時が最も新しいソケット
サイトの明示的な選択
MCP 設定で接続先のサイトを指定します。
{
"mcpServers": {
"wordpress-dev": {
"command": "npx",
"args": ["-y", "@verygoodplugins/mcp-local-wp@latest"],
"env": {
"SITE_NAME": "dev"
}
}
}
}
または、サイト ID を直接指定します。
{
"env": {
"SITE_ID": "lx97vbzE7"
}
}
作業ディレクトリの検出
Claude Code または Cursor を使用すると、サーバーは現在のディレクトリに基づいて、作業中のサイトを自動的に検出します。/Users/.../Local Sites/dev/app/public/wp-content/plugins/my-plugin/ 内のファイルを編集している場合、サーバーは「dev」サイトのデータベースに自動的に接続します。
接続の確認
mysql_current_site ツールを使用すると、接続中のサイトを確認できます。
{
"siteName": "dev",
"siteId": "lx97vbzE7",
"sitePath": "/Users/.../Local Sites/dev",
"domain": "dev.local",
"selectionMethod": "cwd_detection",
}
mysql_list_sites を使用すると、利用可能なすべてのサイトとそのステータスを確認できます。
利用可能なツール
mysql_query
Local の WordPress データベースに対して、読み取り専用の SQL を実行します。
入力フィールド:
sql(文字列):単一の読み取り専用ステートメント(WITH CTE を含む SELECT、または SHOW/DESCRIBE/EXPLAIN)params((文字列 | 数値 | ブール値 | null)[]):省略可能なパラメーター値。?プレースホルダーに使用します。
使用例:
-- With parameters
SELECT * FROM wp_posts WHERE post_status = ? ORDER BY post_date DESC LIMIT ?;
-- params: ["publish", "5"]
-- Direct queries
SELECT option_name, option_value FROM wp_options WHERE option_name LIKE '%theme%';
SHOW TABLES;
DESCRIBE wp_users;
-- Common table expression (CTE)
WITH published AS (SELECT ID, post_title FROM wp_posts WHERE post_status = ?)
SELECT * FROM published LIMIT 10;
-- params: ["publish"]
mysql_schema
INFORMATION_SCHEMA を使ってデータベースのスキーマを調べます。
- 引数なし:最大 100 件のテーブル名をバイナリ名順に一覧表示し、
hasMoreとnextAfterを返します。 - 一覧表示オプション:
prefix(大文字と小文字を区別するリテラルのプレフィックス)、limit(1~200)、after(前のページのnextAfter)、includeStats(デフォルトは false) tableを指定:そのテーブルのカラムとインデックスを返します。
hasMore が true の場合、同じプレフィックスを指定して nextAfter を after に渡すと、次のページを取得できます。最後のページでは hasMore が false、nextAfter が null になります。デフォルトでは、一覧の各行には table_name のみが含まれます。includeStats: true を指定すると、エンジン、推定行数、データのバイト数、インデックスのバイト数が追加されます。プレフィックス内の % と _ はリテラル文字として扱われます。詳細を調べるには table のみを使用してください。一覧表示オプションと併用することはできません。各ページには現在のスキーマが反映されるため、リクエスト間にテーブルが変更されると、一覧の内容に影響する場合があります。
使用例:
// First page of table names
{
"tool": "mysql_schema",
"args": {}
}
// Filter to WordPress tables and include statistics
{
"tool": "mysql_schema",
"args": { "prefix": "wp_", "limit": 50, "includeStats": true }
}
// Continue a filtered listing using the previous response's nextAfter
{
"tool": "mysql_schema",
"args": { "prefix": "wp_", "limit": 50, "after": "wp_posts" }
}
// Inspect a specific table
{
"tool": "mysql_schema",
"args": { "table": "wp_posts" }
}
mysql_current_site
現在接続中の Local WordPress サイトの情報を取得します。
サイト名、ID、パス、ドメイン、ソケットパス、およびサイトの選択方法(環境変数、cwd の検出、自動検出)を返します。
{
"tool": "mysql_current_site",
"args": {},
}
// Returns:
// {
// "siteName": "dev",
// "siteId": "lx97vbzE7",
// "sitePath": "/Users/.../Local Sites/dev",
// "domain": "dev.local",
// "selectionMethod": "cwd_detection",
// "socketPath": "/Users/.../Local/run/lx97vbzE7/mysql/mysqld.sock"
// }
mysql_list_sites
利用可能なすべての Local WordPress サイトと、その実行状態を一覧表示します。
{
"tool": "mysql_list_sites",
"args": {},
}
// Returns:
// {
// "sites": [
// { "id": "lx97vbzE7", "name": "dev", "domain": "dev.local", "running": true },
// { "id": "WP7lolWDi", "name": "staging", "domain": "staging.local", "running": false }
// ],
// "currentSiteId": "lx97vbzE7"
// }
インストール
前提条件
- Local by Flywheel がインストールされ、実行中であること
- アクティブな Local サイトが実行中であること
- Node.js 24 以降
クイックセットアップ(推奨)
始めるのに最も簡単な方法です。インストールは不要です。
Cursor IDE の設定
Cursor の MCP 設定ファイル(.cursor/mcp.json)に以下を追加します。
{
"mcpServers": {
"mcp-local-wp": {
"command": "npx",
"args": ["-y", "@verygoodplugins/mcp-local-wp@latest"]
}
}
}
Claude Desktop の設定
Claude Desktop の設定ファイルに以下を追加します。
macOS:~/Library/Application Support/Claude/claude_desktop_config.json
Windows:%APPDATA%\\Claude\\claude_desktop_config.json
{
"mcpServers": {
"mcp-local-wp": {
"command": "npx",
"args": ["-y", "@verygoodplugins/mcp-local-wp@latest"]
}
}
}
詳細セットアップ(ローカル開発)
カスタマイズまたはローカル開発を行う場合:
ソースからインストール
git clone https://github.com/verygoodplugins/mcp-local-wp.git
cd mcp-local-wp
npm install
npm run build
ローカル設定
{
"mcpServers": {
"mcp-local-wp": {
"command": "node",
"args": ["/full/path/to/mcp-local-wp/dist/index.js"]
}
}
}
カスタム環境変数
Local 以外のセットアップやカスタム設定の場合:
{
"mcpServers": {
"mcp-local-wp": {
"command": "npx",
"args": ["-y", "@verygoodplugins/mcp-local-wp@latest"],
"env": {
"MYSQL_DB": "local",
"MYSQL_HOST": "localhost",
"MYSQL_PORT": "3306",
"MYSQL_USER": "root",
"MYSQL_PASS": "root"
}
}
}
}
サイト選択変数
| 変数 | 説明 | 例 |
|---|---|---|
SITE_ID | 明示的なサイト ID(最優先) | lx97vbzE7 |
SITE_NAME | 検索するサイト名 | dev |
LOCAL_SITES_JSON | Local の sites.json のパスを上書き | /custom/path/sites.json |
LOCAL_RUN_DIR | Local の実行ディレクトリを上書き | /custom/run/path |
Local by Flywheel との連携方法
この MCP サーバーは、既存の MCP サーバーでは Local by Flywheel の MySQL への接続が**「なんとか動かすのが難しい」**ことから作成されました。解決した問題をご紹介します。
当初の問題
Local by Flywheel で mcp-server-mysql を使おうとしたところ、いくつかの問題に直面しました。
- 動的なソケットパス:Local は
/Users/.../Local/run/lx97vbzE7/mysql/mysqld.sockのようなパスを生成しますが、Local を再起動するたびにlx97vbzE7が変わります - 複雑な設定:元のサーバーではパスをハードコードする必要があり、Local を再起動するたびに動作しなくなります
- ホスト/ポートの混乱:ソケット接続と TCP 接続の両方が利用できるため、Local の MySQL 設定は扱いが難しい場合があります
解決までの手順
段階的に解決しました。
1. プロセスベースの検出
パスを推測する代わりに、実際に実行中の MySQL プロセスを検索します。
ps aux | grep mysqld | grep -v grep
これにより、アクティブな MySQL インスタンスを見つけ、その設定ファイルのパスを取得します。
2. 動的なパス解決
// From the process args: --defaults-file=/Users/.../Local/run/lx97vbzE7/conf/mysql/my.cnf
// We extract the site directory and build the socket path
const configPath = extractFromProcess();
const siteDir = path.dirname(path.dirname(path.dirname(configPath)));
const socketPath = path.join(siteDir, 'mysql/mysqld.sock');
3. 自動設定
サーバーは以下を自動的に設定します。
- アクティブな Local サイトの正しいソケットパス
- 適切なデータベース名(
local) - デフォルトの認証情報(
root/root) - 必要に応じて環境変数にフォールバック
この方法が機能する理由
✅ 再起動に強い:Local by Flywheel を再起動するたびに動作します
✅ サイトの切り替え:Local サイトを切り替えると自動的に対応します
✅ メンテナンス不要:パスを手動で更新する必要はもうありません
✅ エラー処理:MySQL が実行されていない場合、明確なエラーメッセージを表示します
対応する Local のディレクトリ構造
~/Library/Application Support/Local/run/
├── lx97vbzE7/ # Dynamic site ID (changes on restart)
│ ├── conf/mysql/my.cnf # We read this for port info
│ └── mysql/mysqld.sock # We connect via this socket
└── WP7lolWDi/ # Another site (if multiple running)
├── conf/mysql/my.cnf
└── mysql/mysqld.sock
サーバーはアクティブなサイトをインテリジェントに検出し、適切な MySQL インスタンスに接続します。
使用例
接続すると、mysql_query ツールを使って、Local の WordPress データベースに対し、許可された読み取り専用の SQL クエリを実行できます。
最近の投稿を取得する
SELECT ID, post_title, post_date, post_status
FROM wp_posts
WHERE post_type = 'post' AND post_status = 'publish'
ORDER BY post_date DESC
LIMIT 5;
データベース構造を確認する
-- See all tables
SHOW TABLES;
-- Examine a table structure
DESCRIBE wp_posts;
-- Get table info
SHOW TABLE STATUS LIKE 'wp_%';
WordPress 固有のクエリ
-- Get site options
SELECT option_name, option_value
FROM wp_options
WHERE option_name IN ('blogname', 'blogdescription', 'admin_email');
-- Find active plugins
SELECT option_value
FROM wp_options
WHERE option_name = 'active_plugins';
-- Get user information
SELECT user_login, user_email, display_name
FROM wp_users
LIMIT 10;
-- Post meta data
SELECT p.post_title, pm.meta_key, pm.meta_value
FROM wp_posts p
JOIN wp_postmeta pm ON p.ID = pm.post_id
WHERE p.post_type = 'post' AND pm.meta_key = '_edit_last';
開発環境のセットアップ
ソースから実行する
-
Local サイトを起動する:アクティブな Local by Flywheel サイトが実行されていることを確認します
-
クローンしてビルドする:
git clone https://github.com/verygoodplugins/mcp-local-wp.git cd mcp-local-wp npm install npm run build -
接続をテストする:
node dist/index.js
開発モード
npm run dev
このコマンドは、TypeScript の変更を監視しながらサーバーを実行します。
リントとフォーマット
- リント:
npm run lint - リントを修正:
npm run lint:fix - フォーマット:
npm run format - フォーマットを確認:
npm run format:check
ESLint と Prettier により、MCP サーバー全体で規約を統一しています。
トラブルシューティング
よくある問題
-
「アクティブな MySQL プロセスが見つかりません」
- Local by Flywheel が実行中であることを確認してください
- Local で少なくとも 1 つのサイトが起動していることを確認してください
- サイトのデータベースが実行中であることを確認してください
-
「MySQL ソケットが見つかりません」
- Local のサイトが完全に起動していることを確認してください
- Local でサイトを停止してから再起動してみてください
- MySQL の起動に関する問題がないか、Local のログを確認してください
-
接続が拒否されました
- Local のサイトの MySQL サービスが実行中であることを確認してください
- 別のプロセスが MySQL ポートを使用していないか確認してください
- Local by Flywheel を再起動してみてください
-
アクセスが拒否されました
- MySQL ソケットファイルに適切な権限が設定されていることを確認してください
- ユーザーが Local のディレクトリにアクセスできるか確認してください
手動設定
自動検出に失敗する場合は、接続を手動で設定できます。
export MYSQL_SOCKET_PATH="/path/to/your/local/site/mysql/mysqld.sock"
export MYSQL_DB="local"
export MYSQL_USER="root"
export MYSQL_PASS="root"
デバッグ
DEBUGを設定して、デバッグログを有効にしてください。
DEBUG=mcp-local-wp mcp-local-wp
セキュリティ
mysql_queryは、WITH または WITH RECURSIVE で始まる SELECT クエリを含め、単一の SELECT/SHOW/DESCRIBE/DESC/EXPLAIN 文を受け付けます。CTE のクエリ本体と最終的なクエリ式は、ネストされた WITH … SELECT や括弧で囲まれたクエリを含め、SELECT に解決される必要があります。WITH … UPDATE/DELETE は拒否されます。MariaDB のサイクル検出用 CYCLE … RESTRICT 句をサポートしています。トークナイザーは、接続の SQL モードを使用して実際の SQL トークンを検査します。実行可能な MySQL/MariaDB コメント、オプティマイザーヒント、ファイル出力、SELECT INTO、ロック読み取り、アドバイザリーロック関数、EXPLAIN ANALYZE は、CTE 本体を含む文全体で拒否されます。通常のコメントと、引用符で囲まれた値内のセミコロンはサポートされています。
すべての読み取りは、専用接続でデータベースによって強制される読み取り専用トランザクション内で実行されます。セットアップに失敗すると実行は停止し、クリーンアップに失敗すると接続は破棄されます。MYSQL_ALLOW_WRITES=trueを設定すると、別の接続でmysql_writeが公開されます。この設定によってmysql_queryの保護が無効になることはありません。書き込み文では INSERT/UPDATE/DELETE が許可されます。UPDATE/DELETE では、WHERE 内の列比較にバインド済みパラメーターを使う必要があり、AND/OR でグループ化できます。IN、BETWEEN、LIKE でもバインド済みの値を使用できます。プレースホルダーのみ、またはリテラル値のみの述語は拒否されます。スキーマ操作と書き込みサブクエリは引き続きブロックされます。
保護を強化するには、選択したデータベースへの SELECT 権限のみを付与し、FILE 権限と EXECUTE 権限を持たない専用アカウントを設定してください。MYSQL_USERとMYSQL_PASSは、手動接続だけでなく、自動検出された Local のサイトにも適用されます。サーバーがユーザーを作成したり、権限を変更したりすることはありません。読み取り専用トランザクションは、一時テーブルや任意のネイティブ拡張機能に対するサンドボックスではありません。信頼できないデータベースには、最小権限の認証情報を使用してください。
このサーバーはローカル開発をサポートしており、利用可能な場合は Unix ソケットを、明示的な接続では TCP を使用します。脆弱性は、GitHub Security Advisoriesまたは[email protected]を通じて非公開で報告してください。
貢献
貢献を歓迎します。お気軽にプルリクエストを送信してください。
開発ガイドライン
- リポジトリをフォークします
- フィーチャーブランチを作成します:
git checkout -b feature/your-feature-name - 変更を加え、テストを追加します
- TypeScript がコンパイルされることを確認します:
npm run build - プルリクエストを送信します
ライセンス
GPL-3.0-or-later。詳細についてはLICENSEファイルを参照してください。WordPress に特化したツールとして、コミュニティにとってこのツールが自由で開かれたものであり続けるよう、コピーレフトの理念を大切にしています。
サポート
- GitHub Issues:バグの報告や機能のリクエスト
- ドキュメント:この README とインラインコードのドキュメント
- コミュニティ:Model Context Protocol のコミュニティディスカッションに参加する
関連プロジェクト
- mcp-server-mysql - この WordPress 専用バージョンの着想となった、オリジナルの MySQL MCP サーバー
- Local by Flywheel - このサーバー向けに設計されたローカル WordPress 開発環境
- Model Context Protocol - プロトコル仕様
Very Good Plugins の Jack Arturo が🧡を込めて開発 · オープンソースコミュニティへの愛を込めて
コメント
AI アプリケーションが外部のツールやデータソースに統一的な方法で接続するためのオープンなプロトコルです。クライアントはモデルとの対話を担い、MCP サーバーはツール・リソース・プロンプトテンプレートを提供します。標準メッセージでやり取りするため、1 つのサーバーを複数のクライアントで再利用できます。