РуководстваЗапустите удалённый MCP-сервер

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

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

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

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

Исполняемые файлы находятся в remote-mcp-node. Используйте зафиксированный lockfile. Локальный дымовый тест проверяет инициализацию, обнаружение инструментов, вызов инструмента и отклонение без валидного токена. Проверка деплоя также должна подтвердить работу публичного прокси и TLS-пути.

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

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

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

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

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

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.

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

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

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

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

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

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

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. Настройте публичный ключ как многострочное значение переменной окружения; не загружайте приватный ключ подписи или файл токена.

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

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

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

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

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

РезультатПроверка
Процесс завершается при запуске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, стриминг ответа и таймауты прокси.

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

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

HTTP-процесс может оставаться активным между вызовами. Проверьте цены, лимиты и измеренные CPU/память; пустая очередь запросов не означает отсутствие расходов.

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

См. результаты сценарийных тестов для проверенных версий, облачных результатов и оставшихся лимитов.