PHP code example of wizardingcode / laravel-mcp-server

1. Go to this page and download the library: Download wizardingcode/laravel-mcp-server library. Choose the download type require.

2. Extract the ZIP file and open the index.php.

3. Add this code to the index.php.
    
        
<?php
require_once('vendor/autoload.php');

/* Start to develop here. Best regards https://php-download.com/ */

    

wizardingcode / laravel-mcp-server example snippets


use WizardingCode\MCPServer\Facades\MCP;

// Register a static resource
MCP::registerResource('config', 'config://app', function ($uri, $request) {
    return [
        'contents' => [
            [
                'uri' => $uri,
                'text' => 'Application configuration content here',
            ],
        ],
    ];
}, ['description' => 'Application configuration']);



use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;

return new class extends Migration
{
    public function up(): void
    {
        Schema::create('documents', function (Blueprint $table) {
            $table->id();
            $table->string('category');
            $table->string('slug')->unique();
            $table->string('title');
            $table->text('content');
            $table->timestamps();
            
            $table->index(['category', 'slug']);
        });
    }

    public function down(): void
    {
        Schema::dropIfExists('documents');
    }
};



namespace App\Models;

use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model;

class Document extends Model
{
    use HasFactory;
    
    protected $fillable = ['category', 'slug', 'title', 'content'];
}



namespace App\Services;

use App\Models\Document;
use Illuminate\Support\Collection;

class DocumentationService
{
    public function getDocument(string $category, string $slug): ?Document
    {
        return Document::where('category', $category)
            ->where('slug', $slug)
            ->first();
    }
    
    public function getAllDocuments(): Collection
    {
        return Document::all();
    }
    
    public function searchDocuments(string $query): Collection
    {
        return Document::where('title', 'like', "%{$query}%")
            ->orWhere('content', 'like', "%{$query}%")
            ->get();
    }
}



namespace App\Providers;

use App\Services\DocumentationService;
use Illuminate\Support\ServiceProvider;
use WizardingCode\MCPServer\Facades\MCP;

class MCPServiceProvider extends ServiceProvider
{
    public function boot()
    {
        $this->setupDocumentationResources();
        $this->setupDocumentationTools();
    }
    
    protected function setupDocumentationResources()
    {
        // Register a document resource template
        MCP::registerResourceTemplate(
            'document',
            'docs://{category}/{slug}',
            function ($uri, $variables, $request) {
                $documentationService = app(DocumentationService::class);
                $document = $documentationService->getDocument(
                    $variables['category'],
                    $variables['slug']
                );
                
                if (!$document) {
                    throw new \Exception("Document not found");
                }
                
                return [
                    'contents' => [
                        [
                            'uri' => $uri,
                            'text' => "# {$document->title}\n\n{$document->content}",
                            'mimeType' => 'text/markdown',
                        ],
                    ],
                ];
            },
            ['description' => 'Company documentation'],
            // List callback for all documents
            function ($request) {
                $documentationService = app(DocumentationService::class);
                $documents = $documentationService->getAllDocuments();
                $resources = [];
                
                foreach ($documents as $doc) {
                    $resources[] = [
                        'uri' => "docs://{$doc->category}/{$doc->slug}",
                        'name' => $doc->title,
                    ];
                }
                
                return ['resources' => $resources];
            }
        );
        
        // Register a document index resource
        MCP::registerResource(
            'document-index',
            'docs://index',
            function ($uri, $request) {
                $documentationService = app(DocumentationService::class);
                $documents = $documentationService->getAllDocuments();
                
                $index = "# Company Documentation Index\n\n";
                $currentCategory = '';
                
                foreach ($documents as $doc) {
                    if ($doc->category !== $currentCategory) {
                        $currentCategory = $doc->category;
                        $index .= "\n## {$currentCategory}\n\n";
                    }
                    
                    $index .= "- [{$doc->title}](docs://{$doc->category}/{$doc->slug})\n";
                }
                
                return [
                    'contents' => [
                        [
                            'uri' => $uri,
                            'text' => $index,
                            'mimeType' => 'text/markdown',
                        ],
                    ],
                ];
            },
            ['description' => 'Documentation index']
        );
    }
    
    protected function setupDocumentationTools()
    {
        // Register a document search tool
        MCP::registerTool(
            'search-docs',
            function ($arguments, $request) {
                $query = $arguments['query'] ?? '';
                
                if (empty($query)) {
                    return [
                        'content' => [
                            [
                                'type' => 'text',
                                'text' => 'Search query cannot be empty',
                            ],
                        ],
                        'isError' => true,
                    ];
                }
                
                $documentationService = app(DocumentationService::class);
                $results = $documentationService->searchDocuments($query);
                
                if ($results->isEmpty()) {
                    return [
                        'content' => [
                            [
                                'type' => 'text',
                                'text' => "No documents found matching '{$query}'",
                            ],
                        ],
                    ];
                }
                
                $response = "## Search Results for '{$query}'\n\n";
                
                foreach ($results as $doc) {
                    $response .= "- [{$doc->title}](docs://{$doc->category}/{$doc->slug})\n";
                }
                
                return [
                    'content' => [
                        [
                            'type' => 'text',
                            'text' => $response,
                        ],
                    ],
                ];
            },
            [
                'type' => 'object',
                'properties' => [
                    'query' => ['type' => 'string'],
                ],
                '

App\Providers\MCPServiceProvider::class,



namespace Database\Seeders;

use App\Models\Document;
use Illuminate\Database\Seeder;

class DocumentSeeder extends Seeder
{
    public function run(): void
    {
        $documents = [
            [
                'category' => 'hr',
                'slug' => 'employee-handbook',
                'title' => 'Employee Handbook',
                'content' => "## Welcome to Our Company\n\nThis handbook contains all the policies and procedures for employees. Please read it carefully.\n\n## Work Hours\n\nStandard work hours are 9 AM to 5 PM, Monday through Friday.\n\n## Benefits\n\nWe offer comprehensive health insurance, 401(k) with matching, and unlimited PTO.",
            ],
            [
                'category' => 'hr',
                'slug' => 'code-of-conduct',
                'title' => 'Code of Conduct',
                'content' => "## Professional Behavior\n\nAll employees are expected to conduct themselves professionally at all times.\n\n## Inclusivity\n\nWe are committed to fostering an inclusive environment for all employees.",
            ],
            [
                'category' => 'engineering',
                'slug' => 'coding-standards',
                'title' => 'Coding Standards',
                'content' => "## General Guidelines\n\n- Use consistent indentation (4 spaces)\n- Write meaningful comments\n- Follow naming conventions\n\n## Code Reviews\n\nAll code must be reviewed by at least one other developer before being merged.",
            ],
            [
                'category' => 'engineering',
                'slug' => 'deployment-process',
                'title' => 'Deployment Process',
                'content' => "## Staging Environment\n\nAll changes must be deployed to staging first.\n\n## Production Deployment\n\nProduction deployments occur every Wednesday at 2 PM.\n\n## Rollback Procedure\n\nIn case of issues, use the rollback script in the deployment repository.",
            ],
        ];
        
        foreach ($documents as $document) {
            Document::create($document);
        }
    }
}



use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;

return new class extends Migration
{
    public function up(): void
    {
        Schema::create('customers', function (Blueprint $table) {
            $table->id();
            $table->string('name');
            $table->string('email')->unique();
            $table->string('phone')->nullable();
            $table->string('address')->nullable();
            $table->timestamps();
        });
    }

    public function down(): void
    {
        Schema::dropIfExists('customers');
    }
};



use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;

return new class extends Migration
{
    public function up(): void
    {
        Schema::create('products', function (Blueprint $table) {
            $table->id();
            $table->string('name');
            $table->text('description');
            $table->decimal('price', 10, 2);
            $table->integer('stock')->default(0);
            $table->timestamps();
        });
    }

    public function down(): void
    {
        Schema::dropIfExists('products');
    }
};



use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;

return new class extends Migration
{
    public function up(): void
    {
        Schema::create('orders', function (Blueprint $table) {
            $table->id();
            $table->foreignId('customer_id')->constrained();
            $table->string('status')->default('pending');
            $table->decimal('total', 10, 2);
            $table->timestamp('shipped_at')->nullable();
            $table->timestamp('delivered_at')->nullable();
            $table->timestamps();
        });
    }

    public function down(): void
    {
        Schema::dropIfExists('orders');
    }
};



use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;

return new class extends Migration
{
    public function up(): void
    {
        Schema::create('order_items', function (Blueprint $table) {
            $table->id();
            $table->foreignId('order_id')->constrained()->onDelete('cascade');
            $table->foreignId('product_id')->constrained();
            $table->integer('quantity');
            $table->decimal('price', 10, 2);
            $table->timestamps();
        });
    }

    public function down(): void
    {
        Schema::dropIfExists('order_items');
    }
};



namespace App\Models;

use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\Relations\HasMany;

class Customer extends Model
{
    use HasFactory;
    
    protected $fillable = ['name', 'email', 'phone', 'address'];
    
    public function orders(): HasMany
    {
        return $this->hasMany(Order::class);
    }
}



namespace App\Models;

use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\Relations\HasMany;

class Product extends Model
{
    use HasFactory;
    
    protected $fillable = ['name', 'description', 'price', 'stock'];
    
    public function orderItems(): HasMany
    {
        return $this->hasMany(OrderItem::class);
    }
}



namespace App\Models;

use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\Relations\BelongsTo;
use Illuminate\Database\Eloquent\Relations\HasMany;

class Order extends Model
{
    use HasFactory;
    
    protected $fillable = ['customer_id', 'status', 'total', 'shipped_at', 'delivered_at'];
    
    protected $casts = [
        'shipped_at' => 'datetime',
        'delivered_at' => 'datetime',
    ];
    
    public function customer(): BelongsTo
    {
        return $this->belongsTo(Customer::class);
    }
    
    public function items(): HasMany
    {
        return $this->hasMany(OrderItem::class);
    }
}



namespace App\Models;

use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\Relations\BelongsTo;

class OrderItem extends Model
{
    use HasFactory;
    
    protected $fillable = ['order_id', 'product_id', 'quantity', 'price'];
    
    public function order(): BelongsTo
    {
        return $this->belongsTo(Order::class);
    }
    
    public function product(): BelongsTo
    {
        return $this->belongsTo(Product::class);
    }
}



namespace Database\Seeders;

use App\Models\Customer;
use App\Models\Order;
use App\Models\OrderItem;
use App\Models\Product;
use Illuminate\Database\Seeder;

class EcommerceSeeder extends Seeder
{
    public function run(): void
    {
        // Create customers
        $customers = [
            [
                'name' => 'John Doe',
                'email' => '[email protected]',
                'phone' => '+12025550177',
                'address' => '123 Main St, New York, NY',
            ],
            [
                'name' => 'Jane Smith',
                'email' => '[email protected]',
                'phone' => '+12025550184',
                'address' => '456 Oak Ave, Los Angeles, CA',
            ],
        ];
        
        foreach ($customers as $customerData) {
            Customer::create($customerData);
        }
        
        // Create products
        $products = [
            [
                'name' => 'Smartphone X',
                'description' => 'Latest smartphone with advanced features',
                'price' => 799.99,
                'stock' => 50,
            ],
            [
                'name' => 'Wireless Headphones',
                'description' => 'Noise-cancelling wireless headphones',
                'price' => 149.99,
                'stock' => 100,
            ],
            [
                'name' => 'Laptop Pro',
                'description' => 'Professional-grade laptop with 16GB RAM',
                'price' => 1299.99,
                'stock' => 25,
            ],
            [
                'name' => 'Smart Watch',
                'description' => 'Fitness tracking and notifications',
                'price' => 199.99,
                'stock' => 75,
            ],
        ];
        
        foreach ($products as $productData) {
            Product::create($productData);
        }
        
        // Create orders
        $orders = [
            [
                'customer_id' => 1,
                'status' => 'shipped',
                'total' => 949.98,
                'shipped_at' => now()->subDays(2),
                'items' => [
                    ['product_id' => 1, 'quantity' => 1, 'price' => 799.99],
                    ['product_id' => 2, 'quantity' => 1, 'price' => 149.99],
                ],
            ],
            [
                'customer_id' => 2,
                'status' => 'pending',
                'total' => 1299.99,
                'items' => [
                    ['product_id' => 3, 'quantity' => 1, 'price' => 1299.99],
                ],
            ],
            [
                'customer_id' => 1,
                'status' => 'delivered',
                'total' => 199.99,
                'shipped_at' => now()->subDays(5),
                'delivered_at' => now()->subDays(3),
                'items' => [
                    ['product_id' => 4, 'quantity' => 1, 'price' => 199.99],
                ],
            ],
        ];
        
        foreach ($orders as $orderData) {
            $items = $orderData['items'];
            unset($orderData['items']);
            
            $order = Order::create($orderData);
            
            foreach ($items as $itemData) {
                $itemData['order_id'] = $order->id;
                OrderItem::create($itemData);
            }
        }
    }
}



namespace App\Services;

use Illuminate\Support\Facades\Http;
use Illuminate\Support\Facades\Log;

class WhatsAppService
{
    protected string $apiUrl;
    protected string $apiToken;
    
    public function __construct()
    {
        $this->apiUrl = config('services.whatsapp.api_url');
        $this->apiToken = config('services.whatsapp.api_token');
    }
    
    public function sendMessage(string $recipient, string $message): bool
    {
        try {
            $response = Http::withToken($this->apiToken)
                ->post($this->apiUrl . '/messages', [
                    'messaging_product' => 'whatsapp',
                    'to' => $recipient,
                    'type' => 'text',
                    'text' => [
                        'body' => $message
                    ],
                ]);
            
            if (!$response->successful()) {
                Log::error('WhatsApp API error', [
                    'response' => $response->body(),
                    'recipient' => $recipient,
                ]);
                return false;
            }
            
            return true;
        } catch (\Exception $e) {
            Log::error('WhatsApp service error', [
                'exception' => $e->getMessage(),
                'recipient' => $recipient,
            ]);
            return false;
        }
    }
}

'whatsapp' => [
    'api_url' => env('WHATSAPP_API_URL', 'https://graph.facebook.com/v18.0/your-phone-number-id'),
    'api_token' => env('WHATSAPP_API_TOKEN'),
],



namespace App\Providers;

use App\Models\Customer;
use App\Models\Order;
use App\Models\Product;
use App\Services\WhatsAppService;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\ServiceProvider;
use WizardingCode\MCPServer\Facades\MCP;

class EcommerceMCPServiceProvider extends ServiceProvider
{
    public function boot()
    {
        // Register database schema resource
        MCP::registerResource(
            'db-schema',
            'db://schema',
            function ($uri, $request) {
                $tables = DB::select("
                    SELECT 
                        table_name, 
                        column_name, 
                        data_type 
                    FROM 
                        information_schema.columns 
                    WHERE 
                        table_schema = 'public'
                        AND table_name IN ('customers', 'products', 'orders', 'order_items')
                    ORDER BY 
                        table_name, 
                        ordinal_position
                ");
                
                $schema = "# E-commerce Database Schema\n\n";
                $currentTable = '';
                
                foreach ($tables as $column) {
                    if ($column->table_name !== $currentTable) {
                        $currentTable = $column->table_name;
                        $schema .= "\n## Table: {$currentTable}\n\n";
                        $schema .= "| Column | Type |\n";
                        $schema .= "|--------|------|\n";
                    }
                    
                    $schema .= "| {$column->column_name} | {$column->data_type} |\n";
                }
                
                return [
                    'contents' => [
                        [
                            'uri' => $uri,
                            'text' => $schema,
                            'mimeType' => 'text/markdown',
                        ],
                    ],
                ];
            },
            ['description' => 'E-commerce database schema']
        );
        
        // Register orders resource
        MCP::registerResource(
            'orders',
            'ecommerce://orders',
            function ($uri, $request) {
                $orders = Order::with(['customer', 'items.product'])->get();
                
                $orderList = "# All Orders\n\n";
                $orderList .= "| Order ID | Customer | Status | Total | Date |\n";
                $orderList .= "|----------|----------|--------|-------|------|\n";
                
                foreach ($orders as $order) {
                    $orderList .= "| #{$order->id} | {$order->customer->name} | {$order->status} | \${$order->total} | {$order->created_at->format('Y-m-d')} |\n";
                }
                
                return [
                    'contents' => [
                        [
                            'uri' => $uri,
                            'text' => $orderList,
                            'mimeType' => 'text/markdown',
                        ],
                    ],
                ];
            },
            ['description' => 'All orders']
        );
        
        // Register order details resource template
        MCP::registerResourceTemplate(
            'order-detail',
            'ecommerce://orders/{id}',
            function ($uri, $variables, $request) {
                $orderId = $variables['id'];
                $order = Order::with(['customer', 'items.product'])->find($orderId);
                
                if (!$order) {
                    throw new \Exception("Order #{$orderId} not found");
                }
                
                $orderDetail = "# Order #{$order->id}\n\n";
                $orderDetail .= "**Customer**: {$order->customer->name}\n";
                $orderDetail .= "**Email**: {$order->customer->email}\n";
                $orderDetail .= "**Phone**: {$order->customer->phone}\n";
                $orderDetail .= "**Status**: {$order->status}\n";
                $orderDetail .= "**Total**: \${$order->total}\n";
                $orderDetail .= "**Date**: {$order->created_at->format('Y-m-d')}\n\n";
                
                if ($order->shipped_at) {
                    $orderDetail .= "**Shipped**: {$order->shipped_at->format('Y-m-d')}\n";
                }
                
                if ($order->delivered_at) {
                    $orderDetail .= "**Delivered**: {$order->delivered_at->format('Y-m-d')}\n";
                }
                
                $orderDetail .= "\n## Items\n\n";
                $orderDetail .= "| Product | Quantity | Price | Subtotal |\n";
                $orderDetail .= "|---------|----------|-------|----------|\n";
                
                foreach ($order->items as $item) {
                    $subtotal = $item->quantity * $item->price;
                    $orderDetail .= "| {$item->product->name} | {$item->quantity} | \${$item->price} | \${$subtotal} |\n";
                }
                
                return [
                    'contents' => [
                        [
                            'uri' => $uri,
                            'text' => $orderDetail,
                            'mimeType' => 'text/markdown',
                        ],
                    ],
                ];
            },
            ['description' => 'Order details'],
            // List callback
            function ($request) {
                $orders = Order::all();
                $resources = [];
                
                foreach ($orders as $order) {
                    $resources[] = [
                        'uri' => "ecommerce://orders/{$order->id}",
                        'name' => "Order #{$order->id}",
                    ];
                }
                
                return ['resources' => $resources];
            }
        );
        
        // Register query tool
        MCP::registerTool(
            'query-orders',
            function ($arguments, $request) {
                $status = $arguments['status'] ?? null;
                $customer = $arguments['customer'] ?? null;
                
                $query = Order::with(['customer', 'items.product']);
                
                if ($status) {
                    $query->where('status', $status);
                }
                
                if ($customer) {
                    $query->whereHas('customer', function ($q) use ($customer) {
                        $q->where('name', 'like', "%{$customer}%")
                          ->orWhere('email', 'like', "%{$customer}%");
                    });
                }
                
                $orders = $query->get();
                
                if ($orders->isEmpty()) {
                    return [
                        'content' => [
                            [
                                'type' => 'text',
                                'text' => 'No orders found matching your criteria.',
                            ],
                        ],
                    ];
                }
                
                $result = "# Order Search Results\n\n";
                $result .= "| Order ID | Customer | Status | Total | Date |\n";
                $result .= "|----------|----------|--------|-------|------|\n";
                
                foreach ($orders as $order) {
                    $result .= "| #{$order->id} | {$order->customer->name} | {$order->status} | \${$order->total} | {$order->created_at->format('Y-m-d')} |\n";
                }
                
                return [
                    'content' => [
                        [
                            'type' => 'text',
                            'text' => $result,
                        ],
                    ],
                ];
            },
            [
                'type' => 'object',
                'properties' => [
                    'status' => ['type' => 'string'],
                    'customer' => ['type' => 'string'],
                ],
            ],
            'Search for orders by status or customer'
        );
        
        // Register update order status tool
        MCP::registerTool(
            'update-order-status',
            function ($arguments, $request) {
                $orderId = $arguments['order_id'] ?? null;
                $newStatus = $arguments['status'] ?? null;
                
                if (!$orderId || !$newStatus) {
                    return [
                        'content' => [
                            [
                                'type' => 'text',
                                'text' => 'Order ID and new status are 

App\Providers\EcommerceMCPServiceProvider::class,



namespace App\Services;

use Illuminate\Support\Collection;
use League\Csv\Reader;
use League\Csv\Writer;

class SalesDataService
{
    protected string $dataPath;
    
    public function __construct()
    {
        $this->dataPath = storage_path('app/data');
        
        if (!file_exists($this->dataPath)) {
            mkdir($this->dataPath, 0755, true);
        }
        
        $this->ensureSalesDataExists();
    }
    
    public function getSalesData(): Collection
    {
        $csv = Reader::createFromPath($this->dataPath . '/sales_data.csv', 'r');
        $csv->setHeaderOffset(0);
        
        $records = collect($csv->getRecords());
        
        // Convert string values to appropriate types
        return $records->map(function ($record) {
            return [
                'date' => $record['date'],
                'product' => $record['product'],
                'region' => $record['region'],
                'sales' => (float) $record['sales'],
                'units' => (int) $record['units'],
            ];
        });
    }
    
    public function getSalesByRegion(): array
    {
        $salesData = $this->getSalesData();
        
        $regions = $salesData->groupBy('region')
            ->map(function ($items, $region) {
                return [
                    'region' => $region,
                    'total_sales' => $items->sum('sales'),
                    'total_units' => $items->sum('units'),
                ];
            })
            ->values()
            ->all();
            
        return $regions;
    }
    
    public function getSalesByProduct(): array
    {
        $salesData = $this->getSalesData();
        
        $products = $salesData->groupBy('product')
            ->map(function ($items, $product) {
                return [
                    'product' => $product,
                    'total_sales' => $items->sum('sales'),
                    'total_units' => $items->sum('units'),
                ];
            })
            ->values()
            ->all();
            
        return $products;
    }
    
    public function getSalesByDate(string $startDate = null, string $endDate = null): array
    {
        $salesData = $this->getSalesData();
        
        if ($startDate) {
            $salesData = $salesData->filter(function ($item) use ($startDate) {
                return $item['date'] >= $startDate;
            });
        }
        
        if ($endDate) {
            $salesData = $salesData->filter(function ($item) use ($endDate) {
                return $item['date'] <= $endDate;
            });
        }
        
        return [
            'total_sales' => $salesData->sum('sales'),
            'total_units' => $salesData->sum('units'),
            'average_daily_sales' => $salesData->groupBy('date')->count() > 0 
                ? $salesData->sum('sales') / $salesData->groupBy('date')->count() 
                : 0,
        ];
    }
    
    protected function ensureSalesDataExists(): void
    {
        $filePath = $this->dataPath . '/sales_data.csv';
        
        if (file_exists($filePath)) {
            return;
        }
        
        // Create sample sales data
        $sampleData = [
            ['date', 'product', 'region', 'sales', 'units'],
            ['2023-01-01', 'Product A', 'North', '5000', '100'],
            ['2023-01-01', 'Product B', 'North', '3000', '50'],
            ['2023-01-01', 'Product A', 'South', '4500', '90'],
            ['2023-01-02', 'Product B', 'South', '3500', '60'],
            ['2023-01-02', 'Product C', 'East', '2000', '40'],
            ['2023-01-03', 'Product A', 'West', '6000', '120'],
            ['2023-01-03', 'Product C', 'North', '2500', '50'],
            ['2023-01-04', 'Product B', 'East', '3200', '55'],
            ['2023-01-04', 'Product A', 'South', '4800', '95'],
            ['2023-01-05', 'Product C', 'West', '2200', '45'],
            ['2023-01-05', 'Product B', 'North', '3100', '52'],
            ['2023-01-06', 'Product A', 'East', '5500', '110'],
            ['2023-01-06', 'Product C', 'South', '2300', '46'],
            ['2023-01-07', 'Product B', 'West', '3400', '58'],
            ['2023-01-07', 'Product A', 'North', '5200', '105'],
        ];
        
        $csv = Writer::createFromPath($filePath, 'w+');
        $csv->insertAll($sampleData);
    }
}



namespace App\Services;

use Illuminate\Support\Facades\Http;
use Illuminate\Support\Facades\Log;

class N8NService
{
    protected string $webhookBaseUrl;
    
    public function __construct()
    {
        $this->webhookBaseUrl = config('services.n8n.webhook_base_url');
    }
    
    public function executeWorkflow(string $workflowId, array $data = []): array
    {
        $url = $this->webhookBaseUrl . '/' . $workflowId;
        
        try {
            $response = Http::post($url, $data);
            
            if ($response->failed()) {
                Log::error('N8N workflow execution failed', [
                    'workflow' => $workflowId,
                    'status' => $response->status(),
                    'body' => $response->body(),
                ]);
                
                throw new \Exception('Workflow execution failed: ' . $response->body());
            }
            
            return $response->json() ?: ['success' => true];
        } catch (\Exception $e) {
            Log::error('N8N service error', [
                'workflow' => $workflowId,
                'exception' => $e->getMessage(),
            ]);
            
            throw $e;
        }
    }
    
    public function getAvailableWorkflows(): array
    {
        // In a real implementation, you would fetch this from n8n's API
        // Here we're using mock data
        return [
            [
                'id' => 'generate-sales-report',
                'name' => 'Generate Sales Report',
                'description' => 'Creates a PDF sales report and emails it to specified recipients',
            ],
            [
                'id' => 'export-to-sheets',
                'name' => 'Export to Google Sheets',
                'description' => 'Exports data to a Google Sheets document',
            ],
            [
                'id' => 'update-dashboard',
                'name' => 'Update BI Dashboard',
                'description' => 'Refreshes the Power BI dashboard with latest data',
            ],
            [
                'id' => 'alert-sales-threshold',
                'name' => 'Sales Threshold Alert',
                'description' => 'Sends alerts when sales fall below or exceed thresholds',
            ],
        ];
    }
}

'n8n' => [
    'webhook_base_url' => env('N8N_WEBHOOK_BASE_URL', 'https://n8n.yourcompany.com/webhook'),
],



namespace App\Providers;

use App\Services\N8NService;
use App\Services\SalesDataService;
use Illuminate\Support\ServiceProvider;
use WizardingCode\MCPServer\Facades\MCP;

class BIMCPServiceProvider extends ServiceProvider
{
    public function boot()
    {
        $this->setupSalesDataResources();
        $this->setupN8NTools();
    }
    
    protected function setupSalesDataResources()
    {
        // Sales overview resource
        MCP::registerResource(
            'sales-overview',
            'bi://sales/overview',
            function ($uri, $request) {
                $salesDataService = app(SalesDataService::class);
                $salesByRegion = $salesDataService->getSalesByRegion();
                $salesByProduct = $salesDataService->getSalesByProduct();
                $salesOverall = $salesDataService->getSalesByDate();
                
                $overview = "# Sales Data Overview\n\n";
                $overview .= "## Overall Metrics\n\n";
                $overview .= "- **Total Sales**: \${$salesOverall['total_sales']}\n";
                $overview .= "- **Total Units**: {$salesOverall['total_units']}\n";
                $overview .= "- **Average Daily Sales**: \${$salesOverall['average_daily_sales']}\n\n";
                
                $overview .= "## Sales by Region\n\n";
                $overview .= "| Region | Total Sales | Total Units |\n";
                $overview .= "|--------|-------------|-------------|\n";
                
                foreach ($salesByRegion as $region) {
                    $overview .= "| {$region['region']} | \${$region['total_sales']} | {$region['total_units']} |\n";
                }
                
                $overview .= "\n## Sales by Product\n\n";
                $overview .= "| Product | Total Sales | Total Units |\n";
                $overview .= "|---------|-------------|-------------|\n";
                
                foreach ($salesByProduct as $product) {
                    $overview .= "| {$product['product']} | \${$product['total_sales']} | {$product['total_units']} |\n";
                }
                
                return [
                    'contents' => [
                        [
                            'uri' => $uri,
                            'text' => $overview,
                            'mimeType' => 'text/markdown',
                        ],
                    ],
                ];
            },
            ['description' => 'Sales data overview']
        );
        
        // Sales data by region resource template
        MCP::registerResourceTemplate(
            'sales-by-region',
            'bi://sales/regions/{region}',
            function ($uri, $variables, $request) {
                $region = $variables['region'];
                $salesDataService = app(SalesDataService::class);
                $allSalesData = $salesDataService->getSalesData();
                
                $regionSales = $allSalesData->filter(function ($item) use ($region) {
                    return strtolower($item['region']) === strtolower($region);
                });
                
                if ($regionSales->isEmpty()) {
                    throw new \Exception("No sales data found for region: {$region}");
                }
                
                $totalSales = $regionSales->sum('sales');
                $totalUnits = $regionSales->sum('units');
                
                $salesByProduct = $regionSales->groupBy('product')
                    ->map(function ($items, $product) {
                        return [
                            'product' => $product,
                            'total_sales' => $items->sum('sales'),
                            'total_units' => $items->sum('units'),
                        ];
                    })
                    ->values()
                    ->all();
                
                $salesByDate = $regionSales->groupBy('date')
                    ->map(function ($items, $date) {
                        return [
                            'date' => $date,
                            'total_sales' => $items->sum('sales'),
                            'total_units' => $items->sum('units'),
                        ];
                    })
                    ->values()
                    ->all();
                
                $report = "# Sales Report for {$region} Region\n\n";
                $report .= "## Summary\n\n";
                $report .= "- **Total Sales**: \${$totalSales}\n";
                $report .= "- **Total Units**: {$totalUnits}\n\n";
                
                $report .= "## Sales by Product\n\n";
                $report .= "| Product | Total Sales | Total Units |\n";
                $report .= "|---------|-------------|-------------|\n";
                
                foreach ($salesByProduct as $product) {
                    $report .= "| {$product['product']} | \${$product['total_sales']} | {$product['total_units']} |\n";
                }
                
                $report .= "\n## Daily Sales\n\n";
                $report .= "| Date | Total Sales | Total Units |\n";
                $report .= "|------|-------------|-------------|\n";
                
                foreach ($salesByDate as $day) {
                    $report .= "| {$day['date']} | \${$day['total_sales']} | {$day['total_units']} |\n";
                }
                
                return [
                    'contents' => [
                        [
                            'uri' => $uri,
                            'text' => $report,
                            'mimeType' => 'text/markdown',
                        ],
                    ],
                ];
            },
            ['description' => 'Sales data by region'],
            // List callback
            function ($request) {
                $salesDataService = app(SalesDataService::class);
                $regions = collect($salesDataService->getSalesByRegion());
                
                return [
                    'resources' => $regions->map(function ($region) {
                        return [
                            'uri' => "bi://sales/regions/{$region['region']}",
                            'name' => "{$region['region']} Region Sales",
                        ];
                    })->all(),
                ];
            }
        );
        
        // Sales data CSV resource
        MCP::registerResource(
            'sales-data-csv',
            'bi://sales/data.csv',
            function ($uri, $request) {
                $salesDataService = app(SalesDataService::class);
                $salesData = $salesDataService->getSalesData();
                
                $csvContent = "date,product,region,sales,units\n";
                
                foreach ($salesData as $row) {
                    $csvContent .= "{$row['date']},{$row['product']},{$row['region']},{$row['sales']},{$row['units']}\n";
                }
                
                return [
                    'contents' => [
                        [
                            'uri' => $uri,
                            'text' => $csvContent,
                            'mimeType' => 'text/csv',
                        ],
                    ],
                ];
            },
            ['description' => 'Raw sales data in CSV format']
        );
    }
    
    protected function setupN8NTools()
    {
        // List workflows tool
        MCP::registerTool(
            'list-workflows',
            function ($arguments, $request) {
                $n8nService = app(N8NService::class);
                $workflows = $n8nService->getAvailableWorkflows();
                
                $response = "# Available n8n Workflows\n\n";
                
                foreach ($workflows as $workflow) {
                    $response .= "## {$workflow['name']}\n\n";
                    $response .= "**ID**: `{$workflow['id']}`\n\n";
                    $response .= "**Description**: {$workflow['description']}\n\n";
                    $response .= "---\n\n";
                }
                
                return [
                    'content' => [
                        [
                            'type' => 'text',
                            'text' => $response,
                        ],
                    ],
                ];
            },
            [],
            'List all available n8n workflows'
        );
        
        // Execute workflow tool
        MCP::registerTool(
            'execute-workflow',
            function ($arguments, $request) {
                $workflowId = $arguments['workflow_id'] ?? null;
                $params = $arguments['params'] ?? [];
                
                if (!$workflowId) {
                    return [
                        'content' => [
                            [
                                'type' => 'text',
                                'text' => 'Workflow ID is 

App\Providers\BIMCPServiceProvider::class,
bash
php artisan vendor:publish --tag=mcp-config
bash
php artisan vendor:publish --tag=mcp-config
bash
php artisan migrate
bash
php artisan make:model Document
bash
php artisan make:seeder DocumentSeeder
bash
php artisan db:seed --class=DocumentSeeder
bash
php artisan serve
bash
php artisan migrate
bash
php artisan make:model Customer
php artisan make:model Product
php artisan make:model Order
php artisan make:model OrderItem
bash
php artisan make:seeder EcommerceSeeder
bash
php artisan db:seed --class=EcommerceSeeder
bash
php artisan serve
bash
php artisan serve