Use case — Threat modelling
Threat modelling has a predictable failure in fast-paced environments — either it is done too early (and is out of date by the time the code arrives), or it is done too late (and turns into compliance theatre). The MCP helps to do it at a useful moment: the agent extracts from the manual the threats already catalogued for the project's risk level and the system's concerns, and anchors them in the controls that mitigate them — with IDs.
The example here is a public user-management API (create account, authenticate, recover password). In two calls to the server, the agent gathers the material for a defensible threat model, with the confidence of each link marked in mitigation_confidence. Today, every served link is derived, structural. If another value appears, the link is inferred and is labelled as such.
Prior requirements​
- MCP installed, skill loaded.
- Project risk level —
L2in the example (public API, user data).
Flow​
1. Identify the system's concerns​
From the prose description, map to the ontological vocabulary:
| System aspect | Concern |
|---|---|
| Login / authentication | auth |
| Public REST endpoints | api |
| Input validation (email, password strength) | validation |
| Password hashing, tokens | encryption |
| Audit log of sensitive operations | logging |
→ concerns = ["auth", "api", "validation", "encryption", "logging"]
2. Threat landscape​
Important: get_threat_landscape runs consult internally — do not call consult_security_requirements beforehand.
get_threat_landscape({
"risk_level": "L2",
"concerns": ["auth", "api", "validation", "encryption", "logging"]
})
Expected output (real shape — threats MT-NNN; each link cites the control_id):
{
"threats": [
{
"id": "MT-055", "name": "Interfaces expostas sem isolamento",
"chapter_id": "04-arquitetura-segura", "threat_category": "STRIDE",
"mitigation_confidence": "derived", "mitigation_strength": "parcial",
"mitigated_by": [
{"control_id": "CTRL-infrastructure-segmentacao-e-controlo-arquitetural-dceb3c1f0b", "domain": "infrastructure"}
]
}
]
}
routing_basisThe response declares, for each concern, the basis of the routing in routing_basis: domain_chapter when the concern has a threat chapter of its own, activated_controls when the threats arrive through the chapters that define the activated controls. Reading routing_basis before structuring the threat model tells where each threat came from — and, with that, how to present it.
3. Practices by role (optional, but useful)​
For the role that will mitigate (e.g.: arquitetos-software in design, developer in implement):
get_guide_by_role({"risk_level": "L2", "role": "arquitetos-software", "phase": "design"})
→ returns practice assignments + user stories to use as acceptance criteria.
4. Structure the threat model​
Recommended model (STRIDE adapted to the output):
## Threat Model — <componente>
### Componente em análise
- Surface: <endpoint, mĂłdulo, dataflow>
- Risk level: L2
- Concerns: auth, api, validation, encryption, logging
### Data flow (DFD)
<diagrama mermaid ou descrição>
### Threats (manual-grounded)
#### MT-NNN — <tĂtulo da ameaça do output>
- **Descrição:** <`name` do output do MCP>
- **STRIDE:** <`threat_category`>
- **Mitigated by:** `CTRL-<domain>-<slug>-<hash>` (do `mitigated_by`)
- **Mitigation confidence:** derived · strength parcial ✅
- **Acceptance criteria:** <user stories de get_guide_by_role>
#### MT-NNN — <outra ameaça, ligação fraca>
- **Mitigation confidence:** *fallback* sem ligação estrutural → rotular como **inferido** ⚠️
- **Nota:** validar com revisĂŁo humana / testes.
### Threats sem mitigação no manual
- <`MT-*` devolvidos sem `mitigated_by`> — flag para revisão humana
### ResĂduo
<o que não foi endereçado>
Output discipline​
mitigation_confidence: "derived"(strength typically"parcial") → structural link. Present it as a reliable link.- Fallback without a structural link → treat as inferred; label it explicitly, not as a certainty.
- If
threats: []→ write "No threats catalogued in the manual for this scope — not to be confused with absence of risk". Do not invent. - Cite
MT-*andCTRL-*IDs exactly as returned.
Skill / subagent — Cursor​
.cursorrules, dedicated section:
## Threat modeling com SbD-ToE
Quando for pedido threat model ou análise de ameaças:
1. Identificar concerns aplicáveis a partir do escopo do sistema.
2. Chamar mcp__sbd-toe__get_threat_landscape(risk_level, concerns).
3. Chamar mcp__sbd-toe__get_guide_by_role(risk_level, role, phase) para acceptance criteria.
4. Estruturar relatĂłrio STRIDE-adaptado citando MT-* e CTRL-* exactos.
5. Rotular mitigation_confidence (derived/parcial); ligação fraca → inferido.
6. Não inventar threats nem ligações. Threats vazios → flag para revisão humana.
Anti-patterns​
- ❌ Calling
consult_security_requirementsbeforeget_threat_landscape— unnecessary duplication; the tool already runsconsultinternally. - ❌ Presenting an inferred link (without
mitigation_confidence: "derived") as a certainty. - ❌ Inventing
MT-CUSTOM-001to fit a threat that is known but not in the output — write it in a separate section as an observed threat and mark itnot verifiedin the manual. - ❌ Confusing technical
concerns(auth) with STRIDE domains (Spoofing).
Related​
- Grounded codegen — after the threat model, generate mitigations with IDs.
get_threat_landscapein the reference.