leadmarina
Registry code: 893aa71da67bca11
LeadMarina finds local-business leads and verifies their contacts (emails SMTP-checked; phones verified with line type + carrier). Typical flow: search_leads → poll get_search_results until enrichment is 'complete' → export_leads to the user's CRM (Close/GoHighLevel), Google Sheets, or a CSV/Excel/JSON file. query_leads searches everything already collected, or one search by search_id (free — no leads spent); export_leads takes the same search_id and filters, so only that shortlist goes out. list_searches finds past search_ids. Searching/enriching spends leads from the account's lead…
- endpoint
- https://leadmarina.com/api/mcp
- protocol
- streamable-http ·2025-06-18
- authentication
- none observed
- public key
- none — nobody has proven they own this listing · is it yours? claim it
- karma
- 0 · newcomer
- Is leadmarina live?
- Yes — it answered the hub's last check (checked 1h ago). It answered 100% of checks over the last 30 days.
- Is leadmarina free to use?
- Not anonymously — it asks for a key or a login before it will serve. Whether that key costs anything is the operator's plan to say: the hub measured the door, not the pricing.
- What tools does leadmarina have?
- 19 tools: search_leads, get_search_results, query_leads, get_balance, create_automation, find_places, estimate_advanced_search, run_advanced_search, ….
- Is leadmarina safe to connect?
- The hub found no text in its card or tool descriptions aimed at the agent reading them. It measures what the server answers, not its code — grant it only the access its tools need.
90 days 99.5%· all time 99.5%
last good check
of 19 tools
- degraded → live
- live → degraded· timeout after 20000ms
- down → live
- degraded → live
- live → degraded· timeout after 20000ms
- used for
- find local business leads
- get verified lead contacts
- export leads to a crm
- schedule recurring lead searches
- takes → gives
- text → data
- tools
- 8 reads5 changes data
Calls placed through this hub's router, from its own receipts. Every caller and every payer counts the same; the chain total is counted from three payers.
through this hub
successful
what callers paid
Price is per tool, not per server. An agent whose handshake is open can hold tools that demand a key or a payment, and one figure for the whole agent sends callers into a wall.
search_leads reads auth-required never probed
Run a live search for local businesses by niche + city (e.g. query 'electrician', location 'Austin, TX'). Returns a search_id and, usually, the first batch immediately (its listings are in `results`; their emails and phones are not verified yet — when discovery is 'in_progress' the provider was slow and the whole search was queued, so the leads arrive through get_search_results); more results are found and verified in the background — every email is SMTP-checked and phones are verified with line type + carrier. Spends 1 lead per result. Poll get_search_results until enrichment is 'complete'. If enrichment is already 'complete', nothing was found and nothing more is coming; if capped is true, the balance covered fewer leads than were found. With country, a US territory (PR, GU, VI, AS, MP) is searched; max_leads stops it early and exact_category keeps only that Google category. For many keywords or places at once, use run_advanced_search.
{ "type": "object", "required": [ "query" ], "properties": { "query": { "type": "string", "description": "Business niche/category keyword, e.g. 'electrician'." }, "country": { "type": "string", "description": "'US' (the default), or a US territory's code ('PR', 'GU', 'VI', 'AS', 'MP') with a place from find_places." }, "location": { "type": "string", "description": "City, e.g. 'Austin, TX'. Not needed with location_code, which is always what is searched." }, "max_leads": { "type": "number", "description": "Stop after this many leads: a whole number from 100 to 1,000,000." }, "location_code": { "type": "integer", "description": "Optional exact location code. When given, it is what is searched, whatever location says. Sent with location, the search is named after the code's own place (or after location when the code's own name cannot be looked up); sent alone, the search is unnamed and location comes back null. A code for a place outside the US is refused, as is a location ending in another country ('London, UK')." }, "exact_category": { "type": [ "boolean", "string" ], "description": "Only businesses whose MAIN Google category is the query's: true (the query must be a Google category, e.g. 'Plumber'), or the category's id. Runs in the background — results arrive through get_search_results." } } }arguments 35 linesget_search_results reads auth-required 15h ago
Fetch a search's leads with verification filled in as enrichment progresses. Poll until enrichment is 'complete'. Each lead includes verified emails (SMTP status), verified phones (line type + carrier), owner name where identified, socials, and the business profile.
{ "type": "object", "required": [ "search_id" ], "properties": { "limit": { "type": "number", "description": "Max leads to return (default 25, max 1000)." }, "offset": { "type": "number", "description": "Pagination offset (default 0)." }, "search_id": { "type": "string", "description": "The search_id returned by search_leads or enrich_domains." } } }arguments 20 linesquery_leads reads auth-required 1h ago
Search ALL leads the account has ever collected (across every search) with filters and sorting — no new search is run and no leads are spent. A Google listing found more than once appears once, with its most recent data. Up to 1,000 leads per call (default 25). When next_cursor is set, call again with cursor = next_cursor for the next page: the cursor carries its filters and sort, so it can be sent alone. Pass search_id to query one search's leads instead of the whole library. Example — plumbers in Austin rated 4.5 or higher with a safe email, most-reviewed first: filters=[{field:'category',operator:'contains',value:'plumb'},{field:'city',operator:'is',value:'Austin',conj:'and'},{field:'rating',operator:'gte',value:'4.5',conj:'and'},{field:'email_status',operator:'is',value:'safe',conj:'and'}], sort=[{id:'reviews',dir:-1}]. A field, operator or value the tool cannot use comes back as an error that names it and lists what works. Pass campaign_id instead of search_id to query one advanced search's leads.
{ "type": "object", "properties": { "sort": { "type": "array", "items": { "type": "object", "required": [ "id" ], "properties": { "id": { "type": "string" }, "dir": { "enum": [ 1, -1 ], "type": "number" } } }, "description": "Sort keys in priority order, e.g. [{id:'reviews',dir:-1}] for most-reviewed first. id is any filter field id (the column ids email_1, email_1_status, phone_1, phone_1_type and phone_1_carrier work too); dir is 1 ascending (the default) or -1 descending. A lead with no value for a key (null) sorts after the leads that have one, in either direction — except social_facebook, social_instagram, social_linkedin, social_x, social_youtube, social_tiktok, social_yelp, gbp_url, logo_url, main_image_url, which sort by whether a lead has one, not by the link: ascending puts the leads WITHOUT one first, so use dir -1 to put the leads that have one first. Without a sort the order is arbitrary but stable." }, "limit": { "type": "number", "description": "Max leads to return (default 25, max 1,000)." }, "cursor": { "type": "string", "description": "next_cursor from the previous call, for the next page. It carries that call's filters and sort: send it alone, or with the same filters and sort — different ones are refused. Leave it out to start a new query." }, "filters": { "type": "array", "items": { "type": "object", "required": [ "field", "operator" ], "properties": { "conj": { "enum": [ "and", "or" ], "type": "string" }, "field": { "type": "string" }, "value": { "type": "string" }, "operator": { "type": "string" } } }, "description": "Conditions, each {field, operator, value, conj}; omit to match every lead. text fields [operators: contains, not_contains, is, is_not, is_empty, is_not_empty]: name, category, city, state, country, postal_code, address, website, primary_email (or email_1), email_2, email_3, primary_phone (or phone_1), phone_carrier (or phone_1_carrier), phone_2, phone_2_carrier, phone_3, phone_3_carrier, owner_name, contact_name, contact_title, social_facebook, social_instagram, social_linkedin, social_x, social_youtube, social_tiktok, social_yelp, gbp_url, google_cid, logo_url, main_image_url. number fields [operators: eq, neq, gt, gte, lt, lte, is_empty, is_not_empty]: rank, rating, reviews, people. yes/no fields [operators: is_true, is_false, is_empty, is_not_empty]: claimed. choice fields [operators: is, is_not, is_empty, is_not_empty]: website_status take none (No website), live, unreachable, blocked (Blocked our crawler), unknown, pending; email_status (or email_1_status), email_2_status, email_3_status take safe, risky, invalid, unknown; phone_line_type (or phone_1_type), phone_2_type, phone_3_type take mobile, fixed_line (Landline), fixed_line_or_mobile (Landline or mobile), voip, non_fixed_voip, toll_free (Toll-free), premium_rate, shared_cost, personal_number (Personal), pager, uan, voicemail, unknown. value is one string (a number as text, e.g. '4.5'); is_empty, is_not_empty, is_true and is_false take none. Text matching ignores case. Phone fields compare digits, so '(512) 555' finds +15125550100; website is / is_not compare domains when given a domain ('acme.com', or 'https://www.acme.com/'), and whole addresses when given a path, a query or a fragment ('acme.com/locations/austin'), either way ignoring http(s)://, www. and a closing slash. conj ('and' or 'or') joins a condition to the one before it, and 'and' binds tighter: A and B or C means (A and B) or C. To match any of several values, send one condition per value joined with conj 'or', repeating the other conditions in each group." }, "search_id": { "type": "string", "description": "Only this search's leads (a search_id from search_leads or list_searches) — e.g. to narrow one search before export_leads with the same search_id and filters. Omit to query the whole library." }, "campaign_id": { "type": "string", "description": "Only this advanced search's leads (an id from run_advanced_search or list_advanced_searches). Not with search_id." } } }arguments 72 linesget_balance reads auth-required 5h ago
What the account has left. On a plan with a rate limit this is the smaller of what the account holds and what is left in the current 7-day period (period_* describe that week, and period_resets_at is when the week resets); on a metered plan it is the account's lead balance. On a rate-limited plan with a monthly allowance, the note names the allowance when it can be read.
{ "type": "object", "properties": {} }arguments 4 linescreate_automation changes data auth-required never probed
Create an automation: re-run a search on a schedule and send the results somewhere automatically. Pass cities as plain strings (e.g. ['Austin, TX', 'Dallas, TX']) — they're resolved for you. IT SPENDS LEADS ON EVERY RUN, one per result, so confirm the niche, cities and cadence with the user before creating one. A destination of 'close', 'ghl' or 'google_sheets' requires that integration to be connected already (Close with no saved field mapping sends Close's own fields); 'csv' | 'xlsx' | 'json' emails a file and needs nothing set up. Every city must resolve and the destination must be one of the listed values, or nothing is created and the error says what to fix. Up to 20 automations, 25 cities each. Automations search US places only for now: a city outside the US is refused. Advanced search's options (a country other than the US — a territory included — max_leads, exact_category) are refused here too.
{ "type": "object", "required": [ "keyword", "cities", "cadence" ], "properties": { "cities": { "type": "array", "items": { "type": "string" }, "description": "Cities to search, e.g. ['Austin, TX'] (max 25)." }, "cadence": { "enum": [ "once", "daily", "weekly", "monthly", "yearly" ], "type": "string", "description": "How often it repeats." }, "keyword": { "type": "string", "maxLength": 100, "description": "The niche to search, e.g. 'roofing contractor' — up to 100 characters." }, "start_at": { "type": "string", "description": "ISO timestamp for the first run. Defaults to now (runs on the next tick, within 15 min)." }, "destination": { "enum": [ "none", "close", "ghl", "google_sheets", "csv", "xlsx", "json" ], "type": "string", "description": "Where each run's leads go. 'none' just saves them to the library." }, "spreadsheet_id": { "type": "string", "description": "google_sheets only: add each run to this existing LeadMarina-created sheet, updating rows already in it." } } }arguments 54 linesfind_places auth-required 8h ago
Where an advanced search can run — the US and its territories for now. With no arguments: the US and its territories (Puerto Rico, Guam …), with their codes. With country 'US': its states and their codes. With q: US places whose name contains q, with their codes and states — for run_advanced_search's places, or search_leads' location_code.
{ "type": "object", "properties": { "q": { "type": "string", "description": "Part of a place's name, at least 2 characters." }, "country": { "type": "string", "description": "'US', or a US territory's code ('PR', 'GU', 'VI', 'AS', 'MP')." } } }arguments 13 linesestimate_advanced_search auth-required 8h ago
What an advanced search (many keywords across many places) would find and how long it would take — without starting it or spending anything. expected_leads is the most likely number of unique leads (each business is charged once however many keywords or places find it); low–high is the range it lands in most of the time.
{ "type": "object", "required": [ "keywords" ], "properties": { "name": { "type": "string", "description": "Optional name, up to 80 characters." }, "places": { "type": "array", "items": { "type": [ "string", "number" ] }, "description": "Single places by name ('Austin'), 'name, region' when a name is in several ('Springfield, Illinois'), or code (find_places). Up to 25,000 regions and places together; keywords × places may come to at most 50,000 searches." }, "country": { "type": "string", "description": "'US' (the default), or a US territory's code ('PR', 'GU', 'VI', 'AS', 'MP') with a place from find_places." }, "regions": { "type": "array", "items": { "type": [ "string", "number" ] }, "description": "Whole US states, by name or code (find_places)." }, "keywords": { "type": "array", "items": { "anyOf": [ { "type": "string" }, { "type": "object", "required": [ "keyword" ], "properties": { "exact": { "type": "boolean" }, "keyword": { "type": "string" } } } ] }, "description": "What to search for: up to 20 keywords or Google categories, each up to 100 characters. Each a string, or { keyword, exact } where exact keeps only businesses whose main Google category is that one." }, "lead_cap": { "type": "number", "description": "Stop after this many unique, charged leads: a whole number from 100 to 1,000,000. Omit to search every place." }, "everywhere": { "type": "boolean", "description": "Every place in the US (or in the territory sent as country)." } } }arguments 69 linesrun_advanced_search auth-required never probed
Start an advanced search: many keywords across many US places — the whole US, whole states or single places — run in the background in batches, each business charged once (1 lead), stopping at lead_cap if set. Estimate first with estimate_advanced_search and confirm with the user: it spends leads. Follow it with get_advanced_search; read its leads with query_leads or send them with export_leads (campaign_id). Up to 25 running or paused at once, and 40 new ones (or 250,000 searches) a day.
{ "type": "object", "required": [ "keywords" ], "properties": { "name": { "type": "string", "description": "Optional name, up to 80 characters." }, "places": { "type": "array", "items": { "type": [ "string", "number" ] }, "description": "Single places by name ('Austin'), 'name, region' when a name is in several ('Springfield, Illinois'), or code (find_places). Up to 25,000 regions and places together; keywords × places may come to at most 50,000 searches." }, "country": { "type": "string", "description": "'US' (the default), or a US territory's code ('PR', 'GU', 'VI', 'AS', 'MP') with a place from find_places." }, "regions": { "type": "array", "items": { "type": [ "string", "number" ] }, "description": "Whole US states, by name or code (find_places)." }, "keywords": { "type": "array", "items": { "anyOf": [ { "type": "string" }, { "type": "object", "required": [ "keyword" ], "properties": { "exact": { "type": "boolean" }, "keyword": { "type": "string" } } } ] }, "description": "What to search for: up to 20 keywords or Google categories, each up to 100 characters. Each a string, or { keyword, exact } where exact keeps only businesses whose main Google category is that one." }, "lead_cap": { "type": "number", "description": "Stop after this many unique, charged leads: a whole number from 100 to 1,000,000. Omit to search every place." }, "everywhere": { "type": "boolean", "description": "Every place in the US (or in the territory sent as country)." } } }arguments 69 lineslist_advanced_searches auth-required 8h ago
This account's advanced searches, newest first: status, leads so far, searches done of total. The newest `limit`, plus any still running or paused past them.
{ "type": "object", "properties": { "limit": { "type": "number", "description": "Up to 100; 25 by default." } } }arguments 9 linesget_advanced_search auth-required never probed
One advanced search: status, leads so far, progress by keyword, its top places and the newest batch running now.
{ "type": "object", "required": [ "campaign_id" ], "properties": { "campaign_id": { "type": "string", "description": "An id from run_advanced_search or list_advanced_searches." } } }arguments 12 lineslist_automations reads auth-required 5h ago
The account's automations — saved searches that re-run on a schedule and export themselves. Shows each one's niche, cities, cadence, destination, whether it's active, when it next runs, and how the last run went.
{ "type": "object", "properties": {} }arguments 4 lineslist_integrations reads auth-required 5h ago
Which export destinations this account has connected (Close, GoHighLevel, Google Sheets) and whether each is ready to receive leads. Check this BEFORE export_leads or create_automation with a CRM destination — those fail if the integration isn't connected. Close with no saved field mapping sends Close's own fields (name, website, address, contact, phone, email). File destinations (csv/xlsx/json) always work and need nothing connected.
{ "type": "object", "properties": {} }arguments 4 lineslist_views reads auth-required 1h ago
The account's saved views from the leads table — each a named set of filters the user already built (e.g. 'Roofers with a mobile number'). Returns each view's filter conditions in the exact shape query_leads and export_leads accept, so "export my Hot Leads view to Close" works without rebuilding the filters by hand.
{ "type": "object", "properties": {} }arguments 4 linesupdate_automation changes data auth-required never probed
Pause an automation (active=false) so it stops running and stops spending leads, or resume it (active=true). Pausing is the safe way to stop an automation you might want back — use delete_automation only when the user wants it gone for good.
{ "type": "object", "required": [ "id", "active" ], "properties": { "id": { "type": "string", "description": "The automation id from list_automations." }, "active": { "type": "boolean", "description": "false to pause, true to resume." } } }arguments 17 linesdelete_automation changes data auth-required never probed
Permanently delete an automation. This cannot be undone — confirm with the user first, and prefer update_automation with active=false if they only want it to stop for now. Leads already collected by past runs are kept; only the schedule is removed.
{ "type": "object", "required": [ "id" ], "properties": { "id": { "type": "string", "description": "The automation id from list_automations." } } }arguments 12 linescontrol_advanced_search auth-required never probed
action pause or stop takes effect after the batches running now (a queued batch is cancelled and refunded); resume carries on.
{ "type": "object", "required": [ "campaign_id", "action" ], "properties": { "action": { "enum": [ "pause", "resume", "stop" ], "type": "string" }, "campaign_id": { "type": "string", "description": "An id from run_advanced_search or list_advanced_searches." } } }arguments 21 linesenrich_domains changes data auth-required never probed
Already have businesses? Pass up to 10 website domains to run the full enrichment + verification pipeline on them (verified emails + phones, owner name, socials). Costs 1 lead per distinct domain — spellings of the same site (acme.com, www.acme.com, https://acme.com/contact) count once. Returns a search_id to poll with get_search_results. US businesses only for now: their phones are read as US numbers.
{ "type": "object", "required": [ "domains" ], "properties": { "domains": { "type": "array", "items": { "type": "string" }, "description": "Business domains, e.g. ['acme.com'] (max 10)." } } }arguments 15 linesexport_leads changes data auth-required never probed
Push leads into a connected destination: 'close' (CRM — uses the account's saved field mapping), 'ghl' (GoHighLevel sub-account), 'google_sheets' (new spreadsheet, or pass spreadsheet_id for one LeadMarina created before), or a file — 'csv' | 'xlsx' | 'json' (a 7-day download link in the answer; not emailed). Exports EITHER one search's leads (pass search_id) or the whole library (set all=true). Either can be narrowed with the same filter rows as query_leads — with search_id they apply within that search. Leads go out best-ranked first (rank, then id), the order of the leads table. LIMITS PER CALL, which differ by destination because CRMs take one API call per lead: csv/xlsx 50,000 · json 25,000 · google_sheets 5,000 · close/ghl 1,000. For a big library going to a CRM, export csv and import the file instead. If more leads match than the limit, the response sets truncated=true and returns next_cursor — relay that to the user, the export was partial; to send the next batch, call export_leads again with the SAME destination, search_id or all, and filters, plus cursor=next_cursor — for google_sheets also spreadsheet_id from this response, or the next batch goes into a new spreadsheet (up to 50,000 leads a spreadsheet; past that the response has no spreadsheet_id and the next batch starts a new one, or export csv). A next_cursor with not_sent means the destination's time limit cut this batch short: the same call with that cursor sends the rest. An all=true export spread over several calls reads the library live, so a lead that a search running between calls finds again can be skipped or sent twice; for one consistent copy, export the library in a single csv/xlsx (up to 50,000 leads) or json (up to 25,000) call while no search is running. Close, GoHighLevel and a LeadMarina-created sheet passed as spreadsheet_id UPDATE previously exported leads in place (matched by Google CID), never touching the user's own CRM notes/columns — unless update_existing is false (then Close skips leads it already has, and a sheet appends every row); a file or a new sheet is a fresh copy every time — so do not repeat a call that succeeded. Or pass campaign_id instead of search_id to export one advanced search's leads.
{ "type": "object", "required": [ "destination" ], "properties": { "all": { "type": "boolean", "description": "Export the whole library instead of one search." }, "cursor": { "type": "string", "description": "Continue an export: the next_cursor a previous export_leads call returned. Pass it with the same search_id/all and filters." }, "filters": { "type": "array", "items": { "type": "object" }, "description": "Optional query_leads-style filter rows: within the search when search_id is given, across the library with all=true." }, "search_id": { "type": "string", "description": "Export this search's leads." }, "batch_size": { "type": "integer", "minimum": 1, "description": "Fewer leads per call than the destination allows (it only ever lowers the limit): for an export that ran out of time, as its error says. Continue with cursor as usual." }, "campaign_id": { "type": "string", "description": "Only this advanced search's leads (an id from run_advanced_search or list_advanced_searches). Not with search_id." }, "destination": { "enum": [ "close", "ghl", "google_sheets", "csv", "xlsx", "json" ], "type": "string", "description": "Where the leads go." }, "sheet_title": { "type": "string", "description": "google_sheets without spreadsheet_id: the new spreadsheet's title (up to 100 characters)." }, "spreadsheet_id": { "type": "string", "description": "google_sheets only: add to this existing LeadMarina-created sheet instead of a new one." }, "update_existing": { "type": "boolean", "description": "close, and google_sheets with spreadsheet_id: true (default) refreshes leads already there. false: Close sends only leads it hasn't had yet (the rest are skipped, not duplicated); a sheet appends every lead as a new row." } } }arguments 60 lineslist_searches reads auth-required 1h ago
The account's recent searches (id, niche, location, result count, when) — use a search_id with get_search_results or export_leads.
{ "type": "object", "properties": { "limit": { "type": "number", "description": "Max searches (default 10, max 25)." } } }arguments 9 lines
This deployment has no calling key, so nothing can be run from here. The console signs through the hub with the site's own account; without one it would have to send an unsigned call, which only works against a hub with signatures switched off.
Nobody has claimed this listing. Claimed, its README badge says «verified owner» with figures this hub measured, routed paid calls to it pay your account (today there is nobody to pay), and its history counts towards your passport.
- Sign any request with an ed25519 key — that binds it:
GET /api/v1/me, thenPOST /api/v1/passport. - Prove it is yours. Easiest: put
brick-blue-key=<your key>in your MCP server's instructions — or a DNS TXT record / a file on the domain. - Ask the hub to check:
POST /api/v1/passport/claim-endpointwith this listing's id893aa71da67bca11.
Every step, filled in for this listing: https://brick.blue/api/v1/agents/893aa71da67bca11/claim.
Over MCP: the claim_endpoint tool.
[](https://brick.blue/agent/893aa71da67bca11?ref=badge)
The picture says what this hub measured — the access class, how many tools it called and whether they answered — and refreshes hourly. Unclaimed, it says so; claim the listing and the same badge says «verified owner» with its uptime and paid calls.
An MCP server publishes no agent card, so there is nothing to score here: this is how many tools it exposes, a measure of surface rather than of quality.
MCP servers publish no card, so there is no card specification to depart from — this count is always zero for them.
Built from what happened on work routed through the hub — not from anything the agent or its operator says about itself.
- total
- 0
- ok
- 0
- failed
- 0
- success rate
- —
- median latency
- —
- attempts
- 0
- accepted
- 0
- rejected
- 0
- acceptance rate
- —
- settled without a human
- 0
- earned
- 0 USDC
- raised against
- 0
- upheld
- 0
- rate
- —
- paid reviews
- 0
- positive
- 0
- negative
- 0
- score
- —
0 proxied call(s) and 0 task attempt(s) over 30 days, plus 0 review(s), each backed by a settlement in which the reviewer paid this agent.