Pre-Black Friday: 20% off, for as long as you stayEARLYBFon Solo and AgencyEnds Nov 28Start free

How-to guide

How to Automate List Enrichment Using MCP (Claude Code and the LeadOcean MCP Server)

Connect once, size the job for free, give the agent a record budget, and keep a REST loop for the rows it should not touch.

Get your free API key →Free to start. No credit card. 1,000 records to spend whenever you like.

To automate list enrichment over MCP, connect an AI agent to a hosted data server, tell it the exact tools and the record budget, and let it work the list row by row. The agent does the looping. You keep the rules.

Most guides stop at "add the URL, then ask nicely". That works for ten rows and fails for a thousand. This one adds the parts a technical buyer needs: a free size check, a budget, a stop rule and a REST fallback.

The setup uses Claude Code and the LeadOcean MCP server at https://api.leadocean.io/mcp. Any client that speaks remote MCP over HTTP works the same way.

TL;DR

  • The first run takes about 20 minutes. After that, a new list is one prompt.
  • The walkthrough spends about 60 records: one per person returned or enriched. Counts, filter lookups and 404s are free.
  • Let the agent plan and size. Do the bulk loop in a script, where rate and cost are fixed.

Prerequisites

  • A LeadOcean account from app.leadocean.io. Free is 1,000 records, one-off, no card.
  • Claude Code installed. Cursor, Codex, VS Code and others also work.
  • For Step 5 only: an API key exported as $LEADOCEAN_API_KEY, plus curl and jq.
  • A CSV of targets. Examples use acme.com and Jane Doe as placeholders.
bash
export LEADOCEAN_API_KEY="paste-your-key-here"

Step 1: Connect the MCP server

MCP signs in with OAuth 2.1, so no key is pasted into the client or the chat log. One URL is the whole configuration.

bash
claude mcp add --transport http leadocean https://api.leadocean.io/mcp

Open Claude Code, type /mcp, pick leadocean and approve the sign-in in the browser. The server exposes 13 tools. You can see and revoke the connection under API keys, then Connected apps, in the app. Source: LeadOcean MCP docs, September 2026.

Step 2: Learn what is free and what spends records

Split the 13 tools into two groups before you write a prompt. The agent should know this too.

ToolCost
leadocean_count_leads, leadocean_count_companiesFree
leadocean_list_filters, leadocean_list_enum_valuesFree
leadocean_get_account, leadocean_get_export, leadocean_list_exportsFree
leadocean_search_leads, leadocean_search_companies1 record per row returned
leadocean_get_lead, leadocean_get_company, leadocean_find_phone1 record
leadocean_export_leads1 record per row

A call that finds nobody costs nothing, the same as a REST 404. One record is one person or company you receive.

Step 3: Size the list for free

Ask the agent to count before it pulls anything. This is the cheapest check you will ever run.

text
Use leadocean_count_leads with facets=false. Filters: jobLevel VP,
jobFunction "Sales & Business Development", country US,
employeeRange 51-200. Report total, totalAll and distinctCompanies.
Do not call any tool that spends records.

The default count covers only mailable people (verified, catch_all_valid or catch_all). totalAll is the same filters with no email condition. Say which one you mean when you report a number.

Enum values are exact strings. If the agent guesses Sales, you get zero rows. Tell it to resolve with leadocean_list_enum_values first.

Step 4: Enrich the list with a budgeted prompt

Give the agent the input, the output, the tools it may use and a hard record budget. A prompt with no budget is a prompt that spends your balance.

text
Read targets.csv (columns: company, domain).
For each domain, in order:
1. leadocean_search_leads with domain=[<domain>], seniority ["c_suite","vp"],
   limit 2. Keep rows whose title matches sales, revenue or growth.
2. For each kept person, leadocean_get_lead with reveal_email=true.
3. Write enriched.csv: domain, full_name, title, email, email_status, person_id.

Rules:
- Call leadocean_get_account first and again every 20 domains.
- Stop and report if records left drops under 100 or any call returns 402.
- Never use leadocean_find_phone or export tools in this run.
- Keep only email_status verified, catch_all_valid or catch_all.
- If a search returns nobody, write the domain to misses.csv and move on.

Search returns a thin row with a person_id and flags, not the address. The address comes from get_lead with reveal_email. There is no name-plus-domain lookup, which is why the prompt searches by domain first.

Start with 10 domains. Read enriched.csv, then run the rest.

Step 5: Move the bulk loop to a script

For hundreds of rows, use REST instead. A script has a fixed rate and a fixed cost per row. An agent has neither. If your list is LinkedIn URLs, enrich by linkedin_url.

One LinkedIn URL per line in targets.csv, no header.

bash
while read -r url; do
  curl -s https://api.leadocean.io/v1/people/enrich \
    -H "x-api-key: $LEADOCEAN_API_KEY" \
    -H "Content-Type: application/json" \
    -d "{\"linkedin_url\": \"$url\", \"reveal_email\": true}" \
  | jq -c '{url: "'"$url"'", status: .data.contact_data.email_status, emails: .data.contact_data.contact_emails}'
  sleep 0.25
done < targets.csv > enriched.jsonl

Enrich takes exactly one of linkedin_url, email, phone or person_id. The sleep 0.25 keeps you under 5 requests a second on Free. A person we hold nothing for is a 404 and costs nothing.

Since October 2026 the enrich response also carries career history under resume_data: past roles, education, certifications and awards. Past employers have no company_id yet.

For a filter-defined list rather than a known one, skip both routes. POST /v1/exports takes the people-search filters, up to 50,000 rows a request and 500,000 a day. Bulk CSV export is not on Free. The Exports page in the app shows the record price before you start.

Step 6: Check the output before you send

Read email_status on every row. LeadOcean gives no refund for bounces, so the filter in the prompt is your protection.

bash
jq -c 'select(.status | IN("verified","catch_all_valid","catch_all"))' enriched.jsonl \
  | wc -l

catch_all means the domain accepts everything and the mailbox is unproven. Send those in a smaller, separate batch.

Step 7: Make the run repeatable

An agent run you cannot repeat is a one-off. Save the prompt from Step 4 in your repo as enrich-prompt.md and pin three things in it: the tools allowed, the record budget and the output columns.

Keep person_id in every output row. It is the stable key. On the next run, skip any domain already present in enriched.csv, so a restart does not pay twice for the same person.

Treat the agent's output like any other data pipeline output. Diff it against the last run, spot-check ten rows by hand, and read misses.csv. A high miss rate usually means the input domains are wrong, not that the data is missing.

Two limits are worth writing into the prompt. One search pages to 10,000 rows, and meta.depthCapped tells you when it stopped. And search returns people at the domain, so a domain with no one at VP level returns nothing. Loosen seniority to director before you decide the company is empty.

What the agent is good at here

The agent earns its place in three jobs. It turns a vague brief into valid filters by resolving enum values. It sizes the market before spending. It handles the messy rows: a parked domain, a subsidiary, a title that says "Head of Growth" instead of "VP Sales".

It is a poor loop runner. It spends more tokens per row than a script, it can retry, and it decides its own call count. That is why Step 4 caps the run and Step 5 moves volume to curl.

What you get

Step 3 is free. We ran leadocean_count_leads on 2026-10-21 with jobLevel VP, jobFunction Sales & Business Development, country US and employeeRange 51-200, facets off.

MeasureValue
Mailable people (default filter)18,567 (exact)
Same filters, no email condition60,456
Distinct employers spanned12,192
Records spent0

That is a market, not a list to enrich in one pass. Narrow by industry or add domain before you spend.

An enriched person comes back in this shape. This is the response shape from the API reference, with placeholder values.

json
{
  "success": true,
  "data": {
    "profile_data": { "profile_full_name": "Jane Doe" },
    "contact_data": {
      "has_email": true,
      "email_status": "verified",
      "contact_emails": [
        { "email": "jane.doe@acme.com", "type": "work", "status": "verified" }
      ]
    }
  }
}

Troubleshooting

ErrorCauseFix
401The x-api-key header is missing, or the key is wrong or revoked.Copy a fresh key from the app and reload $LEADOCEAN_API_KEY.
402Your records are spent. On Free the 1,000 are one-off.Check leadocean_get_account or GET /v1/account, or move to a paid plan.
429Requests above your plan's rate limit: 5 a second on Free, 200 on Agency.Wait the Retry-After seconds. Add a sleep to the loop.
Empty resultsA filter value is not an exact enum string, such as Sales for Sales & Business Development.Call leadocean_list_enum_values and pass the exact string.
Search stops, meta.depthCapped trueOne search pages to 10,000 rows.Split by country, industry or headcount band and run several searches.
Export refusedOne export is capped at 50,000 rows a request and 500,000 a day.Split the job across requests and days, or narrow the filters.

FAQ

Should the agent or a script do the enrichment?

Use the agent to size, plan and handle the odd cases. Use a script for volume. A script has a fixed rate and a cost you can compute. An agent decides its own call count.

How many people can I enrich on the free plan?

You have 1,000 records, one-off. A person found by search and revealed costs about 2 records, so roughly 500 people. Enrich by linkedin_url and it is 1 record each.

Does the agent ever see my API key?

Not over MCP. The connection uses OAuth 2.1, and you can revoke it under Connected apps. The REST loop in Step 5 does use a key, which stays in your shell.

Does a paid plan change the workflow?

The data and features are the same. Solo ($97 a month) and Agency ($497 a month) use a fair-use pace instead of credits, and Agency allows 200 requests a second. See pricing.

For the wider picture, read data enrichment for developers and API enrichment and automated prospecting. The term itself is defined in the enrichment glossary. More recipes live in the blog hub.

Connect the MCP server and size your list free

Free to start. No credit card. 1,000 records to spend whenever you like.

Get your free API key →