Playbooks · Skill & signal

Cursor: Enrich a CSV That's Already in Your Repo

Point Cursor's agent at a CSV in your working tree and let it call RichAPI through MCP, row by row, writing an enriched copy back to disk. No pipeline, no UI, no ETL. The risk is an agent that decides to loop over 4,000 rows unsupervised, so this page is mostly about bounding that.

Last updated September 22, 2026

Pattern: CSV in the repo → Cursor agent reads it → agent calls the MCP tools (email_finder, then email_verifier on hits) → agent writes enriched.csv alongside. You review the diff like any other change, because it is one.

Credit math: A 300-row CSV: email_finder at 5 credits bills only on rows that resolve. At a 60% hit rate that is 180 × 5 = 900 credits, and 120 misses cost zero because email_finder is waterfall. email_verifier at 2 credits on 180 rows is 360 credits. 1,260 total. Ask the agent to run the first 20 rows and stop; multiply what that actually costs by 15 instead of trusting the 60%.

ROI math: The comparison is not against another enrichment vendor, it is against the afternoon you would spend writing a script, a rate limiter and a resume file for a list you will enrich once. If the list is recurring, write the script; the agent is for one-offs and for the twenty-row spike that tells you whether the script is worth writing. Credit tiers on /pricing.

Owned internally by: The developer with the repo open. Nobody else needs to know this happened.

Best for: One-off lists that arrived as a file, conference exports, a sales spreadsheet someone dropped in Slack, and the exploratory pass before you commit to building a pipeline.

example
# ~/.cursor/mcp.json — the whole configuration.
{
  "mcpServers": {
    "richapi": {
      "url": "https://mcp.richapi.ai/mcp",
      "headers": { "x-api-key": "YOUR_KEY" }
    }
  }
}

# Then, in Cursor's agent chat, a prompt that bounds the run:
#
#   Read leads.csv. For the FIRST 20 ROWS ONLY, call email_finder with
#   first_name, last_name and company_domain. If success is false, write
#   an empty email and the reason, do not retry. For rows that returned an
#   address, call email_verifier on it. Write leads.enriched.csv with the
#   original columns plus email, verifier_status and billed. Then stop and
#   report the hit rate. Do not process the remaining rows.

# Equivalent HTTP call, if you would rather the agent wrote a script:
curl -s https://api.richapi.ai/api/v1/email_finder \
  -H "x-api-key: $RICHAPI_KEY" \
  -H "content-type: application/json" \
  -d '{"first_name":"Dana","last_name":"Weiss","company_domain":"acme.com"}'
the prompt
Read leads.csv. For the first 20 rows only, call the richapi email_finder
tool with first_name, last_name and company_domain from each row.

A miss returns success:false — that is expected, not an error. Write an
empty email for those rows and do not retry them.

For rows that returned an address, call email_verifier on that address.

Write leads.enriched.csv containing every original column plus: email,
verifier_status, billed, and the execution_log summary.

Then stop. Report how many of the 20 resolved, and the total credits billed.
Do not continue to the remaining rows unless I say so.

Cursor: enrich a CSV that's already in your repo

Someone sends you a list. It becomes `leads.csv` in a scratch directory and sits there because enriching it properly means writing a script with a rate limiter, a retry policy and a resume file, for a job you will do once. Cursor's agent will do it instead. Config is six lines of JSON, the CSV never leaves your machine except as API calls, and the output arrives as a file you can diff. [Cursor](/integrations/cursor) has the setup in full. An unbounded "enrich this CSV" on a 4,000-row file is the expensive mistake, so most of this page is about bounding the run.

Configure once

```json { "mcpServers": { "richapi": { "url": "https://mcp.richapi.ai/mcp", "headers": { "x-api-key": "YOUR_KEY" } } } } ``` In `~/.cursor/mcp.json` for every project, or `.cursor/mcp.json` for one. Restart, confirm the tools show up in the agent's tool list, and use a key you're willing to rotate, because editor configs get committed.

Bound the run, then widen it

An agent with a file handle and a tool will keep going. That's what it's for. It is also why "enrich this CSV" against a 4,000-row export is a sentence with a price attached that you did not calculate. So the first prompt says twenty rows and stop. Twenty rows gives you a real hit rate on *your* list, which is the only number that matters, since hit rate is a property of the list and not of the vendor. VPs at software companies resolve well. A directory scrape of contractors does not. Multiply the measured cost by the row count and decide whether to continue. The second thing to put in the prompt: **`success: false` is expected**. Left to itself, an agent reads a miss as a failure and retries, sometimes with variations, sometimes for a while. Credits-wise a retried miss on a waterfall endpoint is still free. Wall-clock-wise you've handed the run to a loop.

The billing, scoped

`/email_finder` and `/email_verifier` are **waterfall endpoints**: several providers run cheapest-first and if none of them return data you get a 2xx with `success: false` and `billed: false`, costing zero. That is the exception, not the rule. If you ask the agent to also pull company detail with `/enrich_company` at 1 credit, that endpoint bills on any 2xx including a thin one, and it wants a **LinkedIn company URL**, not the domain sitting in your CSV. Agents will cheerfully pass a domain and get nothing useful. `/enrich_profile` at 1 credit has the same shape: LinkedIn URL in, bills on any 2xx. Ask the agent to write `billed` into the output CSV. Then the run audits itself and you can sum a column instead of guessing.

The failure mode: in-place edits and a misparsed comma

Ask the agent to edit `leads.csv` directly and one of two things happens eventually. Either it rewrites the file with a different quoting convention and your company names with commas in them silently shift a column, or it runs out of context halfway and leaves you a half-enriched file with no marker for where it stopped. A new file fixes both. `leads.enriched.csv` next to the original, every original column preserved, plus the new ones. `git diff` becomes your QA step, and if the agent dies at row 130 you still have `leads.csv` intact and can restart from row 131 by saying so. This is the same discipline you'd apply to any agent-written change. The fact that it's data rather than code doesn't buy it an exemption.

Where CSV enrichment in Cursor goes wrong

This is a one-off tool. If the same list arrives every Monday, have the agent write you a script on one of these runs and move on; a recurring job wants idempotency, resume and a cron, and the agent loop has none of those. Nothing here sends mail, scores the list, or touches a CRM. The output is a file.

CSV enrichment in Cursor FAQ

**Does Cursor need my CSV to leave the machine?** The rows you enrich go out as API calls, the same as any HTTP client. The file itself stays where it is. **MCP or plain HTTP?** MCP when you want the agent doing the calling and the reasoning. HTTP when you want a script. Same key, same credit pool, same endpoints either way. **Can the agent see my credit balance?** It sees what the responses tell it, including `billed` per call. Ask it to total them at the end of the run. **It retried the same miss four times. Why?** Because you didn't tell it a miss was normal. Put `success:false is expected, do not retry` in the prompt. **Same thing in VS Code or Claude?** Yes, same server, same header. See [Cursor](/integrations/cursor) for the Cursor specifics.

Where to go after CSV enrichment in Cursor

[Cursor](/integrations/cursor) for setup detail, [agent driven account research](/use-cases/agent-driven-account-research) for the research-shaped version of this, [bulk enrich without seats](/use-cases/bulk-enrich-without-seats) when the list outgrows an agent loop, [n8n enrich and push hubspot](/use-cases/n8n-enrich-and-push-hubspot) if it should become a scheduled workflow, and [use cases](/use-cases) for the rest. Tiers on [pricing](/pricing). **25 free credits, no card.** Enough for a small bounded run, which is exactly what this page is asking you to do first.

Frequently asked.

Does Cursor need my CSV to leave the machine?
The rows you enrich go out as API calls, the same as any HTTP client. The file itself stays where it is.
MCP or plain HTTP?
MCP when you want the agent doing the calling and the reasoning. HTTP when you want a script. Same key, same credit pool, same endpoints either way.
Can the agent see my credit balance?
It sees what the responses tell it, including `billed` per call. Ask it to total them at the end of the run.
It retried the same miss four times. Why?
Because you didn't tell it a miss was normal. Put `success:false is expected, do not retry` in the prompt.
Same thing in VS Code or Claude?
Yes, same server, same header. See [Cursor](/integrations/cursor) for the Cursor specifics.

More playbooks

Try it with 25 free credits.