isGranted($role)) { throw new RuntimeException("Permission denied: {$role} required."); } } private function jsonResponse(array $data): CallToolResult { return new CallToolResult( content: [new TextContent(text: json_encode($data, JSON_THROW_ON_ERROR | JSON_UNESCAPED_UNICODE))], ); } private function mcpError(string $category, string $message): never { throw new RuntimeException("{$category}: {$message}"); } /** * @return array{page: int, limit: int, offset: int} */ private function paginationParams(int $page = 1, int $limit = 30): array { $page = max(1, $page); $limit = min(100, max(1, $limit)); $offset = ($page - 1) * $limit; return ['page' => $page, 'limit' => $limit, 'offset' => $offset]; } private function paginatedResponse(array $items, int $total, int $page, int $limit): CallToolResult { return $this->jsonResponse([ 'items' => $items, 'total' => $total, 'page' => $page, 'limit' => $limit, 'pageCount' => (int) ceil($total / max(1, $limit)), ]); } }