# MCP security review: <server> for <use case>

One record per server per use case. Placeholders are in angle brackets. Use roles, never personal names. Record key names only, never a token, key or customer record.

## Decision

- Outcome: <GO | GO WITH CONDITIONS | NO-GO> (<final | provisional, paper review: C16 lists the tests not yet run>)
- Valid until: <YYYY-MM-DD or the first re-review trigger, whichever comes first>
- Reason in one sentence: <why>
- What would change a NO-GO: <the fix, a different identity, or the vendor's official server>
- Tier: <1 | 2 | 3>, set by: <the criterion, for example "identity can publish pages">
- Reviewer: <role>; system owner: <role>; privacy owner: <role>; connection owner: <role>
- Review date: <YYYY-MM-DD>; decided by: <system owner role, with privacy owner where B9 or C6 applies>

## Scope

- Use case: <task and the decision it supports>
- Data categories: <category (personal: yes or no)>, ...
- Identity: <per-user OAuth | service account | system user | API key>, permission level <role or access level>, read from <admin screen or identity tool>
- Clients and plans: <AI client, plan, where it runs>
- Mode: <attended | scheduled | headless | research>
- Server: <vendor-hosted remote | local stdio | third-party hosted | internal>
- Endpoint or artifact: <URL, or package@version, or image@sha256 digest>
- Repository and tag: <URL and tag or commit, or not applicable>
- Capture: <file name>, source <live capture | vendor docs>, captured <YYYY-MM-DD>, server version <version as reported, self-reported and unverified>, complete <yes | no, T12>, matches the team's client <yes | no, what differs>
- List fingerprint: <sha256:...>
- Instructions fingerprint: <sha256:... | none in the capture>

## Blockers

- <B#> <finding>. Evidence: <what shows it>. Fix: <what removes it, enforced below the prompt>

## Conditions

- <C#> <condition>. Due: <before connecting | within 30 days, YYYY-MM-DD>. Owner: <role>. Closing evidence: <what will prove it>. Status: <open | met on YYYY-MM-DD with evidence>

## Checks

### Publisher and supply chain

- Vendor page naming this endpoint or package: <URL, date read, or "none found">
- Registry entry: <name, namespace type reverse-DNS or io.github, or none>
- Package: maintainers <count and account type>, last release <date>, provenance <attestation or none>, install scripts <yes or no>
- Pin: <exact version or digest, or what the config uses today>
- Advisory check: <databases searched, date, result>
- Hosted third party: <operator, region, stores upstream tokens yes or no, security page>

### Tools and definitions

- Script: `node scripts/review-mcp-tools.mjs <files>`; summary: <n FAIL, n WARN, n INFO, n PASS>
- Counts: <n> read, <n> reversible write, <n> hard-to-reverse
- Hard-to-reverse tools: <names>
- Indicators and verdicts:
  - <rule> <tool or field>: <directive confirmed | benign, because ...>
- Annotations trusted: <yes | no, because ...>

### Permissions and read-only enforcement

- Permission level at the source: <level>, read from <screen or tool, with date>
- Consent scopes: <list>
- Enforcing layer: <vendor switch | source permission | client only (not enough for Tier 3 hard-to-reverse tools)>
- Tests in <test account or sandbox name>:
  - Allowed read: <time, result, matches the UI yes or no>
  - Out-of-scope read: <record ID an admin confirmed exists, from the admin view>, <time, denied or empty>
  - Harmless write through an exposed write tool: <time, denied | not needed because the layer removes write tools>
  - Second identity (Tier 2 and 3): <time, result>
- Production identities hold the tested role: <yes or no, read from the admin screen or identity tool, read-only, date>

### Data path and personal data

- <category> (personal: yes or no): <source fields> to <server operator> to <AI provider, plan, training, retention, region> to <client storage and retention> to <logs> to <outputs>
- Minimisation: <source control and the test query that proves it>
- Privacy owner sign-off: <decisions.md entry ID, or not required because ...>

### Outsider text and session design

- Servers in the session: <list>
- Legs: private data <tools>; outsider text <tools>; outward <tools>
- Removed leg: <leg>, enforced by <control>, proven by <test>
- Canary cases: <case ID, test record ID, date, result>

### Tokens, client settings and logging

- Config scan: `node scripts/scan-mcp-config.mjs <files>`; summary: <n FAIL, n WARN, n INFO, n PASS>
- Token storage per client: <client: keychain | managed store | plaintext fallback>
- Approval setting per write tool: <tool: blocked | prompt | always allowed>
- Session permission mode per client: <client: manual | auto | bypassPermissions | dontAsk | the client's own equivalent, and where it is set>
- Log outside the agent: <where>, test call seen at <time>
- Revocation: owner <role>, where <vendor setting or key deletion>, test <time and result, or not run with reason>

## Not checked

- <item>: <reason>

## Re-review

- Triggers: version change, fingerprint change, new scopes or re-install prompt, identity or client change, new data category or users, publisher change, vendor advisory.
- Drift check: every <30 | 90> days, `node scripts/review-mcp-tools.mjs <new capture> --baseline <baseline file>`; any D01 to D05 finding is a re-review trigger
- Full re-review: <YYYY-MM-DD>

## Proposed martech-context updates (not applied)

- stack.md, <system>: Agent access: <server, endpoint, read-only layer>; Credentials: <secret name and where it is stored>
- decisions.md: D-<YYYYMMDD>-<n>, <decision, tier, conditions with owners and dates, expiry, triggers>
- mcp-reviews/<YYYY-MM-DD>-<server>.md: this record
- mcp-reviews/baselines/<server>-<version>-<YYYY-MM-DD>-tools.json: the capture
- README.md (index): under Optional files present, add mcp-reviews/, written by mcp-security-review: one record per server and use case, baselines in mcp-reviews/baselines/
