From 6fc1767d311789bff330e8f5aa033ec8ad893548 Mon Sep 17 00:00:00 2001 From: Virgil Date: Mon, 30 Mar 2026 06:14:22 +0000 Subject: [PATCH] fix(api): normalize remaining MCP and rate-limit error envelopes --- .../src/Api/Controllers/McpApiController.php | 33 ++++++++++++------- .../Exceptions/RateLimitExceededException.php | 22 ++++++++----- 2 files changed, 35 insertions(+), 20 deletions(-) diff --git a/src/php/src/Api/Controllers/McpApiController.php b/src/php/src/Api/Controllers/McpApiController.php index 8070188..3e97795 100644 --- a/src/php/src/Api/Controllers/McpApiController.php +++ b/src/php/src/Api/Controllers/McpApiController.php @@ -156,16 +156,18 @@ class McpApiController extends Controller // Sunset versions return 410 Gone $status = ($error['code'] ?? '') === 'TOOL_VERSION_SUNSET' ? 410 : 400; - return response()->json([ - 'success' => false, - 'error' => $error['message'] ?? 'Version error', - 'error_code' => $error['code'] ?? 'VERSION_ERROR', - 'server' => $validated['server'], - 'tool' => $validated['tool'], - 'requested_version' => $validated['version'] ?? null, - 'latest_version' => $error['latest_version'] ?? null, - 'migration_notes' => $error['migration_notes'] ?? null, - ], $status); + return $this->errorResponse( + errorCode: $error['code'] ?? 'VERSION_ERROR', + message: $error['message'] ?? 'Version error', + meta: [ + 'server' => $validated['server'], + 'tool' => $validated['tool'], + 'requested_version' => $validated['version'] ?? null, + 'latest_version' => $error['latest_version'] ?? null, + 'migration_notes' => $error['migration_notes'] ?? null, + ], + status: $status, + ); } /** @var McpToolVersion|null $toolVersion */ @@ -267,7 +269,16 @@ class McpApiController extends Controller // Log full request for debugging/replay $this->logApiRequest($request, $validated, 500, $response, $durationMs, $apiKey, $e->getMessage()); - return response()->json($response, 500); + return $this->errorResponse( + errorCode: 'tool_execution_error', + message: $e->getMessage(), + meta: array_filter([ + 'server' => $validated['server'], + 'tool' => $validated['tool'], + 'version' => $toolVersion?->version ?? ToolVersionService::DEFAULT_VERSION, + ]), + status: 500, + ); } } diff --git a/src/php/src/Api/Exceptions/RateLimitExceededException.php b/src/php/src/Api/Exceptions/RateLimitExceededException.php index 30b3b0e..d96702a 100644 --- a/src/php/src/Api/Exceptions/RateLimitExceededException.php +++ b/src/php/src/Api/Exceptions/RateLimitExceededException.php @@ -5,6 +5,7 @@ declare(strict_types=1); namespace Core\Api\Exceptions; use Core\Api\RateLimit\RateLimitResult; +use Core\Api\Concerns\HasApiResponses; use Illuminate\Http\JsonResponse; use Symfony\Component\HttpKernel\Exception\HttpException; @@ -15,6 +16,8 @@ use Symfony\Component\HttpKernel\Exception\HttpException; */ class RateLimitExceededException extends HttpException { + use HasApiResponses; + public function __construct( protected RateLimitResult $rateLimitResult, string $message = 'Too many requests. Please slow down.', @@ -35,15 +38,16 @@ class RateLimitExceededException extends HttpException */ public function render(): JsonResponse { - return response()->json([ - 'success' => false, - 'error' => 'rate_limit_exceeded', - 'error_code' => 'rate_limit_exceeded', - 'message' => $this->getMessage(), - 'retry_after' => $this->rateLimitResult->retryAfter, - 'limit' => $this->rateLimitResult->limit, - 'resets_at' => $this->rateLimitResult->resetsAt->toIso8601String(), - ], 429, $this->rateLimitResult->headers()); + return $this->errorResponse( + errorCode: 'rate_limit_exceeded', + message: $this->getMessage(), + meta: [ + 'retry_after' => $this->rateLimitResult->retryAfter, + 'limit' => $this->rateLimitResult->limit, + 'resets_at' => $this->rateLimitResult->resetsAt->toIso8601String(), + ], + status: 429, + )->withHeaders($this->rateLimitResult->headers()); } /**