148 lines
4.2 KiB
Markdown
148 lines
4.2 KiB
Markdown
# Les 15 — Huiswerk
|
||
## Voeg een eigen tool toe aan je Polderfest MCP server
|
||
|
||
**Vak:** AI-Assisted Development
|
||
**Opleiding:** NOVI Hogeschool Utrecht
|
||
**Werkvorm:** take-home (±1–2 uur)
|
||
**Deadline:** vóór Les 16
|
||
|
||
---
|
||
|
||
## Doel
|
||
|
||
Je breidt je Polderfest MCP server uit met minimaal één eigen tool. Daarmee laat je zien dat je het patroon van `server.tool()` zelf kunt toepassen — en je geeft Cursor een nieuwe mogelijkheid die er niet eerder was.
|
||
|
||
---
|
||
|
||
## Wat je gaat doen
|
||
|
||
### Stap 1 — Bedenk een tool
|
||
|
||
Kies één van de voorbeelden hieronder, of bedenk er zelf één.
|
||
|
||
#### Voorbeeld A — `findBandsByVibe`
|
||
|
||
Input: een vibe-omschrijving (string, bv. "donker en stoer" of "vrolijk zonnig").
|
||
Output: 5 bands die bij die vibe passen.
|
||
|
||
Implementatie-hint: gebruik `searchBands` onderliggend met een keyword-mapping, of vraag de AI om de vibe te interpreteren als genre.
|
||
|
||
#### Voorbeeld B — `comparePerformances`
|
||
|
||
Input: twee dagen (`day1`, `day2`).
|
||
Output: vergelijking — hoeveel bands per stage, populairste genres, schema-conflicten.
|
||
|
||
#### Voorbeeld C — `recommendForGenres`
|
||
|
||
Input: een lijst favoriete genres (string array).
|
||
Output: aanbevolen bands die in die genres vallen, gegroepeerd per dag.
|
||
|
||
#### Voorbeeld D — `getBandDetails`
|
||
|
||
Input: bandnaam (string).
|
||
Output: alle info over die band — stage, dag, tijd, genre, eventueel duurtijd-berekening.
|
||
|
||
#### Voorbeeld E — `searchByTimeSlot`
|
||
|
||
Input: dag + tijdsblok (`day`, `from`, `to`).
|
||
Output: welke bands spelen er in dat blok.
|
||
|
||
### Stap 2 — Implementeer
|
||
|
||
Open `app/api/mcp/route.ts` in je Polderfest MCP folder. Voeg je tool toe onder de bestaande tools.
|
||
|
||
**Template:**
|
||
|
||
```typescript
|
||
server.tool(
|
||
"naamVanTool",
|
||
"Korte beschrijving — wat doet hij. Goede beschrijvingen helpen de AI te beslissen wanneer hij de tool aanroept.",
|
||
{
|
||
// Zod input-schema
|
||
arg1: z.string(),
|
||
arg2: z.enum(["optie1", "optie2"]).optional(),
|
||
},
|
||
async ({ arg1, arg2 }) => {
|
||
// Jouw logica — meestal een Supabase-query
|
||
const { data } = await supabase.from("bands")./* ... */;
|
||
return {
|
||
content: [
|
||
{ type: "text", text: JSON.stringify(data, null, 2) },
|
||
],
|
||
};
|
||
},
|
||
);
|
||
```
|
||
|
||
### Stap 3 — Lokaal testen
|
||
|
||
```bash
|
||
npm run dev
|
||
```
|
||
|
||
In Cursor: stel een vraag die je nieuwe tool zou moeten aanroepen. Check dat:
|
||
- De MCP-indicator je tool laat zien
|
||
- Cursor de tool aanroept (zie tool-call output in chat)
|
||
- De output zinvol is
|
||
|
||
### Stap 4 — Pushen + deployen
|
||
|
||
```bash
|
||
git add .
|
||
git commit -m "feat: <jouw tool-naam>"
|
||
git push
|
||
```
|
||
|
||
**Vercel deploy't automatisch** zodra je naar `main` pusht. Wacht ±45 seconden.
|
||
|
||
### Stap 5 — Test op productie
|
||
|
||
In Cursor (mcp.json wijst al naar productie-URL), stel dezelfde vraag. Check dat het ook live werkt.
|
||
|
||
---
|
||
|
||
## Op te leveren (via Teams)
|
||
|
||
1. **GitHub repo URL** met je nieuwe tool
|
||
2. **Korte beschrijving** (3–5 zinnen):
|
||
- Welke tool heb je gebouwd?
|
||
- Welke probleem lost hij op?
|
||
- Met welke prompt heb je hem in Cursor getest?
|
||
3. **Twee screenshots:**
|
||
- Cursor chat waar je tool aangeroepen wordt (zichtbaar in tool-call output)
|
||
- De output die Cursor met je tool gaf
|
||
|
||
**Deadline:** vóór Les 16 (volgende week).
|
||
|
||
---
|
||
|
||
## Beoordeling
|
||
|
||
| Criterium | Punten |
|
||
|-----------|--------|
|
||
| Tool is gedefinieerd met juiste `server.tool()` signature | 25% |
|
||
| Input-schema gebruikt Zod correct (geen `any`) | 15% |
|
||
| Tool returnt valide MCP-output (`{ content: [...] }`) | 15% |
|
||
| Tool werkt lokaal én op productie | 25% |
|
||
| Beschrijving + screenshots compleet | 20% |
|
||
|
||
---
|
||
|
||
## Tips
|
||
|
||
- **Hou de tool focused.** Eén ding goed doen is beter dan vijf dingen half.
|
||
- **Schrijf een goede description.** De AI leest die om te beslissen wanneer hij hem aanroept. Zwakke beschrijving = tool wordt niet gebruikt.
|
||
- **Test met meerdere prompts.** Sommige tools worden alleen aangeroepen bij heel specifieke woorden — probeer variaties.
|
||
- **Gebruik Cursor om Cursor te bouwen.** Vraag in een aparte Cursor chat: *"Schrijf een MCP tool voor X gebaseerd op de patronen in @file:app/api/mcp/route.ts"*. Meta!
|
||
|
||
---
|
||
|
||
## Vooruitblik
|
||
|
||
In Les 16 (RAG + Embeddings) ga je verder met je Supabase project, dus zorg dat:
|
||
- Je MCP server live blijft staan
|
||
- Je huiswerk-tool werkt (we komen erop terug)
|
||
- Je `.cursor/mcp.json` correct wijst naar productie
|
||
|
||
Veel succes!
|