---
title: "MCP Integration"
status: active
audience: [contributor]
language: en
last_updated: 2026-05-07
when_to_read: "Whenever Claude Code is interacting with Scrum4Me — opening a story, claiming a job, asking the user a question."
---

# 04 — MCP Integration

Scrum4Me exposes its REST API as native Claude Code tools through a dedicated **MCP server** living in [`madhura68/scrum4me-mcp`](https://github.com/madhura68/scrum4me-mcp). Schemas are shared via a git submodule (`vendor/scrum4me`) so there's exactly one definition of every type. From the agent's perspective, Scrum4Me looks like a set of native tools prefixed `mcp__scrum4me__*`.

This chapter is the **onboarding tour**. The full tool reference (all 18 tools, their parameters, and edge cases) is in [`docs/runbooks/mcp-integration.md`](../runbooks/mcp-integration.md).

## Three ways the agent works

| Mode | Triggered by | Loop |
|---|---|---|
| **Track A — MCP-driven** | User says *"implement the next story"* | `get_claude_context` → execute tasks → `update_task_status` → commit per layer → repeat until queue empty → push + PR |
| **Track B — Manual** | User describes a one-off change in chat | Read pattern + styling → edit → verify → wait for `commit it` → commit |
| **Worker — Queue-driven** | Background worker container running on a Mac/NAS | `wait_for_job` (blocks ≤600s) → switch on `kind` → execute → `update_job_status` → loop forever |

CLAUDE.md describes Track A and Track B; this manual focuses on the **Worker** mode because it's the most novel and the most likely to surprise a new contributor reading server logs.

## A typical Track A run

```mermaid
sequenceDiagram
    participant U as User
    participant C as Claude
    participant M as MCP server
    participant DB as Postgres

    U->>C: "implement the next story"
    C->>M: get_claude_context(product_id)
    M->>DB: SELECT product, sprint, next story, tasks
    M-->>C: { story, tasks[], pbi, sprint }
    loop per task in sort_order
        C->>M: update_task_status(task_id, 'in_progress')
        C->>C: read pattern + styling, edit files
        C->>M: log_implementation(story_id, content)
        C->>M: update_task_status(task_id, 'review')
        C->>M: log_test_result(story_id, 'PASSED')
        C->>M: update_task_status(task_id, 'done')
    end
    C->>U: "milestone ready for your test"
    U->>C: "looks good, push it"
    C->>C: git push + gh pr create
```

The contract every step relies on:

- All inputs are **lowercase API enums** (`'in_progress'`, never `'IN_PROGRESS'`); the MCP server applies [`lib/task-status.ts`](../../lib/task-status.ts) under the hood.
- Status writes are **forbidden for demo accounts** — they return `403`. See [02 — Statuses](./02-statuses-and-transitions.md#db-vs-api-mapping) and [`docs/adr/0006-demo-user-three-layer-policy.md`](../adr/0006-demo-user-three-layer-policy.md).
- Bearer tokens are bound to a product. `list_products` returns only what the token can see; `get_claude_context` is product-scoped.

## Idea jobs vs task implementation

The worker `wait_for_job` returns a payload with a `kind` discriminator. The agent must switch on it:

| `kind` | Behaviour |
|---|---|
| `TASK_IMPLEMENTATION` | Default. Execute the `implementation_plan`, follow the [git workflow](./03-git-workflow.md), end with `update_job_status('done')`. |
| `IDEA_GRILL` | Read embedded `prompt_text` + existing `idea.grill_md`. Iterate with `ask_user_question` / `get_question_answer`. End with `update_idea_grill_md(markdown)`. |
| `IDEA_MAKE_PLAN` | Read `prompt_text` + `idea.grill_md`. **Do not ask questions** — single-pass output in strict YAML-frontmatter. End with `update_idea_plan_md(markdown)`. Server-side parser may reject → `PLAN_FAILED`. |
| `PLAN_CHAT` | Conversational refinement loop on an existing plan (M12+). |
| `SPRINT_IMPLEMENTATION` | Sprint-level run that cascades through every task; `update_task_status` calls must include the `sprint_run_id`. |

For the full Idea state machine (DRAFT → GRILLING → … → PLANNED) see [02 — Statuses & Transitions § Idea](./02-statuses-and-transitions.md#idea).

## The Q&A channel

When Claude needs a human decision mid-run, it doesn't block silently — it posts a question through the MCP and either polls or returns control:

```mermaid
sequenceDiagram
    participant C as Claude
    participant M as MCP
    participant DB as Postgres
    participant U as User (NavBar bell)
    C->>M: ask_user_question({ story_id, question, wait_seconds: 600 })
    M->>DB: INSERT user_question; NOTIFY user_question_created
    DB-->>U: SSE event → bell pulses
    U->>M: POST /api/questions/:id/answer
    M->>DB: UPDATE user_question; NOTIFY user_question_answered
    DB-->>C: ask_user_question returns { answer }
    C->>C: continue execution
```

Key facts:

- `wait_seconds` is capped at 600. If the user doesn't answer in time, `ask_user_question` returns with status `pending`; Claude can resume later via `get_question_answer(question_id)`.
- Idea questions (`{ idea_id }` instead of `{ story_id }`) are **user-private** — they bypass `productAccessFilter`, so collaborators don't see them.
- A question can be cancelled by the asker via `cancel_question`.

The persistent design (table + `LISTEN/NOTIFY`) is documented in [`docs/architecture/claude-question-channel.md`](../architecture/claude-question-channel.md).

## The worker's pre-flight quota check

The worker doesn't blindly call `wait_for_job`. Each iteration it first checks Anthropic API quota via `bin/worker-quota-probe.sh` so it doesn't burn a 10-minute block on a queue it can't actually process. The full algorithm — settings, `worker_heartbeat` SSE event, sleep-until-reset — is in [`docs/runbooks/mcp-integration.md`](../runbooks/mcp-integration.md#pre-flight-quota-check-m13). The Docker chapter ([05](./05-docker.md#quota-probe)) shows how to test it locally.

## Schema-drift watchdog

If Scrum4Me's Prisma schema changes but `scrum4me-mcp` isn't synced, the MCP server will fail at runtime — not at deploy. To prevent that, a remote agent runs every Monday at 08:00 Amsterdam time, syncs `vendor/scrum4me`, and runs `prisma:generate` + `tsc --noEmit` in `scrum4me-mcp`. Drift reports must be resolved **before** any Scrum4Me PR with schema changes can merge. See [`docs/runbooks/mcp-integration.md`](../runbooks/mcp-integration.md#schema-drift-bewaking).

## Deep links

| Topic | Authoritative source |
|---|---|
| Tool reference (all 18 tools) | [`docs/runbooks/mcp-integration.md`](../runbooks/mcp-integration.md) |
| Worker idempotency & job-status protocol | [`docs/runbooks/worker-idempotency.md`](../runbooks/worker-idempotency.md) |
| Q&A channel architecture (table + LISTEN/NOTIFY) | [`docs/architecture/claude-question-channel.md`](../architecture/claude-question-channel.md) |
| Idea-laag plan & prompts | [`docs/plans/M12-ideas.md`](../plans/M12-ideas.md) |
| Sprint execution modes (PER_TASK vs SPRINT_BATCH) | [`docs/architecture/sprint-execution-modes.md`](../architecture/sprint-execution-modes.md) |
| Realtime NOTIFY payload contract | [`docs/patterns/realtime-notify-payload.md`](../patterns/realtime-notify-payload.md) |
| Demo-user write protection | [`docs/adr/0006-demo-user-three-layer-policy.md`](../adr/0006-demo-user-three-layer-policy.md) |

## What's next

→ [05 — Docker](./05-docker.md) covers how the worker container is run, debugged, and operated.
