Słownik chciał wygodniejszych drzwi. Notatki z wyprowadzki MCP z WordPressa

przez lukasz | lip 1, 2026 | Bez kategorii | 0 komentarzy

Nie zamierzałem budować bramki MCP. Zamierzałem przestać edytować słownik przez formularz WordPressa. To jest uczciwy zapis drogi między tymi dwoma punktami — decyzji, podwójnych uprawnień, pytań, na które wciąż nie mam pełnej odpowiedzi. Jedna budowa, opisana od środka.


Wszystko zaczęło się od żmudnej roboty.

Prowadzę słownik pojęć agentic web. Mieszka w WordPressie. Dodawanie, edycja i kasowanie haseł przez panel administracyjny jest znośne przy jednym pojęciu i męczące przy pięćdziesięciu. Chciałem wygodniejszych drzwi — czegoś, z czym mogę rozmawiać, zamiast formularza, przez który muszę się przeklikać.

Oczywistą odpowiedzią było REST API. WordPress je wystawia; mogłem oskryptować się w jedno popołudnie i mieć spokój. Ale jesteśmy w środku przejścia na agentic web, a MCP staje się portem USB tej epoki — standardową wtyczką, której agent się spodziewa. W tym świetle podpięcie słownika zwykłym skryptem REST byłoby jak kładzenie własnego, zamkniętego kabla, kiedy uniwersalne gniazdo leży obok. Żal byłoby nie skorzystać.

Prawdziwe pytanie nigdy więc nie brzmiało „REST czy MCP". Brzmiało: gdzie ten serwer MCP ma mieszkać. I to pytanie okazało się całą historią.

Wersja łatwa — i linijka, którą w niej zostawiłem

Najszybsza droga to serwer MCP wewnątrz WordPressa — wtyczka, narzędzia podpięte prosto do bazy przez istniejącą warstwę REST. Zbudowałem to najpierw. Zadziałało w jedno popołudnie, dokładnie tak, jak obiecywano.

Zawierało też jedną linijkę, którą napisałem świadomie i świadomie w nim zostawiłem:

php

'permission_callback' => '__return_true',   // każdy może wywołać ten endpoint

To nie było lenistwo. Kiedy serwer MCP mieszka wewnątrz WordPressa, granica bezpieczeństwa przebiega przez WordPressa -między endpointem MCP a resztą aplikacji - i musisz tę granicę zbudować oraz utrzymać sam, w PHP, w tym samym procesie, który renderuje Twojego bloga. __return_true było odłożeniem tej roboty na później, żeby najpierw zobaczyć, że całość działa. Zadziałała. A otwarte drzwi zostały, i wciąż je kątem oka widziałem.

To „widzenie kątem oka" jest miejscem, w którym zaczęła się druga wersja. (Samą tę linijkę rozłożyłem osobno w pierwszej części serii o bramce — tu jest tylko punktem wyjścia.)

Wyprowadzka

Alternatywa jest bezceremonialna: serwer MCP nie mieszka w WordPressie w ogóle. To osobny proces, na osobnym hoście, który stoi przed WordPressem jak bramka. Agent rozmawia tylko z bramką. Bramka trzyma poświadczenia do WordPressa i decyduje, co przepuścić. Sam WordPress może zniknąć z publicznego internetu.

Ten ruch rozwiązuje __return_true, czyniąc je bezprzedmiotowym — publiczną rzeczą nie jest już WordPress, tylko bramka, która ma uwierzytelnianie od pierwszej minuty. Ale „po prostu wyprowadź to na zewnątrz" ukrywa sześć problemów, które spotkałem dopiero w budowie. Żadnego z nich nie ma w wersji prostej. Wszystkie są ceną za tę granicę.

1. Bramka musi udowodnić, kim jest — a WordPress podał mi odpowiedź

Serwer wewnątrz WordPressa dziedziczy jego sesję. Osobny proces nie dziedziczy niczego. Musi uwierzytelnić się do WordPressa jakoś, jako jakiś użytkownik, jakimś poświadczeniem, które teraz muszę przechować i chronić.

Tu projekt uratowały Application Passwords WordPressa. Dały mi pełnoprawny sposób, by zewnętrzny proces uwierzytelnił się jako realny użytkownik WordPressa, bez ruszania głównego hasła i bez sklecania własnego schematu tokenów. Bramka trzyma Application Password; agent nigdy go nie widzi. Jedna wbudowana funkcja zamieniła paskudny problem w nudny.

2. Dwa systemy uprawnień, wskazujące w różne strony

Potem Application Password wydobył subtelniejszy problem — ten, który uważam za właściwą lekcję całej budowy.

W czystym WordPressie jest jedna oś uprawnień: użytkownik jest subskrybentem, albo redaktorem, albo administratorem. To cały model.

W chwili, gdy bramka staje z przodu, pojawia się druga oś, prostopadła do pierwszej. WordPress wciąż pyta „czy ten użytkownik jest administratorem, czy subskrybentem?". Ale bramka musi teraz odpowiedzieć na inne pytanie: kto dotarł do mnie przez MCP, które narzędzia wolno mu wywołać i dlaczego w ogóle ma do nich dostęp?. To nie są te same pytania. Wywołujący może być — od strony WordPressa — pojedynczym użytkownikiem z jednym Application Password, a jednocześnie — od strony bramki — zasługiwać na dostęp do jednych narzędzi, a nie do innych.

Wersja wewnątrz WordPressa nigdy nie zmusza cię, byś to zobaczył, bo obie osie są zwinięte w jedną. Wyprowadzka je rozdziela i drugą musisz zaprojektować świadomie. To jest część, którą powiedziałbym każdemu, kto zaczyna: trudnym problemem bramki MCP nie jest transport. Jest nim to, że właśnie nabyłeś model uprawnień, którego wczoraj nie miałeś.

3. Wyszedłem z WordPressa, ale nie wyszedłem z jego REST-a

Istnieje fantazja o wersji „na zewnątrz", w której bramka jest czysta i wolna od WordPressa. Rzeczywistość jest bardziej lepka. Bramka wciąż musi z WordPressem rozmawiać, a to oznaczało wybór bez darmowej opcji:

  • przyjąć WordPress REST takim, jaki jest, i ukształtować narzędzia wokół niego, albo
  • dobudować własną warstwę przed nim — cienką fasadę REST, albo, absurdalnie, mały dodatkowy MCP wewnątrz WordPressa tylko po to, by wystawić operacje tak, jak chciałem.

Rozumienie tej trójki to sedno: opuszczenie WordPressa nie znaczy ucieczki od WordPressa. Jego model danych wychodzi za tobą przez drzwi.

4. Pytania, na które trzeba odpowiedzieć przed kodem: CORS, Cloudflare i kto w ogóle woła

Część tej budowy wydarzyła się przed jedną linijką kodu — w topologii. Serwer MCP, który był prywatnym endpointem wewnątrz WordPressa, jest teraz, potencjalnie, publicznym procesem na własnym hoście. To przestawia wszystko: reguły CORS, co stoi z przodu (Cloudflare, reverse proxy, TLS) i pytanie leżące pod nimi wszystkimi — kto właściwie będzie to wołał?

Bo publicznie wystawiony serwer MCP to nowa powierzchnia ataku. Nie wariacja na temat powierzchni ataku WordPressa — naprawdę nowa, mówiąca protokołem, którego większość istniejących narzędzi bezpieczeństwa jeszcze nie inspekcjonuje. W wersji wtyczkowej to pytanie jest stłumione, bo endpoint chowa się za frontowymi drzwiami WordPressa. Wyprowadź go, a musisz zdecydować, wprost, kto jest po drugiej stronie gniazda, zanim je otworzysz.

5. Cache: bramka działa — ale na jakiej wersji prawdy?

Ten wciąż nie jest u mnie rozstrzygnięty. Bramka wykonuje akcje — ale na jakich danych? Jeśli cache'uje stan słownika dla szybkości, agent może zadziałać na haśle, które zmieniło się minutę temu. Jeśli nie cache'uje nigdy, każde wywołanie to podróż w obie strony do WordPressa. Opcje są niedoskonałe: nie cache'ować; cache'ować, ale jakoś sygnalizować nieświeżość; cache'ować przez ograniczony czas i zaakceptować okno błędu. Dla słownika stawka jest niska. Dla bramki stojącej przed czymkolwiek transakcyjnym to jest cała gra — i nie sądzę, by istniała odpowiedź domyślnie poprawna. Jest tylko odpowiedź poprawna dla danego narzędzia.

6. Brak hooków — separacja tnie w obie strony

Najczystsza rzecz w wyprowadzeniu MCP z WordPressa jest zarazem najbardziej ograniczająca. Poza procesem dostaję prawdziwą izolację: agent nie może tknąć wnętrzności WordPressa bezpośrednio. To jest zaleta.

Ale to też koszt. Straciłem dostęp do wszystkiego, co WordPress daje wewnątrz procesu — hooków, filtrów, całego modelu zdarzeń, który wtyczka bierze za pewnik. Stojąc na zewnątrz, nie zawieszę logiki na akcji WordPressa; mogę ją tylko wywołać z frontu i zareagować na to, co zwróci. Izolacja, której chciałem dla bezpieczeństwa, jest tą samą izolacją, która odcina mnie od własnej maszynerii platformy. Jednego nie ma bez drugiego.

Gdzie to właściwie wylądowało

Zacząłem od chęci wygodniejszej edycji słownika. Skończyłem, trzymając pytanie, którego tego ranka nie miałem: gdzie ma mieszkać warstwa narzędzi dla agenta — wewnątrz aplikacji, której służy, czy przed nią, jako osobny obywatel?

Nie sądzę, by istniała uniwersalna odpowiedź, i przestałem jej szukać. Wewnątrz jest prościej i dziedziczy tożsamość platformy oraz hooki za darmo. Z przodu daje prawdziwą granicę zaufania, miejsce na sekrety i niezależny cykl życia — a w zamian wręcza ci drugi model uprawnień, pytanie o cache i nową publiczną powierzchnię do obrony. Dla słownika wygrało „z przodu", ale tylko dlatego, że już wiedziałem, iż docelowo chcę za bramką więcej niż jeden backend.

Co testuję dalej

To nie jest skończone, i wolę powiedzieć, gdzie jest krawędź, niż udawać, że to gotowy produkt.

Następna rzecz, którą chcę wiedzieć, to czy MCP wygodnie niesie payloady binarne — pliki, nie tylko tekst i JSON. Jeśli to się utrzyma, kolejny test jest tym, na którym naprawdę mi zależy: generowanie grafik na backendzie przez LLM i odsyłanie ich przez MCP do panelu efektów. To zupełnie inne obciążenie niż przerzucanie haseł słownika, i jeszcze nie wiem, gdzie się napina.

Jeśli pęknie, to będzie następna notatka terenowa. Co jest uczciwym stanem większości tej roboty — mapę rysuje się krok po kroku, w miarę jak się je przechodzi, a najciekawsza jest zawsze ta część, której jeszcze nie przeszedłeś.


To jest raport z działającego systemu: bramka MCP przed słownikiem pojęć agentic web hostowanym w WordPressie. Pomyłki i otwarte pytania są moje, z opisanej budowy. Jeśli są znajome — dobrze. Jeśli jeszcze nie, będą, gdy pierwszy raz wyprowadzisz serwer MCP z aplikacji, której służy.