diff --git a/.cursor/mcp.json b/.cursor/mcp.json new file mode 100644 index 00000000..31d42ca9 --- /dev/null +++ b/.cursor/mcp.json @@ -0,0 +1,13 @@ +{ + "mcpServers": { + "rdb-local": { + "command": "npx", + "args": [ "-y", "@automattic/mcp-wordpress-remote@latest" ], + "env": { + "WP_API_URL": "http://localhost:8888/", + "JWT_TOKEN": "{{ JWT token from WordPress MCP settings }}", + "LOG_FILE": "/tmp/mcp-remote-data-blocks-local.log" + } + } + } +} diff --git a/.gitignore b/.gitignore index 1179b36c..321236de 100644 --- a/.gitignore +++ b/.gitignore @@ -51,4 +51,5 @@ vendor/ !.idea/runConfigurations/ .vscode/* !.vscode/launch.json +!.vscode/mcp.json .zed diff --git a/.nvmrc b/.nvmrc index 209e3ef4..2bd5a0a9 100644 --- a/.nvmrc +++ b/.nvmrc @@ -1 +1 @@ -20 +22 diff --git a/.vscode/launch.json b/.vscode/launch.json index ab72388d..92aadaca 100644 --- a/.vscode/launch.json +++ b/.vscode/launch.json @@ -7,7 +7,9 @@ "request": "launch", "port": 9003, "pathMappings": { - "/var/www/html/wp-content/plugins/remote-data-blocks": "${workspaceFolder}/" + "/var/www/html/wp-content/plugins/remote-data-blocks": "${workspaceFolder}/", + "/var/www/html/wp-content/plugins/wp-feature-api": "${workspaceFolder}/../wp-feature-api", + "/var/www/html/wp-content/plugins/wordpress-mcp": "${workspaceFolder}/../wordpress-mcp" } }, { diff --git a/.vscode/mcp.json b/.vscode/mcp.json new file mode 100644 index 00000000..2448bc11 --- /dev/null +++ b/.vscode/mcp.json @@ -0,0 +1,13 @@ +{ + "servers": { + "rdb-local": { + "command": "npx", + "args": [ "-y", "@automattic/mcp-wordpress-remote@latest" ], + "env": { + "WP_API_URL": "http://localhost:8888/", + "JWT_TOKEN": "{{ JWT token from WordPress MCP settings }}", + "LOG_FILE": "/tmp/mcp-remote-data-blocks-local.log" + } + } + } +} diff --git a/.wp-env.json b/.wp-env.json index c4f1cd99..8c472227 100644 --- a/.wp-env.json +++ b/.wp-env.json @@ -13,6 +13,8 @@ "plugins": [ ".", "https://downloads.wordpress.org/plugin/query-monitor.latest-stable.zip", - "https://downloads.wordpress.org/plugin/redis-cache.latest-stable.zip" + "https://downloads.wordpress.org/plugin/redis-cache.latest-stable.zip", + "https://github.com/Automattic/wp-feature-api/releases/download/0.1.5/wp-feature-api.zip", + "https://github.com/Automattic/wordpress-mcp/releases/download/v0.2.0/wordpress-mcp.zip" ] } diff --git a/inc/Integrations/Mcp/Features/ListDataSourcesFeature.php b/inc/Integrations/Mcp/Features/ListDataSourcesFeature.php new file mode 100644 index 00000000..011ab2fa --- /dev/null +++ b/inc/Integrations/Mcp/Features/ListDataSourcesFeature.php @@ -0,0 +1,139 @@ + 'rdb-list-data-sources', + 'name' => 'List Remote Data Block data sources', + 'description' => 'List all Remote Data Block data sources with optional filtering by service type or block enablement status, including code snippets', + 'callback' => [ __CLASS__, 'handle_request' ], + 'is_eligible' => '__return_true', + 'permission_callback' => '__return_true', + 'input_schema' => [ + 'type' => 'object', + 'properties' => [ + 'service' => [ + 'type' => 'string', + 'description' => 'Filter by service name (e.g., "airtable", "google-sheets", "shopify")', + 'enum' => [ + 'airtable', + 'generic-http', + 'google-sheets', + 'shopify', + ], + ], + 'enable_blocks' => [ + 'type' => 'boolean', + 'description' => 'Filter by blocks enabled status (true shows only sources with blocks enabled, false shows only disabled)', + ], + 'include_snippets' => [ + 'type' => 'boolean', + 'description' => 'Include code snippets for each data source (default: true)', + 'default' => true, + ], + ], + 'additionalProperties' => false, + ], + ] ); + } + + /** + * Handle the feature request and return data sources. + */ + public static function handle_request( WP_REST_Request $request ): array { + // Validate and sanitize parameters + $params = $request->get_params(); + $filters = []; + + if ( isset( $params['service'] ) && is_string( $params['service'] ) ) { + $filters['service'] = sanitize_text_field( $params['service'] ); + } + + if ( isset( $params['enable_blocks'] ) && is_bool( $params['enable_blocks'] ) ) { + $filters['enable_blocks'] = $params['enable_blocks']; + } + + $include_snippets = $params['include_snippets'] ?? true; + $data_sources = DataSourceConfigManager::get_all( $filters ); + + // Handle errors + if ( is_wp_error( $data_sources ) ) { + return [ + 'success' => false, + 'error' => $data_sources->get_error_message(), + ]; + } + + return [ + 'success' => true, + 'data' => array_map( + function ( array $data_source ) use ( $include_snippets ): array { + return self::format_data_source( $data_source, $include_snippets ); + }, + $data_sources + ), + 'count' => count( $data_sources ), + ]; + } + + /** + * Format data source + */ + private static function format_data_source( array $data_source, bool $include_snippets = true ): array { + // Add code snippets if requested and data source has UUID + $code_snippets = []; + if ( $include_snippets && isset( $data_source['uuid'] ) ) { + $code_snippets = Snippet::generate_snippets( $data_source['uuid'] ); + + // Only add snippets if generation was successful + if ( is_wp_error( $code_snippets ) ) { + $code_snippets = []; + } + } + + return [ + 'uuid' => $data_source['uuid'] ?? null, + 'display_name' => $data_source['service_config']['display_name'] ?? $data_source['display_name'] ?? null, + 'code_snippets' => array_map( + function ( Snippet $snippet ): array { + return $snippet->jsonSerialize(); + }, + $code_snippets + ), + 'config_source' => $data_source['config_source'] ?? 'unknown', + 'service' => $data_source['service'] ?? null, + ]; + } +} diff --git a/inc/Integrations/Mcp/Mcp.php b/inc/Integrations/Mcp/Mcp.php new file mode 100644 index 00000000..94b737af --- /dev/null +++ b/inc/Integrations/Mcp/Mcp.php @@ -0,0 +1,12 @@ + 'list-remote-data-blocks-data-sources', + 'description' => 'List Remote Data Blocks data sources.', + 'arguments' => [ + [ + 'name' => 'data-source-uuid', + 'description' => 'The UUID of the Remote Data Blocks data source to retrieve (optional)', + 'required' => false, + 'type' => 'string', + ], + ], + ], + [ + [ + 'role' => 'user', + 'content' => [ + 'type' => 'text', + 'text' => 'List all registered Remote Data Blocks data source', + ], + ], + [ + 'role' => 'user', + 'content' => [ + 'type' => 'text', + 'text' => 'List the Remote Data Blocks data source with the UUID: {{data_source_uuid}}', + ], + ], + ], + ); + } +} diff --git a/remote-data-blocks.php b/remote-data-blocks.php index 32677be3..fcf0cbc8 100644 --- a/remote-data-blocks.php +++ b/remote-data-blocks.php @@ -53,6 +53,7 @@ Integrations\Airtable\AirtableIntegration::init(); Integrations\Google\Sheets\GoogleSheetsIntegration::init(); Integrations\Shopify\ShopifyIntegration::init(); +Integrations\Mcp\Mcp::init(); Integrations\VipBlockDataApi\VipBlockDataApi::init(); // REST endpoints