forWorkspace($workspaceId) ->active() ->forEvent($eventType) ->get(); if ($endpoints->isEmpty()) { return; } $payload = [ 'event' => $eventType, 'timestamp' => now()->toIso8601String(), 'data' => [ 'server_id' => $serverId, 'tool_name' => $toolName, 'arguments' => $arguments, 'success' => $success, 'duration_ms' => $durationMs, 'error' => $errorMessage, ], ]; foreach ($endpoints as $endpoint) { $this->deliverWebhook($endpoint, $payload); } } /** * Deliver a webhook to an endpoint. */ protected function deliverWebhook(WebhookEndpoint $endpoint, array $payload): void { $payloadJson = json_encode($payload); $signature = $endpoint->generateSignature($payloadJson); $startTime = microtime(true); try { $response = Http::timeout(10) ->withHeaders([ 'Content-Type' => 'application/json', 'X-Webhook-Signature' => $signature, 'X-Webhook-Event' => $payload['event'], 'X-Webhook-Timestamp' => $payload['timestamp'], ]) ->withBody($payloadJson, 'application/json') ->post($endpoint->url); $durationMs = (int) ((microtime(true) - $startTime) * 1000); // Record delivery WebhookDelivery::create([ 'webhook_endpoint_id' => $endpoint->id, 'event_id' => 'evt_'.uniqid(), 'event_type' => $payload['event'], 'payload' => $payload, 'response_code' => $response->status(), 'response_body' => substr($response->body(), 0, 1000), 'status' => $response->successful() ? 'success' : 'failed', 'attempt' => 1, 'delivered_at' => $response->successful() ? now() : null, ]); if ($response->successful()) { $endpoint->recordSuccess(); } else { $endpoint->recordFailure(); Log::warning('MCP Webhook delivery failed', [ 'endpoint_id' => $endpoint->id, 'url' => $endpoint->url, 'status' => $response->status(), ]); } } catch (\Throwable $e) { $durationMs = (int) ((microtime(true) - $startTime) * 1000); WebhookDelivery::create([ 'webhook_endpoint_id' => $endpoint->id, 'event_id' => 'evt_'.uniqid(), 'event_type' => $payload['event'], 'payload' => $payload, 'response_code' => 0, 'response_body' => $e->getMessage(), 'status' => 'failed', 'attempt' => 1, ]); $endpoint->recordFailure(); Log::error('MCP Webhook delivery error', [ 'endpoint_id' => $endpoint->id, 'url' => $endpoint->url, 'error' => $e->getMessage(), ]); } } }