Uvod
Ruku na srce — ako ste ikada gradili AI agenta koji treba pristupiti bazi podataka, pretražiti web ili poslati e-mail, znate koliko je to bilo bolno. Prije godinu dana, svaka integracija značila je zaseban kod: različiti API formati, različita autentifikacija, različito rukovanje pogreškama. Svaki novi alat gutao je dane rada. A onda to pomnožite s brojem LLM-ova koje želite podržati i dobijete pravu noćnu moru.
Model Context Protocol (MCP) mijenja tu paradigmu iz temelja.
Zamislite ga kao USB-C priključak za AI — univerzalni standard koji omogućuje bilo kojem AI modelu da se poveže s bilo kojim vanjskim alatom kroz jedan standardizirani protokol. Umjesto N×M integracija (N modela × M alata), dobivate N+M: svaki model implementira MCP klijent, svaki alat implementira MCP server, i sve jednostavno radi. Bez posebnog ljepila između.
U prethodnim člancima pokazali smo kako orkestrirati višeagentne sustave, graditi produkcijske RAG cjevovode i primijeniti napredne tehnike promptiranja. MCP je zapravo ono što sve te komponente povezuje u praksi — protokol koji vašim agentima daje ruke i oči za interakciju sa stvarnim svijetom.
U ovom vodiču proći ćemo kroz cijeli proces: od MCP arhitekture, preko izgradnje funkcionalnog servera u Pythonu s FastMCP-om, do sigurnosnih praksi za produkciju. Svaki korak popraćen je radnim kodom koji možete odmah primijeniti.
Što je Model Context Protocol i zašto je važan
Model Context Protocol (MCP) je otvoreni standard koji je Anthropic predstavio u studenom 2024. U 2026. prerastao je u de facto industrijski standard za povezivanje AI sustava s vanjskim alatima i izvorima podataka. Protokol je danas u vlasništvu Linux Foundationa i otvoren za doprinose cijele zajednice.
Ono što MCP čini posebnim nije samo standardizacija — već brzina usvajanja. OpenAI ga je usvojio uz istodobnu najavu postupnog ukidanja svog Assistants API-ja (planirano za sredinu 2026.), Google DeepMind ga je integrirao, a danas postoji više od 500 javno dostupnih MCP servera koji pokrivaju baze podataka, sustave za pohranu datoteka, web scraping i razne API-je. Impresivno, zar ne?
Problem koji MCP rješava
Tradicionalni pristup bio je, najblaže rečeno, kaotičan. Za svaki API pisala se zasebna integracija, svaki pružatelj modela imao je svoj format za pozive alata, a promjena modela značila je prepisivanje svega ispočetka. MCP to eliminira uvođenjem:
- Standardiziranog komunikacijskog protokola temeljenog na JSON-RPC 2.0
- Jasno definiranih primitiva — alata (tools), resursa (resources) i promptova (prompts)
- Klijent-server arhitekture koja razdvaja logiku modela od logike integracije
- Ugrađene sigurnosti s OAuth 2.1 autentifikacijom za HTTP transport
Arhitektura MCP-a: host, klijent i server
MCP arhitektura ima tri ključne komponente:
- MCP Host — runtime okruženje koje pokreće AI aplikaciju (npr. Claude Desktop, IDE s MCP podrškom ili vaša vlastita aplikacija). Host upravlja komunikacijom između klijenta i servera.
- MCP klijent — komponenta unutar hosta koja prevodi zahtjeve LLM-a u MCP format i odgovore servera natrag u format koji model razumije. Klijent otkriva i koristi dostupne MCP servere.
- MCP server — vanjski servis koji pruža kontekst, podatke ili funkcionalnosti LLM-u. Izlaže alate, resurse i predloške promptova kroz standardizirani protokol.
U praksi tok izgleda ovako: korisnik postavi pitanje → LLM prepozna da treba vanjski alat → MCP klijent pošalje zahtjev serveru → server izvrši akciju (recimo SQL upit) → rezultat se vrati LLM-u → LLM formulira odgovor. Jednostavno i čisto.
Tri temeljna primitiva MCP-a
MCP serveri mogu izložiti tri vrste mogućnosti. Svaka ima svoju jasnu svrhu, pa ih vrijedi razumjeti prije nego što krenemo kodirati.
Alati (Tools) — izvršavanje akcija
Alati su funkcije koje LLM može pozvati za izvršavanje akcija u vanjskom svijetu. Svaki alat ima ime, opis, JSON Schema za argumente i predvidljivi format izlaza. Možete ih zamisliti kao ekvivalent POST endpointova u REST API-ju — proizvode sporedne efekte (pišu u bazu, šalju e-mail, kreiraju datoteku).
Resursi (Resources) — čitanje podataka
Resursi pružaju pristup podacima samo za čitanje. Model ih koristi za učitavanje konteksta — sadržaja datoteka, rezultata API poziva, stanja baze. Ekvivalent su GET endpointova: dohvaćaju podatke bez modificiranja stanja sustava.
Promptovi (Prompts) — predlošci interakcije
Promptovi su unaprijed definirani predlošci koji vode korisnike i modele kroz specifične radne tijekove. Pomažu u strukturiranju interakcije za učinkovitije korištenje alata i resursa. Iskreno, ovo je primitiv koji se u praksi najmanje koristi, ali kad vam zatreba — nezamjenjiv je.
Praktična implementacija: izgradnja MCP servera s FastMCP-om
Ajmo na kodiranje.
FastMCP je Python okvir koji dramatično pojednostavljuje izgradnju MCP servera. Trenutna stabilna verzija je FastMCP 3.0 koja donosi provider/transform arhitekturu, konkurentno izvršavanje alata i CLI alate za upravljanje serverima. Zanimljiv podatak: FastMCP pokreće 70% svih MCP servera u ekosustavu.
Korak 1: Instalacija i postavljanje projekta
# Kreiranje virtualnog okruženja
python -m venv mcp-env
source mcp-env/bin/activate
# Instalacija FastMCP
pip install "fastmcp>=3.0"
# Za integraciju s bazom podataka
pip install aiosqlite
Korak 2: Osnovni MCP server s alatima i resursima
Izgradimo praktični MCP server za upravljanje zadacima koji demonstrira sve tri primitiva:
from mcp.server.fastmcp import FastMCP
from datetime import datetime
# Inicijalizacija MCP servera
mcp = FastMCP("Upravitelj zadataka", json_response=True)
# Simulirana baza podataka
zadaci: dict[int, dict] = {}
sljedeci_id = 1
@mcp.tool()
def kreiraj_zadatak(naslov: str, opis: str, prioritet: str = "srednji") -> dict:
"""Kreira novi zadatak s naslovom, opisom i prioritetom.
Prioritet može biti: niski, srednji, visoki, kritični.
"""
global sljedeci_id
zadatak = {
"id": sljedeci_id,
"naslov": naslov,
"opis": opis,
"prioritet": prioritet,
"status": "otvoreno",
"kreirano": datetime.now().isoformat()
}
zadaci[sljedeci_id] = zadatak
sljedeci_id += 1
return zadatak
@mcp.tool()
def zavrsi_zadatak(zadatak_id: int) -> dict:
"""Označava zadatak kao završen prema ID-u."""
if zadatak_id not in zadaci:
return {"greska": f"Zadatak {zadatak_id} ne postoji"}
zadaci[zadatak_id]["status"] = "zavrseno"
return zadaci[zadatak_id]
@mcp.resource("zadaci://lista")
def lista_zadataka() -> str:
"""Dohvaća listu svih zadataka."""
if not zadaci:
return "Nema aktivnih zadataka."
redovi = []
for z in zadaci.values():
redovi.append(
f"[{z['id']}] {z['naslov']} "
f"(prioritet: {z['prioritet']}, status: {z['status']})"
)
return "\n".join(redovi)
@mcp.resource("zadaci://{zadatak_id}")
def detalji_zadatka(zadatak_id: int) -> str:
"""Dohvaća detalje specifičnog zadatka."""
if zadatak_id not in zadaci:
return f"Zadatak {zadatak_id} ne postoji."
z = zadaci[zadatak_id]
return (
f"Naslov: {z['naslov']}\n"
f"Opis: {z['opis']}\n"
f"Prioritet: {z['prioritet']}\n"
f"Status: {z['status']}\n"
f"Kreirano: {z['kreirano']}"
)
@mcp.prompt()
def planiranje_sprinta(broj_zadataka: int = 5) -> str:
"""Generira prompt za planiranje sprinta."""
return (
f"Pregledaj listu aktivnih zadataka i predloži plan sprinta "
f"s maksimalno {broj_zadataka} zadataka. Prioritiziraj prema "
f"hitnosti i međuovisnostima. Za svaki zadatak navedi procijenjeno "
f"vrijeme i obrazloženje prioriteta."
)
if __name__ == "__main__":
mcp.run(transport="stdio")
Korak 3: Napredniji primjer — MCP server s bazom podataka
Za produkcijske scenarije, zadaci se naravno pohranjuju u stvarnu bazu podataka. Evo primjera s SQLite-om i asinkronim pristupom:
from mcp.server.fastmcp import FastMCP
from contextlib import asynccontextmanager
import aiosqlite
import json
DB_PATH = "zadaci.db"
@asynccontextmanager
async def zivotni_ciklus(server):
"""Inicijalizira bazu podataka pri pokretanju servera."""
async with aiosqlite.connect(DB_PATH) as db:
await db.execute("""
CREATE TABLE IF NOT EXISTS zadaci (
id INTEGER PRIMARY KEY AUTOINCREMENT,
naslov TEXT NOT NULL,
opis TEXT,
prioritet TEXT DEFAULT 'srednji',
status TEXT DEFAULT 'otvoreno',
kreirano TIMESTAMP DEFAULT CURRENT_TIMESTAMP
)
""")
await db.commit()
yield
mcp = FastMCP(
"Produkcijski upravitelj zadataka",
lifespan=zivotni_ciklus
)
@mcp.tool()
async def dodaj_zadatak(naslov: str, opis: str = "", prioritet: str = "srednji") -> dict:
"""Dodaje novi zadatak u bazu podataka."""
async with aiosqlite.connect(DB_PATH) as db:
cursor = await db.execute(
"INSERT INTO zadaci (naslov, opis, prioritet) VALUES (?, ?, ?)",
(naslov, opis, prioritet)
)
await db.commit()
return {"id": cursor.lastrowid, "naslov": naslov, "status": "kreirano"}
@mcp.tool()
async def pretrazi_zadatke(upit: str, status: str = "") -> list[dict]:
"""Pretražuje zadatke po ključnim riječima i opcionalnom statusu."""
async with aiosqlite.connect(DB_PATH) as db:
db.row_factory = aiosqlite.Row
if status:
rows = await db.execute_fetchall(
"SELECT * FROM zadaci WHERE naslov LIKE ? AND status = ?",
(f"%{upit}%", status)
)
else:
rows = await db.execute_fetchall(
"SELECT * FROM zadaci WHERE naslov LIKE ?",
(f"%{upit}%",)
)
return [dict(r) for r in rows]
if __name__ == "__main__":
mcp.run(transport="streamable-http")
Transportni slojevi: stdio vs. HTTP
MCP podržava dva glavna transportna mehanizma. Koji ćete odabrati ovisi o tome gdje i kako pokrećete server.
stdio — za lokalne integracije
Standard input/output (stdio) koristi se kada MCP server radi lokalno na istom stroju kao i host. Komunikacija ide kroz stdin/stdout kanale, što je brzo i jednostavno za postavljanje. Idealan izbor za razvoj, testiranje i lokalne alate poput Claude Desktop integracije.
Jedna kritična napomena: kod stdio transporta nikada ne pišite na stdout. Svaki ispis na standardni izlaz korumpira JSON-RPC poruke i lomi komunikaciju. Ovo je greška koja se teško debugira jer server naizgled radi, ali poruke dolaze iskrivljene. Koristite stderr ili dedicirane sustave za logiranje.
Streamable HTTP — za produkciju i udaljeni pristup
Streamable HTTP (nasljednik ranijeg SSE transporta) koristi se za produkcijske implementacije. Pruža bolju skalabilnost, podržava više istodobnih klijenata i omogućuje postavljanje iza load balancera.
# Lokalno pokretanje (stdio)
if __name__ == "__main__":
mcp.run(transport="stdio")
# Produkcijsko pokretanje (HTTP)
if __name__ == "__main__":
mcp.run(transport="streamable-http", host="0.0.0.0", port=8080)
Povezivanje MCP servera s Claude Desktopom
Da biste testirali svoj MCP server s Claude Desktopom, trebate urediti konfiguracijsku datoteku claude_desktop_config.json:
{
"mcpServers": {
"upravitelj-zadataka": {
"command": "python",
"args": ["/putanja/do/vaseg/server.py"],
"env": {
"DB_PATH": "/putanja/do/baze/zadaci.db"
}
}
}
}
Nakon spremanja konfiguracije i ponovnog pokretanja Claude Desktopa, vaši alati pojavit će se u sučelju. Claude automatski prepoznaje dostupne alate i koristi ih kada je to relevantno za korisnikov upit.
Za brže postavljanje, FastMCP 3.0 nudi i CLI naredbu koja sve obavi umjesto vas:
# Automatska registracija s Claude Desktop, Cursor ili Goose
fastmcp install server.py --name "Upravitelj zadataka"
Testiranje i debugiranje
Ovo je dio koji mnogi preskoče, ali je izuzetno važan.
MCP ekosustav pruža MCP Inspector — vizualni alat za testiranje servera bez potrebe za AI modelom. Pokrećete ga jednom naredbom:
# Pokretanje inspektora za vaš server
npx @modelcontextprotocol/inspector python server.py
Inspector otvara web sučelje na kojem možete pregledati sve registrirane alate, resurse i promptove, slati testne pozive i provjeravati odgovore. FastMCP 3.0 dodatno nudi korisne CLI alate:
# Pregled svih alata na serveru
fastmcp list tools server.py
# Poziv specifičnog alata
fastmcp call server.py kreiraj_zadatak --naslov "Test" --opis "Testni zadatak"
# Otkrivanje svih konfiguriranih servera u vašem editoru
fastmcp discover
Sigurnosne prakse za produkcijsku implementaciju
Prema OWASP vodiču za sigurnu MCP implementaciju iz veljače 2026., MCP serveri zahtijevaju ozbiljnu pozornost na sigurnost. Rade s delegiranim korisničkim dozvolama i dinamičkim pozivima alata, što ih čini potencijalnom metom za napade. Evo na što treba paziti.
Autentifikacija i autorizacija
Za HTTP transport, MCP specifikacija standardizira OAuth 2.1 s PKCE-om. Izbjegavajte statičke API ključeve u produkciji — teško ih je rotirati i nadzirati. Umjesto toga:
- Koristite OAuth 2.0/OIDC s enterprise identity providerima (Okta, Azure AD, Auth0)
- Implementirajte DPoP ili mTLS binding za sprečavanje krađe tokena
- Primijenite princip najmanje privilegije — svaki server ima pristup samo onome što mu je stvarno nužno
Validacija ulaza i zaštita od injection napada
MCP serveri izloženi su specifičnim prijetnjama poput prompt injection, tool poisoning i SSRF napada. Svaki ulaz mora se validirati bez iznimke:
import re
@mcp.tool()
async def pretrazi_bazu(upit: str) -> list[dict]:
"""Pretražuje bazu podataka s validacijom ulaza."""
# Ograničenje duljine upita
if len(upit) > 200:
return [{"greska": "Upit je predugačak (max 200 znakova)"}]
# Korištenje parametriziranih upita — NIKADA string interpolacije
async with aiosqlite.connect(DB_PATH) as db:
rows = await db.execute_fetchall(
"SELECT * FROM zadaci WHERE naslov LIKE ? LIMIT 50",
(f"%{upit}%",)
)
return [dict(r) for r in rows]
Izolacija servera i mrežna sigurnost
Svaki MCP server trebao bi imati jednu jasno definiranu svrhu. Izbjegavajte monolitne servere koji istodobno pristupaju bazama podataka, datotečnim sustavima i vanjskim API-jima — to je recept za katastrofu. Koristite mrežnu segmentaciju, rate limiting i WAF za zaštitu HTTP endpointova.
MCP u 2026: ekosustav i budućnost
MCP ekosustav raste nevjerojatnom brzinom. Evo što ga definira u ovom trenutku:
- Preko 500 javno dostupnih servera za baze podataka, sustave za pohranu, web scraping i razne API-je
- FastMCP pokreće 70% svih servera s više od milijun dnevnih preuzimanja
- Podrška svih velikih igrača — Anthropic, OpenAI, Google i Microsoft imaju nativnu MCP integraciju
- Kubernetes Gateway API Inference Extension za model-aware usmjeravanje MCP prometa u klasterima
Sljedeći veliki korak na MCP cestovnoj karti je agent-to-agent komunikacija. Zamislite scenarij u kojem „Putni agent" MCP server autonomno pregovara s „Booking agent" MCP serverom oko rezervacije leta. To otvara vrata rekurzivnim agentičkim sustavima u kojima se složeni zadaci dekompoziraju na podzadatke koje obrađuju specijalizirani podagenti — svi koordinirani putem MCP-a. Zvuči kao znanstvena fantastika, ali infrastruktura je već tu.
Često postavljana pitanja
Koja je razlika između MCP-a i tradicionalnog function callinga?
Function calling specifičan je za svakog pružatelja — OpenAI, Anthropic i Google svaki imaju svoj format. MCP je univerzalni standard koji radi s bilo kojim modelom. Jednom kad napišete MCP server, on radi sa svim MCP-kompatibilnim klijentima bez promjena koda. Dodatna prednost: MCP nudi tri primitiva (alate, resurse i promptove) dok function calling obično podržava samo alate.
Mogu li koristiti MCP s OpenAI modelima ili samo s Claudeom?
MCP radi sa svim velikim pružateljima modela. OpenAI je službeno usvojio MCP i integrirao ga u svoj Agents SDK. Google DeepMind, Microsoft i mnogi drugi također podržavaju protokol. Upravo ta univerzalnost čini MCP posebno vrijednim — niste zaključani uz jednog vendora.
Koliko je teško migrirati postojeće integracije na MCP?
Lakše nego što biste očekivali. Vaša postojeća Python funkcija koja poziva API postaje MCP alat dodavanjem @mcp.tool() dekoratora. FastMCP automatski generira JSON Schema iz type hintova i docstringova. Za većinu integracija, migracija se svodi na omatanje postojeće logike u MCP server — bez prepisivanja poslovne logike.
Je li MCP siguran za produkcijsku upotrebu s osjetljivim podacima?
Da, uz pravilnu implementaciju. MCP specifikacija standardizira OAuth 2.1 za HTTP transport, podržava mTLS i prati princip najmanje privilegije. OWASP je u veljači 2026. objavio dedicirani vodič za sigurnu MCP implementaciju. Ključno je: validirajte sve ulaze, koristite parametrizirane upite, implementirajte rate limiting i vodite revizijske logove svih poziva alata.
Kako se MCP odnosi prema EU AI Actu?
MCP pomaže u usklađivanju s regulatornim zahtjevima jer pruža strukturirani revizijski trag svih interakcija između modela i vanjskih sustava. Svaki poziv alata je praćen i dokumentiran, što olakšava transparentnost u donošenju odluka AI sustava — jedan od ključnih zahtjeva EU AI Acta. Kombinacijom MCP-a s alatima za opservabilnost poput Langfuse dobivate potpuni audit trail.