---
title: "Do Not Contact List via MCP: Block Domains Safely Now"
description: "Do not contact list MCP guide: add and check blocked domains from Claude Code, and keep removals with a human."
date: "2026-09-10"
tags: "mcp, blocked-domains, suppression, compliance, claude-code"
readTime: "24 min read"
author: "FirstSales Team"
slug: "do-not-contact-list-mcp"
canonical: "https://firstsales.io/blog/do-not-contact-list-mcp/"
---

# Blocked domains and do-not-contact lists through MCP

**TL;DR:** Adding a domain to a do-not-contact list only makes sending safer, so an agent connected through MCP can do it. Removing a block should stay with a person using the FirstSales CLI, where the command is explicit and every change can be previewed.

---

## Table of contents

- [One-way doors and two-way doors](#one-way-doors-and-two-way-doors)
- [What a blocked domain does in FirstSales](#what-a-blocked-domain-does-in-firstsales)
- [Why the law cares about this list](#why-the-law-cares-about-this-list)
- [Connect MCP and read what it offers](#connect-mcp-and-read-what-it-offers)
- [Read the current list](#read-the-current-list)
- [Add domains through MCP](#add-domains-through-mcp)
- [Add domains from the CLI with an idempotency key](#add-domains-from-the-cli-with-an-idempotency-key)
- [Campaign-level and workspace-level blocks](#campaign-level-and-workspace-level-blocks)
- [Check whether an address is suppressed](#check-whether-an-address-is-suppressed)
- [Removing a block](#removing-a-block)
- [Contacts delete is a different thing](#contacts-delete-is-a-different-thing)
- [A weekly hygiene routine](#a-weekly-hygiene-routine)
- [A worked example from reply to block](#a-worked-example-from-reply-to-block)
- [Write the policy down for the agent](#write-the-policy-down-for-the-agent)
- [Mailbox rules that reward a clean list](#mailbox-rules-that-reward-a-clean-list)
- [Keep an audit trail you can read in a year](#keep-an-audit-trail-you-can-read-in-a-year)
- [Who may do what](#who-may-do-what)
- [Common mistakes](#common-mistakes)
- [FAQs](#faqs)
- [Conclusion](#conclusion)

---

## One-way doors and two-way doors

Some actions are cheap to undo and others are not. A do-not-contact list teaches a useful lesson about the difference.

Adding a domain to the list is almost always safe. The worst outcome is that you miss a prospect you could have emailed.

Removing a domain is the opposite. The worst outcome is that you email someone who asked you to stop, and that is a legal, reputational and deliverability problem at once.

That asymmetry gives this post its single point of view: let an agent add to the list and keep removals and exports of personal data with a human. The rule is simple enough to write into your agent's instructions in one line.

It also matches how Model Context Protocol (MCP) works. The tool list a server exposes depends on who you are and what you granted, so you decide up front which doors an assistant can open.

The FirstSales Product MCP server is `firstsales-product`, a streamable HTTP server at `https://api.app.firstsales.io/mcp`. It uses OAuth with PKCE, and it does not accept Developer API keys.

In one connected session, the tools we confirmed included `blocked_domains_list` and `blocked_domains_add`. Your own tool list may differ, so call `tools/list` and read what your account exposes before you build on any name.

This post shows how to use those tools for what they are good at, and how to switch to the FirstSales command line interface (CLI) for the rest. All IDs are placeholders such as `org_123` and `ws_123`.

## What a blocked domain does in FirstSales

A blocked domain is a domain FirstSales will not email. The README states it plainly: "A Blocked Domain also blocks its subdomains."

That one sentence has a large effect. Blocking `example.com` also blocks `mail.example.com` and `sales.example.com`.

Use that behavior on purpose. When a company tells you to stop, the right unit is the whole company domain and not a single address.

### What goes on the list

Five groups of domains belong there.

First are people and companies who asked you to stop. Second are your own domains and your customers' domains, which you should not cold email.

Third are partners and competitors you have chosen not to approach. Fourth are domains in regulated or sensitive sectors where your policy says no outreach.

Fifth are free mailbox providers if your campaign targets business addresses only. That choice is yours, and the list is a simple way to enforce it.

For the strategy side of naming rivals in copy, read [naming competitors in cold email](/blog/naming-competitors-in-cold-email).

### What stays off the list

The list is a blunt tool. Do not use it to hold individual bounced addresses or low-scoring leads.

Bounces belong to your verification process. The posts on [email verification before sending](/blog/email-verification-before-sending) and [cold email bounce rate](/blog/cold-email-bounce-rate) cover that.

## Why the law cares about this list

A do-not-contact list is the operational form of an opt-out. The law treats a request to stop as a deadline.

The US Federal Trade Commission's [CAN-SPAM compliance guide](https://www.ftc.gov/business-guidance/resources/can-spam-act-compliance-guide-business) says you must honor opt-out requests within 10 business days. It also states that the law makes no exception for business-to-business email.

The same guide says each separate email in violation can carry penalties of up to $53,088. A list that fails to stop a repeat send multiplies that figure by every message.

Google adds a deliverability angle. Its [email sender guidelines](https://support.google.com/a/answer/81126) tell senders to keep the user-reported spam rate below 0.10% and to prevent it from ever reaching 0.30%.

Someone who asked you to stop and then receives another email is the most likely person to click "report spam." A reliable block list protects both your legal position and your reputation.

I am not giving legal advice. Rules differ by country, and the wave of laws covering email changes often, so the posts on [whether cold email is legal in 2026](/blog/is-cold-email-legal-2026) and [cold email compliance penalties](/blog/cold-email-compliance-penalties) are better starting points.

## Connect MCP and read what it offers

If you have not connected Claude Code to FirstSales yet, the post on [connecting FirstSales MCP to Claude Code](/blog/firstsales-mcp-claude-code-setup) walks through it.

In short, the package ships a config file that points at the server. The server is `firstsales-product`, and authentication is OAuth, so Claude Code opens a browser window for you to approve access.

You never paste an API key for MCP. Developer API keys are not accepted by the MCP server, and MCP tokens are not Developer API credentials.

### Read tools/list first

The protocol defines a way to ask the server what it offers. The [MCP tools specification](https://modelcontextprotocol.io/specification/2025-11-25/server/tools) describes `tools/list` and notes that a server can announce when its list changes.

Ask your assistant to show the FirstSales tool list, then look for the blocked-domain tools by name. If they are missing, your grant does not include them, and you should not build a workflow around them.

> "For trust and safety and security, there SHOULD always be a human in the loop with the ability to deny tool invocations." (MCP specification, tools section, version 2025-11-25, as of October 2026)

That line is a design principle worth borrowing. Keep a person able to say no to any tool call that changes the list.

For a broader view of what to expose and what to hold back, read [which MCP tools an agent should get](/blog/mcp-tool-permissions-sales).

## Read the current list

Start every session with a read. Ask Claude Code to list the blocked domains in your workspace through the MCP tool.

```text
Using the FirstSales MCP tools, list the blocked domains for this workspace.
Show them as a plain list. Do not add or change anything.
```

The tool is read-only, so this prompt is safe to run any time. If you prefer a terminal, the CLI does the same read.

```bash
firstsales blocked-domains list --org org_123 --workspace ws_123 --json
```

Save the output before you change anything. A before-and-after pair makes the change auditable.

```bash
firstsales blocked-domains list --org org_123 --workspace ws_123 --json > blocked-before.json
```

### Why the read comes first

A list you have not read is a list you might duplicate or contradict. Reading first tells you whether the domain is already blocked.

It also anchors the agent in facts. An assistant that has just printed the real list is less likely to invent entries.

## Add domains through MCP

Adding is the job that fits an agent well. Give the assistant the domains and a reason, and let it call the add tool.

```text
Using the FirstSales MCP tools, add these domains to the workspace blocked list:
acme-example.com, rival-example.io
Reason: both asked us to stop on 2026-10-07.
Before adding, list the current blocked domains and skip any that already exist.
After adding, list them again and show me what changed.
```

The prompt asks for a read before and a read after. That keeps the change visible in the transcript.

Two rules make this safe. The domains come from you and not from the model's imagination, and the model reports exactly what changed.

### Do not let the agent decide who to block

An assistant should not infer domains from a reply it read. Paste the domain from a message you verified.

A model might guess `acme.com` when the sender used `acme-corp.io`. A wrong block costs you a prospect, and a missed block costs you a complaint.

### Check the tool's input before you trust it

Tool schemas differ. Ask the assistant to show the tool's input fields before the first call, then confirm that it will send domains as plain hostnames without a scheme or a path.

The README example for the CLI uses bare hostnames such as `competitor.com`. Follow the same style.

## Add domains from the CLI with an idempotency key

The CLI covers the same job with more control. It is the right choice for batches, scripts and anything you want in version control.

```bash
firstsales blocked-domains add competitor.com rival.io \
  --org org_123 --workspace ws_123 \
  --idempotency-key block-001
```

The README requires `--idempotency-key` for `add`: "the API rejects the call without it; the CLI never makes one up." Pick a key that names the batch, such as `block-2026-10-08-optouts`.

For a long list, use a file.

```bash
firstsales blocked-domains add --data-file domains.json \
  --org org_123 --workspace ws_123 \
  --idempotency-key block-002
```

The README shows this form and does not define the file schema, so check the OpenAPI contract at `developer.firstsales.io` for the exact body shape before you write the file.

### Preview the request

Add `--dry-run` to see the method, URL, redacted headers and body without sending anything. It does not use auth or the network.

```bash
firstsales blocked-domains add --data-file domains.json \
  --org org_123 --workspace ws_123 \
  --idempotency-key block-002 --dry-run
```

Read the URL and body before you run the real command. Check the org, the workspace and every domain.

### Why the idempotency key matters

A retry after a timeout should not create a mess. The key lets the API recognise the same operation sent twice.

Reuse a key only for a retry of the same batch. A different batch needs a different key.

### Verify afterwards

Read the list again and compare it with the earlier snapshot.

```bash
firstsales blocked-domains list --org org_123 --workspace ws_123 --json > blocked-after.json
diff blocked-before.json blocked-after.json
```

The diff should show exactly the domains you meant to add. Anything else is a reason to stop and investigate.

## Campaign-level and workspace-level blocks

There are two scopes, and the difference matters. A workspace block applies to everything in the workspace, while a campaign block applies to one campaign.

The README says: "Add `--campaign <id>` to any of these to manage that campaign's own Blocked Domains; a campaign cannot lift a workspace block."

```bash
firstsales blocked-domains list --org org_123 --workspace ws_123 --campaign camp_123 --json
```

### Pick the right scope

Use the workspace scope for opt-outs, customers and your own domains. Those people should never get email from any campaign.

Use the campaign scope for exclusions that only make sense in one campaign. For example, a domain you plan to approach next quarter with a different message.

### The one-way property

Because a campaign cannot lift a workspace block, a workspace block wins every time. This is a safety property: nobody can accidentally unblock a domain by editing a single campaign.

It also means the workspace list deserves the most care. A mistake there affects every campaign you run.

## Check whether an address is suppressed

Sometimes you do not want to change the list. You want to know whether an address would be skipped.

The CLI has `suppression check` for that.

```bash
firstsales suppression check jane@acme.com acme.com --org org_123 --workspace ws_123
firstsales suppression check --data-file values.json --org org_123 --workspace ws_123 --json
```

According to the README, it checks up to 100 named addresses or domains and shows `value`, `suppressed` and `reason` for each. It adds: "There is no list or export."

### What "no list or export" means

You can ask about specific values, but you cannot ask for everyone who is suppressed. That is a deliberate privacy boundary.

For your workflow, it means the check works well as a pre-import filter. Run your prospect list through it in batches of 100 before you load the list.

### A batch filter

Split a long list into chunks of 100 and check each chunk. The sketch below is a shell outline and not a tested script, so adapt it to your file format.

```bash
# values-001.json, values-002.json ... each holds { "values": [ up to 100 items ] }
for f in values-*.json; do
  echo "== $f"
  firstsales suppression check --data-file "$f" --org org_123 --workspace ws_123 --json
done
```

Read the output for any entry whose `suppressed` field is true, and remove those people from the file before import. The related post on [importing leads and building lists from the terminal](/blog/import-leads-from-terminal) covers the import side.

### Keep a log of what you removed

Write down the reason for each removal. If someone asks why you did not email them, you want an answer.

Keep the log free of unneeded personal data. A hashed or partial record is often enough.

## Removing a block

Removal is the one-way door in reverse, and it deserves ceremony. The CLI command exists.

```bash
firstsales blocked-domains remove competitor.com --org org_123 --workspace ws_123
```

This is the README form. The command table in the README shows it as a `DELETE` call to the blocked-domains endpoint.

The README states a general rule that `DELETE` commands require `--confirm`, while its command table does not mark this one as destructive. Run `firstsales blocked-domains remove --help` to see what your installed version requires, and treat the command as consequential either way.

### When removal is correct

Removal is right in a few cases. You added a domain by mistake, a partner relationship ended and the domain now belongs on your prospect list, or the person who opted out explicitly asked to hear from you again.

The last case needs a record. Keep the message that shows the request.

### When removal is wrong

Do not remove a block because a campaign is underperforming and the list looks long. Do not remove a block because an agent suggested it.

Do not remove a block to hit a lead target. A domain that opted out is not a lead.

### Why removal stays with a human

An agent can be wrong in a confident way, and a wrong removal is the expensive direction. A person reading the exact domain and the reason is the cheapest safeguard.

Set your agent's permissions so that `blocked-domains remove` always prompts. Allow `blocked-domains list` and `suppression check` freely.

Guardrail ideas for the wider agent are in [guardrails for email-sending agents](/blog/email-agent-guardrails).

## Contacts delete is a different thing

Do not confuse a block with a delete. A blocked domain stops sending to a domain. `contacts delete` removes a contact record, and it cannot be undone.

```bash
firstsales contacts delete --org org_123 --workspace ws_123 --contact contact_123 --confirm
```

The `--confirm` flag exists because deletion is destructive. Confirm the flag name with `firstsales contacts delete --help` for your version.

### Why delete is a poor opt-out tool

Deleting a contact can remove the record that proves you should not email them. If the same address returns through a later import, nothing stops the next send.

A block on the domain keeps working after the contact is gone. For a person who opted out, block first, then decide whether to delete.

### Privacy requests

Some people ask for their data to be erased. That is a separate legal process from an opt-out, and it needs its own handling.

Keep the opt-out record you need to prove compliance, and follow your privacy policy for the rest. This post does not replace advice from your lawyer.

## A weekly hygiene routine

A list that nobody reviews decays. A short weekly routine keeps it sharp.

Monday, ask your assistant to list the blocked domains and print the count. A sudden drop is an alarm.

Then paste any opt-out replies from the week, and add their domains through the MCP tool or the CLI. The posts on [the reply handling playbook](/blog/reply-handling-playbook) and [sorting your reply inbox from Claude Code](/blog/reply-inbox-claude-code) show how to find those replies.

Then run `suppression check` on the next campaign's list before import. Last, save the before and after files to your repository.

### Make the routine boring

Boring is the goal. A routine that takes ten minutes and never surprises you is a routine you will follow.

If you want it on a schedule, cron works well for the read steps only. Keep the add and remove steps manual.

## A worked example from reply to block

A walkthrough shows how the pieces connect. The domains and dates below are invented for illustration, and no real company is involved.

On a Tuesday, a reply arrives from a person at `northwind-example.com` saying "please remove us, we do not want these emails." You read it yourself and confirm the sender domain in the message headers.

### Step one: read the list

You ask Claude Code to list the blocked domains through the MCP tool. The domain is not there, so you proceed.

### Step two: add through MCP

You paste the verified domain and a reason into the prompt from earlier. The assistant calls the add tool, lists the domains again and shows you the difference.

You read the difference. One new entry, the one you meant to add.

### Step three: protect the next list

Before the next import, you run `suppression check` on the prospect file in chunks of 100. Any value with `suppressed` set to true comes out of the file.

This catches the case where a colleague at the same company sits in your next batch. The block on the domain does the real work, and the check gives you early notice.

### Step four: log it

You record the date, the domain, the reason and the place where the opt-out reply lives. Total time is a few minutes.

If a regulator or a customer ever asks why a domain was blocked, that record is your answer. Without it, you are reconstructing events from memory.

## Write the policy down for the agent

An agent follows the rules you give it. Put the do-not-contact rules in a short policy file in your repository, and tell the agent to read it first.

A good policy file is plain. It lists who may be added, who may be removed and who must approve each step.

Here is a starting point you can adapt.

```text
Do-not-contact policy for workspace ws_123
- Add: any verified opt-out domain, any customer domain, any domain on the legal hold list.
- Never infer a domain. Use the domain the human pasted and repeat it back before writing.
- Remove: never. Ask a human to run blocked-domains remove after reading the reason.
- Always list before and after, and show the diff.
- Never run contacts delete. Never create or print API keys.
```

Six lines do most of the work. They state the one-way rule, the verification rule and the key rule in terms an assistant cannot misread.

### Review the policy when your tool list changes

MCP servers can change their tool list over time, and the protocol includes a way for a server to announce that change. After a client update or a new grant, run `tools/list` again and compare it with your policy.

If a new tool can remove blocks, decide before you use it whether the agent may call it. The default answer is no.

The risks of tool lists that change quietly are covered in [MCP security for outbound](/blog/mcp-security-outbound).

## Mailbox rules that reward a clean list

A clean block list helps with the big mailbox providers too. Both of them now ask bulk senders to make leaving easy.

Google's sender guidelines require marketing and subscribed mail to support one-click unsubscribe, which is specified in [RFC 8058](https://www.rfc-editor.org/rfc/rfc8058). Microsoft's [Outlook requirements for high-volume senders](https://techcommunity.microsoft.com/blog/microsoftdefenderforoffice365blog/strengthening-email-ecosystem-outlook%E2%80%99s-new-requirements-for-high%E2%80%90volume-senders/4399730) took effect on May 5, 2025.

When a recipient unsubscribes, your system should remember it. The block list is where that memory lives for company-level requests.

Pair the list with monitoring. [Google Postmaster Tools](/blog/google-postmaster-tools-cold-email) shows the spam rate that a leaky list pushes up.

If the rate rises after a send, pause the campaign first and investigate second, as described in [starting, pausing and resuming campaigns from the CLI](/blog/start-pause-campaigns-cli).

### What a leak looks like

Signs that your list leaks are simple. Opt-out replies from people you thought you had blocked, complaints from domains on the list, and a spam rate that climbs without a copy change.

Each sign has a different cause. A reply from a blocked domain can come from a second domain the company uses, a complaint can come from a forwarded message, and a rising rate can come from a bad segment elsewhere.

Treat every one as a prompt to read the list, run `suppression check` on the person and look at the campaign scope.

## Keep an audit trail you can read in a year

A list is only as trustworthy as its history. Store the before and after files from every change in a folder in your repository, named by date.

A simple naming scheme works: `blocked-2026-10-08-before.json` and `blocked-2026-10-08-after.json`. Add a one-line note in the commit message with the reason and the source of the request.

### What to keep and what to leave out

Keep the domain, the date, the reason and a pointer to the opt-out message. Leave out names, phone numbers and any other personal data you do not need.

Less personal data in the log means less to protect and less to erase later. The goal is proof that you acted, not a second copy of the conversation.

### Review the trail once a quarter

Open the folder every quarter and scan for patterns. Many opt-outs from one campaign point at a targeting problem, while many opt-outs after one step point at a copy problem.

The list is a signal as well as a shield. Use it to improve the campaigns that feed it.

When the numbers worry you, compare against your own history. The same campaign last month is the fairest benchmark you have.

## Who may do what

The table summarizes the permissions this post argues for. A check mark means an agent may act alone, and a cross means a person must approve.

| Action | Surface | Agent alone | Why |
| --- | --- | --- | --- |
| List blocked domains | MCP or CLI | ✓ | Read-only |
| Check suppression for specific values | CLI | ✓ | Read-only, 100 values per call |
| Add a domain you supplied | MCP or CLI | ✓ | Makes sending safer |
| Add a domain the agent inferred | MCP or CLI | ✗ | Wrong guesses cost prospects |
| Remove a blocked domain | CLI | ✗ | May re-enable email to an opt-out |
| Delete a contact | CLI | ✗ | Cannot be undone |
| Create an API key | CLI | ✗ | Changes who can act |

### The decision as a diagram

The diagram shows how an opt-out reply should move through the system.

```mermaid
flowchart TD
    A[Opt-out reply arrives] --> B{Domain verified by a human?}
    B -- yes --> C[Add domain to workspace block list]
    B -- no --> D[Human checks the sender domain]
    D --> C
    C --> E[List blocked domains again]
    E --> F{Domain now present?}
    F -- yes --> G[Log date, domain, reason]
    F -- no --> H[Stop and investigate]
    G --> I[Run suppression check on next list]
```

Every path ends in a verified read. The agent never writes without a read before it and a read after it.

## Common mistakes

Most list failures come from a few habits. Each is easy to fix once you can name it.

### Blocking only the address

A person at a company opts out, you block one address, and a colleague receives the next sequence. Block the domain when the company asked you to stop.

### Assuming a campaign block protects the workspace

A campaign block covers one campaign. A different campaign can still email the domain, so use the workspace scope for opt-outs.

### Letting an agent infer the domain

Models guess. Paste the verified domain and ask the agent to repeat it back before it writes.

### Skipping the idempotency key

The CLI add command needs one. Without it, the API rejects the call, and a made-up reused key can mask a real second batch.

### Removing a block to hit a number

A shorter list is not a better list. Never remove a block without a recorded reason.

### Treating delete as an opt-out

`contacts delete` cannot be undone and can erase your proof. Block first.

### Putting credentials in the prompt

Never paste an API key into a prompt. MCP uses OAuth, and the CLI reads `FIRSTSALES_API_KEY` from the environment.

### Forgetting the pre-launch gate

A clean block list is one of several checks. Run `campaigns readiness` and `campaigns send-test-email` before `campaigns start`, as covered in [the pre-launch checklist from the terminal](/blog/campaign-readiness-check-cli).

For a deeper look at the cost of unsupervised sending, read [unsupervised AI outbound](/blog/unsupervised-ai-outbound) and [human-in-the-loop cold email](/blog/human-in-the-loop-cold-email).

## FAQs

### What does a blocked domain do?

FirstSales will not email that domain. According to the README, a blocked domain also blocks its subdomains.

### Can MCP add a blocked domain?

In one connected session we confirmed `blocked_domains_add` and `blocked_domains_list`. Your tool list depends on your tenant and grant, so check `tools/list`.

### Can MCP remove a blocked domain?

Do not assume it. Use `firstsales blocked-domains remove` in the CLI, where a person can read the exact command first.

### Does the add command need an idempotency key?

In the CLI, yes. The README says the API rejects the call without one and the CLI never makes one up.

### What is the difference between a campaign block and a workspace block?

A workspace block applies everywhere in the workspace. A campaign block applies to one campaign, and a campaign cannot lift a workspace block.

### How do I check if an address is suppressed?

Run `firstsales suppression check <values> --org <org> --workspace <workspace>`. It accepts up to 100 addresses or domains and returns `value`, `suppressed` and `reason`.

### Can I export the full suppression list?

No. The README says there is no list or export for suppression checks.

### How long do I have to honor an opt-out?

The FTC's CAN-SPAM guide says within 10 business days. Check your local law too, because rules differ by country.

### Does CAN-SPAM apply to business email?

Yes. The FTC guide states the law makes no exception for business-to-business email.

### What is the maximum penalty per email?

The FTC guide says each separate violating email can carry penalties of up to $53,088.

### Should I delete a contact who opted out?

Block the domain first. Deleting removes the record and cannot be undone, which can erase proof of the opt-out.

### Is `contacts delete` reversible?

No. It needs `--confirm` and cannot be undone.

### Can an AI agent decide which domains to block?

It should not. Give it verified domains from a source you checked, and have it repeat them back before it writes.

### What spam rate should I stay under?

Google says to keep the user-reported rate below 0.10% and never let it reach 0.30%.

### How do I preview a block-list change?

Add `--dry-run` to the CLI command. It prints the request without sending it and uses no auth or network.

### Should free mailbox domains be on the list?

Only if your policy targets business addresses. It is your choice, and the block list is a simple way to enforce it.

### How often should I review the list?

Weekly is a good start. Read the list, add the week's opt-outs and run `suppression check` on the next campaign list.

### Does MCP need an API key?

No. MCP uses OAuth, and Developer API keys are not accepted by the MCP server.

### Where do I create the campaign first?

Use `firstsales campaigns create`, then use MCP to edit and watch it. Creating a campaign through MCP is not confirmed.

### What must I run before starting a campaign?

Run `campaigns readiness` and `campaigns send-test-email` before `campaigns start`.

---

## Conclusion

A do-not-contact list is the smallest tool in your outbound stack and one of the most important. Treating adds and removals differently is how you keep it trustworthy.

These are the takeaways.

- Let an agent add domains you verified, through MCP or the CLI, with a read before and a read after.
- Keep removals, deletes and key creation with a person, and make your agent prompt for each.
- Use the workspace scope for opt-outs, because a campaign cannot lift a workspace block.
- Check suppression in batches of 100 before you import a list, and remember there is no export.
- Honor opt-outs within 10 business days, and run `campaigns readiness` and `campaigns send-test-email` before every `campaigns start`.
- `contacts delete` and other delete commands cannot be undone, and API keys never belong in a prompt.

To try it, connect MCP, ask your assistant to list the blocked domains, and write down what you see. Then read [the reply inbox post](/blog/reply-inbox-claude-code) to learn how opt-outs reach the list in the first place.