1. Навіщо взагалі потрібен ще один шар?
Майже всі починають однаково: є один MCP‑сервер, він описує кілька інструментів, ChatGPT звертається до нього напряму через HTTPS — і, здається, усе працює. Умовна архітектура виглядає так:
ChatGPT → ваш MCP‑сервер → база / зовнішні API
На етапі навчального проєкту це справді нормальний варіант. Але щойно застосунок починає обростати функціональністю, а команда розробки — зростати, проблеми проявляються дуже швидко.
По‑перше, MCP‑сервер перетворюється на «God‑об’єкт». У ньому одночасно «живуть» і інструменти добору подарунків, і checkout, і аналітика, і ще щось із серії «а давайте сюди ж додамо звітність». Різні частини коду мають різні SLA та різні вимоги до безпеки, але все це склеєно в один процес.
По‑друге, ChatGPT та інші клієнти змушені знати топологію ваших сервісів. Якщо за пів року у вас з’явиться ще один MCP‑сервер для commerce, вам доведеться перепід’єднувати клієнтів, змінювати конфігурації й описи. Замість «однієї точки входу» виходить зоопарк URL‑адрес.
По‑третє, стає незрозуміло, де реалізовувати спільні для всіх сервісів речі: автентифікацію, логування, метрики, лімітування запитів (rate limiting), перевірку токенів, локалізацію та маршрутизацію за регіонами. Якщо розкидати це по всіх MCP‑/Agent‑сервісах, ви отримаєте багато дублювання й різну поведінку в різних сервісах.
Щоб розірвати цю зв’язаність і водночас приховати внутрішню складність від ChatGPT, у гру вступає MCP Gateway — мережевий шлюз і єдина точка входу для всього MCP‑трафіку.
2. Що таке MCP Gateway у контексті ChatGPT App
Формально MCP Gateway — це проксі‑шар і єдина точка входу між MCP‑клієнтами (ChatGPT, MCP Jam, ваші внутрішні інструменти) та набором ваших бекенд‑сервісів. Зазвичай це REST/HTTP API, мікросервіси, сервіси Agents, commerce‑бекенд тощо.
Gateway сам реалізує MCP‑протокол назовні (для ChatGPT він виглядає як один MCP‑сервер), а всередині просто звертається до звичайних REST‑ендпойнтів через HTTP/gRPC.
На запит tools/list gateway не проксіює виклик далі, а повертає власний список інструментів: він або жорстко описаний у коді, або збирається з конфігурації. Кожен інструмент прив’язаний до конкретного REST‑ендпойнта й схеми даних. На запит tools/call gateway бере ім’я інструмента, знаходить відповідний REST‑маршрут і викликає його через fetch/HTTP‑клієнт.
Схематично це можна уявити так:
flowchart LR
ChatGPT["ChatGPT / модель"] --> |MCP JSON-RPC| Gateway["MCP Gateway<br/>(єдиний MCP‑сервер)"]
Gateway --> GiftAPI["Gift REST API<br/>/ мікросервіс подарунків"]
Gateway --> CommerceAPI["Commerce REST API<br/>/ ACP / платежі"]
Gateway --> AnalyticsAPI["Analytics Service<br/>/ події та метрики"]
Для ChatGPT це один сервер: один URL, один набір інструментів, один потік подій. Для вас це гнучка точка маршрутизації трафіку до різних «холодних» і «гарячих» сервісів.
3. MCP Gateway в архітектурі GiftGenius
Щоб менше говорити абстрактно й показати gateway «у живій системі», продовжимо наш приклад GiftGenius — застосунку, який добирає подарунки й уміє оформляти замовлення через ACP/Instant Checkout.
У простій версії в нас був один MCP‑сервер, який умів і suggest_gifts, і checkout_start. Тепер, коли застосунок розрісся, ми розділяємо обов’язки:
- Gift REST API — пошук і рекомендації подарунків, робота з каталогом і фідом (звичайний HTTP/REST‑сервіс).
- Commerce REST API — ACP, checkout‑сесії, статуси замовлень, зв’язок із платіжним провайдером.
- Analytics Service / REST API — збір подій і метрик (які добірки відкривають, що купують).
- Окремий сервіс Agents (за потреби) — складні багатокрокові сценарії. Він теж доступний через HTTP/REST, а не через MCP.
MCP Gateway стає єдиною точкою входу для всіх цих компонентів. Він:
- на запит tools/list повертає єдиний список інструментів, який описує сам: кожен інструмент прив’язаний до конкретного REST‑ендпойнта одного з сервісів;
- на запит tools/call дивиться на ім’я інструмента (params.name), за таблицею маршрутизації визначає, у який REST‑сервіс іти, і викликає відповідний HTTP‑метод (через fetch, axios тощо).
Якщо приходить tools/call з ім’ям suggest_gifts, gateway викликає відповідний REST‑ендпойнт у Gift REST API. Якщо це checkout_start, запит піде в Commerce REST API.
Невеликий псевдокод на TypeScript у стилі Express може виглядати так:
// Дуже спрощений обробник MCP‑запитів
app.post("/mcp", async (req, res) => {
const mcpReq = req.body as { method: string; params?: any };
const ctx = buildContextFromHeaders(req); // auth, locale тощо
const toolName = mcpReq.params?.name;
const backendRes = await callBackend(toolName, mcpReq, ctx);
res.json(backendRes);
});
Усередині pickBackend ви можете спиратися на ім’я методу, ім’я інструмента, локаль користувача і навіть на версію сервісу (для «канарейкових» і релізів blue/green, про які говоритимемо пізніше в модулі).
4. Обов’язки MCP Gateway: що він точно робить
Ми подивилися, як gateway вписується в архітектуру GiftGenius. Тепер чітко зафіксуймо, які обов’язки він має як окремий шар — незалежно від конкретного застосунку. Важливо сприймати gateway як мережевий і міжсервісний шар. Його завдання — не займатися бізнес‑логікою подарунків, а розв’язувати інфраструктурні завдання навколо неї.
Маршрутизація запитів
Перша роль — маршрутизатор. Gateway отримує MCP‑запит і, спираючись на його вміст, контекст користувача та свою конфігурацію, обирає цільовий сервіс.
Наприклад, у GiftGenius можна завести просту таблицю маршрутизації:
const TOOL_ROUTES: Record<string, "gift" | "commerce" | "analytics"> = {
suggest_gifts: "gift",
get_similar_gifts: "gift",
checkout_start: "commerce",
get_order_status: "commerce",
log_event: "analytics",
};
І далі використати її:
function pickBackend(req: McpRequest, ctx: GatewayContext): Backend {
if (req.method === "tools/list") return "aggregator";
if (req.method === "tools/call") {
const toolName = req.params?.name;
const group = TOOL_ROUTES[toolName] ?? "gift";
return group === "commerce" ? commerceBackend : giftBackend;
}
return giftBackend;
}
У нашому випадку giftBackend, commerceBackend, analyticsBackend — це звичайні REST‑сервіси: у кожного є базовий URL ("https://gift-api.internal", "https://commerce-api.internal", …). Gateway не пересилає MCP усередину: він розкладає MCP‑виклик на HTTP‑запит до потрібного REST‑ендпойнта.
Автентифікація та авторизація на периметрі
Друга ключова функція — захист периметра. Gateway — зручне місце, щоб перевірити токен, зрозуміти, хто користувач, від якої організації він прийшов, і які права доступу в нього є.
Він може, наприклад, прийняти OAuth‑токен від ChatGPT або від вашого MCP Auth‑сервера, перевірити його (бажано за допомогою перевіреної бібліотеки, а не саморобної криптографії) і перетворити на охайний об’єкт контексту:
type GatewayContext = {
userId: string | null;
tenantId: string | null;
locale: string;
};
function buildContextFromHeaders(req: Request): GatewayContext {
const token = req.headers["authorization"]; // "Bearer ..."
const claims = token ? verifyJwt(token) : null;
return {
userId: claims?.sub ?? null,
tenantId: claims?.tenant ?? null,
locale: (req.headers["x-openai-locale"] as string) || "en-US",
};
}
Внутрішні бекенд‑/REST‑сервіси тоді можуть не перейматися розбором сирих HTTP‑заголовків і токенів, а отримувати вже нормалізований context із userId, tenantId і locale. Рекомендації MCP‑документації прямо кажуть: не реалізовуйте валідацію токенів «з нуля» — використовуйте перевірені бібліотеки та короткоживучі токени.
Логування, трасування і метрики
Третя роль — спостережуваність. Gateway бачить усі вхідні MCP‑запити та всі відповіді, тож це ідеальне місце, щоб проставити correlation‑id, записати в лог параметри інструментів (без чутливих даних), зафіксувати час відповіді та статус.
Найпростіша ідея:
app.use((req, res, next) => {
const requestId = crypto.randomUUID();
(req as any).requestId = requestId;
const start = Date.now();
res.on("finish", () => {
const ms = Date.now() - start;
console.log(
`[${requestId}] ${req.method} ${req.url} -> ${res.statusCode} in ${ms}ms`
);
});
next();
});
Пізніше в модулі про спостережуваність ви зможете надсилати ці дані не просто в console.log, а в структуроване сховище й будувати на їхній основі дашборди.
Базовий контроль навантаження
Четверте, але теж важливе завдання — первинний контроль навантаження. На gateway зручно поставити лічильники викликів за користувачами, організаціями, інструментами й ендпойнтами, щоб не дати одному «скаженіючому» клієнту спалити ваш кластер і бюджет на моделі.
У цьому модулі ми поки лише фіксуємо ідею: лімітування запитів (rate limiting) і черги живуть на рівні gateway. Деталі реалізації (Redis, token buckets, leaky buckets) розбиратимемо в наступній лекції про захист периметра.
Збагачення запитів контекстом
І нарешті, gateway — хороше місце, щоб перетворити сирий контекст MCP‑клієнта на охайні аргументи для внутрішніх інструментів.
Наприклад, ChatGPT може передавати локаль користувача через openai/locale і _meta["openai/userLocation"]. Gateway може:
- обрати потрібний регіональний сервіс (uk‑сервер, en‑сервер тощо);
- додати locale в аргументи виклику інструмента, навіть якщо сам інструмент явно не вимагав цього в JSON Schema (наприклад, як необов’язкове поле).
Умовно:
function enrichToolArgs(args: any, ctx: GatewayContext) {
return {
...args,
locale: args.locale ?? ctx.locale,
tenantId: ctx.tenantId,
};
}
У результаті Gift API одразу отримує «багатий контекст» і може, наприклад, підтягнути українські описи подарунків для "uk-UA" та англійські — для "en-US".
5. Що MCP Gateway робити НЕ повинен
Коли в розробника з’являється «магічне місце, через яке проходить усе», виникає природне бажання запхнути туди все, що раніше жило в окремих сервісах. Так gateway ризикує перетворитися на монстра.
Є кілька речей, яким зазвичай не варто «жити» в цьому шарі.
По‑перше, складна бізнес‑логіка. Добір подарунків, правила знижок, розрахунок вартості доставки, логіка ACP — усе це має залишатися всередині спеціалізованих бекенд‑/commerce‑сервісів. Gateway може хіба що зробити легку попередню валідацію (наприклад, перевірити, що ціна не від’ємна), але не обирати SKU і не рахувати податок за регіонами.
По‑друге, довготривалий користувацький стан. Gateway — типовий stateless‑сервіс. Він має спокійно масштабуватися горизонтально, не покладатися на локальну пам’ять і перезапускатися без наслідків. Якщо ви почнете зберігати в ньому, наприклад, стан checkout‑майстра або тимчасовий вміст кошика, ви швидко отримаєте проблеми із синхронізацією між інстансами.
По‑третє, специфічні функції, які логічніше розмістити всередині самих бекенд‑сервісів (Gift API, Commerce API). Наприклад, якщо Gift backend хоче кешувати результат пошуку подарунків, нехай робить це сам — можливо, використовуючи Redis. Gateway не зобов’язаний знати про цю внутрішню оптимізацію. Ми ще окремо говоритимемо про захист периметра, і там якраз підкреслюється: шлюз — це про мережеві та міжсервісні функції, а не про бізнес‑правила рекомендацій.
По‑четверте, важкі обчислення. Якщо всередині gateway ви почнете смикати LLM‑моделі, робити складні трансформації й агрегації, він перестане бути «легким» фронтом і перетвориться на ще один «товстий» бекенд, який складно масштабувати й налагоджувати.
6. Gateway, локалізація і версії сервісів
Ми розібрали базові обов’язки gateway і те, чого в нього краще не класти. Тепер подивімося на кілька типових «просунутих» завдань, які зручно розв’язувати саме на цьому шарі: локалізацію і версіонування сервісів. Ще одна цікава роль gateway — розумна маршрутизація за локаллю та версіями сервісів.
Коли ChatGPT викликає ваш App, у нього вже є уявлення про мову користувача (openai/locale) і часто — про його геолокацію (_meta["openai/userLocation"]). Gateway може використати цю інформацію, щоб надсилати запити до потрібних бекенд‑сервісів.
Наприклад, можна побудувати архітектуру «один gateway — багато одномовних бекенд‑серверів»:
- uk‑Gift API — лише український каталог подарунків і тексти.
- en‑Gift API — лише англомовний.
- jp‑Gift API — японський (коли ви вирішите підкорити світ).
Gateway у цьому разі виступає MCP‑сервером для ChatGPT і за locale та userLocation обирає потрібний внутрішній сервіс.
Умовно:
function pickGiftBackendByLocale(ctx: GatewayContext): Backend {
if (ctx.locale.startsWith("uk")) return giftUkBackend;
if (ctx.locale.startsWith("ja")) return giftJpBackend;
return giftEnBackend;
}
Там же зручно реалізувати найпростіший канарейковий роутинг. У цьому модулі про production‑архітектуру ми якраз пропонуємо використовувати gateway, щоб частину трафіку надсилати в новий кластер сервісу, а решту — у старий.
Приклад дуже грубої «канарейки»:
function pickGiftBackendCanary(ctx: GatewayContext): Backend {
const hash = hashUser(ctx.userId ?? "anonymous");
const bucket = hash % 100;
return bucket < 5 ? giftBackendV2 : giftBackendV1; // 5% трафіку йде на v2
}
Так можна безпечно розгортати нову версію Gift API, дивлячись на метрики та помилки, не ламаючи весь продакшен одразу.
7. Типові архітектури: від «все в одному» до Gateway
Раніше в курсі ви вже бачили кілька варіантів production‑архітектури ChatGPT App. У цьому модулі ми виокремлюємо три базові топології, яких у 90 % випадків достатньо.
Перша — «все в одному». Віджет App (Next.js), MCP‑сервер, Agents‑логіка і простий commerce‑бекенд живуть в одному сервісі, часто в одному репозиторії й навіть в одній Vercel‑апці. Плюс такого підходу — майже немає DevOps, розгортання просте, затримка мінімальна. Мінус — складно масштабувати окремі частини: одна «гаряча» фіча може покласти весь застосунок, а межі між компонентами розмиті.
Друга — App + MCP Gateway + кілька бекенд‑сервісів. Тут Next.js‑віджет живе окремо (наприклад, на Vercel), а весь MCP‑трафік іде через Gateway, який маршрутизує запити до Gift REST API, Commerce REST API, сервісу Agents, ACP‑бекенду та інших. Це саме та схема, яку ми зараз розбираємо в межах GiftGenius і яка підходить для 90 % реальних production‑кейсів.
Третя — те саме, але в кількох регіонах (multi‑region), із глобальним балансувальником перед gateway. Тоді користувач із Європи потрапляє в eu‑кластер, зі США — в us‑кластер, а кожен регіон будується за схемою «Gateway + кілька бекенд‑сервісів». Це вже історія для доволі великих проєктів із глобальною аудиторією.
Для нас зараз важливо не стільки запам’ятати всі варіанти, скільки звикнути мислити gateway як окремим логічним компонентом архітектури — навіть якщо на перших етапах його роль виконує, скажімо, один MCP‑моноліт або бекенд вашого App.
8. Де фізично «живе» MCP Gateway
Хороша новина: MCP Gateway — це не обов’язково величезний окремий сервіс на Kubernetes. Найчастіше він проходить кілька стадій дорослішання.
На найменшому масштабі роль gateway може виконувати сам MCP‑сервер. У цьому разі вам просто потрібно охайно структурувати код: винести маршрутизацію, автентифікацію й логування в один модуль, а логіку інструментів — в інші. У цьому модулі ми прямо зазначаємо: у малих системах функції gateway можуть бути всередині MCP‑сервера або бекенд‑частини App (наприклад, у Next.js API route).
Наступний крок — окремий Node/TypeScript‑сервіс. Це може бути Express/Fastify‑застосунок, який слухає "/mcp" і звертається всередину до кількох HTTP‑сервісів. Для багатьох команд це комфортний варіант: він добре лягає на звичні DevOps‑інструменти.
Найпростіший скелет такого сервісу:
const app = express();
app.use(express.json());
app.post("/mcp", handleMcpRequest); // тут уся магія gateway
app.listen(4000, () => {
console.log("MCP Gateway listening on :4000");
});
На ще зрілішому етапі gateway можна реалізувати поверх managed‑рішень: AWS API Gateway, Cloudflare Workers/Routes, NGINX/Envoy із конфігом роутингу та Lua/JS‑скриптами. Важливо розуміти: це зміна реалізації, а не концепції. Архітектурно ChatGPT, як і раніше, ходить в одну точку, а всі деталі розбирає gateway.
9. Міні‑приклад: простий MCP Gateway для GiftGenius
Ми вже окремо подивилися на маршрутизацію, контекст і обробку tools/list. Тепер зберімо все сказане в один чіткий, але невеликий приклад. Нехай у нас є два внутрішні REST‑сервіси:
- GIFT_API_BASE = "https://gift-api.internal";
- COMMERCE_API_BASE = "https://commerce-api.internal".
І один gateway, до якого ChatGPT ходитиме за адресою "https://gateway.giftgenius.com/mcp".
Спочатку визначимо кілька типів:
type Backend = "gift" | "commerce";
type ToolRoute = {
backend: Backend;
method: "GET" | "POST";
path: string;
};
const TOOL_ROUTES: Record<string, ToolRoute> = {
suggest_gifts: {
backend: "gift",
method: "POST",
path: "/api/gifts/suggest",
},
checkout_start: {
backend: "commerce",
method: "POST",
path: "/api/checkout/start",
},
get_order_status: {
backend: "commerce",
method: "GET",
path: "/api/orders/status",
},
};
Далі реалізуємо вибір бекенду й виклик:
async function callBackend(toolName: string, mcpReq: McpRequest, ctx: GatewayContext) {
const route = TOOL_ROUTES[toolName];
if (!route) {
throw new Error(`Unknown tool: ${toolName}`);
}
const base =
route.backend === "gift" ? GIFT_API_BASE : COMMERCE_API_BASE;
const url = base + route.path;
// args, що прийшли в MCP‑виклику tools/call
const args = {
...(mcpReq.params?.arguments ?? {}),
locale: ctx.locale,
};
const res = await fetch(url, {
method: route.method,
headers: { "content-type": "application/json" },
body: route.method === "POST" ? JSON.stringify(args) : undefined,
});
const data = await res.json();
// Загортаємо відповідь REST‑сервісу в MCP‑відповідь
return {
result: data,
} satisfies McpResponse;
}
І нарешті — основний обробник, який:
- Будує контекст із заголовків (auth, locale).
- Обирає бекенд.
- Або агрегує tools/list, або проксіює tools/call.
app.post("/mcp", async (req, res) => {
const mcpReq = req.body as McpRequest;
const ctx = buildContextFromHeaders(req);
if (mcpReq.method === "tools/list") {
// Gateway сам оголошує інструменти та їхні схеми
const tools = [
{
name: "suggest_gifts",
description: "Підбирає подарунки за бюджетом та інтересами.",
inputSchema: { /* ... JSON Schema ... */ },
},
{
name: "checkout_start",
description: "Створює чорновик замовлення та запускає checkout.",
inputSchema: { /* ... */ },
},
// ...
];
return res.json({ result: { tools } });
}
if (mcpReq.method === "tools/call") {
const toolName = mcpReq.params?.name;
const backendRes = await callBackend(toolName, mcpReq, ctx);
return res.json(backendRes);
}
res.status(400).json({ error: { message: "Unsupported MCP method" } });
});
Це, звісно, спрощена схема, але вона вже показує ключові ідеї:
- gateway не знає, як саме Gift API добирає подарунки;
- він лише охайно маршрутизує, збагачує аргументи та, за потреби, логує й обмежує виклики.
10. Як усе це пов’язано з подальшими темами модуля
MCP Gateway — фундаментальна частина всього, що ми обговорюватимемо в решті лекцій модуля:
- У наступній темі ми говоритимемо про захист периметра: лімітування запитів (rate limiting), черги та backpressure. Усе це живе насамперед на рівні gateway, тому що саме він бачить увесь вхідний трафік і може «відрізати зайве» до того, як запити завалять бекенд.
- Далі ми обговоримо стійкість: timeouts, circuit breakers, bulkheads. Gateway — точка, де зручно централізовано задавати тайм‑аути на зовнішні виклики та вмикати/вимикати проблемні сервіси (наприклад, тимчасово «відрубати» Commerce API, якщо він починає часто падати з помилками).
- І нарешті, під час розмови про масштабування й розгортання ми дивитимемося на gateway як на окремий кластер, який можна балансувати, розгортати за схемами blue/green і canary та відкочувати незалежно від внутрішніх MCP‑сервісів.
По суті, якщо раніше ви думали «у мене є App і MCP‑сервер», то тепер схема розширюється до «у мене є App, MCP Gateway, кілька бекенд‑/Agents‑кластерів і commerce‑бекенд». І саме gateway дозволяє при цьому не ускладнювати конфігурацію для ChatGPT: він, як і раніше, бачить одну MCP‑точку.
11. Типові помилки під час роботи з MCP Gateway
Помилка № 1: перетворювати gateway на «бізнес‑монстра».
Поширена пастка: раз через gateway проходить усе, то чому б не додати туди розрахунок знижок, добір SKU, складні правила категорій або валідацію промокодів. У підсумку ви отримуєте «товстий» сервіс, який складно масштабувати й змінювати, і втрачаєте сенс поділу на Gift API, Commerce API та інші спеціалізовані компоненти. Краще тримати gateway як тонкий мережевий шар, а все предметно специфічне залишити всередині профільних сервісів.
Помилка № 2: зберігати в gateway довготривалий користувацький стан.
Ідея «а давайте запам’ятаємо кошик користувача прямо в пам’яті gateway» звучить привабливо, доки у вас один інстанс. Щойно з’являється другий — починаються проблеми: де справжній кошик, в інстансі A чи B? Що буде після рестарту? Gateway має залишатися stateless: максимум — невеликий кеш handshakeʼів або конфігурацій, а весь стан сесій і замовлень зберігається в БД або у спеціалізованих сервісах.
Помилка № 3: робити ChatGPT «в курсі» внутрішньої топології сервісів.
Якщо ви починаєте прокидати в ChatGPT одразу кілька API‑серверів (окремо Gift API, окремо Commerce API), а gateway використовувати «місцями», ви втрачаєте головну перевагу: єдиний вхід і централізований контроль. За зміни топології доведеться оновлювати конфігурацію в кількох місцях. Значно простіше один раз налаштувати MCP Gateway як офіційний endpoint для App і сховати всі внутрішні зміни за ним.
Помилка № 4: дублювати міжсервісну логіку в усіх бекендах.
Іноді команди намагаються реалізувати автентифікацію, лімітування запитів (rate limiting), логування і локалізацію в кожному REST‑сервісі окремо. У підсумку політика прав і лімітів у Gift API одна, у Commerce API — інша, і поведінка App стає непередбачуваною. Gateway якраз і потрібен, щоб ці речі централізувати: перевірити токен, визначити tenant і locale, записати виклик у лог, застосувати ліміти, а далі вже йти в конкретний сервіс.
Помилка № 5: перевантажувати gateway важкими обчисленнями та LLM‑викликами.
Технічно ніщо не заважає вам із gateway викликати ще одну LLM‑модель, робити складні агрегації або довгі batch‑операції. Але це швидко перетворить його на ще один важкий бекенд, який неможливо нормально масштабувати й ізолювати. Gateway має залишатися швидким і передбачуваним: максимум — легка трансформація та маршрутизація. Усе «важке» — всередину REST‑сервісів або в черги/воркери, про які ми поговоримо далі в модулі.
Помилка № 6: занадто рано ускладнювати інфраструктуру.
Протилежна крайність — одразу будувати окремий Kubernetes‑кластер, NGINX‑стек, Cloudflare Workers і купу складних конфігів заради маленького навчального App. У цьому немає сенсу, доки у вас немає реального навантаження і вимог до відмовостійкості. Цілком нормально починати з одного MCP‑моноліту або простого Node‑gateway і лише потім, у міру зростання, виносити окремі компоненти в кластери й managed‑сервіси.
ПЕРЕЙДІТЬ В ПОВНУ ВЕРСІЮ