Claude Code can run the data half of cold email: size a list, pull verified contacts, and draft a first line for each. It cannot send. This guide is the short version, with the queries and the output.
The split is deliberate. Claude reads a record and writes one sentence about it well. It cannot know who exists. A database answers that with a count you can check, so never ask Claude to find leads from memory.
TL;DR
- Claude Code connects to the LeadOcean MCP server in one command, so it can count, search and enrich leads without you pasting a key.
- The whole build takes about 30 minutes. Sizing the list is free. A 25-lead test run spends about 50 records of your 1,000 free ones.
- Claude writes the first line and the draft. You review, then load the CSV into the sender you already use.
Prerequisites
- A LeadOcean account. Start free: no card, 1,000 records for life, 5 requests a second.
- Claude Code installed and signed in.
- An API key from app.leadocean.io, exported as
$LEADOCEAN_API_KEY, for the REST steps. - A sender that takes a CSV (any sequencer). LeadOcean has no sequencer, so it does not send email.
Step 1: Connect the MCP server
Run one command in your terminal. Claude Code documents claude mcp add --transport http <name> <url> for remote servers (Claude Code docs, October 2026).
claude mcp add --transport http leadocean https://api.leadocean.io/mcpThen open Claude Code and run /mcp. Pick leadocean and sign in. Auth is OAuth 2.1, so you paste no key.
The server exposes 13 tools. Seven are free, including leadocean_count_leads, leadocean_count_companies, leadocean_list_filters and leadocean_list_enum_values. Search, get, phone and export tools spend records.
Step 2: Size the list before you spend anything
Ask for a count first. A count costs 0 records.
Use leadocean_count_leads. Filters: jobLevel VP, jobFunction
"Sales & Business Development", country US. Report the total,
distinctCompanies and the top 5 industries. Spend no records.Enum values are exact strings. If a filter returns nothing, ask Claude to call leadocean_list_enum_values for that field before you retry.
The default count covers only addresses worth sending to: verified, catch_all_valid and catch_all. Say so when you quote the number.
Step 3: Tighten the list before you scale
Add filters until the count looks like a list you would hand-pick. Ask Claude to try three variants and report each total.
Call leadocean_count_leads three times with jobLevel VP, country US:
1) add employeeRange 51-200
2) add industry "Software Development"
3) add technologies ["HubSpot"]
Show the three totals side by side. Spend no records.Do not count with funding, revenue, HQ city or HQ state filters. The count tool rejects them or returns a fake total, so apply those at search time and say the list is narrower.
Pick the variant with a few thousand people, not a few hundred thousand. You will review a sample of every send, and a smaller list keeps that honest.
Step 4: Pull a small test batch
Search 25 people, not 25,000. You are testing the prompt, not the list.
curl -s https://api.leadocean.io/v1/people/search \
-H "x-api-key: $LEADOCEAN_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"jobLevel": ["VP"],
"jobFunction": ["Sales & Business Development"],
"country": ["US"],
"industry": ["Software Development"],
"emailStatus": ["verified"],
"limit": 25
}' > batch.jsonSearch returns a thin projection with no contact points. Each person returned is one record. Page with meta.nextCursor.
You can ask Claude Code to do the same through the MCP tool instead. The REST call is better once you script it, because the file lands on disk and Claude can read it.
Step 5: Enrich the people you will write to
Enrich returns the email (with reveal_email) and the profile detail you need for personalization. Take one input per call: person_id, linkedin_url, email or phone.
curl -s https://api.leadocean.io/v1/people/enrich \
-H "x-api-key: $LEADOCEAN_API_KEY" \
-H "Content-Type: application/json" \
-d '{"person_id": "PERSON_ID_FROM_SEARCH", "reveal_email": true}'Since October 2026, enrich also returns resume_data: past roles, education, certifications and awards when held. That gives Claude real material for a first line. A person we hold nothing for is a 404 and costs nothing.
Stay under 5 requests a second on Free. A short loop with a 250 ms sleep is enough.
Step 6: Write the personalization prompt
Put the rules in a file Claude Code reads every time. Save this as CLAUDE.md in the project folder.
Cold email rules (project instructions)
- Input: enriched/*.json. Output: drafts.csv with columns
email, first_name, first_line, body.
- first_line: one sentence, under 20 words, built from ONE fact in
the record (current title, a past role, a certification).
- If the record has no usable fact, leave first_line empty. Never guess.
- body: 3 sentences. Problem, proof, one question. No links.
- Skip any row whose email_status is not verified.
- Never invent a customer, a metric or a mutual connection.Run it with a short instruction.
Read enriched/*.json and apply the cold email rules. Write drafts.csv.
Then print 3 rows so I can check the first lines.The empty-line rule matters. A blank first line sends a plain email. A made-up one sends a lie.
Step 7: Check the drafts before you send
Run three checks on every batch. They take five minutes.
jq -r 'select(.data.contact_data.email_status != "verified") | .data.profile_data.profile_full_name' enriched/*.json
python3 -c "import csv; r=list(csv.DictReader(open('drafts.csv'))); print(sum(not x['first_line'] for x in r), 'of', len(r), 'first lines empty')"The first line lists people whose status is not verified. None of them should appear in drafts.csv.
- Open 10 random rows and check the first-line fact against the record.
- Count empty first lines. A high share means the filter is thin on profile data, not that the prompt is wrong.
- Confirm every row has
email_statusofverified. Drop the rest.
Version the rules file. When a first line goes wrong, add one rule that prevents it.
Step 8: Review, then hand off
Read every first line in the 25-row batch. Fix the prompt, not the rows, so the next 1,000 improve too.
Then export for the sender. Bulk CSV export is included on Solo and above. Free has no bulk export, so for a test batch use drafts.csv from Step 6. The export body takes filters (the people search filters), limit and an optional preset or columns list (API reference, October 2026).
curl -s -X POST https://api.leadocean.io/v1/exports \
-H "x-api-key: $LEADOCEAN_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"name": "us-vp-sales-verified",
"filters": {"jobLevel": ["VP"], "jobFunction": ["Sales & Business Development"], "country": ["US"], "emailStatus": ["verified"]},
"limit": 1000,
"preset": "full"
}'Poll GET /v1/exports/{id} until it is done, then download the file. An export takes up to 50,000 rows a request and 500,000 a day, and every row costs one record. Read email_1_status in the CSV before you send: there is no refund for bounces.
A 1,000-lead run is about 2,000 records if you search and then enrich: 1,000 from search and up to 1,000 from enrichment. An export with the full preset returns the contact columns in one pass at one record a row. Either way it is past the 1,000 Free records. Solo at $97 a month covers one person at this volume. Agency at $497 a month is for teams, with 5 keys. Paid plans have a fair-use pace, not credits, so there is no overage invoice. See pricing.
What you get
Here is the free count from Step 2, run on 21 October 2026 through leadocean_count_leads. It cost 0 records.
{
"total": 129494,
"totalIsExact": true,
"totalAll": 350517,
"distinctCompanies": 58121,
"distinctCompaniesIsExact": false,
"credits": 0,
"facets": {
"industry": [
{"value": "Financial Services", "count": 12677},
{"value": "Software Development", "count": 10144},
{"value": "Banking", "count": 7813}
]
}
}Read it like this. 129,494 US VPs in sales and business development have an address worth sending to. 350,517 match with no email filter. They sit across about 58,121 employers (an estimate above 40,000).
A search page looks like this. Response shape from the API reference, placeholder values only:
{
"success": true,
"data": [
{
"profile_data": {"profile_full_name": "Jane Doe", "profile_headline": "VP Sales at Acme"},
"contact_data": {
"contact_current_experiences": [{"job_title": "VP Sales", "company_name": "Acme", "company_domain": "acme.com"}],
"has_email": true,
"email_status": "verified"
},
"meta": {"source_ids": {"person_id": "<person_id>"}}
}
],
"meta": {"count": 25, "limit": 25, "credits": 25, "nextCursor": "..."}
}Troubleshooting
| Error | Cause | Fix |
|---|---|---|
| 401 | Missing or wrong x-api-key header | Re-export $LEADOCEAN_API_KEY from app.leadocean.io and retry |
| 429 | Above the plan's rate limit (5 a second on Free, 200 on Agency) | Honor Retry-After, slow the loop, or move up a plan |
| 402 | Records spent (Free is 1,000 for life) | Check GET /v1/usage, then move to Solo at $97 a month |
| Empty results | A filter value is not an exact enum string | Call leadocean_list_enum_values and copy the value |
Search stops with meta.depthCapped | One search pages to 10,000 rows | Narrow the filters and run several searches |
| Export refused | Over 50,000 rows a request or 500,000 a day | Split the export by country or seniority |
FAQ
Can Claude Code send the emails?
No. Claude Code drafts and organizes. Sending needs a sender with mailboxes, warm-up and unsubscribe handling. LeadOcean is the data layer, not a sequencer.
How many records does a test run cost?
About 50 for 25 leads: 25 for the search page and up to 25 for enrichment. Counts and filter lookups are free. See pricing.
Do I need the MCP server, or is REST enough?
REST is enough for a script. MCP is faster for exploring, because Claude can count and fix filters in conversation. Use both.
How do I keep the personalization honest?
Give Claude one source fact per line and a rule to leave the line empty when there is none. Review a sample every run. More patterns are in how to use AI to personalize cold emails.
What comes after the draft?
Sequencing, timing and follow-ups. Read cold email automation to sequences that convert and the cold email prompt.
Give Claude Code a list it can actually write to
Free to start. No credit card. 1,000 records to spend whenever you like.
Get your free API key →