Jak z ChatGPT zrobić semi-agenta. Własny MCP z folderem, Pythonem, PowerShellem i ngrok
Pełny agent brzmi widowiskowo, ale zwykle kończy się nadmiarem uprawnień i niedomiarem kontroli. Znacznie rozsądniejszy jest semi-agent: ChatGPT dostaje kilka precyzyjnych narzędzi, działa na jednym katalogu i wykonuje wybrane zadania. Bez pełnego shella, bez dostępu do całego dysku, bez niepotrzebnego ryzyka.
Notatka przed czytaniem
Architektura przepływu bez sztucznego dymu i laserów
ChatGPT dostaje zestaw narzędzi MCP, ruch wpada przez tunel, trafia do lokalnego endpointu, a stamtąd tylko do jednego workspace i kontrolowanych akcji.
ChatGPT jako semi-agent, nie jako bóg infrastruktury
Jeżeli chcesz, żeby ChatGPT naprawdę pomagał przy technicznej robocie, nie potrzebujesz od razu pełnej autonomii. Potrzebujesz modelu, który może dokładnie to, na co mu pozwolisz.
U nas najlepiej sprawdził się wariant pośredni: semi-agent do pracy na jednym repo. Taki układ nie steruje całym systemem. Widzi jeden katalog roboczy, umie czytać i zapisywać pliki tekstowe, potrafi uruchamiać przygotowane skrypty w Pythonie i PowerShellu. I na tym koniec.
To już wystarcza do zaskakująco dużej liczby zadań: poprawy konfiguracji, generowania plików pomocniczych, uruchamiania walidacji, analizy wyników i ponawiania prób. Nadal nie jest to pełny agent. I bardzo dobrze.
Co zbudowaliśmy u siebie
Zamiast wielkiego kombajnu postawiliśmy connector minimum. Operacyjnie korzystamy tylko z zestawu narzędzi, który naprawdę ma sens dla codziennej pracy technicznej.
get_root
list_dir
read_file_text
write_file_text
append_file_text
stat_path
search_text
run_python_file
run_powershellTo jest punkt, w którym ChatGPT staje się użyteczny, ale jeszcze nie zamienia się w cyfrowego stażystę z kluczem do serwerowni. Sam serwer może wystawiać więcej funkcji, ale do scenariusza semi-agenta używamy tylko wybranego minimum tooli.
Jeden folder zamiast całego świata
Najważniejszy element bezpieczeństwa nie siedzi w promptach. Siedzi w granicach serwera. Kluczowa zasada była prosta: semi-agent działa tylko w obrębie repo.
- operacje plikowe wykonują się w katalogu projektu
- Python uruchamia wyłącznie pliki .py z repo
- PowerShell działa tylko z workdir mieszczącym się w repo
- najpierw testujemy odczyt, potem zapis, a dopiero na końcu procesy wykonawcze
Mniej elastyczności, więcej przewidywalności. W praktyce to bardzo dobry interes, bo model nie ma fizycznej możliwości wędrówki poza ustaloną strefę.
Czego brakowało wcześniej: instalacja FastMCP i ngrok
Poprzednia wersja tekstu miała istotną lukę. Opisywała uruchomienie i tunelowanie, ale nie prowadziła czytelnika od zera przez instalację FastMCP i instalację ngrok.
To ważne także dlatego, że w naszym repo kod importuje FastMCP, ale obecny requirements.txt nie zawiera jeszcze jawnie pakietu fastmcp. Czyli ktoś, kto postawi środowisko wyłącznie z tego pliku, może skończyć z klasycznym błędem o brakującym module.
Instalacja FastMCP krok po kroku
Jeżeli startujesz od zera, najpierw przygotuj środowisko:
cd C:\jagoda-memory-api
python -m venv .venv
.\.venv\Scripts\Activate.ps1Jeżeli PowerShell blokuje aktywację:
Set-ExecutionPolicy -Scope Process -ExecutionPolicy Bypass
.\.venv\Scripts\Activate.ps1Potem instalujesz zależności z repo:
.\.venv\Scripts\python.exe -m pip install -r requirements.txtA następnie doinstalowujesz FastMCP:
.\.venv\Scripts\python.exe -m pip install fastmcpJeżeli chcesz od razu naprawić projekt, a nie tylko środowisko lokalne, dopisz fastmcp do requirements.txt, żeby kolejna osoba nie musiała zgadywać, czego brakuje.
Na końcu sprawdź, czy FastMCP faktycznie siedzi w środowisku:
fastmcp versionInstalacja ngrok krok po kroku
ngrok nie jest częścią repo Python i nie powinien udawać, że nią jest. To osobny składnik infrastrukturalny, instalowany systemowo obok projektu.
Najprostsza ścieżka jest taka: instalujesz ngrok Agent CLI systemowo, logujesz go do swojego konta przez authtoken, sprawdzasz konfigurację i dopiero potem wystawiasz lokalny port.
Po instalacji sprawdzasz, czy narzędzie działa:
ngrok versionNastępnie podłączasz konto:
ngrok config add-authtoken <TWOJ_TOKEN>Potem weryfikujesz konfigurację:
ngrok config checkA jeśli wszystko jest poprawnie, uruchamiasz tunel na lokalny serwer:
ngrok http 8015Jak uruchamialiśmy to lokalnie
Projekt działał lokalnie w katalogu C:\\jagoda-memory-api. Serwer startowaliśmy zwyczajnie:
python server.pyPo poprawnym uruchomieniu aktywny był lokalny endpoint:
http://127.0.0.1:8015/mcp/Przed startem środowiska warto też sprawdzić bazę, aktywować virtualenv i odświeżyć zależności.
python --version
pip --version
powershell -v
.\.venv\Scripts\Activate.ps1
Set-ExecutionPolicy -Scope Process -ExecutionPolicy Bypass
.\.venv\Scripts\Activate.ps1
.\.venv\Scripts\python.exe -m pip install -r requirements.txtSmoke test, który naprawdę ma sens
Bardzo łatwo po starcie serwera pójść w złą stronę i od razu testować zapis albo wykonywanie skryptów. To jest błąd. U nas najrozsądniej działała taka kolejność:
1. get_root()
2. list_dir('.')
3. read_file_text('README.md')
4. stat_path('README.md')Ten prosty smoke test odpowiada na cztery najważniejsze pytania: czy serwer stoi na właściwym katalogu, czy umie listować strukturę, czy odczyt plików działa i czy metadane plików są widoczne. Dopiero później warto przechodzić do zapisu, Pythona i PowerShella.
Status 406 nie musi oznaczać awarii
To detal, który potrafi zmarnować pół dnia. W naszym wdrożeniu endpoint /mcp/ odpowiadał, a przy bezpośrednim wejściu mógł zwracać status 406. I to nie oznaczało, że serwer jest zepsuty.
Wręcz przeciwnie. To był sygnał, że endpoint żyje, ale oczekuje poprawnego żądania MCP. Zanim zaczniesz rozkręcać debugging na poziomie kodu, sprawdź warstwę klienta, nagłówki i sposób wołania protokołu.
Python i PowerShell, ale na krótkiej smyczy
W technicznym semi-agencie najłatwiej przesadzić właśnie tu. Skrót myślowy „skoro już działa, to dajmy pełny shell” prowadzi prosto do kłopotów.
run_python_file powinien uruchamiać tylko lokalny plik .py z obrębu repo. Model nie wykonuje dowolnego kodu przekazanego jako tekst, tylko wybrany plik istniejący w kontrolowanym katalogu.
print("Hello from MAPI connector minimum")run_powershell powinien przyjmować niepusty skrypt, mieć limit czasu i pilnować, żeby workdir siedział w repo. Na start najlepiej używać komend nudnych, ale bezpiecznych:
Get-Location
Get-ChildItem
Test-Path .Gdzie dokładnie przydaje się ngrok
Sam lokalny serwer to za mało, jeśli ChatGPT ma go zobaczyć spoza Twojej maszyny. I właśnie tu wchodzi ngrok. U nas nie był częścią repo ani zależnością z requirements.txt, tylko osobną warstwą infrastrukturalną.
Najpierw sprawdzasz, czy ngrok w ogóle jest zainstalowany i czy konfiguracja przechodzi walidację:
ngrok version
ngrok config checkU nas problem dotyczył konfiguracji związanej z update_channel. Pomogła taka poprawka:
version: "3"
agent.update_channel: stable
agent.update_check: falseJak wystawiliśmy lokalny MCP na zewnątrz
Tunel musi wskazywać na lokalny serwer działający pod http://localhost:8015. Nie tunelujesz „jakiegoś procesu”. Tunelujesz wybrany port, na którym już działa serwer MCP.
Dopiero kiedy lokalny serwer wstaje, port odpowiada, endpoint /mcp/ jest aktywny, a ngrok ma poprawną konfigurację, całość zaczyna mieć sens jako zewnętrznie widoczny connector.
Jak ogarniać warstwy, zamiast debugować wszystko naraz
Największy błąd przy takich integracjach polega na tym, że ludzie patrzą na cały stos jak na jedną rzecz. A to nie jest jedna rzecz. To kilka warstw, które trzeba rozdzielać.
- Środowisko lokalne: Python działa, pip działa, PowerShell działa, .venv daje się aktywować, fastmcp jest zainstalowany.
- Warstwa projektu: są krytyczne pliki, zależności są zainstalowane, python server.py startuje bez tracebacka.
- Warstwa MCP lokalnie: port 8015 odpowiada, endpoint /mcp/ odpowiada, smoke test plikowy przechodzi.
- Warstwa wykonawcza: działa run_python_file i działa run_powershell.
- Warstwa ekspozycji zewnętrznej: ngrok ma poprawną konfigurację, tunel wskazuje na localhost:8015, a klient trafia w prawidłowy endpoint MCP.
Prompty do pierwszych testów w ChatGPT
Kiedy connector jest już widoczny od strony klienta, nie zaczynaj od zadań złożonych. Najpierw każ modelowi zrobić rzeczy kontrolne.
Użyj mojego MCP i wywołaj get_root.
Użyj mojego MCP i pokaż zawartość katalogu głównego przez list_dir('.').
Użyj mojego MCP i odczytaj README.md przez read_file_text.
Znajdź w repo wystąpienia run_powershell przez search_text.
Utwórz plik raport.md, zapisz krótkie podsumowanie i dopisz do niego wynik kolejnego kroku.
Uruchom testowy plik Python z katalogu scripts.
Uruchom bezpieczną komendę PowerShell w katalogu projektu.Najczęstsze problemy
PowerShell blokuje aktywację .venv
Set-ExecutionPolicy -Scope Process -ExecutionPolicy Bypass.Brakuje fastmcp, mimo że serwer go importuje
fastmcp i dopisać go do requirements.txt.Endpoint odpowiada, ale widzisz 406
Ngrok jest zainstalowany, ale konfiguracja jest zła
ngrok config check i popraw konfigurację, zamiast debugować pół internetu naraz.Serwer działa lokalnie, ale klient zewnętrzny go nie widzi
http://localhost:8015, a nie na zły port albo zły proces.Za szybko przechodzisz do komend wykonawczych
Dlaczego ten model działa lepiej niż pełny agent
Bo jest przewidywalny. ChatGPT w tym układzie nie ma magicznych zdolności. Ma kilka narzędzi, jasno ograniczony obszar pracy i prosty zakres odpowiedzialności. Dzięki temu łatwiej go testować, debugować, zabezpieczyć i wdrożyć.
Semi-agent nie jest uboższą wersją agenta. W wielu scenariuszach jest często lepszą wersją narzędzia do pracy.
Podsumowanie
Jeżeli chcesz zrobić z ChatGPT coś na kształt technicznego operatora, nie zaczynaj od pełnej autonomii. Zacznij od dobrze ograniczonego MCP. Daj mu jeden katalog zamiast całego dysku, pliki, Pythona i PowerShella, ale tylko w obrębie repo.
Najpierw sprawdź odczyt. Potem zapis. Na końcu wykonanie procesów. A jeśli chcesz wystawić lokalny serwer na zewnątrz, zrób to świadomie przez ngrok jako osobną warstwę infrastruktury.
U nas właśnie taki układ okazał się najrozsądniejszy: lokalny serwer pod 127.0.0.1:8015/mcp/, smoke test przed cięższymi akcjami, ograniczony zestaw tooli, ręczne dopięcie fastmcp tam, gdzierequirements.txt jeszcze go nie obejmował, i tunel do świata zewnętrznego dopięty dopiero wtedy, gdy lokalne fundamenty były już sprawdzone.
I to jest chyba najlepsza definicja semi-agenta: nie robi wszystkiego, tylko robi to, co trzeba, w granicach, które da się zrozumieć i utrzymać.
Chcesz uporządkować pracę modelu zamiast dawać mu klucze do całej serwerowni?
Jeśli chcesz zbudować kontrolowany workflow z AI, MCP, plikami i bezpiecznym zakresem działania, pokażemy Ci, jak zrobić to technicznie i bez nadmiernych założeń.
Czytaj dalej w sekcji Techniczna
Dlaczego AI potrzebuje pamięci. RAG to za mało, kiedy liczy się ciągłość pracy
Sama wyszukiwarka kontekstu nie wystarcza, gdy AI ma pracować dłużej niż kilka minut. Zobacz, po co asystentowi pamięć, czym różni się od RAG i dlaczego bez niej wiele wdrożeń kończy się operacyjną amnezją.
Automatyzacja wyszukiwania firm i mailingu: architektura, ryzyka i lekcje z prototypu
Jak wygląda prototyp, który wyszukuje firmy, porządkuje dane kontaktowe i przygotowuje mailing bez scrapowania Google Maps i bez automatu wysyłającego wiadomości bez kontroli.