Skip to main content
Glama
README.md
# Sora (空)

> **日本のWebをAIエージェントから利用するための Self-hosted MCP / REST 統合サーバー**  
> *All-in-One, Zero-Middleware Web Scraping & Japanese Life Infrastructure Engine for AI Agents*

`Sora` は、LLM や AI エージェント(Claude Desktop, Cursor, Cline, OpenCodeInterpreter, Dify など)が **日本の Web 空間と日常インフラを自由かつ安全に探索・操作するための All-in-One MCP / REST サーバー** です。

外部 DB(Redis / PostgreSQL)やメッセージキューを一切必要とせず、**ヘッドレス Chromium と日本語 CJK フォントを内包した単一コンテナ** だけで動作します。Chromium はブラウザ描画が必要になった時だけ起動し、無操作が続くと自動で閉じるため、静的取得が中心の用途では常駐メモリは 200MB 前後(実測)です。1GB 級の小さな VPS では、ブラウザ描画の同時実行数が利用可能メモリから自動で絞られます([4.4 低メモリ環境での運用](#44-低メモリ環境での運用))。

```mermaid
flowchart LR
    subgraph Clients["AI Clients / Agents"]
        Claude["Claude Desktop / Cursor"]
        Agents["LangChain / AutoGen / Dify"]
    end

    subgraph Sora["Sora All-in-One (Distroless / Bun)"]
        direction TB
        MCP["MCP Server (Streamable HTTP / SSE)"]
        REST["Hono REST API (OpenAPI 3.0)"]
        Auth["Timing-Safe Auth & SSRF Guard"]
        LRU["True LRU In-Memory Cache"]
        
        subgraph Engine["Dual Scrape Engine"]
            Fast["Static Fetch + Readability + AI Chunker"]
            Browser["Stealth Chromium + Browser DSL (Tabs/Clicks)"]
            Rho["ρSelect: Query-Bounded Fractional Optimizer"]
        end

        subgraph JP["Japan Life Infrastructure"]
            JMA["気象庁 1,805自治体 天気予報"]
            Transit["Yahoo! 路線乗換・IC運賃"]
            Yahoo["Yahoo! リアルタイム(X)/知恵袋/ニュース/画像/動画"]
        end
    end

    subgraph Web["Public Internet"]
        Sites["Web Sites / PDFs / SPAs"]
        PublicData["気象庁 / Yahoo / X"]
    end

    Clients <-->|MCP / REST| Sora
    Fast --> Sites
    Browser --> Sites
    JP --> PublicData
```

> 📖 **Web証拠選択エンジン「ρSelect v2 (Canonical Engine)」の数理理論ドキュメント**:  
> クエリ固有の数学的最適性証明書(Certificate: $LB \le \rho^* \le UB$)を備えた分数最適化エンジン「ρSelect v2」の理論解説・実測ベンチマークについては、[docs/rho_select.md](docs/rho_select.md) および LLM向けハンドオーバー仕様書 [docs/rho_select_v2_llm_handover.md](docs/rho_select_v2_llm_handover.md) をご覧ください。

---

## ⚡ 5秒で繋がる Quickstart

Sora は **MCP (Model Context Protocol)** サーバーとして動作し、Docker / Podman コンテナで起動して AI エージェントから接続します。

### ① Docker / Podman での起動
```bash
docker run -d -p 3016:8000 --name sora ghcr.io/ikenokazuki/sora:latest
```

### ② MCP 接続 (Claude Desktop / Cursor / Cline / Antigravity)
AI エージェントの設定ファイル(`claude_desktop_config.json` 等)に以下を追加するだけで接続できます。
Sora は Anthropic の Tool Search / progressive disclosure 設計原則を参考にしつつ、client-neutral MCP として独自の **CORE (13ツール) + DEFERRED (33ツール) + `search_tools`** 方式を実装しており、初期状態では 13 のコアツール(`scrape`, `search_web`, `search_deep`, `get_weather`, `search_route` 等)と `search_tools` のみを露出し、残りの 33 ツールは `search_tools` により動的にオンデマンド有効化されるため、ツール定義によるコンテキスト消費を最小限に抑えられます(全 47 ツール)。

```json
{
  "mcpServers": {
    "sora": {
      "url": "http://localhost:3016/mcp"
    }
  }
}
```

### ③ ChatGPT (Custom GPTs / Actions & Desktop MCP) での利用
- **Custom GPTs (Actions / OpenAI)**:
  1. ChatGPT の GPT Builder で「Configure」→「Actions」→「Create new action」を選択。
  2. 「Import from URL」に `http://<your-host>:3016/openapi.json` を指定すると、全 70 オペレーション(64 パス、別名を含む)が自動登録され、ChatGPT から日本の Web 検索・スクレイピング・天気・知恵袋・X速報・荷物追跡等を呼び出せます。
- **ChatGPT Desktop (MCP)**:
  `http://localhost:3016/mcp` を MCP サーバーとして指定。

### ④ LLM ネイティブ機能との共存・2層構造ツール決定フレームワーク (Zero-Refusal & Two-Tier Architecture v2.13.0+)

ChatGPT や Claude、ローカル LLM(Llama / Qwen / Ollama 等)と MCP を接続した際、**「専用ツールが見当たらないと『ツールがないため答えられません』と勝手に回答を拒絶してしまう」「スニペットだけで中途半端に推測してハルシネーションを起こす」** という課題が発生しがちです。

Sora では、**回答拒絶の完全防止(Zero-Refusal Policy)と、Google / Firecrawl のベストプラクティスを取り入れた 2 層構造ツール決定フレームワーク (v2.13.0+)** を標準実装しています:

1. **回答拒絶の全面禁止(Zero-Refusal Policy)**:
   - MCP 初期化ハンドシェイク(`initialize`)時に注入される `instructions` において、「スケジュール専用ツール、営業時間専用ツール、発売日専用ツール等がない」という理由で回答を拒絶することを厳禁としています。
2. **2層構造ツール決定フレームワーク (Two-Tier Architecture)**:
   - **Tier 1(公式専門データ直結ツール・強制呼び出し)**:
     貿易(HTS/CPSC/FDA)、日本法令・国会審議録、気象庁防災・地震・道路交通、路線乗換・フライト・標高、Xリアルタイム速報、iTunes音楽メタデータの 6 大ドメインは、モデル自前の推測を厳禁とし、必ず Sora の専用ツールを実行。
   - **Tier 2(万能深層Web検索ツール・全実世界データ調査)**:
     上記以外のあらゆる事実調査(ライブ・イベント・試合日程、新製品・発売日、営業時間・店舗情報、人物・企業の最新動向、時事ニュース、技術ドキュメント等)は、**`search_deep`(推奨一次ツール)** を呼び出し、ノイズ除去された Clean Markdown 本文まで深く読み込んで包括的・根拠ある回答を構築。
3. **Web 探索・本文取得の使い分けルール**:
   - `search_web`(formats 省略時: 高速な URL・スニペット探索)を使用し、スニペットだけで開場時間や規約などの詳細が不確定な場合は、推測で終わらせず公式 URL を `scrape` ツールで精読して本文を確認することを推奨。ただし、`search_web` に `formats: ["markdown"]` を指定して同一呼出で既に本文を取得済みである場合は、二重の `scrape` 呼び出しは不要です。深層Web+X調査には `search_deep` を使用。
4. **軽量な返却キー注記による入力・出力の分離**:
   - トークン爆発やローカル LLM の KV キャッシュ枯渇・互換性問題を引き起こす巨大な JSON 出力スキーマは避け、ツールの説明末尾に返却キー(`返却: { ... }`)を注記することで、LLM がレスポンスの構造を理解しやすくしています。

> [!TIP]
> **ChatGPT や Cursor、Cline 等の Custom Instructions(システムプロンプト)設定例**:
> もしクライアント側でさらに確実にツール呼び出しを徹底させたい場合は、以下をシステム指示に追加することを推奨します:
> ```text
> 【Sora ツール利用規約】
> 1. 専用ツールがないことを理由に回答を拒否してはならない(ライブ日程・営業時間・発売日・最新動向等は必ず search_deep または search_web でWebから能動調査すること)。
> 2. 以下の専門・公的データに関しては、自身の知識で推測せず必ず Sora MCP ツールを実行すること:
>    - 米国貿易・通関・HTSコード・FDA・CPSC規制判定: check_product_compliance, predict_hts_code, verify_hts_code, check_fda_regulated, check_cpsc_certificate
>    - 日本の法令・国会審議録: search_laws, get_law_text, search_diet_minutes
>    - 気象・防災・地震・道路交通・標高・施設・航空運航: get_weather, search_disaster_warnings, search_earthquake, search_road_traffic, get_elevation, search_poi, get_flight_status
>    - 国内交通乗換・運賃: search_route
>    - 日本のSNS速報・知恵袋・トレンド・音楽: search_realtime、公開SNS投稿: search_social_posts, fetch_social_post(REST: POST /social/search・POST /social/fetch), search_chiebukuro, search_trend, search_song, search_artist
> 3. search_web でスニペットのみ取得して詳細が不足する場合は公式URLを scrape で精読すること(ただし search_web + formats: ["markdown"] で既に本文取得済みの場合は再度の scrape は不要)。深層Web+X調査には search_deep を使用すること。
> ```

---
## Soraの由来
Soraはアイドルグループ「[君と見るそら](https://x.com/kimisora_jpn)」から引用しました。
「そら」は夜空に晴天に雨上がりに夕焼けにカラッとした夏空などいろんな「表情」があります。
リアルタイム情報や知の蓄積であるWEBもある意味で「表情」。
それをAIに「伝えて」リアルタイムで反映するという想いを込めてます。
cloud(雲)も空にあり空は世界中繋がってます。
ネット上の情報を一つのツールで「繋げる」という意味もあります。

---

## 🌟 主な特徴と強み (Why Sora?)

1. **🗾 日本の日常インフラ & Web 探索を単一 MCP で提供**:
   - 海外製ツール(Firecrawl / Tavily)では対応できない「Yahoo! 知恵袋」「X (Twitter) リアルタイム速報」「気象庁公式オープンデータ直結(全国 1,805 市区町村自動選定)」「電車乗換案内」を単一 MCP で提供。
2. **⚡ ミリ秒級の応答 & 低メモリ(2026-10-08 実測)**:
   - Bun ランタイムで、`/health` は 1ms 前後、起動から応答可能になるまで約 0.6 秒、起動直後の常駐メモリは約 160MB(静的取得後 約 200MB)。
   - ブラウザ描画(SPA 昇格・`browser_action` 等)が必要になった時だけ Chromium が起動し(描画中は合計 約 950MB)、無操作 5 分(`BROWSER_IDLE_TTL_MS`)で閉じて約 200MB に戻ります。
3. **📦 完全オールインワン & ゼロミドルウェア**:
   - Redis、PostgreSQL、外部ワーカーキュー等は一切不要。単一コンテナだけで即座に完結。
4. **🛡️ Distroless(シェルなし)& 厳格なセキュリティ**:
   - ベースイメージに `gcr.io/distroless/cc-debian12` を採用。コンテナ内に `/bin/sh`, `bash`, `curl` 等が存在せず、RCE(任意コード実行)攻撃を無力化。
   - SSRF / DNS Rebinding 遮断、定数時間比較による Timing Attack 防止、ブラウザセッション所有権分離、DoS 防御(Body Limit 10MB)を標準装備。
5. **🕹️ ステートフルなブラウザ操作 DSL**:
   - `open` → `fill` → `click` → `screenshot` → `evaluate` の複数ターン対話型ブラウザセッションを API / MCP から直接制御。
6. **⚡ 次世代スクレイピング&構造化抽出エンジン (v2.13.0+)**:
   - **BrowserContext セッション分離 & アセット高速遮断**: 常駐 Chromium におけるセッションごとの完全隔離と、不要メディア・Webフォント・3Dモデル・広告トラッカーのネットワーク層即時遮断(転送量を大幅に削減。ページにより異なる)。CSS/JS は保持しレイアウト計算と不可視要素除外を担保。
   - **本文ベースの静止検知(SPA待機)**: 固定スリープを廃止し、見えている本文(長さ・先頭/中央/末尾・画像数)が 200ms 変化しなくなった時点で完了。多言語化ウィジェット等が属性だけを書き換え続けるページで、上限まで待たない。`networkidle` が来ないページも、`load` 後 5 秒で打ち切って現在の DOM から本文を取得。
   - **イベント・パンくず・表構造化抽出**: Schema.org `Event`/`MusicEvent` の自動構造化、パンくず階層ナビゲーションパス抽出、複雑な表の結合セル(`colspan`/`rowspan`)2Dマトリクス正規化、および重要告知画像(チラシ・タイテ・図表)スコアリングを標準搭載。
   - **Clean Content Sanitizer**: プロンプトインジェクション用制御トークンや不可視ゼロ幅文字を自動無害化。
7. **🎯 ρSelect v2 (クエリ固有の最適性証明書を備えた証拠選択エンジン v2.18.0+)**:
   - **数理目的関数**: $\max_{S \subseteq V} \rho_\tau(S) = \frac{\Phi(y(S))}{\tau + \sum_{i \in S} c_i}$。連続適合スコア $r_{it} \in [0, 1]$ に対する Graded Max-Evidence 則 $y_t(S) = \max_{i \in S} r_{it}$ と座標単調効用関数 $\Phi(y)$ を最大化。
   - **Canonical Unconstrained Mode**: ハード上限 $K=3$ への依存を完全撤廃。State-Witness Sparsity 定理(高々 $m$ 候補からなる疎な最適解 $|S^*| \le m$ の存在)に基づき、目的関数が自律的に必要十分な証拠集合を選出。
   - **Safe Dominance 剪定**: コストと全要件スコアにおいてパレート劣位な候補を事前パージし、状態空間を実測で最大 52 分の 1 に劇的圧縮。
   - **二段階ハイブリッド・ソルバー**: Exact Observed-Rank DP(厳密動的計画法)と Adaptive Refinement(AR; 粗密適応的細分化)により、実測 1.89ms(旧版 9.61ms 比 約 5.1 倍 高速)で高速収束。
   - **数学的オプティマイザ証明書 (`certificate`)**: 各クエリごとに下界 $LB$・上界 $UB$・相対ギャップを厳密に保証(実測 `gap: 0.00%`、独立監査器内蔵)。
   - **補完証拠動的統合 & メタデータ排除**: 検索スニペット・ディスクリプションの自動合流、YAML Frontmatter やパンくずメタデータの自動サニタイズを完備。
   - 📖 **詳細な数理理論ドキュメント**: [docs/rho_select.md](docs/rho_select.md) / **LLMハンドオーバー仕様書**: [docs/rho_select_v2_llm_handover.md](docs/rho_select_v2_llm_handover.md)
8. **📊 検索順位の保持と取得後の証拠評価**:
   - Web検索の単一結果集合はプロバイダーの順位を保持します。複数クエリ統合は加重 RRF、Deep Search の本文・ハイライト選択は BM25 と回答値・対象との関連・日付整合性を用いて評価します。新しいページを一律に優先する設計ではありません。
9. **🛡️ Evidence-Preserving Accessibility Hints(根拠データプレーン v2.15.0+)**:
   - **Block Provenance (出所トラッキング)**: 各見出し・段落・表ブロックへ `[S1:P4 | 2026-09-01]` 形式のアンカー識別子と連番を自動付与。LLM が回答時に引用元ブロックを決定論的に特定可能。
   - **Contextual Highlights (文脈保持パッセージ)**: Dinkelbach法で選ばれた最適抽出文単体ではなく、親見出し階層(H1/H2/H3)やテーブルヘッダーを含む文脈セット(`HighlightItem`)を返し、文脈欠落ハルシネーションを防止。
   - **Evidence Diagnostics (客観的証拠診断量)**: Sora 自身が主観で「情報不足」と断定せず、クエリ基本単語網羅率(`queryCoverage`)や候補数、客観的な証拠シグナル(`weakEvidenceSignal`)を返し、上位エージェントが追加調査要否を自律判断。
   - **Candidate Discrepancies (不一致候補の対比提示)**: 日付・金額・バージョンの複数異なる候補値を検出時、勝手に1つに丸めず(Silent Resolve を完全禁止)、対比構造(`CandidateDiscrepancy`)として提示。
   - **Safe Normalization (決定論的数値正規化 & 導出履歴)**: 全角数字・漢数字「万」「億」や物理単位(km/ms)を固定規則で正規化し、導出履歴(`derivations`)を追跡。為替などの外部推測が必要な変換は行わない。
10. **🌐 最新 IR (情報検索) & RAG 理論 3大アルゴリズム (v2.16.0+)**:
   - **Lost in the Middle 対策 (U字型リオーダリング)**: スコア降順ではなく、最重要情報を「先頭」と「末尾」に配置(`1位, 3位, 5位 ... 4位, 2位`)することで、LLM の長文中央部に対する注意減衰(Attention Degradation)を緩和する配置(`reorderUFlat: true`。効果は未計測)。
   - **MMR (Maximal Marginal Relevance) 多様性選択**: Jaccard 類似度を用いた反復多様性選択により、同一内容の言い換え重複を抑え、異なる観点の重要文を幅広く採択(`diversityWeight: 0.7`)。
   - **インメモリ PRF (擬似適合フィードバック)**: 上位適合ドキュメント群の共起語から高TF-IDFな重要語彙を抽出し、クエリを自動拡張。語彙ミスマッチをミリ秒未満で補正(`enablePrf: true`)。
11. **⏳ Temporal Context Anchor (時間的文脈アンカー / 相対日時の絶対解決)**:
   - 記事の `publishedTime` を基準日(Reference Date)とし、「明日」「来週金曜」「3日前」等の相対日時表現を決定論的にパースして `[YYYY-MM-DD]` 注記を自動埋め込み&構造化返却。過去記事を未来の予定と取り違える誤りを防止(`annotateTemporal: true`)。
12. **🗜️ Smart Table Minimizer (表・スペック表のトークン圧縮)**:
   - Web 上のスペック表・料金表・比較表から、全行空欄の列、同一プレースホルダー列(`-`, `—`, `N/A`, `なし` 等)、および空行を $O(R \times C)$ のインメモリ走査で自動検知・パージ。テーブルのトークン消費を 30〜70% 削減(`minimizeTables: true`)。
13. **📦 日本主要5社+UPS・FedEx・DHL Express 荷物追跡 API & MCP ツール**:
   - 8社の追跡結果を統一スキーマで返します。認証情報が必要なキャリアで未設定の場合は `unknown` と公式追跡URLを返します。
   - 伝票番号の形式で候補を絞り、最大2社ずつ・合計4社まで照会します。配送イベントなどの根拠を確認して採用し、通信失敗は `error` として未登録の `not_found` と区別します。

---

### 📊 パフォーマンスと構成(Sora の実測値)

| 項目 | 実測値 | 計測条件 |
|---|---|---|
| `/health` 応答 | 0.6〜1.3 ms | ローカル、2026-10-08 |
| 起動 → 応答可能 | 約 0.6 秒 | `bun src/index.ts`、空の SQLite |
| 常駐メモリ(起動直後) | 約 160 MB | bun プロセスのみ(Chromium 未起動) |
| 常駐メモリ(静的取得後) | 約 195 MB | `mode: fast` でスクレイプした後 |
| 常駐メモリ(ブラウザ描画中) | 約 950 MB | bun 約 250MB + Chromium 約 700MB(7 プロセス) |
| 常駐メモリ(無操作 5 分後) | 約 200 MB | Chromium 解放後(`BROWSER_IDLE_TTL_MS`) |
| イメージサイズ | 約 1.3 GB | Bun + Chromium + 日本語フォント |
| 必要なコンテナ構成 | 単一コンテナ | Redis / PostgreSQL / ワーカーキュー不要 |
| セキュリティ設計 | Distroless(シェルなし・非 root) | `gcr.io/distroless/cc-debian12` |

> 他のスクレイピング製品(Firecrawl のセルフホスト等)とのメモリ・応答時間の数値比較は、同一条件で計測していないため掲載しません。Sora の特徴は、外部ミドルウェア不要の単一コンテナであることと、知恵袋・X・気象庁・乗換・法令など日本向けのデータ源を標準で備えていることです。

---

### ⏱️ 各エンドポイントの実測応答速度 (Measured Latency: Cold vs Cached)

実機ローカルサーバーにおける「初回取得(非キャッシュ時)」と「キャッシュヒット時」の実測レイテンシ一覧です。計測時期が異なる値を含みます(再計測した値は上の表と下の「LLM に渡る量の目安」を参照)。ネットワーク待ちが支配的な項目は、相手先の状況や出口 IP により大きく変わります。

| エンドポイント | 初回取得 (非キャッシュ時) | キャッシュ時 (2回目以降) | 処理内容・技術特徴 |
|---|:---:|:---:|---|
| `GET /health` | **0.2 〜 1.8 ms** | — | API 死活監視・ヘルスチェック(Bun 最適化) |
| `GET /weather` (気象庁天気) | **約 38 ms** | **0.4 〜 0.7 ms** | 気象庁公式 CDN(`jma.go.jp`)直結パース+1,805自治体自動選定 |
| `POST /scrape` (静的最速モード) | **約 79 ms** | **0.5 〜 1.0 ms** | Web ページの高速フェッチ+Markdown 本文抽出 |
| `POST /scrape` (SPA自動昇格 / ブラウザ描画) | **約 0.8 〜 1.3 秒** | **0.5 〜 1.0 ms** | BrowserContext一時分離+アセット遮断+DOM Quiescence(200ms静止検知)により大幅高速化 |
| `POST /transit/route` (乗換案内) | **約 390 ms** | **0.6 〜 7.0 ms** | Yahoo! 路線情報スクレイプ(最適経路・IC運賃計算) |
| `POST /search/realtime` (X速報) | **約 440 ms** | **0.6 ms** | Yahoo! リアルタイム検索(Xツイート&画像抽出) |
| `POST /search/news` (ニュース) | **約 480 ms** | **0.6 ms** | Yahoo! ニュース最新記事検索 |
| `POST /search/image` / `video` | **450 〜 550 ms** | **0.6 ms** | Yahoo! 画像・動画検索 |
| `POST /search/chiebukuro` (知恵袋) | **420 〜 500 ms** | **0.6 ms** | Yahoo! 知恵袋 Q&A 検索 |
| `POST /search/suggest` (サジェスト) | **約 820 ms** | **0.5 ms** | Yahoo! オートコンプリート関連語補完 |
| `POST /browser/action` (初回実行) | **約 1.1 秒** | — | Stealth Chromium 起動+描画+クリック+待機+スクショ+Markdown 抽出 |
| `POST /browser/action` (セッション継続) | **約 0.3 〜 0.6 秒** | — | 既存タブ(`sessionId`)上での追加アクション実行 |
| `POST /trade/compliance` (商品判定) | **約 0.6 〜 1.2 秒** | **0.5 ms** | HTS実在検証+FDA規制判定+CPSC証明書・eFiling一括診断 |
| `POST /trade/hts-predict` (HTSコード推測) | **約 0.2 〜 0.4 秒** | **0.5 ms** | 商品名・素材からの10桁HTS自動推測+関税率+多層防御ヒアリング誘導 |
| `POST /tracking` (荷物追跡) | **約 200 〜 400 ms** | **0.5 ms** | 主要8社(ヤマト・佐川・日本郵便・西濃・福山・UPS・FedEx・DHL)並行投機照会+自動判別 |

#### ⚡ 内部エンリッチメント・AI最適化処理の実測速度 (In-Memory Latency)

外部 LLM API を介さず、すべて Bun ネイティブおよび最適化アルゴリズムにより **1ミリ秒未満(< 1ms)** で完結します。

| 処理・機能 | 処理時間 (1回あたり実測値) | 特徴・アルゴリズム |
|---|:---:|---|
| **Dinkelbach法 最大情報密度パッセージ抽出** (`dinkelbachOptimalPassage`) | **0.005 ms** (`5 µs`) | 分数計画法による厳密な最適連続文探索($\max \frac{W}{L^\alpha}, \alpha=0.6$) |
| **祖先見出し階層BM25 スコアリング** (`scoreSectionsWithHierarchicalBM25`) | **0.02 ms** (`21 µs`) | 祖先全階層減衰伝播($\gamma=0.6$)+形態素バイグラム自動合成 |
| **読了時間・文字統計計算** (`calculateContentStats`) | **0.03 ms** (`31 µs`) | CJK/英単語の高速カウント&推定読了時間算出 |
| **イベント・スケジュール構造化抽出** (`extractEventsFromJsonLd`) | **0.05 ms** (`48 µs`) | Schema.org Event/MusicEvent の正規化と日時・会場・チケット解析 |
| **パンくず階層パス抽出** (`extractBreadcrumbs`) | **0.04 ms** (`42 µs`) | BreadcrumbList & nav[aria-label=breadcrumb] の自動マッピング |
| **テーブル結合セル2D正規化** (`gfmTable` / `normalizeTable`) | **0.06 ms** (`60 µs`) | colspan / rowspan のグリッド自動展開補完マトリクス |
| **Clean Content Sanitizer** (`cleanMarkdownTokens`) | **0.04 ms** (`45 µs`) | LLM 制御トークン・不可視ゼロ幅文字の安全なサニタイズ |
| **出典・引用リンク抽出** (`extractCitationsFromMarkdown`) | **0.06 ms** (`62 µs`) | 正規表現+文脈コンテキストスライシング |
| **検索結果アイテム間 動的IDF BM25+ リランキング** (`rerankSearchResults`) | **0.08 ms** (`85 µs`) | 検索結果コーパスからの動的IDF算出+タイトル/本文多信号リランキング |
| **RAG セマンティック・チャンキング** (`chunkMarkdownContent`) | **0.13 ms** (`138 µs`) | 見出し・コードブロック境界を考慮したセマンティック分割 |
| **Block Provenance 出所付与** (`assignBlockProvenance` / `formatBlockAnchor`) | **0.05 ms** (`50 µs`) | 各ブロックへの連番識別子(`[S1:P4]`)・引用アンカー付与 |
| **Evidence Diagnostics 客観的証拠診断** (`computeEvidenceDiagnostics`) | **0.05 ms** (`50 µs`) | クエリ単語網羅率($Coverage$)・証拠シグナル算出 |
| **Candidate Discrepancies 不一致候補対比** (`detectDiscrepancies`) | **0.06 ms** (`60 µs`) | 日付・金額・バージョンの複数候補検出と対比構造化 |
| **Safe Normalization 決定論的数値正規化** (`normalizeSafeNumeric`) | **0.10 ms** (`100 µs`) | 全角半角・漢数字「万」「億」・物理単位正規化と導出履歴追跡 |
| **Lost in the Middle 対策 U字型配置** (`reorderLostInTheMiddle`) | **0.001 ms** (`1 µs`) | 両端交互パッキングによる U字型シーケンス生成 |
| **MMR 多様性パッセージ選択** (`selectMaximalMarginalRelevance`) | **0.02 ms** (`20 µs`) | Jaccard 類似度を用いた類似文ペナルティ&多様性最大化 |
| **インメモリ PRF クエリ拡張** (`expandQueryWithPseudoRelevanceFeedback`) | **0.05 ms** (`50 µs`) | 上位適合文書の重要共起語による動的クエリ拡張 |
| **Temporal Context Anchor 相対日時解決** (`extractTemporalAnchors`) | **0.04 ms** (`40 µs`) | 基準日からの決定論的オフセット計算&注記付与 |
| **Smart Table Minimizer 表トークン圧縮** (`minimizeTableMatrix`) | **0.03 ms** (`30 µs`) | 空欄列・冗長記号列・空行の O(R*C) 自動パージ |
| **検索結果の重複・類似排除** (`dedupSearchResults`) | **0.33 ms** (`335 µs`) | 50件の N-gram Jaccard 類似度判定 |
| **PII 個人情報自動マスキング** (`maskPiiInText`) | **0.55 ms** (`557 µs`) | メール・電話・Luhn クレジットカード判定&置換 |
| **超高速 抽出型自動要約 (TL;DR)** (`generateExtractiveSummary`) | **0.97 ms** (`970 µs`) | TF-IDF 類似の重要文抽出アルゴリズム |
| **検索語句 Markdown 強調ハイライト** (`highlightMatches`) | **9.1 ms** | 正規表現による構文安全な `<mark>` タグ挿入 |

---

## 🏛️ 設計思想 (Design Philosophy & Principles)

`Sora` は、以下の **4つのコア設計原則** に基づいて構築されています:

1. **✂️ オッカムの剃刀(Occam's Razor & Zero-Middleware)**:
   - *「必要が無いなら多くのものを定立してはならない。要件を満たす最も単純な構成が最良の構成である。」*
   - Redis、PostgreSQL、外部キュー、重厚なマイクロサービス群を一切排除。**「単一コンテナ(All-in-One)」** だけで動作し、月800円の VPS や Raspberry Pi から数万リクエストのクラウドまで壊れずに常駐します。
2. **🛡️ ステルスと生還率のパレート最適(Stealth & Pareto Optimum)**:
   - 単に「0ms で機械的アクセス」をすれば、相手先サーバーの WAF や Cloudflare に即座に IP を BAN され、成功率は 0% に堕ちます。
   - 同一ドメインへの連続アクセス時に **150ms + Jitter(0〜100ms ゆらぎ)** を自動挿入し、タイピングにも **15〜40ms の人間的遅延** を付与。AI から見た体感速度を損なわずに **確実にデータを持ち帰る生還率** を最優先しています。
3. **🔒 ディストロレスによる堅牢なセキュリティ(Distroless by Design)**:
   - コンテナ内に `/bin/sh`, `bash`, `curl`, `apt` が存在しないため、万が一未知の脆弱性があっても攻撃者がシェルを奪取する余地(RCE: 任意コード実行)が原理的にありません。非 root 実行および厳格な SSRF 遮断を標準装備。
4. **🗾 公的オープンデータ直結・持続可能性(Sustainable & Autonomous)**:
   - 天気予報は気象庁公式オープンデータ CDN(`jma.go.jp`)へ直接アクセス。全国 1,805 市区町村名のゼロミリ秒自動解決と 30 分 LRU キャッシュにより、相手先サーバーへの負荷を最小限に抑えながら永久に自律稼働します。

---

## 1. クイックスタート

### 1.1 コンテナの起動 (Docker / Podman)

GitHub Container Registry (GHCR) から 1 コマンドで即座に起動できます:

```bash
docker run -d \
  --name sora \
  -p 3016:8000 \
  -e ENABLED_MODULES="all" \
  ghcr.io/ikenokazuki/sora:latest
```

APIキーによる認証は任意です。必要な場合のみ `-e API_KEY="..." ` を追加してください(設定時はキー必須、未設定時は認証なしで利用可能)。

> [!NOTE]
> `localhost` / `127.0.0.1` / `[::1]` からの接続は、ホスト側のポート(上の例では 3016)が何であってもそのまま使えます。LAN の IP アドレス・公開ホスト名・リバースプロキシ経由で MCP(`/mcp`・`/sse`・`/message`)へ接続する場合は、`-e SORA_ALLOWED_HOSTS="sora.example.com"` を追加してください(ブラウザ上のクライアントから接続するなら `-e SORA_ALLOWED_ORIGINS="https://sora.example.com"` も)。許可されていない Host や Origin からの接続は 403 になり、応答の `hint` に設定すべき環境変数が示されます。

### 1.2 MCP クライアント設定(Claude Desktop / Cursor / Cline / Windsurf 等)

#### Streamable HTTP 接続(推奨・標準)
設定ファイル(例: `claude_desktop_config.json` や Cursor の MCP 設定)に以下を追加します:

```json
{
  "mcpServers": {
    "sora": {
      "url": "http://localhost:3016/mcp",
      "headers": {
        "Authorization": "Bearer your-secret-api-key"
      }
    }
  }
}
```

#### SSE 接続(レガシー SSE クライアント向け)
```json
{
  "mcpServers": {
    "sora": {
      "url": "http://localhost:3016/sse",
      "headers": {
        "Authorization": "Bearer your-secret-api-key"
      }
    }
  }
}
```
*(※ API キーが未設定の場合は `headers` を省略可能です)*

---

## 2. 提供 MCP ツール一覧 (全 47 ツール / 11 のモジュール & ハイブリッド 14 コア構成)

Sora は、目的に応じて **11 個の論理モジュール(全 47 ツール)** で構成されています。環境変数 `ENABLED_MODULES`(デフォルト: `all`、または `web,browser,yahoo,life,disaster,watch,music,gov,trade,media,intel`)で有効化するカテゴリを自由にカスタマイズ可能です。

### 🔍 動的ツール発見 (Tool Search Tool: `search_tools`)
Anthropic の Tool Search / progressive disclosure 設計原則を参考にしつつ、Sora では client-neutral MCP として独自の **CORE (13ツール) + DEFERRED (33ツール) + `search_tools`** 方式を実装しています。AI エージェントが日常的・頻繁に使う代表的な 13 個のコアツールを初期有効(★ CORE)とし、残りの 33 ツールは `search_tools` によるオンデマンド動的有効化(・ DEFERRED)とすることで、1-hop の即時自律実行とコンテキストトークン消費の極小化を両立しています。

- **初期有効 (★ CORE 14 ツール: 機能 13 + search_tools)**:
  - `scrape`: Web ページ Markdown 抽出・フルページスクリーンショット(`fullPage: true`)・Shopify 等の DOM 剪定 & 在庫/価格/ブランド メタデータ抽出
  - `search_web`: 最速 1-hop Web 検索(候補 URL・スニペット即応、formats 指定で上位本文インライン取得対応)
  - `search_deep`: 深層統合検索・本文一括スクレイピング & リアルタイム速報(responseMode: full / evidence)
  - `search_social_posts`: 公開 SNS 投稿検索(Weibo 新着 / Threads・Instagram・Facebook 公開投稿)
  - `fetch_social_post`: 公開 SNS 投稿の本文・日時・反応取得
  - `search_tools`: 現在 tools/list に表示されていない追加/deferred ツールの検索・動的有効化(Tool Search Tool)
  - `check_product_compliance`: 商品統合コンプライアンス一括診断(HTSコード/FDA/CPSC/eFiling)
  - `get_weather`: 気象庁 1,805 市区町村天気予報
  - `search_route`: Yahoo! 乗換案内・IC 運賃
  - `search_chiebukuro`: Yahoo! 知恵袋 Q&A 検索
  - `search_realtime`: Yahoo! リアルタイム検索(X/Twitter 最新投稿・画像 URL 抽出)
  - `search_disaster_warnings`: 気象庁 警報・注意報
  - `search_earthquake`: 気象庁 地震情報
  - `search_laws`: e-Gov 法令キーワード検索
- **動的有効化 (・ DEFERRED 33 ツール)**:
  - `track_package`: 日米主要8社(ヤマト・佐川・郵便・西濃・福山・UPS・FedEx・DHL)荷物追跡・自動キャリア判別。米3社も含め資格情報なしで動作(米3社はステルスブラウザ取得、資格情報があれば公式API優先)
  - `inspect_image`: 画像 URL 取得 & MCP マルチモーダル視覚入力(Base64 / `ImageContent`)
  - `get_flight_status`: 羽田・成田・関空・福岡等 主要空港フライト運航状況・遅延・欠航
  - `get_elevation`: Nominatim 住所・地名の座標解決 & 国土地理院の標高(海抜)取得
  - `search_poi`: OpenPOI直結 全国施設POI検索(座標付き。338万件)
  - `search_diet_minutes`: 国会会議録 衆参本会議・委員会答弁検索
  - `predict_hts_code`: 米国 USITC 公式 HTS/HS コード自動推測・ヒアリング誘導
  - `verify_hts_code`: 米国 USITC 公式 HTS/HS コード実在検証
  - `check_fda_regulated`: 米国 FDA 規制判定
  - `check_cpsc_certificate`: 米国 CPSC 証明書 (GCC/CCC) / eFiling 義務判定
  - `browser_action`: ヘッドレス Chromium ブラウザ自動操作(クリック/入力/待機/スクショ)
  - `scrape_batch`, `map_site`, `crawl_site`, `search_image`, `search_video`, `search_news`, `search_trend`, `suggest_keywords`, `search_road_traffic`, `watch_register`, `watch_check`, `watch_list`, `watch_delete`, `search_song`, `search_artist`, `search_music`, `get_law_text`, `research_country_context`, `get_country_context`, `get_country_context_evidence`, `get_country_context_updates`, `fetch_x_post`

```
┌───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┐
│                                                         Sora - Modular MCP                                                        │
├─────────────────┬───────────────────┬──────────────────┬─────────────────┬─────────────┬───────────────┬──────────────┬───────────┤
│ 🌐 Core Web     │ 🤖 Browser Action │ 🇯🇵 Yahoo Services │ 🗾 Daily Life   │ 🚨 Disaster │ 👁️ Watch/Diff │ 🏛️ Gov / Law │ 📦 Trade  │
│ (`web`)         │ (`browser`)       │ (`yahoo`)        │ (`life`)        │(`disaster`) │ (`watch`)     │ (`gov`)      │ (`trade`) │
│ ★scrape         │ ・browser_action  │ ・search_image   │ ★search_route   │★search_     │・watch_       │★search_laws  │★check_    │
│ ★search_web     │   (クリック/入力/ │ ・search_video   │   (乗換案内)    │  disaster_  │  register     │・get_law_text│  product_ │
│ ★search_deep    │    スクショ/JS実行│ ・search_news    │ ★get_weather    │  warnings   │・watch_check  │・search_diet_│  compli-  │
│ ★search_tools   │    セッション保持)│ ★search_chie-    │   (気象庁天気)  │★search_     │・watch_list   │  minutes     │  ance     │
│ ・scrape_batch  │                   │   bukuro         │ ・search_road_  │  earthquake ├───────────────┤ (国会会議録) │・predict_ │
│ ・map_site      │                   │ ★search_realtime │   traffic (道路)│・get_       │ 🎵 Music      ├──────────────┤  hts_code │
│ ・crawl_site    │                   │ ・search_trend   │ ・get_flight_   │  elevation  │ (`music`)     │ 📷 Media     │・verify_  │
│                 │                   │ ・suggest_       │   status (航空) │ (国土地理院)│・search_song  │ (`media`)    │  hts_code │
│                 │                   │   keywords       │ ・track_package │             │・search_artist│・inspect_    │・check_   │
│                 │                   │                  │   (荷物追跡)    │             │・search_music │  image       │  fda_regu-│
│                 │                   │                  │                 │             │               │ (マルチモ    │  lated    │
│                 │                   │                  │                 │             │               │  ーダル視覚) │・check_   │
│                 │                   │                  │                 │             │               │              │  cpsc_cert│
└─────────────────┴───────────────────┴──────────────────┴─────────────────┴─────────────┴───────────────┴──────────────┴───────────┘
★ = 初期常時有効 (CORE: 14ツール: 機能 13 + search_tools) / ・ = search_tools により動的オンデマンド有効化 (DEFERRED: 33ツール)
図は 8 列の簡略表示です。Media(`inspect_image`)・Music・Intel(`research_country_context` 他 3 件)・公開 SNS(`search_social_posts` / `fetch_social_post`)の扱いは本文の一覧が正です。
```

### 🌐 Module 1: Core Web & Crawling (`ENABLED_MODULES=web`)
Web 検索と本文スクレイピング、一括並行取得、深層統合検索、動的ツール発見、サイトマップ解析、再帰クロール。

| ツール名 | 状態 | 説明 | 識別プロパティ | 主要引数 |
|---|:---:|---|---|---|
| `scrape` | **★ CORE** | 指定 URL の Web ページまたは PDF をスクレイピングし、本文をクリーンな Markdown に変換して返却します。動的・SPA サイトは DOM Quiescence(200ms静止検知)と一時 BrowserContext 分離により、不要アセットを高速遮断しながら安全に完全描画待機。イベント構造化(Schema.org Event/MusicEvent)、パンくず階層パス、テーブル結合セル(colspan/rowspan)の2D正規化、Smart Table Minimizer(空欄・冗長列自動パージ)、重要告知画像(チラシ・タイテ・図表)スコアリング、祖先見出し階層BM25(減衰係数0.6)&最新の ρSelect v2 パッセージ最適化(分数計画法による情報密度最大化と数学的オプティマイザ証明書)、U字型配置(Lost in the Middle対策)、MMR多様性選択、Temporal Context Anchor(相対日時の絶対解決)、Block Provenance出所追跡(`[S1:P4]`)・Contextual Highlights(文脈保持パッセージ)・客観的証拠診断量・不一致候補対比・決定論的数値正規化、RAGチャンキング・出典抽出・読了時間・PII保護・要約生成を完備。 | `source: "web"` | - `url` (string, 必須): 対象 URL / PDF<br>- `maxChars` (number, 任意): 最大文字数 (デフォルト: 30000)<br>- `mode` (string, 任意): `"auto"` (デフォルト), `"fast"`, `"browser"`<br>- `formats` (string[], 任意): `["markdown", "html", "rawHtml", "links", "screenshot", "jsonLd", "images", "tables"]`<br>- `onlyMainContent` (boolean, 任意): 本文のみ抽出 (デフォルト: true)<br>- `selectors` (object, 任意): ピンポイント抽出用 CSS セレクタ<br>- `extractHighlights` / `query` (任意): キーワード重要文抽出<br>- `highlightAlgorithm` (string, 任意): `"rho-select-v2"` (デフォルト: クエリ証明書付き最新最適化), `"rho-select"`<br>- `highlightOverheadTokens` (number, 任意): 固定オーバーヘッド τ (デフォルト: 96)<br>- `reorderUFlat` (boolean, 任意): U字型リオーダリング (デフォルト: false)<br>- `diversityWeight` (number, 任意): MMR多様性比率 (デフォルト: 0.7)<br>- `annotateTemporal` (boolean, 任意): 相対日時の絶対解決注記 [YYYY-MM-DD]<br>- `minimizeTables` (boolean, 任意): 表の空欄・冗長列自動パージ (デフォルト: true)<br>- `evidenceMode` (string, 任意): `"full"`, `"highlights"`, `"contextual_highlights"`<br>- `includeDiagnostics` (boolean, 任意): クエリ網羅率等の客観的証拠診断量を付与<br>- `includeDiscrepancies` (boolean, 任意): 日付・金額等の不一致候補を対比提示<br>- `safeNormalize` (boolean, 任意): 漢数字・単位の決定論的正規化と導出履歴<br>- `chunkMarkdown` (boolean, 任意): RAG 用セマンティック分割<br>- `maskPii` (boolean, 任意): 個人情報自動マスキング<br>- `verbose` (boolean, 任意): 内部詳細メタデータを含めるか |
| `search_web` | **★ CORE** | **【万能Web検索・候補探索】** Web 検索を実行し、タイトル・概要スニペット・URL を高速取得します(省略時は高速軽量検索)。`formats: ["markdown"]` などを指定した場合は上位ヒット記事をインライン取得・スクレイプし、1回の呼び出しで本文まで返却可能です。アイテム間動的コーパスIDF付きBM25+リランキングにより適合度の高い情報を上位表示。ドメイン絞り込み・除外・期間指定に対応。 MCP は `count`・`items` を最上位で返し、REST(`POST /search/web`)は `data` で包みます。 | `source: "web"` | - `query` (string, 必須): 検索キーワード<br>- `limit` (number, 任意): 取得件数 (最大: 20。formats指定時に省略した場合は5。formats未指定かつlimit省略時は軽量provider searchの既定結果件数を維持)<br>- `includeDomains` (string[], 任意): 絞り込むドメイン<br>- `excludeDomains` (string[], 任意): 除外するドメイン<br>- `updated` (string, 任意): 期間指定 (`"all"`, `"day"`, `"week"`, `"year"`)<br>- `formats` (string[], 任意): 出力形式 (例: `["markdown"]` 指定で上位ページを自動スクレイプして本文インライン返却)<br>- `maxChars` (number, 任意): formats 指定時の最大文字数<br>- `onlyMainContent` (boolean, 任意): 本文のみ抽出 (デフォルト: true) |
| `search_deep` | **★ CORE** | **【万能深層Web検索・最新事実/スケジュール/イベント調査】** Web 検索+上位サイト本文自動スクレイプ(Clean Markdown)+X/Twitterリアルタイム速報を一度にまとめて取得(Firecrawl/Tavily互換)。インメモリ PRF、U字型配置、MMR多様性選択、Temporal Context Anchor、Smart Table Minimizer、深層エビデンス駆動リランキング(`rerankByDeepEvidence`)対応。返却量を抑える場合は `responseMode` を選択可能。局所的事実で足りる場合は `evidence`、全文要約・網羅的調査・複数観点の比較・ページ全体の文脈が必要な場合は `full`(デフォルト)を使用。`evidence` で根拠が不足・曖昧な場合は `full` または `formats: ["markdown"]` で再取得できます。根拠が足りているかは、応答の `contextSufficiency` で確認できます。 | Web: `source: "web"`<br>X: `source: "x"` | - `query` (string, 必須): 検索キーワード<br>- `limit` (number, 任意): 本文取得件数 (デフォルト: 5, 最大: 20)<br>- `responseMode` (string, 任意): `"full"` (デフォルト: 全文・網羅調査重視) または `"evidence"` (局所事実・ハイライト優先)<br>- `formats` (string[], 任意): 出力フォーマット(responseMode と直交して指定可能)<br>- `scrapeContent` (boolean, 任意): 本文を含めるか (デフォルト: true)<br>- `includeRealtime` (boolean, 任意): リアルタイム検索も含めるか (デフォルト: true)<br>- `realtimeFocus` (string, 任意): X 投稿で優先する発信者。`"official"`=本人・公式(予定・告知・事実確認)、`"public"`=本人以外(評判・感想・炎上・現地の様子)。省略時はクエリの語から判定(評判・炎上・口コミなどがあれば public)<br>- `realtimeAnchor` (string, 任意, 100字まで): X 検索で守る固有名詞(クエリ中の人名・グループ名・作品名・会場名など)。クエリの語に対応すれば推定より優先し、緩和検索でこの語を落とさない。対応する語が無ければ無視して推定する<br>- `realtimeLimit` (number, 任意, 1〜100, デフォルト: 20): 返す X 投稿の上限(公式の投稿は別枠)。省いた件数は `realtime.omittedCount`。20 より大きくすると取得も増やす(Yahoo の1回の取得は最大40件)<br>- `officialAccountId` (string, 任意): 公式XアカウントID<br>- `updated` (string, 任意): 期間指定 (`"all"`, `"day"`, `"week"`, `"year"`)<br>- `noCache` (boolean, 任意): キャッシュ迂回・強制最新取得<br>- `maxChars` (number, 任意): 最大文字数 (デフォルト: 30000)<br>- `includeMedia` (boolean, 任意, デフォルト: true): `false` で画像・動画の URL(X 投稿の `media`、各ページの `ogImage` と `media`、本文中の画像)を省く。画像の内容が必要な質問では省かない<br>- `highlightAlgorithm` (string, 任意): `"rho-select-v2"` (デフォルト), `"rho-select"`, `"legacy"`<br>- `reorderUFlat` / `enablePrf` / `diversityWeight` / `annotateTemporal` / `minimizeTables` (任意)<br>- `adaptiveScrape` (boolean, 任意, デフォルト: false): 証拠不足時の追加取得を許可<br>- `scrapeBudget` (number, 任意, デフォルト: 8, 最大: 20): adaptive時の取得上限<br>- `scrapeDeadlineMs` (number, 任意, 0〜120,000, デフォルト: 0=無効): 本文取得の打ち切り上限(opt-in。遅いが本文のあるページも落ちるため、待ち時間を優先する場合のみ指定)。半数のページが揃ってから5秒待っても終わらないページ、または上限に達したページは打ち切り、`deadlineExceeded: true` とスニペット代替で返す(打ち切りを発動した応答はキャッシュせず、補充取得も `adaptiveScrape` の追加取得も行わない。打ち切った取得自体は継続しキャッシュに残る)<br>- `maxTotalChars` (number, 任意, 1,000〜500,000): 全結果の本文 Markdown 合計の上限。上位ほど多く配分し、超過分は段落境界で切り詰めて `markdownTruncated: {totalChars, keptChars}` を付与(`highlights` は削らない。切り詰めのとき本文の塊を先に残し、ナビの塊(短いラベルのリンクだけの塊)を先に落とす。未指定なら制限なし) |
| `search_tools` | **★ CORE** | **【追加ツール検索・動的有効化】** 現在 tools/list に表示されていない Sora の追加/deferred ツール(荷物追跡・音楽メタデータ・国会会議録・フライト運航状況・米国輸出通関詳細等)をキーワード検索し、現在の MCP セッション内で即座に有効化します。すでに tools/list に表示されているツール(天気・乗換・知恵袋・X速報等)は直接呼び出してください。サーバー設定で無効化されたモジュールのツールは search_tools では復活しません。 | - | - `query` (string, 必須): 検索キーワードまたはカテゴリ名 (例: `"荷物追跡"`, `"ヤマト"`, `"音楽"`, `"国会"`, `"trade"`, `"life"`) |
| `scrape_batch` | ・ DEFERRED | 複数の Web ページ URL を指定し、ドメインスロットリングを維持しながら高速に並行スクレイピングして一括返却します。 | `source: "web"` | - `urls` (string[], 必須): スクレイピング対象 URL 配列 (最大20件)<br>- `concurrency` (number, 任意): 並行ワーカー数 (デフォルト: 3, 最大: 5)<br>- `reorderUFlat` / `diversityWeight` / `annotateTemporal` / `minimizeTables` (任意) |
| `map_site` | ・ DEFERRED | 指定した Web サイトの sitemap.xml や内部リンクを探索し、サイト内の全 URL 一覧(サイトマップ)を高速抽出します。 | - | - `url` (string, 必須): 対象のベース URL<br>- `limit` (number, 任意): 取得件数 (デフォルト: 200, 最大: 1000) |
| `crawl_site` | ・ DEFERRED | 指定した URL 配下のページを再帰的にクロールし、複数ページの本文を一括収集します。 | `source: "web"` | - `url` (string, 必須): クロール開始 URL<br>- `maxPages` (number, 任意): 最大取得ページ数 (デフォルト: 10, 最大: 50)<br>- `maxDepth` (number, 任意): 最大リンク深度 (デフォルト: 2)<br>- `reorderUFlat` / `diversityWeight` / `annotateTemporal` / `minimizeTables` (任意) |
---

### 💡 LLM / Agent 連携時のベストプラクティス & `limit` 調整ガイド

遅延ツールは `search_tools` で有効化すると、正式名(例: `search_trend`)と LibreChat 互換名(`default.search_trend`)が公開されます。初期公開は14ツールで、有効化した遅延ツールごとに2定義が追加されます。通常は正式名を使用してください。カテゴリ名を指定した検索は、そのカテゴリの全ツールを対象にします。

有効化状態はMCPセッションごとに分離されます。`initialize` の応答で受け取った `Mcp-Session-Id` を後続の要求に付けると、そのセッション内で追加ツールを利用できます。同じAPIキーを使う別接続や、別の匿名接続には引き継がれません。切断・セッション期限切れ・再接続後は `search_tools` で再度有効化してください。セッションIDを持つ要求は、作成時と同じAPIキー(匿名の場合は匿名接続)で送信してください。

セッションIDを付けない単発要求では有効化状態を保存せず、`tools/list` は初期公開の14ツールを返します。既知の遅延ツール名と入力スキーマを使った `tools/call` は、その要求内だけで実行できます(`default.` 互換名も対応)。`search_tools` の呼び出しは後続の別要求の一覧を変更しません。どちらの接続方式でも無効モジュールのツールは利用できません。`SORA_DEFER_TOOLS=false` は従来どおり正式名の全47ツールを公開します。

エージェントや RAG アプリケーションで Web 検索・スクレイピング・クロールを活用する際、取得件数(`limit`)の設定によってレイテンシや回答品質が大きく変化します。

#### 1. 取得件数を増やすメリット・デメリット

| 項目 | メリット | デメリット・リスク | 推奨設定 |
| :--- | :--- | :--- | :--- |
| **統合深層検索 (`/search`)** | より幅広いソースから情報を網羅できる。 | ・**レイテンシ増大**: 10〜20 サイトを並行取得すると応答時間が 5〜15 秒に遅延。<br>・**LLM コンテキスト肥大化**: 大量の全文を渡すとトークン消費が増大し、重要情報が埋もれる(*Lost in the Middle* 現象)。 | デフォルト `5`<br>(最大 `20`) |
| **サイト内クロール (`/crawl`)** | ドキュメント全体の網羅的なナレッジ収集が可能。 | ・**時間・リソース消費**: ページ数に比例して処理時間が増大。 | デフォルト `10`<br>(最大 `50`) |
| **サイトマップ探索 (`/map`)** | サイト全体の構造を瞬時に把握可能。 | ・テキスト処理のみのため負荷は極めて小さい。 | デフォルト `200`<br>(最大 `1000`) |

#### 2. 最も高精度な LLM 活用のベストプラクティス
> [!TIP]
> **より効果的なアプローチ**:
> 1. **スニペットと全文の使い分け**: 検索スニペット(`search_web`)自体は **10〜20 件** 返して概要を広く把握しつつ、全文スクレイプ対象(`search_deep` の `limit`)は **上位 3〜5 件に絞る** のが最も高速かつ高精度です。
> 2. **ρSelect v2 (クエリ固有の最適性証明書を備えた証拠選択エンジン)**: `extractHighlights: true`(`query` 指定)を有効化すると、最新の **ρSelect v2**($\max_{S \subseteq V} \frac{\Phi(y(S))}{\tau + \sum_{i \in S} c_i}$、Graded Max-Evidence 連続スコアリング、Safe Dominance 剪定、Exact Observed-Rank DP / Adaptive Refinement 二段階ソルバー、検索スニペット・ディスクリプション補完証拠融合)が作動します。LLM は長いページ全体を読む代わりに**クエリに関連する最も情報密度の高い段落・センテンス区間のみを自律的に選出して集中して読める**ため、ハルシネーションを防止しつつ不要トークンを大幅に削減できます。さらに W3C 標準の `textFragmentUrl`(`#:~:text=...`)が自動生成され、ブラウザや `browser_action` が該当位置へ即座に自動スクロール・反転表示します(完全インメモリ、実測 1.89ms で超高速動作)。各クエリごとに大域的最適性を数学的に保証する証明書(`certificate`: $LB \le \rho^* \le UB$、実測 `relativeGap: 0.00%`)が返却されます。詳細な理論は [docs/rho_select.md](docs/rho_select.md)、LLM連携ハンドオーバー仕様は [docs/rho_select_v2_llm_handover.md](docs/rho_select_v2_llm_handover.md) を参照。
> 3. **Evidence-Preserving Accessibility Hints(根拠データプレーン)**: `evidenceMode: "contextual_highlights"` を指定すると、ブロック単位の出所識別子(`[S1:P4 | 2026-09-01]`)と見出し階層・テーブルヘッダーを保持した構造化パッセージ(`highlightItems`)が返却されます。さらに `includeDiagnostics: true` で客観的観測量(クエリ単語網羅率 `queryCoverage` や `weakEvidenceSignal`)を付与し、`includeDiscrepancies: true` で日付・金額等の不一致候補を対比提示、`safeNormalize: true` で全角/漢数字(万)や単位の決定論的正規化と導出履歴(`derivations`)を追跡できます。LLM の自律判断を妨げず、決定論的な事実データを供給します。
> 4. **検索結果の動的コーパスIDF付きアイテム間 BM25+ リランキング & 深層エビデンス駆動リランキング**: `search_web`, `search_deep`, `search_chiebukuro` 等の検索結果は、返却されたヒットアイテム群からインメモリでドキュメント頻度 $df(t)$ と動的 IDF を算出し、タイトル(重み 3.0)と本文(重み 1.0)の BM25 TF 飽和+長さ正規化で瞬時にリランキングされます。さらに深層統合検索(`/search`, `/search/deep`)では、スクレイピング完了後に本文およびハイライトの重要クエリ単語カバレッジや ρSelect v2 エビデンススコアを再評価する**深層エビデンス駆動リランキング(`rerankByDeepEvidence`)**が自動作動し、スニペット段階の偽陽性(作詞者等のキーフレーズが本文に含まれない記事)を排除して真に回答根拠を含むソースを最上位に浮上させます。
> 5. **Google 流 説明文自動選定器 (Meta vs Body Dynamic Arbiter)**: サイト共通の固定定型文(ボイラープレート)を自動検知し、クエリ直結の動的スニペットを `description` に自動昇格。検索結果一覧(SERP)の段階で AI が 100% 正確に内容を把握できます。
> 6. **全エンドポイント共通メタデータ (Firecrawl / Tavily 互換)**: `publishedTime`(公開日時/更新日時)、`author`(著者名)、`siteName`(サイト名)を OGP / JSON-LD / HTML メタタグから自動抽出し、Frontmatter および JSON レスポンスに付与。LLM が情報の鮮度(ファクトチェック)を瞬時に判定可能。
> 7. **GFM シンタックスハイライト言語の保持**: `<pre><code class="language-python">` 等からプログラミング言語名を正確に識別し、Markdown 出力時に ` ```python ` として再現。
> 8. **自動トークン圧縮 & ノイズ除去**: 空リンク、無効な JavaScript リンク、不要な重複空行を自動クレンジング(`cleanMarkdownTokens`)し、Cookie 同意バナー(OneTrust / Cookiebot 等)も完全パージするため、LLM コンテキストを常にクリーンに保ちます。
> 9. **robots.txt サイトマップ自動発見**: `/robots.txt` から変則配置された Sitemap URL を自動検出し、Sitemap Index を最大 1,000 件まで再帰走査。
> 10. **クロール時のストリーミング**: 多数のページを巡回する際は、`POST /crawl/stream`(SSE)を利用して 1 ページ取得完了ごとに逐次受信・処理することで、全体の完了を待たずに即座にユーザーや LLM へ中間応答を返せます。
> 11. **最新 IR 理論 3大アルゴリズム (`reorderUFlat`, `diversityWeight`, `enablePrf`)**:
>     - **U字型配置 (`reorderUFlat: true`)**: スコア降順ではなく最重要情報を「先頭」と「末尾」に配置(`1位, 3位 ... 4位, 2位`)することで、LLM の中央部注意減衰 (*Lost in the Middle*) を緩和。
>     - **MMR 多様性選択 (`diversityWeight: 0.7`)**: Jaccard 類似度ペナルティにより、同一事実の言い換え重複を排除し、異なる観点の重要文を幅広く採択。
>     - **インメモリ PRF (`enablePrf: true`)**: 上位検索結果の共起語からクエリを自動拡張し、語彙ミスマッチをミリ秒未満で自己解決。
> 12. **時間的文脈アンカー (`annotateTemporal: true`)**: 記事の公開日時(`publishedTime`)を基準日とし、「明日」「来週金曜」「3日前」などの相対日時表現を決定論的にパースして `[YYYY-MM-DD]` 注記を自動埋め込み&`temporalAnchors` 構造体を返却。過去記事を未来の予定と誤認する時間的な取り違えを防止。
> 13. **スマート表トークン圧縮 (`minimizeTables: true`, デフォルト有効)**: Web 上のスペック表・料金表・比較表から、全行空欄列、同一プレースホルダー列(`-`, `—`, `N/A`, `なし` 等)、および空行を $O(R \times C)$ で自動パージし、表のトークン消費を 30〜70% 削減。





#### 3. 実測ベンチマークとスケーラビリティ特性 (ローカル実測値)

| 処理 | 件数・ページ数 | 平均レイテンシ (ms) | スループット | 特性・備考 |
| :--- | :--- | :--- | :--- | :--- |
| **サイト内クロール** (`/crawl`) | `maxPages: 5` (旧デフォルト) | **358 ms** | 13.9 pages/sec | 3並行フェッチにより極めて高速 |
| | `maxPages: 10` (**新デフォルト**) | **341 ms** | **29.3 pages/sec** | 並行キューの効率化で旧デフォルトと同等の所要時間 |
| | `maxPages: 20` | **2,046 ms** | 9.8 pages/sec | 20ページの全文収集を約2秒で完了 |
| | `maxPages: 50` (**新上限**) | **4,685 ms** | 10.7 pages/sec | 50ページ巡回も 5秒未満で安定動作 |
| **サイトマップ探索** (`/map`) | `limit: 100` (旧デフォルト) | **826 ms** | - | XML/HTML パースのみで極めて軽量 |
| | `limit: 200` (**新デフォルト**) | **882 ms** | - | 100件時とほぼ変わらない応答速度 (+56ms) |
| | `limit: 1000` (**新上限**) | **808 ms** | - | 1,000件探索でもオーバーヘッドほぼゼロ |
| **統合深層検索** (`/search`) | `limit: 3` (旧デフォルト) | **約 1.4 秒** | - | Web検索 + 上位3件並行スクレイプ |
| | `limit: 5` (**新デフォルト**) | **約 2.0 〜 3.4 秒** | - | Web検索 + 上位5件並行スクレイプ |
| | `limit: 20` (**新上限**) | **約 4 〜 8 秒** | - | 幅広いソースのディープ調査用 |

#### 4. `search_deep` のレイテンシとコンテキスト量を調整する(2026-10-08 実測)

LLM の待ち時間は「サーバーの取得時間」と「LLM に渡る量(プロンプトの長さ)」で決まります。既定設定・`limit: 5` で 18 クエリを計測した値です(ローカル、初回取得)。

- **応答サイズ**: 平均 81KB(24〜240KB)。内訳は本文 Markdown 49%、X 投稿 31%、ハイライト 11%。
- **待ち時間**: 1.1〜14.4 秒、中央値 3.3 秒。遅いときは、最も遅い 1 ページ(ブラウザ描画に昇格したページなど)が全体を律速します。
- **`tools/list`**: 全 47 ツールで約 82KB(`outputSchema` を除外した後。除外前は約 245KB)。初期公開の 14 ツールは約 35KB です。

| 目的 | 指定するもの | 内容と注意 |
|---|---|---|
| 渡す量を上限で抑える | `maxTotalChars` | 全結果の本文合計の上限。上位ほど多く配分し、超過分は段落境界で切り詰めて `markdownTruncated` を付与(`highlights` は削らない。切り詰めのとき本文の塊を先に残し、ナビの塊を先に落とすため、ナビだけが残ることを避けられる)。実測では 60,000 で値・関連段落の欠落なし、40,000 で値の再現が平均 98%(最小 87%)、24,000 以下は一覧・比較ページの後半の値が落ちます。応答バイトの削減は 40,000 で平均 4%、24,000 で 10% 程度のため、効果が出るのは本文が大きい一部のクエリです |
| 局所的な事実だけが欲しい | `responseMode: "evidence"` | ハイライトを残し、安全条件を満たす結果だけ本文の重複返却を省略 |
| 遅いページに引きずられたくない | `scrapeDeadlineMs` | opt-in(既定は無効)。半数のページが揃ってから 5 秒待っても終わらないページ、または上限に達したページを打ち切り、`deadlineExceeded: true` とスニペット代替で返す。遅いが本文のあるページも落ちるため、待ち時間を優先する場合のみ指定 |
| 不足していれば追加取得したい | `adaptiveScrape` / `scrapeBudget` | 根拠が不足している間だけ候補を追加で取得(opt-in) |
| 足りているかを知りたい | 応答の `contextSufficiency` | 常に付与(`scrapeContent: true`)。`partial` の `reasons`(`unmentioned:語` / `unanswered:語` / `few-success`)を見て、`responseMode: "full"` での再取得や追加調査を判断できます。`no_gap_detected` は十分の保証ではありません |

まず既定のまま呼び、`contextSufficiency` が `partial` / `insufficient` のときだけ追加の手を打つ使い方を想定しています。

---

### 🤖 Module 2: Browser Actions & Automation (`ENABLED_MODULES=browser`)
フォーム入力、ボタンクリック、画面スクロール、JavaScript 実行、スクリーンショット撮影、マルチターン対話セッション。

| ツール名 | 説明 | 識別プロパティ | 主要引数 |
|---|---|---|---|
| `browser_action` | Web ページを開き、指定された一連のアクションシーケンス(クリック・文字入力・キー押下・スクロール・待機・スクショ・JS実行・ページ遷移)を実行して最終画面の Markdown や Base64 スクリーンショットを返却。ボタンの「表示テキスト指定クリック」や `sessionId` によるマルチターン対話セッション維持に対応。 | `source: "browser"` | - `url` (string, 任意): 開始/遷移 URL<br>- `sessionId` (string, 任意): 既存セッションID<br>- `createSession` (boolean, 任意): セッションを作成・維持するか<br>- `closeSession` (boolean, 任意): セッションを終了するか<br>- `actions` (array, 任意): 実行アクション一覧 (`click`, `fill`, `press`, `select`, `scroll`, `wait`, `evaluate`, `navigate`)<br>- `extract` (object, 任意): `{ markdown: true, screenshot: true, html: false }`<br>- `timeout` (number, 任意): タイムアウト ms |

---

### 🇯🇵 Module 3: Yahoo! JAPAN Services (`ENABLED_MODULES=yahoo`)
日本のメディア・Q&A・トレンド・リアルタイム情報に完全特化した検索群。

| ツール名 | 説明 | 識別プロパティ | 主要引数 |
|---|---|---|---|
| `search_image` | Yahoo! JAPAN 画像検索を実行し、画像タイトル・画像URL・サムネイル・画像サイズ・ソース元ページを取得します。 | 各アイテムに `source: "image"` | - `query` (string, 必須): 検索キーワード<br>- `limit` (number, 任意): 取得件数 (デフォルト: 20, 最大: 50) |
| `search_video` | Yahoo! JAPAN 動画検索を実行し、動画タイトル・動画URL・再生時間・配信元・サムネイルを取得します。 | 各アイテムに `source: "video"` | - `query` (string, 必須): 検索キーワード<br>- `limit` (number, 任意): 取得件数 (デフォルト: 20, 最大: 50) |
| `search_news` | Yahoo!ニュース検索を実行し、最新ニュース記事のタイトル・概要・配信社・公開日時・記事URLを取得します。 | 各アイテムに `source: "news"` | - `query` (string, 必須): 検索キーワード<br>- `limit` (number, 任意): 取得件数 (デフォルト: 10, 最大: 50) |
| `search_chiebukuro` | Yahoo!知恵袋 Q&A 検索を実行し、質問タイトル・回答数・解決ステータス・本文スニペットを取得します。アイテム間動的コーパスIDF付きBM25+リランキングによりクエリへの適合度が高いQ&Aを最上位表示。 | 各アイテムに `source: "chiebukuro"` | - `query` (string, 必須): 検索キーワード<br>- `limit` (number, 任意): 取得件数 (デフォルト: 10, 最大: 50) |
| `suggest_keywords` | Yahoo! JAPAN オートコンプリートサジェストを取得し、関連検索ワード・補完候補を返します。 | `source: "suggest"` | - `query` (string, 必須): 補完キーワード<br>- `limit` (number, 任意): 取得件数 (デフォルト: 10, 最大: 30) |
| `search_realtime` | **【必須・Web検索代替不可】** Yahoo! リアルタイム検索を実行し、X (旧 Twitter) の最新ポスト(投稿者・本文・投稿日時・メディア・URL)を取得します。アイドルのライブ出演・物販タイテ・緊急告知・現地の生の声や障害速報の調査に最適。新着順 (`recent`) と 話題順 (`popular`) の切り替えに対応。X取得はYahooのJSON直取得 (MCPバイナリ不使用)。一部失敗時は `partial: true` と `providerErrors` を付与。 MCP は `count`・`items` を最上位で返し、REST(`POST /search/realtime`)は `data` で包みます。 | 各アイテムに `source: "x"` | - `query` (string, 任意): 検索キーワード (他条件の指定時は省略可)<br>- `accountId` / `fromUser` (string, 任意): 特定アカウント (`id:xxx` に変換)<br>- `toAccount` (string, 任意): 宛先 (`@xxx` に変換)<br>- `hashtags` (string, 任意): ハッシュタグ (`#` 付与)<br>- `excludeWords` (string, 任意): 除外語 (`-` 付与)<br>- `orWords` (string[], 任意): OR検索 (`(A B)` に変換)<br>- `url` (string, 任意): URL/ドメイン (`URL:` 演算子として送信)<br>- `sort` (string, 任意): `"recent"` (新着順, デフォルト) または `"popular"` (話題順)<br>- `limit` (number, 任意): 返す投稿の上限 (デフォルト: 20, 最大: 40)。省いた件数は `omittedCount`<br>- `page` (number, 任意): ページ番号 (デフォルト: 1。Yahoo側は40件固定幅)<br>- `focus` (string, 任意): `"official"`(本人・公式を優先)または `"public"`(本人以外を優先。評判・感想・炎上の調査)。省略時はクエリの語から判定<br>- `anchor` (string, 任意, 100字まで): 守る固有名詞(クエリ中の語)。クエリの語に対応すれば推定より優先し、緩和検索でこの語を落とさない |
| `search_trend` | Yahoo リアルタイム検索の最新トレンド(急上昇キーワードランキング 20 件)を取得します。 | 各アイテムに `source: "x"` | - `limit` (number, 任意): 取得件数 (デフォルト: 20) |
| `fetch_x_post` | Xの個別投稿をステータスIDまたは投稿URLで指定して全文・投稿日時・メディアを取得(FxTwitter経由・ID突合検証済みのみ返却)。`search_realtime` で見つけた投稿の深掘り用。取得不可は明示エラー。 | `found: true` 時に `detail.text` | - `statusId` (string, 任意): 数値ステータスID<br>- `url` (string, 任意): X投稿URL(`statusId` の代わりに指定可) |

> 💡 **X (旧 Twitter) ポスト詳細・長文投稿(Note Tweet)の適応的補完**:  
> X post detail enrichment may use the third-party FxTwitter/FxEmbed public API. Only the public X status ID is sent. The integration is fail-soft and can be disabled with `SORA_X_DETAIL_PROVIDER=off`.

---

### 🗾 Module 4: Japan Daily Life & Transit (`ENABLED_MODULES=life`)
日本の公共交通・気象庁公式オープンデータに直結した生活インフラ機能。

| ツール名 | 説明 | 識別プロパティ | 主要引数 |
|---|---|---|---|
| `search_route` | 日本国内の電車乗換案内。駅間の最適ルート・所要時間・乗換回数・IC/きっぷ運賃を探索。経由駅指定(最大3駅)、日時指定、特急/新幹線利用フラグに対応。 | `source: "transit"` | - `from` (string, 必須): 出発駅名 (例「東京」)<br>- `to` (string, 必須): 到着駅名 (例「新宿」)<br>- `via` (string[], 任意): 経由駅 (最大3駅)<br>- `timeType` (string, 任意): `"departure"`, `"arrival"`, `"first_train"`, `"last_train"`<br>- `ticket` (string, 任意): `"ic"`, `"cash"`<br>- `sortBy` (string, 任意): `"time"`, `"transfer"`, `"fare"` |
| `get_weather` | 気象庁公式オープンデータ直結による日本全国各地の今日・明日・明後日および週間(最大8日間)の天気予報、予想気温、降水確率、天気概況、風・波情報を取得。全国 1,805 市区町村名の自動解決に対応。 | `source: "weather"` | - `city` (string, 必須): 市区町村名 (例「天童市」「軽井沢」「箱根」「浦安」「東京」) または 地点ID (例「130010」)<br>- `days` (number, 任意): 予報日数 (1〜8日, デフォルト: 7) |
| `search_road_traffic` | JARTIC 連携データによる日本全国の高速道路・都市高速・主要有料道路のリアルタイム道路交通情報(事故・渋滞・通行止め・車線規制・工事等)を取得。都道府県・主要高速道路の区間別詳細に対応。 | `source: "jartic"` | - `pref` (string, 任意): 都道府県名またはコード (例「東京都」「愛知県」「大阪府」「13」)<br>- `road` (string, 任意): 道路名 (例「東名高速」「首都高」「中央道」「名神高速」) |
| `get_flight_status` | 主要空港(羽田・成田・伊丹・関空・中部・新千歳・福岡・那覇等)の国内線・国際線フライトのリアルタイム運航状況、定刻、変更時刻、便名、行先、欠航・遅延ステータスおよび理由詳細を取得。 | `source: "yahoo-transit"` | - `airport` (string, 任意): 空港名またはコード (例: "羽田", "成田", "HND", "NRT", デフォルト: "羽田")<br>- `type` (string, 任意): `"departure"`(出発) または `"arrival"`(到着)<br>- `category` (string, 任意): `"domestic"`(国内線) または `"international"`(国際線)<br>- `flightNumber` (string, 任意): 便名絞り込み (例: "ANA2421", "JAL505")<br>- `keyword` (string, 任意): 行先・航空会社名絞り込み |
| `track_package` | 日本の主要運送会社(ヤマト運輸、佐川急便、日本郵便、西濃運輸、福山通運)および UPS の荷物追跡・配達状況を照会。伝票番号からのキャリア自動判別(`carrier: "auto"`)および公式追跡Webリンク生成に対応。 | `source: "tracking"` | - `trackingNumber` (string, 必須): お問い合わせ伝票番号 (ハイフン有無両対応)<br>- `carrier` (string, 任意): 運送会社コード (`"auto"`: 自動判別, `"yamato"`, `"sagawa"`, `"japanpost"`, `"seino"`, `"fukuyama"`, `"ups"`) |


---

### 🚨 Module 5: Disaster & Emergency (`ENABLED_MODULES=disaster`)
気象庁公式特別警報・気象警報・注意報および P2P地震情報 / 気象庁リアルタイム地震速報。

| ツール名 | 説明 | 識別プロパティ | 主要引数 |
|---|---|---|---|
| `search_disaster_warnings` | 気象庁公式防災情報による特別警報・気象警報・注意報(大雨、洪水、暴風、大雪、波浪、高潮、雷等)を市区町村・都道府県単位でリアルタイム取得します。 | `source: "disaster"` | - `city` (string, 任意): 市区町村名または都道府県名 (例: "東京", "新宿区", "大阪府", "福岡")<br>- `areaCode` (string, 任意): 気象庁エリアコード (6桁または2桁, 例: "130000", "130010") |
| `search_earthquake` | P2P地震情報および気象庁公式速報によるリアルタイム地震履歴(発生時刻、震源地、マグニチュード、深さ、最大震度、津波有無、各地の観測地点)を取得します。 | `source: "disaster"` | - `limit` (number, 任意): 取得件数 (1〜20, デフォルト: 5)<br>- `minIntensity` (number, 任意): 最小震度フィルター (10=震度1, 20=震度2, 30=震度3, 40=震度4, 45=震度5弱, 50=震度5強) |
| `get_elevation` | 住所・地名をNominatimで緯度経度へ解決し、国土地理院から海抜標高(m)を取得。解決先は`matchedTitle`、取得元の確認要求は`needsVerification`で確認できます。 | `source: "gsi"` | - `address` (string, 任意): 住所・地名文字列 (例: "東京都千代田区永田町1-7-1", "原宿")<br>- `lat` (number, 任意): 緯度<br>- `lon` (number, 任意): 経度<br>- `noCache` (boolean, 任意): 座標・標高を再取得 |
| `search_poi` | OpenPOI直結の全国施設POI検索。中心地名をNominatimで座標化し、周辺施設を返却。`centerResolved`で解決先・取得元・要確認フラグを確認できます。応答の`attribution`(OpenPOI API・[出典ページ](https://openpoiapi.com/attribution.html))と各`pois[].attributions`は、結果を表示・公開する際に出典として表示し、保存時は`licenses` / `attributions`を保持してください。 | `source: "openpoi"` | - `query` (string, 任意): 施設キーワード (例: "ラーメン")<br>- `center` (string, 任意): 中心地名 (例: "渋谷", "原宿")<br>- `lat` / `lon` (number, 任意, ペア指定): 中心座標。centerとは排他<br>- `radiusMeters` (number, 任意): 半径m (デフォルト: 5000)<br>- `bbox` (string, 任意): 矩形範囲 (center/radiusより優先)<br>- `limit` (number, 任意): 最大件数 (1-50)<br>- `noCache` (boolean, 任意): 地名解決を再取得 |

---

### 👁️ Module 6: Watch & Diff Monitoring (`ENABLED_MODULES=watch`)
汎用 Web ページ監視プリミティブ。URL / セレクタごとの定期差分検知、SQLite 履歴永続化、自動 Webhook 通知。

| ツール名 | 説明 | 識別プロパティ | 主要引数 |
|---|---|---|---|
| `watch_register` | Web ページの変更監視ターゲットを登録し、初期ハッシュベースラインを構築します。チケット当落、再販監視、お知らせ検知等に利用可能。 | `source: "watch"` | - `url` (string, 必須): 監視対象の Web ページ URL<br>- `title` (string, 任意): 監視ターゲットの識別用タイトル<br>- `selector` (string, 任意): ピンポイントで監視する CSS セレクタ<br>- `webhookUrl` (string, 任意): 差分検知時に通知する Webhook URL<br>- `intervalSeconds` (number, 任意): 監視インターバル目安 (秒, デフォルト: 3600) |
| `watch_check` | 登録された監視ターゲットの差分スキャンを実行し、変化の有無・ハッシュ値・スナップショットを返します。差分検知時は自動で Webhook を発火します。 MCP は `id` 指定時は結果1件、省略時は結果の配列をそのまま返し、REST(`POST /watch/check`)は `{ result }` / `{ results }` で包みます。 | `source: "watch"` | - `id` (string, 任意): 特定の監視ターゲット ID (省略時は全登録ターゲットを一括スキャン) |
| `watch_list` | 現在 SQLite に永続化されている監視ターゲットの一覧および最終チェック状態を取得します。 MCP は監視対象の配列をそのまま返し、REST(`GET /watch/list`)は `{ count, targets }` で返します。 | `source: "watch"` | - なし |
| `watch_delete` | 指定したIDの監視ターゲットをSQLiteから削除し、以後の差分監視を停止します。 | `source: "watch"` | - `id` (string, 必須): 削除する監視ターゲットのID |

---

### 🎵 Module 7: Music Metadata (`ENABLED_MODULES=music`)
iTunes 公式 Search API と連携した楽曲・アルバム・アーティストのメタデータ検索(法的リスクゼロ)。

| ツール名 | 説明 | 識別プロパティ | 主要引数 |
|---|---|---|---|
| `search_song` | iTunes Search API による曲名(楽曲タイトル)指定の楽曲メタデータ検索を実行し、高解像度ジャケット画像(600x600)、30秒試聴音源 URL、アーティスト名、リリース日、Apple Music リンク等を取得します。 | `source: "music"` | - `query` (string, 必須): 検索曲名・タイトル (例: "アイドル", "季節外れのリナリア")<br>- `country` (string, 任意): 国コード (デフォルト: "jp")<br>- `limit` (number, 任意): 取得件数 (1〜50, デフォルト: 20) |
| `search_artist` | iTunes Search API によるアーティスト名指定の音楽メタデータ検索を実行し、公式カタログの代表曲一覧、アルバム一覧、アーティスト基本情報を取得します。※ライブ・公演日程や最新の出演スケジュール・最新活動情報は `search_deep` または `search_realtime` を使用してください。 | `source: "music"` | - `query` (string, 必須): アーティスト名 (例: "君と見るそら", "CUTIE STREET")<br>- `country` (string, 任意): 国コード (デフォルト: "jp")<br>- `entity` (string, 任意): "song" (楽曲一覧), "album" (アルバム一覧), "musicArtist" (アーティスト情報) (デフォルト: "song")<br>- `limit` (number, 任意): 取得件数 (1〜50, デフォルト: 20) |
| `search_music` | iTunes Search API による楽曲・アルバム・アーティストメタデータ検索を実行します(汎用・後方互換用)。 | `source: "music"` | - `query` (string, 必須): 検索キーワード (曲名、アーティスト名、アルバム名)<br>- `country` (string, 任意): 国コード (デフォルト: "jp")<br>- `entity` (string, 任意): "song", "album", "musicArtist" (デフォルト: "song")<br>- `attribute` (string, 任意): "songTerm", "artistTerm", "albumTerm"<br>- `limit` (number, 任意): 取得件数 (1〜50, デフォルト: 20) |

---

### 🏛️ Module 8: Government & Law Data (`ENABLED_MODULES=gov`)
デジタル庁・総務省公式 e-Gov 法令 API v2 および 国立国会図書館公式 API と連携した日本の法令条文検索・国会審議発言録全文検索(完全無料・登録不要)。

| ツール名 | 説明 | 識別プロパティ | 主要引数 |
|---|---|---|---|
| `search_laws` | e-Gov 法令 API v2 によるキーワード法令検索を実行し、法令名、法令番号、公布年月日、法令種別の一覧を取得します。BM25+ 多信号リランキングにより完全一致法令を最上位表示。 | `source: "e-gov"` | - `keyword` (string, 必須): 検索キーワード (例: "著作権法", "民法")<br>- `limit` (number, 任意): 取得件数 (1〜50, デフォルト: 20) |
| `get_law_text` | e-Gov 法令 API v2 による法令条文・本文詳細取得を実行し、章・節・条・項・号が正確に構造化された Markdown 形式で返却します。 | `source: "e-gov"` | - `lawId` (string, 必須): e-Gov 法令ID (例: "129AC0000000089") |
| `search_diet_minutes` | 国立国会図書館公式 API による戦後〜最新(2026年)の衆議院・参議院本会議および全委員会の発言記録・議員答弁全文検索。立法趣旨・政治政策ファクトチェックに活用可能。 | `source: "kokkai-ndl"` | - `keyword` (string, 任意): 検索キーワード<br>- `speaker` (string, 任意): 発言者名 (例: "総理大臣")<br>- `nameOfHouse` (string, 任意): `"衆議院"` または `"参議院"`<br>- `nameOfMeeting` (string, 任意): 委員会名<br>- `from` / `until` (string, 任意): 期間 (YYYY-MM-DD)<br>- `limit` (number, 任意): 取得件数 (1〜30, デフォルト: 10) |

---

### 🚢 Module 9: Trade Compliance (`ENABLED_MODULES=trade`)
米国向け輸出入コンプライアンス判定(商品情報からのHTSコード自動推測、2026年7月 CPSC適合証明書eFiling完全義務化 & ACE免責Disclaimer判定、FDA実務PGAフラグFD1〜FD4判定、2026 HTS Revision 18・Chapter 99特別関税対応)。いずれも参考情報であり法的助言ではありません。

| ツール名 | 説明 | 識別プロパティ | 主要引数 |
|---|---|---|---|
| `predict_hts_code` | 商品名・説明文・素材・用途・対象年齢・食品接触有無から、セマンティックスコアリングと米国USITC公式API(hts.usitc.gov)を連携させた2段階ハイブリッド照合により、米国通関申告に必須となる10桁HTSコードおよび一般関税率・関連PGA規制(CPSC/FDA)を自動推測します。 | `bestMatch`, `detectedSubheading` | - `productName` (string, 必須): 商品名 (例: "Pokemon Pikachu Plush Toy")<br>- `description` (string, 任意): 詳細説明・用途<br>- `material` (string, 任意): 主素材 (例: cotton, wood, ceramic)<br>- `productCategory` (string, 任意): カテゴリ (例: toy, tableware, cosmetics, food)<br>- `targetAge` (string, 任意): `"adult"` \| `"child"` \| `"unknown"`<br>- `foodContact` (boolean, 任意): 飲食接触用途か (食器・調理器具のFD1判定分岐)<br>- `hasBattery` (boolean, 任意): 電池内蔵/同梱の有無 |
| `check_cpsc_certificate` | HTSコードと製品情報から、米国CPSC(消費者製品安全委員会)管轄品目の適合証明書(GCC/CCC)発行要否・CBP ACEへの電子申告(eFiling: 2026年7月8日より完全義務化、De Minimis免責除外なし)義務有無を判定します。非規制対象品や類似コード品に対しては通関保留エラー防止のためのACE免責申告コード(`disclaimerCodeHint: A または B`)を案内します。 | `source: "cpsc-hts-list"` | - `htsCode` (string, 必須): HTSコード (例: "9503.00.0073")<br>- `targetAge` (string, 必須): `"adult"` \| `"child"` \| `"unknown"`<br>- `material` (string, 任意): 主な素材<br>- `productCategory` (string, 任意): 製品カテゴリ補足<br>- `description` (string, 任意): 自由記述補足 |
| `check_fda_regulated` | HTSコードおよび商品情報から、米国CBP/FDA実務で機械的に用いられるPGAフラグ(FD1: 用途により該当/食品接触物質, FD2: 食品以外必須/化粧品MoCRA・医薬品・医療機器, FD3: 用途により食品, FD4: 食品必須/事前通知Prior Notice PNC確認番号必須)を判定し、必要な通関アクションとACE免責(Disclaimer)を案内します。 | `fdFlag`, `priorNoticeRequired` | - `htsCode` (string, 必須): HTSコード (例: "0902.10.10.15", "3304.99.5000")<br>- `productDescription` (string, 任意): 製品の自由記述説明<br>- `foodContact` (boolean, 任意): 食品・飲料接触用途か(食器・調理器具のFD1判定分岐) |
| `verify_hts_code` | LLM・利用者が推論したHTSコード候補を米国USITC公式データ (hts.usitc.gov) と照合し実在確認・正式品目名・一般関税率を取得します。2026 HTS Revision 18(大統領布告 PP 11059/11055)や通商法301条に基づくChapter 99特別追加関税の適用リスク・通関士確認手順もガイダンスします。 | `source: "usitc-hts"` | - `htsCode` (string, 必須): 検証したいHTSコード (例: "9503.00.0073")<br>- `productDescription` (string, 必須): 製品の説明(素材・用途・機能・加工度合い等)。コード推論の根拠を明示するため必須 |
| `check_product_compliance` | 商品ページのURL、または商品名・説明・素材・カテゴリから、HTS自動推測エンジンと連携し、HTS実在検証(関税率取得)、FDA実務PGAフラグ判定(食品・化粧品・食器等)、CPSC適合証明書(GCC/CCC)および2026年7月eFiling完全義務化判定を一連のパイプラインとして一括自動実行し、通関前アクションプランを含む総合診断レポートを返します。 | `overallStatus`, `actionPlan`, `htsPrediction` | - `url` (string, 任意): 商品ページURL (指定時は自動スクレイプ)<br>- `productName` (string, 任意): 商品名<br>- `description` (string, 任意): 商品説明・素材・用途<br>- `htsCode` (string, 任意): ユーザー指定の既知HTSコード(【LLM推測値の入力厳禁】省略時にSoraが自動推測)<br>- `targetAge` (string, 任意): `"adult"` \| `"child"` \| `"unknown"`<br>- `material` (string, 任意): 主素材<br>- `productCategory` (string, 任意): 製品カテゴリ<br>- `foodContact` (boolean, 任意): 飲食接触用途か<br>- `hasBattery` (boolean, 任意): 電池内蔵の有無 |

---

---

## 3. REST API 仕様

### 🖼️ Module 10: Media Inspection (`ENABLED_MODULES=media`)
画像の取得・解析(チラシ・時刻表・告知・ポスター等の視覚情報抽出)。`web` モジュール有効時も利用可能です。

| ツール名 | 説明 |
|---|---|
| `inspect_image` ・ DEFERRED | 画像URLから視覚情報を抽出します。`search_tools` で有効化してください。REST: `POST /media/inspect-image` |

### 🌍 Module 11: Country & Region Intelligence (`ENABLED_MODULES=intel`)
証拠基盤の国・地域コンテキスト調査。評価・推奨は含みません。詳細は「🌍 Country Intelligence」章を参照ください。

| ツール名 | 説明 |
|---|---|
| `research_country_context` ・ DEFERRED | 指定国・地域の政治・経済・安全・災害・保健・旅行等の分野横断調査。初回は代表証拠、全件はcontextId参照 |
| `get_country_context` ・ DEFERRED | 保存済みコンテキストの取得 |
| `get_country_context_evidence` ・ DEFERRED | 証拠明細の取得 |
| `get_country_context_updates` ・ DEFERRED | 更新差分の取得 |

ベース URL: `http://localhost:3016` (またはデプロイ先のドメイン URL)

> **📖 対話型 API ドキュメント & OpenAPI 仕様書**:
> - **Scalar API Reference (推奨・モダンUI)**: [`http://localhost:3016/docs`](http://localhost:3016/docs) (ダークモード・パラメータ型・制約・実行テスト対応)
> - **Swagger UI (互換用)**: [`http://localhost:3016/swagger`](http://localhost:3016/swagger)
> - **OpenAPI 3.0 仕様書 (JSON)**: [`http://localhost:3016/openapi.json`](http://localhost:3016/openapi.json)

### 3.1 ヘルスチェック & メトリクス
#### `GET /health`
```json
{
  "status": "ok",
  "service": "sora",
  "cachedEntries": 0,
  "chromiumAvailable": true,
  "yahooMcpAvailable": true,
  "mcpConnected": true,
  "timestamp": "2026-08-21T05:54:26.782Z"
}
```

#### `GET /health?detailed=true` (外部依存関係並行ヘルスチェック & アラート)
SQLite, Chromium, Yahoo, 気象庁 (JMA), P2P地震情報, e-Gov への並行疎通確認レポートを返します。SQLite 障害で degraded 判定時は `ADMIN_ALERT_WEBHOOK_URL` が設定されていれば管理者 Webhook へアラート通知を行います。
```json
{
  "status": "ok",
  "service": "sora",
  "version": "2.13.0",
  "uptimeSeconds": 1420,
  "timestamp": "2026-08-24T18:00:00.000Z",
  "dependencies": {
    "sqlite": { "status": "ok", "latencyMs": 0.4 },
    "chromium": { "status": "ok" },
    "yahooMcp": { "status": "ok" },
    "jma": { "status": "ok", "latencyMs": 85 },
    "p2pquake": { "status": "ok", "latencyMs": 92 },
    "egov": { "status": "ok", "latencyMs": 140 }
  }
}
```

#### `GET /metrics` (運用統計・キャッシュヒット率・リソース使用量)
```json
{
  "status": "ok",
  "service": "sora",
  "uptimeSeconds": 1420,
  "cache": {
    "size": 42,
    "maxSize": 3000,
    "hits": 156,
    "misses": 48,
    "hitRatio": 0.7647
  },
  "botDetection": {
    "upgradeCount": 12,
    "retryCount": 3
  },
  "activeSessions": 2,
  "chromium": {
    "available": true,
    "sharedConnected": true
  },
  "memory": {
    "rssMb": 86,
    "heapUsedMb": 34,
    "heapTotalMb": 58
  },
  "timestamp": "2026-08-22T04:20:00.000Z"
}
```

#### `GET /metrics?format=prometheus` または `Accept: text/plain` (Prometheus 監視用メトリクス)
Grafana / Prometheus 監視スタックにそのまま取り込める標準テキスト形式で出力します。
```text
# HELP sora_uptime_seconds Process uptime in seconds
# TYPE sora_uptime_seconds gauge
sora_uptime_seconds 1420
# HELP sora_memory_rss_bytes Resident set size in bytes
# TYPE sora_memory_rss_bytes gauge
sora_memory_rss_bytes 90177536
# HELP sora_cache_hits_total Total cache hits
# TYPE sora_cache_hits_total counter
sora_cache_hits_total 156
```

##### 検索 / セキュリティカウンタ一覧(`GET /metrics` の `counters` とPrometheus形式の両方に出力します。累積値のみ、ゲージは`verbose`診断参照。主要なもの)

| カウンタ | 意味 |
|---|---|
| `yahoo_request_total` | Yahooプロバイダ呼び出し回数 |
| `yahoo_429_total` | Yahoo上流の429検出回数 |
| `yahoo_circuit_open_total` | プロバイダ回路開放回数 |
| `yahoo_cache_hit_total` | Yahoo検索freshキャッシュヒット |
| `yahoo_stale_hit_total` | 制限時のstaleキャッシュ出力 |
| `yahoo_singleflight_join_total` | 同一検索の合流回数 |
| `sora_search_queries_total` | 検索成功出力回数 |
| `sora_throttled_total` | 制限時即時失敗回数 |
| `sora_scrape_refill_total` | scrape補充回数 |
| `sora_scrape_deadline_total` | 締切で打ち切ったページ数 |
| `sora_deep_search_wave_total` | deep追加wave回数 |
| `sora_browser_launch_total` | ブラウザ起動回数 |
| `sora_browser_recall_saved_total` | recall抽出でブラウザを省略した回数 |
| `sora_credential_strip_total` | クロスオリジン除去回数 |
| `sora_redirect_block_total` | redirect保護による拒否回数 |
# HELP sora_cache_hit_rate Cache hit rate
# TYPE sora_cache_hit_rate gauge
sora_cache_hit_rate 0.7647
# HELP sora_active_browser_sessions Active browser sessions count
# TYPE sora_active_browser_sessions gauge
sora_active_browser_sessions 2
# HELP sora_bot_upgrade_total Static fetch results that triggered SPA/bot detection and were upgraded to browser rendering
# TYPE sora_bot_upgrade_total counter
sora_bot_upgrade_total 12
# HELP sora_bot_retry_total Browser-rendered results still flagged as SPA/bot after first render, triggering a retry
# TYPE sora_bot_retry_total counter
sora_bot_retry_total 3
```

`sora_bot_upgrade_total` / `sora_bot_retry_total`(JSON では `botDetection`)は、静的取得が SPA / Bot 検知画面と判定されてブラウザ描画へ昇格した回数と、ブラウザ描画後もなお空白と判定されて再試行した回数です。対象サイトの Bot 対策の強さや取得成功率の傾向を把握する運用指標として利用できます。

#### `POST /cache/clear` (キャッシュ全削除)
メモリキャッシュと SQLite 永続キャッシュを全て破棄します。取得内容を強制的に最新化したい場合に利用します。

```bash
curl -X POST http://127.0.0.1:3016/cache/clear
# => {"status":"ok","cleared":42}
```

---

### 3.2 単一 URL / PDF スクレイプ (`POST /scrape`)
- **リクエスト**:
```json
{
  "url": "https://example.com/article",
  "maxChars": 30000,
  "mode": "auto",
  "formats": ["markdown", "jsonLd", "images", "links"],
  "onlyMainContent": true,
  "selectors": {
    "productName": "h1.product-title",
    "price": ".price-value",
    "buyLink": "a.btn-buy@href",
    "thumbnail": "img.main-photo@src"
  },
  "extractHighlights": true,
  "query": "新機能 リリース"
}
```
- **レスポンス例 (デフォルト: Compact Mode - LLMトークンを50%以上削減)**:
```json
{
  "url": "https://example.com/article",
  "title": "最新アップデートのお知らせ",
  "content": "---\npublishedTime: \"2026-08-22T10:00:00Z\"\nauthor: \"開発チーム\"\nsiteName: \"Tech Blog\"\n---\n\n> 📍 **階層**: ホーム > ニュース > 製品情報\n> 📅 **イベント情報**: Sora 新機能発表カンファレンス 2026 (日時: 2026-09-15T18:00:00+09:00 | 会場: 東京国際フォーラム | 出演: Sora Core Team)\n\n...",
  "pageType": "article",
  "publishedTime": "2026-08-22T10:00:00Z",
  "author": "開発チーム",
  "siteName": "Tech Blog",
  "breadcrumb": [
    "ホーム",
    "ニュース",
    "製品情報"
  ],
  "events": [
    {
      "name": "Sora 新機能発表カンファレンス 2026",
      "startDate": "2026-09-15T18:00:00+09:00",
      "location": "東京国際フォーラム",
      "performer": "Sora Core Team"
    }
  ],
  "extracted": {
    "productName": "Sora プレミアムキーボード",
    "price": "¥24,800",
    "buyLink": "https://example.com/cart/add?id=123",
    "thumbnail": "https://example.com/images/feature.png"
  },
  "jsonLd": [
    {
      "@context": "https://schema.org",
      "@type": "NewsArticle",
      "headline": "最新アップデートのお知らせ"
    }
  ],
  "images": [
    {
      "url": "https://example.com/images/feature.png",
      "alt": "新機能の画面イメージ",
      "isImportant": true,
      "imageType": "photo"
    }
  ],
  "highlights": [
    "本日より新機能の提供を開始いたします。"
  ]
}
```

> [!NOTE]
> **🪶 Compact Response Mode & `verbose: true`**:
> v2.9.0 より、LLM のコンテキスト窓を節約するため、デフォルトでは内部評価メトリクス(`quality`, `completeness`, `qualityReasons`, `missingFields`, `evidence`, `renderedWithBrowser` 等)を自動パージした軽量レスポンスを返します。
> デバッグや品質検証などで全内部メトリクスが必要な場合は、リクエストに `"verbose": true`(または `/search?verbose=true`)を指定してください。

> [!NOTE]
> **🧹 Base64 インライン画像の自動置換・パージ & `keepDataImages: true`**:
> Web ページ内の巨大なインライン画像(`data:image/png;base64,...`)は、LLM のトークンを大量消費する原因となります。Sora では自動的に `![画像: alt属性]` へ置換してパージします。画像を Base64 のまま保持したい場合は `"keepDataImages": true` を指定してください。

> [!TIP]
> **🇯🇵 日本語レガシーサイト自動対応**: `Shift_JIS (CP932)` や `EUC-JP` の Web サイトも文字コードを自動判定してデコードします。文字化けの心配はありません。
> 
> **📄 PDF 抽出強化**: 複数ページの PDF ドキュメントは `<!-- Page 1 -->\n## Page 1` のようにページ番号区切りで構造化 Markdown 出力され、`totalPages` や作成者等のメタデータも自動抽出されます。
> 
> **✂️ 構文安全トリミング & トークン見積もり**: `maxChars` で文字数制限された場合でも、開いたコードブロック(` ``` `)やテーブルを自動的に安全に補正・閉鎖します。また、レスポンスには推定 LLM トークン数 `estimatedTokens` が付与されます。
> 
> **🧩 RAG 最適化セマンティック・チャンキング (`chunkMarkdown: true`)**: 見出し階層(H1〜H4)や段落・コードブロックを壊さず適切に分割された `chunks: [{ index, heading, content, estimatedTokens }]` を自動生成し、ベクトル検索や RAG へ即座に投入できます。
> 
> **🖼️ 画像メタデータ & キャプション抽出 (`formats: ["images"]`)**: 各画像について URL に加え、`<figcaption>` の説明文(`caption`)、`width`/`height`、およびアイキャッチ判定(`isMainImage`)を自動抽出します。
> 
> **🔗 ページ内リンクの健全性・到達性判定 (`validateLinks: true`)**: ページ内のリンクに対して軽量な並行検証を行い、HTTP ステータスと有効性 `linksWithStatus: [{ url, status, ok }]` を返却します。
> 
> **📚 出典・引用リンク構造化抽出 (`extractCitations: true`)**: 本文中の外部リンクや参考文献をコンテキスト文付きで `citations: [{ text, url, context }]` として自動抽出します。
> 
> **⏱️ 読了時間 & 文字・単語数統計**: 本文から `characterCount`、`wordCount`、および言語特性に応じた推定読了時間 `readingTimeMin`(分数)を自動算出して付与します。
> 
> **🔔 非同期 Webhook コールバック (`webhookUrl`)**: 長時間バッチ処理や大規模クロール完了時に、指定したエンドポイントへ非同期で結果ペイロードを HTTP POST 通知します。
> 
> **🛡️ PII 自動マスキング (`maskPii: true`)**: メールアドレス、日本の電話番号、クレジットカード番号(Luhn検証)などの機密情報を自動で `[EMAIL]`, `[PHONE]`, `[CREDIT_CARD]` に伏字化して LLM への送信を保護します。
> 
> **📡 進行状況リアルタイム SSE ストリーミング (`POST /scrape/stream`)**: `start` → `fetch` → `render` → `enrich` → `done` の各ステージ進行イベントをリアルタイムに Server-Sent Events で受信可能です。
> 
> **🎬 YouTube / 動画メディアメタデータ & チャプター抽出 (`media`)**: 動画ページから再生時間、サムネイル、チャプター一覧(タイムスタンプ付き目次)を自動構造化抽出します。
> 
> **🤖 LLM 最適化プロンプト XML 自動生成 (`formatAsPrompt: true`)**: Claude / GPT / Gemini が最も理解しやすい標準的な `<web_page url="..." title="...">...</web_page>` 形式のコンテキストラッパー `promptContext` を自動生成します。
> 
> **🖍️ 検索キーワードの本文自動強調 (`highlightMatches: true`)**: 指定した `query` のキーワードを本文 Markdown 内で `<mark>キーワード</mark>` として強調表示した `highlightedContent` を取得できます。
> 
> **📊 テーブル構造化 JSON 抽出 & 結合セル 2D 正規化 (`formats: ["tables"]`)**: ページ内の表(`<table>`)を `{ caption, headers, rows }` の構造化 JSON 配列として取得可能です。さらに `colspan` や `rowspan` を含む複雑な結合セルを 2 次元マトリクスで自動補完・展開し、Markdown の表崩れ・列ズレを解消します。
> 
> **📅 イベント・スケジュール構造化抽出 (`events`)**: Schema.org の `Event` / `MusicEvent` を自動抽出し、構造化データ `events: [{ name, startDate, endDate, location, performer, offers, ... }]` を返却。さらに Markdown 冒頭にも `> 📅 **イベント情報**:` コールアウトとして自動付加されるため、LLM が公演日程やチケット情報を即座に正確把握できます。コールアウトは 1 件 1 行で、開催中・今後の予定を近い順、過去の予定をその後ろに最大 10 件まで並べ、超えた分は「ほか N 件」と件数で示します(`events` 自体は抽出順のまま全件を返します)。
> 
> **🗓 予定の統合一覧 (`schedule`, `search_deep`)**: 上位ページの `events`(公式サイト・TimeTree・まとめサイトなど)から、開始日と名称が同じ予定を 1 件にまとめた一覧を、`results` の前に返します。各予定に載せていたページの URL を `sources` で示し、開催中・今後は近い順、過去はその後ろに並べます(予定は削除しません)。通常応答ではページごとの `results[].events` はこの一覧に移り、`verbose: true` では従来どおり `results[].events` に入ります。`maxTotalChars` の対象外です。
> 
> **📍 パンくずリスト階層ナビゲーション (`breadcrumb`)**: サイトの `BreadcrumbList` および `<nav aria-label="breadcrumb">` から階層パスを自動抽出し、`breadcrumb: ["トップ", "カテゴリ", ...]` を返却。Markdown 冒頭にも `> 📍 **階層**:` として明記され、ページの文脈・所属カテゴリが正確に把握できます。
> 
> **🖼️ 重要画像スコアリング (`isImportant` / `imageType`)**: フライヤー(告知チラシ)、タイムテーブル、図表・チャートなどの画像メタデータを自動判別し、`isImportant: true` および `imageType: 'timetable' | 'flyer' | 'diagram'` を付与。画像内にのみ文字情報が焼き込まれた告知を逃さず特定できます。
> 
> **🛡️ Clean Content Sanitizer(プロンプトインジェクション無害化)**: Web ページ内に悪意を持って埋め込まれた `[SYSTEM: ...]`, `<system>`, `[INST]` などの LLM 制御トークンや不可視ゼロ幅文字(`\u200B`等)を自動的に安全な文字へサニタイズ・パージし、間接プロンプトインジェクション攻撃を防御します。
> 
> **⚡ インテリジェント・アセット遮断 & DOM Quiescence SPA 待機**: ブラウザ描画時(`mode: "browser"` / SPA 自動昇格時)、不要な画像バイナリ、動画、Webフォント、3Dモデル、広告・解析トラッカーをネットワーク層(Request Interception)で即座に abort し、転送量を 99.8% 削減。さらに固定スリープを排して `MutationObserver` による 200ms 静止検知を行うことで、動的 SPA の描画完了を最速・確実に捉えます。
> 
> **⚡ 超高速 抽出型自動要約 (`extractSummary: true`)**: 外部 LLM API を呼ばず、内部アルゴリズムによりミリ秒単位で重要文(TL;DR 要約)`summary: string[]` を自動生成します。
> 
> **🎯 スクレイピング品質スコア & 充足度保証 (`quality` & `completeness` / ※ `verbose: true` 指定時)**: コンテンツ量・見出し構造・Schema.org 構造化データ・Bot対策判定から 0〜100 の品質スコア `quality` とページ種別(`article`, `product`, `qa`, `generic`)に応じた重要項目の充足率 `completeness`、欠損項目 `missingFields` をインメモリで超高速判定(< 0.1ms)して付与します。
> 
> **🔍 出処根拠追跡 & クロスバリデーション (`evidence` / ※ `verbose: true` 指定時)**: 抽出された価格・在庫・著者・公開日時などの各フィールドがどこから抽出されたか(`jsonld`, `meta`, `dom`)の出処根拠(Provenance)を `evidence` マップとして返却し、ハルシネーション検出や検証を容易にします。
> 
> **🎯 検索結果の重複排除 (`dedup: true`)**: ニュース検索やリアルタイム検索で、コピペ投稿や転載記事を類似度判定で自動排除し、ユニークな情報のみを厳選します。
> 
> **🔄 自動リトライポリシー (`retries` & `retryDelayMs`)**: 接続失敗や 429/503 エラー時に指数バックオフで自動再試行し、耐障害性を向上させます。
> 
> **📸 要素指定スクリーンショット (`clipSelector`)**: 特定の要素(例: `clipSelector: "#stock-chart"`)を指定することで、その要素のみを切り抜いた Base64 PNG を取得できます。
> 
> **🍪 カスタムヘッダー & Cookie 注入 (`headers` / `cookies`)**: 会員サイトや言語指定(`Accept-Language`)、年齢認証 Cookie などを透過的に送信可能です。
> 
> **🔄 U字型パッセージ配置 (`reorderUFlat: true`)**: *Lost in the Middle* 現象を克服するため、スコア降順ではなく最重要情報を先頭と末尾に配置(`1位, 3位 ... 4位, 2位`)して返却します。
> 
> **🎛️ MMR 多様性制御 (`diversityWeight: 0.7`)**: Jaccard 類似度を用いた反復多様性選択により、同一内容の言い換え重複を排除し、多角的な重要パッセージを採択します。
> 
> **⏳ 時間的文脈アンカー (`annotateTemporal: true`)**: 記事の公開日時(`publishedTime`)を基準日とし、「明日」「来週金曜」「3日前」などの相対日時表現を決定論的にパースして `[YYYY-MM-DD]` 注記を自動埋め込み&`temporalAnchors` 配列を返却します。
> 
> **🗜️ スマート表トークン圧縮 (`minimizeTables: true`, デフォルト有効)**: Web 上の表から全行空欄列、同一プレースホルダー列(`-`, `—`, `N/A`, `なし` 等)、および空行を $O(R \times C)$ で自動パージし、表のトークン消費を 30〜70% 削減します。
> 
> **🧹 ユーザー指定ノイズセレクタ除去 (`removeSelectors`)**: `removeSelectors: [".ad", ".comments", "#related-articles"]` を指定し、特定ブロックを Markdown 変換前に徹底パージできます。
> 
> **✂️ リンク URL プレーンテキスト化 (`stripLinks: true`)**: Markdown 内のリンク `[テキスト](URL)` から URL 表記を削ぎ落とし `テキスト` のみに変換します。LLM のトークン消費を 20〜40% 削減し、純粋な文章コンテキストのみを効率的に渡せます。
> 
> **🌲 リンク密度フィルター (`filterLinkDensity: true`)**: タグ一覧、関連記事リスト、ナビゲーションメニューなど、実効テキストに対するリンク文字数の割合(リンク密度)が極端に高いノイズブロックを自動検出してパージします。
> 
> **🛡️ 間接プロンプトインジェクション & 不可視 CSS 徹底防御**: `<!-- ... -->` の HTML コメントや、`text-indent: -9999px`、`color: transparent`、`opacity: 0`、`font-size: 0` 等の悪意ある隠しテキストを DOM レベルで完全パージします。また、`<|im_start|>`, `[INST]`, `<<SYS>>` 等の LLM 特殊制御トークン文字列も安全に無害化(サニタイズ)します。
> 
> **🚫 Data URI / Base64 画像の完全無害化**: HTML 内に埋め込まれた長大な `data:image/...;base64,...` 文字列を完全除去し、`alt` 属性が存在する場合は `[画像: 説明文]` に置換してトークンの枯渇を 100% 防止します。
> 
> **📖 対話型 API ドキュメント (`GET /docs`)**: ブラウザから `http://localhost:3016/docs` にアクセスすると、Swagger UI から全 API を直接テスト実行(Try it out)できます。

---

### 3.2.1 複数 URL 一括並行スクレイプ (`POST /scrape/batch`)

複数の Web ページ URL を指定し、ドメイン別スロットリングを維持しながら高速にサーバー側で並行フェッチして一括取得します。

- **リクエスト (POST)**:
```json
{
  "urls": [
    "https://example.com/page1",
    "https://example.com/page2",
    "https://example.com/page3"
  ],
  "concurrency": 3,
  "maxChars": 10000,
  "mode": "auto",
  "formats": ["markdown", "jsonLd"]
}
```
- **レスポンス例**:
```json
{
  "total": 3,
  "successful": 3,
  "failed": 0,
  "results": [
    {
      "url": "https://example.com/page1",
      "title": "Page 1 Title",
      "content": "...",
      "estimatedTokens": 450
    }
  ],
  "errors": []
}
```

---

### 3.3 対話型ブラウザ自動操作 (`POST /browser/action` または `POST /action`)

Web ページを開き、クリック・テキスト入力・スクロール・待機・スクリーンショット撮影などの一連のアクションを順次実行して最終結果を取得します。**ワンショット実行** と、チャットで対話しながら操作を進める **ステートフル・マルチターン対話セッション (`sessionId`)** の両方に対応しています。

#### ① ワンショット実行(1回完結)
- **リクエスト (POST)**:
```json
{
  "url": "https://example.com/search",
  "actions": [
    { "type": "fill", "selector": "input[name='q']", "text": "Sora" },
    { "type": "click", "text": "検索" },
    { "type": "wait", "selector": ".results-container", "ms": 5000 },
    { "type": "scroll", "direction": "down", "distance": 1000 }
  ],
  "extract": {
    "markdown": true,
    "screenshot": true,
    "html": false
  },
  "timeout": 30000
}
```

- **レスポンス例**:
```json
{
  "success": true,
  "url": "https://example.com/search?q=Sora",
  "markdown": "---\ntitle: \"検索結果 - Sora\"\nurl: \"https://example.com/search?q=Sora\"\n---\n\n# 検索結果\n...",
  "screenshot": "iVBORw0KGgoAAAANSUhEUgA...",
  "actionOutputs": [
    { "step": 1, "type": "fill", "result": "ok" },
    { "step": 2, "type": "click", "result": "ok" },
    { "step": 3, "type": "wait", "result": "ok" },
    { "step": 4, "type": "scroll", "result": "ok" }
  ],
  "renderedWithBrowser": true,
  "source": "browser"
}
```

#### ② ステートフル・マルチターン対話セッション(対話型チャット向け)
- **Turn 1 (セッション作成 & 画面オープン)**:
```json
{
  "url": "https://example.com/login",
  "createSession": true,
  "actions": [
    { "type": "fill", "selector": "#username", "text": "myuser" }
  ],
  "extract": { "screenshot": true }
}
```
*(レスポンスで `"sessionId": "sess_a1b2c3d4"` が返却されます)*

- **Turn 2 (開いたままの画面で続けて操作)**:
```json
{
  "sessionId": "sess_a1b2c3d4",
  "actions": [
    { "type": "fill", "selector": "#password", "text": "mypassword" },
    { "type": "click", "text": "ログイン" },
    { "type": "wait", "selector": "#dashboard" }
  ],
  "extract": { "markdown": true }
}
```

- **Turn 3 (セッション終了 & クリーンアップ)**:
```json
{
  "sessionId": "sess_a1b2c3d4",
  "closeSession": true
}
```
*(※ 操作が 5 分間途切れた場合も自動タイムアウトで安全にメモリ解放されます)*

---

### 3.4 万能深層Web検索 (`POST /search` / `/search/deep` / `/search/integrated` / `/deep-search`) & Web 検索 (`POST /search/web`)

`POST /search`(別名 `/search/deep` / `/search/integrated` / `/deep-search`)は、Web 検索・上位サイトの本文自動スクレイピング(Clean Markdown 抽出・重複排除)・X/Twitter リアルタイム速報をワンストップで一括実行する万能深層検索エンドポイントです(Firecrawl / Tavily 互換)。最新事実、ライブ・公演日程、新製品・発売日、営業時間、時事ニュースなどの調査に最適です。

- **返る件数の考え方 (`POST /search`)**:
  - **Web (`results`)**: `limit`(既定5、最大20)の件数だけ本文を取得します。取得に失敗した(本文が取れずスニペット代替になった)ページは、次の候補で補って取得するため、`results` が `limit` を超えることがあります。`adaptiveScrape: true` では、証拠が足りない間 `scrapeBudget`(既定8、最大20)まで追加で取得します。`maxTotalChars` は本文の合計だけを制限し、件数は変えません。
  - **X (`realtime.items`)**: `realtimeLimit`(既定20)が上限で、公式アカウントの投稿は別枠で追加されます(`official` は先頭に最大5件、`public` は後ろに最大2件)。そのため件数は最大で上限+5件です。上限で省いた件数は `realtime.omittedCount` で分かります。
- **小さなモデル・低コスト向けの設定 (`POST /search` / MCP `search_deep`)**: 応答の量は引数で絞れます。既定のままだと X 投稿の画像 URL や予定データ(`events`)も含めて大きくなるため、LLM の文脈が小さい場合は次のように指定してください(「=LOVE ライブ 予定」の実測。トークン数は GPT 系の数え方)。

  | 設定 | 指定する引数 | 応答の量 |
  |---|---|---|
  | 既定 | (なし) | 約27,700字・13,700トークン |
  | 軽量 | `limit: 3`, `responseMode: "evidence"`, `realtimeLimit: 8`, `maxTotalChars: 3000` | 約18,100字・8,700トークン |
  | 最小 | `limit: 3`, `responseMode: "evidence"`, `realtimeLimit: 5`, `maxTotalChars: 1500` | 約13,900字・6,400トークン |
  | X なし | 軽量に `includeRealtime: false` を加える | 約9,300字・4,100トークン |

  表の量は v2.36.1 での実測です。さらに、画像・動画の URL は `includeMedia: false` で省けます(既定は従来どおり残します。画像の内容が必要な質問では省かないでください)。予定は `schedule` に統合されて重複が減ります(v2.37.3)。`evidence` は本文を省いてハイライトを残すモードで、予定(`schedule`)と X 投稿の画像 URL は減らしません。待ち時間とメモリだけを減らすなら `scrape` の `mode: "fast"`(静的取得のみ)がありますが、LLM に渡る量は変わりません。根拠が足りないときは `contextSufficiency` を見て `responseMode: "full"` や `adaptiveScrape` で取り直せます。
- **深層検索リクエスト (`POST /search` / `/search/deep` / `/search/integrated` / `/deep-search`)**:
```json
{
  "query": "君と見るそら 好きって コール",
  "officialAccountId": "kimisora_JPN",
  "limit": 5,
  "scrapeContent": true,
  "includeRealtime": true,
  "extractHighlights": true,
  "formats": ["markdown"]
}
```
> 💡 **公式Xアカウント自動特定 & ハイブリッド統合**:
> `officialAccountId` を指定すると、一般ファンの投稿に加えて公式アカウント(@kimisora_JPN)の最新ポストが独立枠で取得され、重複排除された上で最上位に `isOfficial: true` でピン留めされます。また、未指定の場合でも、Web検索結果のURLやHTMLメタタグ(`twitter:site` / `twitter:creator`)から公式Xアカウントが自動検出された場合はハイブリッド統合が自動適用されます。ただし自動検出したアカウントは、表示名か最近の投稿(3割以上)にクエリの語が含まれる場合だけ公式として扱います(クエリと無関係なページの X 欄は使いません)。評判・炎上の調査(`realtimeFocus: "public"`)では、公式の投稿は後ろに最大2件です。
>
> 💡 **親文脈継承&局所IDF適正化ハイライト (`extractHighlights: true`)**:
> `ρSelect v2` が各セクションに親タイトルやパンくず階層(例: `【君と見るそら】コール > ・好きって。`)を自然に継承し、全セクション共通の低情報量語を適切に減衰させます。これにより、短文の無関係セクションに誤爆することなく、目的の曲やトピックの本文エビデンスをピンポイントで抽出します。

- **HTML 形式で取得する場合**:
```json
{
  "query": "React 19 新機能",
  "formats": ["html"]
}
```
- **重要ハイライトのみ抽出する場合 (トークン節約モード)**:
```json
{
  "query": "React 19 新機能 変更点",
  "extractHighlights": true
}
```
- **Web 検索リクエスト (`POST /search/web`)**:

```json
{
  "query": "新商品 発売情報",
  "includeDomains": ["example.com", "news.example.org"],
  "excludeDomains": ["spam.example.com"],
  "updated": "week"
}
```

---

### 3.4.1 サイトマップ探索 (`POST /map`)
指定ドメインの `sitemap.xml` や内部リンクを探索し、サイト内の全 URL リストを抽出します。
- **リクエスト**:
```json
{
  "url": "https://example.com",
  "limit": 200,
  "includeSubdomains": false
}
```

---

### 3.4.2 サブページ再帰的クロール (`POST /crawl` & `POST /crawl/stream`)
指定 URL から配下ページを再帰的に巡回し、複数ページの Markdown/HTML/画像/構造化データを一括収集します。`includePatterns` / `excludePatterns` による Glob ワイルドカードフィルタリングに対応。
- **リクエスト (一括取得)**:
```json
{
  "url": "https://example.com/docs",
  "maxPages": 20,
  "maxDepth": 2,
  "includePatterns": ["/docs/**", "/guide/*"],
  "excludePatterns": ["/tag/**", "*.pdf"],
  "formats": ["markdown", "jsonLd", "images"]
}
```
- **SSE ストリーミング (`POST /crawl/stream`)**: ページが取得されるたびにリアルタイムで Server-Sent Events(`start` -> `page` -> `done`)を配信。

---

### 3.5 画像・動画・ニュース・知恵袋・サジェスト検索
- **画像検索 (`POST /search/image`)**: `{ "query": "富士山", "limit": 10 }`
- **動画検索 (`POST /search/video`)**: `{ "query": "簡単 レシピ", "limit": 10 }`
- **ニュース検索 (`POST /search/news`)**: `{ "query": "AI ロボット", "limit": 10 }`
- **知恵袋 Q&A (`POST /search/chiebukuro`)**: `{ "query": "プログラミング 初心者", "limit": 10, "status": "solved" }`
- **キーワード補完 (`POST /search/suggest`)**: `{ "query": "天気", "limit": 10 }`

---

### 3.6 電車乗換案内 (`POST /transit/route`)
- **リクエスト**:
```json
{
  "from": "東京",
  "to": "新宿",
  "sortBy": "time"
}
```
- **レスポンス例**:
```json
{
  "source": "transit",
  "from": "東京",
  "to": "新宿",
  "routeCount": 3,
  "routes": [
    {
      "index": 1,
      "totalTime": "14分",
      "transfers": "乗換:0回",
      "fare": "IC優先:209円",
      "sections": [
        {
          "line": "JR中央線快速・高尾行",
          "from": "東京",
          "departureTime": "09:30",
          "to": "新宿",
          "arrivalTime": "09:44"
        }
      ]
    }
  ]
}
```

---

### 3.7 日本全国 天気予報 (`POST /weather` / `GET /weather` / `GET /weather/:city`)

気象庁公式オープンデータ API(および livedoor 天気互換形式)を直接解析し、日本全国の今日・明日・明後日の詳細な気象データを完全自律で取得します。

#### 本機能の利点 (Features & Advantages)
- **完全自律・公式直結(ゼロ依存)**: 気象庁の公式 CDN(`jma.go.jp`)から直接気象データを取得・パース。
- **全国 1,805 市区町村のスマート自動解決**: 気象庁公式のエリア定義(`area.json`)を内蔵。「天童市」「軽井沢」「箱根」「浦安」「別府」などの市区町村名・有名地名から、担当する気象台の地点 ID を 0ms で自動選定。県名なしの入力にも対応。
- **AI エージェントフレンドリーな構造化データ**: 3日間の天気テロップ、風・波、予想最高/最低気温(℃)、時間帯別降水確率(0-6時, 6-12時, 12-18時, 18-24時)、気象台発表の天気概況文(見出し・本文)をクリーンな JSON で一括取得。
- **LRU キャッシュによる超高速応答**: 30分間のインメモリ LRU キャッシュを標準搭載し、気象庁サーバーへの不要な重複アクセスを自動防止。

- **リクエスト (POST)**:
```json
{
  "city": "天童市",
  "days": 3
}
```
- **GET リクエスト**: `GET /weather?city=軽井沢&days=2` または `GET /weather/箱根`
- **レスポンス例**:
```json
{
  "source": "weather",
  "cityId": "060010",
  "title": "村山 の天気",
  "publishedTime": "2026-08-21T17:00:00+09:00",
  "publicTime": "2026-08-21T17:00:00+09:00",
  "publishingOffice": "山形地方気象台",
  "location": {
    "area": "東北",
    "prefecture": "山形県",
    "city": "天童市"
  },
  "overview": "前線が、日本海から東北地方を通って、日本の東にのびています。村山地方では、夜遅くにかけて雷を伴い激しい雨が降る所がある見込みです。",
  "description": {
    "headline": "",
    "body": "前線が、日本海から東北地方を通って、日本の東にのびています...",
    "text": "..."
  },
  "forecasts": [
    {
      "date": "2026-08-21",
      "dateLabel": "今日",
      "telop": "曇り",
      "detail": {
        "weather": "くもり 所により 夕方 雨 で 雷を伴い 激しく 降る",
        "wind": "北の風 後 南東の風",
        "wave": null
      },
      "temperature": {
        "min": "22℃",
        "max": "31℃"
      },
      "chanceOfRain": {
        "T00_06": "30%",
        "T06_12": "0%",
        "T12_18": "0%",
        "T18_24": "30%"
      },
      "image": "https://www.jma.go.jp/bosai/forecast/img/200.svg"
    }
  ]
}
```

---

### 3.8 Yahoo リアルタイム検索 & トレンド (`POST /search/realtime` / `POST /realtime` / `POST /search/trend`)
- **リアルタイム検索 (`POST /search/realtime` または `POST /realtime`)**: `{ "query": "イベント名", "sort": "popular", "limit": 20, "page": 1 }`
  - `sort`: `"recent"` (新着順, デフォルト) または `"popular"` (話題順 / エンゲージメント順)
  - 各ポストに `publishedTime` (ISO 8601 文字列), `author` (ユーザー名 + @アカウント名), `siteName: "X (Twitter)"` が統一フォーマットで自動付与されます。
  - **X 長文投稿 (Note Tweet) 全文補完**: クエリ要求やスニペット省略記号(`…`)を検知し、上位候補を FxTwitter v2 API(最大 2 件、1,500ms fail-soft)で自動補完。完全な本文とメディアを取得可能です。
  - Xリアルタイム検索はYahooのJSON取得を直接呼びます (MCPバイナリ不使用)。Web・画像・動画・ニュース・知恵袋は従来どおりMCPバイナリを使用します。
  - 検索演算子はYahoo公式仕様どおりに送信します: `id:xxx` (投稿者) / `@xxx` (宛先) / `#tag` / `-除外` / `(A B)` (OR) / `URL:value` / URL直接入力。複数語と組み合わせ可能です (例: `君と見るそら ライブ 出演 id:kimisora_JPN`)。
  - 構造化 `url` オプションは `URL:` 演算子として送信します。
  - OR・URL条件・引用符を含む複雑な式は、意味を変える自動relaxを行わず原式の単発取得になります。
  - **固有名詞を守る緩和 (v2.36.0)**: 原式で全語の揃う投稿が無いとき、語を1つ落として再検索します。このとき、Web 検索上位のタイトルと X の総ヒット数から固有名詞(例: `ライブ 予定 =LOVE` の `=LOVE`)を判定し、固有名詞を落とす再検索はしません(語順は問いません)。最後の再検索は固有名詞だけで行います。
    - Yahoo が記号を無視して別物を返す固有名詞(`=LOVE` が「LOVE」一般の投稿になる等)は、公式 X アカウントの投稿のハッシュタグから別名(`イコラブ`)を見つけて検索し、固有名詞も別名も含まない投稿を除きます。
    - 判定に Web 検索を1回使います(原式で揃った場合は行いません)。評価セットの12クエリ(固有名詞の位置を変えたもの)の実測では、固有名詞か別名を含む投稿の割合が 24% → 100%、X への検索回数が 38 → 30 回になりました。緩和が必要なクエリでは所要時間が約 0.4〜1.3 秒増えます(原式で揃うクエリは変わりません)。`SORA_REALTIME_ANCHOR=off` で従来の動作に戻せます。
    - 呼び出し側が固有名詞を指定できます(`search_realtime` の `anchor`、`search_deep` の `realtimeAnchor`、v2.38.0)。指定がクエリの語に対応すれば推定より優先し、判定のための Web 検索と総ヒット数の取得を省きます。辞書や総ヒット数では見分けにくい語(「出演時間」と「君と見るそら」はどちらも X で約400件)でも守れます。クエリの語に無い指定は無視して推定します。
  - 応答の `missingTerms` は、1件の投稿に揃って現れなかったクエリ語です(空なら省略)。`aliasTerms` は固有名詞の代わりに検索した別名です(使った時のみ)。
  - **誰の投稿を優先するか (`focus`, v2.36.1)**: `official`(本人・公式。予定・告知・事実確認)か `public`(本人以外。評判・感想・炎上・現地の様子)。省略時はクエリに「評判・口コミ・感想・反応・炎上・批判」などがあれば `public`、無ければ `official` です。`public` では、評判系の語(評判・口コミ・感想・反応・炎上・批判など)を必須の語にしません。投稿にほぼ書かれない語(評判・口コミ)は検索語から外し、投稿にも書かれる語(感想・反応・炎上など)は、その語つきの検索と語なしの検索を並行して行い、語つきの投稿を先に並べます。上限を超えるときは同じ投稿者の投稿を後回しにして選び、`search_deep` では本人の投稿を後ろに最大2件へ下げます。適用した方は応答の `focus` に入ります。
  - **返す件数 (`limit`、既定20)**: 検索で取得した投稿が上限を超えるときは、検索ごとに交互に選びます。ただし、上限内のどの投稿にも無いクエリ語を含む投稿は、上限を超えて最大5件まで残します。`search_deep` の `realtime.items` は、この上限の件数に公式アカウントの投稿の枠(`official` は先頭に最大5件、`public` は後ろに最大2件。上限とは別に追加)を足した数になります。省いた件数は `omittedCount` に入るので、足りなければ `limit`(`search_deep` は `realtimeLimit`)を上げるか `page` で続きを取得してください。
  - 投稿の `like_count`・`reply_count`・`repost_count` は 0 のとき、`isOfficial` は公式のとき以外は省略します(`verbose: true` では常に返します)。
  - `page` は1始まりでYahoo側は40件固定幅 (`page=2` はoffset 40)。`limit` は1〜40 (デフォルト20)。
  - provider障害時は成功扱いの0件ではなくエラー (HTTP 502 / MCP `isError`) を返します。一部失敗時は `partial: true` と `providerErrors` を付けて成功分を返します。
- **急上昇トレンド (`POST /search/trend`)**: `{ "limit": 20 }`

---

### 3.9 サイトマップ & クロール (`POST /map` / `POST /crawl`)
- **サイトマップ (`POST /map`)**: `{ "url": "https://example.com", "limit": 200 }`
- **再帰クロール (`POST /crawl`)**: `{ "url": "https://example.com/docs", "maxPages": 10 }`

---

### 3.10 気象警報・注意報 & リアルタイム地震速報 (`POST /disaster/warnings` / `POST /disaster/earthquake`)
- **気象警報・注意報 (`POST /disaster/warnings`)**:
  - 市区町村名または都道府県名から、気象庁発表の特別警報・警報・注意報をリアルタイム取得。
  ```json
  { "city": "新宿区" }
  ```
  - レスポンス例:
  ```json
  {
    "areaCode": "130010",
    "areaName": "新宿区",
    "prefecture": "東京都",
    "reportTime": "2026-08-24T18:00:00+09:00",
    "specialWarnings": [],
    "warnings": [
      { "code": "03", "name": "大雨警報", "level": "warning", "status": "発表" }
    ],
    "advisories": [
      { "code": "14", "name": "雷注意報", "level": "advisory", "status": "継続" }
    ],
    "hasActiveAlerts": true
  }
  ```

- **地震速報・履歴 (`POST /disaster/earthquake`)**:
  - P2P地震情報 API + 気象庁フォールバックによるリアルタイム地震履歴(震度1〜7、震源地、M値、深さ、津波情報、観測地点)を取得。
  ```json
  { "limit": 5, "minIntensity": 30 }
  ```
  - レスポンス例:
  ```json
  {
    "count": 1,
    "earthquakes": [
      {
        "id": "20260824183000",
        "time": "2026/08/24 18:30:00",
        "hypocenter": { "name": "千葉県北西部", "magnitude": 4.5, "depthKm": 70 },
        "maxScale": "震度3",
        "maxScaleRaw": 30,
        "tsunami": "津波の心配なし",
        "source": "p2pquake",
        "points": [
          { "pref": "東京都", "addr": "東京千代田区大手町", "scale": "震度3" }
        ]
      }
    ]
  }
  ```

---

### 3.11 道路交通情報 (`POST /traffic/road`, `GET /traffic/road/:pref?`)
JARTIC(日本道路交通情報センター)連携データに基づき、日本全国の高速道路・都市高速・主要有料道路のリアルタイム道路交通情報(事故・渋滞・通行止め・車線規制・チェーン規制・工事等)を取得します。

- **リクエスト (`POST /traffic/road`)**:
  ```json
  {
    "pref": "東京都",
    "road": "東名高速"
  }
  ```
- **レスポンス例**:
  ```json
  {
    "pref": "東京都",
    "road": "東名高速",
    "updatedAt": "8月25日 20時15分 現在",
    "hasIssues": true,
    "summary": "東名高速にて 16 件の規制・事故等の情報があります。",
    "items": [
      {
        "roadName": "東名高速",
        "direction": "上り",
        "status": "路肩規制",
        "section": "春日井IC付近",
        "cause": "工事",
        "detail": "春日井IC付近 路肩規制 (工事)"
      }
    ],
    "source": "jartic"
  }
  ```

---

### 3.12 汎用 Web ページ差分監視 & Webhook (`POST /watch/*`, `GET /watch/list`, `DELETE /watch/:id`)
URL またはピンポイント CSS セレクタを定期スキャンし、前回値(SHA-256 ハッシュ)と比較して差分検知時に自動で Webhook を発火します。データは SQLite に永続化。

- **監視ターゲット登録 (`POST /watch/register`)**:
  ```json
  {
    "url": "https://example.com/ticket",
    "title": "チケット当落発表ページ",
    "selector": "#result-box",
    "webhookUrl": "https://api.example.com/hooks/ticket-alert",
    "intervalSeconds": 1800
  }
  ```
- **差分スキャン実行 (`POST /watch/check`)**:
  - 単一ターゲット: `{ "id": "wt_abc123" }`
  - 全ターゲット一括: `{}`
  - 差分検知時に Webhook(SSRF 保護済み)へペイロード送信。
- **ターゲット一覧 (`GET /watch/list`)**
- **ターゲット削除 (`DELETE /watch/:id`)**

---

### 3.13 音楽メタデータ検索 (`POST /search/song` / `POST /search/artist` / `POST /search/music`)
iTunes 公式 Search API と連携し、曲名検索・アーティスト検索・汎用メタデータ検索を実行します(歌詞本文を扱わないため著作権リスクゼロ)。

- **曲名指定 楽曲検索 (`POST /search/song` または `POST /search/music/song`)**:
  ```json
  {
    "query": "アイドル",
    "limit": 5
  }
  ```
- **アーティスト名指定 音楽検索 (`POST /search/artist` または `POST /search/music/artist`)**:
  ```json
  {
    "query": "YOASOBI",
    "entity": "song",
    "limit": 10
  }
  ```
- **汎用音楽検索 (`POST /search/music`)**:
  ```json
  {
    "query": "YOASOBI",
    "entity": "song",
    "attribute": "artistTerm",
    "limit": 10
  }
  ```
- **レスポンス例**:
  ```json
  {
    "query": "YOASOBI",
    "country": "jp",
    "entity": "song",
    "attribute": "artistTerm",
    "count": 10,
    "items": [
      {
        "id": "1537012345",
        "type": "song",
        "title": "夜に駆ける",
        "artist": "YOASOBI",
        "album": "THE BOOK",
        "artwork": {
          "thumbnail": "https://.../100x100bb.jpg",
          "highRes": "https://.../600x600bb.jpg"
        },
        "previewUrl": "https://audio-ssl.itunes.apple.com/.../preview.m4a",
        "releaseDate": "2019-12-15T08:00:00Z",
        "genre": "J-Pop",
        "url": "https://music.apple.com/jp/album/..."
      }
    ],
    "source": "itunes"
  }
  ```

---

### 3.14 e-Gov 日本法令検索 & 条文 Markdown 取得 (`POST /gov/laws` / `POST /gov/law-text`)
デジタル庁・総務省の公式 e-Gov 法令 API v2 と連携し、日本の現行法令(憲法、法律、政令、府省令)のキーワード検索および構造化 Markdown 条文を取得します。

- **法令キーワード検索 (`POST /gov/laws`)**:
  ```json
  {
    "keyword": "著作権法",
    "limit": 5
  }
  ```
  - レスポンス例:
  ```json
  {
    "count": 5,
    "items": [
      {
        "id": "345AC0000000048",
        "title": "著作権法",
        "lawNum": "昭和四十五年法律第四十八号",
        "promulgationDate": "1970-05-06",
        "category": "Act"
      }
    ],
    "source": "e-gov"
  }
  ```

- **法令条文 Markdown 取得 (`POST /gov/law-text`)**:
  ```json
  {
    "lawId": "345AC0000000048"
  }
  ```
  - レスポンス例:
  ```json
  {
    "id": "345AC0000000048",
    "title": "著作権法",
    "lawNum": "昭和四十五年法律第四十八号",
    "era": "Showa",
    "lawType": "Act",
    "markdown": "# 著作権法\n\n**法令番号:** 昭和四十五年法律第四十八号\n\n## 第一章 総則\n\n### 第一条 ((目的))\nこの法律は、著作物並びに実演、レコード、放送及び有線放送に関し著作権者の権利及びこれに隣接する権利を定め...\n\n### 第二条 ((定義))\nこの法律において、次の各号に掲げる用語の意義は、当該各号に定めるところによる。\n- **一** 著作物 思想又は感情を創作的に表現したものであつて...\n- **二** 実演家 俳優、舞踊家、演奏家、歌手その他実演を行う者...",
    "articleCount": 157,
    "source": "e-gov"
  }
  ```

### 3.15 国会会議録検索 (`POST /gov/diet-minutes` / `GET /gov/diet-minutes`)
国立国会図書館公式 API と連携し、戦後から最新(2026年)までの衆議院・参議院の本会議および全委員会の発言記録・議員答弁を全文検索します。

- **リクエスト (POST)**:
  ```json
  {
    "keyword": "人工知能",
    "nameOfHouse": "衆議院",
    "nameOfMeeting": "予算委員会",
    "limit": 5
  }
  ```
- **リクエスト (GET)**: `GET /gov/diet-minutes?keyword=少子化対策&limit=3`
- **レスポンス例**:
  ```json
  {
    "count": 5,
    "totalHits": 342,
    "items": [
      {
        "speechId": "121305261X00220240205_001",
        "house": "衆議院",
        "meeting": "予算委員会",
        "date": "2024-02-05",
        "speaker": "岸田文雄",
        "speakerPosition": "内閣総理大臣",
        "speech": "○岸田内閣総理大臣 委員御指摘の人工知能(AI)に関する法規制及び利活用の推進につきましては...",
        "speechUrl": "https://kokkai.ndl.go.jp/txt/..."
      }
    ],
    "source": "kokkai-ndl"
  }
  ```

---

### 3.16 座標解決・国土地理院の標高取得 (`POST /geo/elevation` / `GET /geo/elevation`)

住所・地名を[Nominatim (OpenStreetMap)](https://nominatim.org/)で緯度経度へ解決し(該当なしの番地住所は[国土地理院の住所検索](https://msearch.gsi.go.jp/address-search/AddressSearch)で補完)、国土地理院からその地点の海抜標高(m)を取得します。座標解決の取得元は`geocodingSource`、その出典表示は`geocodingAttribution`(結果を表示・公開する際に併記)、標高の取得元は`source: "gsi"`です。上位候補が複数の都道府県にまたがる場合は`needsVerification: true`を返すため、`matchedTitle`が意図した地域か確認してください。

地名解決は`search_poi`と共有します。同一Soraプロセス内のMCP・REST全要求で、Nominatimへの実際の問い合わせ開始を1.1秒以上空けます。同じ地名の同時要求は1回にまとめ、成功結果は24時間キャッシュします。異なる未キャッシュ地名の要求は順番に待機します。`noCache: true`でも1.1秒間隔の制限は維持します。直接`lat` / `lon`を指定した場合は地名解決を行いません。

- **リクエスト (POST)**:
  ```json
  {
    "address": "原宿"
  }
  ```
- **リクエスト (GET)**: `GET /geo/elevation?address=原宿` または `GET /geo/elevation?lat=35.6812&lon=139.7671`
- **レスポンス例**:
  ```json
  {
    "query": "原宿",
    "address": "原宿",
    "matchedTitle": "東京都渋谷区神宮前 原宿",
    "geocodingSource": "nominatim",
    "geocodingAttribution": "出典: © OpenStreetMap contributors (ODbL) https://www.openstreetmap.org/copyright",
    "needsVerification": true,
    "lat": 35.669968,
    "lon": 139.709008,
    "elevationMeters": 22.1,
    "dataAccuracy": "1m(レーザ)",
    "formatted": "東京都渋谷区神宮前 原宿 の標高 (海抜): 22.1m (精度: 1m(レーザ))",
    "source": "gsi"
  }
  ```

#### 周辺施設検索の中心地名 (`POST /geo/poi` / `GET /geo/poi`)

施設キーワードと場所を分けて指定すると、Soraが中心地名を座標化し、[OpenPOI API](https://docs.openpoiapi.com/)へ経度・緯度と検索半径を渡します。MCPの`search_poi`も同じ処理を使います。

```json
{"query":"ラーメン","center":"原宿","radiusMeters":1000,"limit":5}
```

GETでは`/geo/poi?query=ラーメン&center=原宿&radiusMeters=1000&limit=5`と指定できます。応答の`centerResolved`には`input`、`address`、`lat`、`lon`、`source: "nominatim"`、出典表示の`attribution`、`needsVerification`を含めます。結果を表示・公開する際は`centerResolved.attribution`も出典として併記してください。互換フィールドの`ambiguous`は`needsVerification`と同値、`candidates`は空配列です。候補一覧や一意性の保証を示すものではありません。

OpenPOIの複数語検索はORのため、場所を`query`へ混ぜず`center`へ指定してください。地名解決失敗時はエラーを返し、広域検索へ切り替えません。該当なしの場合や座標が不正な場合は失敗として扱います。

---

### 3.17 主要空港フライト運航状況・欠航・遅延リアルタイム検索 (`POST /traffic/flight` / `GET /traffic/flight/:airport?`)
羽田、成田、伊丹、関西、中部、新千歳、福岡、那覇等の主要空港における国内線・国際線、出発・到着便のリアルタイム運航ステータスを取得します。

- **リクエスト (POST)**:
  ```json
  {
    "airport": "羽田",
    "type": "departure",
    "category": "domestic",
    "flightNumber": "ANA2421"
  }
  ```
- **リクエスト (GET)**: `GET /traffic/flight/羽田?type=departure&category=domestic`
- **レスポンス例**:
  ```json
  {
    "airportName": "東京国際空港(羽田空港)",
    "airportCode": "HND",
    "type": "departure",
    "category": "domestic",
    "updatedAt": "8月26日 16時10分 時点",
    "count": 1,
    "hasDelaysOrCancellations": true,
    "summary": "東京国際空港(羽田空港) 国内線 出発: 対象便数 1便。 (欠航: 1便, 遅延: 0便)",
    "flights": [
      {
        "scheduledTime": "06:10",
        "airline": "全日本空輸",
        "flightNumber": "ANA2421",
        "isCodeshare": true,
        "destinationOrOrigin": "那覇",
        "status": "欠航",
        "detail": "定刻06:10発 ANA2421便(羽田→那覇) は欠航です。"
      }
    ],
    "source": "yahoo-transit"
  }
  ```

---

### 3.18 米国CPSC適合証明書 eFiling完全義務化 & ACE免責判定 (`POST /trade/cpsc-check`)
HTSコードと製品情報から、米国CPSC管轄品目の適合証明書(GCC/CCC)発行要否、および2026年7月8日より完全義務化された米国税関(CBP)ACEシステムへの電子申告(eFiling: De Minimis免責除外なし)義務を判定します。対象年齢(`targetAge`)や素材が未確定の場合は先回りの推測を避け、`clarifyingQuestions`(確認質問)と `impactExplanation`(実務的影響)を返却します。非規制対象品や類似コード品に対しては通関保留エラー防止のためのACE免責申告コード(`disclaimerCodeHint`)を案内します。

- **リクエスト**:
  ```json
  {
    "htsCode": "9503.00.0073",
    "targetAge": "unknown"
  }
  ```
- **レスポンス例 (年齢未確定時)**:
  ```json
  {
    "certificateRequired": "unknown",
    "certificateType": "unknown",
    "eFilingRequired": false,
    "applicableRegulations": [ ... ],
    "inputCompleteness": "partial",
    "missingInputs": ["targetAge"],
    "clarifyingQuestions": [
      "この製品の対象年齢層は12歳以下の子供向けですか?それとも大人・一般向けですか?"
    ],
    "impactExplanation": "対象年齢が未確定のため証明書種別を確定できません。12歳以下の子供向け製品の場合はCPSC認定第三者試験機関による適合性試験とCPC作成、および2026年7月完全義務化のeFilingが必要です。大人向けの場合は一般適合証明書(GCC)となります。",
    "nextActions": [
      "不足情報(対象年齢など)を補って再判定してください。"
    ],
    "disclaimer": "本ツールは参考情報を提供するものであり、法的助言ではありません。..."
  }
  ```

### 3.19 米国FDA規制対象 実務判定 (`POST /trade/fda-check`)
HTSコードおよび商品情報から、米国CBP/FDA実務で機械的に用いられるPGAフラグ(FD1〜FD4)を判定し、Prior Notice要否やMoCRA、ACE免責(Disclaimer)申告コードを案内します。食器・調理器具等の食品接触物質(FD1)では `foodContact` 未指定時に先回り推測を行わず、`clarifyingQuestions`(飲食用途か装飾用か)と `impactExplanation` を返却します。

- **リクエスト**:
  ```json
  {
    "htsCode": "6912.00.4100",
    "productDescription": "Ceramic coffee mugs"
  }
  ```
- **レスポンス例 (食品接触用途未指定時)**:
  ```json
  {
    "fdaRegulatedLikely": true,
    "fdFlag": "FD1",
    "possiblePrograms": ["FCS"],
    "priorNoticeMayApply": false,
    "matchedSubheading": "6912",
    "confidence": "hts-flag-match",
    "inputCompleteness": "partial",
    "missingInputs": ["foodContact"],
    "clarifyingQuestions": [
      "この製品は飲食物に直接接触する用途(飲食・調理・保存等)ですか?それとも装飾・観賞用等の非食品用途ですか?"
    ],
    "impactExplanation": "本品目(FD1)は食品接触用途(飲食・調理用)である場合のみFDA食品接触物質安全基準(溶出試験等)が適用されます。装飾・工業用等の非接触用途であればACE通関時にDisclaimer(免責申告:コードA)が可能です。",
    "requiredActions": [
      "【FDA食品接触物質 (FCS)】食品・飲料用容器・食器の場合、FDA食品接触安全基準(溶出試験・鉛・カドミウム・BPA等)適合確認が必要です。非食品接触用途の場合はACE Disclaimerを申告してください。"
    ],
    "disclaimer": "本ツールは参考情報を提供するものであり、法的助言ではありません。..."
  }
  ```

### 3.20 HTS/HSコード実在確認・検証 (`POST /trade/hts-verify`)
LLM・利用者が推論したHTSコード候補を、米国USITC公式データ (hts.usitc.gov) と照合し実在確認・正式品目名・一般関税率を取得します。6桁サブヘディングまでしか一致しない場合は `clarifyingQuestions` で10桁統計細分の特定に必要な追加仕様をヒアリング誘導します。HTS Revision 18(大統領布告 PP 11059/11055)や通商法301条に基づくChapter 99特別追加関税の適用リスク・通関士確認手順もガイダンスします。

- **リクエスト**:
  ```json
  {
    "htsCode": "9503.00.00.11",
    "productDescription": "Stuffed plush toy doll for children under 3 years"
  }
  ```
- **レスポンス例(完全一致)**:
  ```json
  {
    "htsCode": "9503.00.00.11",
    "productDescription": "Stuffed plush toy doll for children under 3 years",
    "verified": true,
    "matchLevel": "exact",
    "hsCode": "950300",
    "officialDescription": "Under 3 years of age",
    "generalRate": "Free",
    "otherRate": "70%",
    "specialRate": "Free (AU, BH, CL, CO, ...)",
    "nearbyCandidates": [],
    "inputCompleteness": "complete",
    "impactExplanation": "米国USITC公式関税率表にて10桁統計細分コードの実在および一般関税率が確認されました。",
    "disclaimer": "本ツールは米国USITC公式データによる実在確認・関税率取得であり、法的な分類判断ではありません。...",
    "source": "usitc-hts"
  }
  ```

### 3.21 商品情報からのHTS/HSコード推測 (`POST /trade/hts-predict`)
商品名・説明文・素材・用途・対象年齢・食品接触有無から、セマンティックスコアリングと米国USITC公式API(hts.usitc.gov)を連携させた2段階ハイブリッド照合により、米国通関申告に必須となる10桁HTSコードおよび一般関税率・関連PGA規制(CPSC/FDA)を自動推測します。

> **多層防御・先回り推測の防止**: LLMが素材や対象年齢を一般論ででっち上げてツールを呼び出さないよう、スキーマとプロンプトで「不明な任意項目は省略すること」を徹底しています。品名のみ等の部分的な入力に対しても暫定推測結果を返しつつ、`missingInputs`(未指定項目)、`clarifyingQuestions`(LLMがユーザーへ確認すべき質問文)、`impactExplanation`(情報不足による関税率や規制の分岐説明)を返却し、自然な追加ヒアリングを誘導します。

- **リクエスト (品名のみの最小入力例)**:
  ```json
  {
    "productName": "Travel Coffee Mug",
    "description": "Insulated mug for hot drinks"
  }
  ```
- **レスポンス例 (動的ヒアリング誘導)**:
  ```json
  {
    "detectedSubheading": "6912.00",
    "category": "Tableware",
    "bestMatch": {
      "htsCode": "6912.00.4100",
      "description": "Mugs and other steins",
      "generalRate": "5.7%",
      "score": 32,
      "confidence": "high",
      "reason": "商品名・説明文から \"Tableware\" (Subheading 6912.00) と分類し、USITC公式品目定義とのセマンティック照合により最適コードを特定しました。",
      "cpsc": { ... },
      "fda": { "fdFlag": "FD1", "fdaRegulatedLikely": true, "possiblePrograms": ["FCS"] }
    },
    "candidates": [ ... ],
    "inputCompleteness": "partial",
    "missingInputs": ["material", "foodContact"],
    "clarifyingQuestions": [
      "製品の主要素材は何ですか?(例: 陶磁器、ガラス、プラスチック、ステンレス、木、綿など。素材の違いによってHTSコードおよび一般関税率が大きく変動します)",
      "この製品は飲食物に直接接触する用途(飲食・調理・保存等)で使用されますか?それとも装飾・観賞用等の非食品用途ですか?(食品接触用途の場合、FDAの事前通知(Prior Notice)や食品接触安全基準が適用されます)"
    ],
    "impactExplanation": "一部の情報(material、foodContact)が未指定のため、代表的な仕様を前提とした暫定的なHTSコード候補を提示しています。実務上、【素材の違いによりHTSコードおよび一般関税率が大きく変動(例: 0%〜20%以上)、食品接触用途の場合はFDA食品安全基準適用、非接触の場合はACE免責(Disclaimer)申告が可能】という重大な分岐が生じるため、正確な関税率算出および通関規制判定には追加情報の確認を強く推奨します。",
    "disclaimer": "本ツールは米国USITC公式データによる実在確認・関税率取得であり、法的な分類判断ではありません。..."
  }
  ```

---

### 3.22 商品統合コンプライアンス一括判定 (`POST /trade/compliance`)
商品ページのURL、または商品名・説明・素材・カテゴリから、HTS自動推測エンジンと連携し、HTS実在検証(関税率取得)、FDA実務PGAフラグ判定(食品・化粧品・食器等)、CPSC適合証明書(GCC/CCC)および2026年7月eFiling完全義務化判定を一連のパイプラインとして一括自動実行し、通関前アクションプランを含む総合診断レポートを返します。

- **リクエスト**:
  ```bash
  curl -X POST http://localhost:3016/trade/compliance \
    -H "Content-Type: application/json" \
    -d '{
      "productName": "Wooden Building Blocks for Toddlers",
      "description": "Educational wooden puzzle block toy for children aged 3+. Non-toxic paint."
    }'
  ```
- **レスポンス例**:
  ```json
  {
    "product": {
      "name": "Wooden Building Blocks for Toddlers",
      "description": "Educational wooden puzzle block toy for children aged 3+. Non-toxic paint.",
      "detectedCategory": "Toys",
      "targetAge": "child",
      "material": "wood",
      "htsCode": "9503.00.0073"
    },
    "overallStatus": "action_required",
    "summary": "CPSC規制対象 (CCC証明書作成 & eFiling電子申告が必須)",
    "htsVerification": {
      "htsCode": "9503.00.0073",
      "verified": true,
      "matchLevel": "exact",
      "generalRate": "Free"
    },
    "fda": {
      "fdaRegulatedLikely": false,
      "fdFlag": "none",
      "possiblePrograms": [],
      "priorNoticeMayApply": false
    },
    "cpsc": {
      "certificateRequired": true,
      "certificateType": "CCC",
      "eFilingRequired": true,
      "applicableRegulations": [
        {
          "cfr": "CPSC HTS Guidance List (2026年完全義務化施行)",
          "summary": "HTSコード \"9503.00.0073\" は \"Toys\" カテゴリとしてCPSC eFiling対象HTSリストに掲載"
        }
      ],
      "disclaimerCodeHint": "A (Not Regulated by CPSC) または B (Not Subject to Mandatory Standard)"
    },
    "htsPrediction": {
      "detectedSubheading": "9503.00",
      "bestMatch": {
        "htsCode": "9503.00.00.13",
        "description": "3 to 12 years of age",
        "generalRate": "Free",
        "score": 27,
        "confidence": "high"
      }
    },
    "actionPlan": [
      "【CPSC CCC】12歳以下の子供向け製品として、CPSC認定の第三者試験機関による適合性試験を実施してください。",
      "【CPSC CCC】試験結果に基づき Children’s Product Certificate (CCC) を作成・発行してください。",
      "【CPSC eFiling完全義務化】2026年7月8日以降、米国到着前にCBP ACEシステムへの電子申告(eFiling: フルメッセージセット送信またはProduct Registry事前登録)が必須です。",
      "【特別追加関税確認】HTS Revision 18等の大統領布告・通商法301条に基づくChapter 99特別追加関税の適用有無を通関業者にご確認ください。"
    ]
  }
  ```

---

### 3.23 画像取得 & マルチモーダル視覚入力 (`POST /media/inspect-image`)
WebページやX(Twitter)の投稿に含まれる画像URLを取得し、AIが視覚的に直接読み取れる形式(MCP `ImageContent` / Base64)に変換して返却します。タイムテーブル、告知チラシ、図表、領収書、スクリーンショットなどの画像内詳細情報をマルチモーダルAIが100%の精度で解読可能にします。

- **リクエスト**:
  ```json
  {
    "url": "https://example.com/timetable.jpg"
  }
  ```
- **レスポンス例**:
  ```json
  {
    "success": true,
    "url": "https://example.com/timetable.jpg",
    "mimeType": "image/jpeg",
    "sizeBytes": 284082,
    "markdown": "![画像](https://example.com/timetable.jpg)\n\n- **フォーマット**: `image/jpeg`\n- **サイズ**: 277 KB\n- **ステータス**: MCP ImageContent としてマルチモーダル視覚入力にロード完了",
    "imageContent": {
      "type": "image",
      "data": "/9j/4AAQSkZJRgABAQAAAQABAAD...",
      "mimeType": "image/jpeg"
    }
  }
  ```

### 3.24 荷物追跡・配達状況照会 (`POST /tracking`, `GET /tracking/:carrier/:number`, `GET /tracking/:number`)
日本の主要配送業者5社(ヤマト運輸、佐川急便、日本郵便、西濃運輸、福山通運)および国際配送の UPS の荷物配達状況をスクレイピング・API連携により横断追跡・正規化します。伝票番号(ハイフン有無・全角半角不問)のフォーマットや Modulus 7 / Luhn チェックサムによる運送会社自動判別に対応。並行投機照会の **Fail-fast 早期確定**(結果確定時に他社タイムアウトを待たず即時返却)および UPS 認証情報未設定時の安全な `status: "unknown"` フォールバックを備えています。5分間のインメモリキャッシュを内蔵。

- **対応キャリア**:
  - `yamato` (ヤマト運輸 / クロネコヤマト)
  - `sagawa` (佐川急便)
  - `japanpost` (日本郵便 / ゆうパック・書留)
  - `seino` (西濃運輸 / カンガルー便)
  - `fukutsu` / `fukuyama` (福山通運)
  - `ups` (UPS / United Parcel Service)
  - `auto` (自動判別: デフォルト)

- **リクエスト (POST /tracking)**:
  ```json
  {
    "trackingNumber": "1234-5678-9012",
    "carrier": "auto",
    "noCache": false
  }
  ```
- **リクエスト (GET /tracking/:number または GET /tracking/:carrier/:number)**:
  - `GET /tracking/123456789012` (自動判別)
  - `GET /tracking/yamato/123456789012` (キャリア指定)
  - クエリパラメータ: `?noCache=true` (キャッシュバイパス)

- **レスポンス例**:
  ```json
  {
    "carrier": "yamato",
    "carrierName": "ヤマト運輸",
    "trackingNumber": "123456789012",
    "status": "delivered",
    "statusText": "配達完了",
    "events": [
      { "date": "2026/09/08 18:20", "status": "荷物受付", "location": "東京ベース店" },
      { "date": "2026/09/09 08:15", "status": "配達中", "location": "渋谷センター" },
      { "date": "2026/09/09 14:30", "status": "配達完了", "location": "渋谷センター" }
    ],
    "trackingUrl": "https://toi.kuronekoyamato.co.jp/cgi-bin/tneko",
    "details": { "deliveryDate": "2026/09/09 14:30", "serviceType": "宅急便" },
    "cached": false
  }
  ```

---

### 3.25 公開SNS投稿検索・取得 (`POST /social/search` / `POST /social/fetch`)
Weibo新着検索とThreads/Instagram/Facebook公開投稿の発見+本文取得。追加費用・ログイン不要。Xは対象外のため `search_realtime` を使うこと。検索は最大55秒、取得は最大30秒の締め切り付き。

- **リクエスト (`POST /social/search`)**:
  ```json
  {
    "platform": "weibo",
    "query": "桜",
    "limit": 10,
    "lookbackHours": 24
  }
  ```
  `platform` は `weibo` / `threads` / `instagram` / `facebook`。`limit` は1〜30、`lookbackHours` は1〜2160。

- **リクエスト (`POST /social/fetch`)**:
  ```json
  {
    "url": "https://www.threads.com/@user/post/abc123",
    "commentLimit": 10
  }
  ```

- **レスポンス**: `status`(`ok` / `partial` / `empty` / `unavailable`)、`items`(投稿配列)、`matchedInWindow`、`unknownTime`、`failures`、`warnings` を返す。取得系は `post` 単体と `failures` / `warnings` を返す。

### 3.26 国・地域インテリジェンス (`POST /intelligence/country`, v2.27.0)

Evidence-backed country context via `POST /intelligence/country` and deferred MCP tool `research_country_context` (module `intel`, activate with `search_tools` query `国地域`).

- Request: `{ region, query?, topics?, period?: "7d"|"30d"|"90d", includeSocial?, noCache?, verbose? }`. Omitting `topics` queries every enabled provider within bounded two-pass caps (12 + 8).
- Report separates article/evidence count, event cluster count, and independent source counts. Publisher geography never becomes event geography. Ambiguous regions (e.g. `Georgia`) stay low-confidence.
- Region links: every evidence carries `regionLink` (`direct`/`related`/`candidate`/`unrelated`/`unknown`) with reasons plus `acquisition` (provider, record id, query, collection scope). `keyEvents` and all counts use only `direct`/`related`. Only region-query prose lands in `domainContext.general.candidateFactors`; unattributed global-feed records stay evidence-only. Empty domains return `factors_missing` instead of falling back to everything.
- Events keep per-record identity: same provider with different stable event ids never merges on title alone; records more than 72h apart never merge without a shared stable id. Occurrence/publication/update timestamps are stored separately (`timeBasis: structured|published`). Out-of-window finished events drop out; disasters continuing into the window stay.
- Coverage semantics: per-area `good`/`partial`/`limited`, `missingEvidence` lists areas without evidence, `unavailableProviders` lists failed providers. One provider failure yields a partial report, never 500.
- Providers: GDELT Events export files (in-memory yauzl unzip, no external `unzip`; DOC excluded from defaults until upstream recovers — return condition: DOC p95 under 8s for three consecutive days via `bun run test:intel:live`), GDACS API (8s) with one RSS fallback incl. timeouts (18s cap; `GDACS_API_FALLBACK_RSS`), USGS, EONET (both with ISO place-name attribution and coordinates preserved), region-matched news RSS (3 global + 10 regional: Al Jazeera/DW/France24/CBC/ABC-AU/NDTV/Yonhap/SCMP/Straits-Times/Nikkei-Asia; globals + country match, max 6 per request; live-verified 2026-09-22), official web search (Yahoo web search with region-dropping fallback disabled; curated official-domain seeds in `official_domains.ts` (37 domains, 20 countries) become verified `manual_seed` sources for pass-2 `site:` queries and `official_evidence`; Yahoo realtime never used, including Japan), Bluesky request search (public AppView `searchPosts`, latest 25, 8s cap; `includeSocial: true` to enable, `SORA_BLUESKY_DIDS` to restrict authors; 2026-09-22 observed: searchPosts returns 403 from server networks while other public endpoints return 200, so failures surface as provider errors and authenticated access is future work), World Bank (6 indicators with series), Nager holidays (with scope details), Wikidata (source discovery only), Google News country-edition RSS (q prefers the planned request query, region-name fallback; region-derived gl/hl/ceid, max 15), Wikipedia Current Events region bullets (MediaWiki API, max 10; live-verified), GDELT media-tone metric (AvgTone avg, no new fetch). Pass1 covers up to 16 providers, Baidu realtime hot list (CN-only, rank + hot index + tag; JSON API first, HTML second, TopHub mirror last with per-stage 5s/5s/8s timeouts and a 20s provider cap, keyless; direct verified from alternate egress, currently both direct and mirror are bot-gated from the JP verification network so failures stay honest errors); so360 query search (CN-only, 360 Search SSR with cookie-following redirect, data-mdurl publisher URLs, max 10, 14s cap; live-verified from JP network). Google News evidence uses source publisher URLs. Yahoo web search falls back to direct fetch when the MCP binary is rate-limited (429). Dropped: Google Trends daily (endpoint retired, persistent 404). Local processing failures surface as `PROVIDER_LOCAL_*`, never as fake upstream 5xx.
- Report v3 (`schemaVersion: "3"`, v2 still readable): first response embeds `evidenceDetails` for everything it cites plus an `enrichment` outcome. Article bodies are fetched by default with the built-in scraper (fast mode, no browser; `SORA_INTEL_SCRAPE=off` disables, falling back to an explicit `article_enrichment_unavailable` limitation). `SORA_INTEL_WEB_SEARCH=off` stops the `official_web` provider's real web search (the provider stays in the run and returns no items); tests use it to stay offline. Enrichment order is region link, then article count, then recency. Scraped headlines for title-less records land in `resolvedTitle` and lead the factor text. Headline-less GDELT rows resolve their `SOURCEURL` the same way. `actualWindows` derives from each provider's declared collection window (24h feeds / latest-15min exports never claim a full 30d). Whole-request deadline defaults to 29s (collection ≤18s worst case, enrichment bounded: 12 items, 3 concurrent, 4s each).
- MCP (`intel`, `search_tools` keyword country): `research_country_context`, `get_country_context`, `get_country_context_evidence`, `get_country_context_updates`. All four return text JSON plus validated `structuredContent`. REST mirrors them: `GET /intelligence/context/:contextId/evidence|updates`.
- No sentiment, hostility, anti-Japan, safety, or risk scores by design.
- Persistence: SQLite at `SORA_DB_PATH` (production: mount a volume and use `SORA_DB_PATH=/data/sora.db`). Reports retained 90 days, evidence excerpts and details 180 days. Retrieval: `GET /intelligence/context/:contextId`.
- Opt-in live smoke: `bun run test:intel:live`

### 3.27 Realtime / Web の compact 既定 (v2.27.0)

`search_realtime` / `search_web` / `search_deep` はデフォルトでcompact応答(回答必須項目のみ)。検索診断(`retrievalQueries` / `contributingQueries` / `resultsMerged`等)が必要な場合のみ `verbose: true` 指定。REST `/search/realtime`・`/search/web` も同様。X の `missingTerms`(空でない時)と `aliasTerms` は回答の欠落を判断する手がかりとして compact 応答にも含めます(v2.36.0)。MCP の `search_deep` と `search_realtime` は、整形(インデント)なしの JSON で返します(v2.36.1。`verbose: true` のときだけ整形あり)。別の結果と同じハイライトのページは、2つ目以降の `highlights` を省いて `highlightsSameAs`(先の結果の URL)を付けます。 (offline parser contracts; append `--live` for bounded South Korea/Taiwan/United States/France/Indonesia reachability).

### 3.28 Retrieval v2 / Security

単一 SERP はプロバイダ順を保持し、全体の BM25 並べ替えを行いません(診断・deep 選択用の局所スコアのみ)。X は recent/popular の意味を保つネイティブ順を維持し、汎用 Web リランカーで置き換えません。複数クエリ統合は `SORA_WEB_QUERY_UNION=true` で有効化し、加重 RRF(original 1.0、fallback/rescue 0.6)で統合します。scrape 失敗時は有効コンテンツ基準で補充します。認証付き scrape は共有キャッシュを使わず、クロスオリジン redirect では認証系ヘッダを除去します。`adaptiveScrape` / `enablePrf` はリクエスト単位の opt-in(デフォルト off)です。Yahoo 上流の 429 対策として共有ゲート+ブレーカー+429 後 fan-out 停止を備え、live 評価は間隔を空けた少量実行としてください。詳細は [docs/retrieval-v2-dod.md](docs/retrieval-v2-dod.md) と [docs/retrieval-v2-rollout.md](docs/retrieval-v2-rollout.md) を参照してください。検索・スクレイプの仕組みは [docs/search-scrape-mechanics.md](docs/search-scrape-mechanics.md) にまとめています。

### 3.29 Deep Search v2.32.0: 日付と追加取得

REST `POST /search`(別名 `/search/deep` / `/search/integrated` / `/deep-search`)と MCP `search_deep` は、同じ検索オプションを受け付けます。API仕様は `GET /openapi.json`、対話型ドキュメントは `GET /docs` と `GET /swagger` で確認できます。

```json
{
  "query": "君と見るそら 2026年10月11日 ライブ",
  "adaptiveScrape": true,
  "scrapeBudget": 8,
  "includeRealtime": true,
  "responseMode": "evidence",
  "verbose": false
}
```

- `adaptiveScrape`: 根拠不足時の追加取得を許可します。既定は `false`、`scrapeContent: true` の場合に有効です。
- `scrapeBudget`: 適応取得の上限。1〜20の整数、既定8、`limit` 未満の指定は `limit` まで引き上げます。
- 日付: 年付きの日付は指定年と照合します。年なしの月日はサーバー日時から次に到来する年を仮定します。過去の出来事は年を明示してください。`updated` はページの更新期間指定で、イベント開催日の指定ではありません。
- 時間表現: クエリの「明日」などはサーバー日時、本文への `annotateTemporal` 注記は記事の公開日時が基準です。すべての検索を新着順にはしません。
- 根拠の充足信号: `scrapeContent: true` の応答に `contextSufficiency: { level, reasons }` を付けます(応答内容は変えません。本文もハイライトも取得しない指定では付けません)。`level` は `no_gap_detected`(欠落を検出しなかった)/ `partial`(不足の根拠あり)/ `insufficient`(本文を取得できたページも投稿も無い)。`reasons` は `few-success`(取得成功が3件未満)、`unmentioned:語`(クエリの entity・intent 語がどの証拠にも出てこない)、`unanswered:語`(時刻・金額・日付など回答値を求める語に対して値が見つからない。「■料金」の次の行に金額が来る形は2文先まで探します)。要件語は verbose 診断の `webRequirements` と同じ `extractQueryRequirements`、証拠は各ページの ρSelect 選抜(`highlights`。無ければ本文)とXの投稿本文、判定は ρSelect v2 診断と同じ `computeEvidenceCoverage` です。スニペット代替・取得失敗・締切超過は証拠に数えません。語彙ベースの検出なので、`partial` / `insufficient` は不足の根拠になりますが、`no_gap_detected` は十分の保証ではありません(実測: 18クエリで誤検出0件、存在しない語・年の欠落など対照5件中3件を検出)。不足が示された場合は、`responseMode: "full"` での再取得や追加調査を検討してください。
- 診断: `verbose: true` で取得・証拠評価の診断を表示します。`verbose` は `responseMode: "evidence"` より優先し、全文も返します。

回答値・対象との関連・日付整合性の評価は辞書と規則に基づきます。Eval-100の人手ラベルは未完了であり、全用途の精度改善を実証済みという意味ではありません。適応取得・PRF・複数クエリ統合の既定値は有効化していません。

---

## 4. セキュリティ & アーキテクチャ

### 4.1 ディストロレス (Distroless) コンテナ設計
- **ベースイメージ**: `gcr.io/distroless/cc-debian12`
- **シェルなし・パッケージマネージャなし**: コンテナ内に `/bin/sh` や `apt`、`curl` は一切存在せず、攻撃者がシェルを奪取する余地がありません。
- **最小権限設計**: 非 root 実行に対応し、Docker / Podman / Kubernetes などの標準コンテナ環境で安全に隔離・実行可能。

### 4.2 セキュリティ & パフォーマンス機能
- **🛡️ 多重 SSRF & DNS Rebinding 防御**:
  - プライベート IP(`10.0.0.0/8`, `172.16.0.0/12`, `192.168.0.0/16`, `127.0.0.0/8` 等)、CGNAT(`100.64.0.0/10`)、IPv6 特殊アドレス、クラウドメタデータ IP(`169.254.169.254`)への内部アクセスを遮断。
  - `dns.promises.lookup` による事前名前解決を行い、ドメイン偽装による **DNS Rebinding 攻撃** も接続前に即時ブロック。
- **📸 フルページスクリーンショット & Lazy-load 自動スクロール (`fullPage: true`)**:
  - `formats: ['screenshot']` 時にページ最下部まで 1 枚の縦長画像として丸ごと撮影。自動スクロールにより遅延読み込み画像や動的要素を確実に描画させてから撮影(最大高さ 15,000px 安全ガード付き)。
- **🛍️ EC/Shopify DOM 剪定 & JSON-LD 在庫・価格メタデータ抽出**:
  - Shopify 等の EC サイトで隠し「売り切れ」バッジやカートモーダルを誤認して抽出するのを防止し、JSON-LD の `InStock` / `OutOfStock`、価格、ブランド、SKU を正確に抽出。
- **⚡ Single-Flight Cache (In-flight Deduplication)**:
  - 同一 URL への並行リクエスト発生時、Promise を共有して 1 回の外部通信に集約。Thundering Herd(キャッシュスタンピード)を防ぎ、外部サーバーとローカルリソースを保護。
- **🚦 ブラウザ同時実行制限 (Concurrency Control)**:
  - `SimpleSemaphore` により Chromium プロセスの同時実行数(`MAX_CONCURRENT_BROWSERS`、デフォルトは利用可能メモリから 1〜5 を自動算出)を安全に制御。サーバーの CPU/メモリ枯渇を防止。
- **🔒 Timing-Safe 認証 & 日次クォータ・レートリミット制御**:
  - API キー照合には `crypto.timingSafeEqual` + SHA-256(定数時間比較)を採用し、Timing Attack を防御。
  - Multi-turn ブラウザセッション(`sessionId`)を作成者トークンと暗号学的に紐付け、他者からのセッション乗っ取りを防止。
- **🩺 外部依存関係並行監視 & 管理者 Webhook アラート (`checkDetailedHealth`)**:
  - `GET /health?detailed=true` により SQLite、Chromium、Yahoo、気象庁、P2P地震情報、e-Gov への並行疎通確認を実施。
  - SQLite 障害で degraded 判定時に、`ADMIN_ALERT_WEBHOOK_URL` が設定されていれば管理者へ障害通知 Webhook を発火(外部依存の瞬断では発火しない)。
- **🛡️ 任意 JavaScript 実行の安全制御スイッチ (`ALLOW_BROWSER_EVALUATE`)**:
  - 環境変数 `ALLOW_BROWSER_EVALUATE=false` または `SAFE_BROWSER_MODE=true` により、`/browser/action` での `evaluate` スクリプト実行を即座に無効化・ロックダウン可能。
- **📐 共通 Zod スキーマ & OpenAPI 3.0 自動生成**:
  - REST / MCP 双方で Zod スキーマによる入力検証を統一。
  - `/openapi.json` はコード側の Zod スキーマから OpenAPI 3.0 仕様を **動的に自動生成** し、リクエスト・レスポンスのドキュメントがコードから乖離しないようにしています。
  - エラーレスポンスは `{ "error": "...", "code": "SSRF_BLOCKED", "status": 403, "retryable": false }` のように AI エージェントが自己修復・自律判断しやすい構造を提供。
- **💾 `bun:sqlite` による自己完結の永続化層 (Zero-Dependency SQLite)**:
  - Bun ネイティブの組み込み SQLite3 C エンジンを活用。
  - `PRAGMA journal_mode = WAL;` により、外部 DB デーモン(Redis / PostgreSQL)不要で高速な永続キャッシュ、API キー使用量カウント、watch/diff 差分履歴をローカルに安全保持。
  - プロセス再起動後も L2 SQLite からキャッシュを即座に復元するハイブリッド L1/L2 アーキテクチャ。

### 4.3 環境変数一覧 (Environment Variables)

Sora は 12-Factor App 原則に基づき、環境変数によってすべての動作・ネットワーク・セキュリティポリシーを一元管理します。

| 環境変数名 | デフォルト値 | 説明 |
|---|---|---|
| `PORT` | `8000` | HTTP / MCP サーバーのリッスンポート |
| `WEB_FETCHER_API_KEY` | *(未設定)* | **サーバー側の API 認証キー(最優先)**。設定時は `Authorization: Bearer <key>` または `X-API-Key` ヘッダーによる認証が必須化されます |
| `API_KEY` | *(未設定)* | `WEB_FETCHER_API_KEY` が未設定の場合に参照されるフォールバックの認証キー |
| `NODE_ENV` | *(未設定)* | プロセス環境の表示用。認証キーが未設定の場合は環境を問わず Fail-Open(認証なしで利用可能)。認証判断に NODE_ENV は使わない(bun build がビルド時にインライン化するため) |
| `ALLOW_LOCAL_NO_AUTH` | `false` | `true` の場合、`X-Forwarded-For` / `X-Real-IP` が付かない直接ローカル接続に限り API キー無しでのアクセスを許可します。**リバースプロキシ配下では有効化しないでください** |
| `ENABLED_MODULES` | `all` | 有効化するモジュール(カンマ区切り: `web,browser,yahoo,life,disaster,watch,music,gov,trade,media,intel` または `all`) |
| `SORA_SCRAPE_DEADLINE_MS` | `0`(無効) | 深層検索の本文取得の既定の打ち切り上限(ms)。リクエストの `scrapeDeadlineMs` が優先されます |
| `SORA_TOOL_OUTPUT_SCHEMA` | `false` | `true` で `tools/list` に各ツールの `outputSchema` を含めます。既定では省略してツール定義のサイズを抑えます(`tools/call` の `structuredContent` 検証は変わりません) |
| `SORA_DEFER_TOOLS` | `true` | 包括ツール初期公開ハイブリッドモード(13 コアツール+`search_tools`常時露出+特殊ツール遅延発見)を有効化するか。`false` で全 47 ツール静的一括ロード |
| `SORA_PROXY_URL` | *(未設定)* | Sora 専用プロキシ URL(最優先)。`http://`, `https://`, `socks5://` に対応 |
| `SORA_PROXY_LIST` | *(未設定)* | 静的fetch用プロキシURLのカンマ区切りリスト。設定時はリクエストごとにランダムでローテーション(`SORA_PROXY_URL`より優先)。SSRF対策のためMCP/RESTのリクエストパラメータからは指定不可 |
| `HTTP_PROXY` / `http_proxy` | *(未設定)* | 標準 HTTP プロキシ URL(Bun fetch および Chromium ヘッドレスブラウザに自動適用) |
| `HTTPS_PROXY` / `https_proxy` | *(未設定)* | 標準 HTTPS プロキシ URL(Chromium および外部 HTTPS 通信に自動適用) |
| `ALL_PROXY` / `all_proxy` | *(未設定)* | 標準汎用プロキシ URL(SOCKS5 等) |
| `NO_PROXY` / `no_proxy` | *(未設定)* | プロキシバイパス対象ホスト一覧(カンマ区切り、例: `localhost,127.0.0.1,.local`) |
| `MAX_CONCURRENT_BROWSERS` | *(メモリから自動: 1〜5)* | 同時に起動・実行を許可する Chromium ブラウザセッションの上限数。cgroup のメモリ上限(無ければ搭載メモリ)から `(メモリMB − 700) ÷ 300` を 1〜5 に丸めて決めます(1GB→1、2GB→4、4GB以上→5)。正の整数を指定した場合はそれが優先されます(上限50。数値でない値は無視して自動算出) |
| `BROWSER_IDLE_TTL_MS` | `300000` | 共有 Chromium が無操作のまま経過したら閉じるまでの時間(ms)。`0` で無効。次回のブラウザ利用時に自動で再起動します(実測: 常駐時 約925MB → 終了後 約197MB)。開いているブラウザセッションがある間は閉じません |
| `DAILY_REQUEST_LIMIT` | *(無制限)* | API キー別の日次最大リクエスト数(レートリミット制御) |
| `ALLOW_BROWSER_EVALUATE` | `true` | `false` 指定時に `/browser/action` での `evaluate`(任意JS実行)を完全遮断・ロックダウン |
| `ADMIN_ALERT_WEBHOOK_URL` | *(未設定)* | `GET /health?detailed=true` が degraded(SQLite 障害)の場合に送信する管理者アラート Webhook URL |
| `CHROME_PATH` / `CHROME_BIN` / `PUPPETEER_EXECUTABLE_PATH` | *(自動検出)* | Chromium 実行バイナリのパスを明示指定します(未指定時は標準パスと `PATH` を自動探索) |
| `SORA_DB_PATH` | `./data/sora.db` | SQLite データベースファイルのパス(キャッシュ・監視対象・ドメイン別 Cookie / localStorage を格納。ファイルは自動で `0600` に制限されます) |
| `LOG_FORMAT` | *(未設定)* | `json` を指定するとリクエストログを構造化 JSON で出力します |
| `ALLOW_LOCAL_FETCH` | `false` | `true` の場合、`localhost` / プライベート IP へのスクレイピングを許可します(SSRF 対策の緩和。**テスト用途のみ**) |
| `SORA_WEB_NATIVE_RANKING` | `true` | 単一 SERP をプロバイダ順で保持します。`false` で従来の BM25 全体並べ替え(`providerRank` は記録継続) |
| `SORA_RRF_ENABLED` | `true` | 複数クエリ統合に RRF を使用します。`false` で first-wins dedup |
| `SORA_WEB_QUERY_UNION` | `false` | `true` で Web 複数クエリ統合を有効化(opt-in)。デフォルトは逐次 first-nonempty |
| `SORA_X_SOURCE_ISOLATION` | `false` | `true` で X ソース分離を有効化(opt-in) |
| `SORA_REALTIME_ANCHOR` | *(有効)* | `off` で X 検索の固有名詞を守る緩和・別名検索・無関係な投稿の除外を止め、従来の緩和に戻します |
| `SORA_ALLOW_ANONYMOUS` | `false` | `true` でキー無し警告を抑止します。キー未設定時は値によらず Fail-Open(匿名アクセス可能。認証なしで公開する運用は意図した方針で、本番の fetcher.ikebun.jp は `true` を指定して警告を止めています)。キー設定時は無効なキーでのアクセスを `401` で拒否します |
| `TRUST_PROXY` | *(未設定)* | `true` で `X-Forwarded-For` を信頼します。リバースプロキシ配下でのみ設定してください |
| `SORA_ALLOWED_HOSTS` | *(未設定)* | MCP エンドポイント(`/mcp`・`/sse`・`/message`)が受け付ける Host のカンマ区切りリスト(例: `sora.example.com,localhost:3016`)。未設定なら `localhost`・`127.0.0.1`・`[::1]` を**ポート不問**で許可します(`-p 3016:8000` のようなポート割り当てでもそのまま接続できます)。設定した場合は、書いた Host だけをポート込みで厳密に照合します。LAN・公開ホスト名・リバースプロキシ経由で使うときは設定してください |
| `SORA_ALLOWED_ORIGINS` | `localhost`・`127.0.0.1`・`[::1]`(ポート無し/`PORT` 付き) | MCP に接続してよいブラウザの Origin のカンマ区切りリスト(例: `http://localhost:3016`)。Origin ヘッダーを送らない通常の MCP クライアント(Claude Desktop・Cursor・CLI など)には影響しません。ブラウザ上のクライアントから接続するときに設定します |
| `SORA_MCP_MAX_SESSIONS` | `100` | 同時に保持する MCP セッション数の上限(正の整数)。1 セッションは JS ヒープを約 3〜4MB 使います。上限に達すると、30 秒以上使われていないセッションのうち最も古いものを閉じて新しい接続を受け入れ、すべてが直近まで使われている場合は `503`(`Retry-After: 5`)で断ります。小さな VPS では小さく設定してください。発生は `/metrics` の `sora_mcp_session_evicted_total`・`sora_mcp_session_rejected_total` で確認できます |
| `SORA_OPENPOI_BASE_URL` | `https://api.openpoiapi.com` | search_poi endpoint |
| `SORA_X_DETAIL_PROVIDER` | *(有効)* | `off` で FxTwitter/FxEmbed による X 詳細補完を無効化します(fail-soft) |
| `SORA_YAHOO_MIN_INTERVAL_MS` | `500` | Yahoo プロバイダ呼び出しの最小間隔(ms)。共有ゲートでバーストを抑制します |
| `SORA_YAHOO_BREAKER_COOLDOWN_MS` | `120000` | 429 検出後のブレーカー冷却期間(ms)。期間中は即時失敗して `throttled` を返します |
| `SORA_YAHOO_THROTTLE` | *(有効)* | `off` でスロットル規律を無効化します(**テスト用途のみ**) |
| `SORA_WEB_RETRY_WAIT_MS` | *(deprecated)* | 初期spacingのoverrideとしてのみ使用。通常はProvider pressure controllerが制御します |

### 4.4 低メモリ環境での運用

- **ブラウザ描画の同時数は自動で絞られます**。`MAX_CONCURRENT_BROWSERS` を指定しない場合、cgroup のメモリ上限(無ければ搭載メモリ)から `(メモリMB − 700) ÷ 300` を 1〜5 に丸めて決めます。

  | 利用可能メモリ | 同時数の既定 |
  |---|---|
  | 1GB 以下 | 1 |
  | 2GB | 4 |
  | 4GB 以上 | 5 |

  1 ページあたり約 300MB は目安です。明示した値が優先されます。
- **Chromium は無操作で閉じます**(`BROWSER_IDLE_TTL_MS`、既定 5 分、`0` で無効)。次にブラウザが必要になったとき自動で再起動します(実測: 再起動後の最初のブラウザ描画も、起動済みの場合と同等の約 3.6 秒)。ブラウザセッション(`sessionId`)や追跡・SNS 取得でコンテキストが開いている間は閉じません。
- **実測の目安**: 起動直後 約 160MB、静的取得後 約 195MB、ブラウザ描画中 約 950MB(bun 約 250MB + Chromium 約 700MB)、解放後 約 200MB。
- **ブラウザを使わせたくないリクエスト**には `scrape` の `mode: "fast"`(静的取得のみ)を指定します。
- **ツール定義を軽くする**には、`tools/list` から `outputSchema` を省いたまま使います(既定。`SORA_TOOL_OUTPUT_SCHEMA=true` で含める)。MCP クライアント側にツール検索がある場合はそちらを使い、ない場合は `SORA_DEFER_TOOLS=true`(既定)で初期公開を 14 ツールに絞れます。

---

## 5. 謝意・クレジット (Acknowledgments)

`Sora` は、以下の優れたオープンソースプロジェクト、公開サービス、公的オープンデータ、およびライブラリ作者の皆様の素晴らしい貢献に支えられています。心より感謝申し上げます。

### 🗾 データソース & 着想元 (Data Sources & Inspirations)

- **Nominatim / OpenStreetMap**: [nominatim.org](https://nominatim.org/)(地名・住所の座標解決。データ © OpenStreetMap contributors, ODbL)
  - 住所・地名・ランドマーク名から緯度経度を解決できる公開APIの提供と運用に感謝いたします。Soraは問い合わせを1.1秒以上の間隔に制限し、成功結果を24時間キャッシュして利用しています。利用にあたっては、検索頻度やサービスを利用して料金を取る行為に関する注意を含め、提供元の利用条件をご確認ください。
- **OpenPOI API**: [API仕様・ドキュメント](https://docs.openpoiapi.com/)
  - 日本全国の施設POIを検索できる公開APIの提供に感謝いたします。Soraの施設検索では、施設名・所在地・座標とともに提供元の`licenses`および`attributions`を保持して返します。取得データの保存・再利用時もこれらの情報を保持してください。
- **気象庁(JMA)オープンデータ**: [jma.go.jp](https://www.jma.go.jp/)
  - 日本全国の高精度な気象予報・防災気象警報データおよび全国 1,800 以上のエリア定義データのオープン公開に深く感謝いたします。
- **P2P地震情報 (P2PQuake)**: [p2pquake.net](https://www.p2pquake.net/)
  - リアルタイムな地震情報・震度速報 API の公開に感謝いたします。(※商用利用時は開発元への事前利用申請が必要です)
- **e-Gov 法令 API(デジタル庁 / 総務省)**: [laws.e-gov.go.jp](https://laws.e-gov.go.jp/)
  - 日本の全現行法令オープンデータおよび e-Gov 法令 API v2 の一般公開に深く感謝いたします。
- **iTunes Search API** (Apple Inc.):
  - 公式な音楽メタデータ検索 API の提供に感謝いたします。
- **天気予報 API(livedoor 天気互換)設計着想**: [tsukumijima/weather-api](https://github.com/tsukumijima/weather-api) / [weather.tsukumijima.net](https://weather.tsukumijima.net/)
  - livedoor 天気互換フォーマットの分かりやすいスキーマ設計と長年のコミュニティ貢献に感謝いたします。
- **Yahoo Japan Search MCP**: [mouseos/Yahoo-Japan-Search-MCP](https://github.com/mouseos/Yahoo-Japan-Search-MCP)
  - Yahoo! JAPAN の画像・動画・ニュース・知恵袋・サジェスト検索の MCP 実装に感謝いたします。
- **norikae-mcp**: [tysonwu/norikae-mcp](https://github.com/tysonwu/norikae-mcp)
  - Yahoo! 路線情報スクレイピングによる乗換案内ロジックの設計・実装に感謝いたします。

### 🛠️ 基盤オープンソース・ライブラリ (Core Libraries & Ecosystem)
- **[Hono](https://hono.dev/)** ([@yusukebe](https://github.com/yusukebe)) — 超高速 Web API フレームワーク & MCP 統合
- **[Puppeteer](https://pptr.dev/)** (Google Chrome Team) — ヘッドレス Chromium 制御・ステルス操作
- **[Readability](https://github.com/mozilla/readability)** (Mozilla) — リーダーモード記事本文抽出エンジン
- **[Cheerio](https://cheerio.js.org/)** (cheeriojs team) — 高速 DOM 解析 & メタデータ抽出
- **[Turndown](https://github.com/mixmark-io/turndown)** ([Dom Christie](https://github.com/domchristie)) — HTML to Markdown コンバーター
- **[LinkeDOM](https://github.com/WebReflection/linkedom)** ([Andrea Giammarchi](https://github.com/WebReflection)) — 超軽量インメモリ DOM エンジン
- **[unpdf](https://github.com/unjs/unpdf)** (UnJS Team) — 高速・軽量 PDF テキスト抽出
- **[wreq-js](https://github.com/sqdshguy/wreq-js)** ([@sqdshguy](https://github.com/sqdshguy)) — TLS / HTTP 指紋偽装 & 高速静的フェッチエンジン
- **[Model Context Protocol SDK](https://github.com/modelcontextprotocol)** (Anthropic / MCP Team) — 次世代 AI ツール接続規格

---

## 6. 免責事項 (Disclaimer)

- **非公式サードパーティ製ツール**:
  - 本ソフトウェアは、個人開発・学術研究・自社内利用を目的として開発された非公式(サードパーティ製)ツールです。
- **商標について**:
  - 「Yahoo!」「Yahoo! JAPAN」および各サービス名は、LINEヤフー株式会社の商標または登録商標です。
  - 「Apple」「iTunes」「Apple Music」は、Apple Inc. の商標です。
  - 本プロジェクトは各社とは一切関係ありません。
- **利用規約・法令の遵守 & 商用利用の注意**:
  - 各外部サービス(Yahoo! JAPAN、気象庁、P2P地震情報、iTunes 等)へのアクセスにあたっては、相手先サービスの利用規約、ガイドライン、robots.txt、および適用法令を遵守し、過度な負荷をかけないよう利用者自身の責任においてご利用ください。
  - P2P地震情報の商用利用を行う場合は、利用者の名義にて P2PQuake 開発元への事前利用申請を行ってください。
- **責任の限定**:
  - 本ソフトウェアの利用により生じたいかなる損害(相手先サービスからのアクセス制限、データの完全性・正確性・最新性等を含む)について、本プロジェクトの開発者は一切の責任を負いません。

---

## 7. ライセンス (License)

本ソフトウェアは **[Business Source License 1.1 (BSL 1.1 / BUSL-1.1)](LICENSE)** の下で公開されています。

- **自由・無料にご利用いただける用途**:
  - 個人開発、学術研究、非商用利用
  - 企業・組織内での自社システム向けセルフホスト利用(自社製品や社内ツールを支える内部バックエンドとして動作させること)
  - ソースコードの改変・フォーク・内部共有
- **禁止事項 (Restriction)**:
  - 本ソフトウェア(またはその派生物)を、第三者向けの「有料クラウドサービス」「有料スクレイピング / 検索 API サービス」「マネージドサービス」として提供・再販すること。
- **Change Date (オープンソース転換日)**:
  - **2030年8月1日**(またはそれ以前)に、自動的に完全な **MIT License** に転換されます。

詳細については [LICENSE](LICENSE) をご確認ください。

Copyright (c) 2026 ikeno

## 8. 開発時の検証 (Development & Testing)

```bash
bun install --frozen-lockfile
bun run typecheck
NODE_ENV=test SORA_DB_PATH=:memory: bun test --timeout 60000
```

ブラウザを使うテストには Chromium/Chrome が必要です。検出できない場合は `CHROME_PATH` に実行ファイルを指定してください。

通常スイートは外部ネットワークに出ません。`src/test_preload.ts` がテストの開始時にプロキシの環境変数を閉じたポートに向け(手元のテスト用サーバーは `NO_PROXY` で除外)、外部への接続をすぐ失敗させます。USITC・iTunes・気象庁・P2P地震情報・Yahoo! 道路交通情報は、`src/test_fixtures/external_apis.ts` の固定応答で確かめます。

実サイト・実 API の応答に依存するテストは `SORA_LIVE_TESTS=1` で明示的に有効化します(このときは外部への接続も固定応答も使わず、本物に問い合わせます)。

```bash
SORA_LIVE_TESTS=1 NODE_ENV=test SORA_DB_PATH=:memory: bun test src/services/tracking.test.ts --timeout 60000
```

通常CIでは佐川の未登録応答・HTTP 403/429/503・通信失敗を固定応答で検証します。GitHub Actions の Test ワークフローは失敗時のログ全文と失敗一覧を表示し、JUnitと実行ログを7日間保存します。

Maintenance

ActivityActive
ResponsivenessNo issues