Brengt de docs gelijk met de werkelijkheid na PBI-46/47/50/58/59/61/63 en M12. Belangrijkste fixes: - data-model.md herschreven naar prisma/schema.prisma: nieuwe entiteiten (Idea, IdeaLog, IdeaProduct, UserQuestion, ClaudeQuestion, ClaudeJob, SprintRun, SprintTaskExecution, ClaudeWorker, LoginPairing, PushSubscription, ModelPrice, ProductMember), nieuwe enums (FAILED/EXCLUDED, OPEN/CLOSED/ARCHIVED, ADMIN, etc.) en codes (PBI/ST/T/SP-N) toegevoegd; verwijderde todos-tabel verwijderd. - glossary.md: Sprint zonder "max 1 actief" (PBI-63), Story/Task incl. FAILED/EXCLUDED, Todo verwijderd, Idea/SprintRun/ClaudeJob/ verify_result toegevoegd. - project-structure.md: app/(app)/todos vervangen door ideas/insights/jobs/manual/admin/solo; api-tree volledig. - overview.md: "geen realtime in v1" en Docker-rationale herschreven — Postgres LISTEN/NOTIFY + SSE, claude_jobs als queue, opt-in Docker-deploy-flow. - functional.md: F-08 Todo-lijst -> Ideeen-laag, F-09 multi-sprint, F-10 Task-status incl. FAILED/EXCLUDED, F-11 endpoint-lijst, navigatiestructuur, datamodel-schets en Flow 3 bijgewerkt. - README.md API-tabel: /api/todos weg, ideas/jobs/users/profile/health toegevoegd, kort over realtime/auth-pair/internal/cron. - patterns + mcp-integration runbook: Todo-/ACTIVE-references vervangen door Idea/OPEN; create_todo MCP-tool note over verwijdering. Linkcheck groen (105 files), INDEX hergegenereerd (98 docs). Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
120 lines
7.8 KiB
Markdown
120 lines
7.8 KiB
Markdown
---
|
|
title: "MCP Integration — Scrum4Me Tools"
|
|
status: active
|
|
audience: [ai-agent]
|
|
language: nl
|
|
last_updated: 2026-05-08
|
|
when_to_read: "When using MCP tools to interact with the Scrum4Me backlog."
|
|
---
|
|
|
|
# MCP-integratie
|
|
|
|
Scrum4Me heeft een eigen MCP-server in repo [`madhura68/scrum4me-mcp`](https://github.com/madhura68/scrum4me-mcp) die de REST-API als native tools voor Claude Code aanbiedt. Schema's worden gedeeld via een git submodule (`vendor/scrum4me`), niet gedupliceerd.
|
|
|
|
## Tools beschikbaar in Claude Code (18)
|
|
|
|
**Read / context:**
|
|
- `mcp__scrum4me__health` — service + DB ping
|
|
- `mcp__scrum4me__list_products` — producten waar de tokengebruiker toegang tot heeft
|
|
- `mcp__scrum4me__get_claude_context` — bundled product / actieve sprint (`status='OPEN'`) / next story (met tasks) / open ideas
|
|
|
|
**Authoring (PBI/Story/Task aanmaken):**
|
|
- `mcp__scrum4me__create_pbi` — `{ product_id, title, description?, priority, sort_order? }`; auto sort_order = last+1 binnen prio-groep
|
|
- `mcp__scrum4me__create_story` — `{ pbi_id, title, description?, acceptance_criteria?, priority, sort_order? }`; product_id afgeleid uit PBI; status=OPEN
|
|
- `mcp__scrum4me__create_task` — `{ story_id, title, description?, implementation_plan?, priority, sort_order? }`; sprint_id geërfd van story; status=TO_DO
|
|
|
|
> Idea-aanmaak loopt niet via MCP maar via de UI of `POST /api/ideas`. De voormalige `create_todo`-tool is verwijderd; idea-mutaties gaan via de Idea-tools onder *Idea-laag (M12)* hieronder.
|
|
|
|
**Task / story writes:**
|
|
- `mcp__scrum4me__update_task_status`, `mcp__scrum4me__update_task_plan`
|
|
- `mcp__scrum4me__log_implementation`, `mcp__scrum4me__log_test_result`, `mcp__scrum4me__log_commit`
|
|
|
|
**Vraag-antwoord-kanaal (M11):**
|
|
- `mcp__scrum4me__ask_user_question` — post een vraag over een story; optionele `wait_seconds` (max 600) polt voor het antwoord
|
|
- `mcp__scrum4me__get_question_answer` — huidige status + antwoord (voor latere session-pickup)
|
|
- `mcp__scrum4me__list_open_questions` — eigen vragen, max 50, recente eerst
|
|
- `mcp__scrum4me__cancel_question` — asker-only annulering van een eigen open vraag
|
|
|
|
**Job queue — agent worker mode (M13):**
|
|
- `mcp__scrum4me__wait_for_job` — blokkeert ≤600s, claimt atomisch een QUEUED-job via FOR UPDATE SKIP LOCKED. **Sinds M12** retourneert de payload een `kind`-discriminator:
|
|
- `kind: 'TASK_IMPLEMENTATION'` (default) — payload met `implementation_plan`, `story`, `pbi`, `sprint`, `repo_url`
|
|
- `kind: 'IDEA_GRILL'` of `'IDEA_MAKE_PLAN'` — payload met `idea`, `product`, `repo_url`, en `prompt_text` (de embedded prompt uit `lib/idea-prompts/`)
|
|
Stale CLAIMED-jobs (>30min) worden eerst terug naar QUEUED gezet. Lege queue na block-time = klaar.
|
|
- `mcp__scrum4me__update_job_status` — agent rapporteert `running|done|failed` + optionele branch/summary/error; triggert automatisch SSE-event. Bij `failed` voor `IDEA_GRILL`/`IDEA_MAKE_PLAN` wordt de idea-status automatisch op `GRILL_FAILED` resp. `PLAN_FAILED` gezet. Auth: Bearer-token moet matchen `claimed_by_token_id`. Optionele token-velden: `model_id` (string), `input_tokens`, `output_tokens`, `cache_read_tokens`, `cache_write_tokens` (alle non-negative int) — worden opgeslagen op de ClaudeJob-rij bij done/failed.
|
|
|
|
**Idea-jobs (M12) — agent gedrag per kind:**
|
|
|
|
| Kind | Werkwijze | Eind-call |
|
|
|---|---|---|
|
|
| `IDEA_GRILL` | Lees `prompt_text` (embedded grill-prompt) + `idea.grill_md` als startpunt; itereer met `ask_user_question(idea_id=...)`/`get_question_answer`; log onderweg `log_idea_decision`; eindig met `update_idea_grill_md(markdown)` | `update_job_status('done')` |
|
|
| `IDEA_MAKE_PLAN` | Lees `prompt_text` (embedded make-plan-prompt) + `idea.grill_md` + repo-context. **Stel GEEN vragen** — single-pass output. Bouw plan in strict yaml-frontmatter format en eindig met `update_idea_plan_md(markdown)`. Server-side parser kan parse-fail → `PLAN_FAILED` | `update_job_status('done')` |
|
|
|
|
**MCP-tools — Idea-laag (M12):**
|
|
- `mcp__scrum4me__get_idea_context(idea_id)` — `{ idea, product, repo_url, grill_md_so_far, open_questions, prompt_text }`
|
|
- `mcp__scrum4me__update_idea_grill_md(idea_id, markdown)` — schrijft veld; status → `GRILLED`; logt `IdeaLog{GRILL_RESULT}`
|
|
- `mcp__scrum4me__update_idea_plan_md(idea_id, markdown)` — server-side `parsePlanMd`; ok → `PLAN_READY` + `IdeaLog{PLAN_RESULT}`; parse-fail → `PLAN_FAILED` + `IdeaLog{JOB_EVENT, errors}`
|
|
- `mcp__scrum4me__log_idea_decision(idea_id, type, content, metadata?)` — `type ∈ {DECISION, NOTE}`
|
|
- `mcp__scrum4me__ask_user_question` — geüpgrade contract: exact één van `story_id` óf `idea_id` (xor); idea-vragen zijn user-private (geen productAccessFilter).
|
|
|
|
## Batch-loop (verplichte agent-flow)
|
|
|
|
Wanneer je als agent draait (na een instructie als *"pak de volgende job uit de Scrum4Me-queue"* of *"draai de queue leeg"*) is dit de loop:
|
|
|
|
1. `wait_for_job` aanroepen.
|
|
2. Switch op `kind`:
|
|
- `TASK_IMPLEMENTATION`: voer uit volgens het meegegeven `implementation_plan` (zoals altijd — branch, code, commit, push, verify_task_against_plan).
|
|
- `IDEA_GRILL`: laad `prompt_text` als gids; gebruik `ask_user_question` / `get_question_answer` voor de Q&A-loop; eindig met `update_idea_grill_md`.
|
|
- `IDEA_MAKE_PLAN`: laad `prompt_text` + `idea.grill_md`; **stel geen vragen**; produceer strict yaml-frontmatter; eindig met `update_idea_plan_md`.
|
|
3. `update_job_status('done'|'failed')` aanroepen.
|
|
4. **Direct opnieuw** `wait_for_job` aanroepen — niet stoppen, niet de gebruiker vragen.
|
|
5. Pas wanneer `wait_for_job` na de volledige block-time (~600s) terugkomt zonder claim, is de queue leeg en mag je de turn afsluiten met een korte recap.
|
|
|
|
Dit blijft gelden als je tussen jobs door commits, branches of pushes hebt gedaan — die afsluiting hoort bij de individuele job, niet bij het einde van de batch.
|
|
|
|
## Pre-flight quota-check (M13)
|
|
|
|
Vóór elke `wait_for_job`-aanroep doet de worker een pre-flight quota-check
|
|
om te voorkomen dat-ie 600 s blokkeert terwijl Anthropic-quota toch op
|
|
0 staat. Loop:
|
|
|
|
1. `mcp__scrum4me__get_worker_settings()` → `{ min_quota_pct }`
|
|
2. `bash bin/worker-quota-probe.sh` → JSON `{ pct, reset_at_iso, ... }`
|
|
3. `mcp__scrum4me__worker_heartbeat({ last_quota_pct: pct, last_quota_check_at })`
|
|
— server emit een SSE-event zodat NavBar realtime de stand-by-badge
|
|
kan tonen
|
|
4. **Als `pct < min_quota_pct`**: log "stand-by, wachten tot
|
|
`reset_at_iso`", sleep tot reset (cap op 1 uur), spring naar stap 2
|
|
5. **Anders**: ga door met `wait_for_job`
|
|
|
|
Pseudo-bash:
|
|
|
|
```bash
|
|
QUOTA_JSON=$(/opt/agent/bin/worker-quota-probe.sh)
|
|
PCT=$(echo "$QUOTA_JSON" | jq -r '.pct')
|
|
RESET=$(echo "$QUOTA_JSON" | jq -r '.reset_at_iso')
|
|
|
|
# Stuur naar server (best-effort; failure niet-fataal)
|
|
mcp_call worker_heartbeat "{\"last_quota_pct\": $PCT}"
|
|
|
|
if [[ "$PCT" -lt "$MIN_PCT" ]]; then
|
|
log "stand-by until $RESET (pct=$PCT < min=$MIN_PCT)"
|
|
sleep_until "$RESET"
|
|
continue
|
|
fi
|
|
```
|
|
|
|
**Beperking**: de probe kost ~1 outputtoken per check. 12 checks/uur =
|
|
12 tokens/uur overhead — verwaarloosbaar. De `min_quota_pct`-setting
|
|
staat per default op 20% — bij vrije Pro/Max-plans typisch ruim genoeg
|
|
om dagelijks werk niet te verstoren.
|
|
|
|
**Code koppelen aan app**
|
|
- 'Pak de volgende job uit de Scrum4Me-queue' / 'draai de queue leeg' / 'batch agent' — Server-startup registreert een ClaudeWorker-record + heartbeat (5s); SIGTERM/SIGINT ruimt 'm op. UI in NavBar telt actieve workers via `last_seen_at < now() - 15s`.
|
|
|
|
## Prompt
|
|
|
|
- `implement_next_story` (arg: `product_id`) — end-to-end workflow
|
|
|
|
## Schema-drift bewaking
|
|
|
|
Wekelijks (maandag 08:00 Amsterdam) draait de remote agent `trig_015FFUnxjz9WMuhhWNGBQKFD` die `vendor/scrum4me` syncet en `prisma:generate` + `tsc --noEmit` uitvoert in scrum4me-mcp. Als die agent drift rapporteert, hoort dat **vóór** een Scrum4Me-PR met schema-wijziging gemerged kan worden — anders breekt de MCP-server stilletjes op runtime.
|