> ## Documentation Index
> Fetch the complete documentation index at: https://subtext.fullstory.com.pgm.c5nprx.cc/docs/llms.txt
> Use this file to discover all available pages before exploring further.

# Subtext Privacy MCP Tools: Complete Reference Guide

> Complete reference for Subtext's privacy MCP tools across element, URL, and network rules: propose, create, list, promote, delete, plus URL and network rule management.

Subtext's privacy tools manage three kinds of rule that control what Fullstory captures in session recordings:

* **Element rules** — CSS-selector rules that mask or exclude specific page elements.
* **URL rules** — scrub sensitive parts of captured URLs (host, path, query).
* **Network rules** — control whether request and response bodies are captured, redacted, or partially allowlisted.

Each tool is called by your agent directly — no manual UI steps required. Listing and creation exist for all three kinds; propose, promote, and delete apply to element rules only.

## Safety model

Two lifecycle models sit underneath these tools. Which one applies depends on the rule kind.

**Element rules use a two-tier scope.** When your agent creates an element rule, it lands in **preview** scope first. Preview rules apply only to sessions opened in preview mode, leaving production capture untouched — so you can create, test, and delete them freely. A rule reaches production only when you **promote** it to **live** (all-sessions) scope, and live rules cannot be deleted through the agent tooling.

<Warning>
  The agent can only delete **preview** element rules. Live rules are intentionally protected from deletion via the MCP tools — removing a production masking rule could expose PII in all future recordings. To remove a live rule, use the Fullstory settings UI directly.
</Warning>

This asymmetry lets the agent autonomously run the entire propose → create → promote cycle while a human retains final authority over what gets removed from production coverage.

**URL and network rules have no preview step.** `privacy-url-create` and `privacy-network-create` take effect for **all sessions immediately** — there is no preview scope to validate in, nothing to promote, and (today) no MCP delete. Double-check the pattern before you create the rule, then confirm it with the matching `-list` tool afterward.

***

## Element rules

### `privacy-propose`

Scan a session for PII and propose masking rules as a dry-run.

`privacy-propose` is read-only. It inspects every page of a session, identifies elements that appear to contain personally identifiable information, and returns candidate CSS selectors with a suggested rule name and PII type for each. Nothing is written to Subtext.

**Key behaviors:**

* Takes a `session_url`. All pages in the session are analyzed and results are deduplicated across them.
* Returns candidate selectors, not finalized rules — you decide which to act on.
* Optional `block_type` (`mask`, the default, or `exclude`) sets the kind of rule suggested.
* Charges 1 credit per call.

<Tip>
  Run `privacy-propose` on a freshly captured session after shipping any feature that introduces new user-facing data. It's the fastest way to catch unmasked PII before it accumulates in your session archive.
</Tip>

**Example usage:**

```
privacy-propose(session_url="https://app.fullstory.com.pgm.c5nprx.cc/ui/org/session/abc123")
```

The agent returns something like:

```
Proposed masking rules for the session:
1. Selector: [data-testid="account-email"]   pii_type: EMAIL_ADDRESS
   Reason: Visible email address in account settings panel.
2. Selector: .profile-card__phone            pii_type: PHONE_NUMBER
   Reason: Phone number rendered as plain text in user profile.
```

Pass the selectors you want to keep into `privacy-create` to persist them.

***

### `privacy-create`

Persist element-block rules from CSS selectors in preview scope.

`privacy-create` takes one or more selectors and writes them as rules scoped to **preview sessions only**. Matching elements are blocked in the replay viewer when a session is opened in preview mode, so you can verify behavior before rolling out broadly.

**Key behaviors:**

* `selectors` is a list of objects, each with a `selector` and an optional `pii_type` used to name the rule.
* Optional `block_type` (`mask`, the default, or `exclude`). Unmask rules cannot be created here.
* Rules do **not** affect production capture until explicitly promoted.
* Returns a rule ID for each created rule — save these for `privacy-promote` and `privacy-delete`.
* Works with selectors you wrote yourself, not just those from `privacy-propose`.

<Note>
  Creating a preview rule does not modify previously recorded sessions. It only affects sessions captured after the rule is created and viewed in preview mode.
</Note>

**Example usage:**

```
privacy-create(selectors=[
  {"selector": "[data-testid=\"account-email\"]", "pii_type": "EMAIL_ADDRESS"},
  {"selector": ".profile-card__phone", "pii_type": "PHONE_NUMBER"}
])
```

Response:

```
Created 2 preview rule(s):
- rule_id: prv_001  selector: [data-testid="account-email"]
- rule_id: prv_002  selector: .profile-card__phone
```

***

### `privacy-list`

List element-block (privacy) rules.

`privacy-list` returns element rules across preview and live scopes. Use it to audit masking coverage, confirm a newly created rule is registered, identify promotion candidates, or spot redundant rules.

**Key behaviors:**

* Each entry includes the rule ID, selector, scope, and type.
* `scope_filter` narrows results to `preview` or `all`; `type_filter` narrows to `mask`, `exclude`, or `unmask`.
* System-managed rules are hidden by default. Pass `include_system=true` to include them — these cannot be deleted or promoted.
* Read-only.

**Example usage:**

```
privacy-list()
privacy-list(scope_filter="preview")
```

Response:

```
Active privacy rules:
Preview scope:
- prv_001  [data-testid="account-email"]   type: mask
- prv_002  .profile-card__phone            type: mask

Live scope:
- prv_007  input[name="cc-number"]         type: mask
- prv_008  .checkout__cvv                  type: exclude
```

***

### `privacy-promote`

Promote preview rules to live scope so they apply to all sessions.

`privacy-promote` escalates one or more preview rules to production. After promotion, every new session your application captures masks elements matching the promoted selectors. The rule also becomes protected — it can no longer be deleted through the agent tooling.

**Key behaviors:**

* `rule_ids` is a list, so you can promote several rules in one call.
* Only `mask` and `exclude` rules can be promoted; `unmask` rules are rejected.
* Promotion changes each rule's scope to live in place — confirm the new scope with `privacy-list`.
* Promotion is immediate. Past recordings are not affected; masking applies to sessions captured afterward.

<Warning>
  Promotion is a one-way operation via the agent tools. Once a rule is live, it cannot be demoted or deleted through `privacy-delete`. Review your selectors carefully in preview before promoting.
</Warning>

**Example usage:**

```
privacy-promote(rule_ids=["prv_001"])
```

Response:

```
Promoted 1 rule to live scope (all sessions):
- prv_001  [data-testid="account-email"]  → applies to all new sessions
```

***

### `privacy-delete`

Delete preview rules by ID.

`privacy-delete` removes preview rules permanently. Use it to discard selectors that turned out to be incorrect, overly broad, or no longer needed after a UI change. Only preview rules can be deleted — live rules are protected.

**Key behaviors:**

* `rule_ids` is a list. Every ID must be preview-scoped; passing a live rule ID is rejected.
* Deletion is immediate and irreversible for the rule record itself. You can always recreate a rule with the same selector.
* Does not affect previously captured sessions.

<Note>
  To remove a live rule, use the Privacy section of the Fullstory settings UI. This deliberate friction ensures production masking coverage is never reduced without a conscious manual action.
</Note>

**Example usage:**

```
privacy-delete(rule_ids=["prv_002"])
```

Response:

```
Preview rule prv_002 deleted.
Selector .profile-card__phone will no longer be applied in preview sessions.
```

If you pass a live rule ID:

```
Error: rule prv_007 is in live scope and cannot be deleted via the agent tools.
Use the Fullstory settings UI to manage live rules.
```

***

## URL rules

URL rules scrub sensitive parts of captured URLs — a host, a path segment, or a query parameter's value. They apply to all sessions the moment they're created; there is no preview scope.

### `privacy-url-list`

List URL privacy rules.

Returns every URL rule and its condition and exclusions. Each rule has a `guid` — you'll need it to update or reason about a rule. Read-only.

**Example usage:**

```
privacy-url-list()
```

***

### `privacy-url-create`

Create a URL privacy rule, or update one in place by passing its `guid`.

A rule has a `name` plus a condition (which URLs it applies to) and exclusions (which parts to redact). Cover the common case with the simplified fields; reach for `advanced` only when they can't express the rule.

**Key behaviors:**

* `match_host` and `match_path` are regexes forming the condition (AND'd together). Leave both empty for an unconditional rule that applies to every URL.
* `exclude_query_params` redacts the named query parameters' values while leaving the keys visible. `exclude_path` / `exclude_query` take a raw regex against the path or full query string — use a capture group to redact only part of the match.
* `advanced` is a structured `if`/`exclude` pattern set over host, path, query, `query_param`, and hash. It replaces the simplified fields entirely.
* Goes live for all sessions immediately.

<Warning>
  URL rules have no preview scope — the rule is live the moment it's created. Double-check the pattern before calling, then verify with `privacy-url-list`.
</Warning>

**Example usage:**

```
privacy-url-create(name="scrub-ssn-param", match_host="example\.com", exclude_query_params=["ssn"])
```

This redacts the `ssn` query parameter's value (not its key) on URLs whose host matches `example\.com`.

**Updating a rule:** pass the rule's `guid` (from `privacy-url-list`) to replace it in place. Update is a **full replace, not a merge** — send the complete desired state (name, condition, exclusions), or omitted fields are lost.

```
privacy-url-create(guid="<guid>", name="scrub-ssn-param", match_host="example\.com", exclude_query_params=["ssn", "token"])
```

<Note>
  Built-in rules — the default rule set created when privacy settings are first set up — cannot be updated this way.
</Note>

***

## Network rules

Network rules control whether the request and response bodies of network calls are captured, redacted, or partially allowlisted. Like URL rules, they apply to all sessions immediately and have no preview scope.

### `privacy-network-list`

List network privacy rules.

Returns every network rule, its `url_regex`, and how it handles request and response bodies. Read-only.

**Example usage:**

```
privacy-network-list()
```

***

### `privacy-network-create`

Create a network privacy rule, or update the existing rule for a `url_regex` by passing `overwrite=true`.

A rule matches network calls by `url_regex` and sets how their request and/or response bodies are handled.

**Key behaviors:**

* `request_body` and `response_body` each accept `elide` (the default — redact the whole body) or `whitelist` (keep only named fields). `record` (capture the full body) increases data capture and must be set up manually — it is rejected here.
* When a body mode is `whitelist`, list the field names to keep in `request_allowlist_fields` / `response_allowlist_fields`.
* Rules are keyed by `url_regex` — there is no separate rule ID.
* Goes live for all sessions immediately.

<Warning>
  Network rules have no preview scope — the rule is live the moment it's created. Verify with `privacy-network-list` after creating one.
</Warning>

**Example usage:**

```
privacy-network-create(url_regex="/api/checkout/.*", request_body="whitelist", request_allowlist_fields=["order_id", "status"])
```

This keeps only `order_id` and `status` in the request body of matching `/api/checkout/` calls and redacts everything else.

**Updating a rule:** creating a rule for a `url_regex` that already has one is a no-op by default. Pass `overwrite=true` to replace the existing rule instead of skipping it.

```
privacy-network-create(url_regex="/api/checkout/.*", request_body="whitelist", request_allowlist_fields=["order_id", "status", "total"], overwrite=true)
```
