← Все статьи
Новости13 мин чтения

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

Почему рабочий chat completion в OpenCode не доказывает вызов MCP-инструмента и как канарейкой проверить провайдер, модель, MCP-сервер и локальный backend по слоям.

Обложка статьи: OpenCode API ключ и точки отказа MCP со сторонними моделями

Ты вписал ключ, 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, каждый со своим типом отказа

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

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

Карта отказов OpenCode: три именованных класса и MCP-ветвь без документированного типа ошибки

Локальный 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. И отдельная гипотеза, которую я не выдаю за установленный факт: в любой реальной сборке хотя бы один из четырёх слоёв потребует отдельной настройки. Проверяй, а не верь на слово.

Сравнительная таблица: локальный llama.cpp, прямой зарубежный провайдер и совместимый провайдер на одной канарейке

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

Карта локализует слой первого отказа - и только. Она не гарантирует совместимость со всеми моделями или всеми 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 и командной работы

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, 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.