Ask Claude or Cursor for a person's personal email and the agent calls get_lead with reveal_email set to true. One URL, OAuth sign-in, 1 record per lookup.
This page is about setup and prompts. For the REST endpoint and the field list, see Find Personal Email and the API version. Other clients are on the MCP hub. For business addresses, see Find Work Email with MCP.
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 command 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.
The tool
There is no separate personal email tool. The tool is get_lead, listed by the server as leadocean_get_lead. It costs 1 record per call, with or without reveal_email.
| Input | Type | Meaning |
|---|---|---|
linkedin_url | URL | LinkedIn profile URL. Preferred key. |
email | Work email, when you have no LinkedIn URL. | |
phone | string | A number you already hold, to find who it belongs to. |
person_id | string | The meta.source_ids.person_id from a search row. Digits only. |
reveal_email | boolean | Set true to return email addresses and phone numbers. Default false. |
Send one identifier. reveal_email adds no cost, so set it whenever you want the address. It returns every contact point we hold, work and personal, and you pick the personal ones by type.
The REST twin is GET /v2/people/email/personal. It returns only personal addresses.
Prompts that work
| Prompt | What the agent calls | Records |
|---|---|---|
| "Enrich linkedin.com/in/jane-doe with reveal_email and list any personal email addresses." | get_lead with linkedin_url | 1 |
| "How many US VPs of Sales have a personal email on file? Do not pull anyone." | count_leads with emailType: personal | 0 |
| "Find 5 US VPs of Sales, then reveal their personal emails. Stop at 10 records." | search_leads, then get_lead with person_id per row | 10 |
Put the record limit in the prompt. Search returns one record per row, so the third prompt costs 5 for the search and 5 for the lookups.
The agent picks the tool from your wording. A question about size goes to count_leads, which is free. A named person goes to get_lead.
What the agent gets back
The result is a leadocean.person.v1 record, shown here without the REST success wrapper. With reveal_email on, addresses arrive in contact_data.contact_emails[], best first. The shape is from the enrich docs, September 2026. Values below are placeholders.
{
"profile_data": { "profile_url": "https://www.linkedin.com/in/jane-doe" },
"contact_data": {
"has_email": true,
"email_type": "work",
"contact_emails": [
{ "email": "jane@example.com", "type": "work", "status": "verified" },
{ "email": "jane.doe@example.org", "type": "personal", "status": "untested" }
],
"contact_phones": [
{ "phone": "+14155550133", "type": "mobile" }
]
},
"meta": { "credits": 1 }
}Read type before you send. personal means webmail. The email_type flag repeats the type of the best address only, so a person with a work address can still hold a personal one further down.
Treat personal addresses as unchecked. Our verification has never tested one, so status mostly reads untested. The REST personal endpoint drops that field and withholds known-bad addresses instead, as the contact docs explain.
Free checks first
count_leads, list_enum_values and get_account spend no records. Run them before any paid call.
We ran count_leads on 2026-10-01 with emailType: personal, jobLevel: VP, jobFunction: Sales & Business Development and country: US. We set emailStatus to verified, catch_all_valid, catch_all, unknown and untested. It returned total: 8470, totalIsExact: true, credits: 0. Sizing first tells the agent whether a list is worth a record.
Troubleshooting
| Error | Cause | Fix |
|---|---|---|
| 401 | The OAuth sign-in is missing or expired. | Run claude mcp login leadocean or /mcp in Claude Code. 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 the Retry-After seconds and retry. Ask the agent to work in small batches. |
| Wrong enum | A filter value is not in the catalogue, for example Personal instead of personal. | Call list_enum_values with name: email_type and use the exact string it returns. |
FAQ
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.
What does a call cost, and what does a miss cost?
A found person costs 1 record, whether or not a personal address comes back. A person we hold nothing for is a miss and costs nothing over MCP, the same as the REST 404. Filter with count_leads first to avoid paying for empty answers.
Can the agent find a personal email by name?
No. It needs a LinkedIn URL, a work email, a number or a person_id. Search by title and company domain first, then pass the person_id back. The free plan is 1,000 records, one-off, no card. Each lookup uses 1.
Find your first personal email from Claude, free
Free to start. No credit card. 1,000 records to spend whenever you like.
Get your free API key →