listriver-mcp
OfficialListRiver Business Data API
New and active U.S. businesses from official state business registries (Secretary of State filings), as JSON. New LLCs, corporations, nonprofits and partnerships, filtered by state, city, county, ZIP, NAICS industry, entity type, formation month, and whether a phone or email is on file.
Free key: 500 records a month, no card needed: get one here
Full documentation with a live "Try it" panel and examples in cURL, Python, JavaScript, C# and PHP: listriver.com/api-docs
Python client:
pip install listriver(source)OpenAPI 3 spec: openapi.yaml (import into Postman, Insomnia, Swagger UI or an AI agent)
MCP server for Claude and other AI assistants, source in
mcp/:uvx listriver-mcp
Typical uses: lead lists of brand-new businesses (formed this month), CRM enrichment, sales territory research, KYB and business verification, market sizing, and B2B prospecting by industry and place.
Quick start (2 minutes)
Create a free API account and click the link in the confirmation email.
On the API page, click Get my free API key and copy it.
Count a search (free), then pull the records:
# How many businesses formed in Miami in the last few months have a phone number? (free)
curl -H "X-Api-Key: YOUR_KEY" "https://listriver.com/api/data.ashx?action=count&states=FL&city=MIAMI&hasPhone=1&formedWithin=3"
# The first 10 of them
curl -H "X-Api-Key: YOUR_KEY" "https://listriver.com/api/data.ashx?action=records&states=FL&city=MIAMI&hasPhone=1&formedWithin=3&limit=10"{
"ok": true,
"rows": [
{
"businessName": "ANGELI TRAVEL LLC",
"entityType": "LIMITED LIABILITY COMPANY",
"status": "ACTIVE",
"formed": "2026-08",
"registrationState": "FL",
"stateFilingNumber": "L26000446708",
"address": "2125 BISCAYNE BLVD, STE 204 #27572",
"city": "MIAMI",
"zip": "33137",
"county": "MIAMI-DADE",
"phone": "(786) 298-9566",
"website": "HTTPS://ANGELITRAVELS.COM",
"registeredAgent": "ULLOA SANCHEZ YUDELSA",
"listriverId": "FL-L26000446708",
"...": "35 fields in all"
}
],
"cursor": "FL.6604750",
"resume": "FL.6604750"
}Python
from listriver import Client
lr = Client("YOUR_KEY")
search = dict(states="FL", city="MIAMI", has_phone=True, formed_within=3)
print(lr.count(**search)) # free
for business in lr.records(**search, max_records=100):
print(business["businessName"], business["phone"])More: examples/ (Python, JavaScript, curl) and the recipes (also C# and PHP).
Related MCP server: Echo MCP Server
MCP server (source in this repo)
This repository contains a Model Context Protocol server for ListRiver, written in Python:
mcp/listriver_mcp/server.py (package mcp/, tests in mcp/tests/,
MIT license). It runs over stdio and gives AI assistants (Claude Desktop, Claude Code, Cursor and other MCP clients) three tools:
Tool | What it does | Cost |
| States covered and their record counts | free |
| How many businesses match a search (state, city, county, ZIP, NAICS, entity type, formation month, phone/email on file) | free |
| The matching businesses, 25 by default and up to 100 per call, with a cursor for more | counts against your records |
The server tells the assistant to count first and to fetch only what you need.
Install from PyPI (published from this repo's mcp/ folder) and add it to Claude Desktop (Settings > Developer > Edit Config):
{
"mcpServers": {
"listriver": {
"command": "uvx",
"args": ["listriver-mcp"],
"env": { "LISTRIVER_API_KEY": "lr_key_..." }
}
}
}Or run it from source:
git clone https://github.com/ListRiver-LLC/listriver-api && cd listriver-api
pip install ./python ./mcp
LISTRIVER_API_KEY=lr_key_... listriver-mcp
# or with Docker, using the Dockerfile in this repo
docker build -t listriver-mcp .
docker run -i --rm -e LISTRIVER_API_KEY=lr_key_... listriver-mcpSetup for other clients: mcp/README.md. Listed in the official MCP Registry as io.github.ListRiver-LLC/listriver.
Calls
Every call is an HTTPS GET to https://listriver.com/api/data.ashx with your key in the X-Api-Key header.
| What it returns | Cost |
| Available states and record counts per formation window | free |
| How many records match your filters, per state | free (20 calls a minute) |
| Up to 1,000 matching records per call; pass | each record returned counts |
Filters
records and count take the same filters. A record must match all of them; where a filter takes several
comma-separated values, any one of them matches.
Parameter | Example | What it does |
|
| Registration states (leave out for all) |
|
| Business city (needs |
|
| Business county (needs |
|
| 5-digit ZIPs or 3-digit prefixes (needs |
|
| NAICS industry prefix, 2 to 6 digits |
|
|
|
|
| Only businesses with a phone / email on file |
|
| Formed this month or in the N months before it |
|
| Formed in this range of months |
|
| Shortcut windows |
Formation dates are month-level (registries publish the month), so windows are whole calendar months.
Pricing
Plan | Records | Price |
Free | 500 / month | $0 |
Prepaid packs | 5,000 / 7,500 / 10,000 (use within 12 months) | $50 / $75 / $100 |
Monthly plans | 5,000 / 12,000 / 28,000 / 75,000 per month | $50 / $100 / $200 / $450 |
AWS Marketplace | larger volumes, billed on your AWS invoice | see listing |
Only records returned count, and each record counts every time it is returned: overlapping or repeated searches
count again. Count first (free), save the cursor or resume position to carry on later, and use listriverId to
de-duplicate. Packs and plans are on your API page. Current prices are always
on listriver.com/api-docs.
Keeping a feed up to date
Every records answer includes resume: the position after the last record returned, even on the last page. Save it per
state, and pass it as cursor next time to get only the businesses ListRiver has added since. See
examples/python/daily_feed.py.
Sample data
sample-data/ has a small sample of recent Florida formations (CSV and JSON, no emails) so you can judge the data before signing up. It is a sample, not a full file.
Data and terms
Records come from official state business registries, with addresses standardized and contact details, NAICS codes and
EINs added where available. A field is null when the state doesn't publish it or ListRiver doesn't have it; nothing is
estimated. Coverage and update schedules: listriver.com/methodology.
The code in this repository is MIT-licensed. The data (including sample-data/) is covered by the
ListRiver API agreement: for your own business use, not for resale,
and not for credit, insurance, employment or housing decisions.
Questions: support@listriver.com
Available Tools
3 toolscount_businessesARead-onlyIdempotent
Count businesses matching the filters, per state. Free: use it before search_businesses.
Args:
states: Comma-separated two-letter registration states, e.g. "FL" or "FL,TX". Required with city, county or zip.
city: Comma-separated business cities, e.g. "MIAMI".
county: Comma-separated counties, e.g. "MIAMI-DADE" (or "FL:MIAMI-DADE").
zip: Comma-separated 5-digit ZIP codes or 3-digit ZIP prefixes, e.g. "33139,331".
naics: Comma-separated NAICS prefixes, 2-6 digits, e.g. "23" (construction) or "722511".
entity_type: Comma-separated of LLC, CORP, LP, LLP, NONPROFIT, OTHER.
has_phone: Only businesses with a phone number on file.
has_email: Only businesses with an email on file.
formed_within: Formed in the current month or the N months before it (1 = this month or last). Set 0 for any formation date.
formed_from: First formation month, "YYYY-MM" (overrides formed_within).
formed_to: Last formation month, "YYYY-MM" (overrides formed_within).
| Name | Required | Description | Default |
|---|---|---|---|
| zip | No | ||
| city | No | ||
| naics | No | ||
| county | No | ||
| states | No | ||
| formed_to | No | ||
| has_email | No | ||
| has_phone | No | ||
| entity_type | No | ||
| formed_from | No | ||
| formed_within | No |
Output Schema
| Name | Required | Description |
|---|---|---|
| result | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare readOnlyHint, idempotentHint and openWorldHint, so the safety profile is covered. The description adds genuinely new context: the call is free (cost signal that shapes call ordering) and results are grouped per state. It does not discuss rate limits or what a zero-match response looks like, but the output schema covers return shape.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The purpose and the cost-based routing rule are front-loaded in a single sentence, then the args list follows. The arg block is long but every line carries format or default information absent from the schema, so there is little waste; the one sloppy phrase ("Comma-separated of LLC...") is minor.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For an 11-parameter tool with zero schema descriptions, the definition covers every parameter, the default for formed_within, and the cross-parameter dependency. With an output schema present it need not explain return values, though it could say whether states-less calls are legal (all params optional) or what happens when no filters are given.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 0%, so the description carries the full burden and does so for all 11 parameters: formats (two-letter states, 5-digit or 3-digit ZIP prefixes, 2-6 digit NAICS), worked examples, entity_type vocabulary, and the boolean filters. It also states non-obvious interaction rules the schema cannot express — formed_from/formed_to override formed_within, and states is required when city, county or zip is supplied.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
States a specific verb and resource plus the aggregation scope: "Count businesses matching the filters, per state." It also names the sibling it precedes (search_businesses), so an agent can distinguish it from both siblings without opening either schema.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Explicit routing rule with a rationale: "Free: use it before search_businesses," which tells the agent to cheaply size a result set before running the costlier search. It names the alternative but gives no explicit when-not condition or guidance on choosing between list_states and this tool.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
list_statesARead-onlyIdempotent
List the states ListRiver covers, with how many businesses each has: formed this month or last ("recent"), in the last 12 months ("year"), and every active business ("all"). Free.
| Name | Required | Description | Default |
|---|---|---|---|
No parameters | |||
Output Schema
| Name | Required | Description |
|---|---|---|
| result | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already establish readOnlyHint, idempotentHint, and openWorldHint, so safety and repeatability are covered. The description adds value beyond them by disclosing that the call is "Free" (no credit consumption) and by defining the semantic windows behind each count category. It does not discuss freshness of the counts or caching, which would have been a further bonus.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
A single sentence front-loads the purpose and then defines the three count categories without filler. The nested parenthetical quoting is dense and slightly harder to scan than a short bulleted breakdown would be, but nothing is redundant.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
This is a parameterless, read-only listing tool with an output schema that documents the return shape. The description supplies the one thing the schema and annotations cannot: what each count window means and that the call is free. Nothing needed to call it correctly is missing.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
The tool takes zero parameters, so the baseline is 4 and there is no parameter meaning to add. The description does usefully map the labels "recent", "year", and "all" to concrete time windows, which likely correspond to fields in the output rather than inputs.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description names a specific verb and resource ("List the states ListRiver covers") and immediately clarifies the payload: business counts per state. The three metric windows ("recent", "year", "all") are spelled out precisely. It stops short of naming siblings like count_businesses or search_businesses, so the differentiation is implicit rather than explicit.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Usage is implied: this is the coverage/overview call for enumerating supported states and their business volumes. There is no explicit when-to-use versus when-not-to-use statement and no pointer to the sibling tools for filtered or aggregate queries. "Free" gives a useful cost signal but is not routing guidance.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
search_businessesARead-onlyIdempotent
Get businesses matching the filters (same filters as count_businesses). USES THE USER'S RECORDS: each business returned counts, every time it is returned, so ask only for what the user needs.
Args:
states: Comma-separated two-letter registration states. Required with city, county or zip.
city: Comma-separated business cities.
county: Comma-separated counties.
zip: Comma-separated 5-digit ZIP codes or 3-digit prefixes.
naics: Comma-separated NAICS prefixes, 2-6 digits.
entity_type: Comma-separated of LLC, CORP, LP, LLP, NONPROFIT, OTHER.
has_phone: Only businesses with a phone number on file.
has_email: Only businesses with an email on file.
formed_within: Formed in the current month or the N months before it (1 = this month or last; 0 = any date).
formed_from: First formation month, "YYYY-MM".
formed_to: Last formation month, "YYYY-MM".
limit: How many businesses to return, 1-100 (default 25).
cursor: The cursor from a previous search_businesses answer, to get the next businesses of the same search.
| Name | Required | Description | Default |
|---|---|---|---|
| zip | No | ||
| city | No | ||
| limit | No | ||
| naics | No | ||
| county | No | ||
| cursor | No | ||
| states | No | ||
| formed_to | No | ||
| has_email | No | ||
| has_phone | No | ||
| entity_type | No | ||
| formed_from | No | ||
| formed_within | No |
Output Schema
| Name | Required | Description |
|---|---|---|
| result | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
The annotations already cover read-only, open-world, and idempotent behavior, but the description adds an important non-annotated trait: each returned business has a cost every time it is returned. It does not detail authentication, rate limits, or result ordering, though the output schema likely covers return shape.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The definition is front-loaded with purpose and cost warning, then uses a clean Args list. Every line adds useful information, and no parameter documentation is wasted.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a 13-parameter search tool with an output schema and annotations, the description covers purpose, cost behavior, pagination, all filter semantics, defaults, and conditional requirements. Nothing critical for correct invocation is missing.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 0%, so the description carries the full parameter burden, and it succeeds. It documents all 13 parameters with formats, comma-separation rules, NAICS digit lengths, allowed entity-type values, date formats, limit range, cursor meaning, and a conditional requirement for states with city/county/zip.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description states a specific verb and resource: "Get businesses matching the filters." It also links to count_businesses via "same filters as count_businesses" and makes clear this tool returns actual businesses, distinguishing it from the counting sibling.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description gives clear usage context by warning that each returned business counts and advising the agent to ask only for what the user needs. It also explains the cursor for paging. It stops short of explicitly saying when to use count_businesses versus this tool, leaving that inference to the sibling relationship.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
Tool Schema Changelog
Recent tool additions, removals, and schema changes observed during successful MCP inspections.
3 tool updates
v0.1.0- First observed
count_businesses - First observed
list_states - First observed
search_businesses
TDQS
Scored across 3 tools
Each tool has a clearly distinct role: list_states returns coverage/metadata, count_businesses returns free aggregate counts, and search_businesses returns paginated records that consume the user's quota. The descriptions explicitly frame the intended workflow (count first, then search only what you need), leaving no realistic chance of misselection.
All three names follow a strict verb_noun snake_case pattern (list_states, count_businesses, search_businesses) with the noun consistently referring to the domain entity. No mixed conventions or vague verbs.
Three tools map exactly onto the three capabilities the service exposes: coverage, free counting, and metered record retrieval. Nothing is redundant and nothing feels padded, making the small surface well-scoped rather than thin.
The lifecycle is well covered: discover states, filter/count, then page through results with a cursor, and search shares the same rich filter set as count. The main gaps are the absence of a name/text filter and any single-record lookup, which agents may expect when researching a specific business.
Maintenance
Related MCP Connectors
MCP server for Riveter's enrichment, scraping, and monitoring API
MCP server for progressive tool usage at any scale (see https://klavis.ai)
MCP server for accessing curated awesome list documentation
Related MCP Servers
- AlicenseNot gradedqualityAmaintenanceOfficial MCP Server for Buildkite.56MIT
- FlicenseNot gradedqualityDmaintenanceA simple demonstration MCP server that provides an echo tool and resource for learning how to build MCP servers. Serves as a starting point and template for creating custom MCP server implementations.1-
- FlicenseNot gradedqualityDmaintenanceA demonstration MCP server implementation with Docker support that provides a simple hello-world tool and includes a web-based inspector for interactive testing and exploration of MCP tools.-
- AlicenseNot gradedqualityCmaintenanceThe most complete open-source MCP server for Discord — 80+ tools, dual-mode: integrated (plugin) or standalone59 npm14MIT