推しチームの公式サイトをMCPサーバーにしたら「次の試合いつ?」で答えが返ってきた

この記事で作るもの

WordPressで運営されているWebサイトを、MCPサーバーとしてClaude Desktopから使えるようにします。最終的にnpmに公開して、誰でも npx 一発で使える状態にします。

題材は、福岡の女子サッカークラブ「福岡J・アンクラス」の公式サイト( https://anclas.jp/ )です。完成すると、Claude Desktopでこんな会話ができます。

あなた: 「アンクラスの次の試合いつ?」
Claude: 4月12日(日) 12:00、Qリーグ開幕戦 vs ヴィアマテラス宮﨑Alegrita、
        会場は宇美町総合スポーツ公園です。

コードは GitHub で公開しています。
https://github.com/atani/anclas-mcp-server

インストール方法

Claude Code を使う場合

コマンド一発で追加できます。

claude mcp add anclas -- npx anclas-mcp-server

Claude Desktop を使う場合

設定ファイルを直接編集します。

OS 設定ファイルのパス
Mac ~/Library/Application Support/Claude/claude_desktop_config.json
Windows %APPDATA%Claudeclaude_desktop_config.json
{
  "mcpServers": {
    "anclas": {
      "command": "npx",
      "args": ["anclas-mcp-server"]
    }
  }
}

保存したらClaude Desktopを再起動してください。入力欄の + → 「コネクタ」に anclas が表示されます。

以降は、このMCPサーバーをゼロから作ってnpmに公開するまでの手順です。

なぜWordPressサイトが狙い目なのか

MCPサーバーを作るには、データを取得するAPIが必要です。WordPressサイトにはデフォルトで REST API(/wp-json/wp/v2/)が有効になっており、認証なしで投稿・カテゴリ・タグを取得できます。

WordPressで作られたサイトであれば、どれでもMCPサーバー化の候補です。お気に入りのブログ、地元のスポーツチーム、好きなメディア。WordPressかどうかは https://サイトURL/wp-json/wp/v2/posts にアクセスしてJSONが返るかで確認できます。

技術スタック

すべて無料です。

要素 選択
言語 TypeScript
MCP SDK @modelcontextprotocol/sdk
データ取得 WordPress REST API(認証不要)
実行方式 stdio(サーバー不要)
配布 npm

Step 1: WordPress REST API を調査する

まず、対象サイトのAPIでどんなデータが取れるか調べます。

# 投稿一覧
curl -s "https://anclas.jp/wp-json/wp/v2/posts?per_page=3" | jq '.[].title.rendered'

# カテゴリ一覧
curl -s "https://anclas.jp/wp-json/wp/v2/categories?per_page=100" | jq '.[] | {id, name, count}'

# タグ一覧
curl -s "https://anclas.jp/wp-json/wp/v2/tags?per_page=100" | jq '.[] | {id, name, count}'

anclas.jpの場合、以下のことがわかりました。

  • カテゴリに「GAME (Qリーグ) 2025」「GAME(皇后杯)2025」など試合カテゴリがある
  • タグに「小山 莉奈ブログ」「平良 文果ブログ」など選手ごとのブログタグがある
  • 投稿本文に「福岡J・アンクラス 4(1-0,3-1)1 琉球デイゴス」のようにスコアが記載されている

この構造を理解した上で、MCPツールを設計します。

Step 2: プロジェクトのセットアップ

mkdir anclas-mcp-server && cd anclas-mcp-server
npm init -y
npm install @modelcontextprotocol/sdk zod
npm install -D typescript @types/node

tsconfig.json を作成します。

{
  "compilerOptions": {
    "target": "ES2022",
    "module": "ES2022",
    "moduleResolution": "bundler",
    "outDir": "dist",
    "rootDir": "src",
    "strict": true,
    "esModuleInterop": true,
    "skipLibCheck": true,
    "declaration": true
  },
  "include": ["src"]
}

package.json に以下を追加します。

{
  "type": "module",
  "main": "dist/index.js",
  "bin": {
    "anclas-mcp-server": "dist/index.js"
  },
  "scripts": {
    "build": "tsc",
    "start": "node dist/index.js"
  }
}

Step 3: WordPress APIクライアントを実装する

src/wordpress-client.ts にWordPress REST APIのラッパーを作ります。

const BASE_URL = "https://anclas.jp/wp-json/wp/v2";

const ALLOWED_PATHS = ["/posts", "/categories", "/tags"] as const;

async function wpFetch<T>(path: string, params: Record<string, string> = {}): Promise<T> {
  if (!ALLOWED_PATHS.some((p) => path === p)) {
    throw new Error(`Invalid API path: ${path}`);
  }
  const url = new URL(`${BASE_URL}${path}`);
  for (const [key, value] of Object.entries(params)) {
    url.searchParams.set(key, value);
  }
  const res = await fetch(url.toString(), { signal: AbortSignal.timeout(10_000) });
  if (!res.ok) {
    const body = await res.text().catch(() => "");
    throw new Error(`WordPress API error: ${res.status} ${res.statusText} - ${body}`);
  }
  return res.json() as Promise<T>;
}

ポイントは3つあります。

  • ALLOWED_PATHS でパスをホワイトリスト化し、意図しないAPI呼び出しを防ぐ
  • AbortSignal.timeout で10秒タイムアウトを設定し、MCPサーバーのハングを防ぐ
  • エラー時はレスポンスの本文も取得して、デバッグしやすくする

Step 4: 試合情報パーサーを実装する

WordPressの投稿本文はHTMLです。スコアや日時は構造化されておらず、テキストとして埋め込まれています。正規表現で抽出します。

// "福岡J・アンクラス 4(1-0,3-1)1 琉球デイゴス" → { score: "4-1", awayTeam: "琉球デイゴス" }
const detailedScorePattern =
  /(?:福岡J・アンクラス|アンクラス)s*(d+)s*(([^)]+))s*(d+)s*(.+?)(?:n|$)/;

// "2026 年 4 月 12 日 (日)、12:00キックオフ" → { date: "2026年4月12日", kickoff: "12:00" }
const wideFormatPattern =
  /(d{4})s*年s*(d{1,2})s*月s*(d{1,2})s*日s*[((][日月火水木金土][))][、,]?s*(d{1,2})[::](d{2})/;

日本語サイトでは全角コロン()やスペース入りの日付(2026 年)への対応が必要です。

Step 5: MCPツールを定義する

MCP SDKの McpServer クラスを使って、ツールを定義します。

import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
import { z } from "zod";

const server = new McpServer({
  name: "anclas-mcp-server",
  version: "1.0.0",
});

server.tool(
  "get_next_match",
  "次の試合情報を取得する。日時・対戦相手・会場・キックオフ時間を返す。",
  {},
  async () => {
    // 最新投稿からキーワード検索 + スコア不在で試合告知を判定
    const posts = await getPosts({ perPage: 30, order: "desc" });
    // ... パースして返す
  }
);

合計7つのツールを定義しました。

ツール 説明
get_next_match 次の試合情報
get_recent_matches 直近の試合結果
get_season_results シーズン成績サマリー
get_player_blog 選手ブログ記事
get_players 選手一覧
get_latest_news 最新ニュース
search_articles フリーワード検索

設計上の工夫

試合カテゴリの動的取得

カテゴリIDをハードコードすると、新シーズンごとにコード変更が必要です。起動時にAPIからカテゴリ一覧を取得し、GAME で始まるカテゴリを自動検出する方式にしました。

let gameCategoriesCache: WPCategory[] | null = null;

export async function getGameCategories(): Promise<WPCategory[]> {
  if (gameCategoriesCache) return gameCategoriesCache;
  const all = await getCategories();
  gameCategoriesCache = all.filter((c) => /^GAME/i.test(c.name));
  return gameCategoriesCache;
}

ユーザー入力のサニタイズ

MCPツールの引数はユーザーが自由に入力できます。出力にMarkdownインジェクションが起きないよう、ユーザー入力はバッククォートで囲みます。

function sanitizeInput(input: string): string {
  return ``${input.replace(/`/g, "")}``;
}

Step 6: ビルドしてテストする

npm run build

MCP Inspector やJSON-RPCで直接テストできます。

echo '{"jsonrpc":"2.0","id":1,"method":"initialize","params":{"protocolVersion":"2024-11-05","capabilities":{},"clientInfo":{"name":"test","version":"1.0.0"}}}
{"jsonrpc":"2.0","id":2,"method":"tools/call","params":{"name":"get_next_match","arguments":{}}}' 
  | node dist/index.js 2>/dev/null | tail -1 | jq .

Step 7: npm に公開する

package.json にnpm公開用の設定を追加します。

{
  "files": ["dist"],
  "scripts": {
    "prepublishOnly": "npm run build"
  },
  "license": "MIT",
  "repository": {
    "type": "git",
    "url": "https://github.com/atani/anclas-mcp-server.git"
  }
}

公開します。

npm login
npm publish --access public

公開後は npx anclas-mcp-server で実行できるようになります。

Step 8: Claude Desktop で使う

冒頭の「インストール方法」の通り、claude_desktop_config.json に設定を追加してClaude Desktopを再起動すれば使えます。

応用: 他のWordPressサイトでも作れる

この手法はWordPressサイトならどこでも応用できます。

  1. https://対象サイト/wp-json/wp/v2/posts でAPI確認
  2. カテゴリ・タグ構造を調査
  3. BASE_URL を書き換え、パーサーをサイトに合わせて調整
  4. npm公開

地元のスポーツチーム、好きなメディア、自分のWordPressブログなど、好きなサイトをMCPサーバー化してみてください。

まとめ

WordPressの REST API を使えば、認証不要・無料でMCPサーバーを作れます。npmに公開すれば、設定ファイルに3行追加するだけで誰でも使えます。

https://github.com/atani/anclas-mcp-server
https://www.npmjs.com/package/anclas-mcp-server

推しチームの公式サイトをMCPサーバーにしたら「次の試合いつ?」で答えが返ってきた

この記事で作るもの

WordPressで運営されているWebサイトを、MCPサーバーとしてClaude Desktopから使えるようにします。最終的にnpmに公開して、誰でも npx 一発で使える状態にします。

題材は、福岡の女子サッカークラブ「福岡J・アンクラス」の公式サイト( https://anclas.jp/ )です。完成すると、Claude Desktopでこんな会話ができます。

あなた: 「アンクラスの次の試合いつ?」
Claude: 4月12日(日) 12:00、Qリーグ開幕戦 vs ヴィアマテラス宮﨑Alegrita、
        会場は宇美町総合スポーツ公園です。

コードは GitHub で公開しています。
https://github.com/atani/anclas-mcp-server

インストール方法

Claude Code を使う場合

コマンド一発で追加できます。

claude mcp add anclas -- npx anclas-mcp-server

Claude Desktop を使う場合

設定ファイルを直接編集します。

OS 設定ファイルのパス
Mac ~/Library/Application Support/Claude/claude_desktop_config.json
Windows %APPDATA%Claudeclaude_desktop_config.json
{
  "mcpServers": {
    "anclas": {
      "command": "npx",
      "args": ["anclas-mcp-server"]
    }
  }
}

保存したらClaude Desktopを再起動してください。入力欄の + → 「コネクタ」に anclas が表示されます。

以降は、このMCPサーバーをゼロから作ってnpmに公開するまでの手順です。

なぜWordPressサイトが狙い目なのか

MCPサーバーを作るには、データを取得するAPIが必要です。WordPressサイトにはデフォルトで REST API(/wp-json/wp/v2/)が有効になっており、認証なしで投稿・カテゴリ・タグを取得できます。

WordPressで作られたサイトであれば、どれでもMCPサーバー化の候補です。お気に入りのブログ、地元のスポーツチーム、好きなメディア。WordPressかどうかは https://サイトURL/wp-json/wp/v2/posts にアクセスしてJSONが返るかで確認できます。

技術スタック

すべて無料です。

要素 選択
言語 TypeScript
MCP SDK @modelcontextprotocol/sdk
データ取得 WordPress REST API(認証不要)
実行方式 stdio(サーバー不要)
配布 npm

Step 1: WordPress REST API を調査する

まず、対象サイトのAPIでどんなデータが取れるか調べます。

# 投稿一覧
curl -s "https://anclas.jp/wp-json/wp/v2/posts?per_page=3" | jq '.[].title.rendered'

# カテゴリ一覧
curl -s "https://anclas.jp/wp-json/wp/v2/categories?per_page=100" | jq '.[] | {id, name, count}'

# タグ一覧
curl -s "https://anclas.jp/wp-json/wp/v2/tags?per_page=100" | jq '.[] | {id, name, count}'

anclas.jpの場合、以下のことがわかりました。

  • カテゴリに「GAME (Qリーグ) 2025」「GAME(皇后杯)2025」など試合カテゴリがある
  • タグに「小山 莉奈ブログ」「平良 文果ブログ」など選手ごとのブログタグがある
  • 投稿本文に「福岡J・アンクラス 4(1-0,3-1)1 琉球デイゴス」のようにスコアが記載されている

この構造を理解した上で、MCPツールを設計します。

Step 2: プロジェクトのセットアップ

mkdir anclas-mcp-server && cd anclas-mcp-server
npm init -y
npm install @modelcontextprotocol/sdk zod
npm install -D typescript @types/node

tsconfig.json を作成します。

{
  "compilerOptions": {
    "target": "ES2022",
    "module": "ES2022",
    "moduleResolution": "bundler",
    "outDir": "dist",
    "rootDir": "src",
    "strict": true,
    "esModuleInterop": true,
    "skipLibCheck": true,
    "declaration": true
  },
  "include": ["src"]
}

package.json に以下を追加します。

{
  "type": "module",
  "main": "dist/index.js",
  "bin": {
    "anclas-mcp-server": "dist/index.js"
  },
  "scripts": {
    "build": "tsc",
    "start": "node dist/index.js"
  }
}

Step 3: WordPress APIクライアントを実装する

src/wordpress-client.ts にWordPress REST APIのラッパーを作ります。

const BASE_URL = "https://anclas.jp/wp-json/wp/v2";

const ALLOWED_PATHS = ["/posts", "/categories", "/tags"] as const;

async function wpFetch<T>(path: string, params: Record<string, string> = {}): Promise<T> {
  if (!ALLOWED_PATHS.some((p) => path === p)) {
    throw new Error(`Invalid API path: ${path}`);
  }
  const url = new URL(`${BASE_URL}${path}`);
  for (const [key, value] of Object.entries(params)) {
    url.searchParams.set(key, value);
  }
  const res = await fetch(url.toString(), { signal: AbortSignal.timeout(10_000) });
  if (!res.ok) {
    const body = await res.text().catch(() => "");
    throw new Error(`WordPress API error: ${res.status} ${res.statusText} - ${body}`);
  }
  return res.json() as Promise<T>;
}

ポイントは3つあります。

  • ALLOWED_PATHS でパスをホワイトリスト化し、意図しないAPI呼び出しを防ぐ
  • AbortSignal.timeout で10秒タイムアウトを設定し、MCPサーバーのハングを防ぐ
  • エラー時はレスポンスの本文も取得して、デバッグしやすくする

Step 4: 試合情報パーサーを実装する

WordPressの投稿本文はHTMLです。スコアや日時は構造化されておらず、テキストとして埋め込まれています。正規表現で抽出します。

// "福岡J・アンクラス 4(1-0,3-1)1 琉球デイゴス" → { score: "4-1", awayTeam: "琉球デイゴス" }
const detailedScorePattern =
  /(?:福岡J・アンクラス|アンクラス)s*(d+)s*(([^)]+))s*(d+)s*(.+?)(?:n|$)/;

// "2026 年 4 月 12 日 (日)、12:00キックオフ" → { date: "2026年4月12日", kickoff: "12:00" }
const wideFormatPattern =
  /(d{4})s*年s*(d{1,2})s*月s*(d{1,2})s*日s*[((][日月火水木金土][))][、,]?s*(d{1,2})[::](d{2})/;

日本語サイトでは全角コロン()やスペース入りの日付(2026 年)への対応が必要です。

Step 5: MCPツールを定義する

MCP SDKの McpServer クラスを使って、ツールを定義します。

import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
import { z } from "zod";

const server = new McpServer({
  name: "anclas-mcp-server",
  version: "1.0.0",
});

server.tool(
  "get_next_match",
  "次の試合情報を取得する。日時・対戦相手・会場・キックオフ時間を返す。",
  {},
  async () => {
    // 最新投稿からキーワード検索 + スコア不在で試合告知を判定
    const posts = await getPosts({ perPage: 30, order: "desc" });
    // ... パースして返す
  }
);

合計7つのツールを定義しました。

ツール 説明
get_next_match 次の試合情報
get_recent_matches 直近の試合結果
get_season_results シーズン成績サマリー
get_player_blog 選手ブログ記事
get_players 選手一覧
get_latest_news 最新ニュース
search_articles フリーワード検索

設計上の工夫

試合カテゴリの動的取得

カテゴリIDをハードコードすると、新シーズンごとにコード変更が必要です。起動時にAPIからカテゴリ一覧を取得し、GAME で始まるカテゴリを自動検出する方式にしました。

let gameCategoriesCache: WPCategory[] | null = null;

export async function getGameCategories(): Promise<WPCategory[]> {
  if (gameCategoriesCache) return gameCategoriesCache;
  const all = await getCategories();
  gameCategoriesCache = all.filter((c) => /^GAME/i.test(c.name));
  return gameCategoriesCache;
}

ユーザー入力のサニタイズ

MCPツールの引数はユーザーが自由に入力できます。出力にMarkdownインジェクションが起きないよう、ユーザー入力はバッククォートで囲みます。

function sanitizeInput(input: string): string {
  return ``${input.replace(/`/g, "")}``;
}

Step 6: ビルドしてテストする

npm run build

MCP Inspector やJSON-RPCで直接テストできます。

echo '{"jsonrpc":"2.0","id":1,"method":"initialize","params":{"protocolVersion":"2024-11-05","capabilities":{},"clientInfo":{"name":"test","version":"1.0.0"}}}
{"jsonrpc":"2.0","id":2,"method":"tools/call","params":{"name":"get_next_match","arguments":{}}}' 
  | node dist/index.js 2>/dev/null | tail -1 | jq .

Step 7: npm に公開する

package.json にnpm公開用の設定を追加します。

{
  "files": ["dist"],
  "scripts": {
    "prepublishOnly": "npm run build"
  },
  "license": "MIT",
  "repository": {
    "type": "git",
    "url": "https://github.com/atani/anclas-mcp-server.git"
  }
}

公開します。

npm login
npm publish --access public

公開後は npx anclas-mcp-server で実行できるようになります。

Step 8: Claude Desktop で使う

冒頭の「インストール方法」の通り、claude_desktop_config.json に設定を追加してClaude Desktopを再起動すれば使えます。

応用: 他のWordPressサイトでも作れる

この手法はWordPressサイトならどこでも応用できます。

  1. https://対象サイト/wp-json/wp/v2/posts でAPI確認
  2. カテゴリ・タグ構造を調査
  3. BASE_URL を書き換え、パーサーをサイトに合わせて調整
  4. npm公開

地元のスポーツチーム、好きなメディア、自分のWordPressブログなど、好きなサイトをMCPサーバー化してみてください。

まとめ

WordPressの REST API を使えば、認証不要・無料でMCPサーバーを作れます。npmに公開すれば、設定ファイルに3行追加するだけで誰でも使えます。

https://github.com/atani/anclas-mcp-server
https://www.npmjs.com/package/anclas-mcp-server

コメント

タイトルとURLをコピーしました