MCP ETO Travel

nyxandro/mcp-eto-travel
2 starsCommunity

Install to Claude Code

This server doesn't publish a one-line install command. Follow the setup in the source repository.

Summary

Enables searching tours on eto.travel using browser automation via Playwright. Supports finding a single tour or a categorized selection (budget, optimal, premium) based on filters like destination, departure city, nights, and month.

README.md

MCP ETO Travel

MCP-сервер для поиска туров на eto.travel через браузерную автоматизацию Playwright.

Проект подготовлен для двух сценариев использования:

  • Local / stdio — пользователь запускает MCP локально на своей машине.
  • Remote / self-hosted HTTP — пользователь поднимает MCP у себя на сервере и подключается к нему по URL.

В репозитории нет привязки к вашему серверу, IP или временному домену. Всё оформлено как универсальный self-hosted проект, который любой человек сможет развернуть у себя.

Что умеет сервер

  • ищет туры через реальный UI сайта https://eto.travel/search/
  • принимает структурированные фильтры вместо одного свободного текста
  • возвращает один тур или небольшую подборку туров
  • сообщает клиенту, что долгий поиск начался и может занять около минуты
  • просит уточнить критичные данные, если не указаны направление, город вылета или число взрослых
  • ослабляет только не-критичные фильтры (month, departureCity, nights), если строгий поиск не дал результата
  • отбрасывает нерелевантные карточки для точечных направлений вроде Сочи

Инструменты

  • find_any_tour — поиск одного подходящего тура
  • find_tour_options — поиск подборки туров с категориями:
  • budget — самый бюджетный вариант
  • optimal — самый сбалансированный вариант
  • premium — самый дорогой или комфортный вариант из найденных

Общие входные аргументы:

  • destination — обязательное направление или курорт, например Турция или Сочи
  • departureCity — город вылета, например Москва
  • adults — количество взрослых
  • nights — количество ночей или null
  • month — месяц в нормализованном виде (январь ... декабрь) или null
  • rawQuery — исходная пользовательская формулировка или null

Быстрый старт для обычного пользователя

Если человек просто хочет поставить проект у себя, у него есть два простых варианта.

Вариант 1. Локально без сервера

git clone https://github.com/nyxandro/mcp-eto-travel.git
cd mcp-eto-travel
npm install
npx playwright install chromium
npm run build

Дальше MCP можно подключать как локальный процесс.

Вариант 2. На своём сервере по URL

git clone https://github.com/nyxandro/mcp-eto-travel.git
cd mcp-eto-travel
cp .env.example .env

После этого нужно открыть .env и заменить хотя бы:

  • ALLOWED_HOSTS
  • PUBLIC_DOMAIN

Потом запуск:

docker-compose up -d --build

Health check:

curl http://127.0.0.1:3000/health

Если нужен публичный домен без порта, ставится reverse proxy вроде Nginx.

Установка для разработки

Требования:

  • Node.js 20+
  • npm 10+
  • Chromium для Playwright

Если Chromium ещё не установлен:

npx playwright install chromium

Установка:

npm install
npx playwright install chromium
npm run build

Локальный MCP для OpenCode

Запуск вручную:

node dist/index.js

Или в dev-режиме:

npm run dev

Пример OpenCode-конфига:

{
  "$schema": "https://opencode.ai/config.json",
  "mcp": {
    "eto-travel-local": {
      "type": "local",
      "command": ["node", "./dist/index.js"],
      "enabled": true,
      "timeout": 180000
    }
  }
}

Готовый пример лежит в examples/opencode.local.json.

Классический MCP-конфиг для клиентов с mcpServers:

{
  "mcpServers": {
    "eto-travel": {
      "command": "node",
      "args": ["/absolute/path/to/mcp-eto-travel/dist/index.js"]
    }
  }
}

Или:

{
  "mcpServers": {
    "eto-travel": {
      "command": ["node", "/absolute/path/to/mcp-eto-travel/dist/index.js"]
    }
  }
}

Self-hosted remote MCP по URL

1. Настройка .env

Скопируйте пример:

cp .env.example .env

Пример .env:

TRANSPORT_MODE=http
HOST=0.0.0.0
PORT=3000
MCP_PATH=/mcp
ALLOWED_HOSTS=mcp.example.com,localhost,127.0.0.1
PUBLIC_DOMAIN=mcp.example.com

Что важно заменить:

  • ALLOWED_HOSTS — сюда обязательно впишите свой домен
  • PUBLIC_DOMAIN — тоже замените на свой реальный домен

2. Запуск через Docker Compose

docker-compose up -d --build

Это поднимет:

  • MCP HTTP endpoint внутри контейнера
  • health endpoint на /health
  • основной MCP path на /mcp

3. Проверка

Локально на сервере:

curl http://127.0.0.1:3000/health

Ожидаемый ответ:

{"status":"ok"}

4. Публичный URL через Nginx

В репозитории лежит шаблон nginx.mcp-eto-travel.conf.

Он показывает, как проксировать запросы на контейнер.

Типовой итоговый endpoint будет таким:

https://mcp.example.com/mcp

Важно:

  • в server_name нужно указать свой домен
  • в .env тот же домен должен быть в ALLOWED_HOSTS

Пример OpenCode-конфига для remote режима

{
  "$schema": "https://opencode.ai/config.json",
  "mcp": {
    "eto-travel-remote": {
      "type": "remote",
      "url": "https://mcp.example.com/mcp",
      "enabled": true,
      "timeout": 180000
    }
  }
}

Готовый пример лежит в examples/opencode.remote.json.

Классический MCP-конфиг для обычных клиентов:

{
  "mcpServers": {
    "eto-travel": {
      "url": "https://mcp.example.com/mcp"
    }
  }
}

Если клиент требует явный transport:

{
  "mcpServers": {
    "eto-travel": {
      "url": "https://mcp.example.com/mcp",
      "transport": "streamable-http"
    }
  }
}

Что лежит в репозитории для удобного деплоя

  • Dockerfile — готовый образ для запуска
  • docker-compose.yml — запуск через Compose
  • .env.example — пример env-настроек
  • nginx.mcp-eto-travel.conf — шаблон reverse proxy
  • examples/opencode.local.json — локальный OpenCode-конфиг
  • examples/opencode.remote.json — remote OpenCode-конфиг

Архитектура

  • src/index.ts — entrypoint, переключает режим запуска между stdio и http
  • src/runtime/config.ts — нормализация runtime env-конфига
  • src/runtime/http-server.ts — HTTP transport для remote MCP
  • src/mcp/server.ts — регистрация MCP tools
  • src/mcp/find-any-tour.ts — single-result MCP handler
  • src/mcp/find-tour-options.ts — multi-result MCP handler
  • src/eto-travel/search-service.ts — orchestration сценария поиска
  • src/eto-travel/search-results-reader.ts — чтение нескольких карточек из выдачи
  • src/eto-travel/tour-collection.ts — категоризация budget / optimal / premium
  • src/eto-travel/search-plan.ts — fallback-план ослабления фильтров
  • src/eto-travel/tour-normalizer.ts — нормализация карточки и проверка релевантности направления
  • src/shared/query-parser.ts — нормализация направлений, месяцев и городов вылета

Примеры вызова инструментов

Один тур:

{
  "tool": "find_any_tour",
  "arguments": {
    "destination": "Турция",
    "departureCity": "Москва",
    "adults": 2,
    "nights": 7,
    "month": "июнь",
    "rawQuery": "Найди тур в Турцию из Москвы на июнь на 7 ночей для 2 взрослых"
  }
}

Подборка:

{
  "tool": "find_tour_options",
  "arguments": {
    "destination": "Турция",
    "departureCity": "Москва",
    "adults": 2,
    "nights": 7,
    "month": "июнь",
    "rawQuery": "Подбери несколько туров в Турцию из Москвы на июнь на 7 ночей для 2 взрослых"
  }
}

Пример ответа для подборки:

{
  "tours": [
    {
      "category": "budget",
      "title": "Budget Hotel",
      "price": "90 000 RUB",
      "url": "https://example.com/budget"
    },
    {
      "category": "optimal",
      "title": "Comfort Hotel",
      "price": "115 000 RUB",
      "url": "https://example.com/optimal"
    },
    {
      "category": "premium",
      "title": "Luxury Resort",
      "price": "180 000 RUB",
      "url": "https://example.com/premium"
    }
  ]
}

Проверка и разработка

npm test
npm run lint
npm run typecheck
npm run build

Проверка через Inspector для локального режима:

npx @modelcontextprotocol/inspector node ./dist/index.js

Что стоит проверить:

  • видны оба tools: find_any_tour и find_tour_options
  • single-tool возвращает одну карточку
  • multi-tool возвращает подборку из нескольких карточек, если сайт их отдал
  • при нехватке критичных данных сервер просит уточнение
  • при нерелевантной карточке сервер не подменяет курорт другим регионом

Важные нюансы

  • сайт eto.travel/search/ использует внешний виджет tourvisor.ru
  • стабильность зависит от DOM-структуры виджета и доступности стороннего контента
  • итоговая ссылка на карточку может вести не на eto.travel, а на tourcart.ru — это штатное поведение виджета
  • для долгих поисков у MCP-клиента лучше ставить timeout не меньше 180000 мс

Что публиковать на GitHub

Для публичной раздачи проекта достаточно оставить в репозитории:

  • исходный код
  • Dockerfile
  • docker-compose.yml
  • .env.example
  • nginx.mcp-eto-travel.conf
  • examples/opencode.local.json
  • examples/opencode.remote.json

И не публиковать:

  • временные IP
  • приватные dev-домены
  • локальные override-файлы под конкретный сервер

В таком виде любой пользователь сможет либо подключить локальный MCP, либо поднять remote MCP у себя почти без ручной доработки.

Related MCP servers

Browse all →