Ты вписал ключ, opencode models показал модель, чат ответил осмысленным текстом. Выглядит как готовая настройка. А потом первый же агентный запрос, которому нужен инструмент, молча возвращает абзац текста вместо действия - файл не прочитан, команда не выполнена, ничего не вызвано. И ты сидишь и гадаешь, что сломалось: ключ, модель, MCP-сервер или локальный движок.
Ответ, который экономит вечер отладки: рабочий chat completion не доказывает ровным счётом ничего про вызов инструмента. Это два разных протокола, и проверять их надо по отдельности. Дальше - как разложить конфигурацию OpenCode на четыре независимо проверяемых слоя и прогнать по каждому канарейку, которая заранее говорит, где именно связка развалится.
Сразу оговорю границу: это про OpenCode и MCP, а не про настройку MCP в Cursor - там свой формат конфига и свой UI, и переносить выводы один в один нельзя.
Подключите AI-агентов с оплатой в рублях на provod.ai
Почему рабочий ответ модели ничего не говорит про инструменты?
Спорное убеждение, на котором горит большинство: «раз совместимый запрос прошёл, значит инструментальный протокол работает». Не работает такая логика. По базовой спецификации Model Context Protocol (modelcontextprotocol.io, доступ 18.07.2026) MCP - это отдельный протокол поверх JSON-RPC 2.0 со своим жизненным циклом: инициализация, согласование возможностей, свои типы запросов, ответов и уведомлений. Он не имеет отношения к контракту completion-эндпоинта модели. Модель отвечает по одному каналу, инструменты вызываются по другому.
Отсюда прямое следствие для тебя как разработчика coding-инструмента: успешный /v1/chat/completions подтверждает, что жив канал модели, и только его. Инструментальный слой в этот момент может быть не сконфигурирован, не подключён или несовместим с конкретной моделью - и ты этого не увидишь, пока не проверишь его отдельным входом с заранее заданным ожиданием.
Чтобы канарейка была чистой, держи под рукой один заведомо совместимый сторонний источник модели: тогда ты проверяешь протокол, а не свою основную настройку заодно с ним. На эту роль подойдёт любой провайдер с поддержкой протокола OpenAI - например, provod.ai (российский аналог OpenRouter), где ключ и base URL меняются без правок кода клиента.
Четыре слоя, которые редактируются отдельно друг от друга
По документации OpenCode (opencode.ai/docs, доступ 18.07.2026) файл opencode.json объявляет provider, model и mcp как отдельные top-level объекты. Они сливаются по фиксированной цепочке приоритета: глобальный ~/.config/opencode/opencode.json, затем проектный opencode.json, и проект побеждает. То есть авторизация провайдера, выбор модели и конфигурация MCP-сервера живут в трёх структурно независимых, отдельно редактируемых слоях.
К этим трём добавляется четвёртый, невидимый в самом opencode.json: хранилище секретов. Поток /connect в TUI или команда opencode mcp auth пишут ключи в ~/.local/share/opencode/auth.json, тогда как блок provider в конфиге описывает только форму эндпоинта - npm-пакет SDK, baseURL и список моделей. Значит «работает ли API ключ» и «резолвится ли ID модели» - это две разные проверки, каждая со своим исходом.
Разложим по слоям, чтобы дальше было что канарить:
- Провайдер (auth). Принят ли ключ. Отказ этого слоя в документации назван явно:
ProviderInitError. Лечится повторным/connectили очисткой~/.local/share/opencode. - Ссылка на модель. Резолвится ли
<providerId>/<modelId>. Отказ -ProviderModelNotFoundError, проверяется черезopencode models. Это другой, отдельно опознаваемый класс ошибки. - Форма эндпоинта. Для кастомного OpenAI-совместимого провайдера OpenCode требует явного выбора npm-пакета:
@ai-sdk/openai-compatibleдля API формы/v1/chat/completionsпротив@ai-sdk/openaiдля формы/v1/responses, плюс вручную объявленные лимиты токенов модели. Провайдер может успешно авторизоваться и при этом быть направлен на неверную форму completion-эндпоинта. - MCP-сервер. Настраивается в отдельном блоке
mcp:type: "local"требует массивcommand,type: "remote"требуетurl, и у каждого сервера свой переключательenabled: true/false, независимый от провайдера и модели.
Четыре слоя - четыре независимых источника отказа. Именно поэтому отлаживать всю связку разом бессмысленно: ты не сможешь сказать, какой из четырёх выстрелил первым.
Польза от такого деления видна уже по тому, как люди формулируют проблему. «opencode ai api» почти всегда упирается в первый слой: принят ключ или нет. «opencode openai compatible» - в третий: какой npm-пакет и какая форма эндпоинта. «mcp сервер для opencode» - в четвёртый, и с первыми тремя он не связан вообще. Одинаковая на слух жалоба «не работает» распадается на разные диагнозы ещё до того, как ты откроешь конфиг.

Как устроена канарейка по слоям?
Главное правило: один прогон меняет один слой. Смешал два - потерял локализацию. Тезис, вокруг которого строится вся проверка, фальсифицируемый: если компонент нельзя отдельно подтвердить заранее заданным наблюдением, то отказ всей связки OpenCode/MCP локализовать нельзя. Значит каждому слою нужен вход, ожидание и место, где смотреть наблюдение.
Наблюдение живёт в логах. Они хранятся timestamped-файлами в ~/.local/share/opencode/log/ (по документации удерживаются последние 10), а --log-level DEBUG даёт подробный диагностический вывод. Важная оговорка про безопасность: сырые ключи лежат в отдельном auth.json, и шаг логирования канарейки не должен затягивать содержимое этого файла в сохраняемый артефакт. Секрет в логе - это отдельный класс отказа, который ты создашь сам.
Ниже - таблица «компонент-вход-ожидание-наблюдение». Читай её как протокол для собственного прогона: фиксируешь версии компонентов на момент теста и заполняешь последнюю колонку сам. Собрана она из документации; своего запуска за ней нет, и конкретные исходы будут зависеть от твоей связки.
| Слой | Вход (канарейка) | Ожидание | Где смотреть наблюдение |
|---|---|---|---|
| Провайдер / auth | /connect или opencode mcp auth | ключ принят, запись в auth.json | нет ProviderInitError |
| Ссылка на модель | opencode models | <providerId>/<modelId> резолвится | нет ProviderModelNotFoundError |
| Форма эндпоинта | пробный chat completion | ответ по нужной форме (/v1/chat/completions или /v1/responses) | текст ответа в DEBUG-логе |
| MCP-сервер | opencode mcp list, затем opencode mcp debug <name> | статус connected, инициализация прошла | лог debug по имени сервера |
| Вызов инструмента | запрос, которому нужен инструмент | модель реально вызывает tool | запись вызова в DEBUG-логе |
Обрати внимание: opencode mcp list (алиас ls) отчитывается о статусе подключения каждого MCP-сервера независимо от состояния провайдера и модели, а opencode mcp debug <name> изолирует диагностику OAuth и соединения для одного названного сервера. Это канарейка, ограниченная слоем MCP, отдельная от opencode models и /connect. Ровно то, что нужно, чтобы отделить «модель отвечает» от «инструмент вызывается».
Минимальный кастомный провайдер для формы /v1/chat/completions выглядит так - здесь baseURL подставляешь свой, ключ уходит в auth.json, а не в этот файл:
{ "provider": { "my-route": { "npm": "@ai-sdk/openai-compatible", "options": { "baseURL": "https://api.provod.ai/v1" }, "models": { "some-model": { "limit": { "context": 32000, "output": 8000 } } } } } }
Прогон по слоям медленнее эффектного демо, где всё поднимается одной командой. Это осознанная цена: демо показывает, что связка иногда работает, а послойная канарейка показывает, где она ломается. Второе полезнее, когда ты собираешь инструмент, а не скриншот.

Где именно ломается связка: карта отказов
Теперь собери из слоёв карту отказов. Ценность у неё одна: каждый класс отказа опознаётся своим симптомом, и ты перестаёшь путать их между собой.
Первые два класса уже названы выше, и оба выдают себя именем ошибки: ProviderInitError про ключ, ProviderModelNotFoundError про ссылку на модель. Разбирать их заново незачем. Коварнее третий - форма эндпоинта. Провайдер авторизован, ключ живой, а npm-пакет указан не тот, и совместимый по виду запрос уходит в API другой формы. Именованного типа ошибки здесь нет вообще; симптом - странный или пустой ответ при рабочей авторизации.
Отдельно стоит слой модели в узком смысле - способность вызывать инструменты. По документации провайдеров OpenCode надёжность tool-calling варьируется от модели к модели даже на корректно авторизованном провайдере. Документация советует модели с сильной поддержкой вызова инструментов (называются варианты Qwen-Coder, DeepSeek-Coder) и отмечает, что некоторым локальным серверам моделей нужен увеличенный контекст, num_ctx в диапазоне 16k-32k. То есть подключённая и отвечающая модель может отказать именно на вызове инструмента - и это свойство самой модели, MCP тут ни при чём.
Честно про пробел: официальная страница troubleshooting не даёт для MCP-соединения отдельного руководства, отличного от OAuth-debug. Режимы отказа MCP помимо OAuth - кривой локальный command, недостижимый удалённый url - не описаны именованными типами ошибок так, как описаны провайдер и модель. Это реальный пробел документации, и на канарейке он значит одно: по MCP-слою ты опираешься на статус opencode mcp list и вывод opencode mcp debug. Аккуратного кода ошибки, на который можно грепнуть, тут просто нет.
Дальше карту удобнее держать таблицей маршрутизации. Смысл простой: одинаковый симптом должен всегда попадать в один и тот же слой проверки. Это страховка от «починили не то».
| Симптом или вопрос | Слой проверки | Первое действие |
|---|---|---|
| «opencode zen api могу ли подключить claude» | провайдер + форма эндпоинта | сверить npm-пакет и baseURL маршрута |
| «как подключить llama cpp к opencode» | локальный backend + модель | поднять сервер, задать num_ctx, проверить tool-calling |
| «mcp сервер для opencode» не отвечает | MCP-слой | opencode mcp debug <name> |
| модель отвечает в чате, но инструмент не вызывается | модель | взять модель с сильной поддержкой tool-calling |
| ключ принят, а ответ пустой или странный | форма эндпоинта | сверить @ai-sdk/openai-compatible против @ai-sdk/openai |
Вопрос «opencode zen api могу ли подключить claude» - типичный случай, где в одну фразу склеены источник модели и её способность работать инструментами; канарейка разводит это на два слоя. По совместимости конкретных сочетаний провайдер-модель-MCP-backend честный статус - «неизвестно до теста»: документация даёт общую вариативность tool-calling, но не матрицу совместимости на каждую комбинацию.

Локальный backend проходит ту же канарейку
Отдельный частый вопрос - как подключить llama cpp к opencode. По структуре локальный движок это тот же кастомный OpenAI-совместимый провайдер: baseURL указывает на локальный сервер, выбираешь пакет @ai-sdk/openai-compatible под форму /v1/chat/completions, вручную объявляешь лимиты токенов. Отдельно поднимаешь num_ctx до 16k-32k, если сервер режет контекст, - иначе агентные подсказки не помещаются, и вызовы инструментов сыплются не из-за MCP, а из-за окна.
Соблазн здесь - собрать всё разом: локальный сервер, кастомный провайдер, MCP и агентный сценарий. Не делай так. Сначала канарейка формы эндпоинта: один пробный completion, смотришь ответ в DEBUG-логе. Потом отдельно tool-calling выбранной локальной модели - помни, что это свойство модели, а не сервера. И только затем opencode mcp debug по MCP-серверу. Один прогон - один слой, иначе при отказе ты не отличишь узкое окно контекста от несовместимой формы API.
Способы достать сторонний ключ для чистой канарейки стоит сравнить отдельно. Локальный llama.cpp даёт полный контроль и офлайн, но перекладывает на тебя лимиты токенов, tool-calling и железо. Прямой зарубежный провайдер упирается в иностранную карту и чаще всего VPN. Российский агрегатор снимает оба барьера: provod.ai отдаёт модели по протоколу OpenAI, так что тот же блок provider из примера выше заводится после замены ключа и base URL, без правок логики клиента; поддерживаемые Anthropic-совместимые клиенты тоже подключаются. Платить можно из России рублями - картой, через СБП или по счёту, без VPN и иностранной карты, - а доступ к моделям идёт по официальным ценам провайдеров, без наценки provod.ai. Для канарейки это значит ровно одно: совместимый сторонний маршрут поднимается за минуту, и поведение своей связки ты отделяешь от поведения маршрута.
Про калибровку уверенности, чтобы не выдавать желаемое за факт. Установлено: слои можно проверять изолированными прогонами - это следует из структуры конфигурации и раздельных команд. Вероятно: послойная канарейка локализует отказ - это разумное следствие, но зависит от того, насколько чисто ты держишь «один слой на прогон». Неизвестно до теста: совместимость конкретной пары провайдер-модель с конкретным MCP-сервером и backend. И отдельная гипотеза, которую я не выдаю за установленный факт: в любой реальной сборке хотя бы один из четырёх слоёв потребует отдельной настройки. Проверяй, а не верь на слово.

Чего эта карта не решает
Карта локализует слой первого отказа - и только. Она не гарантирует совместимость со всеми моделями или всеми MCP-серверами: это по-прежнему проверяется прогоном на твоей конкретной связке. Она не заменяет чтение документации по каждому выбранному маршруту. И она ничего не может поделать с тем, что OpenCode активно развивается: у проекта есть зеркальные версии доков, а точные имена CLI-подкоманд вроде opencode mcp debug и число удерживаемых логов меняются между релизами. Поэтому фиксируй версию и дату, на которой ты гонял таблицу.
Ещё раз про границу с фактами. То, что четыре слоя существуют и падают по-разному, - внешний факт из документации. То, что их стоит канарить по одному «компонент-вход-ожидание-наблюдение», - инженерное решение, которое я отстаиваю, а не цитата. И ключевой тезис - «совместимый completion ничего не говорит про вызов инструмента» - построен на факте протокольной независимости MCP из спецификации, но конкретно как рабочий пример «успешный чат против успешного tool call» официальной документацией отдельно не разобран. Это моя инференция поверх факта, и я держу её именно такой.
FAQ
Рабочий opencode api ключ - этого достаточно для запуска агента?
Нет. Принятый ключ проходит только слой провайдера (ProviderInitError не возникает). Резолв модели, форма эндпоинта, статус MCP-сервера и способность модели вызывать инструменты - отдельные проверки.
Как быстро понять, что упал MCP, а не модель?
Прогони opencode mcp list и opencode mcp debug <name>. Они отчитываются о статусе соединения MCP-сервера независимо от провайдера и модели. Если модель отвечает в чате, а debug не показывает connected - слой MCP.
Почему модель отвечает, но не вызывает инструмент?
Надёжность tool-calling варьируется по модели даже на корректном провайдере. Документация советует модели с сильной поддержкой инструментов и увеличение num_ctx до 16k-32k для локальных серверов. Это слой модели, не MCP.
Это подходит для настройки MCP в Cursor?
Нет. Здесь про OpenCode и его opencode.json. У Cursor свой конфиг MCP; логика послойной канарейки переносима как идея, детали команд - нет.
Куда смотреть наблюдение и как не слить секрет?
DEBUG-логи в ~/.local/share/opencode/log/ (последние 10). Ключи живут в отдельном auth.json - следи, чтобы шаг логирования не затянул его содержимое в сохранённый артефакт.

provod.ai — единый AI-контур для бизнеса и команды
Рабочие пространства, отдельные аккаунты и разграничение доступа — компания централизованно управляет балансом, правами и расходами, а сотрудники не используют разрозненные личные ключи.
В одном каталоге — актуальные модели для текста и медиа: GPT от OpenAI, Claude от Anthropic, Gemini от Google, Grok от xAI, DeepSeek, Qwen, GLM, Kimi и MiniMax; для изображений — Nano Banana 2 Pro и GPT Image; для видео — последние версии Seedance, Kling, Veo и Google Omni. Также доступны модели для reasoning, поиска, документов, эмбеддингов, музыки и аудио.
Компания оплачивает запросы по ценам самих провайдеров: 1:1 и без надбавки provod.ai. Расчёты идут в рублях, для юридических лиц доступны договор, счёт и закрывающие документы.
Соберите корпоративное пространство в provod.ai: форма регистрации · цены на модели · защита данных по 152-ФЗ · реквизиты для договора
Источники
- OpenCode docs, config - структура и приоритет
opencode.json(opencode.ai/docs/config), доступ 18.07.2026. - OpenCode docs, providers - хранилище auth, выбор npm-пакета формы, вариативность tool-calling,
num_ctx(opencode.ai/docs/providers), доступ 18.07.2026. - OpenCode docs, mcp-servers - блок
mcp,typelocal/remote,enabled(opencode.ai/docs/mcp-servers), доступ 18.07.2026. - OpenCode docs, cli -
opencode mcp list/ls,opencode mcp debug(opencode.ai/docs/cli), доступ 18.07.2026. - OpenCode docs, troubleshooting -
ProviderInitError,ProviderModelNotFoundError, расположение и число логов (opencode.ai/docs/troubleshooting), доступ 18.07.2026. - Model Context Protocol, базовая спецификация - JSON-RPC 2.0, жизненный цикл, независимость от completion API (modelcontextprotocol.io/specification), доступ 18.07.2026.
