Zum Inhalt springen
Doctor SEO

SEO mit KI: KI als Arbeitswerkzeug

Claude mit deinen eigenen Daten verbinden: Search Console und GA4 per MCP

Die Oberfläche der Search Console trennt seit dem 24. September 2026 zwei Suchtypen. Die Referenz der Search-Analytics-API führt den zweiten nicht – und ein MCP-Server liest die API. Diese Lektion zeigt, was daraus für die Einwilligung folgt, die du erteilst, welche Konnektoren es mit welchem Prüfdatum gibt und wie du eine Konnektor-Konfiguration beurteilst, bevor du zustimmst.

Aktualisiert am 8 Oktober 2026 24 Min. Lesezeit

Für Google Search Console gibt es keinen Konnektor von Anthropic und keinen von Google: die Recherche dieses Kurses fand am 20. September 2026 keinen. Was es gibt, pflegen Einzelpersonen in öffentlichen Repositorien, und diese Lektion nennt sie mit Versionsnummer und Prüfdatum. Das ist keine Beschwerde über ein Produkt, sondern eine Angabe darüber, wem du vertraust.

Die zweite Angabe ist die, um die es hier geht: für die Anbindung erteilst du eine Einwilligung, und die kann lesend bleiben oder nicht. Weder Google Search Console noch Google Analytics 4 gewinnen durch einen Schreibzugriff etwas, das du haben willst: korrigieren lässt sich dort nichts, und mit dem Schreibzugriff gibst du das Instrument aus der Hand, mit dem du den Agenten prüfst. Diese Asymmetrie ist das Argument – nicht Vorsicht als Haltung.

Dazu kommt ein nachlesbarer Unterschied zwischen Oberfläche und Schnittstelle: die Oberfläche der Search Console trennt seit dem 24. September 2026 zwei Suchtypen, die Referenz der Search-Analytics-API führt den zweiten nicht. Claude liest die API.

Eine Abgrenzung vorweg: hier ist Claude der Operator, der deine Berichte liest. Die umgekehrte Richtung – wer dich zitiert – deckt Level 4 zu GEO und AIO ab.

Was du lernst

  • Entscheiden, welche Einwilligung du erteilst – und den Grund in einem Satz sagen können.
  • Den Bestand an Konnektoren mit Datum lesen und erkennen, ab wann er abgelaufen ist.
  • Konnektor-Konfigurationen prüfen, bevor du im Einwilligungsdialog zustimmst.
  • Begründen, warum Google Analytics 4 dieselbe Datei und denselben Entzug teilt.
  • Die datierte Lücke zwischen Oberfläche und API benennen, an der deine Zahlen auseinanderlaufen.
  • Sagen, was eine Anbindung an Arbeit spart – und was sie nicht entscheidet.

Für deine eigenen Daten gibt es keinen Konnektor aus erster Hand

Stand 20. September 2026 pflegt für Google Search Console und Google Analytics 4 niemand aus erster Hand einen Konnektor – also keinen MCP-Server, über den Claude eine Datenquelle als aufrufbare Werkzeuge erreicht. Für die Daten zweier bezahlter Suiten gibt es ihn. Die Tabelle unten trägt deshalb ihr Prüfdatum: Werkzeugzahlen wandern, und ein Gemeinschaftsprojekt stellt die Pflege ein, ohne es anzukündigen.

Konnektor Wer ihn veröffentlicht Aus erster Hand für diese Daten? Was dokumentiert ist Quelle und Prüfdatum
Google Search Console Gemeinschaft: AminForou/mcp-gsc Nein 20 Werkzeuge, darunter batch_url_inspection und compare_search_periods GitHub, Version 0.3.3, Juli 2026; geprüft am 20. September 2026
Search Console und GA4 zusammen Gemeinschaft: delaren47/gsc-ga4-mcp Nein Beide Quellen hinter einer Einwilligung GitHub; geprüft am 20. September 2026
Semrush Semrush, offiziell Ja, für Semrushs eigene Daten Dokumentierter MCP-Endpunkt im Entwicklerportal Semrush, Stand 5. August 2026
Ahrefs Ahrefs, mit Anthropics Prüfzeichen Ja, für Ahrefs’ eigene Daten Recherchedaten des Anbieters Konnektorseite, Metadatum „Added January 2026“

Die dritte Spalte ist nicht meine Einordnung: Dewang Mishra führt Google Search Console in seinem Bestand an MCP-Konnektoren für Marketing-Stacks bei Passionfruit vom 28. März 2026 unter „Community / self-hosted“.

Praktisch verschiebt das eine Zuständigkeit und keine Qualität: hinter einem Gemeinschaftsserver steht kein Unternehmen am Endpunkt, also landen Quellcode, Version und Update-Entscheidung bei dem, der ihn installiert. Ohne Prüfdatum ist dieser Bestand eine Behauptung.

Die Asymmetrie: ein Schreibzugriff auf Messdaten bringt dir nichts

Ein Schreibzugriff auf Search Console oder Google Analytics 4 bringt dir nichts ein, deshalb erteile Lesezugriff – und nur auf die Properties, die deine Frage braucht. Google Search Console berichtet, was Google von deinen Seiten gesehen hat; korrigiert wird auf der Website, nicht im Bericht. Google Analytics 4 hält fest, was eine Sitzung getan hat; eine Änderung dort ändert den Vermerk, nicht das Verhalten.

Zu verlieren ist dagegen viel. Search Console und Google Analytics 4 sind das Instrument, mit dem du den Agenten prüfst, und ein Agent, der in das Instrument schreiben kann, hat deine Prüfung still abgeschafft. Die Arbeitsteilung dieses Levels hängt daran, dass das Nachrechnen außerhalb seiner Reichweite bleibt.

Eine Zahl sagt, woran das Zurückhalten hängt. In „State of AI in SEO 2026“ von Keyword.com (1. Januar 2026, n = 97 verwertbare Antworten, selbst gewählte Teilnahme, ohne veröffentlichte Fehlermarge) ist die Bezugsgröße nicht die ganze Stichprobe, sondern die Teilgruppe, die weitere Automatisierung bewusst liegen lässt: in ihr nennen 57 % mangelnde Qualität als Grund.

Und hier gehört eine Lücke benannt. In den Quellen dieser Lektion steht kein gemessener Fall, in dem ein Agent Daten in Google Search Console oder Google Analytics 4 beschädigt hätte – keine Untersuchung, kein Vorfallsbericht, keine Stichprobengröße. Die Regel steht damit auf dem, was eine Berechtigung möglich macht, nicht auf einer Beobachtung.

Drei Schritte, von denen nur einer eine Entscheidung ist

Claude an Google Search Console anzubinden besteht aus drei Schritten, und nur einer davon ist eine Entscheidung: ein Programm betreiben, das deine Search-Console-Daten als aufrufbare Werkzeuge bereitstellt, es in der Konfigurationsdatei deines Claude-Clients eintragen und es per OAuth gegen dein Google-Konto autorisieren. MCP, das Model Context Protocol, ist die Schnittstelle, über die Claude eine externe Funktion aufruft und strukturierte Daten zurückbekommt. Danach fragt Claude nach Leistungsdaten statt nach einem CSV-Export.

Auswählen und Eintragen ist Tipparbeit; die Einwilligung vergibt etwas, das nachher gilt. Deshalb steht die Berechtigung hier vor der Installation.

Dokumentiert sind zwei Server, beide in der Tabelle oben. AminForou/mcp-gsc stand im Juli 2026 bei Version 0.3.3 und stellt 20 Werkzeuge bereit, darunter batch_url_inspection und compare_search_periods; delaren47/gsc-ga4-mcp bedient Google Search Console und Google Analytics 4 aus einem Server und damit hinter einer Einwilligung. Beide wurden am 20. September 2026 geprüft.

Die Zähler eines Repositoriums entscheiden das nicht: rund 1.300 Sterne und 183 Forks sind eine Momentaufnahme vom 20. September 2026, kein Testbericht und keine Aussage darüber, ob jemand den Server morgen noch aktualisiert. Wer so einen Server betreibt, setzt die Grenze vorher statt sie vom Programm zu erwarten; Claude Code für technisches SEO übt genau diese Reihenfolge ein.

Warum diese Lektion keine Berechtigungszeichenkette abdruckt

Hier steht keine Scope-Zeichenkette zum Kopieren – kein Text also, mit dem ein Einwilligungsdialog eine einzelne Berechtigung benennt. Keine der zitierten Quellen dokumentiert die wörtliche Berechtigung für einen reinen Lesezugriff auf Search Console oder Analytics, und eine aus dem Gedächtnis zitierte Berechtigung wäre eine Mechanismusbehauptung ohne Quelle: der Preis des Irrtums ist kein Tippfehler, sondern echter Zugriff auf echte Daten.

Zu haben ist die Prüffrage: gesucht ist die Berechtigung, die Leistungsdaten abfragt und nichts verändert. Ihren Wortlaut liest du auf dem Dialog ab, der vor dir steht.

Der Prüfer im nächsten Abschnitt bekommt die Antwort deshalb von dir. Welche Endung in deinem Dialog einen Lesezugriff auszeichnet, trägst du als Feld lesemarker ein; fehlt es, verweigert das Skript. So steht die Angabe, die niemand belegen kann, in deiner Datei und nicht in meinem Text.

Der Prüfer, den du vor dem Einwilligungsdialog laufen lässt

scopepruefung.py liest eine oder mehrere Konnektor-Konfigurationen von der Platte – etwa die für Google Search Console und Google Analytics 4 – und sagt pro Eintrag, ob die angeforderten Scopes über eine Lesehaltung hinausgehen. Original für diese Lektion, nur Standardbibliothek, kein Socket. Beurteilt wird die Form einer Zeichenkette: endet das letzte Pfadsegment eines Scopes auf den lesemarker derselben Datei, gilt er als lesend. Ein Eintrag heißt LESEND, wenn jeder Scope besteht, und ZU WEIT, sobald einer durchfällt. Das ist eine Namenskonvention und keine Autoritätsprüfung – wer eine schreibende Berechtigung auf den Marker enden lassen darf, hat den Prüfer überholt.

Checklisten vergessen die zweite Hälfte: eine beschädigte Datei darf nie als Bestanden durchgehen. Deshalb verweigert das Skript, sobald es seine Eingabe nicht versteht, und jede Ursache bekommt ihren eigenen Rückgabewert – vierzehn belegte Werte, die 1 bleibt frei.

Wert Woran es liegt Wurde ein Urteil gedruckt?
0 Befund: jeder Eintrag ist lesend ja, alle drei Abschnitte
2 Befund: mindestens ein Eintrag geht über die Lesehaltung hinaus ja, alle drei Abschnitte
3 kein Pfad übergeben nein
4 Pfad ist keine lesbare reguläre Datei nein
5 die Bytes sind nicht UTF-8 nein
6 UTF-8, aber kein gültiges JSON nein
7 gültiges JSON, aber kein Objekt mit konnektoren als Liste nein
8 lesemarker fehlt oder ist leer nein
9 ein Eintrag führt name, umfang oder scopes nicht nein
10 scopes ist keine nicht leere Liste nicht leerer Zeichenketten nein
11 umfang ist keine ganze Zahl nein
12 konnektoren ist eine Liste ohne Einträge nein
13 unerwartete Ausnahme beim Einlesen nein
14 derselbe Konnektorname steht in zwei Dateien nein
1 bleibt unbelegt –

Die 1 bleibt frei, weil Python sie selbst setzt, wenn eine Ausnahme ungefangen durchfällt: läge dort ein Befund, wäre ein Absturz des Prüfers nicht von seinem Urteil zu unterscheiden. Zwei Werte tragen Befunde, elf je einen Eingabefehler, einer die unerwartete Ausnahme. Der Wert 4 entsteht an zwei Stellen im Code – der Pfad ist keine Datei, oder er ist eine und das Lesen scheitert –, bleibt aber eine Ursache: nichts wurde gelesen.

An drei Punkten hätte der Prüfer stillschweigend falsch urteilen können. umfang geht durch eine Prüfung, die true abweist, bevor sie auf eine ganze Zahl prüft, denn ein Wahrheitswert ist in Python eine Ganzzahl und ginge sonst als 1 durch. Der Dekodierfehler ist eine Unterklasse von ValueError; ein except OSError fängt ihn nicht, also steht sein Zweig neben dem Lesezweig. Und nirgends steht ein get(feld, ""): ein fehlendes Feld ist ein Verweigerungsgrund und kein leerer Wert, sonst spaziert ein beschädigter Export als saubere Lesehaltung durch.

#!/usr/bin/env python3
"""Prüft Konnektor-Konfigurationen gegen eine Lesehaltung, bevor du eine
Einwilligung erteilst.

    python3 scopepruefung.py <konfiguration.json> [weitere.json ...]

Jede Datei ist ein JSON-Objekt mit lesemarker und konnektoren. lesemarker ist
die Endung, die auf deinem eigenen Einwilligungsdialog einen reinen Lesezugriff
auszeichnet; diese Lektion druckt keine ab. Jeder Eintrag unter konnektoren
führt name, umfang und scopes.

Ein Eintrag gilt als lesend, wenn das letzte Pfadsegment jedes seiner scopes
auf den lesemarker endet. Geprüft wird die Form einer Zeichenkette, nicht das,
was ein Autorisierungsserver zurückgegeben hat.

Gedruckt wird in drei Abschnitten: die Einträge, die Scopes ohne Lesemarker
und die Bilanz. Vierzehn Werte sind belegt, je einer pro Ursache; die 1 bleibt
frei, weil Python sie für eine ungefangene Ausnahme selbst setzt.

   0  jeder Eintrag lesend
   2  Befund: mindestens ein Eintrag geht über die Lesehaltung hinaus
   3  kein Pfad übergeben
   4  Pfad ist keine lesbare reguläre Datei
   5  die Bytes sind nicht UTF-8
   6  UTF-8, aber kein gültiges JSON
   7  gültiges JSON, aber kein Objekt mit konnektoren als Liste
   8  lesemarker fehlt oder ist leer
   9  ein Eintrag führt name, umfang oder scopes nicht
  10  scopes ist keine nicht leere Liste nicht leerer Zeichenketten
  11  umfang ist keine ganze Zahl
  12  konnektoren ist eine Liste ohne Einträge
  13  unerwartete Ausnahme, es wird kein Befund gedruckt
  14  derselbe Konnektorname steht in zwei Dateien
   1  bleibt frei

Nur Standardbibliothek, kein Netzzugriff.
"""
import json
import os
import sys

FEHLT = object()                 # Platzhalter: nirgends ein get(feld, "")
FELDER = ("name", "umfang", "scopes")


def abbruch(code, text):
    sys.stderr.write("scopepruefung: " + text + "\n")
    raise SystemExit(code)


def lies_json(pfad):
    """Bytes von der Platte zu einem JSON-Wert. Codes 4, 5, 6."""
    if not os.path.isfile(pfad):
        abbruch(4, "keine lesbare reguläre Datei: %s" % pfad)
    try:
        rohbytes = open(pfad, "rb").read()
    except OSError as fehler:
        abbruch(4, "nicht lesbar: %s (%s)" % (pfad, fehler))
    try:
        text = rohbytes.decode("utf-8")
    except UnicodeDecodeError as fehler:
        # UnicodeDecodeError hängt unter ValueError und nicht unter OSError,
        # deshalb steht dieser Zweig neben dem Lesezweig und nicht in ihm.
        abbruch(5, "nicht UTF-8 kodiert: %s (%s)" % (pfad, fehler))
    try:
        return json.loads(text)
    except ValueError as fehler:
        abbruch(6, "kein gültiges JSON: %s (%s)" % (pfad, fehler))


def pruefe_rahmen(pfad, wert):
    """Gibt (lesemarker, konnektoren) zurück. Codes 7, 8, 12."""
    if not isinstance(wert, dict) or not isinstance(wert.get("konnektoren", FEHLT), list):
        abbruch(7, "kein Objekt mit konnektoren als Liste: %s" % pfad)
    marker = wert.get("lesemarker", FEHLT)
    if marker is FEHLT or not isinstance(marker, str) or not marker.strip():
        abbruch(8, "kein lesemarker in %s: ohne ihn wird nichts beurteilt" % pfad)
    konnektoren = wert["konnektoren"]
    if not konnektoren:
        abbruch(12, "konnektoren ist eine Liste ohne Einträge: %s" % pfad)
    return marker.strip(), konnektoren


def pruefe_eintrag(pfad, nummer, eintrag):
    """Gibt (name, umfang, scopes) zurück. Codes 9, 10, 11."""
    if not isinstance(eintrag, dict):
        abbruch(9, "%s, Eintrag %d ist kein Objekt" % (pfad, nummer))
    for feld in FELDER:
        if eintrag.get(feld, FEHLT) is FEHLT:
            abbruch(9, "%s, Eintrag %d führt kein Feld %s" % (pfad, nummer, feld))
    name = eintrag["name"]
    if not isinstance(name, str) or not name.strip():
        abbruch(9, "%s, Eintrag %d: name ist leer" % (pfad, nummer))
    scopes = eintrag["scopes"]
    if not isinstance(scopes, list) or not scopes:
        abbruch(10, "%s, %s: scopes ist keine nicht leere Liste" % (pfad, name))
    for scope in scopes:
        if not isinstance(scope, str) or not scope.strip():
            abbruch(10, "%s, %s: ein scope ist leer" % (pfad, name))
    umfang = eintrag["umfang"]
    if isinstance(umfang, bool) or not isinstance(umfang, int):
        # bool ist in Python eine Unterklasse von int: true darf nicht als 1
        # durchgehen, sonst trägt die Akte eine Zahl, die niemand gemeint hat.
        abbruch(11, "%s, %s: umfang ist keine ganze Zahl" % (pfad, name))
    return name.strip(), umfang, [scope.strip() for scope in scopes]


def ohne_marker(scopes, marker):
    """Die scopes, deren letztes Pfadsegment nicht auf den marker endet."""
    return [s for s in scopes if not s.rstrip("/").rsplit("/", 1)[-1].endswith(marker)]


def sammle(pfade):
    """Baut die Akte: eine Zeile pro Eintrag, Dateireihenfolge erhalten."""
    akte = []
    gesehen = {}
    for pfad in pfade:
        marker, konnektoren = pruefe_rahmen(pfad, lies_json(pfad))
        for nummer, eintrag in enumerate(konnektoren):
            name, umfang, scopes = pruefe_eintrag(pfad, nummer, eintrag)
            if name in gesehen:
                abbruch(14, "%s steht in %s und in %s" % (name, gesehen[name], pfad))
            gesehen[name] = pfad
            offen = ohne_marker(scopes, marker)
            akte.append((pfad, name, umfang, scopes, offen,
                         "ZU WEIT" if offen else "LESEND"))
    return akte


def drucke_eintraege(akte):
    breite = max(len(zeile[1]) for zeile in akte)
    print("1 | Einträge")
    for pfad, name, umfang, scopes, _offen, urteil in akte:
        print("    %s  scopes %d  umfang %d  %-7s [%s]"
              % (name.ljust(breite), len(scopes), umfang, urteil, pfad))


def drucke_abweichungen(akte):
    print("2 | Scopes ohne Lesemarker")
    treffer = [(name, scope) for _p, name, _u, _s, offen, _v in akte for scope in offen]
    if not treffer:
        print("    keine")
        return
    for name, scope in treffer:
        print("    %s -> %s" % (name, scope))


def drucke_bilanz(akte):
    zu_weit = [zeile for zeile in akte if zeile[5] == "ZU WEIT"]
    dateien = len({zeile[0] for zeile in akte})
    print("3 | Bilanz")
    print("    Dateien %d, Einträge %d, über der Lesehaltung %d"
          % (dateien, len(akte), len(zu_weit)))
    print("    Geprüft ist die Form der Zeichenketten in diesen Dateien.")
    print("    Was der Konnektor zur Laufzeit anfordert, steht hier nicht.")
    print("    umfang gleicht niemand ab: halte ihn gegen deine Property-Liste.")
    return 2 if zu_weit else 0


def main(argv):
    if len(argv) < 2:
        sys.stderr.write("Aufruf: scopepruefung.py <konfiguration.json> [weitere.json ...]\n")
        raise SystemExit(3)
    try:
        akte = sammle(argv[1:])
    except Exception as fehler:
        abbruch(13, "unerwartete Ausnahme, kein Befund: %r" % (fehler,))
    drucke_eintraege(akte)
    drucke_abweichungen(akte)
    raise SystemExit(drucke_bilanz(akte))


if __name__ == "__main__":
    main(sys.argv)

Die Konfigurationsdateien der Radwerkstatt Hollerbach sind erfunden – eine Fahrradwerkstatt, die es nicht gibt –, und erfunden sind damit die Einträge, der Lesemarker und jede Zeichenkette in den Scope-Listen. Gemessen hat keine dieser Dateien etwas: die einzigen Zahlen darin sind ausgedachte umfang-Werte. Jede steht in einem eigenen Block ohne Beschriftungszeile; ein Zeilenumbruch am Ende ändert nichts. Zuerst der Normalfall, hollerbach-lesend.json:

{
 "lesemarker": ".lesen",
 "konnektoren": [
  {"name": "search-console-hauptdomain",
   "umfang": 2,
   "scopes": ["platzhalter/berechtigung/suchdaten.lesen",
              "platzhalter/berechtigung/seitenpruefung.lesen"]},
  {"name": "analytics-hauptdomain",
   "umfang": 1,
   "scopes": ["platzhalter/berechtigung/berichtsdaten.lesen"]}
 ]
}

Dann hollerbach-werkstattblog.json, die zweite Property derselben erfundenen Werkstatt, deren zweiter Scope den Marker nicht trägt:

{
 "lesemarker": ".lesen",
 "konnektoren": [
  {"name": "search-console-werkstattblog",
   "umfang": 1,
   "scopes": ["platzhalter/berechtigung/suchdaten.lesen",
              "platzhalter/berechtigung/seitenpruefung"]}
 ]
}

Und hollerbach-doppelt.json, die einen Eintragsnamen von oben wiederholt – eine der beiden Dateien ist veraltet:

{
 "lesemarker": ".lesen",
 "konnektoren": [
  {"name": "search-console-hauptdomain",
   "umfang": 9,
   "scopes": ["platzhalter/berechtigung/suchdaten.lesen"]}
 ]
}

Acht beschädigte Eingaben legen diese Befehle an, aus der ersten Datei oder per printf:

sed '/lesemarker/d' hollerbach-lesend.json > ohne-marker.json
sed 's/"umfang": 2/"umfang": true/' hollerbach-lesend.json > umfang-wahr.json
sed '/"umfang": 2,/d' hollerbach-lesend.json > feld-fehlt.json
printf '{"lesemarker": ".lesen", "konnektoren": []}\n' > leere-liste.json
printf '[]\n' > nur-liste.json
printf '{"lesemarker": ".lesen", "konnektoren": [{"name": "search-console-hauptdomain", "umfang": 1, "scopes": []}]}\n' > scopes-leer.json
printf '{"lesemarker": ".lesen",\n' > halbe-datei.json
printf '{"lesemarker": "\344"}\n' > latin1.json

Dreizehn Aufrufe lösen dreizehn der vierzehn belegten Werte aus. Nicht dabei ist die 13: die unerwartete Ausnahme tritt an keiner dieser Eingaben ein. fehlt.json wird nie angelegt.

$ python3 scopepruefung.py hollerbach-lesend.json
1 | Einträge
    search-console-hauptdomain  scopes 2  umfang 2  LESEND  [hollerbach-lesend.json]
    analytics-hauptdomain       scopes 1  umfang 1  LESEND  [hollerbach-lesend.json]
2 | Scopes ohne Lesemarker
    keine
3 | Bilanz
    Dateien 1, Einträge 2, über der Lesehaltung 0
    Geprüft ist die Form der Zeichenketten in diesen Dateien.
    Was der Konnektor zur Laufzeit anfordert, steht hier nicht.
    umfang gleicht niemand ab: halte ihn gegen deine Property-Liste.
exit 0
$ python3 scopepruefung.py hollerbach-lesend.json hollerbach-werkstattblog.json
1 | Einträge
    search-console-hauptdomain    scopes 2  umfang 2  LESEND  [hollerbach-lesend.json]
    analytics-hauptdomain         scopes 1  umfang 1  LESEND  [hollerbach-lesend.json]
    search-console-werkstattblog  scopes 2  umfang 1  ZU WEIT [hollerbach-werkstattblog.json]
2 | Scopes ohne Lesemarker
    search-console-werkstattblog -> platzhalter/berechtigung/seitenpruefung
3 | Bilanz
    Dateien 2, Einträge 3, über der Lesehaltung 1
    Geprüft ist die Form der Zeichenketten in diesen Dateien.
    Was der Konnektor zur Laufzeit anfordert, steht hier nicht.
    umfang gleicht niemand ab: halte ihn gegen deine Property-Liste.
exit 2
$ python3 scopepruefung.py hollerbach-lesend.json hollerbach-doppelt.json
scopepruefung: search-console-hauptdomain steht in hollerbach-lesend.json und in hollerbach-doppelt.json
exit 14
$ python3 scopepruefung.py ohne-marker.json
scopepruefung: kein lesemarker in ohne-marker.json: ohne ihn wird nichts beurteilt
exit 8
$ python3 scopepruefung.py umfang-wahr.json
scopepruefung: umfang-wahr.json, search-console-hauptdomain: umfang ist keine ganze Zahl
exit 11
$ python3 scopepruefung.py feld-fehlt.json
scopepruefung: feld-fehlt.json, Eintrag 0 führt kein Feld umfang
exit 9
$ python3 scopepruefung.py leere-liste.json
scopepruefung: konnektoren ist eine Liste ohne Einträge: leere-liste.json
exit 12
$ python3 scopepruefung.py nur-liste.json
scopepruefung: kein Objekt mit konnektoren als Liste: nur-liste.json
exit 7
$ python3 scopepruefung.py scopes-leer.json
scopepruefung: scopes-leer.json, search-console-hauptdomain: scopes ist keine nicht leere Liste
exit 10
$ python3 scopepruefung.py halbe-datei.json
scopepruefung: kein gültiges JSON: halbe-datei.json (Expecting property name enclosed in double quotes: line 2 column 1 (char 25))
exit 6
$ python3 scopepruefung.py latin1.json
scopepruefung: nicht UTF-8 kodiert: latin1.json ('utf-8' codec can't decode byte 0xe4 in position 16: invalid continuation byte)
exit 5
$ python3 scopepruefung.py fehlt.json
scopepruefung: keine lesbare reguläre Datei: fehlt.json
exit 4
$ python3 scopepruefung.py
Aufruf: scopepruefung.py <konfiguration.json> [weitere.json ...]
exit 3

Drei Grenzen druckt das Skript selbst in den dritten Abschnitt: geprüft sind Zeichenketten in Dateien, und was der Konnektor zur Laufzeit anfordert, steht in keiner von ihnen.

Google Analytics 4 teilt die Datei, die Einwilligung und den Entzug

Google Analytics 4 steht in derselben Konfigurationsdatei und unter derselben Einwilligung wie Google Search Console; im Prüfer oben ist es der Eintrag analytics-hauptdomain, beurteilt nach derselben Regel. delaren47/gsc-ga4-mcp bedient beide Quellen aus einem Server, weil sich kein Schritt unterscheidet: dasselbe Programm, dieselbe OAuth-Autorisierung, dieselbe Entscheidung über die Berechtigung. Deshalb steht Google Analytics 4 hier als Unterabschnitt: zwei Seiten unterschieden sich um ein Substantiv.

Eine Folge wird übersehen: liegen beide Quellen hinter einer Einwilligung, ist auch der Entzug einer. Notiere das Datum der Erteilung neben der Konfiguration, sonst steht die Einwilligung noch, wenn die Frage längst beantwortet ist.

Unterschiedlich sind die Fragen, die jede Quelle beantwortet. Welche Anfrage in Google eine Impression und einen Klick eingetragen hat, weiß Google Search Console; was die Sitzung danach getan hat, weiß Google Analytics 4. Keines der Produkte hält die andere Hälfte, also kann ein Agent mit beiden im Lesezugriff sie zusammenführen – solange er die Zusammenführung als ungefähr ausweist. Mit nur einer kommt die halbe Antwort aus einer Vermutung im gleichen sicheren Ton. Wie man Zahlen aus beiden Quellen über die Zeit liest, steht in Level 5 zu SEO-Analytics und Messung.

Was Claude über die API liest, zeigt die Oberfläche anders

Oberfläche und Search-Analytics-API laufen nicht synchron, und dafür gibt es einen datierten Fall. Google Search Central kündigte am 24. September 2026 die Aufteilung des Suchtyps Web in web: text-based und web: multimodal an, „rolling out globally starting today“. Die Referenz der API zu searchanalytics.query, Stand 11. August 2026, am 26. September 2026 nachgesehen, führt keinen multimodalen Wert. Beide Quellen stehen hier ohne Link.

Die Folge: ein MCP-Server fragt die API, arbeitet mit der Summe und kann eine Dimension nicht aufschlüsseln, die die API nicht ausgibt. Bittest du den Agenten, einen Sprung zu erklären, der erst mit der neuen Aufteilung sichtbar wird, greift er nach einer anderen Erklärung.

Was die neuen Zeilen bedeuten, ist offen, und diese Lektion entscheidet es nicht. Entweder tragen sie Impressionen, die vorher nicht gezählt wurden, oder solche, die in der alten Summe schon steckten. Daran hängt, wie du den Sprung in deiner Grafik liest: in der ersten Lesart steigt die Summe, während deine Website unverändert bleibt; in der zweiten gibt die Textzeile ab, was die neue Zeile gewinnt.

Für die erste Lesart spricht Google selbst. John Mueller schrieb am 24. September 2026 um 14:16 UTC auf Bluesky zuerst „I’ll double-check, I thought these were not reported at all before“ und danach „And … checking with the team, the data wasn’t previously in the counts, the report has new data“.

Für die zweite Lesart spricht eine Beobachtung an Properties. Dave Smart, zitiert von Barry Schwartz bei Search Engine Roundtable am 24. September 2026: „I am seeing corresponding drops in impressions and clicks starting the 10th on a few properties“. Zu dieser Beobachtung wurden keine Zahl der Properties, kein Impressionsvolumen und keine Domains veröffentlicht – ein Praktiker auf einer nicht genannten Zahl von Websites.

Entscheiden ließe sich das mit einer gepaarten Impressionsreihe über beide Daten hinweg, bei der die Properties offenliegen. Eine solche Reihe hat niemand veröffentlicht, und Google hat keine Notiz zu einem Beginn der Datenerhebung veröffentlicht; kein Lager kann seinen Fall zeigen. Die Richtung des Sprungs in deiner Summe ist damit keine Position, sondern eine Messung: exportiere beide Seiten des 24. September 2026.

Die Anbindung spart Arbeit und entscheidet nichts

Ein angebundenes Search Console nimmt dir das Exportieren und Zusammenrechnen ab, nicht das Urteil. Anfragen gruppieren, URLs im Stapel prüfen, Zeiträume gegeneinanderstellen, Impressionsrückgänge Verzeichnis für Verzeichnis verfolgen: der Teil, der vorher aus Export und Tabelle bestand. Dass das Urteil nicht mitwandert, belegen zwei Quellen.

Keyword.com legt eine Stichprobengröße offen, was selten genug ist: „State of AI in SEO 2026“ vom 1. Januar 2026 beruht auf n = 97 verwertbaren Antworten, selbst gewählte Teilnahme, ohne veröffentlichte Fehlermarge. Darin setzen 38 % KI für technische SEO-Audits ein, und genau 1 % – eine Person von 97 – beschreibt die eigene Arbeit als vollständig automatisiert. Eine Rangfolge unter 97 Antworten, keine Hochrechnung auf die Branche.

Echte Zahlen helfen dem Modell weniger als erwartet. Bei ContextBolt hat „David“ am 23. Juni 2026 eine Woche seines eigenen SEO mit Claude geführt und protokolliert, dass das Modell fremde Schätzungen wie Messwerte behandelte und ein aussichtsloses Keyword weiterempfahl, während dessen Schwierigkeitswert auf dem Schirm stand. Ein Autor, eine Website, sieben Tage, keine Vergleichsgruppe, keine veröffentlichte Stichprobengröße. Eine Anbindung korrigiert die Herkunft der Zahlen, nicht das, was ein Modell mit einer Zahl macht.

Eine Grenze verschiebt kein Konnektor. Lawrence Hitches fasste sie am 2. April 2026 in „Claude for Technical SEO“ in einen Satz: Claude wertet Crawl-Daten aus, es crawlt keine Websites. Welche Fragen erst ein eigener Crawl beantwortet, steht in Level 2 zu technischem SEO, und Was Claude im SEO leisten kann – und was nicht nimmt das Modell ohne jede Anbindung auseinander. Ein angebundenes Search Console übergibt dir Googles Bericht über deine Seiten, gefiltert durch das, was Google berichten wollte – eine Beschreibung aus zweiter Hand, so frisch die Zahlen darin auch sind.

Häufige Fehler

  • Eine Datei prüfen, die der Client nicht lädt. Zwei Konfigurationen mit demselben Eintragsnamen heißen, dass eine veraltet ist, und geprüft wird gern die gepflegte. Die Korrektur: beide in einem Aufruf übergeben – der Prüfer endet bei 14.
  • Aus einer 0 eine Freigabe lesen. Sie sagt, dass die Zeichenketten in deiner Datei die richtige Form haben – über das, was der Autorisierungsserver zurückgibt, nichts. Die Korrektur: Einträge und umfang von Hand gegen den Dialog halten, und den Befund pro Eintrag lesen statt pro Datei: einer genügt für ZU WEIT.
  • Alle Properties freigeben, weil der Dialog sie gemeinsam anbietet. Eine Einwilligung über acht Properties beantwortet die Frage zu einer davon genauso gut und steht hinterher für alle acht. Die Korrektur: zählen, wie viele die Frage braucht, und diese Zahl als umfang neben die Konfiguration schreiben.

Kurzfassung

  • Die Oberfläche der Search Console trennte den Suchtyp Web am 24. September 2026 in web: text-based und web: multimodal; die API-Referenz zu searchanalytics.query (Stand 11. August 2026, nachgesehen am 26. September 2026) führt keinen multimodalen Wert. Ein MCP-Server fragt die API, also sieht Claude die Trennung nicht.
  • scopepruefung.py druckt nur bei 0 und 2 ein Urteil über deine Konfiguration; jede unlesbare oder unvollständige Eingabe bekommt ihren eigenen Wert. Vierzehn Werte sind belegt, die 1 bleibt für den Absturz frei – eine beschädigte Datei kann so nicht als Lesehaltung durchgehen.
  • Für Google Search Console ist kein Konnektor von Anthropic und keiner von Google dokumentiert: Dewang Mishra führt die Quelle bei Passionfruit am 28. März 2026 unter „Community / self-hosted“, und der Bestand für diesen Kurs wurde am 20. September 2026 geprüft. Gepflegt werden AminForou/mcp-gsc (Version 0.3.3, Juli 2026) und delaren47/gsc-ga4-mcp, das beide Quellen hinter einer Einwilligung bedient – der Entzug trifft dann beide.
  • Die Lesehaltung begründet sich aus einer Asymmetrie: zu schreiben gibt es in Google Search Console und Google Analytics 4 nichts, was du willst, zu verlieren das Instrument, mit dem du den Agenten prüfst. Ein gemessener Fall, in dem ein Agent dort Daten beschädigt hätte, steht in diesen Quellen nicht – also auch keine Stichprobengröße.
  • Eine Berechtigungszeichenkette steht hier nicht, weil keine Quelle dieser Lektion eine dokumentiert. Den Lesemarker liest du auf deinem eigenen Einwilligungsdialog ab und trägst ihn in die Konfiguration ein; der Prüfer urteilt damit.
  • Ob die multimodalen Zeilen neue Daten oder eine Umbuchung sind, ist strittig: John Mueller sagt am 24. September 2026 neu, Dave Smart beobachtet Rückgänge ab dem 10. auf einer nicht genannten Zahl von Properties, und eine gepaarte Impressionsreihe über beide Daten hat niemand veröffentlicht. Beantworte es an deinem Export.

Häufige Fragen

Ich habe mehrere Properties – welche gebe ich frei?

Die, welche in der Frage vorkommen, und die zählst du vorher. Eine Einwilligung über alle Properties lässt sich hinterher nicht verengen, nur zurücknehmen und neu erteilen – und auffallen wird sie kaum, solange die Antworten stimmen. Schreibe vor dem Dialog auf, welche Property die Frage nennt.

Reicht es, die Konfigurationsdatei zu prüfen, oder muss ich den Dialog lesen?

Der Dialog entscheidet, die Datei erklärt nur, was der Client anfragen wird. Deshalb liest du den Lesemarker auf dem Dialog ab, und deshalb druckt der Prüfer hin, dass er über die Laufzeit nichts weiß. Prüfe die Datei, um eine zu weite Anfrage zu verhindern, bevor sie gestellt wird – und lies den Dialog, weil dort steht, was tatsächlich erteilt wird.

Welche Zahl gehört in umfang, und was macht der Prüfer damit?

Hinein gehört die Zahl der Properties, für die die Einwilligung gelten soll. Der Prüfer stellt zwei Dinge daran fest: dass das Feld da ist und dass es eine ganze Zahl trägt – ein true weist er ab, weil ein Wahrheitswert in Python eine Ganzzahl ist. Verglichen wird die Zahl mit nichts: dass sie zu deiner Property-Liste passt, stellst du selbst fest, und dieser Abgleich ist der einzige Teil der Prüfung, den kein Rückgabewert anzeigen kann.

Quellen

Wo (ohne Link) steht, trägt die Quelle Publikation, Autor und Datum und keine URL.

  • Dewang Mishra, Passionfruit, „MCP Connectors for Marketing: Connect Claude to Your Entire Stack (2026)“ – 28. März 2026. Google Search Console dort unter „Community / self-hosted“.
  • GitHub, AminForou/mcp-gsc – Version 0.3.3, Juli 2026; rund 1.300 Sterne, 183 Forks, 20 Werkzeuge. Geprüft am 20. September 2026.
  • GitHub, delaren47/gsc-ga4-mcp – beide Quellen hinter einer Einwilligung. Geprüft am 20. September 2026.
  • Semrush, „Semrush MCP“ – Stand 5. August 2026.
  • Anthropic, Konnektorseite zu Ahrefs – Metadatum „Added January 2026“.
  • Keyword.com, „State of AI in SEO 2026“ – 1. Januar 2026. n = 97 verwertbare Antworten, selbst gewählte Teilnahme, keine veröffentlichte Fehlermarge. Drei Werte verwendet: 38 % KI bei technischen SEO-Audits, 57 % nennen mangelnde Qualität als Grund, weitere Automatisierung liegen zu lassen – Anteil dieser Teilgruppe, nicht der 97 Antworten; eine Person von 97 vollständig automatisiert.
  • David, ContextBolt, „Claude SEO Experiment: A Week of Running My Real SEO“ – veröffentlicht am 23. Juni 2026. Ein Autor, eine Website, sieben Tage, keine Vergleichsgruppe, keine veröffentlichte Stichprobengröße.
  • Lawrence Hitches, „Claude for Technical SEO: Audits, Crawl Fixes & Schema“ – 2. April 2026. Ohne Stichprobengröße.
  • Google, Referenz der Search Analytics API zu searchanalytics.query – Stand 11. August 2026, nachgesehen am 26. September 2026. Kein multimodaler Wert. (ohne Link)
  • Google Search Central, Ankündigung der Aufteilung des Suchtyps Web – 24. September 2026, „rolling out globally starting today“. (ohne Link)
  • John Mueller, Beiträge auf Bluesky – 24. September 2026, 14:16 UTC. (ohne Link)
  • Dave Smart, zitiert von Barry Schwartz bei Search Engine Roundtable – 24. September 2026. Keine Zahl der Properties, kein Impressionsvolumen, keine Domains veröffentlicht. (ohne Link)
  • scopepruefung.py, die drei Konfigurationsdateien, die acht Vorbereitungsbefehle und die dreizehn Aufrufe stehen oben vollständig: nur Standardbibliothek, kein Netzzugriff, vierzehn belegte Rückgabewerte. Die Ausgabe hängt allein an den abgedruckten Dateien und trägt kein Datum. Die Dateien der Radwerkstatt Hollerbach sind erfunden.

Weiter im Kurs