'Create a new WooCommerce product (simple or variable) with attributes, variations, and images.', 'inputSchema' => [ 'type' => 'object', 'required' => ['name'], 'properties' => [ 'name' => [ 'type' => 'string', 'description' => 'Product title' ], 'type' => [ 'type' => 'string', 'enum' => ['simple','variable','grouped','external'], 'default' => 'simple' ], 'status' => [ 'type' => 'string', 'enum' => ['publish','draft','private'], 'default' => 'draft' ], 'regular_price' => [ 'type' => 'string', 'description' => 'Price (simple products)' ], 'description' => [ 'type' => 'string' ], 'short_description' => [ 'type' => 'string' ], 'sku' => [ 'type' => 'string' ], 'manage_stock' => [ 'type' => 'boolean', 'default' => false ], 'stock_quantity' => [ 'type' => 'integer' ], 'stock_status' => [ 'type' => 'string', 'enum' => ['instock','outofstock','onbackorder'], 'default' => 'instock' ], 'categories' => [ 'type' => 'array', 'items' => [ 'type' => 'object' ] ], 'tags' => [ 'type' => 'array', 'items' => [ 'type' => 'object' ] ], 'images' => [ 'type' => 'array', 'items' => [ 'type' => 'object' ], 'description' => 'Array of {src, alt}. First image becomes the featured image.' ], 'attributes' => [ 'type' => 'array', 'items' => [ 'type' => 'object' ] ], 'variations' => [ 'type' => 'array', 'items' => [ 'type' => 'object' ], 'description' => 'Omit to auto-generate one variation per attribute combination.' ], ], ], ]; return $tools; } add_filter( 'store_mcp_handle_tool', 'store_mcp_handle_create_product_tool', 10, 2 ); /** * Handle the create_product tool call. * * @param mixed $result Existing result (null if not yet handled). * @param array $payload [ 'tool' => string, 'params' => array ] * @return mixed Handled result or original $result. */ function store_mcp_handle_create_product_tool( $result, array $payload ) { if ( 'create_product' !== ( $payload['tool'] ?? '' ) ) { return $result; // Not our tool — pass through. } if ( ! class_exists( 'WooCommerce' ) ) { return new WP_Error( 'woocommerce_missing', 'WooCommerce is not active.', [ 'status' => 500 ] ); } $p = $payload['params'] ?? []; /* ------------------------------------------------------------------ */ /* 1. Create the product via the WooCommerce REST API internally. */ /* ------------------------------------------------------------------ */ $request = new WP_REST_Request( 'POST', '/wc/v3/products' ); $request->set_header( 'content-type', 'application/json' ); $body = [ 'name' => sanitize_text_field( $p['name'] ?? '' ), 'type' => sanitize_key( $p['type'] ?? 'simple' ), 'status' => sanitize_key( $p['status'] ?? 'draft' ), 'description' => wp_kses_post( $p['description'] ?? '' ), 'short_description' => wp_kses_post( $p['short_description'] ?? '' ), 'regular_price' => sanitize_text_field( $p['regular_price'] ?? '' ), 'sku' => sanitize_text_field( $p['sku'] ?? '' ), 'manage_stock' => (bool) ( $p['manage_stock'] ?? false ), 'stock_quantity' => isset( $p['stock_quantity'] ) ? (int) $p['stock_quantity'] : null, 'stock_status' => sanitize_key( $p['stock_status'] ?? 'instock' ), 'categories' => $p['categories'] ?? [], 'tags' => $p['tags'] ?? [], 'images' => $p['images'] ?? [], 'attributes' => $p['attributes'] ?? [], ]; $request->set_body( wp_json_encode( $body ) ); $response = rest_do_request( $request ); if ( $response->is_error() ) { $error = $response->as_error(); return [ 'success' => false, 'error' => $error->get_error_message(), 'code' => $error->get_error_code(), ]; } $product_data = $response->get_data(); $product_id = $product_data['id']; /* ------------------------------------------------------------------ */ /* 2. Optionally create variations for variable products. */ /* ------------------------------------------------------------------ */ $created_variations = []; if ( 'variable' === $body['type'] ) { $variations_input = $p['variations'] ?? []; // Auto-generate one variation per attribute combination if none supplied. if ( empty( $variations_input ) && ! empty( $body['attributes'] ) ) { $variations_input = store_mcp_generate_variations( $body['attributes'], $body['regular_price'] ); } foreach ( $variations_input as $var ) { $var_request = new WP_REST_Request( 'POST', "/wc/v3/products/{$product_id}/variations" ); $var_request->set_header( 'content-type', 'application/json' ); $var_request->set_body( wp_json_encode( $var ) ); $var_response = rest_do_request( $var_request ); if ( ! $var_response->is_error() ) { $created_variations[] = $var_response->get_data(); } } } /* ------------------------------------------------------------------ */ /* 3. Return a clean summary. */ /* ------------------------------------------------------------------ */ return [ 'success' => true, 'product_id' => $product_id, 'name' => $product_data['name'], 'type' => $product_data['type'], 'status' => $product_data['status'], 'permalink' => $product_data['permalink'], 'edit_url' => admin_url( "post.php?post={$product_id}&action=edit" ), 'price' => $product_data['price'] ?? $body['regular_price'], 'images' => count( $product_data['images'] ?? [] ), 'variations' => count( $created_variations ), 'sku' => $product_data['sku'] ?? '', ]; } /** * Auto-generate variation combinations from a list of attributes. * * @param array $attributes WooCommerce attribute objects with 'name' and 'options'. * @param string $price Default price to apply to every variation. * @return array Array of variation payloads ready for the REST API. */ function store_mcp_generate_variations( array $attributes, string $price = '' ): array { // Build a [ name => [option, option, …] ] map for attributes flagged for variation. $variation_attrs = []; foreach ( $attributes as $attr ) { if ( ! empty( $attr['variation'] ) && ! empty( $attr['options'] ) ) { $variation_attrs[ $attr['name'] ] = (array) $attr['options']; } } if ( empty( $variation_attrs ) ) { return []; } // Cartesian product of all option arrays. $combos = [ [] ]; foreach ( $variation_attrs as $attr_name => $options ) { $new_combos = []; foreach ( $combos as $combo ) { foreach ( $options as $option ) { $new_combos[] = array_merge( $combo, [ [ 'name' => $attr_name, 'option' => $option ] ] ); } } $combos = $new_combos; } $variations = []; foreach ( $combos as $attrs ) { $variations[] = [ 'regular_price' => $price, 'status' => 'publish', 'attributes' => $attrs, ]; } return $variations; }
Test Mode Purchase Subtotal TotalTotal Due Today