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

How-to guide

How to Build a Lead List (in Windsurf)

One mcp_config.json entry, a free count, a five-row spot-check, then a CSV export. No API key pasted into chat.

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

TL;DR

  • Windsurf reaches LeadOcean through one mcp_config.json entry and a browser sign-in. You size the audience for free, spot-check five rows, then pull it as a CSV.
  • It takes about 20 minutes. The count is free and the spot-check spends 5 of your 1,000 free records. Bulk CSV export is not on Free: the 200-row export needs Solo ($97 a month) or Agency ($497 a month).
  • Counts, filter lookups and enum lookups cost nothing. Only rows you receive count.

Prerequisites

  • A LeadOcean account from app.leadocean.io. The free plan has no card and 1,000 records, one-off.
  • Windsurf installed. The Windsurf MCP docs, October 2026, do not limit remote HTTP servers to a paid plan. Enterprise users must turn MCP on in settings, and team admins can allowlist servers.
  • For the export step: a LeadOcean paid plan (bulk CSV export is included on Solo and Agency, not on Free), and a key in your shell as $LEADOCEAN_API_KEY, plus curl and jq. The export reveals emails, so the key needs the enrich scope.
bash
export LEADOCEAN_API_KEY="paste-your-key-here"

The MCP steps need no key. Setup details for the editor are on Connect LeadOcean to Windsurf.

Step 1: Add the LeadOcean MCP server

Add one remote entry to Cascade's MCP config. In the Cascade panel, open the ... menu, then the Open MCP config file icon in the MCPs section. Windsurf's docs say a remote HTTP server needs a serverUrl or url field.

json
{
  "mcpServers": {
    "leadocean": {
      "serverUrl": "https://api.leadocean.io/mcp"
    }
  }
}

Do not add a headers block. LeadOcean signs you in with OAuth 2.1 in the browser, so there is nothing to paste. The Windsurf docs say OAuth is supported but do not show the Cascade prompt, so check the server's status in the MCPs section after you save.

That config is for the legacy Cascade agent. Devin Local, the default agent for new tabs, reads the Devin CLI config files instead. The Devin CLI docs add a remote server with one command.

bash
devin mcp add leadocean https://api.leadocean.io/mcp

Step 2: Check the tools and your balance

The server exposes 13 leadocean_ tools. Seven never spend records: the two counts, filter list, enum list, account, get export and list exports. Cascade allows 100 tools in total, so LeadOcean uses 13 of them.

Ask for your balance before anything else.

text
Use leadocean_get_account. Tell me my plan and how many records I have left.
Do not search anything.

The REST route for the same check is free too.

bash
curl -s https://api.leadocean.io/v1/account \
  -H "x-api-key: $LEADOCEAN_API_KEY" | jq

To fence off spending, add "disabledTools": ["leadocean_export_leads"] to the server entry until you reach Step 5. Remove it when you are ready to export.

Step 3: Size the audience for free

Write the audience as filters. This example is VP-level sales leaders at US software companies with 51 to 200 staff. Resolve the industry string first, because filters take exact values.

text
Use leadocean_list_enum_values for industry with q "software". Then use
leadocean_count_leads with jobLevel ["VP"], jobFunction ["Sales & Business Development"],
industry ["Software Development"], employeeRange ["51-200"], country ["US"],
facets false. Report the total and say which email statuses it counted.
Do not call any tool that spends records.

The REST version is a people search with count=true as a query parameter and limit at 1. It returns meta.total and no rows.

bash
curl -s "https://api.leadocean.io/v1/people/search?count=true" \
  -H "x-api-key: $LEADOCEAN_API_KEY" -H "content-type: application/json" \
  -d '{
    "jobLevel": ["VP"],
    "jobFunction": ["Sales & Business Development"],
    "industry": ["Software Development"],
    "employeeRange": ["51-200"],
    "country": ["US"],
    "emailStatus": ["verified", "catch_all_valid", "catch_all"],
    "limit": 1
  }' | jq '.meta'

If the number is too big or too small, change one filter and count again. Counting is free however often you do it.

Step 4: Spot-check five rows

Look at real rows before you buy 200 of them. Five records is a cheap test of the match. Search returns thin records and no addresses.

text
Use leadocean_search_leads with the same filters and limit 5. Show a table of name,
job title, company, company domain and email_status. Flag any title that is not a
sales leader so I can add it to excludeTitle.

Each person returned costs one record, so this step spends 5. The REST version is the same body with limit set to 5 and no count. Add excludeTitle (for example ["assistant","intern"]) if the sample shows noise. Search pages take limit 1 to 100 and continue with cursor.

Step 5: Export the list to CSV

Use an export for the bulk pull. Chat is a poor place for hundreds of rows, and an export writes one file. Bulk CSV export is included on Solo and Agency, not on Free. An export takes up to 50,000 rows a request and 500,000 a day. Each row costs one record whatever the columns, and a full export reserves twice the limit up front, then releases what it does not use.

bash
curl -s https://api.leadocean.io/v1/exports \
  -H "x-api-key: $LEADOCEAN_API_KEY" -H "content-type: application/json" \
  -d '{
    "name": "US sales VPs at software companies",
    "filters": {
      "jobLevel": ["VP"],
      "jobFunction": ["Sales & Business Development"],
      "industry": ["Software Development"],
      "employeeRange": ["51-200"],
      "country": ["US"],
      "emailStatus": ["verified", "catch_all_valid", "catch_all"]
    },
    "limit": 200,
    "preset": "full"
  }' | tee export.json | jq '.data | {id, status, requested, perRow, remaining, pollAfter}'

The job runs in the background. Poll every pollAfter seconds, then download when the status is done.

bash
ID=$(jq -r '.data.id' export.json)
curl -s https://api.leadocean.io/v1/exports/$ID -H "x-api-key: $LEADOCEAN_API_KEY" | jq '.data.status'
curl -s https://api.leadocean.io/v1/exports/$ID/download -H "x-api-key: $LEADOCEAN_API_KEY" -o leads.csv

To stay in Windsurf, ask for it in one prompt. The tools leadocean_export_leads and leadocean_get_export start the job and read its status.

text
Start a leadocean export with the filters above, limit 200, preset full. Poll it
with leadocean_get_export until it is done, then give me the download link.

Before you load the CSV anywhere, read the email_status column. Verified and catch_all_valid addresses are the safest to send to. Bounced emails are not refunded, so drop anything you do not trust.

The LeadOcean app has the same export on its Exports page. It has a filter builder, a column picker, the record price before you start and a Download button.

What you get

The Step 3 run is real. On 21 October 2026 we ran leadocean_list_enum_values and leadocean_count_leads with the filters above. Both are free. The enum lookup for "software" returned seven values, among them Software Development:

json
{
  "name": "industry",
  "total": 534,
  "matched": 7,
  "values": [
    "Computer Software",
    "Data Security Software Products",
    "Desktop Computing Software Products",
    "Embedded Software Products",
    "IT System Custom Software Development",
    "Mobile Computing Software Products",
    "Software Development"
  ]
}

The count returned this.

json
{
  "total": 1649,
  "totalIsExact": true,
  "totalAll": 4141,
  "distinctCompanies": 1125,
  "credits": 0,
  "defaults": "Counted only addresses worth sending to (emailStatus: verified or catch_all_valid or catch_all), which is this tool's default.",
  "sample": 1,
  "hasMore": true
}

The total describes the mailable audience, meaning verified, catch_all_valid or catch_all emails. It is not everyone matching the other filters: totalAll shows 4,141 with any email status or none. The 1,649 people work at 1,125 companies. The example exports 200 of them. Your number will differ as the data refreshes monthly.

We did not run the spending steps for this page. The export request returns HTTP 202 and a job. This is the response shape from the API reference, with placeholder values.

json
{
  "success": true,
  "data": {
    "id": "<export id>",
    "name": "US sales VPs at software companies",
    "status": "queued",
    "requested": 200,
    "perRow": "<records per row>",
    "remaining": "<records left after this reservation>",
    "pollAfter": "<seconds>",
    "file": null
  }
}

The finished download is a plain .csv, one row per person. Records are reserved when the export is admitted, and rows never written are released. The run should cost about 205 records: 5 for the spot-check and 200 for the export. On a paid plan those records count toward the fair-use pace, not a credit balance.

Troubleshooting

ErrorCauseFix
401Missing, wrong or revoked key on a REST call, or the MCP sign-in was not approvedRe-copy the key from app.leadocean.io and re-export $LEADOCEAN_API_KEY. For MCP, repeat the browser sign-in.
429Above your plan's rate limit (5 requests a second on Free, 200 on Agency), a fair-use window reached, or an export ceiling reachedWait the Retry-After seconds. Send full pages of 100 rather than more calls.
402Free plan: the 1,000 records are spentCheck GET /v1/account, then move to Solo ($97 a month), which also includes bulk CSV export. Free records do not reset.
400, or a count of 0A filter value outside the catalogue, such as industry: "Software"Resolve it with leadocean_list_enum_values and pass the exact string.
400 export_limit_rowslimit is above 50,000 rows for one exportSplit the audience by country or headcount band and run several exports.
403The key lacks the enrich scope, which a full export needsUse a key with the scope, or set "preset": "search".

FAQ

How many records does a lead list cost?

One record per person returned, or per export row. Sizing is free, so the plan is: count, spot-check five, then export. The example spends about 205 records.

Do I need an API key in Windsurf?

Not for the MCP steps. The server uses OAuth sign-in and you paste nothing into the chat. The REST steps read $LEADOCEAN_API_KEY from your shell.

Why export instead of searching in chat?

A search returns at most 100 rows a page and thin records without addresses. An export writes one CSV with the contact columns. One row costs one record either way.

Can I use the free plan for this?

For Steps 1 to 4, yes. Free is 1,000 records, one-off, with search and enrich both available. Bulk CSV export is not on Free. Solo ($97 a month) includes it, and Agency ($497 a month) allows 50,000 rows a file.

Can I do this in another editor?

Yes. The same MCP URL works in other clients. See the recipes for Cursor, VS Code and Claude. Plans are on pricing.

More recipes live in the blog hub.

Build your first lead list in Windsurf today

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

Get your free API key →