SEO MCP Server selbst bauen: Schritt-für-Schritt-Leitfaden für Mac Mini M4mit Colima

Dieser Leitfaden zeigt Schritt für Schritt, wie du einen eigenen SEO-MCP-Server baust — von der lokalen Entwicklungsumgebung bis zum ersten laufenden Tool im Terminal. Ich arbeite ausschließlich mit Claude Code im Terminal, nicht mit Claude Desktop. Die Basis: ein M4 Mac Mini mit Colima als Containerumgebung.

Ich beschreibe genau die Architektur, die ich selbst nutze. Kein hypothetisches Setup, keine vereinfachten Beispiele.

Was du am Ende haben wirst

  • Einen laufenden MCP-Server mit eigenen SEO-Tools
  • Google Search Console direkt im Terminal via Claude Code abrufbar
  • WordPress-Meta per Befehl im Terminal setzen
  • Keyword-Daten via DataForSEO live abrufbar
  • Saubere Entwicklungsumgebung mit Colima auf dem M4 Mac Mini

Voraussetzungen verstehen: Warum M4 + Colima?

Der M4 Mac Mini bringt ARM64-Architektur. Das bedeutet: native ARM-Performance für Python, keine Rosetta-Overhead, schnelle Kompilierung von Abhängigkeiten. Für einen MCP-Server, der potenziell tausende Zeilen Log-Files analysiert, ist das spürbar.

Colima ist ein quelloffener Container-Runtime für macOS — eine schlanke Alternative zu Docker Desktop. Es startet eine Linux-VM (standardmäßig ARM64) und macht Docker-Befehle direkt verfügbar. Der Vorteil: kein Docker-Desktop-Lizenz-Overhead, volle Kontrolle, läuft stabil im Hintergrund.

Die Architektur sieht so aus:

  • Mac Host: Claude Code CLI (Terminal), Python-Venv für den MCP-Server, Homebrew
  • Colima-VM: Isolierte Entwicklungsumgebung, optionale Services (Redis, PostgreSQL falls nötig)
  • MCP-Server: Läuft als nativer macOS-Prozess — Claude Code startet ihn direkt über stdio im Terminal

Wichtiger Hinweis: Der MCP-Server läuft auf dem Mac-Host, nicht innerhalb der Colima-VM. Claude Code kommuniziert mit ihm über stdin/stdout — das funktioniert nur mit lokalen Prozessen. Ich arbeite bewusst im Terminal statt mit Claude Desktop: volle Kontrolle, kein GUI-Overhead, direkte Skript-Ausführung ohne Umweg.

Schritt 1: Grundumgebung einrichten

Homebrew installieren

/bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh)"

Nach der Installation den PATH setzen (M4 Mac, arm64):

echo 'eval "$(/opt/homebrew/bin/brew shellenv)"' >> ~/.zshrc
source ~/.zshrc

Python 3.12 installieren

Das System-Python (macOS 3.9.x) ist zu alt für MCP — es braucht mindestens 3.10. Wir nehmen 3.12:

brew install python@3.12
python3.12 --version  # sollte 3.12.x ausgeben

Colima einrichten

brew install colima docker
colima start --arch aarch64 --vm-type vz --vz-rosetta --cpu 4 --memory 8

Die Flags im Überblick:

  • --arch aarch64 — ARM64, passend zum M4-Chip
  • --vm-type vz — Apple Virtualization Framework (schneller als QEMU)
  • --vz-rosetta — Rosetta-Support für x86-Images falls nötig
  • --cpu 4 --memory 8 — 4 Kerne, 8 GB RAM für die VM
colima status  # zeigt: running
docker ps      # läuft über Colima

Schritt 2: Projektstruktur anlegen

mkdir ~/seo-dashboard
cd ~/seo-dashboard

# Virtual Environment mit Python 3.12
/opt/homebrew/bin/python3.12 -m venv .venv
source .venv/bin/activate

# Abhängigkeiten installieren
pip install mcp fastmcp pydantic google-auth google-auth-oauthlib \
            google-api-python-client requests

Projektstruktur nach dem Setup:

seo-dashboard/
├── .venv/                    # Virtual Environment
├── seo_mcp_server.py         # Haupt-Server
├── gsc_auth.py               # OAuth-Setup für GSC
└── claude-rankmath-api/      # WordPress-Plugin

Schritt 3: Den ersten MCP-Server schreiben

Erstelle seo_mcp_server.py. Das Grundgerüst:

from mcp.server.fastmcp import FastMCP
from pydantic import BaseModel, Field, ConfigDict

mcp = FastMCP("technical-seo")

class KeywordAuditInput(BaseModel):
    model_config = ConfigDict(str_strip_whitespace=True, extra="forbid")
    url: str = Field(..., description="URL der zu prüfenden Seite")
    keyword: str = Field(..., description="Ziel-Keyword")
    content: str = Field(..., description="Seiteninhalt als Text")

@mcp.tool(name="seo_keyword_audit")
async def seo_keyword_audit(params: KeywordAuditInput) -> str:
    keyword_lower = params.keyword.lower()
    content_lower = params.content.lower()
    count = content_lower.count(keyword_lower)
    words = len(params.content.split())
    density = round(count / words * 100, 2) if words else 0
    in_first_100 = keyword_lower in " ".join(params.content.split()[:100]).lower()

    return (
        f"## Keyword-Audit: {params.keyword}\n\n"
        f"URL: {params.url}\n"
        f"Keyword-Häufigkeit: {count}x\n"
        f"Textlänge: {words} Wörter\n"
        f"Keyword-Dichte: {density}%\n"
        f"In ersten 100 Wörtern: {'Ja' if in_first_100 else 'Nein'}\n"
    )

if __name__ == "__main__":
    mcp.run()

Drei Dinge fallen auf:

  1. FastMCP übernimmt das gesamte JSON-RPC-Protokoll — du schreibst nur die Funktion
  2. Pydantic BaseModel validiert alle Eingaben automatisch
  3. async def — alle Tools sind asynchron, auch wenn sie intern synchronen Code ausführen

Schritt 4: Server testen mit dem MCP Inspector

Bevor der Server in den echten Workflow geht, im Terminal testen:

# MCP CLI installieren (im venv)
pip install mcp[cli]

# Inspector starten
.venv/bin/mcp dev seo_mcp_server.py

Browser öffnet sich auf http://localhost:5173. Dort kannst du jedes Tool manuell aufrufen, Parameter eingeben und die Ausgabe prüfen — direkt aus dem Terminal gestartet, ohne GUI-Abhängigkeit.

Schritt 5: Mit Claude Code CLI verbinden

Ich nutze Claude Code im Terminal — kein Claude Desktop. Der MCP-Server wird direkt in der Claude Code Konfiguration registriert:

# Claude Code MCP Server hinzufügen
claude mcp add technical-seo \
  /Users/DEINNAME/seo-dashboard/.venv/bin/python \
  /Users/DEINNAME/seo-dashboard/seo_mcp_server.py

Alternativ manuell in ~/.claude.json oder der Projekt-Config .claude/settings.json:

{
  "mcpServers": {
    "technical-seo": {
      "command": "/Users/DEINNAME/seo-dashboard/.venv/bin/python",
      "args": ["/Users/DEINNAME/seo-dashboard/seo_mcp_server.py"]
    }
  }
}

Danach Claude Code im Projektverzeichnis starten:

cd ~/seo-dashboard
claude

Claude Code erkennt den MCP-Server automatisch und macht alle Tools im Chat verfügbar. Der Vorteil gegenüber Claude Desktop: du bleibst im Terminal, kannst Scripts direkt ausführen, Logs live verfolgen und alles in einem Workflow halten.

Schritt 6: Google Search Console anbinden

Für GSC-Daten brauchst du ein OAuth2-Client-Secret von Google:

  1. Google Cloud Console öffnen → Projekt erstellen
  2. APIs & Dienste → Search Console API aktivieren
  3. Anmeldedaten → OAuth-Client-ID → Desktop-App → JSON herunterladen
  4. Speichern unter: ~/mcp-credentials/gsc-credentials.json

Auth-Script gsc_auth.py erstellen:

import json, os
from google_auth_oauthlib.flow import InstalledAppFlow

CREDS_PATH = os.path.expanduser("~/mcp-credentials/gsc-credentials.json")
TOKEN_PATH = os.path.expanduser("~/.gsc-mcp/tokens/default.json")
SCOPES = ["https://www.googleapis.com/auth/webmasters.readonly"]

flow = InstalledAppFlow.from_client_secrets_file(CREDS_PATH, SCOPES)
creds = flow.run_local_server(port=0)

token_data = {
    "tokens": {
        "access_token":  creds.token,
        "refresh_token": creds.refresh_token,
        "token_uri":     creds.token_uri,
        "client_id":     creds.client_id,
        "client_secret": creds.client_secret,
        "scopes":        list(creds.scopes),
    }
}
os.makedirs(os.path.dirname(TOKEN_PATH), exist_ok=True)
with open(TOKEN_PATH, "w") as f:
    json.dump(token_data, f, indent=2)
print(f"Token gespeichert: {TOKEN_PATH}")

Einmalig ausführen:

.venv/bin/python gsc_auth.py

Browser öffnet sich → Google-Account auswählen → Zugriff erlauben. Token wird lokal gespeichert und automatisch erneuert.

Im MCP-Server dann:

from google.oauth2.credentials import Credentials
from google.auth.transport.requests import Request
from googleapiclient.discovery import build

def _get_gsc_service():
    with open(os.path.expanduser("~/.gsc-mcp/tokens/default.json")) as f:
        token_data = json.load(f)
    tokens = token_data.get("tokens", token_data)
    creds = Credentials(
        token=tokens.get("access_token"),
        refresh_token=tokens.get("refresh_token"),
        token_uri=tokens.get("token_uri"),
        client_id=tokens.get("client_id"),
        client_secret=tokens.get("client_secret"),
        scopes=["https://www.googleapis.com/auth/webmasters.readonly"],
    )
    if not creds.valid:
        creds.refresh(Request())
    return build("searchconsole", "v1", credentials=creds)

Schritt 7: WordPress-Integration via Custom Plugin

Die WordPress REST API gibt RankMath-Felder nicht von Haus aus frei. Dafür bauen wir ein kleines Plugin.

Datei: claude-rankmath-api/claude-rankmath-api.php

<?php
/**
 * Plugin Name: Claude RankMath API Bridge
 * Version: 1.0.0
 */
add_action('rest_api_init', function() {
    register_rest_route('claude-seo/v1', '/update-meta', [
        'methods'             => 'POST',
        'callback'            => function($req) {
            $id = (int)$req->get_param('post_id');
            if ($t = $req->get_param('rm_title'))   update_post_meta($id, 'rank_math_title', $t);
            if ($d = $req->get_param('rm_desc'))    update_post_meta($id, 'rank_math_description', $d);
            if ($k = $req->get_param('rm_keyword')) update_post_meta($id, 'rank_math_focus_keyword', $k);
            if ($h = $req->get_param('title'))      wp_update_post(['ID' => $id, 'post_title' => $h]);
            return ['success' => true, 'post_id' => $id];
        },
        'permission_callback' => fn() => current_user_can('edit_posts'),
    ]);
});

Als ZIP verpacken und in WP-Admin → Plugins → Plugin hochladen installieren. Dann aus Python direkt aufrufen:

import requests
from requests.auth import HTTPBasicAuth

auth = HTTPBasicAuth("wp-benutzername", "application-password")
requests.post(
    "https://deine-domain.de/wp-json/claude-seo/v1/update-meta",
    json={"post_id": 748, "rm_title": "Neuer SEO Title", "rm_keyword": "zielkeyword"},
    auth=auth
)

Das WordPress Application Password erstellst du unter WP-Admin → Benutzer → Profil → Application Passwords.

Schritt 8: DataForSEO für Keyword-Daten

DataForSEO bietet eine REST API für Keyword-Volumen, CPC und verwandte Keywords. Account unter dataforseo.com erstellen, dann:

import requests
from requests.auth import HTTPBasicAuth

dfs_auth = HTTPBasicAuth("deine@email.com", "api-passwort")

r = requests.post(
    "https://api.dataforseo.com/v3/keywords_data/google_ads/search_volume/live",
    json=[{"keywords": ["technisches seo", "seo tool"], "language_code": "de", "location_code": 2276}],
    auth=dfs_auth
)
for kw in r.json()["tasks"][0]["result"]:
    print(f"{kw['keyword']}: {kw.get('search_volume', 0)} Vol/Monat")

Schritt 9: Colima für die Entwicklung nutzen

Colima ist nützlich für:

  • Isolierte Test-Umgebungen — neues Tool ausprobieren ohne das Haupt-Setup zu gefährden
  • Datenbank-Services — PostgreSQL oder Redis für erweiterte Caching-Funktionen
  • CI-ähnliche Tests — Skripte in einem sauberen Container laufen lassen
# In Colima: Saubere Python-Umgebung für Tests
colima ssh
# In der VM:
sudo apt install python3.12 python3.12-venv -y
python3.12 -m venv ~/test-env
source ~/test-env/bin/activate
pip install mcp fastmcp pydantic requests

Entwicklungsworkflow auf dem M4 Mac Mini:

  1. Code auf dem Mac Host schreiben (VS Code, Cursor, Claude Code)
  2. In Colima testen — isoliert, ohne Produktivumgebung zu berühren
  3. Funktionierenden Code in die Haupt-Venv übernehmen
  4. Claude Desktop lädt den aktualisierten Server beim nächsten Start

Schritt 10: Den Server erweitern

Jedes neue Tool folgt demselben Muster:

class MeinToolInput(BaseModel):
    model_config = ConfigDict(str_strip_whitespace=True, extra="forbid")
    url: str = Field(..., description="Zu prüfende URL")
    # weitere Parameter

@mcp.tool(name="mein_seo_tool")
async def mein_seo_tool(params: MeinToolInput) -> str:
    # Logik
    return "Ergebnis als String"

Wichtige Konventionen:

  • extra="forbid" in ConfigDict — verhindert unbekannte Parameter
  • Alle Tools geben str zurück — MCP überträgt alles als Text
  • Fehler als Return-Wert, nicht als Exception — sonst bricht der MCP-Transport ab
  • Sprechende Tool-Namen mit Prefix — seo_meta_audit statt audit

Häufige Probleme und Lösungen

Python-Version zu alt:
MCP benötigt ≥3.10. System-Python auf macOS ist 3.9. Lösung: Homebrew Python 3.12 und eine eigene Venv.

pip install schlägt fehl (PEP 668):
Homebrew-Python blockiert globale Installs. Lösung: immer in einer Venv installieren, nie global.

GSC-Token abgelaufen:
Google-Tokens laufen nach einigen Monaten ab. Lösung: gsc_auth.py erneut ausführen — der Refresh-Token erneuert sich automatisch, solange er gültig ist.

Claude Code erkennt den MCP-Server nicht:
Absoluten Python-Pfad verwenden (nicht python3, sondern /Users/name/projekt/.venv/bin/python). Config mit claude mcp list prüfen. Claude Code im richtigen Verzeichnis starten — die Projekt-Config in .claude/settings.json gilt nur im jeweiligen Projektordner.

Colima startet nicht auf M4:
--vm-type vz benötigt macOS 13+. Ältere macOS-Versionen: --vm-type qemu verwenden.

Häufige Fragen

Muss ich Python können um diesen Server zu bauen?
Grundkenntnisse reichen: Funktionen definieren, Variablen, String-Formatierung. FastMCP übernimmt die gesamte MCP-Protokollschicht — du schreibst nur die Logik der einzelnen Tools.

Was kostet der Betrieb?
Der MCP-Server selbst kostet nichts — er läuft lokal. Kosten entstehen bei Claude Desktop (Anthropic-Abo), DataForSEO (ca. $0.01–0.10 pro Abfrage) und optional Google Ads API für Keyword-Daten.

Kann ich den Server auf einem Linux-Server deployen?
Ja, aber Claude Desktop muss dann via SSH auf den Server zugreifen können. Einfacher: MCP-Server lokal laufen lassen und nur die Datenbankdienste remote hosten.

Wie viele Tools kann ein MCP-Server haben?
Technisch unbegrenzt. Praktisch: Claude sieht alle Tools gleichzeitig — zu viele ähnliche Tools verwirren das Modell. Klare Namen und sprechende Beschreibungen sind wichtiger als die Anzahl.

Terminal oder Claude Desktop — was ist besser?
Ich arbeite ausschließlich im Terminal mit Claude Code. Vorteile: direkte Script-Ausführung, Logs in Echtzeit, volle Kontrolle über den Prozess, kein GUI-Overhead. Claude Desktop eignet sich besser für Nutzer, die eine grafische Oberfläche bevorzugen. Der MCP-Server selbst funktioniert mit beiden — ohne Codeänderung.

Weitersagen erwünscht: Teile diesen Artikel mit Menschen, die davon profitieren könnten👇🏻

Beitrag veröffentlicht

in

, ,

von