MCP-серверы — это основа расширяемости Codex CLI: каждый сервер добавляет агенту новые тулзы (поиск в интернете, работа с базой данных, обращение к API). Но до версии 0.151.0 результат MCP-тулзы попадал в модель как есть — без валидации, без фильтрации, без возможности исправить ошибку. Релиз 29 августа 2026 года (GitHub) добавил два механизма, которые меняют эту картину: расширения (extensions) теперь перехватывают результаты MCP-тулзов до попадания в модель, а задержка старта для optional-серверов стала настраиваемой. Ниже — как использовать оба на практике.

Что изменилось в 0.151.0
Три ключевых фичи релиза (changelog):
| Фича | Что делает | Пул-реквест |
|---|---|---|
| Extension MCP result interception | Расширения могут инспектировать и заменять результаты MCP-тулзов до отправки в модель | #41202 |
| Configurable grace period | Настраиваемая задержка ожидания optional MCP-серверов при старте | #41199 |
| Per-repo plugin catalog | Каталог плагинов учитывает конфигурацию конкретного репозитория | #41208 |
Обновление — стандартное:
codex --version # проверить текущую версию
# для standalone:
curl -fsSL https://chatgpt.com/codex/install.sh | sh
# для npm:
npm update -g @openai/codex
На момент публикации актуальная версия — 0.151.0 (стабильная). Если у вас стоит 0.149.0 или 0.150.0 — обновление обязательно: оба ключевых механизма отсутствуют в старых версиях.
Зачем перехватывать результаты MCP-тулзов
Стандартный пайплайн MCP в Codex выглядит так: агент вызывает тулзу → MCP-сервер обрабатывает запрос → JSON-результат попадает в модель как часть контекста. Проблема в том, что модель получает сырые данные без какой-либо обработки.
На практике это приводит к трём категориям situations (по данным PR #41202):
-
Секреты в ответах. MCP-сервер может вернуть API-токены, пароли или внутренние идентификаторы в теле ответа. Модель видит их и может воспроизвести в генерируемом коде или командах.
-
Неформатированные ошибки. Когда MCP-сервер возвращает ошибку (
isError: true), модель получает сырой JSON сtechnical details — stack trace, HTTP-коды, внутренние пути сервера. Вместо этого агенту полезнее видеть человекочитаемое описание проблемы. -
Раздутые контексты. Некоторые MCP-тулзы возвращают многостраничные JSON-ответы (каталоги, списки, дампы). Без фильтрации они съедают контекстное окно модели.
До 0.151.0 исправить это можно было только через промпт — просить модель «игнорировать секреты» или «кратко описывать ошибки». Это ненадёжно: модель не всегда следует таким инструкциям, особенно при длинных сессиях.

Extension MCP result interception: как работает
С 0.151.0 расширения (extensions) могут подписаться на событие on_mcp_tool_result (PR #41202). Колбэк вызывается после завершения MCP-вызова, но до отправки результата в модель и до публикации completion-события.
Техническая реализация
Новый интерфейс ToolLifecycleContributor добавляет метод:
fn on_mcp_tool_result<'a>(&'a self, _input: McpToolResultInput<'a>) -> ToolLifecycleFuture<'a> {
Box::pin(std::future::ready(()))
}
McpToolResultInput содержит (исходный код):
| Поле | Тип | Что содержит |
|---|---|---|
session_store |
&SessionExtensionData |
Данные расширения на уровне сессии |
thread_store |
&ThreadExtensionData |
Данные расширения на уровне треда |
turn_store |
&TurnExtensionData |
Данные расширения на уровне хода |
turn_id |
&str |
Идентификатор текущего хода |
call_id |
&str |
Идентификатор MCP-вызова |
mcp_tool |
&McpToolContext |
Контекст тулзы: имя, сервер, источник (Connector / CodeMode) |
arguments |
&Value |
Аргументы, с которыми вызвана тулза |
result |
&mut CallToolResult |
Мутируемый результат — можно заменить или модифицировать |
Ключевой момент — result передаётся как &mut: расширение не просто видит результат, а может его изменить. Модификация применяется к обоим направлениям — и в completion-события (для UI), и в контексте модели.
Порядок выполнения
Код из lifecycle.rs показывает цепочку:
MCP-сервер → result → on_mcp_tool_result() → sanitize → модель
Расширения выполняются последовательно — каждое видит результат предыдущего. Это позволяет выстраивать цепочки: первое расширение удаляет секреты, второе логирует результат, третье форматирует ошибки.
Что можно делать в on_mcp_tool_result
На основании тестов в tool_lifecycle.rs, поддерживается три сценария:
| Сценарий | Что делает расширение | Пример |
|---|---|---|
| Unchanged | Оставляет результат как есть | Логирование MCP-вызова |
| Replace | Заменяет результат целиком | Удаление секретов из ответа |
| Error | Помечает результат как ошибку | Валидация формата ответа |
Тесты проверяют оба режима вызова MCP-тулз — прямой вызов (Direct) и вызов через Code Mode (tools.mcp__* в exec-режиме). В обоих случаях расширение корректно перехватывает результат (тесты).
Практический пример: фильтрация секретов
Допустим, у вас MCP-сервер, подключающийся к корпоративному API. Он возвращает ответы, содержащие временные токены доступа:
{
"content": [{"type": "text", "text": "Results for query..."}],
"_meta": {
"access_token": "eyJhbGciOi...",
"refresh_token": "dGhpcyBpcyBh..."
}
}
Расширение для Codex может очищать такие данные:
impl ToolLifecycleContributor for SecretSanitizer {
fn on_mcp_tool_result<'a>(&'a self, input: McpToolResultInput<'a>) -> ToolLifecycleFuture<'a> {
Box::pin(async move {
// Удаляем чувствительные поля из _meta
if let Some(meta) = input.result.get_mut("_meta") {
if let Value::Object(map) = meta {
map.remove("access_token");
map.remove("refresh_token");
}
}
})
}
}
Модель видит только результат запроса — без токенов, которые могли бы просочиться в генерируемый код.
Практический пример: валидация формата
Другой сценарий: MCP-сервер иногда возвращает ошибки в неожиданном формате. Вместо стандартного { "isError": true, "content": [...] } он отдаёт plain-text описание или HTML:
Error: Connection refused to postgres://...
Расширение нормализует такие ответы:
impl ToolLifecycleContributor for ErrorNormalizer {
fn on_mcp_tool_result<'a>(&'a self, input: McpToolResultInput<'a>) -> ToolLifecycleFuture<'a> {
Box::pin(async move {
if input.result.is_error {
// Форматируем ошибку в человекочитаемый вид
let text = input.result.content.iter()
.filter_map(|c| match c {
ContentItem::Text { text, .. } => Some(text.as_str()),
_ => None,
})
.collect::<Vec<_>>()
.join(" ");
// Убираем технические детали: пути, токены, стек-трейсы
let clean = sanitize_error_message(&text);
input.result.content = vec![ContentItem::Text {
text: format!("MCP-сервер вернул ошибку: {clean}"),
annotations: None,
}];
}
})
}
}
Агент получает чистое описание проблемы, модель не тратит контекст на технический мусор.
Grace period для optional MCP-серверов
Второй ключевой механизм — PR #41199. До 0.151.0 Codex ждал определённое время подключения каждого optional MCP-сервера, и эта задержка была фиксированной. Теперь параметр mcp_optional_startup_grace_ms доступен в конфигурации.
Как это работает
При старте Codex подключается к MCP-серверам параллельно. Required-серверы блокируют запуск — если они не подключились, Codex не начнёт работу. Optional-серверы — нет: агент стартует без них, но только если за отведённое время (grace period) они не появились.
По умолчанию grace period = 1000 мс (PR description):
Add
mcp_optional_startup_grace_mswith a default of 1,000 ms to control how long tool catalog capture waits for optional MCP servers.
Когда менять grace period
| Сценарий | Значение | Почему |
|---|---|---|
| Быстрые MCP-серверы (локальные) | 1000 (по умолчанию) |
Хватает для подключения |
| Тяжёлые серверы (БД, удалённые API) | 3000–5000 |
Даём время на старт |
| Отключение общей задержки | 0 |
Каждый сервер использует свой startup_timeout_sec |
Конфигурация
В config.toml или ~/.codex/config.toml:
# Глобальная задержка для optional-серверов (мс)
mcp_optional_startup_grace_ms = 3000
[mcp_servers.postgres]
command = "mcp-postgres"
args = ["postgresql://localhost/mydb"]
optional = true
startup_timeout_sec = 5
[mcp_servers.github]
command = "mcp-github"
optional = false # required — не зависит от grace period
При mcp_optional_startup_grace_ms = 0 общая задержка отключается — optional-серверы используют индивидуальные значения startup_timeout_sec. Это полезно, если у вас смешанный стек: часть серверов быстрые (мгновенно), часть — тяжёлые (запускаются по 5–10 секунд).

Настройка во время работы
Параметр применяется не только при старте, но и при обновлении MCP-конфигурации:
Apply updated grace values during runtime and MCP configuration refreshes, and reset cached startup deadlines when the configured duration changes.
Это значит, что можно менять grace period через /cd (смена рабочей папки перезагружает конфиг) или при обновлении конфига — не требуя перезапуска сессии.
Сценарии использования
1. Централизованная валидация MCP-ответов
Если вы работаете с несколькими MCP-серверами и хотите гарантировать формат ответов — расширение проверяет result.content на соответствие ожидаемой структуре. Невалидные ответы заменяются на стандартизированную ошибку.
2. Аудит MCP-вызовов
Расширение логирует каждый MCP-вызов: имя тулзы, аргументы, время выполнения, размер ответа. Полезно для отладки долгих серверов или поиска тулз, которые раздувают контекст.
3. Кэширование результатов
Если MCP-тулза вызывается повторно с теми же аргументами — расширение может вернуть кэшированный результат, не обращаясь к серверу. Это ускоряет работу агента при повторяющихся запросах.
4. Комбинирование с grace period
Для production-окружений с несколькими optional-серверами:
- Увеличьте grace period до 3–5 секунд, чтобы дать время тяжёлым серверам
- Добавьте расширение, которое помечает результаты от отсутствующих серверов как «сервер недоступен, результат неполный»
- Модель получает осмысленную информацию о доступности инструментов
Российские реалии
- Установка и обновление Codex CLI — штатные: GitHub и npm доступны из РФ без VPN. Обновление через
curl | shилиnpm update -g @openai/codexработает без ограничений. - Вход — через ChatGPT (OAuth) требует VPN из-за ограничений OpenAI по российским IP; через API-ключ (
OPENAI_API_KEY) работает стабильнее. - Оплата — российские Visa/Mastercard не принимаются. Рабочие варианты: виртуальные зарубежные карты (пополнение по СБП или USDT), карты банков Казахстана/Грузии/Армении. Подробности — в статье «Как оплатить подписку ChatGPT из России в 2026 году».
- Russian providers — Codex CLI можно подключить к другим провайдерам. Разработчик на практике собрал Codex CLI с инференсом Яндекса через AI Studio API — «Агентность на практике: Codex CLI и российский AI-ландшафт».
- Русскоязычные материалы: полный гид по Codex CLI — «Ультимативный гид по Codex CLI», сравнение CLI-агентов — Habr, 4 августа 2026.
Ограничения
- Extensions —perimental API. Интерфейс
ToolLifecycleContributorпоявился в 0.151.0; структураMcpToolResultInputи набор полей могут измениться в следующих релизах. Проверяйте changelog при обновлении Codex. - Расширения не заменяют валидацию на стороне MCP-сервера. Перехват в расширении — это последний рубеж перед моделью. Если MCP-сервер генерирует некорректные данные, лучше исправить его, а не обрабатывать симптомы в расширении.
- Grace period не влияет на required-серверы. Если required MCP-сервер не подключился за
startup_timeout_sec, Codex завершится с ошибкой — обойти это нельзя и не нужно. - Нет встроенных расширений для фильтрации. Codex 0.151.0 добавляет API, но не поставляет расширения из коробки. Фильтрацию секретов, валидацию формата и другие сценарии нужно реализовать самостоятельно или ждать появления готовых решений в каталоге плагинов.
- Контекстное окно не расширяется. Grace period ускоряет старт за счёт включения optional-серверов, но не увеличивает объём контекста. Декомпозиция задач и
/newмежду батчами по-прежнему рекомендуются — об этом подробнее в статье «Как установить Codex CLI». - Из РФ — все ограничения OpenAI по входу и оплате сохраняются; extensions и grace period не зависят от региона.
Связанные статьи
- Как установить Codex CLI — установка, вход, модели
- Codex 0.149.0: дашборд агентов — agents dashboard, queue, /cd
- Что такое MCP — протокол, серверы, тулзы
- Что такое агентный кодинг — архитектура агентов и их экосистема
