WordPress MCP プラグインをサブディレクトリインストールで動作させる方法

Claude Desktopからワードプレスの操作をしたかったが、ワードプレスがルートディレクトリの場合は問題なく動作するのものの、サブディレクトリの場合はエラーが発生することが判明。
結局、ワードプレスのプラグインや公式のMCPサーバーにバグがあることがわかり、修正した記録です。

※以降、AI出力のテキストなので、実施の際はご注意ください。

問題の概要

WordPress MCP プラグイン (v0.2.5) には、サブディレクトリにインストールされた WordPress で動作しないバグが2つあります:

  1. クライアント側のバグ: サブディレクトリのパスを正しく処理できない
  2. プラグイン側のバグ: JWT認証が正しく機能しない

影響を受ける環境

  • 動作する: https://example.com/ (ルートインストール)
  • 動作しない: https://example.com/blog/ (サブディレクトリインストール)

修正方法

パート1: クライアント側の修正(NPMパッケージ)

対象ファイル

@automattic/mcp-wordpress-remote パッケージの dist/proxy.js

修正箇所

38308行目付近の constructApiUrl 関数

修正前:

function constructApiUrl(baseUrl, defaultEndpoint) {
  const cleanUrl = removeTrailingSlash(baseUrl);
  try {
    const urlObj = new URL(cleanUrl);
    const hasCustomPath = urlObj.pathname && urlObj.pathname !== "/" && urlObj.pathname.length > 0;
    const hasCustomQuery = urlObj.search && urlObj.search.length > 0;
    
    if (hasCustomPath || hasCustomQuery) {
      return cleanUrl;  // ← バグ: サブディレクトリでクエリパラメータが付かない
    } else {
      return new URL(`/?rest_route=${defaultEndpoint}`, cleanUrl).toString();
    }
  } catch (error) {
    return new URL(`/?rest_route=${defaultEndpoint}`, cleanUrl).toString();
  }
}

修正後:

function constructApiUrl(baseUrl, defaultEndpoint) {
  const cleanUrl = removeTrailingSlash(baseUrl);
  try {
    const urlObj = new URL(cleanUrl);
    const hasCustomQuery = urlObj.search && urlObj.search.length > 0;
    
    // If there's already a custom query (like ?rest_route=...), use the URL as-is
    if (hasCustomQuery) {
      return cleanUrl;
    } else {
      // Always append ?rest_route= for all paths (including subdirectories)
      // Add trailing slash before query parameter for WordPress compatibility
      return `${cleanUrl}/?rest_route=${defaultEndpoint}`;
    }
  } catch (error) {
    // Fallback: always append ?rest_route=
    return `${cleanUrl}/?rest_route=${defaultEndpoint}`;
  }
}

変更点の説明

  1. hasCustomPath チェックを削除: サブディレクトリの存在をチェックしていた条件を削除
  2. URL構築方法を変更: new URL() ではなく文字列連結を使用してパスを保持
  3. 末尾スラッシュを追加: WordPressのリライトルール互換性のため

修正済みパッケージのインストール方法

方法1: グローバルインストール(推奨)

修正済みパッケージをダウンロード後:

npm install -g /path/to/automattic-mcp-wordpress-remote-0.2.18-patched.tgz

Claude Desktop 設定 (~/Library/Application Support/Claude/claude_desktop_config.json):

{
  "mcpServers": {
    "wordpress-mcp": {
      "command": "npx",
      "args": ["@automattic/mcp-wordpress-remote"],
      "env": {
        "WP_API_URL": "https://example.com/blog/",
        "JWT_TOKEN": "your-jwt-token-here"
      }
    }
  }
}

方法2: ローカルパス指定

修正済みパッケージを展開後:

{
  "mcpServers": {
    "wordpress-mcp": {
      "command": "node",
      "args": ["/Users/username/mcp-packages/dist/proxy.js"],
      "env": {
        "WP_API_URL": "https://example.com/blog/",
        "JWT_TOKEN": "your-jwt-token-here"
      }
    }
  }
}

パート2: プラグイン側の修正(WordPress プラグイン)

修正が必要なファイル(2つ)

1. McpTransportBase.php

ファイルパス:
wp-content/plugins/wordpress-mcp/includes/Core/McpTransportBase.php

修正箇所: 195行目付近

修正前:

/**
 * Check if the user has permission to access the MCP API
 *
 * @return bool|WP_Error
 */
abstract public function check_permission(): WP_Error|bool;

修正後:

/**
 * Check if the user has permission to access the MCP API
 *
 * @param mixed $request The request object (optional).
 * @return bool|WP_Error
 */
abstract public function check_permission( $request = null );

変更点:

  • $request = null パラメータを追加
  • 戻り値の型宣言 : WP_Error|bool を削除(PHP 8.0 互換性のため)

2. McpStdioTransport.php

ファイルパス:
wp-content/plugins/wordpress-mcp/includes/Core/McpStdioTransport.php

修正箇所: 48-102行目付近の check_permission() メソッド

修正前:

public function check_permission(): WP_Error|bool {
    // If MCP is disabled, deny access.
    if ( ! $this->is_mcp_enabled() ) {
        return new WP_Error(
            'mcp_disabled',
            'MCP functionality is currently disabled.',
            array( 'status' => 403 )
        );
    }

    // JWT authentication handles user validation, so just check if user is logged in.
    return is_user_logged_in();  // ← バグ: JWT認証をチェックしていない
}

修正後:

public function check_permission( $request = null ) {
    // If MCP is disabled, deny access.
    if ( ! $this->is_mcp_enabled() ) {
        return new WP_Error(
            'mcp_disabled',
            'MCP functionality is currently disabled.',
            array( 'status' => 403 )
        );
    }

    // Check if request is authenticated.
    $auth_result = apply_filters( 'wpmcp_authenticate_request', null, $request );

    // Also check OAuth Passport if available and no other auth method succeeded.
    if ( empty( $auth_result ) && function_exists( 'oauth_passport_get_current_token' ) ) {
        // OAuth Passport will handle authentication through WordPress core filters.
        // Just check if user is logged in (OAuth Passport sets current user).
        if ( is_user_logged_in() ) {
            $auth_result = true;
        }
    }

    if ( empty( $auth_result ) ) {
        return new WP_Error(
            'unauthorized',
            'Authentication required',
            array( 'status' => 401 )
        );
    }

    // If authentication filter authenticated the user, allow access.
    if ( true === $auth_result ) {
        return true;
    }

    // Fall back to checking if the user is logged in (for cookie auth).
    if ( is_user_logged_in() ) {
        return true;
    }

    // No valid authentication found.
    return new WP_Error(
        'unauthorized',
        'Authentication required. Please provide a valid JWT or OAuth token.',
        array( 'status' => 401 )
    );
}

また、handle_request() メソッドも修正:

修正前(126行目付近):

$params = $message['params'] ?? $message;

修正後(PHP 8.0 互換性のため):

$params = isset( $message['params'] ) ? $message['params'] : $message;

format_error_response() メソッドも修正(189行目付近):

修正前:

protected function format_error_response( array $error, int $request_id = 0 ): WP_Error {
    $error_details = $error['error'] ?? $error;

    return new WP_Error(
        $error_details['code'] ?? 'handler_error',
        ( $error_details['message'] ?? 'Handler error occurred' ) . ' [DEBUG: ' . wp_json_encode( $error_details ) . ']',
        array( 'status' => $error_details['data']['status'] ?? 500 )
    );
}

修正後:

protected function format_error_response( array $error, int $request_id = 0 ) {
    $error_code = isset( $error['error']['code'] ) ? $error['error']['code'] : 'handler_error';
    $error_message = isset( $error['error']['message'] ) ? $error['error']['message'] : 'Handler error occurred';
    $error_status = isset( $error['error']['data']['status'] ) ? $error['error']['data']['status'] : 500;

    return new WP_Error(
        $error_code,
        $error_message . ' [DEBUG: ' . wp_json_encode( $error ) . ']',
        array( 'status' => $error_status )
    );
}

インストール手順

1. バックアップ

必ず元のファイルをバックアップしてください:

wp-content/plugins/wordpress-mcp/includes/Core/にて

  • McpTransportBase.php → コピーして名前を変更 TransportBase.php.backup
  • McpStdioTransport.php → コピーして名前を変更 McpStdioTransport.php.backup

2. ファイルの修正

上記の修正を適用します。

3. プラグインの再起動

  1. WordPress管理画面 → プラグイン → インストール済みプラグイン
  2. 「WordPress MCP」を無効化
  3. 再度有効化
  4. 設定 → パーマリンク設定 → 「変更を保存」をクリック

4. Claude Desktop の再起動

Claude Desktop アプリを完全に終了して再起動します。

あなたへのおすすめ