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:
FastMCPübernimmt das gesamte JSON-RPC-Protokoll — du schreibst nur die FunktionPydantic BaseModelvalidiert alle Eingaben automatischasync 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:
- Google Cloud Console öffnen → Projekt erstellen
- APIs & Dienste → Search Console API aktivieren
- Anmeldedaten → OAuth-Client-ID → Desktop-App → JSON herunterladen
- 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:
- Code auf dem Mac Host schreiben (VS Code, Cursor, Claude Code)
- In Colima testen — isoliert, ohne Produktivumgebung zu berühren
- Funktionierenden Code in die Haupt-Venv übernehmen
- 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
strzurü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_auditstattaudit
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.
