Ask Claude or Cursor for someone's work email and the agent calls get_lead with reveal_email. One URL, OAuth sign-in, 1 record per lookup.
This page is about setup and prompts. For the REST endpoint and field detail, see Find Work Email. Other clients are on the MCP hub.
Connect the server
The server is https://api.leadocean.io/mcp. It signs in with OAuth 2.1, so there is no key to paste. Create a free account first.
Claude Code. The command format is from the Claude Code MCP docs, September 2026:
claude mcp add --transport http leadocean https://api.leadocean.io/mcp
claude mcp login leadoceanThe second line opens the browser sign-in. Running /mcp inside a session does the same.
Cursor. Add a remote server to mcp.json, in the url form shown in the Cursor MCP docs, September 2026:
{
"mcpServers": {
"leadocean": {
"url": "https://api.leadocean.io/mcp"
}
}
}Cursor starts the OAuth sign-in the first time the server is used. Other clients follow the same pattern, see the LeadOcean MCP docs. Windsurf users: find work emails in Windsurf.
The tool
There is no separate work email tool over MCP. The agent uses get_lead, which the server lists as leadocean_get_lead, with reveal_email set to true. It costs 1 record per call, and reveal_email adds nothing.
| Input | Type | Meaning |
|---|---|---|
linkedin_url | URL | LinkedIn profile URL. The preferred key. |
person_id | string | The id on a search_leads row at meta.source_ids.person_id. Works when there is no LinkedIn URL. |
email | string | An address you already hold, to find the person behind it. |
phone | string | A number you already hold. |
reveal_email | boolean | Default false. True returns every email and phone we hold. |
Send one identifier. There is no name plus company lookup: the agent searches by domain first, then enriches by person_id.
The call returns every contact point, so the agent picks the work address itself. It should keep an address only when its type is work and its status is verified or catch_all_valid. The REST twin, GET /v2/people/email/work, does that filtering for you.
Prompts that work
| Prompt | What the agent calls | Records |
|---|---|---|
| "Find the work email for linkedin.com/in/jane-doe. Report it only if type is work and status is verified or catch_all_valid." | get_lead with linkedin_url, reveal_email true | 1 |
| "Find 5 VPs of Sales at example.com who have a work email, then reveal their addresses into a table." | search_leads with domain, jobLevel, emailType, then get_lead with person_id | 10 at most |
| "How many VPs of Sales in Canada have a work email we can send to? Do not pull anyone." | count_leads | 0 |
Put a record limit in the prompt. "Stop after 25 records" is enough for the agent to hold a batch.
The agent picks the tool from your wording. A question about size goes to count_leads, which is free. A request for an address on a named person goes to get_lead, which costs 1 record. Ask it to skip anyone whose result has no work address, and to say "none held" instead of guessing.
What the agent gets back
The result is one leadocean.person.v1 object. Contact points sit in contact_data, per the enrich docs, September 2026. Values below are placeholders.
{
"success": true,
"data": {
"contact_data": {
"has_email": true,
"email_status": "verified",
"contact_emails": [
{ "email": "jane.doe@example.com", "type": "work", "status": "verified", "verified_batch_date": "2026-09-14" }
],
"contact_current_experiences": [
{ "company_name": "Example Inc", "company_domain": "example.com", "job_title": "Title" }
]
}
},
"meta": { "credits": 1 }
}Nothing is invented: a field we do not hold is null, and an empty contact_emails means we hold no address. Read type first. work is the current employer. work_other is a business address at a different company, usually one the person left, and the likeliest to bounce. verified_batch_date is the date of a verification run, shared by a whole batch.
Free checks first
count_leads, list_enum_values and get_account spend no records. Run them before any paid call.
On 2026-09-30 count_leads returned 5,066 mailable people for jobLevel VP, jobFunction Sales & Business Development, country CA. Mailable means verified, catch_all_valid or catch_all. A fresh run on 2026-10-01 returned a 503 (no_source), so that is the latest count we hold.
Troubleshooting
| Error | Cause | Fix |
|---|---|---|
| 401 | The OAuth sign-in is missing or expired. | Run /mcp in Claude Code and re-authenticate. In Cursor, sign in again from the MCP settings. |
| 402 | The free 1,000 records are spent. The free plan is one-off, it does not reset. | Move to Pro at $499 a month. |
| 429 | Faster than 100 requests per second per key. | Wait one second and retry. Ask the agent to work in small batches. |
| Wrong enum | A filter value is not in the catalogue, such as emailType "business". | Call list_enum_values with name set to email_type and use the exact string. The values are work, work_other, work_any, personal, other, unknown and none. |
FAQ
What does a call cost, and what does a miss cost?
A found person costs 1 record, even when that person holds no work email. A person we hold nothing for costs nothing over MCP, the same as the REST 404. The REST endpoint GET /v2/people/email/work differs: it costs 1 record on every call, including one that finds nothing.
Do I need an API key for MCP?
No. The MCP server uses OAuth sign-in. The REST API uses an x-api-key header. Both draw on the same records.
Can the agent find an email from a name and company?
Not in one call. It searches by company domain and title with search_leads, then calls get_lead with the person_id. For a packaged version of that flow, see the Find Work Email skill.
Free gives you 1,000 records, one-off, no card. Pro is $499 a month, see pricing.
Find your first work email from Claude, free
Free to start. No credit card. 1,000 records to spend whenever you like.
Get your free API key →