<span id="host-a-remote-mcp-server" />

# Разместите удалённый MCP-сервер

Разверните MCP-сервер как HTTP-приложение, когда клиентам нужен удалённый URL. Этот пример обслуживает один арифметический инструмент, валидирует bearer-токен и предоставляет эндпоинт здоровья. Он использует Streamable HTTP; локальный сервер `stdio` сам по себе не может обслуживать удалённых клиентов.

<span id="before-you-start" />

## Прежде чем начать

Вам понадобятся Node.js 22, Lizard CLI, проект, в который можно сделать деплой, и MCP-клиент, принимающий настроенный bearer-токен. В примере используется `@modelcontextprotocol/sdk` 1.30.0 в режиме без сохранения состояния. Он не предоставляет OAuth-авторизацию, доступ из браузера или провайдера идентификации.

Исполняемые файлы находятся в [remote-mcp-node](https://github.com/lizard-build/docs/tree/23635ba7e162bafce75d3f6206553b3ef2c0c48e/_examples/remote-mcp-node). Используйте зафиксированный lockfile. Локальный дымовый тест проверяет инициализацию, обнаружение инструментов, вызов инструмента и отклонение без валидного токена. Проверка деплоя также должна подтвердить работу публичного прокси и TLS-пути.

<span id="run-locally" />

## Запуск локально

Из директории примера:

```bash
npm ci
npm test
node issue-token.mjs
export MCP_PUBLIC_KEY="$(cat .mcp-public-key.pem)"
export MCP_ALLOWED_HOSTS=127.0.0.1,localhost
npm start
```

Сгенерированный токен истекает через один час. Приватный ключ подписи не сохраняется. Используйте свой собственный процесс выпуска и ротации токенов для постоянного деплоя; держите его приватный ключ вне сервера.

В другом терминале:

```bash
export MCP_URL=http://127.0.0.1:8000/mcp
export MCP_TOKEN="$(cat .mcp-token)"
node client.mjs
```

Клиент проверяет инициализацию, обнаружение инструментов и результат `5`, затем печатает `MCP initialize, tools/list and tools/call passed: 5`. `/health` возвращает `ok`; запрос к `/mcp` без валидного токена возвращает `401`.

<span id="deploy-the-application" />

## Деплой приложения

Сохраните Dockerfile и lockfile примера. Из директории, содержащей их:

```bash
lizard init --name mcp-example
lizard add --service mcp
lizard domain --service mcp --json
```

Выполните вход через `lizard login`, если команда сообщает, что требуется аутентификация. `init` связывает проект; `add` создаёт именованный сервис. Команда domain назначает его хостнейм перед деплоем. Используйте возвращённый `hostname` ниже, без `https://` или пути:

```bash
lizard secrets set MCP_PUBLIC_KEY="$(cat .mcp-public-key.pem)" --service mcp
lizard secrets set MCP_ALLOWED_HOSTS=YOUR_SERVICE_HOSTNAME --service mcp
```

Задайте оба значения перед первым деплоем. Затем запустите:

```bash
lizard up --service mcp --port 8000
lizard logs --build --service mcp --json
lizard logs --service mcp --json
lizard ps --json
```

На macOS с Lizard CLI 0.3.92 используйте `COPYFILE_DISABLE=1 lizard up --service mcp --port 8000`, чтобы исключить метаданные AppleDouble из архива. Более поздний релиз CLI может включать исправление архива. Проверяйте финальное событие деплоя и публичный эндпоинт; не полагайтесь только на код выхода этой версии CLI после неудачной сборки. `server.mjs` слушает на `0.0.0.0` и читает `PORT`, с 8000 в качестве значения по умолчанию. Команда деплоя устанавливает порт сервиса в 8000. Настройте публичный ключ как многострочное значение переменной окружения; не загружайте приватный ключ подписи или файл токена.

<span id="verify-the-public-endpoint" />

## Проверьте публичный эндпоинт

Установите `MCP_URL` в `https://YOUR_SERVICE_HOSTNAME/mcp`, сохраните валидный токен в окружении клиента и запустите `node client.mjs`. Проверьте все три результата:

1. `/health` возвращает `200` по HTTPS.
2. `/mcp` отклоняет клиента без валидного токена.
3. Аутентифицированный клиент перечисляет инструменты и вызывает `add`, возвращая `5`.

Здоровый процесс сам по себе не доказывает, что MCP-рукопожатие или стриминговый ответ работают через публичный прокси.

<span id="troubleshooting" />

## Устранение неполадок

| Результат | Проверка |
|---|---|
| Процесс завершается при запуске | `MCP_PUBLIC_KEY` должен содержать публичный PEM-ключ; `MCP_ALLOWED_HOSTS` должен содержать хостнейм сервиса. |
| `401` | Токен должен использовать RS256, соответствовать issuer и audience `mcp-example` и не должен быть истёкшим. |
| `403` | Сопоставьте хостнейм запроса с `MCP_ALLOWED_HOSTS`. Браузерные источники в этом примере не включены. |
| `405` с валидным токеном | Этот stateless MCP-эндпоинт принимает протоколные запросы через POST. Используйте MCP-клиент. Браузерный GET без токена сначала возвращает `401`. |
| Локальный тест проходит, но удалённый вызов не работает | Проверьте порт, HTTPS, стриминг ответа и таймауты прокси. |

<span id="limits-and-cost" />

## Ограничения и стоимость

Этот пример не хранит пользовательские сессии или постоянные файлы в памяти сервера. Добавьте базу данных для долговременного состояния приложения и проверяйте доступ по пользователю перед раскрытием приватных инструментов. Для клиентов, требующих OAuth-обнаружение или интерактивный вход, добавьте поддерживаемого OAuth-провайдера вместо распространения этого тестового токена.

HTTP-процесс может оставаться активным между вызовами. Проверьте [цены](https://lizard.build/pricing), [лимиты](https://lizard.build/ru/docs/platform/limits) и измеренные CPU/память; пустая очередь запросов не означает отсутствие расходов.

<span id="next-steps" />

## Следующие шаги

- [Ссылки на окружение](https://lizard.build/ru/docs/variables/references)
- [Восстановление деплоя](https://lizard.build/ru/docs/concepts/deployments)
- [Руководство по MCP TypeScript SDK серверу](https://ts.sdk.modelcontextprotocol.io/server)

См. [результаты сценарийных тестов](https://lizard.build/ru/docs/guides/validation) для проверенных версий, облачных результатов и оставшихся лимитов.
