to
darmowy, otwarty protokół, dzięki któremu modele językowe (takie jak
Dlaczego to tak ważny krok dla branży? Bo przed MCP podłączanie własnych, biznesowych danych do wielu modeli przypominało niekończącą się mękę. Jeśli miałeś 3 ulubione modele i 5 systemów do integracji, musiałeś utrzymywać kilkanaście różnych konektorów. Dzięki MCP ta matematyka dramatycznie się upraszcza: każdy klient i każdy serwer rozmawia w tym samym, dobrze udokumentowanym języku.
W tym artykule rozłożymy architekturę MCP na czynniki pierwsze. Wspólnie postawimy od zera działający serwer w TypeScript, zintegrujemy go z modelem na Twoim komputerze i przegadamy najlepsze praktyki produkcyjne.
Szybka porada na start: jeśli planujesz wpuścić sztuczną inteligencję w swoje prywatne zbiory danych i pozwolić jej wykonywać akcje w Twoim systemie, zbuduj serwer MCP. Potraktuj go jako cieniutką warstwę „tłumaczącą” przed Twoim głównym . Sięgnij po oficjalny pakiet SDK dla TypeScriptu, w fazie dev podepnij się przez stdio, a bezpieczeństwo zablokuj na kłódkę od pierwszego dnia.
Nie myl jednak MCP z WebMCP, które pojawia się w audycie Przeglądanie Agentowe w Lighthouse. MCP opisuje połączenie modelu z zewnętrznymi narzędziami i danymi przez serwer. WebMCP dotyczy strony internetowej w przeglądarce: formularzy, akcji i narzędzi dostępnych dla agenta podczas korzystania z UI. Nazwy są podobne, ale to różne warstwy architektury.
O co w tym dokładnie chodzi i dlaczego MCP zmienia zasady gry?
Jak już wiesz, MCP to lekki protokół kręcący się wokół JSON-RPC. Ogranicza się on w zasadzie do udostępnienia sztucznej inteligencji trzech kluczowych klocków:
Zasoby (Resources) — to czyste dane do konsumpcji. Pomyśl o tym jak o endpointach z metodą GET w typowym . Mogą to być treści z firmowego , wyciągi z bazy danych, a nawet zwykłe, lokalne pliki tekstowe.
Narzędzia (Tools) — to już funkcje wykonawcze, czyli cyfrowe mięśnie dla naszego modelu. Traktuj je jak strzały z metodami POST/PUT. Przykłady? Wysyłanie e-maili, modyfikacja biletów w Jirze, parsowanie danych wewnątrz potężnego zapytania .
Prompty (Prompts) — zaprogramowane przez Ciebie wzorce zapytań i podpowiedzi dla AI. Czysto pomocnicza struktura dla użytkownika, by model bezbłędnie chwytał kontekst.
Sama architektura składa się z zaledwie trzech warstw:
Host — czyli program z wbudowanym oknem czatu dla modelu AI (np. Claude Desktop, Twoje IDE).
Klient MCP — ukryty mały trybik w hoście, służący do zestawienia połączenia.
Serwer MCP — to właśnie tu kręci się Twoja logika, udostępniająca wszystko na zewnątrz.
Przesył sygnału załatwiasz przez jedną z rurek transportowych:
stdio (standardowe wejście/wyjście) — mistrz prostoty dla środowisk lokalnych.
Streamable HTTP — w pełni wyposażona, zdalna alternatywa gotowa na wdrożenia chmurowe.
Mówiąc obrazowo: o ile REST API nauczyło systemy webowe ze sobą rozmawiać, o tyle MCP stało się ostatecznym tłumaczem pomiędzy czystą sztuczną inteligencją a biznesową resztą świata.
Jak wygląda wsparcie w prawdziwych projektach?
Standard szybko się przyjmuje, ale warto być czujnym — "wspieramy MCP" często jest dość płynnym terminem. Jedna platforma świetnie integruje narzędzia i akcje, podczas gdy inna w ogóle nie ma pojęcia o istnieniu zasobów czy predefiniowanych promptów.
Na czym stoisz w 2026?
Trzy filary MCP to żelazna klasyka (resources, tools, prompts).
Najwygodniej komunikować się po stdio lub nowo zatwierdzonym Streamable HTTP.
Oficjalne pakiety deweloperskie ułożyły się w jasne poziomy: najwyższy dla TS, Pythona czy Go. Umiarkowany dla Javy. Najniższy (póki co) dla Swifta i PHP.
Zanim jednak usiądziesz do klawiatury by tworzyć integrację dla konkretnego hosta:
Odpal jego dokumentację i upewnij się, po jakim transporcie się dogaduje.
Sprawdź, jak sobie radzi z uwierzytelnianiem i limitami narzucanymi na wielkość paczek.
Potwierdź, co ze wsparcia MCP zaimplementowano (tylko akcje, czy cały pakiet).
Piszemy własny serwer MCP w TypeScript (krok po kroku)
Stworzymy sobie razem świetny przypadek testowy. Serwer, który wpuści AI do Twojego bloga zbudowanego na markdownie (MDX). Sprawimy, że model sam przeszuka pliki, skonsumuje tekst, a nawet przygotuje i opublikuje nowy wpis bez Twojej ingerencji!
Rozpoczynamy od zainicjowania prostego obiektu McpServer:
Code
// src/index.tsimport { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js'import { StdioServerTransport } from '@modelcontextprotocol/sdk/server/stdio.js'import { z } from 'zod'import { readdir, readFile, writeFile } from 'fs/promises'import { join } from 'path'// Miejsce, z którego zaciągamy wpisy. Jeśli brak w konfiguracji, użyjemy wartości testowejconst BLOG_DIR = process.env.BLOG_DIR || './content/blog'const server = new McpServer({ name: 'blog-content-server', version: '1.0.0',})
Krok 3: Rejestrujemy zasób dla sztucznej inteligencji
Wystawimy modelowi endpoint typu GET, dzięki któremu wczyta sobie spis naszych artykułów. Robi się to bajecznie łatwo:
Krok 4: Nadajemy modelowi prawdziwą władzę (Narzędzia)
Gdy mamy zasoby do czytania, dajmy modelowi zdolność wyszukiwania postów, a także... pisania nowych.
Code
// Konfigurujemy mechanizm solidnej wyszukiwarkiserver.registerTool( 'search-posts', { title: 'Search posts', description: 'Narzędzie, które pozwala na przeczesanie bazy w poszukiwaniu tagu lub słowa kluczowego', inputSchema: { query: z.string().describe('Słowo, którego szukamy'), searchIn: z .enum(['title', 'tags', 'content', 'all']) .default('all') .describe('Pole poszukiwań'), }, }, async ({ query, searchIn }) => { const files = await readdir(BLOG_DIR) const mdxFiles = files.filter((f) => f.endsWith('.mdx')) const results = [] // Lojalnie iterujemy przez wszystkie pliki for (const file of mdxFiles) { const content = await readFile(join(BLOG_DIR, file), 'utf-8') const frontmatter = parseFrontmatter(content) const queryLower = query.toLowerCase() let match = false if (searchIn === 'all' || searchIn === 'title') { match = match || frontmatter.title?.toLowerCase().includes(queryLower) } if (searchIn === 'all' || searchIn === 'tags') { match = match || frontmatter.tags?.some((t: string) => t.toLowerCase().includes(queryLower), ) } if (searchIn === 'all' || searchIn === 'content') { match = match || content.toLowerCase().includes(queryLower) } if (match) { results.push({ slug: file.replace('.mdx', ''), title: frontmatter.title, date: frontmatter.date, excerpt: frontmatter.description, }) } } return { content: [ { type: 'text' as const, text: results.length > 0 ? JSON.stringify(results, null, 2) : `Niestety, nie mamy wyników dla: "${query}"`, }, ], } },)// Pora wyciągnąć ciężkie działa: pisanie na bloga przez samego agentaserver.registerTool( 'create-post', { title: 'Create post', description: 'Generuje w pełni kompletny artykuł MDX, a potem rzuca go na blog', inputSchema: { slug: z .string() .describe('Zgrabny identyfikator URL np. "ai-w-moim-domu"'), title: z.string().describe('Chwytliwy, czytelny tytuł'), description: z.string().describe('Opis zajawkowy dla SEO'), tags: z.array(z.string()).describe('Worek tagów w postaci małej tablicy'), content: z.string().describe('Esencja artykułu zakodowana w Markdownie'), }, }, async ({ slug, title, description, tags, content }) => { // Szybki trik z backslashem, żeby cudzysłowy nie posypały nam pliku const escape = (value: string) => value.replace(/"/g, '\\"') const frontmatter = [ '---', `title: "${escape(title)}"`, `description: "${escape(description)}"`, `date: "${new Date().toISOString().split('T')[0]}"`, `author: "Maciej Sala"`, `tags: [${tags.map((t) => `"${escape(t)}"`).join(', ')}]`, '---', ].join('\n') const fullContent = `${frontmatter}\n\n${content}` const filePath = join(BLOG_DIR, `${slug}.mdx`) await writeFile(filePath, fullContent, 'utf-8') return { content: [ { type: 'text' as const, text: `Brawo! Twój plik właśnie wylądował tutaj: ${filePath}`, }, ], } },)
Krok 5: Helper do obsługi nagłówków i odpalenie rakiety
Jeszcze szybka implementacja bardzo prostego parsera odczytującego konfigurację i gotowe:
Code
// Wyłuskiwacz naszych nagłówków YAMLfunction parseFrontmatter(content: string): Record<string, any> { const match = content.match(/^---\n([\s\S]*?)\n---/) if (!match) return {} const frontmatter: Record<string, any> = {} const lines = match[1].split('\n') for (const line of lines) { const [key, ...valueParts] = line.split(':') if (key && valueParts.length > 0) { let value = valueParts.join(':').trim() if (value.startsWith('"') && value.endsWith('"')) { value = value.slice(1, -1) } if (value.startsWith('[') && value.endsWith(']')) { try { frontmatter[key.trim()] = JSON.parse(value) } catch { frontmatter[key.trim()] = value } } else { frontmatter[key.trim()] = value } } } return frontmatter}// Spinamy to do kupy po standardowym strumieniu STDIOasync function main() { const transport = new StdioServerTransport() await server.connect(transport) console.error('Gratulacje, Twój blogowy serwer MCP właśnie ożył!')}main().catch(console.error)
Krok 6: Ostatni element układanki z Claude Desktop
Twoja aplikacja w tej chwili świetnie pracuje, ale agent z poziomu pulpitu jeszcze tego nie wie. Zmodyfikuj plik claude_desktop_config.json dodając magiczną formułę:
Restart środowiska – odpal aplikację i zapytaj "hej, zrób mi podsumowanie wszystkich artykułów u mnie na blogu".
Dobre praktyki, o których musisz pamiętać przy deployu
Tarcza antyrakietowa dla systemu, czyli trochę o bezpieczeństwie
Pamiętaj: domyślnie nikt tutaj nikogo nie pyta o legitymację. Przenosząc projekt do sieci internetowej, koniecznie zadbaj o własną politykę rygoru:
Code
// Klucze API podpinamy TYLKO po zmiennych zabezpieczonych z poziomu platformy:const API_KEY = process.env.EXTERNAL_API_KEYif (!API_KEY) { throw new Error('Ciężko odpalić auto bez benzyny. Nie mamy EXTERNAL_API_KEY!')}// Podpięcie weryfikatora uprawnień pod konkretne funkcje destrukcyjne:server.registerTool( 'delete-post', { title: 'Delete post', description: 'Skasowanie posta z poziomu logiki', inputSchema: { slug: z.string() }, annotations: { destructiveHint: true }, // Jasny komunikat ostrzegający }, async ({ slug }, { authInfo }) => { // W środowisku chmurowym obiekt authInfo będzie przepełniony solidną sesją OAuth 2.1 if (authInfo?.extra?.role !== 'admin') { return { content: [ { type: 'text' as const, text: 'Wygląda na to, że nie zjadłeś jeszcze chleba na administratora. Blokada.', }, ], isError: true, // Model rozpozna odrzucenie wywołania po tym fladze } } // Miejsce na magię od kasowania... },)
Nadawaj tylko niezbędne poświadczenia
Nigdy nie przekazuj pełnych dostępów tam, gdzie wystarczą wybiórcze. Uruchamiaj integracje stopniowo. Powiem jeszcze raz, bo to ważne: sztuczna inteligencja będzie w stanie zniszczyć dokładnie te same dane produkcyjne, co Twój lokalnie zapięty backend, o ile zostawisz jej uchyloną bramę.
Rozbijaj komunikację błędów z wdziękiem
Ułatw modelowi podnoszenie się po padzie serwera. Skoro już upadasz, zostaw solidny, przemyślany log dla inteligencji, która próbuje wezwać API:
Przykłady, które zarobią dla Ciebie pieniądze (Next.js)
Wariant A: Niewidzialny zarządzający Headless CMS
Twój serwer jest bramą między AI a serwisami na potrójnym sterydzie jak Sanity, czy Strapi. Agent na Twoje polecenie przeczesze i sprawnie zmieni meta tagi wewnątrz całych kategorii, podmieni linkowania oraz przeplatającą się treść produktową – ty rozmawiasz z terminalem. Panelu administracyjnego praktycznie nie znasz.
Wariant B: AI czytające wykresy za Ciebie (GSC + GA4)
Odpalamy połączenie serwera pod statystyki od wujka Google. Zadajesz szybkie pytanie rano podczas kawy: "Sprawdź z czego wynika drastyczny spadek leadów o 10.00 w czwartek i pokaż mi 4 kroki, jak z tym zawalczyć". Koniec z nużącym zeskrobywaniem danych po tablicach rozdzielczych.
Wariant C: Super zwinny analityk sklepów w E-commerce
Połączone Shopify. Model w tle przeczesuje cenniki, raportuje zrównoważone koszta, oraz sam zajmuje się uzupełnianiem opisów, precyzyjnie wdrażając polityki oraz .
Gdzie MCP ma sens, a gdzie klasyczne API i dlaczego?
Nie wrzucaj MCP wszędzie. To nie jest ostateczny substytut dobrych starych wywołań w architekturze REST czy elastycznych zapytań GraphQL. To rewelacyjny klej – warstwa adaptacyjna stworzona z myślą o modelach LLM.
Buduj integrację z MCP jeżeli:
Udostępniasz swoje rozwiązanie do pracy na wprost dla systemów AI.
Wypuszczasz na rynek spójne narzędzie, które natychmiast ma być kompatybilne z całą flotą dzisiejszych modeli bez dodatkowej zabawy.
Twój zespół buduje bogaty warsztat z inteligentnymi rozwiązaniami i pragnie porządnego ich skatalogowania.
Zostań przy starszym, wypróbowanym API, jeśli:
Komunikują się miedzy sobą wyłącznie skrypty aplikacji lub sprzętu.
Chodzi tu tylko i wyłącznie o brutalną szybkość wyciągania dużej ilości relacyjnych danych.
Nie ma potrzeby integracji z interfejsem tekstowym (konwersacyjnym).
Garść porad odnośnie przyszłości
Budujesz mikroskopijny zasób w architekturze? Myśl z perspektywy czasu od samego wczesnego prototypu:
Model AI i host bazują na wiedzy o tym jak zmieniłeś pole po miesiącu. Korzystaj i pilnuj wersjonowania wprowadzanych innowacji.
Celuj w stan pełnego bezstanu (Statelessness), bo nic nie boli tak przy wdrażaniu load-balancerów i skalowaniu aplikacji jak zwalona, niespójna sieć pamięci kontekstu sesji użytkownika.
Uprawnienia per narzędzie a nie per baza to mus. Utrzymuj z tym ład!
Opisuj dokładnie wszystko. Zarówno schematy Zod, logi wejściowe jak i same tytuły poszczególnych komponentów. Nazwa narzędzia i jego solidny, długi opis robi potężną przysługę systemowi rozpoznawczemu modelu AI!
Bezpieczne automatyzacje procesów i agenci AI w n8n, Make i Claude.
Model Context Protocol to otwarty standard komunikacji oparty o JSON-RPC, który umożliwia modelom AI (Claude, GPT, Gemini) łączenie się z zewnętrznymi narzędziami, bazami danych i usługami za pomocą jednego ustandaryzowanego interfejsu. Pomyśl o nim jak o „USB-C dla AI" — piszesz jeden serwer MCP i nagle każdy kompatybilny klient (jak Claude Desktop, Cursor czy Windsurf) może z niego bez problemu korzystać.
W jakim języku programowania mogę napisać serwer MCP?
Oficjalne pakiety SDK dzielą się na trzy kategorie wsparcia. Tier 1 (najpełniejsze i najszybciej rozwijane) to TypeScript, Python, C# i Go. Tier 2 obejmuje Javę i Rusta, natomiast w Tier 3 znajdziesz Swift, Ruby czy PHP (Kotlin jest na etapie planowania). Jeśli pracujesz z Next.js, naturalnym i najprzyjemniejszym wyborem będzie TypeScript SDK (@modelcontextprotocol/sdk). W praktyce najlepiej napisać serwer w tym samym języku, w którym masz już zbudowaną logikę domenową — niech MCP działa jako cieniutka warstwa nad Twoim istniejącym kodem.
Czy MCP jest w pełni bezpieczny do wdrożeń na produkcji?
Sam MCP nie narzuca żadnych rygorystycznych mechanizmów bezpieczeństwa — ta odpowiedzialność spoczywa na Tobie jako na autorze integracji. Wypuszczając serwer na produkcję, bezwzględnie musisz zadbać o autoryzację i uwierzytelnianie (np. OAuth 2.1 przy transporcie Streamable HTTP), dokładną walidację wejścia (świetnie sprawdza się tu Zod), szczegółowe logi i audyty oraz starą dobrą zasadę minimalnych uprawnień. Pamiętaj: model AI z dostępem do Twojego serwera MCP potrafi dokładnie to samo, na co pozwala Twój serwer. Ani mniej, ani więcej.
Jakie klienty AI wspierają protokół MCP w 2026 roku?
Lista jest naprawdę solidna. Z MCP dogadają się natywnie m.in. Claude Desktop, Claude Code, ChatGPT (Developer Mode oraz nadchodzące Apps SDK), Cursor, Windsurf, Zed, Cline, Continue, Sourcegraph Cody i oczywiście Twoje własne aplikacje agentowe. Warto tylko sprawdzić dokumentację konkretnego hosta, by dowiedzieć się, czy wspiera jedynie narzędzia (tools), czy potrafi też ogarnąć zasoby (resources) i prompty, a także z jakim transportem czuje się najlepiej (stdio czy Streamable HTTP).
Czym to się różni od klasycznego function calling w API OpenAI albo Anthropic?
Klasyczny function calling jest dość mocno związany z konkretnym dostawcą. OpenAI i Anthropic miały do tej pory zupełnie inny schemat opisywania narzędzi. Z MCP problem znika: to protokół w pełni niezależny, co oznacza, że jeden, napisany przez Ciebie serwer bez bólu dogada się z dowolnym modelem. Oprócz akcji (narzędzi), MCP oferuje ustandaryzowany odczyt danych (zasoby) oraz predefiniowane prompty. Zresztą OpenAI od 2025 roku oficjalnie zintegrowało MCP, co ostatecznie udowadnia, że to nie jest już wymysł "tylko od Anthropic".
Czy to przydaje się w działaniach marketingowych lub SEO?
Zdecydowanie tak! MCP świetnie sprawdza się w marketingu. Możesz dzięki niemu podłączyć model AI prosto do statystyk z Google Analytics 4 czy Search Console, by na żywo analizował spadki i wzrosty ruchu. Doskonale radzi sobie z systemami headless CMS (jak Sanity czy Strapi), automatyzuje pobieranie raportów z wielu platform naraz i wspiera generowanie treści bazując na firmowej, zamkniętej bazie wiedzy.
Co wybrać — transport stdio czy Streamable HTTP?
Jeśli Twój serwer MCP i klient AI siedzą na tej samej maszynie (np. odpalasz Claude Desktop lub Cursora lokalnie na komputerze), wybierz stdio. Komunikacja przez standardowe wejście/wyjście będzie najszybsza i najprostsza w konfiguracji. Jeżeli natomiast stawiasz serwer zdalny, z którego ma korzystać wielu użytkowników, albo robisz deploy na Vercela czy Cloudflare Workers, naturalnym krokiem będzie Streamable HTTP, które pozwala wpiąć uwierzytelnianie (np. z OAuth 2.1).
O autorze
Maciej Sala
Maciej Sala — Product Manager i Frontend Developer z bogatym doświadczeniem w marketingu internetowym oraz SEO. Na co dzień pracuje z Reactem, Next.js i TypeScriptem, a ostatnio także z Astro i narzędziami do automatyzacji procesów AI. Sprawnie łączy perspektywę produktową z praktycznym podejściem do kodu. Przez kilka lat był związany z branżą gier wideo jako project manager i game designer. Absolwent historii na Uniwersytecie Jagiellońskim oraz studiów podyplomowych z marketingu internetowego na AGH w Krakowie. Po godzinach trenuje na siłowni, maluje figurki i rozwija własne projekty side-projecty.