Model Context Protocol (MCP) to otwarty standard komunikacji oparty o JSON-RPC, który umożliwia modelom AI łączenie się z zewnętrznymi narzędziami i danymi przez jednolity interfejs. Wprowadzony przez Anthropic w listopadzie 2024 r., w 2026 r. stał się de facto standardem ekosystemu AI. 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 API, czyli Application Programming Interface, definiuje sposób komunikacji między aplikacjami lub modułami. Tu chodzi o konwencje plików Next.js, które zamieniają eksportowaną funkcję w gotowy plik sitemap.xml lub robots.txt.. 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.
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 REST API to interfejs udostępniający dane przez standardowe metody HTTP (GET, POST...) pod adresami zasobów — w WordPressie domyślnie pod /wp-json/.. Mogą to być treści z firmowego CMS, czyli Content Management System, to system do zarządzania treścią bez ręcznej edycji kodu., 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 SQL to język zapytań używany do pracy z relacyjnymi bazami danych..
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 SEO, czyli Search Engine Optimization, to optymalizacja strony pod widoczność w wynikach wyszukiwania. oraz GEO, czyli Generative Engine Optimization, to optymalizacja treści pod systemy generatywne i wyszukiwarki AI..
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.
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.