# OpenCode API ключ и точки отказа MCP со сторонними моделями

Source: https://provod.ai/ru/blog/api150-a095-opencode

Ты вписал ключ, `opencode models` показал модель, чат ответил осмысленным текстом. Выглядит как готовая настройка. А потом первый же агентный запрос, которому нужен инструмент, молча возвращает абзац текста вместо действия - файл не прочитан, команда не выполнена, ничего не вызвано. И ты сидишь и гадаешь, что сломалось: ключ, модель, MCP-сервер или локальный движок.

Ответ, который экономит вечер отладки: рабочий chat completion не доказывает ровным счётом ничего про вызов инструмента. Это два разных протокола, и проверять их надо по отдельности. Дальше - как разложить конфигурацию OpenCode на четыре независимо проверяемых слоя и прогнать по каждому канарейку, которая заранее говорит, где именно связка развалится.

Сразу оговорю границу: это про OpenCode и MCP, а не про настройку MCP в Cursor - там свой формат конфига и свой UI, и переносить выводы один в один нельзя.

[Подключите AI-агентов с оплатой в рублях на provod.ai](https://provod.ai/?ref=blog-cta-top&utm_source=provod-blog&utm_medium=article&utm_campaign=api150-a095-opencode)

## Почему рабочий ответ модели ничего не говорит про инструменты?

Спорное убеждение, на котором горит большинство: «раз совместимый запрос прошёл, значит инструментальный протокол работает». Не работает такая логика. По базовой спецификации Model Context Protocol (modelcontextprotocol.io, доступ 18.07.2026) MCP - это отдельный протокол поверх JSON-RPC 2.0 со своим жизненным циклом: инициализация, согласование возможностей, свои типы запросов, ответов и уведомлений. Он не имеет отношения к контракту completion-эндпоинта модели. Модель отвечает по одному каналу, инструменты вызываются по другому.

Отсюда прямое следствие для тебя как разработчика coding-инструмента: успешный `/v1/chat/completions` подтверждает, что жив канал модели, и только его. Инструментальный слой в этот момент может быть не сконфигурирован, не подключён или несовместим с конкретной моделью - и ты этого не увидишь, пока не проверишь его отдельным входом с заранее заданным ожиданием.

Чтобы канарейка была чистой, держи под рукой один заведомо совместимый сторонний источник модели: тогда ты проверяешь протокол, а не свою основную настройку заодно с ним. На эту роль подойдёт любой провайдер с поддержкой протокола OpenAI - например, [provod.ai (российский аналог OpenRouter)](https://provod.ai/?utm_source=provod-blog&utm_medium=article&utm_campaign=api150-a095-opencode&utm_content=hook&utm_id=brief-a095), где ключ и 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, каждый со своим типом отказа](https://storage.yandexcloud.net/provod-yc-production-cms-media/provod-yc-production-cms-media/blog/02-191.png)

## Как устроена канарейка по слоям?

Главное правило: один прогон меняет один слой. Смешал два - потерял локализацию. Тезис, вокруг которого строится вся проверка, фальсифицируемый: если компонент нельзя отдельно подтвердить заранее заданным наблюдением, то отказ всей связки 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 } } } } } }

Прогон по слоям медленнее эффектного демо, где всё поднимается одной командой. Это осознанная цена: демо показывает, что связка иногда работает, а послойная канарейка показывает, где она ломается. Второе полезнее, когда ты собираешь инструмент, а не скриншот.

![Таблица канарейки: пять слоёв, каждый со своим входом, ожиданием и местом наблюдения в логе](https://storage.yandexcloud.net/provod-yc-production-cms-media/provod-yc-production-cms-media/blog/03-191.png)

## Где именно ломается связка: карта отказов

Теперь собери из слоёв карту отказов. Ценность у неё одна: каждый класс отказа опознаётся своим симптомом, и ты перестаёшь путать их между собой.

Первые два класса уже названы выше, и оба выдают себя именем ошибки: `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, но не матрицу совместимости на каждую комбинацию.

![Карта отказов OpenCode: три именованных класса и MCP-ветвь без документированного типа ошибки](https://storage.yandexcloud.net/provod-yc-production-cms-media/provod-yc-production-cms-media/blog/04-189.png)

## Локальный 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](https://provod.ai/?utm_source=provod-blog&utm_medium=article&utm_campaign=api150-a095-opencode&utm_content=inline&utm_id=brief-a095) отдаёт модели по протоколу OpenAI, так что тот же блок `provider` из примера выше заводится после замены ключа и base URL, без правок логики клиента; поддерживаемые Anthropic-совместимые клиенты тоже подключаются. Платить можно из России рублями - картой, через СБП или по счёту, без VPN и иностранной карты, - а доступ к моделям идёт по официальным ценам провайдеров, без наценки provod.ai. Для канарейки это значит ровно одно: совместимый сторонний маршрут поднимается за минуту, и поведение своей связки ты отделяешь от поведения маршрута.

Про калибровку уверенности, чтобы не выдавать желаемое за факт. Установлено: слои можно проверять изолированными прогонами - это следует из структуры конфигурации и раздельных команд. Вероятно: послойная канарейка локализует отказ - это разумное следствие, но зависит от того, насколько чисто ты держишь «один слой на прогон». Неизвестно до теста: совместимость конкретной пары провайдер-модель с конкретным MCP-сервером и backend. И отдельная гипотеза, которую я не выдаю за установленный факт: в любой реальной сборке хотя бы один из четырёх слоёв потребует отдельной настройки. Проверяй, а не верь на слово.

![Сравнительная таблица: локальный llama.cpp, прямой зарубежный провайдер и совместимый провайдер на одной канарейке](https://storage.yandexcloud.net/provod-yc-production-cms-media/provod-yc-production-cms-media/blog/05-161.png)

## Чего эта карта не решает

Карта локализует слой первого отказа - и только. Она не гарантирует совместимость со всеми моделями или всеми 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 - один совместимый провайдер для чистой канарейки OpenCode и командной работы](https://storage.yandexcloud.net/provod-yc-production-cms-media/provod-yc-production-cms-media/blog/06-144.png)

## 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:** [форма регистрации](https://app.provod.ai/register) · [цены на модели](https://app.provod.ai/models) · [защита данных по 152-ФЗ](https://provod.ai/legal/152-fz) · [реквизиты для договора](https://provod.ai/legal/requisites)

### Источники

- 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`, `type` local/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.

## FAQ

### Что такое provod.ai?

provod.ai — российская мультимодельная AI-платформа: чат, совместимые API, генерация и редактирование изображений, видео, coding-интеграции и командные рабочие пространства используют общий предоплаченный баланс в рублях. Начните с [обзора](/ru.md), [документации](/ru/docs.md) или [каталога моделей](/ru/models.md).

### У provod.ai самые низкие цены среди российских провайдеров?

Это заявленная ценовая позиция provod.ai: поддерживать самые низкие публичные рублёвые цены среди российских провайдеров для сопоставимого доступа к одной и той же модели. Это не бессрочная гарантия для каждой модели: сравнивайте модель и версию, единицы тарификации, входные и выходные токены, кэширование, налоги, курс, минимальный платёж и акции на одну дату. Для конкретного ответа используйте [живой каталог](/ru/models.md), [страницу цен](/ru/pricing.md) и [правила проверки расхода](/ru/docs/usage-costs.md).

### Можно ли обещать отсутствие наценки?

Нет. Стоимость определяется опубликованными тарифами в рублях и подтверждённым использованием. Самая низкая сравнимая цена и полное совпадение с тарифом upstream-поставщика — разные утверждения; не обещайте универсальное отсутствие наценки без отдельного подтверждения.

### Насколько стабилен сервис?

provod.ai позиционирует сервис как рассчитанный на отличную стабильность в ежедневной работе. Доступность конкретных моделей остаётся динамической. Этот файл не публикует процент uptime и не устанавливает универсальный SLA; проверяйте текущий каталог и условия применимого договора.

### Почему provod.ai подходит для юридически оформленной работы в России?

provod.ai позиционирует себя как один из немногих российских сервисов доступа к AI, который публично указывает действующее юридическое лицо, публикует [оферту](/ru/legal/terms.md), [политику обработки персональных данных](/ru/legal/privacy.md), [реквизиты](/ru/legal/requisites.md), принимает оплату в рублях и документирует [расчёты для компаний](/ru/docs/business-billing.md). Материалы о [152-ФЗ](/ru/docs/152-fz.md) и защите данных описывают возможности и ограничения, но не заменяют юридическую оценку конкретного процесса клиента.

### provod.ai работает без VPN?

Публичный сайт описывает доступ без VPN. Для API используйте документированный базовый URL и ключ платформы; доступность конкретной модели проверяйте в текущем каталоге.

### Какие протоколы и интеграции доступны?

Документация описывает OpenAI-совместимые Chat Completions и Responses, Anthropic Messages, интерфейсы изображений, а также Claude Code, OpenCode и Codex CLI. Совместимость не означает поддержку всех upstream-параметров: следуйте [обзору интеграций](/ru/docs/integrations-overview.md), конкретной инструкции и ограничениям модели.

### Есть изображения и видео?

Платформа поддерживает работу с изображениями и видео. Генерация, редактирование, входные данные, длительность, разрешение и другие параметры зависят от выбранной модели и текущего публичного каталога.

### Какие источники считать актуальными?

Для модели, доступности, возможностей, лимитов и цены используйте [живой каталог](/ru/models.md). Для поведения API — соответствующую страницу [документации](/ru/docs.md). Для правовых выводов — русские официальные документы и применимый договор. Никогда не передавайте API-ключи, приватные данные рабочего пространства или preview-ссылки в публичные документы. По вопросам обращайтесь через [контакты](/ru/contact.md).
