開発ブログ

BLOG

AI エージェントが使いやすいサイトにするためにしたこと

Claude などの AI のアプリに Metronome.fm をつなぐと、保存した設定や練習の記録を AI に読んでもらえるようになりました。サイトが AI エージェントから使いやすいかを点数で出す isitagentready.com で、20 点を 93 点にするまでにしたことを、項目ごとに書きます。

公開 2026年11月13日

Cloudflare の isitagentready.com は、サイトが AI エージェントから使いやすいかを点数で出すサービスです。Metronome.fm を調べてもらうと、100 点のうち 20 点で、Level 1 でした。1 日かけて、項目ごとに必要なものを作り、93 点・Level 5(Agent-Native)まで上げました。

isitagentready.com の結果。総合 20 点・Level 1。分野ごとの点数(番号 1)は Discoverability 2/4、Content 0/1、Bot Access Control 1/2、API, Auth, MCP & Skill Discovery 0/8
対応する前の結果
  1. 分野ごとの点数。いちばん項目の多い API, Auth, MCP & Skill Discovery の分野は、8 項目すべて不合格でした

点検の項目の多くは、「エージェントが読みに来る決まった場所に、決まった形のファイルを置いてあるか」を見ます。ただ、ファイルだけを置いても、エージェントがその先で何もできなければ意味がありません。そこで、ファイルが案内する先の API も、実際に作ることにしました。その結果、サインインした人が AI のアプリから自分の設定や練習の記録を読める MCP サーバーまで作りました。

この記事では点検の項目ごとに何を用意したかを書きます。

何を点検しているか

点検の項目は 4 つの分野に分かれています。

分野
見ていること
Discoverability(見つけやすさ)
robots.txt・サイトマップ・応答の Link ヘッダー・DNS のレコードで、マニュアルや API の一覧の場所を示しているか
Content(中身)
エージェントが頼んだら、ページを Markdown で返すか
Bot Access Control(クローラーの扱い)
robots.txt に、AI のクローラーへの決まりと Content-Signal があるか
API, Auth, MCP & Skill Discovery
エージェントが使える API・MCP サーバーと、そのサインインの方法を案内しているか

物を売るサイト向けの Commerce の分野もありますが、Metronome.fm は販売のサイトと判定されず、点数に入りませんでした。

robots.txt と Link ヘッダー

まず、手間の少ない 2 つから対応しました。

robots.txt には Content-Signal の行を書きました。サイトの中身を、検索・AI の回答での引用・AI の学習のそれぞれに使ってよいかを宣言する行です。Metronome.fm は多くの機能を無料で使えるメトロノームで、AI に答えの中で紹介してもらえるほうがありがたく、学習に使われて困る中身もないので、3 つとも許可しました。

User-Agent: *
Allow: /
Content-Signal: search=yes, ai-input=yes, ai-train=yes

トップページの応答には Link ヘッダーを付けました。マニュアルを service-doc(使い方の説明)として、API の一覧(後で書く MCP サーバーへの行き先)を api-catalog として示します。エージェントはページの本文を読む前に、ヘッダーだけで行き先がわかります。

link: </docs/en/manual>; rel="service-doc", </.well-known/api-catalog>; rel="api-catalog"

同じ URL で Markdown を返す

エージェントが Accept: text/markdown を付けてページをリクエストしたら、HTML ではなく Markdown を返すようにしました。対象はトップページ・マニュアル・開発ブログです。エージェントは HTML から本文を抜き出さずに済みます。

振り分けは Next.js でリクエストを最初に受ける proxy.ts(Next.js 16 で middleware.ts から名前が変わったファイル)で行います。Markdown を求められたら、Markdown を返す Route Handler へ行き先を切り替えます(rewrite)。ブラウザは text/markdown を求めないので、ふだんの表示は変わりません。*/* や text/* では Markdown にせず、text/markdown がはっきり書かれているときだけにしました。

const rewriteToAgentMarkdown = (request: NextRequest) => {
  if (request.method !== "GET" && request.method !== "HEAD") return null;
  if (!acceptsMarkdown(request.headers.get("accept"))) return null;
  const markdownPath = agentMarkdownPathOf(request.nextUrl.pathname);
  if (!markdownPath) return null;
  const response = NextResponse.rewrite(new URL(markdownPath, request.url));
  response.headers.set("vary", "Accept");
  return response;
};

Markdown はビルドのときに作っておきます。マニュアルの本文は画面の文言と一緒に言語ごとの JSON のファイルに入れているので、そこから作り、ブログの記事は MDX から作ります。MDX の <Figure> などの部品は画像のリンクと説明の文に置き換えます。

気をつけたのはキャッシュです。同じ URL で中身が 2 通りになるので、CDN が Markdown の応答をキャッシュして、それをブラウザに返すと、トップページに Markdown の文字がそのまま並んでしまいます。Markdown の応答には、Accept によって中身が変わることを示す Vary: Accept を付けています。本番に出したあと、ブラウザと同じ Accept と text/markdown を交互に送りました。どちらもキャッシュから返り(x-vercel-cache: HIT)、HTML と Markdown が入れ替わることはありませんでした。

Markdown を返す Route Handler の URL(/agent-markdown/…)を直接開いたときは、X-Robots-Tag: noindex を付けています。同じ中身のページが検索に 2 つ出ないようにするためです。

トップページのメトロノームを WebMCP のツールにする

WebMCP はページでできる操作を、ブラウザの中で動く AI エージェントにツールとして渡す仕組みです。アプリの画面(/app)にはすでにツールを登録していましたが、点検はブラウザでトップページ(/)を開いて調べます。そこで、トップページの先頭で鳴らせるお試しのメトロノームに、5 つのツールを登録しました。

  • 今のテンポと、鳴っているかを読む
  • テンポを変える(40〜300 BPM)
  • 鳴らす
  • 止める
  • アプリを開く

登録は React のコンポーネントの中ではなく、HTML に書いたインラインの script で行います。ページの読み込みが終わった時点で、ツールがそろっているようにするためです。本番の点検では、5 つのツールが見つかったと出ました。

自分のデータを AI に読ませる MCP サーバー

いちばん項目の多い API, Auth, MCP & Skill Discovery の分野は、エージェントが使える API があり、そのサインインの方法を案内しているかを見ます。この分野のために、Claude などの AI のアプリからつなぐリモートの MCP サーバーを https://metronome.fm/mcp に作りました。つなぎ方はマニュアルの「Claude や ChatGPT とつなぐ(MCP)」に書いています。

ツールは読むだけの 4 つです。

ツール
返すもの
list_saved_settings
保存した設定の一覧
get_saved_setting
1 つの設定の中身(テンポ・拍子など)
get_practice_statistics
練習の統計
list_practice_schedules
練習の予定

書き込むツールは作りませんでした。AI の判断で設定を消したり書き換えたりできると、AI がだまされて、利用者の頼んでいない操作をしたときの被害が大きくなるためです。呼び出しの回数にも 1 人ごとの上限を付けています。

サインインは Clerk に任せる

Metronome.fm のサインインには Clerk を使っています。Clerk は OAuth の認可サーバー(サインインを確かめてトークンを出す側)にもなれるので、MCP のサインインもそのまま任せました。流れはこうです。

  1. AI のアプリがトークンなしで /mcp を呼ぶと、401 が返る。WWW-Authenticate ヘッダーで、このサーバーのメタデータ(Protected Resource Metadata)の場所と、求める権限の範囲(スコープ。profile)を伝える
  2. AI のアプリはそのメタデータから Clerk の認可サーバーを知り、利用者を Clerk のサインインと許可の画面に送る
  3. 利用者が許可すると、AI のアプリはアクセストークンを受け取り、それを付けて /mcp を呼び直す

/mcp では、トークンが Clerk の出したもので、宛先(aud)がこのサイトか /mcp であることを確かめます。

const requestState = await clerkClient.authenticateRequest(request, {
  acceptsToken: "oauth_token",
  audience: [origin, mcpResourceUrlOf(origin)],
});

つまずいたのは、proxy.ts の中で全ページに対して動かしている Clerk のミドルウェアです。Clerk は Cookie のないリクエストを、セッションを確かめるために別の URL へ転送します(307)。MCP のクライアントは Cookie を持たないので、/mcp に来たとたんに転送されてつなげませんでした。/mcp と /.well-known/ の下へのリクエストは、proxy.ts で Clerk のミドルウェアを動かさずにそのまま渡し、トークンは /mcp の中で確かめる形にしています。

AI のアプリの登録は CIMD だけを受け付ける

OAuth では、トークンを受け取るアプリ(クライアント)を認可サーバーに登録しておく必要があります。MCP では、前もって登録しなくてもつなげる方法が 2 つあります。

  • CIMD(Client ID Metadata Document): クライアントの ID が自分の情報(名前・サインインのあとに戻る URL など)を書いた JSON の URL になっている。認可サーバーはその URL を読んでクライアントを知る
  • DCR(Dynamic Client Registration): クライアントがつなぐときに認可サーバーへ自分を登録する

Clerk の設定の画面では、DCR を有効にする欄に「Deprecated」(非推奨)と付いていました。DCR では誰でもクライアントを登録できるので、本物のアプリに似せた名前で登録して、利用者に許可の画面を出させることもできます。そこで CIMD だけを受け付け、DCR は切りました。

Clerk の MCP サーバーの確認の結果。番号 1 は Server metadata 2/2 Passed、OAuth discovery 3/3 Passed、Scope guidance Passed の 3 行
Clerk の管理画面にある、MCP サーバーの確認
  1. 401 の返し方・サーバーのメタデータ・認可サーバーの案内・スコープの案内が、すべて合格しています

Clerk の管理画面に MCP サーバーの URL を登録しておくと、外からその URL に問い合わせて、401 の返し方やメタデータを確かめてくれます。本番に出したあとに確かめると、すべて合格でした。最後に、CIMD に対応している Claude Code から本番の /mcp につなぎ、ツールを呼べることも確かめています。

見つけてもらうための案内

MCP サーバーができたので、エージェントがそこへたどり着くための案内を /.well-known/ の下などに置きました。

置き場所
書いたこと
/.well-known/oauth-protected-resource
サーバーのメタデータ(Protected Resource Metadata)。どの認可サーバー(Clerk)でサインインするか。/mcp 用の …/oauth-protected-resource/mcp も置いた
/.well-known/oauth-authorization-server
Clerk の認可サーバーのメタデータ。Clerk ではなく metronome.fm の上にこれを探しに来る古いクライアントのために、Clerk のものをそのまま返す
/.well-known/api-catalog
API の一覧。MCP サーバーと、その説明のページへの行き先
/.well-known/mcp/server-card.json
MCP サーバーの名前・つなぎ方・ツールの一覧
/.well-known/agent-skills/index.json
エージェント向けの手引き(Agent Skills)の一覧。Metronome.fm の使い方(アプリの開き方・WebMCP・Markdown・MCP サーバー)を書いた手引きを 1 つ
/.well-known/ai-catalog.json
AI 向けに使えるものの一覧(ARD。Agentic Resource Discovery)
/auth.md
エージェントがサインインしてデータを読むまでの手順

DNS にも案内を置きました。DNS-AID(DNS for AI Discovery)は、_mcp._agents.metronome.fm に SVCB というレコードを置いて、MCP サーバーのありかを DNS で知らせる仕組みです。点検は、レコードが DNSSEC で署名されていて、偽物でないと確かめられることも見ます。DNSSEC は Cloudflare の管理画面で有効にしました。

_mcp._agents.metronome.fm. 300 IN SVCB 1 metronome.fm. alpn=h2 port=443

93 点と、残った 1 つ

本番に出して調べ直すと、93 点・Level 5 でした。

isitagentready.com の結果。総合 93 点・Level 5 Agent-Native。Discoverability・Content・Bot Access Control は 100、API, Auth, MCP & Skill Discovery(番号 1)は 88 で 7/8
本番に出したあとの結果
  1. API, Auth, MCP & Skill Discovery の 8 項目のうち、auth.md だけが不合格のまま残りました

不合格のまま残ったのは auth.md です。/auth.md は置きましたが、点検はそれに加えて、認可サーバーのメタデータに agent_auth という項目があるかを見ます。agent_auth は、エージェントが自分で登録し、あとから利用者が「このエージェントは自分のものだ」と結びつけるための URL を示す項目です。

この登録を受け付ける処理は、トークンを出す認可サーバー自身が持つ前提になっています。Metronome.fm の認可サーバーは Clerk なので、Clerk が対応しない限り、作れません。メタデータに agent_auth を書き足すだけなら点数は取れますが、示した URL では何も動かないので書きませんでした。auth.md の仕様もまだ版がどんどん上がっている段階なので、Clerk の対応を待つことにしています。

この記事を共有

X でポストはてなブックマーク