llms.txtとMCPで作る、AIエージェント向けニュースポータル実践記

Webサイトの「読者」が人間からAIエージェントへ広がりつつある。llms.txt や MCP(Model Context Protocol)といったエージェント向けの規格が次々と登場するなか、「実際にエージェントを一級の読者としてサイトを設計すると何が必要になるのか」を確かめるため、AIエージェント専用のニュース/CVEポータル(portal.chinng-lab-srv.dev)を自宅サーバー上に構築・公開した。本記事では、その設計原則と実装の勘所をパイプライン設計・discovery層・ライセンス制御の3つの軸で紹介し、あわせてAIエージェントから実際にこのポータルを利用する方法をまとめる。

AIエージェント向けニュース・脆弱性ポータル / Agent-Readiness Directory
ニュース記事とCVE/脆弱性アドバイザリをMCP/REST APIでメタデータ中心に提供し、他サイトのAgent-Readiness(llms.txt/MCP/API catalog対応度)を採点するディレクトリ。

背景: 読者が人間からエージェントに変わると、サイトの設計が変わる

ChatGPT や Claude のようなアシスタントがWebを読む時代になり、サイト側にも「AIに読まれるための構造」が求められ始めている。サイトの全体像をプレーンテキストで示す llms.txt、エージェントがツールとしてサイト機能を呼び出せる MCP、robots.txt の AI 向け拡張である Content Signals など、対応すべき項目は増える一方だ。実際、X(旧Twitter)の開発者向けドキュメントも llms.txt・skill.md・MCPサーバーをまとめた「エージェント向けリソース」ページを公開しており、これはもう実験ではなく実務のトレンドになっている。

ただし、既存の人間向けサイトに後付けで llms.txt を置くだけでは、エージェントにとって使いやすいサイトにはならない。エージェントには人間と違う制約があるからだ。代表的なものは次の3つ。

  • コンテキストウィンドウが有限: 全文を読ませるのはコストが高い。メタデータだけで読む/読まないを判断できる必要がある
  • HTMLの装飾が邪魔: 欲しいのはナビゲーションやCSSではなく、構造化された本文とメタデータ
  • 機械的にアクセスする: 発見(discovery)から取得までが機械可読な規約で繋がっている必要がある

そこで今回は「人間向けサイトのAI対応」ではなく、最初からAIエージェントだけを読者と想定したポータルを作ることにした。設計目標は一文で表せる。「エージェントがメタデータだけで取捨選択でき、先頭数百トークンで要点が完結する」ことだ。

設計その1: Markdownを正典とする非同期パイプライン

ポータルの本体は6コンテナ構成のパイプラインだ。クローラが記事を投入し、非同期でエンリッチ(要約・翻訳・グラフ照会)して、Remote MCP でエージェントに提供する。

クローラ → ingest-api → Markdown(正典) + SQLite(索引)
                ↓
             worker(非同期エンリッチ: 要約→翻訳→グラフ照会)
                ↓
           portal-mcp / nginx → AIエージェント

中核にある設計原則は責務分離だ。入口となる ingest-api は決定的・同期処理のみを担当し、LLMを一切使わない。LLM要約・機械翻訳・ナレッジグラフ照会といった「不確実で遅い処理」はすべて worker が非同期・リトライ前提で行う。この分離により、ローカルLLMや翻訳サービスが落ちていても記事の投入は止まらず、復旧後に worker が自動で追いつく。

データストアは2層に分けた。Markdown(YAML frontmatter付き)が source of truth で、SQLite はそこから再構築可能な導出インデックスに過ぎない。DBが壊れてもコマンド一発で Markdown から作り直せるため、スキーマ変更やデータ移行への耐性が高い。

記事フォーマット自体もエージェント向けに最適化している。frontmatter には要約(日英)・タグ・エンティティ・ライセンス区分を持たせ、本文は TL;DR / Key Points / Details / Source のセクションに機械分割できる構造(1セクション200〜400トークン目安)にした。コンテキストを浪費させない、という設計目標がそのままデータモデルになっている。

設計その2: discovery層 — エージェントに「発見」してもらう

作ったコンテンツをエージェントに発見してもらうには、discovery 層が要る。第二フェーズとして nginx を追加し、以下を実装した。

  • robots.txt + Content Signals: 検索・AI入力・AI学習の可否を明示
  • llms.txt / llms-full.txt: カテゴリ別の入口地図と、ライセンス分岐した全文連結
  • sitemap.xml + Link ヘッダ(RFC 8288): 機械可読な導線
  • MCP Server Card: .well-known/mcp/server-card.json でMCPサーバーの存在と機能を宣言
  • API Catalog(RFC 9727)Agent Skills index: .well-known/ 配下でAPI・スキルを公開
  • Markdown Negotiation: Accept: text/markdown を送ると、同じURLでHTMLではなくMarkdownを返す
  • WebMCP: navigator.modelContext でページ内のJS関数をブラウザ内エージェントにツールとして露出

ここで得た最大の教訓は、discovery は手書きせず、正典から生成することだ。記事は毎日増えるので、静的に書いた sitemap や llms.txt は即座に腐る。このポータルでは正典Markdown+SQLiteから discovery 一式を冪等に生成するジェネレータを worker に持たせ、クロールバッチ後の cron で更新している。MCP Server Card や Agent Skills の内容も MCP サーバーの実体(ツール定義)から生成するため、「カードに書いてある機能と実際のツールがズレる」事故が構造的に起きない。

なお OAuth 系のメタデータは意図的に見送った。実際の認証基盤を持たないのに .well-known/openid-configuration だけ置くのは、それを信じて動くエージェントに対して不誠実だと考えたからだ。discovery は「持っている実体の宣言」であるべきで、体裁のための空手形を切るべきではない。

設計その3: ライセンス分岐とCVE配信 — 「配ってよいもの」の線引き

エージェント向けに再配信するポータルで最初に向き合うべきは、実は技術ではなく再配布ライセンスだ。クロールした第三者のニュース記事を全文再配布することはできない。そこで記事ごとに license_note という区分(full / summary-only / link-only)を持たせ、MCP応答・llms-full.txt・Markdown配信のすべてのレイヤで同じ分岐を共有する。第三者ソースの記事はリンクとメタデータ(エンティティ・関連記事)のみを露出し、逐語的な要約や本文はそもそも正典Markdownに書かない。「配らないものは保存段階から持たない」ことで、どのレイヤからも漏れない構造にした。

一方で、面白い発見もあった。CVE/脆弱性情報の配信を追加するにあたり OSV.dev のライセンスを調査したところ、上流データベース(GHSA・PyPA は CC-BY、NVD はパブリックドメイン、Ubuntu は CC-BY-SA)はすべて再配布可能だった。つまりニュースとは逆に、CVEは全文を full で配ってよい。この調査を踏まえ、依存パッケージの watchlist を OSV.dev に日次照会する osv-ingester を追加し、news/*security/* のカテゴリ名前空間で分離配信している。


AIエージェントからポータルを使う

では、エージェント側から見るとこのポータルはどう使えるのか。利用経路は大きく3つある。

① MCP経由(推奨)。 MCPクライアント(Claude Code / Claude Desktop など)に https://portal.chinng-lab-srv.dev/mcp を streamable-http のリモートサーバーとして登録すると、5つのツールが使えるようになる。

  • portal_list — 本文を含まないメタデータ一覧(トークン軽量)。category="news" / category="security" のプレフィックスでニュースとCVEを絞り込める
  • portal_search — キーワード検索。タイトル・英語要約・エンティティ名が対象で、複数キーワードはAND条件
  • portal_get — IDを指定して記事を取得。license_note に応じて全文/要約のみ/リンクのみが返る
  • portal_list_agent_surfaces / portal_get_agent_surface — 後述の Agent-Readiness ディレクトリの一覧と、ドメイン単位の詳細評価

推奨フローは「portal_list(または portal_search)でメタデータを眺める → 読むべきIDを選ぶ → portal_get で本文を取る」の二段階アクセスだ。一覧の段階で要約・タグ・エンティティが返るため、エージェントは本文を読む前に取捨選択でき、コンテキストを節約できる。

② HTTP + Markdown直取得。 MCPクライアントを持たない、HTTP GETしかできないエージェントでも全機能をたどれる。入口は /llms.txt で、カテゴリ別の入口地図(現在ニュース11カテゴリ+セキュリティ2カテゴリ)と利用方法が書いてある。新着はカテゴリごとの /feeds/<category>.md、記事本体は /news/<category>/<id>.md でMarkdownのまま取得できる。トップページも Accept: text/markdown ヘッダを付ければHTMLではなくMarkdownが返るので、HTMLパーサーは一切不要だ。

③ discovery からの自動発見。 事前知識ゼロでドメインに到達したエージェントも、標準の置き場所をたどれば上記の入口に着く。robots.txt(Content Signals 付き)と sitemap.xml はクローラ向けの従来導線として、.well-known/mcp/server-card.json はMCPエンドポイントとツール定義の宣言として、.well-known/api-catalog はAPI一覧として機能する。①も②も、この discovery 層から機械的に発見できるようになっている。


影響と今後: ディレクトリ化と、エージェントWebの相互運用

このポータルは現在、次の段階として Agent-Readiness Directory に取り組んでいる。GitHub Code Search・SearXNG・Tranco(上位100万ドメイン)から llms.txt を公開しているサイトを発見し、robots.txt・sitemap・API catalog・MCP server card などのエージェント向けサーフェスの充実度を採点してディレクトリ化する試みだ。自サイトを Agent-Ready にする段階から、「WebのどこがAgent-Readyなのか」をエージェント自身が調べられるインフラへ、一歩進めようとしている。

個人の実験プロジェクトではあるが、得られた知見は汎用的だと考えている。エージェント向けサイトを作る(あるいは既存サイトを対応させる)なら、次の3点が要点になる。

  1. メタデータ先行の二段階アクセス: 一覧APIで要約を返し、本文は選択的に取得させる
  2. discovery は実体から生成: 手書きの llms.txt や server card は必ず実体とズレる
  3. ライセンス区分を全レイヤで一貫: 露出制御は配信時ではなく保存時から始める


まとめ

AIエージェントを一級の読者としてサイトを設計してみると、「人間向けサイト+α」では見えない論点が次々に現れた。コンテキストを浪費させないAPI設計、正典から生成する discovery、再配布ライセンスの構造的な担保——いずれも後付けでは難しく、データモデルの段階から織り込む必要があった。llms.txt や MCP への対応を検討しているなら、チェックリストを埋める前に「エージェントは何に困るか」から設計を始めることをお勧めしたい。ポータルは portal.chinng-lab-srv.dev で公開している。まずは /llms.txt を取得するか、MCPクライアントに /mcp を登録して、エージェントから実際に叩いてみてほしい。

参考ソース

関連記事