Skip to content
ブログサイトのためのMCPサービスの構築方法

NextraとLLMsを活用したMCP搭載ブログ記事ジェネレーターの構築

Updated on

MCPサービスの構築方法をご紹介します。このチュートリアルでは、OpenAIやClaudeとチャットするだけで記事を書いて公開できるMCPサービスを構築します。

このチュートリアルでは、大規模言語モデル(LLM)と対話し、コンテンツを生成させる技術的なソリューションを作成します。生成されたコンテンツはMDX形式で書き出され、自動的にあなたのブログのGitHubリポジトリにコミットされ、新しい投稿として追加されます。今回はこの**Model Context Protocol(MCP)**の統合を2つの実装例を通じて解説します。

  1. サーバーレス(GitHub Actions経由): GitHub Actionsのワークフローを利用し、LLMの呼び出しから投稿のコミットまでを自動化します。
  2. ホステッド(Next.js API経由): Next.jsのAPIエンドポイントに簡易的なMCPサーバーを実装し、クライアントとして機能させます。このエンドポイントはLLMを呼び出し、リアルタイムでGitHubに新規投稿をプッシュします。

MCPはAIアシスタントと外部ツール・データを繋ぐためのオープンスタンダードです。これは、AIモデルがクラウドサービスやデータベース、さらにはGitHubやSlackのようなプラットフォームとも、カスタム統合無しに対話できるインターフェースを提供します (Model Context Protocol (MCP) 説明 (opens in a new tab)). 要は、MCPはAIエージェントに“ツール”を使用させ、知識の範囲外のアクション(例:メール送信やコード展開、ブログ投稿の公開)を可能にします (CloudflareにリモートMCPサーバを構築・展開 (opens in a new tab)). 例として、私たちの“ツール”は、新しいMDXファイルの作成とそれをGitリポジトリ(ブログ)へコミットすることになります。

この案内の最後には、あなたが唯一の利用者としてAIエージェントへブログ記事をリクエストし、サイトに自動的に表示させる仕組みを持つ設定例を紹介します。特に、接続方法について(MCPクライアント↔︎LLMとLLM↔︎GitHub)を中心に解説し、シングルユーザ―環境・認証なしで運用できる形を想定しています。

ソリューションの全体像

まずコードに入る前に、アーキテクチャとワークフローの概要を示します。

  • ブログプラットフォーム: Next.jsとNextraの“ブログテーマ”(例:jojocys/nextra-agent-blogリポジトリ)を使い、コンテンツ管理を行います。記事はMDXファイル(Markdown + JSX)としてリポジトリ内に格納され、pages/postsディレクトリに入っています。Nextraはこのフォルダ内のMDXファイルを認識し、タイトルや日付とともにブログ投稿として表示します。

  • LLM(AIアシスタント): OpenAIのGPTやAnthropicのClaudeなどのAIモデルを同記事の生成に利用します。ユーザからのチャットやAPI呼び出し、あるいはprompt入力を元に、MDX形式の記事内容を生成します。

  • MCPクライアント&サーバ: MCPの性質上、LLMは外部のツールを呼び出し可能なホストとして働きます。今回は以下のシナリオを実現します。

    • GitHub Actions: このワークフロー自体がMCPクライアントの役割を果たし、LLMの呼び出しと投稿のコミットを管理します。
    • Next.js API: 独自のAPIサーバ(MCPクライアント&サーバ)として構築し、APIにリクエストを送るとLLMを呼び出し、その結果をGitHubにコミットします。このAPIは、LLM呼び出しとGitHubコミットの橋渡し役です。
  • GitHub連携: どちらの方法でも、GitHub APIを用いて新規記事をリポジトリに追加します。直接Git操作やHTTP APIの利用例があります。既存のMCPのGitHubコネクタ(例: GitHub - modelcontextprotocol/servers (opens in a new tab))もありますが、今回は手作り例を解説します。

この背景のもと、サーバーレスなGitHub Actionsを先に見ていきましょう。

方法1:GitHub Actionsによるサーバーレスブログ記事自動生成

この方法では、GitHub Actionsのワークフローをトリガーとして、ブログ記事の生成と公開を行います。専用サーバは不要で、GitHubがランナーを用いて処理を行います。流れは次の通りです。

  1. トリガー: ユーザが手動またはリポジトリのdispatchイベントでワークフローを起動。トピックやpromptを入力します。
  2. LLM呼び出し: APIを通じてOpenAIやClaudeへpromptを送り、MDX投稿を生成してもらいます。
  3. ファイル作成: LLMの返答からMDX内容を抽出し、posts/以下に保存(YAMLフロントマター付き)。
  4. GitHubにコミット: そのファイルをコミット・プッシュし、サイトに反映させます。

サンプルワークフローファイル(.github/workflows/llm-agent.yml

name: LLMブログ記事ジェネレーター
 
# 手動トリガ可能
on:
  workflow_dispatch:
    inputs:
      prompt:
        description: "ブログ記事のトピックまたはプロンプト"
        required: true
        type: string
 
permissions:
  contents: write
 
jobs:
  generate_post:
    runs-on: ubuntu-latest
    steps:
      - name: リポジトリチェックアウト
        uses: actions/checkout@v3
 
      - name: jqのインストール
        run: sudo apt-get -y install jq
 
      - name: LLM API呼び出し(OpenAI例)
        env:
          OPENAI_API_KEY: ${{ secrets.OPENAI_API_KEY }}
        run: |
          echo "Prompt: ${{ github.event.inputs.prompt }}"
          REQUEST=$(jq -n --arg prompt "${{ github.event.inputs.prompt }}" '{
            "model": "gpt-3.5-turbo",
            "messages": [
              {"role": "system", "content": "あなたは技術系ブログ用のアシスタントです。タイトル、日付、説明、type: postを含むYAMLフロントマターとコンテンツでMDXブログ記事を書いてください。"},
              {"role": "user", "content": $prompt}
            ]
          }')
          RESPONSE=$(curl -sS -H "Content-Type: application/json" -H "Authorization: Bearer $OPENAI_API_KEY" -d "$REQUEST" https://api.openai.com/v1/chat/completions)
          MDX_CONTENT=$(echo "$RESPONSE" | jq -r '.choices[0].message.content')
          TIMESTAMP=$(date +"%Y-%m-%d-%H%M")
          FILENAME="posts/llm-post-$TIMESTAMP.mdx"
          echo "作成ファイル: $FILENAME"
          echo "$MDX_CONTENT" > "$FILENAME"
 
      - name: コミットとプッシュ
        run: |
          git config user.name "github-actions"
          git config user.email "github-actions@users.noreply.github.com"
          git add posts/*.mdx
          git commit -m "AI生成による新規ブログ投稿"
          git push

この例では、

  • 手動起動し、入力したpromptをもとにAIへ指示を送ります。
  • AIはMDX形式のコンテンツを返し、それをファイルに保存。
  • 自動コミット&プッシュにより、反映されます。

これにより、責任者はリポジトリに新しい記事が増えるのを待つだけです。


方法2:Next.js API経由のMCPサーバとしての実装

この方法では、自分のNext.jsアプリ内に、AIとGitHubをつなぐ中間サーバを設置します。APIエンドポイントを作成し、そこにリクエストを行えば、AIからの記事生成とコミットを一括で処理します。

撼の設定例

.env.local(デプロイ環境にも反映してください)

OPENAI_API_KEY=<あなたのOpenAI APIキー>
GITHUB_PAT=<あなたのGitHubパーソナルアクセストークン>
GITHUB_REPO_OWNER=<GitHubユーザ名または組織名>
GITHUB_REPO_NAME=<リポジトリ名>

API例(pages/api/generate-post.js

import { Octokit } from "@octokit/rest";
import { Configuration, OpenAIApi } from "openai";
 
export default async function handler(req, res) {
  const { prompt } = req.body;
  if (!prompt) {
    return res.status(400).json({ error: "プロンプト未提供" });
  }
 
  try {
    const openaiConfig = new Configuration({ apiKey: process.env.OPENAI_API_KEY });
    const openai = new OpenAIApi(openaiConfig);
 
    // AIによるMDX生成
    const completion = await openai.createChatCompletion({
      model: "gpt-3.5-turbo",
      messages: [
        { role: "system", content: "あなたは技術系ブログ用のアシスタントです。トピックに合わせたMDXの記事を生成してください。" },
        { role: "user", content: prompt }
      ],
    });
 
    const mdxText = completion.data.choices[0].message.content;
 
    // タイトル抽出とファイル名作成
    const titleMatch = mdxText.match(/^title:\s*\"?(.+)\"?/m);
    const title = titleMatch ? titleMatch[1] : "untitled-post";
    const slug = title.toLowerCase().replace(/[^a-z0-9]+/g, "-").replace(/(^-|-$)/g, "");
    const filename = `posts/${slug || "untitled"}-${Date.now()}.mdx`;
    const dateStr = new Date().toISOString();
 
    let finalContent = mdxText;
    if (!/^date:/m.test(finalContent)) {
      finalContent = finalContent.replace(/^title:.*/m, `$&\ndate: ${dateStr}`);
    }
    if (!/^type:\s*posts/m.test(finalContent)) {
      finalContent = finalContent.replace(/^title:.*/m, `$&\ntype: posts`);
    }
 
    // GitHubにコミット
    const octokit = new Octokit({ auth: process.env.GITHUB_PAT });
    await octokit.rest.repos.createOrUpdateFileContents({
      owner: process.env.GITHUB_REPO_OWNER,
      repo: process.env.GITHUB_REPO_NAME,
      path: filename,
      message: `AIによる新規投稿: "${title}"`,
      content: Buffer.from(finalContent, "utf-8").toString("base64"),
      committer: {
        name: "MCPエージェント",
        email: "mcp-agent@example.com",
      },
      author: {
        name: "MCPエージェント",
        email: "mcp-agent@example.com",
      },
    });
 
    res.status(200).json({ message: "投稿を作成しました", slug });
  } catch (err) {
    console.error(err);
    res.status(500).json({ error: err.message });
  }
}

利用方法

アプリを展開したら、/api/generate-postにPOSTリクエストを送信します。例:

curl -X POST https://your-site.com/api/generate-post \
-H "Content-Type: application/json" \
-d '{"prompt": "Next.jsとMCPを使ったブログ構築についての記事"}'

効果と拡張

  • AIは入力したpromptに基づいてMDX形式のブログ記事を返し、それを自動でGitHubにコミット。
  • 生成された記事はすぐにブログに反映可能。
  • UIを作れば、チャットや入力フォームへ拡張も容易です。

まとめ

この解説では、AIとブログの連携において、MCPの標準的な仕組みを生かした2つのアプローチを紹介しました。GitHub Actionsによる完全サーバーレスでの自動化と、Next.js APIによる対話的な運用です。いずれも、AIがコンテンツ作成—公開までの「ツール」としての役割を果たす例です。この仕組みを応用すれば、多彩なシステム連携が可能となります。

実際のニーズに応じて、プロンプトの調整やエラーハンドリング、他のLLMプラットフォームの活用も検討してください。あなたのブログ運営に、AIの協力を取り入れてみてはいかがでしょうか。

参考資料:

  1. Anthropic、Model Context Protocol(MCP)の紹介 — AIアシスタントと外部システムの連携規格 (Model Context Protocol (MCP) 説明 (opens in a new tab))
  2. Cloudflare、MCPを一般化した運用 — MCPを用いたAIの操作例(ブログ公開も可能) (Cloudflareブログ記事参照 (opens in a new tab))
  3. MCP対応のオープンソースサーバ群 — GitHubリポジトリ操作例も含む(例:ファイル管理やGitHub API連携) (GitHub - modelcontextprotocol/servers (opens in a new tab):**)
📚