Epistemic discipline and anti-patterns
The MCP server returns structured data; the LLM generates content from it. Putting the two together creates a temptation: presenting LLM inferences as if they were manual facts. For the output to earn the trust of auditors, legal counsel and security champions, every statement must be labellable. And a manual-grounded label says where the requirement comes from, not that the code meets it: verifying the implementation requires tests and review.
The 4 epistemic labels
| Label | Definition | Green light for the user |
|---|---|---|
| manual-grounded | Retrieved via MCP — cite chapterId or ID (CTRL-*, <CAT>-NNN, MT-*, ART-*) | "The manual says: AUT-001 (MFA mandatory). <texto verbatim ou parafraseado fielmente>." |
| observed | Directly visible in the repository / codebase | "In file src/auth/login.ts:42, I observe: <…>." |
| inferred | A logical conclusion drawn from grounded + observed — mark it explicitly | "Inference: given that AUT-001 requires MFA, and the code only validates the password, the second factor is missing." |
| not verified | Not confirmed | "Not verified: <…>. Human inspection / test / log is recommended." |
Golden rule
When in doubt, prefer
not verifiedto presenting something as fact.Marking as
not verifiedlets the user act; wrongly marking asmanual-groundedcreates false positives that cost review effort and credibility.
Where to apply each label
manual-grounded
Allowed only when:
- Returned by an MCP tool (
consult_*,get_*,query_*,resolve_*,prepare_*) - The cited ID exists in the output of the call
- The text reflects what the output says (neither amplifies nor reduces it)
❌ Do not mark as grounded:
- Results of
search_sbd_toe_manualthat were not read (only seen as a snippet) — those are a lead, not evidence - Cross-tool synthesis (e.g. "
AUT-001+LOG-003imply X") — that isinferred
observed
Allowed only when:
- The file/line was read (not inferred from the file name)
- The observation is literally verifiable
❌ Do not mark as observed:
- "The system probably does X" — without having read the code
- Behaviour expected because of the framework — that is
inferred
inferred
Always mark explicitly when:
manual-grounded+observedare combined to reach a conclusion- General security knowledge is applied to a specific context
- A link without
mitigation_confidence: "derived"is extended to another situation
Recommended form: "Inference: <conclusão>. Based on: <grounded ID> + <observação>."
not verified
Use generously. Cases:
- The tool returned an empty list (
controls: [],threats: [],assignments: []) - The risk level was not confirmed by the user
- The result needs a test / scan / log that has not run yet
- The question touches content later than the served snapshot (see
sbd://toe/version)
MCP-specific confidence flags
Some tools return their own confidence fields. Translate them into labels:
| MCP field | Translation |
|---|---|
mitigation_confidence: "derived" | manual-grounded (structural link) |
link without mitigation_confidence: "derived" | inferred — flag explicitly |
completeness_report.m_recall < 1.0 | signal partial coverage — what is missing is not verified |
coverage.hasMore: true / coverage_gaps | a paginated / with declared gaps result — continue via nextOffset; the server is coverage-preserving (nothing silently truncated), but "page 1" ≠ "everything" |
rule_trace without CONCERNS_FILTER_* when concerns were passed | a sign of a problem — it may be returning more than was filtered for |
General anti-patterns
1. Inventing IDs
❌ "Control CTRL-09-99 covers this."
✅ Verify via query_sbd_toe_entities({query: "CTRL-09-99"}) before citing. If it does not exist, say: "No applicable control found in the manual for this case — flag for human review."
2. Declaring regulatory compliance
❌ "This code is compliant with NIS2 Art. 21." ✅ "The manual's NIS2 cross-check maps Art. 21 ↔ chapters N and M. Not a declaration of compliance — it requires an assessment by legal counsel + operational evidence."
3. Treating code as evidence
❌ "I implemented the lockout, so the control is covered."
✅ "Proposed implementation. Expected evidence: a test in test/auth/lockout.spec.ts + log entry auth.lockout.activated with schema X."
4. Merging manual-grounded with inferred
❌ "The manual says that rate limiting + monitoring prevent credential stuffing."
✅ "Manual-grounded: the output links MT-NNN (credential stuffing) to CTRL-<domain>-<slug>-<hash> with mitigation_confidence: derived. Inference (mine): applied together they cover the threat — marked as an inference, not as a fact from the manual."
5. Skipping the needs_clarification / needs_decomposition gate
❌ Calling prepare_sbd_toe_codegen_context again with the same payload to "try again".
✅ Stop, talk with the user, call again only after new inputs.
6. Showing an inferred link as a certainty
❌ "CTRL-… mitigates MT-NNN." — presented as a certainty, without mitigation_confidence: "derived".
✅ "CTRL-… mitigates MT-NNN — an inferred link (without mitigation_confidence: derived); validate with a test / human review."
7. Assuming the snapshot coverage without confirming it
❌ Answering about a normative cross-check (or any page) assuming that the MCP serves it — or that it does not.
✅ Read sbd://toe/version (manual, KG, ontology) and, when in doubt, validate with inspect_sbd_toe_retrieval whether the document appears among the top-ranked records. The published normative cross-checks — CRA / DORA / NIS2 / GDPR / AI Act / ENISA-CSA — are indexed in the served snapshot; content later than the snapshot lives only in the web manual until the next publication (see content lag).
8. Confusing (ontological) concerns with STRIDE domains
❌ concerns: ["spoofing", "tampering"]
✅ concerns: ["auth", "integrity"] — the ontological vocabulary is closed and maps to STRIDE domains indirectly.
9. Skipping setup_sbd_toe_agent at the start of the session
❌ Starting to call tools without initialising.
✅ First message of the security session: setup_sbd_toe_agent(riskLevel, projectRole) — it loads the per-chapter demand and the role rules. In clients that do not expose prompts (such as Claude Desktop), start with sbd://toe/quick-start and the declaration in select_sbd_toe_requirements.
10. Regenerating the skill at the start of every session
❌ Calling generate_sbd_toe_skill() every time.
✅ Generate once, save it at the canonical path (.claude/skills/sbd-toe.md, etc.), regenerate only after an upgrade of the MCP.
11. Confusing "consuming MCP" with "exposing an MCP server" (distinct security scope)
This mini-site covers the use of the MCP server SbD-ToE — consumption. When the organisation starts to expose its own MCP server (not consume one), it enters an additional security scope that is not covered by this mini-site nor by the SbD-ToE manual in general.
❌ Assuming that reading this mini-site covers the security of an MCP server to be published by the organisation.
✅ For exposed MCP servers, consult the OWASP MCP Top 10 (2025) — a dedicated catalogue that covers prompt injection in an MCP context, tool poisoning, excessive permissions, inadequate authentication/authorisation, insecure transport, input validation, output handling, insufficient monitoring and insecure defaults. The relevant SbD-ToE controls (ARC-015, REQ-AGN-001..004, OPS-011..014, Policy 38, Policy 39) apply directly — the OWASP MCP Top 10 works as a specific coverage checklist, complementary to the threat modelling of Ch. 03 §playbook-agentic.
Rigour checklist before submitting any output
- Does every statement carry one of the 4 labels?
- Do all cited IDs exist in MCP outputs from the session?
- Are links without
mitigation_confidence: derivedmarked as inferred? - Was
m_recall < 1.0flagged? - Is there no declaration of compliance?
- Was code not presented as evidence?
- For regulatory questions — was the snapshot coverage confirmed in
sbd://toe/version(and the web manual consulted for later content)?
If any check fails → review before delivering.
Next steps
- Troubleshooting / FAQ — symptoms vs solutions.
- Advanced patterns — for combining tools without losing rigour.