11 KiB
Les 15 — MCP (Model Context Protocol)
Slide Overzicht (Klas A — 3 uur fysiek, demo + hands-on)
Lesvorm: ±1 uur theorie + live demos (veel koppelen, weinig zelf coderen), daarna ±1,5 uur hands-on Demo-MCPs: GitHub MCP, Supabase MCP, Vercel MCP (bestaand) + Polderfest MCP (eigen) Vervolg op: Les 13 — Agents (Polderfest agent met 5 tools) Aansluit op: Les 16 — RAG + Embeddings
Blok-structuur
| Blok | Onderwerp | Slides |
|---|---|---|
| 1 | Welkom + Vandaag | 1–2 |
| 2 | Wat is MCP + ecosysteem | 3–6 |
| 3 | Vier MCPs koppelen — live | 7–10 |
| 4 | Polderfest MCP — eigen server | 11–13 |
| 5 | LIVE — De drie chats workflow | 14–17 |
| 6 | Lesopdracht + Extra + Vooruitblik | 18–20 |
Slide 1: Title
Les 15 — MCP
Visual:
- Background: CREAM
- "Les 15" in BLUE
- "Model Context Protocol" in BLACK
- Subtitle: "Geef AI-clients superkrachten via standard-tools"
- Iconen: GitHub + Supabase + Vercel + Polderfest
Slide 2: Vandaag
Drie blokken + climax
Wat we vandaag doen:
- Theorie — wat is MCP, waarom bestaat het (kort)
- Vier MCPs koppelen — GitHub, Supabase, Vercel, Polderfest
- De drie chats workflow — alles samen aan het werk
Climax (in drie chats):
- Chat 1: GitHub MCP maakt repo + voegt remote toe
- Chat 2: Polderfest features bouwen via Cursor + Supabase MCP
- Chat 3: Vercel MCP project + deploy
Vandaag is dus meer koppelen en zien dan zelf coderen.
Slide 3: Wat is MCP
Eén standaard, vele clients
Model Context Protocol legt vast:
- Hoe AI-clients verbinding maken met tools en data
- Hoe servers tools, resources en prompts beschrijven
- Hoe data heen-en-weer stroomt over een transport
Open spec — geen vendor lock-in:
- Gestart door Anthropic (november 2024)
- Cursor, Claude Desktop, OpenAI, Windsurf, Zed ondersteunen het
Analogie: USB-C voor AI. Eén stekker, elke laptop.
Slide 4: Het probleem
Voor MCP
| Voor MCP | Met MCP |
|---|---|
| Cursor: extension API | Eén MCP-server |
| Claude Desktop: plugins | Cursor: werkt |
| ChatGPT: GPTs/Actions | Claude Desktop: werkt |
| Windsurf: eigen API | ChatGPT: werkt |
| Zed: eigen API | Windsurf: werkt |
| = 5 integraties | = 1 integratie |
Dezelfde tool, één keer bouwen, overal beschikbaar.
Slide 5: Architectuur + primitives
MCP in één plaatje
Drie rollen:
| Rol | Voorbeeld |
|---|---|
| Host | Cursor, Claude Desktop |
| Client | MCP library (zit in host) |
| Server | GitHub MCP, jouw Polderfest |
Drie primitives:
| Primitive | Wat |
|---|---|
| Tools | functies (AI doet iets) |
| Resources | read-only data |
| Prompts | templates / persona's |
Vandaag focus op tools.
Slide 6: Het MCP-ecosysteem
Honderden servers beschikbaar
Top servers:
| Server | Wat je krijgt |
|---|---|
| GitHub | issues, PRs, repos, commits |
| Supabase | DB queries, schema, migrations |
| Vercel | projects aanmaken, deploys |
| Filesystem | lees/schrijf in folders |
| Slack / Linear / Jira | werk-tickets |
| Brave Search / Notion / Postgres | enz. |
Vandaag koppelen we vier in Cursor: GitHub, Supabase, Vercel — en onze eigen Polderfest.
Slide 7: Vier MCPs vandaag
Het overzicht
| MCP | Type | Auth |
|---|---|---|
| GitHub | HTTP (remote) | Bearer (PAT) |
| Supabase | HTTP (remote) | Bearer (sbp_-token) |
| Vercel | HTTP (remote) | OAuth (browser-flow) |
| Polderfest | HTTP (lokaal) | geen (jouw eigen server) |
Alle vier in één mcp.json — zelfde patroon, andere URLs.
Visual: vier logo's met een pijl naar Cursor.
Slide 8: De mcp.json config
~/.cursor/mcp.json — globaal
{
"mcpServers": {
"supabase": {
"type": "http",
"url": "https://mcp.supabase.com/mcp?project_ref=<jouw-ref>&read_only=true",
"headers": { "Authorization": "Bearer sbp_..." }
},
"github": {
"type": "http",
"url": "https://api.githubcopilot.com/mcp/",
"headers": { "Authorization": "Bearer ghp_..." }
},
"vercel": {
"type": "http",
"url": "https://mcp.vercel.com"
},
"polderfest": {
"type": "http",
"url": "http://localhost:3000/api/mcp"
}
}
}
Eén patroon: type: http + url + optioneel headers. Vercel doet OAuth.
Slide 9: Tokens regelen
Drie tokens, één OAuth
GitHub PAT (fine-grained):
- github.com → Settings → Developer settings → Personal access tokens → Fine-grained
- Repo-permissies: Contents + Issues + Pull requests (read+write)
- Token begint met
ghp_...
Supabase Personal Access Token:
- supabase.com → Account → Access Tokens → Generate
- ⚠️ Account-level — NIET project anon key / service role
- Token begint met
sbp_... project_refhaal je uit Supabase project URL
Vercel: geen token vooraf. Bij eerste gebruik in Cursor → OAuth-prompt → toestaan.
Slide 10: Live koppelen + check
Vier stappen
1. mkdir -p ~/.cursor && nano ~/.cursor/mcp.json
2. Plak de JSON van slide 8 + vul je tokens in
3. Volledig herstart Cursor (Cmd+Q, opnieuw openen)
4. Open een chat — onderaan MCP-indicator → moet 4 servers groen tonen
Voor Vercel: klik op "Needs login" → OAuth-flow → autoriseer
Visual: screenshot van 4 groene indicators.
Slide 11: Polderfest MCP
Onze eigen server
polderfest-mcp-finished.zip bevat een complete Next.js-app:
polderfest-mcp/
├── app/
│ ├── api/mcp/route.ts ← MCP server zelf
│ ├── lib/supabase.ts ← Supabase client
│ ├── page.tsx ← landingspagina
│ └── layout.tsx
├── package.json ← mcp-handler + sdk + zod
├── .env.example
└── README.md
Vier tools: searchBands · getStageSchedule · festivalStats · getWeather
Slide 12: Code-tour
Eén tool — anatomie
server.tool(
"searchBands",
"Zoek bands op query, genre, of dag.",
{
query: z.string().optional(),
genre: z.string().optional(),
day: z.enum(["vrijdag","zaterdag","zondag"]).optional(),
},
async ({ query, genre, day }) => {
let q = supabase.from("bands").select("*").limit(50);
if (query) q = q.ilike("name", `%${query}%`);
if (day) q = q.eq("day", capitalizeDay(day));
const { data } = await q;
return { content: [{ type: "text", text: JSON.stringify(data) }] };
},
);
Bekend: Zod (uit Les 12/13). Nieuw: server.tool() + content-array.
Slide 13: Lokaal draaien
Drie commando's
unzip polderfest-mcp-finished.zip
cd polderfest-mcp-finished
npm install
cp .env.example .env.local
# vul SUPABASE_URL + SERVICE_ROLE_KEY (uit Les 11/12)
npm run dev
- Landingspagina:
localhost:3000 - MCP endpoint:
localhost:3000/api/mcp - Polderfest entry zit al in
mcp.json— herstart Cursor → 4 servers groen
Slide 14: De drie chats workflow
Demo overview — alles samen
Drie aparte Cursor-chats. Elke chat = één doel:
| Chat | MCP | Doel |
|---|---|---|
| Chat 1 | GitHub MCP | Maak GitHub repo + voeg toe als remote |
| Chat 2 | Polderfest + Supabase MCP | Bouw een nieuwe feature in onze MCP-server |
| Chat 3 | Vercel MCP | Maak Vercel project + deploy + env vars |
Resultaat: complete deploy van een nieuwe feature, vanaf je editor, zonder browser of CLI-commando's.
Visual: flow-diagram drie chats → één live productie-URL.
Slide 15: Chat 1 — GitHub MCP
Repo aanmaken + remote toevoegen
Cursor chat 1 — prompt:
Maak een nieuwe public GitHub repo "polderfest-mcp" aan
via GitHub MCP. Voeg toe als remote `origin` aan deze folder.
Push de main branch.
Wat er gebeurt:
- GitHub MCP roept
create_repositoryaan → krijgt URL terug - Cursor draait
git remote add origin <url>in terminal - Cursor draait
git push -u origin main - Open github.com → repo staat er met onze code
Geen browser. Geen gh repo create zelf typen.
Slide 16: Chat 2 — Polderfest features
Bouw via Cursor + Supabase MCP
Cursor chat 2 — prompt (nieuwe chat!):
Ik wil een review-systeem voor de Polderfest MCP.
Stap 1: vraag Supabase MCP om een tabel `band_reviews` te maken
(id, band_id FK naar bands, score 1-10, comment, created_at)
Stap 2: voeg twee tools toe aan @file:app/api/mcp/route.ts:
- addReview(bandName, score, comment)
- getReviews(bandName)
Gebruik dezelfde patroon als bestaande tools.
Test live in dezelfde chat:
- "Geef Maud and The Cathedrals een review: 9, episch."
- "Toon alle reviews voor Maud and The Cathedrals."
→ Polderfest MCP voert addReview en getReviews uit.
Slide 17: Chat 3 — Vercel MCP
Project + deploy + env vars
Cursor chat 3 — prompt (nieuwe chat!):
Maak via Vercel MCP een nieuw Vercel-project voor mijn
GitHub repo `polderfest-mcp`. Voeg toe als env vars (production):
- SUPABASE_URL = <plak>
- SUPABASE_SERVICE_ROLE_KEY = <plak>
Daarna: deploy naar productie en geef me de URL terug.
Resultaat: je krijgt een productie-URL terug — polderfest-mcp-<scope>.vercel.app/api/mcp.
Tot slot: vervang in mcp.json de polderfest-URL localhost:3000 door de productie-URL. Herstart Cursor → werkt nu zonder dat npm run dev draait.
Slide 18: Nu jullie — Lesopdracht
Doorloop de hele flow zelf
Stappen (basis, ±1 uur):
- Pak
polderfest-mcp-finished.zipuit +npm install+ env vars npm run dev— test lokaal- Voeg vier MCPs toe aan
~/.cursor/mcp.json(template in lesbestanden) - Herstart Cursor — check 4 indicators groen
- Chat 1: GitHub MCP → repo aanmaken + remote
- Chat 2: Test Polderfest MCP met een paar vragen
- Chat 3: Vercel MCP → project + deploy
- Update mcp.json met productie-URL → herstart Cursor → werkt zonder localhost
Geen deliverables. Gewoon doen tot het werkt.
Slide 19: Extra werk
Voeg een eigen feature toe
Voor wie sneller is. Doe wat Tim in Chat 2 deed — voor je eigen idee.
Patroon:
- Supabase MCP → tabel + seed-data via Cursor
- Cursor → genereer nieuwe tool(s) in
route.ts - Push → Vercel deploy't automatisch (omdat het project gekoppeld is)
- Test in Cursor chat
Ideeën:
addReview+getReviews(zoals de demo)addToWishlist+getMyWishlistrateStage+getStageRatingsaddNote+getNotes
Geen deliverables.
Slide 20: Volgende les
Les 16 — RAG + Embeddings
Wat we gaan bouwen:
- PDF Q&A-app from scratch
- Embeddings + vector search (pgvector)
- AI antwoorden op basis van eigen documenten
Voorbereiding:
- Polderfest MCP staat live op Vercel
- Vier MCPs gekoppeld in Cursor — github, supabase, vercel, polderfest
- Supabase project blijft draaien — we breiden uit met pgvector
Visual: document → vector → AI.