Skip to content
So bauen Sie einen MCP-Dienst für Ihre Blogseite

Aufbau eines MCP-gestützten Blog-Post-Generators mit Nextra und LLMs

Updated on

Wie baut man einen MCP-Dienst? In diesem Tutorial erstellen wir einen MCP-Dienst, der es Ihnen ermöglicht, Artikel zu verfassen und zu veröffentlichen, indem Sie einfach mit OpenAI oder Claude chatten.

In diesem Tutorial erstellen wir eine technische Lösung, mit der Sie mit einem großen Sprachmodell (LLM) chatten und es bitten können, Inhalte für Ihren auf Nextra basierenden Blog zu generieren. Der Inhalt wird in MDX geschrieben und automatisch als neue Beiträge in Ihrem GitHub-Repository veröffentlicht. Wir werden zwei Implementierungen dieses Model Context Protocol (MCP)-Integrationsansatzes betrachten:

  1. Serverless über GitHub Actions: Ein Workflow in GitHub Actions, der den gesamten Prozess steuert – das Aufrufen des LLMs und das Commiten des generierten Beitrags.
  2. Hosted über Next.js API: Eine einfache MCP-Server-Implementierung als Next.js-API-Endpoint (beispielsweise mit jojocys/nextra-agent-blog als Beispiel-Blog-Plattform), der als MCP-Client fungiert. Dieser Endpunkt ruft das LLM auf und pusht neue Beiträge in Echtzeit auf GitHub.

MCP ist ein offener Standard zum Verbinden von KI-Assistenten mit externen Tools und Daten. Es bietet eine universelle Schnittstelle, damit KI-Modelle mit Systemen wie Cloud-Diensten, Datenbanken – sogar Plattformen wie GitHub und Slack – ohne individuelle Integration interagieren können (Model Context Protocol (MCP) erklärt (opens in a new tab)). Anders ausgedrückt, ermöglicht MCP KI-Agenten die Nutzung von „Tools“, um Aktionen jenseits ihres Grundwissens durchzuführen. Ein KI-Assistent könnte z.B. MCP nutzen, um E-Mails zu versenden, Code-Änderungen zu deployen oder Blogbeiträge zu veröffentlichen (Build and deploy Remote Model Context Protocol (MCP) servers to Cloudflare (opens in a new tab)). Hierbei ist unser „Tool“ die Fähigkeit, eine neue MDX-Datei zu erstellen und diese in ein Git-Repository (den Blog) zu commiten.

Am Ende dieses Guides haben Sie ein funktionierendes Setup, bei dem Sie (als einziger Nutzer) eine Blogart (z.B. Thema) an einen AI-Agenten schicken und dieser automatisch auf Ihrer Website erscheint. Wir fokussieren dabei auf die Verknüpfung der Komponenten (MCP-Client↔︎LLM und LLM↔︎GitHub), wobei wir eine Single-User-Szenerie ohne zusätzliche Authentifizierung annehmen.

Überblick über die Lösung

Bevor wir in den Code eintauchen, skizzieren wir die Architektur und den Workflow:

  • Blog-Plattform: Wir verwenden eine Next.js-Seite mit dem Nextra “blog theme” (z.B. das Repository jojocys/nextra-agent-blog), um unseren Content zu verwalten. Blog-Beiträge werden als MDX-Dateien (Markdown mit JSX) im Repository abgelegt (z.B. im Ordner pages/posts). Nextra zeigt alle MDX-Dateien in diesem Ordner als Blog-Posts an, unter Verwendung der Frontmatter-Daten (Titel, Datum, etc.) und des Inhalts.

  • LLM (KI-Assistent): Wir nutzen ein KI-Modell (z.B. OpenAI GPT oder Anthropic Claude), um den Content der Blog-Beiträge zu generieren. Das Modell erhält eine Aufforderung (Prompt), die beschreibt, welchen Artikel es schreiben soll, und liefert eine MDX-formatierte Antwort.

  • MCP-Client & Server: In MCP-Begriffen agiert das LLM als Host, der externe Tools via eine Client-Server-Schnittstelle aufrufen kann. Wir implementieren eine minimalistische MCP-Konfiguration:

    • Bei der GitHub Actions-Variante ist der Workflow selbst der MCP-Client, der das AI-Modell anruft und bei Bedarf das “Schreibe-Post”-Tool (Commit in Repo) ausführt.
    • Bei der Next.js API-Variante erstellen wir eine individuelle API-Route, die sowohl MCP-Client (für LLM-Anfragen) als auch MCP-Server (für die Blog-Operationen) ist. Diese dient als Brücke zwischen LLM und GitHub.
  • GitHub-Integration: Beide Ansätze verwenden die GitHub-API, um den neuen Beitrag zum Repository hinzuzufügen. Das kann direkt via Git-Operationen oder über die HTTP-API von GitHub erfolgen. Wir sehen Beispiele für beide. (Hinweis: Das MCP-Ökosystem enthält auch eine vorgefertigte GitHub-Integration, die Repository-Operationen unterstützt (GitHub - modelcontextprotocol/servers (opens in a new tab)), aber hier lernen wir durch Selberbauen.)

Mit diesem Rahmen starten wir zunächst mit der serverlosen Variante via GitHub Actions.

Ansatz 1: Serverless Blog-Post-Generierung mit GitHub Actions

Hier nutzen wir einen Workflow, der Blogbeiträge bei Bedarf generiert und veröffentlicht. Das bedeutet, Sie brauchen keinen eigenen Server – GitHub startet eine Runner-Instanz, um die Schritte auszuführen. Der Workflow umfasst folgende Schritte:

  1. Trigger: Der Nutzer (Sie) löst den Workflow aus (z.B. per manuellem Dispatch) und gibt einen Prompt oder Thema für den Blogpost an.
  2. LLM-Aufruf: Der Workflow ruft das LLM (z.B. via API, OpenAI oder Claude) mit einer Aufforderung auf, einen MDX-Blogpost zum Thema zu erstellen.
  3. Datei-Erstellung: Der Workflow fängt die Antwort des LLM (den MDX-Content) ab und speichert sie als neue .mdx-Datei im Blog-Repository, inklusive Frontmatter (Titel, Datum etc.).
  4. Commit in GitHub: Die neue Datei wird committet und auf z.B. den main-Branch gepusht, sodass der Blogpost live ist.

Erstellen wir die Workflow-Datei im Repository. Legen Sie in dem Nextra-Blog-Repository unter .github/workflows/llm-agent.yml folgende Datei an:

name: LLM Blog Post Generator
 
# Manuellen Trigger erlauben
on:
  workflow_dispatch:
    inputs:
      prompt:
        description: "Thema oder Prompt für den Blogbeitrag"
        required: true
        type: string
 
permissions:
  contents: write  # Schreibrechte für Push
 
jobs:
  generate_post:
    runs-on: ubuntu-latest
    steps:
      - name: Check out Repository
        uses: actions/checkout@v3
 
      - name: Installiere jq
        run: sudo apt-get -y install jq
 
      - name: Generiere Bloginhalt mit OpenAI
        env:
          OPENAI_API_KEY: ${{ secrets.OPENAI_API_KEY }}
        run: |
          echo "Prompt: ${{ github.event.inputs.prompt }}"
          REQUEST_DATA=$(jq -n --arg prompt "${{ github.event.inputs.prompt }}" '{
              "model": "gpt-3.5-turbo",
              "messages": [
                {"role": "system", "content": "Du bist ein technischer Blog-Assistent. Erstelle einen MDX-Blogbeitrag mit YAML-Frontmatter (title, date, description, type: posts) zum gegebenen Thema."},
                {"role": "user", "content": $prompt}
              ]
            }')
          RESPONSE=$(curl -sS -H "Content-Type: application/json" \
                          -H "Authorization: Bearer $OPENAI_API_KEY" \
                          -d "$REQUEST_DATA" \
                          https://api.openai.com/v1/chat/completions)
          POST_CONTENT=$(echo "$RESPONSE" | jq -r '.choices[0].message.content')
          TIMESTAMP=$(date +"%Y-%m-%d-%H%M")
          FILENAME="posts/llm-post-$TIMESTAMP.mdx"
          echo "Erstelle neue Post-Datei: $FILENAME"
          echo "$POST_CONTENT" > $FILENAME
 
      - name: Commit und push
        run: |
          git config user.name "github-actions"
          git config user.email "github-actions@users.noreply.github.com"
          git add posts/*.mdx
          git commit -m "Automatisch generierter Blogbeitrag durch LLM"
          git push

Was passiert hier?:

  • Trigger & Input: Manuell per “workflow_dispatch” gestartet; Sie geben ein Thema ein.
  • Berechtigungen: Für das Schreiben in den Branch ist contents: write notwendig.
  • Check-out: Repository wird geklont.
  • Tools: jq für JSON-Verarbeitung (häufig vorhanden, aber explizit installiert).
  • Aufruf LLM: Über die API von OpenAI. Systemnachricht instruiert das Modell, einen MDX-Artikel mit Frontmatter zu schreiben. Das Prompt wird vom Nutzer übergeben.
  • Antwort: Der erste Wahltext wird extrahiert und in eine Datei geschrieben.
  • Commit: Neue MDX-Datei wird ins posts/-Verzeichnis committed und gepusht. Damit ist der Blogpost auf der Plattform sichtbar (sofern sie beim Push automatisch gebaut wird).

Testen: Im "Actions"-Tab des Repositories den Workflow starten, mit einem Beispiel-Prompt. Beobachten Sie die Logs, bis der Commit abgeschlossen ist. Die neue MDX-Datei erscheint im posts/-Ordner. Wenn z.B. Ihr Hosting (Vercel, GitHub Pages) auf GitHub reagiert, wird Ihr neuer Blogbeitrag automatisch veröffentlicht.

Hinweis: Alternativ können Sie das Ganze so konfigurieren, dass es z.B. durch Issues, Kommentare oder Releases ausgelöst wird. Für unsere Zwecke reicht die manuelle Auslösung.

Wenn Sie Claude statt OpenAI nutzen wollen, können Sie die API-Calls entsprechend anpassen. Claude hat eine andere API (z.B. via HTTP POST an https://api.anthropic.com/v1/complete), mit unterschiedlichen Payload-Parametern. Aber das Prinzip ist gleich: API aufrufen, Antwort in MDX umwandeln, committen.


Ansatz 2: MCP-Server via Next.js API-Route

Die zweite Variante baut einen eigenen MCP-fähigen Server in Ihrer Next.js-basierten Blogplattform auf. Dabei haben Sie eine API-Route, die:

  • Anfragen (z.B. vom Web-UI) entgegennimmt (z.B. Prompt oder Wunsch),
  • das LLM aufruft,
  • den generierten MDX-Content nimmt,
  • diesen in Ihrem GitHub-Repository speichert (via API oder Git), und
  • ggf. eine Antwort zurückgibt.

Voraussetzungen: Ihr Next.js-Deployment benötigt Zugriff auf Ihr GitHub (über einen Token), sowie auf die API des jeweiligen LLM.

Beispiel:

In Ihrer Next.js-/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: "Kein Prompt" });
 
  try {
    // LLM anfragen
    const config = new Configuration({ apiKey: process.env.OPENAI_API_KEY });
    const openai = new OpenAIApi(config);
    const completion = await openai.createChatCompletion({
      model: "gpt-3.5-turbo",
      messages: [
        { role: "system", content: "Du bist ein technischer Blog-Assistent. Erstelle einen MDX-Beitrag mit Frontmatter." },
        { role: "user", content: prompt }
      ],
    });
    const mdx = completion.data.choices[0].message.content;
 
    // Dateiname und Frontmatter prüfen
    let titleMatch = mdx.match(/^title:\s*\"?(.+)\"?/m);
    let title = titleMatch ? titleMatch[1] : "ohne-titel";
    const slug = title.toLowerCase().replace(/[^a-z0-9]+/g, "-").replace(/(^-|-$)/g, "");
    const filename = `posts/${slug || "untitled"}-${Date.now()}.mdx`;
 
    // Optionally Frontmatter ergänzen
    let finalContent = mdx;
    if (!/^date:/m.test(mdx)) {
      finalContent = finalContent.replace(/^title:.*/m, `$&\ndate: ${new Date().toISOString()}`);
    }
    if (!/^type:\s*posts/m.test(finalContent)) {
      finalContent = finalContent.replace(/^title:.*/m, `$&\ntype: posts`);
    }
 
    // GitHub-API: Datei erstellen/updaten
    const octokit = new Octokit({ auth: process.env.GITHUB_PAT });
    const owner = process.env.GITHUB_REPO_OWNER;
    const repo = process.env.GITHUB_REPO_NAME;
    await octokit.rest.repos.createOrUpdateFileContents({
      owner,
      repo,
      path: filename,
      message: `Automatisch generiert: "${title}"`,
      content: Buffer.from(finalContent).toString("base64"),
      committer: { name: "MCP Server", email: "mcp@local" },
      author: { name: "MCP Server", email: "mcp@local" },
    });
 
    res.status(200).json({ message: "Beitrag erstellt", filename });
  } catch (e) {
    console.error(e);
    res.status(500).json({ error: e.message });
  }
}

Damit bauen Sie eine API, die:

  • den Prompt vom Nutzer entgegennimmt,
  • das LLM aufruft,
  • das Ergebnis in eine MDX-Datei umwandelt,
  • in das Repository schreibt.

Diese API übernimmt die MCP-Client- und Serverfunktionalität: Sie kann in eine UX eingebunden werden (z.B. ein Chat im Frontend), oder auch durch Automatisierung getriggert werden.

Vorteile:

  • Flexibilität: Interaktive Eingaben, multiple Schritte.
  • Kontrolle: Moderieren der Inhalte vor dem Commit.
  • Erweiterbarkeit: Weitere Tools oder Aktionen einfach hinzufügbare.

Zusammenfassung

Wir haben zwei zentrale Ansätze vorgestellt:

  • Serverless (GitHub Actions): Automatisiert bei Trigger, nutzt das LLM und committet direkt.
  • Hosted (Next.js API): Interaktiv, integriert in Ihre Webseite, bietet API für dynamisches Generieren.

Beide Methoden basieren auf dem Grundprinzip von MCP: Das Modell (z.B. via API) kann externe Aktionen (wie Blog-Posts schreiben) auslösen, indem es standardisierte Tools (APIs, Commit-Operationen) nutzt.

Mit diesen Lösungen erweitern Sie Ihr Blog um eine intelligente Content-Funktion, die via KI vollautomatisch Artikel erstellen und veröffentlichen kann – eine konkrete Umsetzung der MCP-Vision: AI als universeller Assistent, der mit externen Systemen nahtlos zusammenarbeitet.

📚