0.167.1
Fixed
- 500 на
GET /api/v1/mcp-serversв PostgreSQL-деплое. На проде (chat.a2v.space, PostgreSQL) эндпоинт возвращал{"error":"failed to list mcp servers"}с duration ~2 мс; страница MCP-серверов в WebUI была полностью недоступна. Аналогично падалGET /api/v1/mcp-servers/{id}(GetMCPServer).
Корневая причина: константа pgMCPCols (internal/store/postgres.go) содержала COALESCE(last_connected_at,'') для колонки типа TIMESTAMPTZ (добавлена миграцией 103_mcp_health, тег v0.162.0). PostgreSQL не может привести литерал '' к timestamp — SELECT падал мгновенно: ОШИБКА: неверный синтаксис для типа timestamp with time zone: "". Воспроизведено напрямую тем же запросом, что выполняет ListMCPServers. В SQLite та же конструкция работала (динамическая типизация), поэтому баг проявлялся только в PG-деплое.
Фикс: COALESCE(last_connected_at,'') → COALESCE(last_connected_at::text,'') по конвенции проекта (так же уже обрабатываются started_at/finished_at в этом же файле). Исправляет ListMCPServers и GetMCPServer (оба используют pgMCPCols). SQLite не затронут.
Логирование ошибок (internal/server/handler/mcp.go). Вторичная проблема инцидента: MCPHandler.List (и др. MCP-методы) возвращали 500, не логируя реальную ошибку Store — клиенту уходил только generic-текст, что сделало диагностику невозможной без SSH-доступа к БД. Добавлен slog.Error с реальной ошибкой во всех MCP-методах, возвращающих 500 без лога (~23 места: List, Get, Create, Update, Delete, Import, Export, ExportOne, OAuth-методы, credentials, grants). Заодно убраны утечки err.Error() в HTTP-ответах (Create, OAuthAuthorize client_credentials/start-flow) — теперь ошибки логируются серверно, а клиенту возвращается санитизированное сообщение. Ключи лога унифицированы под "err" (вместо смешанного "error"/"err").
Тест: TestPgMCPCols_NullableTimestamptzHasTextCast (internal/store/mcp_pg_test.go) — регэксп-проверка, что nullable TIMESTAMPTZ-колонки в pgMCPCols имеют ::text перед COALESCE (регрессионная защита; проверена на откаты фикса — падает корректно).