Wszystkie wpisy

19 czerwca 2026

Audyt GTM przez MCP w Claude Code

Mam kontener web GTM i sGTM skonfigurowany pod pmdata.pl. Mam notatki z kursu Stape o GA4 server-side. I mam pytanie: czy Claude z dostępem do GTM API przez MCP potrafi skrzyżować te dwie rzeczy — przeczytać moją konfigurację i powiedzieć, gdzie odbiega od wzorca?

To nie był test “czy AI ogarnie GTM od zera”. To był test konkretnego use case’u — audyt GTM przez MCP: porównanie istniejącego wdrożenia z dokumentacją.

Jak działa MCP server Google Tag Manager

MCP (Model Context Protocol) to standard, który pozwala modelowi językowym wywoływać zewnętrzne API jak własne narzędzia. Nie muszę opisywać Claude’owi, co jest w kontenerze, ani wklejać screenshotów — model odpytuje GTM bezpośrednio.

Dostępne są dwa serwery — oba third-party, bo Google oficjalnego nie wydał:

  • Stape (gtm-mcp.stape.ai) — 19 zgrupowanych toolów, hosted, OAuth przez serwery Stape. Prostszy na start.
  • Paolo Bietolini (mcp.gtmeditor.com) — ok. 50 osobnych toolów, self-host albo hosted (przy self-host token OAuth zostaje lokalnie, nie wychodzi na cudzy serwer). Wyróżnia go import_gallery_template — jedyna implementacja tej funkcji — oraz warstwa kontekstu domenowego dla modelu: skill dla Claude Code z przepisami jak formatować tagi i odkrywać ID encji (plus osobne repozytorium gtm-api-for-llms ze schematami encji). Stape nic z tego nie ma.

Skonfigurowałem Stape — Paolo dorzucam niżej jako alternatywę. Obie instalacje to jedna komenda:

# Stape
claude mcp add google-tag-manager-mcp-server -- npx -y mcp-remote https://gtm-mcp.stape.ai/mcp

# Paolo (alternatywa)
claude mcp add -t http gtm https://mcp.gtmeditor.com

Pierwsze wywołanie toola → przeglądarka → OAuth z kontem Google → gotowe. Oba serwery mogą działać równolegle w tej samej sesji — narzędzia każdego serwera dostają własny prefiks z jego nazwą, więc nie kolidują. Paolo możesz wywołać do importu szablonu z galerii tam, gdzie Stape nie dotrze.

Cała ścieżka — od polecenia w Claude Code po zapis encji w kontenerze — wygląda na przykładzie serwera Paolo tak:

Claude Code
klient MCP — Twoje polecenia
HTTP · wywołania toolów
Serwer MCP Paolo
mcp.gtmeditor.com · firma trzecia
OAuth 2.1 + PKCE (Google)
GTM API v2
publiczne API Google
odczyt / zapis encji
Kontenery GTM
web + sGTM
Flow Paolo: Claude Code woła toole przez HTTP, serwer MCP autoryzuje się w Google (OAuth 2.1 + PKCE) i uderza w GTM API v2, które czyta i zapisuje encje w obu kontenerach. Odpowiedź wraca tą samą drogą. Żaden z tych serwerów nie jest produktem Google — to integracje firm trzecich nad publicznym GTM API. Paolo dorzuca do tego skill dla Claude Code — warstwę kontekstu domenowego, którą model ładuje osobno.

Audyt GTM przez MCP — krok po kroku

Dałem mu plik z notatkami z lekcji (Markdown z opisem kanonicznego setupu GA4 server-side) i powiedziałem: sprawdź mój GTM pod tym kątem.

Claude równolegle odpytał oba kontenery — web i sGTM. W jednym wywołaniu pobrał listę workspace’ów, w kolejnym — tagi, triggery, zmienne, clients i transformacje ze wszystkich workspace’ów naraz. To co w GTM UI zajęłoby kwadrans klikania — tutaj zajęło kilkanaście sekund i jedno polecenie.

Potem skrzyżował dane z lekcją i wypluł tabelę rozbieżności:

  • Trigger ga4 - client_name all w sGTM używał warunku contains GA4 zamiast equals GA4 — lekcja mówi equals. Różnica subtelna, ale equals jest precyzyjniejsze.
  • Parametr redactVisitorIp w tagu GA4 - Base ustawiony na false — sGTM przepuszczał prawdziwy IP klientów do GA4. W EU to nie jest decyzja do pominięcia.
  • Transformacje z workspace “Do not publish!!!” nie istniały w Default Workspace — co wyglądało jak rozbieżność, ale okazało się celową architekturą.

Dwie pierwsze poprawki Claude wprowadził przez API bezpośrednio, bez otwierania UI. Trzecia wymagała wyjaśnienia kontekstu (patrz niżej) — po czym uznał, że nie ma co naprawiać.

Analogiczna weryfikacja bez MCP wyglądałaby tak: otwórz GTM, kliknij trigger, sprawdź warunek, wróć, otwórz tag, sprawdź parametr, zapisz w notatniku, porównaj z lekcją ręcznie. Przy kilkudziesięciu elementach — zajmuje czas i łatwo coś przegapić.

Gdzie ma realne przewagi

Czytanie konfiguracji w całości. API zwraca pełną strukturę obu kontenerów naraz. Żadne kliknięcie w UI nie da takiego widoku. Przy audycie dużego kontenera z kilkudziesięcioma tagami to nie jest kosmetyczna różnica.

Zmiany chirurgiczne i jawne. Agent zmienia dokładnie jedno pole, a cały payload widać w rozmowie — wiadomo co i dlaczego się zmieniło, zostaje ślad. W klikanym UI łatwiej trafić nie w to pole albo zapomnieć, co się ruszyło. Dodatkowo każdy zapis niesie znacznik wersji elementu (fingerprint): jeśli między odczytem a zapisem coś ten element zmieniło — choćby Ty w drugiej karcie UI — API odrzuca zapis, zamiast po cichu nadpisać.

Kontekst projektu z CLAUDE.md. Opisałem w nim architekturę workspace’ów — że “Do not publish!!!” to środowisko treningowe z tagami marketingowymi i e-commerce, których nigdy nie opublikuję, bo pmdata.pl to portfolio bez sklepu i bez tych tagów w polityce prywatności. Dzięki temu Claude nie traktował rozbieżności między workspace’ami jako błędu do naprawienia. Bez tego kontekstu zadawałby pytania albo — gorzej — “naprawiał” rzeczy, które nie wymagają naprawy.

Problemy — bez lukrowania

Sesja OAuth wygasa po godzinie — i nie da się jej odświeżyć w tle. Przyczyna jest architektoniczna. Stape działa przez mcp-remote — lokalny podproces npx, który bridguje stdio do zdalnego serwera HTTP. Gdy token wygaśnie, ten pośrednik musi ponownie otworzyć przeglądarkę i przeprowadzić cały OAuth flow. Podproces stdio nie radzi sobie z callbackiem w środku sesji — wisi bez błędu i bez sukcesu. Jedyne wyjście: restart Claude Code, ponowna autoryzacja.

StapePaolo
Transportstdio przez mcp-remotehttp natywny
Kto zarządza OAuthosobny proces npxClaude Code bezpośrednio
Token storage~/.mcp-auth/ (plik lokalny)zarządzane przez Claude Code
Refresh po wygaśnięciu❌ wymaga restartu i przeglądarki✅ działa w tle

Paolo tego problemu nie ma, bo używa natywnego transportu HTTP — Claude Code sam zarządza OAuth bezpośrednio, bez pośrednika npx. Token refresh działa w tle.

Restart = utrata kontekstu. Po restarcie Claude nie pamięta nad czym pracował. Trzeba mu od nowa wytłumaczyć projekt, kontenery, zasady workspace’ów, co już sprawdziliśmy. Im więcej kontekstu w CLAUDE.md, tym mniej bólu — ale i tak część idzie na marne. Strata 10-15 minut przy każdym restarcie to realna cena.

Szablony z galerii (vendor templates) — API blokuje write. Wszystkie tagi oparte na szablonach importowanych z galerii (cvt_XXXX) można odczytać przez API, ale nie można ich edytować. Wywołanie write zwraca Unknown entity type. Dotyczy popularnych szablonów Stape: Data Tag, Data Variable, Stape Store Writer i innych. Pierwsza konfiguracja i zmiany tych elementów wymagają ręcznej pracy w GTM UI.

Brak importu szablonów z galerii (w Stape). Nowy szablon — Meta Pixel, Data Tag, cokolwiek z Community Gallery — trzeba dodać ręcznie przez UI zanim Claude może go użyć. MCP Paolo implementuje import_gallery_template, Stape nie.

Czego agent nie zastąpi

MCP zarządza konfiguracją kontenera — nie infrastrukturą. Nie postawi serwera sGTM (Cloud Run, Stape hosting), nie skonfiguruje DNS, certyfikatu SSL ani Netlify Edge Function. To osobna warstwa, której GTM API w ogóle nie dotyka.

GTM Preview i Tag Assistant wymagają interaktywnej sesji przeglądarki. MCP może wywołać quickPreview, ale nie zastąpi ręcznego debugowania złożonych flow w UI — szczególnie gdy chcesz zobaczyć sekwencję odpalenia tagów i wartości zmiennych w czasie rzeczywistym.

Publish do live — celowa bariera. Konto agenta z uprawnieniem Approve (nie Publish) oznacza, że Claude przygotuje workspace i wersję, ale nie wypuści zmian na produkcję samodzielnie. To nie jest ograniczenie MCP — to świadoma decyzja. Agent edytuje, człowiek zatwierdza.

Praktyczne wnioski

Najsilniejszy use case to audyt + cross-reference: masz wdrożenie i dokumentację (lekcję, własne notatki, specyfikację tracking planu), chcesz wiedzieć co się rozjechało. Claude pobiera całą konfigurację naraz i porównuje — szybciej i dokładniej niż ręcznie.

Drugi use case: drobne, precyzyjne zmiany — zmiana warunku triggera, parametru tagu, wartości zmiennej. Bez otwierania UI, z pełną historią w rozmowie co i dlaczego zmieniono.

Nie zastępuje GTM UI przy budowaniu setupu od zera z szablonami vendorskimi — zbyt wiele elementów wymaga ręcznej inicjalizacji przez galerię.

Jeśli planujesz dłuższe sesje z GTM przez MCP — miej plan na restart. Token Stape wygasa i nie da się go odświeżyć bez restartu (problem mcp-remote, opisany wyżej), restart kosztuje kontekst. Im więcej projektu opisanego w CLAUDE.md (architektura workspace’ów, zasady publikacji, co jest czym), tym tańszy restart. I rozważ Paolo zamiast Stape albo równolegle — natywny HTTP transport eliminuje problem OAuth, a skill dla Claude Code (przepisy formatowania tagów, kolejność operacji, reguły bezpieczeństwa) robi robotę, którą przy Stape musisz wykonać ręcznie przez CLAUDE.md.


Artykuły powiązane: jak zbudowałem self-review loop z hookami Claude Code i server-side GTM a adblocki — co naprawdę zyskujesz.

Powiązane wpisy