Один интерфейс клиента может скрыть, что следующий запрос уже вышел из твоей машины. Ты открываешь чат в LM Studio, дописываешь инструмент через MCP, получаешь ответ - и на глаз всё выглядит как локальная работа. А по факту часть вызовов могла уйти на удалённый сервер, и по самому окну ты этого не отличишь.
Тезис этой статьи простой и проверяемый: если команда не может по конфигурации и по журналу маршрута сказать, куда именно ушёл конкретный запрос LM Studio или его MCP-инструмента, она не доказала, что этот запрос остался локальным. Ощущение локальности - не доказательство. Доказательство - наблюдаемый маршрут.
Дальше - карта из трёх узлов (клиент, MCP, контур), два раздельных прогона вместо одного удобного смешанного профиля, и условие, при котором слово «локально» вообще можно произносить. Если тебе нужен внешний совместимый маршрут рядом с локальной моделью, его удобно закрыть через provod.ai — российский аналог OpenRouter: один API к моделям его каталога, подключаемый заменой base_url и ключа. В карте контуров этот путь с самого начала лежит на внешней стороне - со своим ключом и своей строкой в журнале.
Подключите AI-агентов с оплатой в рублях на provod.ai
Почему «один клиент» не значит «один контур»?
Спорное умолчание, с которым живёт большинство: раз это один интерфейс LM Studio, значит и контур обработки данных один. На практике клиент - это только пульт. Куда уходит запрос, решает не окно чата, а конфигурация под ним.
Начиная с LM Studio 0.3.17 (build 10) приложение умеет работать как «MCP Host» и подключается и к локальным, и к удалённым MCP-серверам через один общий файл mcp.json. Это факт из документации LM Studio (доступ 2026-07-18). Формат не разделяет два вида серверов по умолчанию - локальная запись и удалённая лежат рядом, в одном файле, в одной нотации Cursor.
Файл живёт по пути ~/.lmstudio/mcp.json на macOS и Linux и %USERPROFILE%/.lmstudio/mcp.json на Windows. LM Studio советует редактировать его через встроенный редактор во вкладке Program, а не руками. Это тоже документированное поведение LM Studio.
Отсюда первая ловушка. Когда локальный и удалённый серверы описаны в одном файле одинаковым синтаксисом, глаз перестаёт их различать. Разница между «инструмент крутится подпроцессом на твоей машине» и «инструмент дёргает чужой endpoint по сети» становится вопросом одной строки, которую легко не заметить при код-ревью конфига.
Как выглядит локальный endpoint и чем он опасен?
Сначала - самый частый практический сценарий, вокруг которого всё и путается: локальный OpenAI-совместимый сервер LM Studio. По документации он слушает на http://localhost:1234/v1. Существующий клиент на OpenAI SDK переводится на него простой заменой base_url - больше в коде клиента менять ничего не нужно.
from openai import OpenAI
# локальный контур: запрос не покидает машину client = OpenAI( base\_url="http://localhost:1234/v1", api\_key="lm-studio", # локальный сервер по умолчанию токен не проверяет )
И вот здесь прячется вторая ловушка. Раз маршрут определяется одной строкой base_url, тот же самый путь в коде можно перенаправить на нелокальную цель, не тронув ничего вокруг. Клиентский код не заметит подмены. Разработчик, читающий этот код через месяц, тоже.
Дальше - сеть. Настройка «Serve on Local Network» меняет адрес привязки сервера с 127.0.0.1 (только локальная машина) на 0.0.0.0, например через lms server start --bind 0.0.0.0. Любой bind, кроме 127.0.0.1, выставляет сервер за пределы твоей машины, и собственная документация LM Studio советует включать аутентификацию, как только это сделано.
А по умолчанию локальный сервер LM Studio токен не требует. Клиент достучится до него без учётных данных, пока оператор вручную не включит переключатель в Developer Page → Server Settings и не сгенерирует токен. Сложи два факта: bind на 0.0.0.0 плюс выключенная по умолчанию аутентификация - и «локальный» сервер оказывается открытым endpoint в сети, к которому можно прийти без ключа.

Что рисует карта «клиент - MCP - локально/внешне»?
Гадать здесь не нужно - работает карта, обещанная в интро. Каждый запрос проходит через клиент, но выходит либо в подпроцесс на твоей машине, либо в чужую сеть. Задача карты - сделать этот выбор видимым до отправки, а не после.
Здесь помогает различие транспортов из самой спецификации Model Context Protocol (доступ 2026-07-18). Она определяет два семейства с принципиально разной досягаемостью. Первое - stdio: клиент запускает сервер как локальный подпроцесс и обменивается с ним построчным JSON-RPC через stdin/stdout. Второе - Streamable HTTP: стандартный транспорт для сетевых и удалённых MCP-подключений через HTTP-endpoint по POST/GET.
Оговорка, которую важно не выдать за факт LM Studio: спецификация MCP описывает общий протокол, а не конкретную реализацию LM Studio. То, что LM Studio всегда сопоставляет «локальную запись mcp.json» именно с stdio, а «удалённую» - со Streamable HTTP, в её собственной документации отдельно не подтверждено. Это разумный вывод из связки «MCP Host + транспорты MCP», а не документированное поведение. На карте это честно помечается как вывод, а не как гарантия.
Что действительно документировано и годится в опору для карты - механизм атрибуции. Использование MCP через API LM Studio требует версии 0.4.0 и выше и поддерживает два режима определения сервера: эфемерный (задаётся прямо в запросе, без предварительного конфига) и зарегистрированный в mcp.json (постоянный). Каждый ответ на вызов инструмента несёт метаданные провайдера с именем сервера-источника. Это и есть тот крючок, за который оператор может привязать конкретный вызов к конкретному настроенному серверу.

Где смешение происходит незаметно?
Самое опасное место - установка сервера в один клик. Диплинк «Add to LM Studio» (lmstudio://add_mcp?...) несёт в себе Base64-кодированный JSON с конфигом сервера. В документации он показан на примере удалённого MCP-сервера Hugging Face с заголовком-bearer-токеном. И опубликованная документация диплинка не описывает отдельного варианта только для локального сервера. То есть сам механизм установки визуально и структурно не отделяет локальный конфиг от удалённого.
Переведи это на язык последствий. Ты вбиваешь в поиск запрос вида mcp сервер для lm studio, находишь красивую кнопку «Add to LM Studio», жмёшь - и в твой единый mcp.json ложится запись, которая на вид ничем не отличается от локальной, но по факту тянет bearer-токен и ходит в чужую сеть. Клиент покажет инструмент так же, как локальный. Развилки на экране нет.
LM Studio на этот счёт предупреждает прямо: «некоторые MCP-серверы могут выполнять произвольный код, обращаться к твоим локальным файлам и использовать твоё сетевое подключение», и советует никогда не ставить MCP-серверы из недоверенных источников. Перед выполнением вызова инструмента LM Studio показывает диалог подтверждения, где аргументы можно просмотреть и отредактировать, а разрешения «allow once» и «allow always» на каждый инструмент управляются в App Settings → Tools & Integrations.
Диалог подтверждения - хорошая последняя линия, но это ручной контроль по одному вызову. Он не заменяет разделения контуров на уровне конфигурации. Человек, кликающий «allow always» на третьей неделе, уже не читает аргументы. Поэтому граница должна стоять раньше диалога - в том, как устроены сами конфиги и секреты.

Как доказать маршрут: два раздельных прогона
Теперь метод. Замер по нему ещё не проводился: захваченного лога живого ответа для этой статьи нет, и всё, что ниже про «что покажет журнал», описывает проектируемую процедуру, а не зафиксированный результат.
Идея - заменить один удобный смешанный профиль двумя раздельными прогонами и записать маршрут каждого.
Прогон А, локальный. Отдельная конфигурация, где base_url указывает строго на http://localhost:1234/v1, а в mcp.json включены только записи локальных серверов (по разумному выводу - транспорт stdio, подпроцесс). Секрет этого контура - отдельный, а лучше его вовсе нет, потому что локальный сервер по умолчанию токен не проверяет.
Прогон Б, намеренно внешний. Другая конфигурация с явно удалённым MCP-сервером или внешним base_url. Здесь маршрут заведомо выходит наружу, и это нормально - смысл прогона в том, чтобы получить эталон «как выглядит внешний путь в журнале».
// mcp.json прогона А - только локальные записи { "mcpServers": { "fs-local": { "command": "mcp-server-filesystem", "args": ["--root", "./data"] } } }
// mcp.json прогона Б - явно внешний сервер, отдельный секрет { "mcpServers": { "remote-tool": { "url": "https://example-remote/mcp", "headers": { "Authorization": "Bearer ${EXTERNAL\_TOKEN}" } } } }
Журнал маршрута строится на документированной опоре: метаданные провайдера в ответе на вызов инструмента называют сервер-источник. Значит, по каждому проверенному вызову ты можешь отнести его к конкретному настроенному серверу и, через него, к контуру. Прогон А должен показывать только локальные источники; любой внешний источник в прогоне А - это доказанная утечка контура, а не подозрение.
Что здесь установлено, что вероятно и что неизвестно - стоит держать раздельно. Установлено: раздельные прогоны и журнал маршрута фиксируют заявленный локальный или внешний путь для проверенных запросов. Вероятно: разделение конфигураций снижает риск скрытого смешения контуров. Неизвестно: поведение клиента вне проверенных сценариев и все возможные передачи метаданных.
Локальный endpoint против внешнего API: таблица решения
Компромисс честный: две конфигурации менее удобны, чем один профиль, но они не маскируют передачу данных. Ниже - решающая таблица, по которой запрос можно отнести к контуру.
| Признак | Локальный контур | Внешний контур |
|---|---|---|
| base_url | http://localhost:1234/v1 | чужой хост/endpoint |
| Транспорт MCP (вывод) | stdio, подпроцесс | Streamable HTTP по сети |
| bind локального сервера | 127.0.0.1, только своя машина | 0.0.0.0, сервер достижим извне |
| Аутентификация | по умолчанию выкл., токена нет | внешний bearer-токен |
| Источник в метаданных | локальный сервер | удалённый сервер |
| Секрет контура | отдельный или отсутствует | отдельный, не пересекается с локальным |
Правило чтения таблицы одно: локальным считается только тот запрос, чей маршрут наблюдаемо локален по журналу. Если по конфигурации и метаданным нельзя назвать сервер-источник - строка «локально» не заполняется, и запрос по умолчанию считается неопределённым, а не безопасным.
Отсюда и нормативная позиция, которую эта статья защищает: держи конфигурации и секреты локального и внешнего сценариев полностью раздельными. Один секрет на два контура - это уже провал, потому что он делает контуры взаимозаменяемыми. Внешний путь без явной метки - тоже провал, потому что стирает границу.
Внешнему маршруту, если он всё-таки нужен рядом с локальной моделью, проще жить одним предсказуемым совместимым endpoint. Каждый лишний ключ добавляет ещё одну строку, которую придётся вручную относить к контуру. Тут удобен единый API у provod.ai: он совместим с SDK OpenAI и Anthropic - меняешь ключ и base_url, и тот же клиентский код ходит на внешний контур. Для российской команды у этого есть и денежная сторона: оплата в рублях картой РФ, СБП или по счёту, без VPN и зарубежных карт; один баланс; официальные цены моделей без наценки provod.ai. А стабильная мультиканальная маршрутизация держит запросы в работе, когда один внешний канал временно недоступен. В карте контуров этот endpoint честно ложится в колонку «внешне» - и помечать его надо именно так.
# внешний контур как явный, помеченный маршрут external = OpenAI( base\_url="https://api.provod.ai/v1", api\_key=os.environ["EXTERNAL\_TOKEN"], # секрет внешнего контура, не пересекается с локальным )

Чего это не решает
Метод честен ровно в своих границах, и границы стоит назвать вслух.
Раздельный прогон подтверждает маршрут только для тех запросов, что попали в наблюдение. Он не доказывает отсутствия всех прочих сетевых взаимодействий клиента, которые ты не снимал. Документация не говорит, логируются ли где-то по умолчанию запросы к удалённому MCP-серверу так, чтобы оператор мог их проверить; метаданные провайдера в ответе - единственный найденный документированный механизм атрибуции, и он не сверялся с живым логом ответа.
Дефолтное состояние «Serve on Local Network» (включено или выключено) в тексте документации явно не указано - подтверждён только эффект включения, смена адреса привязки. Порог версий тоже нельзя схлопывать: 0.3.17 ввёл сам MCP Host, а 0.4.0 - MCP через API с метаданными провайдера. Это два разных floor, и путать их нельзя.
И отдельно про внешний сервис. Совместимый внешний endpoint не превращается в частную или on-prem инфраструктуру: запрос, ушедший на него, не станет локальным ни при какой настройке клиента. Внешний маршрут - это внешний маршрут, и в карте контуров он остаётся снаружи.
FAQ
С какой версии вообще возможен MCP в LM Studio?
MCP Host появился в LM Studio 0.3.17 (build 10) - до неё вопроса о локальной/внешней маршрутизации ещё нет. MCP через API и метаданные провайдера в ответе требуют 0.4.0 и выше. Это по документации LM Studio, доступ 2026-07-18.
Локальный сервер LM Studio защищён паролем?
По умолчанию - нет. Он слушает http://localhost:1234/v1 и принимает запрос без учётных данных, пока ты вручную не включишь аутентификацию в Developer Page → Server Settings и не сгенерируешь токен.
Почему опасен bind 0.0.0.0?
Любой bind, кроме 127.0.0.1, выставляет сервер за пределы машины. В сочетании с выключенной по умолчанию аутентификацией это открытый endpoint. Документация LM Studio советует включать аутентификацию, как только «Serve on Local Network» активна.
Как отличить локальный вызов инструмента от внешнего?
По метаданным провайдера в ответе на вызов: они называют сервер-источник, и через него вызов относится к контуру. Это единственный документированный механизм атрибуции; проверяй его раздельными прогонами с журналом маршрута.
Можно ли доверять кнопке «Add to LM Studio»?
Диплинк несёт Base64-конфиг и не отделяет локальный вариант от удалённого структурно. Показанный в документации пример - удалённый сервер с bearer-токеном. Ставь только из доверенных источников и проверяй, в какой контур ложится запись.

provod.ai — соедините LLM и медиамодели в одном сценарии
Пусть одна модель готовит идею и промпт, другая создаёт изображение, а третья собирает видео: общий API упрощает автоматизацию цепочки и управление доступом команды.
В одном каталоге — актуальные модели для текста и медиа: 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 по официальной цене соответствующей модели.
Автоматизируйте путь от идеи до ролика: форма регистрации · цены на модели · защита данных по 152-ФЗ · API и интеграции
Источники
- LM Studio, MCP (доступ 2026-07-18): https://lmstudio.ai/docs/app/mcp - MCP Host,
mcp.json, предупреждение о безопасности и диалог подтверждения. - LM Studio, OpenAI compatibility (2026-07-18): https://lmstudio.ai/docs/developer/openai-compat -
http://localhost:1234/v1, заменаbase_url. - LM Studio, Serve on Network (2026-07-18): https://lmstudio.ai/docs/developer/core/server/serve-on-network - bind
127.0.0.1против0.0.0.0. - LM Studio, Authentication (2026-07-18): https://lmstudio.ai/docs/developer/core/authentication - токен по умолчанию выключен.
- LM Studio, MCP via API (2026-07-18): https://lmstudio.ai/docs/developer/core/mcp - 0.4.0+, эфемерный и
mcp.json-режим, метаданные провайдера. - Model Context Protocol, Transports (2026-07-18): https://modelcontextprotocol.io/specification/2025-03-26/basic/transports - stdio против Streamable HTTP.
- LM Studio, Deeplink (2026-07-18): https://lmstudio.ai/docs/app/mcp/deeplink -
lmstudio://add_mcp, Base64-конфиг. - LM Studio, blog v0.3.17 (2026-07-18): https://lmstudio.ai/blog/lmstudio-v0.3.17 - введение MCP Host.
