Раздел: Codex
Идентификатор:codex_mcp· Экран:ui/codex/CodexMcpScreen.kt(474) +CodexMcpCards.kt,CodexMcpActions.kt,CodexMcpDialogs.kt
Снимок: 2026-10-11
1. Зачем и что это
Всё пишется в один файл — ~/.codex/config.toml — через app-server, и применяется без перезапуска. Это ключевое отличие от ручного редактирования конфига: приложение пишет → перечитывает → сверяет результат и честно сообщает, если запись не применилась.
Инварианты этого экрана (они же у Skills):
- тумблер не «прыгает»: слева от
Switchвсегда есть слот спиннера; - карточка не переезжает: выключенный инструмент остаётся на месте и гаснет;
- сообщения — в закреплённой полосе под шапкой (
ToggleStatusStrip), а не отдельным элементом списка; - после тумблера нет второго
forceReload— конфиг перечитывается тихо.
2. Как попасть
Хаб инструментов → секция Codex → карточка «MCP» (hub_codex_mcp_title, тайл на главной — «MCP»).
| Откуда ещё | Путь |
|---|---|
| Меню треда | Codex → MCP (тот же экран) |
| Мост | app_navigate с screen: "codex_mcp" |
Маршрут: Screen.kt:140 ("codex_mcp" -> Screen.CodexMcpHub) → MainRouter.kt:320.
3. Экран: элементы и действия
| Секция | Элемент | Что делает |
|---|---|---|
| «Что это» | Раскрывающаяся шпаргалка | Объяснение серверов, тумблеров, лимитов |
| «Серверы» | McpServerCard на каждый включённый сервер | Состояние, runtimeStatus, список инструментов |
| Тумблер сервера | Switch в карточке | mcp_servers.<name>.enabled |
| Строка инструмента | McpToolRowItem | Тумблер инструмента + кнопка лимита |
| Кнопка лимита | Открывает McpLimitDialog | output_token_limit для инструмента |
| Кнопка «Test call» | McpTestCallDialog → mcpServer/tool/call | Проверить инструмент вручную |
| Кнопка OAuth | mcpOAuthLogin | Открывает авторизацию, McpAuthDialog со ссылкой |
| «Выключенные» | Карточки выключенных серверов | Включить обратно |
| Полоса статуса | ToggleStatusStrip | Результат записи, «записано в config.toml» / «не применилось» |
Лист результата тестового вызова — McpCallResultDialog, окно авторизации — McpAuthDialog.
4. Возможности подробно
Три уровня управления
| Уровень | Что пишется | Ключ в config.toml |
|---|---|---|
| Сервер | Вкл/выкл сервер целиком | mcp_servers.<name>.enabled |
| Инструмент | Вкл/выкл отдельный тул сервера | mcp_servers.<name>.disabled_tools |
| Бюджет вывода | Лимит токенов ответа тула | mcp_servers.<name>.tools.<tool>.output_token_limit |
Запись и применение
Всё идёт через одну функцию writeConfigValue(keyPath, value) → config/value/write {keyPath, mergeStrategy: "upsert", value}. Значение null снимает настройку (сервер удаляет ключ). После записи вызывается applyMcpConfigChange():
config/mcpServer/reload— перечитать config.toml в app-server без перезапуска;- повторно прочитать состояние и применить к экрану.
Порядок «запись → reload → сверка» гарантирует честный результат. Если запись прошла, но конфиг не отражает изменение, показывается предупреждение «записано, но не применилось — проверьте config.toml»: молча вернувшийся тумблер выглядел бы как поломка экрана.
Бюджеты вывода
У каждого инструмента есть output_token_limit — сколько токенов ответа уйдёт в контекст. Значение считается до стандартной 20% надбавки на сериализацию.
Первоначальные лимиты для сервера y83 задаёт функция mcpDefaultOutputLimit:
| Категория | Инструменты | Лимит |
|---|---|---|
| Без ограничения | web_search, web_fetch, research, research_verify, ai_ask, ai_export | не задаётся |
| Структурные (файлы, JSON, репозиторий, мост, журналы) | bridge_command, browser_audit, browser_shot, dev_repo, dev_git, file_read, json_query, plan_read, log_grep, session_messages | 10 000 |
| Остальные | всё прочее | 6 000 |
Глобального tool_output_token_limit у проекта нет намеренно — он задел бы search/WebAI и встроенные инструменты. Явное значение в config.toml всегда важнее этой карты. Инструменты, уже обработанные один раз, повторно не «засеиваются» (seededTools).
Границы значения: MCP_LIMIT_MIN = 1, MCP_LIMIT_MAX = 1 000 000 (0 сервер трактует как «ничего не отдавать»).
Статус серверов
Экран тянет mcpServerStatus/list и config/read. Важная деталь: состояние тумблера сервера берётся из конфига, а не из runtimeStatus, потому что без открытого треда app-server отдаёт runtimeStatus=null у всех серверов, и выключенный сервер выглядел бы включённым.
Для runtime-статуса экран спрашивает серверы с threadId открытого треда: MCP поднимается по требованию треда, поэтому без threadId все статусы были бы «неизвестны». В хабе (без треда) тред нужен только для статус��; из хаба статус выглядит неопределённым — это ожидаемо.
Тестовый вызов и OAuth
mcpServer/tool/call выполняет инструмент вручную и показывает результат (или ошибку) в листе. Для этого нужен открытый тред — иначе экран предупреждает «тестовый вызов требует открытого треда».
mcpServer/oauth/login возвращает authorizationUrl для сервера, который требует OAuth; ссылка открывается во встроенном браузере.
5. Данные: БД, файлы, настройки
| Что | Где лежит | Как меняется | Кто читает |
|---|---|---|---|
| Настройки MCP | ~/.codex/config.toml ([mcp_servers.<server>]) | config/value/write через app-server | Codex (app-server) |
Секции [mcp_servers.y83] | Тот же конфиг | Вручную или приложением | Codex |
Источник правды — конфиг, а не каталог mcpServerStatus/list: выключенный инструмент сервер может вообще не отдавать, и тогда из UI его было бы не вернуть. Поэтому список — это склейка каталога сервера и конфига (mcpToolRows), включая «config-only» инструменты (есть в конфиге, но сервер их не отдал).
6. Backend: REST/роуты
Экран ходит не в REST-бэкенд, а в app-server Codex по JSON-RPC:
| Запрос | Что делает |
|---|---|
mcpServerStatus/list {threadId?} | список серверов и их runtime-статус |
config/read {} | текущий config.toml (настройки серверов/инструментов) |
config/value/write {keyPath, mergeStrategy, value} | запись/снятие ключа |
config/mcpServer/reload | перечитать конфиг без перезапуска |
mcpServer/tool/call {server, threadId, tool, arguments} | тестовый вызов |
mcpServer/oauth/login {name, threadId?} | ссылка авторизации |
Профили MCP-серверов на стороне backend (/mcp, /mcp/codex, /mcp/remote, /mcp/context7) описаны в ../codex-chat.md §7.
7. Мост и MCP
| Что | Как | Примечание |
|---|---|---|
| Открыть экран | app_navigate с screen: "codex_mcp" | BridgeScreenCatalog |
Инструментов для правки MCP-конфига в инвентаре MCP нет — это делается только через экран и app-server.
8. Настройки, конфиг, квоты и лимиты
| Параметр | Значение | Где задаётся |
|---|---|---|
Границы output_token_limit | 1…1 000 000 | MCP_LIMIT_MIN/MAX |
| Дефолт (структурные) | 10 000 | mcpDefaultOutputLimit |
| Дефолт (остальные) | 6 000 | То же |
| Исключения (без лимита) | web_search, web_fetch, research, research_verify, ai_ask, ai_export | MCP_LIMIT_EXEMPT_TOOLS |
| Merge-стратегия записи | upsert | writeConfigValue |
9. Ловушки и ограничения
- Требуется открытый тред для статус�� и тестовых вызовов. Без
threadIdapp-server отдаётruntimeStatus=nullу всех серверов (ленивый старт MCP). Тумблеры при этом работают — их источник конфиг, а не статус. - Запись может не примениться. Если сервер проигнорировал ключ, экран честно скажет «не применилось» — проверьте
config.toml. - Отключённый инструмент может пропасть из каталога. Именно поэтому список строится склейкой каталога и конфига, иначе вернуть инструмент было бы нечем.
- Глобального лимита нет намеренно — он задел бы search/WebAI и встроенные инструменты. Настраивать нужно каждый инструмент отдельно.
- Инструменты с типом «без лимита» (search, research) специально исключены из авто-лимитов — обрезать их вывод нельзя, это ломает результат.
- Одноразово обработанные инструменты не «засеиваются» повторно — новый дефолт-лимит не перезапишет вашу настройку.
- Ошибки записи показывает сам экран (
mcpNotice), снекбар чата за диалогом не виден.
10. Источники правды
app/src/main/java/com/y83/ws/ui/codex/CodexMcpScreen.kt— экран.app/src/main/java/com/y83/ws/ui/codex/CodexMcpCards.kt— карточки серверов/инструментов, форматирование.app/src/main/java/com/y83/ws/ui/codex/CodexMcpActions.kt— запись, reload, тумблеры, OAuth, тестовый вызов.app/src/main/java/com/y83/ws/ui/codex/CodexMcpDialogs.kt— диалоги лимита, тест-вызова, OAuth.app/src/main/java/com/y83/ws/data/codex/CodexMcpSettings.kt— настройки, лимиты, склейка каталога и конфига.app/src/main/java/com/y83/ws/data/codex/CodexMcpParse.kt— разбор ответаmcpServerStatus/list.backend/internal/handlers/mcp/— серверная часть MCP-тулов.