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 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 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',
],
];
}
}