Skip to content

MCP tools

The write path of the reviewer agents (compliance mcp; the swarm starts it for every worker). Generated from the server's tool list.

activities_graph

Every touchpoint that declares or exports data, with how much of it is personal, the API operations it calls / tasks it defers / parties it exports to, and the activities it already belongs to (NONE = orphan). The input of the grouping pass.

activities_list

The GDPR processing activities declared, with what they derive.

activity_add_touchpoints

Add touchpoints (unit:id) to an existing activity.

Argument Type Required
slug string yes
touchpoints list[string] yes

activity_create

Create a GDPR processing activity: {slug (kebab), name, purpose, touchpoints[], reason, legal_basis?, data_subjects?, basis_note?, consent_record?, interest?}. legal_basis: contract, consent, legal_obligation, legitimate_interests, no_pii (handles no personal item; verified). purpose, legal_basis and consent_record accept {"missing": "why, citing code"} when you established that nothing lawful applies. Leave out what you could not establish (it becomes !todo); never invent.

Argument Type Required
slug string yes
name string yes
purpose string \| object yes
touchpoints list[string] yes
reason string yes
legal_basis string \| object \| null no
data_subjects list[string] \| null no
basis_note string \| null no
consent_record string \| object \| null no
interest string \| null no

challenge

Put a reviewed data item (unit:app.Model.field) or declared touchpoint (unit:id) back to pending because a change casts doubt on what its review asserted. grounds: one line citing the change (file:line) and the assertion it undermines. You do not reclassify; a reviewer will. element#SID (or element#SID@sink), as reviews prints them, re-opens one threat stamp instead of the declaration. Refused when already challenged or already answered.

Argument Type Required
ref string yes
grounds string yes

data_add_manual

Declare PERSONAL data the ORM has no row for: transient (a card number sent to the PSP, a position sent to a geocoder, a search query) or kept outside the ORM (cache, queue payload). Processing personal data counts even without storage; non-personal transient values are not tracked. {unit, id, description, pii, sensitivity, category, reason, store?, transient?=true}; transient=false with a store for data kept outside the ORM. Returns the ref for touchpoint_set_data.

Argument Type Required
unit string yes
id string yes
description string yes
pii boolean yes
sensitivity string yes
category string yes
reason string yes
store string \| null no
transient boolean no

data_changed

Given a base git ref: Python files changed since it and the models defined in them, so already-reviewed models can be re-checked.

Argument Type Required
base string yes

data_flag

Record what the code says about one right of one PERSONAL item. verdict=missing: the right is unmet (a deletion view that only deactivates; a purge whose duration contradicts a setting) — writes rights.<right>: !missing with your note. verdict=exempt: the code proves a ground (derived for a computed column, not_provided_by_subject for a system-generated value, legal_obligation with the law in the note). right: access, rectify, erase, retention, portability, object, consent, transfer. note cites file:line.

Argument Type Required
ref string yes
right string yes
verdict string yes
note string yes
ground string \| null no

data_model

Everything needed to review one model: its fields with current classification and status, write sites of its JSON-like fields, the allowed levels/categories, and the class source code. Usually no other reading is needed.

Argument Type Required
model string yes

data_pending

Models that still have fields to review, project models first, then third-party ones (their content is still this project's), JSON-heavy first. One line each: unit:app.Model | N pending of M fields | project|third-party.

Argument Type Required
unit string \| null no

data_review_model

Record the decisions for one model in a single call. decisions is a list of {field, ok} to confirm, or {field, pii?, sensitivity?, category?, reason} to correct (give only what changes; reason cites file:line). JSON-like fields take {field, contents: {name: {pii, sensitivity, category}}, unknown_contents, reason} instead and are rejected with a bare ok. Fields you omit stay pending. note is one line on what you looked at.

Argument Type Required
model string yes
decisions list[Decision] yes
note string yes

Find data item ids by substring or fuzzy match (unit:app.Model.field | pii | sensitivity | category). Use it before referencing an item; never invent a ref.

Argument Type Required
query string yes
unit string \| null no

data_why

For one data item (unit:id): the touchpoints handling it and the activities holding it, or that nobody declares it.

Argument Type Required
item string yes

flow_report

Record a flow the code has and the model lacks: element (touchpoint id), sink (a party id when it exists, else the host or service as the code names it), data (inventory refs of what is sent), note (file:line and what the code does). It becomes a finding until the flow is declared (a transfer, or a store write with stores). Sink: party:<id>, store:<slug>, or the bare host. Not for declared transfers or the project's own stores.

Argument Type Required
element string yes
sink string yes
data list[string] yes
note string yes

flows

The flows of one touchpoint in plain words — what it exchanges with its callers, what it does on which store, what it sends to which organisation (declared transfers are intended, not leaks) — each with the @sink suffix to stamp a flow-only threat. Compare the code with this list; whatever the code sends elsewhere goes to flow_report.

Argument Type Required
element string yes

parties_list

Declared organisations (party id | name | country).

party_add

Declare an external organisation data is sent to (a SaaS, an API provider): {id (kebab), name, website?, country? (ISO-2, only if sure), hosts? (API hostnames the code calls, e.g. api.hubapi.com, when they differ from the website's domain)}. Contact details are left !todo for a human.

Argument Type Required
id string yes
name string yes
website string \| null no
country string \| null no
safeguard string \| null no
dpf_certified boolean \| null no
hosts list[string] \| null no

reviews

What reviewers asserted about the given code files (repo-relative paths, e.g. from git diff --name-only): reviewed data items whose model lives there with their reasons and rights notes, declared touchpoints whose view/task/route lives there with their ops, transfers and note. These assertions are what a change may invalidate.

Argument Type Required
files list[string] yes

store_add

Declare a store of the project that the settings do not show: a realtime document server, a search index, a spreadsheet export... {unit, slug (kebab), type (database|cache|bucket|filesystem|queue|search|realtime|external|browser), name, backend?, hosts? (the hostnames or settings names the code reaches it by, e.g. TMW_URL), description?}. Not for another organisation's service: that is party_add.

Argument Type Required
unit string yes
slug string yes
type string yes
name string yes
backend string \| null no
hosts list[string] \| null no
description string \| null no

stores_list

The stores (databases, caches, buckets, queues) of a unit with their slug, type and backend, so notes can name where data lives.

Argument Type Required
unit string \| null no

threat_cells

The threat cells still open on one element (a touchpoint id, unit:store, party:x, or a flow a->b): SID, topic, title and what to look at. Cells a rule already dismissed are not shown.

Argument Type Required
element string yes

threat_stamp

Record your verdict on one threat of one element: sid exactly as listed (DS06, or DS06@party:mapbox for one flow). Either status: mitigated (note = the file:line that handles it), n/a (note = why it cannot happen here) or accepted (note = the comment or setting that accepts the risk); or missing: one line, file:line, what an attacker gets. Optional, only when the code shows less is at stake than the default: degree existence (a yes/no leaks) or attribute (one field), effect denial (nothing read or written), actor subject (unreachable anonymously).

Argument Type Required
element string yes
sid string yes
status string \| null no
note string \| null no
missing string \| null no
effect string \| null no
degree string \| null no
actor string \| null no

threat_topic

For a per-topic review: the topic's checklist, then for each element given (touchpoint ids) its open SIDs on that topic and where its code lives. Elements omitted: every element with something open on the topic.

Argument Type Required
topic string yes
elements list[string] \| null no

touchpoint_pending

Touchpoints (routes, tasks, admin screens) that do not declare the data they handle yet, or whose declaration is incomplete. One line each: unit:id | kind | framework | N fields, followed by WHY when a declaration exists (a challenge, or a flow the code has that the manifest lacks: answer THAT, do not re-declare the same data).

Argument Type Required
unit string \| null no

touchpoint_set_data

Declare what one touchpoint does to data, in a single call: data lists EVERY inventory item touched, personal or not, as {ref, ops}; ops = [{op, ...metadata}] with the closed vocabulary create[{consent_for}] | read | update | delete[{mode: delete|anonymise}] | retention_purge{after: {days|months|years} or settings.NAME, since, when?} | portability{format} | consent_withdraw{for}. A bare {ref} is a read. unit:app.Model.* covers every field of a model. An empty list means 'checked, touches no item'. transfers lists what leaves to another organisation: [{party, data[], purpose?}] for every external API/provider the code calls (party must exist: parties_list / party_add). stores lists what the code copies into another store of the project: [{store, data[], purpose?}] (store must exist: stores_list / store_add). reason cites file:line. scope = who the touchpoint serves: subject (an authenticated end user on their own data), staff (back-office), public (anonymous), system (task); give it when touchpoint_show's inference is wrong.

Argument Type Required
touchpoint string yes
data list[DataRef] yes
reason string yes
transfers list[ExportDecision] \| null no
scope string \| null no
stores list[StoreDecision] \| null no

touchpoint_show

Everything known about one touchpoint: code location, auth, request/response or page-data shapes, the API operations it calls, the data it declares and the activities holding it.

Argument Type Required
touchpoint string yes