Skip to main content
Glama

検索に引っかからない場所へ

直通チケットがない場合、乗り継ぎで旅程を組み立てます。

どのサービスの検索も「AからBへのチケットはあるか」という問いにしか答えません。直通がない場合、検索結果は空になり、ユーザーは離脱してしまいます。ところが移動は可能で、必要な2枚のチケットはどちらも同じサービスで販売されています。

実際の例。 MCP Тутуでの2026年8月20日「モスクワ → ウグリチ」の検索クエリ:

search_multitransport → 0 вариантов
search_bus            → 0 вариантов
search_rail           → 0 вариантов

同じクエリに対する私たちの回答:

Москва → Ярославль   автобус 09:00 → 13:00    863 ₽
пересадка в Ярославле — 40 минут
Ярославль → Углич    автобус 13:40 → 16:25    616 ₽
                                       итого  1 479 ₽, на месте в 16:25

両方のチケットはТутуが販売しています。Тутуの検索はこのルートを決して表示しません。

仕組み

запрос «Москва → Плёс»
   ↓
MCP Туту: прямой поиск → 0 вариантов, регион «Ивановская область»
   ↓
узлы-кандидаты: справочник «регион → центр» + предложения агента
   ↓
для каждого узла: сначала плечо «узел → цель», затем «откуда → узел»
   ↓
код сводит стыковки: отбрасывает рейсы, на которые не успеть, считает запас и сумму
   ↓
карточки маршрутов

検索を制御するのはエージェントです。どの都市と日付を確認するかをエージェント自身が判断し、ユーザーはその作業の進捗を画面上のフィードとして見ることができます。しかし乗り継ぎ、価格、ランキングの計算はコードが行います。モデルは算術に触れることができません。エージェントが誤るのはまさにそこだからです。Тутуの重いレスポンスはモデルを経由しません。モデルには見つかった区間のIDと短いサマリーだけが渡され、完全なデータは直接インターフェースに送られます。

選択した日に出発できない場合、バックエンドはホテルを探すためにエージェントを追加送信します。直近の出発日を探し、待つ日数ちょうどの泊数で宿泊先を選びます。

エージェントが利用できないか制限に達した場合、インターフェースは黙って決定的検索に切り替わります。画面はどのような場合でも結果を表示します。

Related MCP server: Bay Area Transit MCP

起動

npm install
cp .env.example .env          # вписать OPENROUTER_API_KEY (необязательно)
npm run db:up                 # Postgres в Docker
npm run migrate               # схема базы
npm run warm                  # прогрев кэша реальными ответами Туту
npm run dev                   # http://localhost:3100

OPENROUTER_API_KEYはオプションです。これがない場合、都市の候補表示は無効になり、検索は地域のリファレンスで動作します。

コマンド

コマンド

説明

npm run dev

http://localhost:3100 でアプリを起動

npm run route -- Москва Углич 2026-08-20

コンソールでルートを組み立て

npm run warm

src/modules/tutu/fixtures/ からキャッシュをウォームアップ

npm run cache

現在のキャッシュ内容を表示

npm run smoke

MCP Тутуとのライブ連携を確認

npm run db:up / db:down

DockerでPostgresを起動/停止

npm run migrate

Prismaマイグレーション

npm run lint

ESLint

構造

コードはすべて src/ にあり、ルートには設定のみがあります。インターフェースは1つのフォルダにまとめられ、ロジックはファイルの種類ではなく意味ごとにモジュールに分かれています:

src/
  app/                роутинг Next: страница и три API — тонкие, только вызовы модулей
    api/agent/          агентный поиск потоком
    api/route/          детерминированный поиск (страховка)
    api/stay/           гостиницы

  frontend/           всё, что видно в браузере
    components/route/   форма, календарь, подсказки, лента, карточки, гостиницы
    hooks/              чтение потока агента, определение города
    design.ts           палитра и подписи из макета
    format.ts, geo.ts   форматирование и расстояния
    config.ts           константы интерфейса

  modules/            логика, зависимости однонаправленные: agent → routing → tutu
    tutu/               клиент MCP, кэш, типы, прокси, снятые ответы (fixtures)
    routing/            сборка маршрутов, справочники регионов и городов
    agent/              цикл, инструменты, промпт, ошибки, ретраи, состояние

  lib/                клиент Prisma

モジュール内にレイヤーがない理由 domain/、infra/、api/。そのような切り分けが正当化されるのは、数万行と15前後のドメインがある場合です。ここにあるのは1つのシナリオだけです。レイヤーを作ると、それぞれ1ファイルだけのフォルダと空の contract/ ができてしまいます。モジュールが1000行を超えたら、既存のファイルの周りにレイヤーが現れるでしょう。

MCP Тутуとの連携

接続: https://mcp.tutu.ru/mcp、streamable HTTP、認証は不要です。

これなしでは機能しない2つのエンジニアリング上の決定:

レスポンスは約26KBです。 ツールは、完全なJSONがインターフェースに渡ってカードとして描画され、言語モデルには toModelOutput による圧縮された要約だけが渡されるようにラップされています。実際の検索での測定: 26 305 → 1 971文字、93%の削減。

サーバーには厳しいレート制限があります。 50件ほどの連続リクエストで、数時間にわたってドメイン全体へのアクセスがTCPレベルで遮断されたことがあります。そのため: view: 'compact'、Postgresでのレスポンスキャッシュ、検索あたり最大2ノード、デモの前には fixtures/ から npm run warm コマンドでキャッシュをウォームアップします。サーバーが利用できない場合、画面はキャッシュにあるものを表示し、クラッシュしません。

技術スタック

Next.js 16 (App Router) · TypeScript · @ai-sdk/mcp · Prisma 7 + Postgres 18 · Tailwind 4 + shadcn/ui · OpenRouter(オプション)

ドキュメント

  • SPECIFICATION.md — 製品全体: 問題、根拠、技術、規約

  • SCREEN-SPEC.md — レイアウト用の画面仕様

  • USER-GUIDE.md — ユーザーガイド

  • fixtures/README.md — 保存されたレスポンスの内容とその目的

Related MCP Connectors

Related MCP Servers