MCP toepassen in jullie omgeving?
Leer een koppeling bouwen en testen, met aandacht voor bronrechten en foutafhandeling.
Dennis Claassen
AI-trainer · 35+ teams getraind
Key takeaways
- Je maakt een MCP-server door een functie als tool beschikbaar te stellen, invoer te controleren en een MCP-client te laten verbinden.
- Dit voorbeeld gebruikt Python 3.12 en de officiële MCP Python SDK 2.1.1. De code en lokale tests zijn op 5 september 2026 uitgevoerd.
- De voorbeeldtool berekent werkduur. Je hebt geen API-sleutel, database of AI-abonnement nodig om de server te bouwen en te testen.
- De verbinding met Claude is een aparte stap. Eerst controleer je of de tool werkt; daarna of de AI hem goed gebruikt.
Zelf een MCP-server maken kan met één Python-bestand en een testbestand. In deze handleiding bouw je bereken_werkduur: een tool die het aantal taken vermenigvuldigt met minuten per taak. Vijf taken van twaalf minuten leveren precies zestig minuten op. Zo kun je de hele koppeling controleren met een antwoord dat je vooraf kent.
Het voorbeeld is bewust klein. Het leest geen klantgegevens en verandert geen bestanden. De berekening is een planningshulp, geen gemeten tijdwinst. Wanneer dit werkt, kun je dezelfde opbouw gebruiken voor bijvoorbeeld het opzoeken van een product of het uitlezen van een planning.
Wat is een MCP-server?
Een MCP-server is een programma dat functies of informatie aanbiedt aan een toepassing met een MCP-client. Die toepassing kan de beschikbare functies aan een AI-model doorgeven en een gekozen functie laten uitvoeren. MCP beschrijft hoe de partijen die informatie uitwisselen.
Er zijn drie belangrijke bouwstenen:
| Bouwsteen | Wat bied je aan? | Voorbeeld |
|---|---|---|
| Tool | Een aanroepbare functie met invoer en uitvoer | Bereken werkduur of zoek een order op |
| Resource | Context die een client kan lezen | Een producthandleiding of document |
| Prompt | Een herbruikbaar instructiesjabloon | Een vaste opzet voor een analyse |
Een tool hoeft dus niets te wijzigen: een zoekopdracht of berekening kan ook een tool zijn. Het onderscheid is hoe je de functie of informatie aanbiedt, niet alleen of er iets wordt geschreven. De officiële introductie tot MCP-servers beschrijft deze bouwstenen.
MCP maakt de interface herbruikbaar, maar een client moet wel jouw transport en gebruikte functies ondersteunen. Een lokale server via stdio kun je niet zonder aanpassingen als externe webkoppeling gebruiken.
Stap 1: maak een Python-project met een vaste SDK-versie
Je hebt basiskennis van Python en een terminal nodig. Installeer uv volgens de officiële installatiehandleiding als dat nog ontbreekt. Maak daarna een nieuwe projectmap:
uv init mcp-werkduur --python 3.12
cd mcp-werkduur
uv add "mcp[cli]==2.1.1"
uv beheert de Python-omgeving en legt afhankelijkheden vast. Bewaar pyproject.toml en uv.lock bij je project, zodat je later dezelfde omgeving kunt herstellen.
Dit artikel gebruikt de huidige v2-interface van de officiële Python-SDK, met MCPServer. Oudere voorbeelden gebruiken vaak FastMCP uit SDK v1. Neem imports en testcode daarom uit dezelfde SDK-generatie over. Controleer bij een bestaand project eerst welke versie er is geïnstalleerd. De officiële Python-SDK documenteert het onderscheid tussen v1 en v2.
Werk je vooral met TypeScript? Gebruik dan het officiële TypeScript-SDK-voorbeeld als alternatief. De stappen blijven vergelijkbaar: tool definiëren, transport kiezen, testen en verbinden. Hieronder werken we één Python-route volledig uit.
Stap 2: schrijf een MCP-tool met invoercontrole
Maak in je projectmap een bestand server.py en neem deze code over:
from mcp.server import MCPServer
from mcp.server.mcpserver.exceptions import ToolError
mcp = MCPServer("werkduur")
@mcp.tool()
def bereken_werkduur(aantal_taken: int, minuten_per_taak: int) -> dict[str, int | float]:
"""Bereken geplande werkduur. Dit is geen gemeten tijdwinst."""
if not 0 <= aantal_taken <= 10_000:
raise ToolError("Gebruik 0 tot en met 10.000 taken.")
if not 1 <= minuten_per_taak <= 1_440:
raise ToolError("Gebruik 1 tot en met 1.440 minuten per taak.")
totaal = aantal_taken * minuten_per_taak
return {"minuten": totaal, "uren": round(totaal / 60, 2)}
if __name__ == "__main__":
mcp.run(transport="stdio")
@mcp.tool() maakt de functie beschikbaar als MCP-tool. De parameterbeschrijvingen komen hier uit de namen, Python-types en docstring. Kies dus namen die ook zonder de rest van je code begrijpelijk zijn.
De twee controles leggen grenzen vast voor dit voorbeeld: maximaal 10.000 taken en maximaal 1.440 minuten per taak. Met ToolError geef je een verwachte invoerfout terug aan de client. Dat is geschikter dan een verzonnen uitkomst teruggeven of de server laten stoppen. Zie de SDK-documentatie over foutafhandeling.
stdio betekent dat de client het programma lokaal start en berichten uitwisselt via de standaardinvoer en standaarduitvoer. Zet geen print() in server.py om te debuggen: die uitvoer kan tussen protocolberichten terechtkomen. Gebruik voor serverlogs logging naar stderr, zoals de MCP-documentatie over logging voorschrijft.
Stap 3: test de server zonder AI-model
Maak naast server.py een tweede bestand, check.py:
import asyncio
from mcp import Client
from server import mcp
async def main():
async with Client(mcp) as client:
tools = await client.list_tools()
assert any(tool.name == "bereken_werkduur" for tool in tools.tools)
result = await client.call_tool(
"bereken_werkduur", {"aantal_taken": 5, "minuten_per_taak": 12}
)
assert not result.is_error
assert result.structured_content == {"minuten": 60, "uren": 1.0}
fout = await client.call_tool(
"bereken_werkduur", {"aantal_taken": -1, "minuten_per_taak": 12}
)
assert fout.is_error
print("OK: tool gevonden, 60 minuten berekend, ongeldige invoer geweigerd.")
asyncio.run(main())
Voer het testbestand uit:
uv run check.py
Als alles werkt, eindigt de uitvoer met:
OK: tool gevonden, 60 minuten berekend, ongeldige invoer geweigerd.
Je kunt daarvoor een logregel over de ongeldige invoer zien. Die is hier verwacht: de test probeert expres een negatief aantal taken. De print() in dit aparte testprogramma is wel in orde; dit bestand verzorgt geen stdio-serververbinding.
Deze controle gebruikt de ingebouwde client van de Python-SDK. Hij controleert drie dingen: de tool is vindbaar, geldige invoer geeft de juiste gestructureerde uitvoer en ongeldige invoer levert een fout op.
Wat is daadwerkelijk gecontroleerd? Op 5 september 2026 zijn bovenstaande bestanden lokaal uitgevoerd met Python 3.12.12 en mcp 2.1.1. Daarnaast is dezelfde server als apart proces via stdio getest: één geldige berekening en drie ongeldige invoercombinaties slaagden voor de verwachte controles. Er waren geen externe API-aanroepen nodig. Dat bewijst de werking van dit voorbeeld, niet de werking van een toekomstige databasekoppeling of de keuzes van een AI-model.
Optioneel: inspecteer de tool met een visuele client
Met de MCP Inspector kun je beschikbare tools bekijken en zelf argumenten invoeren. Selecteer stdio, gebruik uv als opdracht en geef --directory, het absolute pad naar je project, run en server.py als argumenten op.
Volg voor de installatie de actuele Inspector-documentatie. De Python-test hierboven blijft een zelfstandige controle: je hoeft geen Node.js of Inspector te installeren om de berekening en foutafhandeling te testen.
Stap 4: koppel je server aan Claude Desktop
Werkt check.py? Dan kun je de server in Claude Desktop registreren. De desktopapp start straks zelf het serverproces; je hoeft server.py niet in een losse terminal te laten draaien.
Open claude_desktop_config.json. Volgens de officiële configuratiehandleiding staat het bestand hier:
| Systeem | Configuratiebestand |
|---|---|
| macOS | ~/Library/Application Support/Claude/claude_desktop_config.json |
| Windows | %APPDATA%\Claude\claude_desktop_config.json |
| Linux | ~/.config/Claude/claude_desktop_config.json |
Voeg werkduur toe onder mcpServers. Als je al servers hebt ingesteld, voeg je alleen deze nieuwe entry toe aan dat bestaande object.
{
"mcpServers": {
"werkduur": {
"command": "uv",
"args": [
"--directory",
"/absoluut/pad/naar/mcp-werkduur",
"run",
"server.py"
]
}
}
}
Vervang het voorbeeldpad door jouw echte projectmap. Op Windows kun je bijvoorbeeld C:/Users/jij/projecten/mcp-werkduur gebruiken. Kan de app uv niet vinden, vervang dan ook "uv" door het volledige pad naar het programma. Je vindt dat met command -v uv op macOS/Linux of where.exe uv op Windows.
Sla de configuratie op en sluit Claude Desktop volledig af. Open de app opnieuw en controleer of de server en zijn tool zichtbaar zijn. Vraag daarna:
Gebruik de tool bereken_werkduur met aantal_taken=5 en minuten_per_taak=12.
Noem de minuten en uren uit het toolresultaat.
Controleer de daadwerkelijke toolaanroep en de gebruikte argumenten. Alleen een correct tekstueel antwoord is onvoldoende: de AI kan vijf keer twaalf ook zonder jouw server uitrekenen.
Gebruik je Claude Code? Die heeft een eigen MCP-configuratie. Volg daarvoor Anthropics instructies voor lokale stdio-servers. Neem de Desktop-configuratie niet automatisch over naar een ander product.
Stap 5: los verbindingsproblemen gericht op
| Wat zie je? | Wat controleer je eerst? |
|---|---|
ModuleNotFoundError: mcp | Start met uv run check.py vanuit de projectmap, zodat de juiste omgeving wordt gebruikt. |
Een import met FastMCP of MCPServer werkt niet | Controleer de geïnstalleerde SDK-versie en meng geen v1- en v2-voorbeelden. |
| De server start, maar er gebeurt niets in de terminal | Een stdio-server wacht op een MCP-client. Gebruik het testbestand of verbind een client. |
| Claude toont geen tool | Controleer JSON, absolute paden, het uv-pad en of je de app volledig hebt herstart. |
| De verbinding verbreekt na een logregel | Zoek naar uitvoer via print() of andere berichten op stdout in je server. |
| Claude geeft antwoord zonder toolaanroep | Vraag expliciet om de tool en controleer of die in de sessie beschikbaar is. |
Verander steeds één onderdeel. Als de lokale test werkt en Desktop niet verbindt, zit het probleem waarschijnlijk bij het starten of configureren van de verbinding. Herschrijf dan niet meteen je berekening.
Van oefenserver naar een koppeling voor je bedrijf
Kies voor de volgende stap één afgebakende functie. Bijvoorbeeld zoek_product(productcode) die één product uit een testcatalogus teruggeeft. Beschrijf vooraf welke velden mogen terugkomen en wat er gebeurt als de productcode ontbreekt.
Zodra je echte systemen toevoegt, krijgt de server ook echte bevoegdheden. Beperk die tot wat de functie nodig heeft. Gebruik voor een opzoektool alleen leestoegang, houd sleutels uit de broncode en stel grenzen aan invoer en responstijd. Laat een schrijvende functie eerst op testgegevens werken en leg vast waar toestemming wordt gecontroleerd. De officiële MCP-beveiligingsrichtlijnen behandelen de aanvullende eisen voor lokale en externe servers.
Een lokaal proces is bovendien nog geen gedeelde dienst voor je team. Voor externe toegang heb je onder meer passend transport, authenticatie en beheer nodig. De keuze daarvoor volgt uit wie de tool gebruikt en welke gegevens hij kan bereiken.
Wil je de koppeling met je eigen systemen leren bouwen? Bekijk de MCP Protocol-training. Daar sluit deze oefening op aan: van een losse functie naar tools voor API's, bestanden en bedrijfsdata. Wil je eerst bestaande koppelingen gebruiken, begin dan bij onze gids over MCP in Claude.
Veelgestelde vragen
Wat is een MCP-server in gewone taal?
Een MCP-server is een programma dat functies of informatie beschikbaar stelt aan een toepassing met een MCP-client. Je kunt tools, leesbare resources en herbruikbare prompts aanbieden. De client moet het transport en de gebruikte functies ondersteunen: een lokale stdio-server is bijvoorbeeld niet automatisch een externe webkoppeling.
Heb je Python of TypeScript nodig voor een MCP-server?
Beide hebben een officiële SDK. Dit artikel werkt één Python-voorbeeld volledig uit met Python 3.12 en MCP SDK 2.1.1. Het gebruikt MCPServer uit SDK v2. Oudere SDK v1-voorbeelden gebruiken andere imports, zoals FastMCP. Kies de taal van je bestaande project en combineer code uit dezelfde SDK-generatie.
Heb ik een API-sleutel nodig om deze MCP-server te testen?
Nee. De voorbeeldtool berekent alleen aantal taken maal minuten per taak. Het testbestand gebruikt de ingebouwde Python-client om de beschikbare tool, de berekening en ongeldige invoer te controleren. Dat werkt lokaal zonder AI-model of externe API. Gebruik met een AI-toepassing is een afzonderlijke stap met de voorwaarden van die toepassing.
Hoe registreer ik mijn MCP-server in Claude Desktop?
Voeg de server toe onder mcpServers in claude_desktop_config.json. Gebruik uv als opdracht, met --directory, het absolute projectpad, run en server.py als argumenten. Als de app uv niet vindt, gebruik je ook daarvoor het volledige pad. Bewaar bestaande serverinstellingen en herstart de app volledig. Controleer vervolgens de echte toolaanroep, niet alleen het antwoord van Claude.
Hoe voeg ik een MCP-server toe aan Claude Code?
Met één commando in de terminal: claude mcp add --transport stdio <naam> -- <commando om je server te starten>. Alles na de -- geeft Claude Code ongewijzigd door aan je server. Dat werkt hetzelfde op macOS, Windows en Linux, dus dit is de kortste route als de Desktop-app niet beschikbaar is. Controleren doe je met claude mcp list of, binnen een sessie, met /mcp.
Hoe weet ik of mijn MCP-server goed werkt?
Controleer eerst of de tool wordt gevonden, of bekende invoer de verwachte uitvoer geeft en of ongeldige invoer wordt geweigerd. Test daarna de verbinding met je gekozen client en controleer de gebruikte argumenten. Het artikel bevat hiervoor een lokaal uitgevoerd testbestand. De MCP Inspector kan aanvullend helpen om tools en hun invoer visueel te onderzoeken.




