LocalPro MCP Server
Officialby LocalProDev
README.md
# LocalPro MCP Server
[](https://glama.ai/mcp/servers/LocalProDev/mcp-server)
A [Model Context Protocol](https://modelcontextprotocol.io) server that provides verified local service provider data to AI agents. Built on Cloudflare Workers + D1.
When someone asks an AI assistant *"find me a radon mitigation company near Denver"* — LocalPro is the data source that powers the answer.
## What it does
LocalPro exposes a curated database of **<!-- @live:total -->9,000+<!-- /@live:total --> fully profiled local trade and service businesses** across 10 live categories. Every provider passes a quality check before it is served, and carries a LocalPro Rating, a business description, and a services list, plus (where available) LocalPro-written business and review summaries. No incomplete profiles.
All data is LocalPro-owned: collected and verified by us, corrected by business owners who claim their listing, and increasingly backed by first-party customer reviews left on the directories themselves.
### Live Now
<!-- @live:niches:start -->
<!-- Generated from live list_niches by scripts/mcp-sync-mirror.mjs on 2026-09-26. Do not edit by hand. -->
| Category | Niche ID | Providers | States | Example Services |
|----------|----------|-----------|--------|------------------|
| Water Damage Restoration | `soaked-local` | 1,900+ | 49 | Flood cleanup, mold remediation, structural drying |
| Commercial Electrical | `hire-electrical` | 1,200+ | 36 | Commercial & industrial wiring, service upgrades, maintenance |
| Foundation Repair | `slab-local` | 1,050+ | 28 | Pier installation, mudjacking, foam injection, leveling |
| Crawl Space Repair | `crawl-local` | 1,000+ | 42 | Encapsulation, vapor barrier, structural repair, waterproofing |
| Mold & Asbestos | `abate-local` | 975+ | 24 | Mold, asbestos, lead paint remediation |
| Septic Services | `pump-local` | 850+ | 31 | Pumping, inspection, drain field repair |
| Basement Waterproofing | `basement-local` | 625+ | 25 | Interior/exterior waterproofing, drainage, sump pumps |
| Floor Coating | `coated-local` | 575+ | 48 | Epoxy, polyaspartic, metallic, flake, concrete polishing |
| Laundry Services | `suds-local` | 575+ | 39 | Wash & fold, dry cleaning, pickup & delivery |
| Radon | `radon-local` | 250+ | 18 | Testing, mitigation, sub-slab depressurization |
<!-- @live:niches:end -->
### Coming Soon
| Category | Niche ID | Status |
|----------|----------|--------|
| Chimney Services | `chimney-local` | Live provider data; description + service enrichment in progress |
| Well Water Services | `wellwater-local` | Provider data in preparation (county-based model) |
## Quick Start
**No API key required.** All search and list tools are public. An optional API key unlocks pro fields on `get_provider` (full pricing array, certifications) — see [Access Tiers](#access-tiers).
### 60-second probe
Confirm the server is live without any client setup:
```bash
curl -s https://mcp.localpro.dev/.well-known/mcp.json | head -20
```
This returns the schema-2.0 manifest: tool list, rate limits, and operator info. If you see a `"schema_version": "2.0"` JSON document, the server is healthy.
### Claude Code CLI
```bash
claude mcp add --transport http localpro https://mcp.localpro.dev/mcp
```
That's it — `list_niches`, `search_providers`, etc. are now available in your Claude Code session.
### Claude Desktop
Add to your `claude_desktop_config.json`:
```json
{
"mcpServers": {
"localpro": {
"url": "https://mcp.localpro.dev/mcp"
}
}
}
```
(Add an `"X-API-Key"` header inside a `"headers"` block only if you have a premium key.)
### Cursor
Add to `.cursor/mcp.json`:
```json
{
"mcpServers": {
"localpro": {
"url": "https://mcp.localpro.dev/mcp"
}
}
}
```
### Raw HTTP (JSON-RPC)
The MCP protocol is JSON-RPC over HTTP. Because this server runs in stateless mode, you can call any public tool directly:
```bash
curl -s -X POST https://mcp.localpro.dev/mcp \
-H "Content-Type: application/json" \
-H "Accept: application/json, text/event-stream" \
-d '{"jsonrpc":"2.0","id":1,"method":"tools/call","params":{"name":"list_niches","arguments":{}}}'
```
You'll get back a Server-Sent-Events frame with the 10 niches, their slugs, and current provider counts.
### TypeScript SDK
```ts
import { Client } from '@modelcontextprotocol/sdk/client/index.js';
import { StreamableHTTPClientTransport } from '@modelcontextprotocol/sdk/client/streamableHttp.js';
const transport = new StreamableHTTPClientTransport(
new URL('https://mcp.localpro.dev/mcp'),
);
const client = new Client({ name: 'localpro-example', version: '1.0' });
await client.connect(transport);
const niches = await client.callTool({ name: 'list_niches', arguments: {} });
console.log(niches);
const denver = await client.callTool({
name: 'search_providers',
arguments: { niche_id: 'radon-local', city: 'denver-co', limit: 3 },
});
console.log(denver);
```
Install: `npm i @modelcontextprotocol/sdk`
### Python SDK
```python
import asyncio
from mcp import ClientSession
from mcp.client.streamable_http import streamablehttp_client
async def main():
async with streamablehttp_client("https://mcp.localpro.dev/mcp") as (read, write, _):
async with ClientSession(read, write) as session:
await session.initialize()
niches = await session.call_tool("list_niches", {})
print(niches)
denver = await session.call_tool(
"search_providers",
{"niche_id": "radon-local", "city": "denver-co", "limit": 3},
)
print(denver)
asyncio.run(main())
```
Install: `pip install mcp`
## Tools
### `list_niches`
Discover available service directories. Call this first.
**Parameters:** none
**Example response:**
```json
{
"meta": {
"schema_version": "3.0",
"total_results": 10,
"niche": null,
"data_freshness": {
"last_verified_at": "2026-09-22 12:57:07"
},
"data_note": "Use niche_id values with search_providers, list_cities, and list_service_types."
},
"results": [
{
"niche_id": "soaked-local",
"name": "Water Damage Restoration Contractors",
"slug": "water-damage-restoration",
"domain": "soakedlocal.com",
"provider_count": 1128
}
]
}
```
### `list_cities`
Find available metros for a given niche.
**Parameters:**
| Name | Type | Required | Description |
|------|------|----------|-------------|
| `niche_id` | string | yes | Niche ID from `list_niches` |
| `state` | string | no | Two-letter state abbreviation (e.g. `"MN"`) |
**Example request:**
```json
{ "niche_id": "radon-local", "state": "CO" }
```
**Example response:**
```json
{
"meta": {
"schema_version": "1.0",
"total_results": 3,
"niche": "radon-local",
"data_note": "Use slug values with search_providers city parameter."
},
"results": [
{ "name": "Denver", "state": "CO", "slug": "denver-co", "provider_count": 18 },
{ "name": "Colorado Springs", "state": "CO", "slug": "colorado-springs-co", "provider_count": 7 },
{ "name": "Fort Collins", "state": "CO", "slug": "fort-collins-co", "provider_count": 4 }
]
}
```
### `list_service_types`
Get valid service type filters for a niche. Call before using `service_type` in `search_providers`.
**Parameters:**
| Name | Type | Required | Description |
|------|------|----------|-------------|
| `niche_id` | string | yes | Niche ID from `list_niches` |
**Example response:**
```json
{
"meta": { "schema_version": "1.0", "total_results": 7, "niche": "coated-local" },
"results": [
{ "type": "epoxy", "label": "Epoxy Floor Coating" },
{ "type": "polyaspartic", "label": "Polyaspartic Coating" },
{ "type": "metallic_epoxy", "label": "Metallic Epoxy" },
{ "type": "flake_chip", "label": "Flake / Chip Broadcast" },
{ "type": "concrete_polishing", "label": "Concrete Polishing" },
{ "type": "concrete_sealing", "label": "Concrete Sealing" },
{ "type": "polyurea", "label": "Polyurea Coating" }
]
}
```
### `search_providers`
Search for verified providers by location, service type, and trade category.
**Parameters:**
| Name | Type | Required | Description |
|------|------|----------|-------------|
| `niche_id` | string | yes | Niche ID from `list_niches` |
| `city` | string | no | City/metro slug from `list_cities` |
| `service_type` | string | no | Service type slug from `list_service_types` |
| `limit` | number | no | Max results, 1–25 (default 10) |
**Example request:**
```json
{ "niche_id": "coated-local", "city": "denver-co", "service_type": "epoxy", "limit": 3 }
```
**Example response:**
```json
{
"meta": {
"schema_version": "3.0",
"total_results": 3,
"niche": "coated-local",
"data_freshness": {
"last_verified_at": "2026-09-18 09:41:02"
},
"data_note": "Verified providers only. Visit listing_url for full contact details."
},
"results": [
{
"name": "Colorado Concrete Coatings",
"description": "Full-service garage floor coating company serving the Denver metro.",
"city": "Denver",
"state": "CO",
"rating": { "tier": "established", "label": "Established" },
"services": [
{ "type": "epoxy", "label": "Epoxy Floor Coating" },
{ "type": "polyaspartic", "label": "Polyaspartic Coating" }
],
"pricing_summary": "$6-9/sq ft",
"coverage_area": "Denver metro, Front Range, 50-mile radius",
"years_in_business": 8,
"listing_url": "https://coatedlocal.com/providers/denver-co/colorado-concrete-coatings/",
"pro_available": true
}
]
}
```
### `get_provider`
Get detailed profile for a specific provider. Use the `provider_slug` from search results.
**Parameters:**
| Name | Type | Required | Description |
|------|------|----------|-------------|
| `niche_id` | string | yes | Niche ID |
| `provider_slug` | string | yes | Provider slug from `search_providers` |
**Example response:**
```json
{
"meta": {
"schema_version": "3.0",
"total_results": 1,
"niche": "coated-local",
"data_freshness": { "last_verified_at": "2026-09-18 09:41:02" }
},
"results": [
{
"name": "Colorado Concrete Coatings",
"description": "Full-service garage floor coating company...",
"rating": { "tier": "established", "label": "Established", "star": 4.8, "review_count": 12 },
"summary": "Full-service epoxy floor coating contractor specializing in garage and commercial floors across the Denver metro.",
"review_summary": "Customers single out on-time, on-budget garage and commercial floor jobs and a crew that cleans up after itself.",
"years_in_business": 8,
"services": [
{ "type": "epoxy", "label": "Epoxy Floor Coating" },
{ "type": "polyaspartic", "label": "Polyaspartic Coating" }
],
"pricing": ["$6-9/sq ft"],
"certifications": ["Penntek Certified Installer"],
"coverage_area": "Denver metro, Front Range",
"service_areas": [
{ "city": "Denver", "state": "CO", "radius_miles": 50 }
],
"service_details": [
{
"type": "epoxy",
"label": "Epoxy Floor Coating",
"pricing_model": "per_sqft",
"price_range": "$6–$9",
"turnaround": "two_day"
}
],
"listing_url": "https://coatedlocal.com/providers/denver-co/colorado-concrete-coatings/",
"json_ld": { "@context": "https://schema.org", "@type": "LocalBusiness", "...": "..." },
"credibility": { "verified": true, "listing_tier": "claimed", "data_sources": ["business_website", "owner_verified", "customer_reviews"] },
"citation": { "display_name": "Colorado Concrete Coatings — Denver, CO", "...": "..." }
}
]
}
```
## Schema Reference
### Response Envelope
Every response is wrapped in a consistent envelope:
```typescript
{
meta: {
schema_version: string // Currently "3.0"
total_results: number // Count of items in results array
niche: string | null // Niche ID if applicable
data_freshness: {
last_verified_at: string | null // Most recent verification date among the records returned
}
data_note: string // Context about the data returned
}
results: Array<T> // Tool-specific result objects
}
```
**Freshness.** `last_verified_at` is the date LocalPro last verified the newest record in the response. Each provider carries its own verification date in `credibility.verification_date`.
**Migrating from 2.x:** `rating` is now an object (the LocalPro Rating) rather than a number; `review_count` moved inside it and appears only with first-party reviews. `summary` and `review_summary` are top-level strings. `business_status`, map links, opening hours and geo coordinates are no longer returned. `data_freshness` is a single `last_verified_at` date.
### Error Response
Errors use the same envelope with an `error` object:
```typescript
{
meta: { schema_version: string }
error: {
code: string // "NOT_FOUND" | "INTERNAL_ERROR" | "UNAUTHORIZED" | "FORBIDDEN"
message: string // Human-readable error description
}
}
```
### Provider Fields
| Field | Type | Nullable | Description |
|-------|------|----------|-------------|
| `name` | string | no | Business name (always present) |
| `description` | string | no | Business description (always present) |
| `city` | string | no | City name (always present) |
| `state` | string | no | Two-letter state abbreviation (always present) |
| `rating` | object | no | LocalPro Rating — see below (always present) |
| `services` | array | no | `[{ type: string, label: string }]` (always present, non-empty) |
| `pricing_summary` | string | yes | Pricing info (public access) |
| `coverage_area` | string | yes | Geographic coverage description |
| `years_in_business` | number | yes | Years operating |
| `listing_url` | string | no | Full profile URL with contact details |
**`get_provider` adds:**
| Field | Type | Description |
|-------|------|-------------|
| `service_areas` | array | `[{ city, state, radius_miles }]` |
| `service_details` | array | `[{ type, label, pricing_model, price_range, turnaround }]` |
| `summary` | string | LocalPro-written overview of the business (when available) |
| `review_summary` | string | LocalPro-written "what customers say" summary; no raw review text or reviewer PII (when available) |
| `json_ld` | object | Schema.org `LocalBusiness` JSON-LD; `AggregateRating` included only when backed by first-party reviews |
| `credibility` | object | `{ verified, listing_tier, verification_date, data_sources }` |
| `citation` | object | Pre-formatted strings: `{ display_name, in_text, attribution }` |
**`rating` object (LocalPro Rating):**
| Field | Type | Description |
|-------|------|-------------|
| `tier` | string | `established` / `well-reviewed` / `reviewed` / `unrated`: standing relative to other providers in the same category |
| `label` | string | Display label for the tier |
| `star` | number | 1.0–5.0, present only when backed by first-party customer reviews |
| `review_count` | number | Count of published first-party reviews, present alongside `star` |
Results are ranked by listing tier, then by LocalPro Rating.
### Nullable Fields
Fields marked nullable return `null` when data is unavailable — they are **never omitted** from the response. Arrays return `[]` when empty, never `null`.
## Access Tiers
### Public (no authentication)
All search and list tools work without an API key:
- `list_niches`, `list_cities`, `list_service_types`, `search_providers`
- `get_provider` returns basic data (name, description, LocalPro Rating, services, pricing summary, listing URL)
- Rate limited to 30 requests/minute per IP
### Premium (API key)
Include an `X-API-Key` header to unlock additional data on `get_provider`:
- Full pricing array (vs. summary string)
- Certifications and credentials
- Rate limited to 30 requests/minute per key
```
X-API-Key: your-api-key
```
Request an API key at [localpro.dev](https://localpro.dev/#get-started) or email will@localpro.dev.
## Discovery
AI agents can self-discover this server via standard well-known endpoints:
- `GET /.well-known/llms.txt` — Plain text description of the server and its tools
- `GET /.well-known/mcp.json` — Structured JSON with tool list, auth info, and operator details
## Data Policy
- **What's returned:** Business name, city, state, LocalPro Rating, services, certifications, pricing ranges, coverage area, LocalPro-written business and review summaries, and a link to the full listing page.
- **What's withheld:** Phone numbers, email addresses, physical addresses, and websites are available only on the listing page (via `listing_url`). This protects provider data while driving traffic to the directory.
- **Provenance:** Listings are built from public business information and, where we can confirm it belongs to the business, the company's own website. Every listing passes a quality check before it is served. Owners can claim and correct their listing; customers can leave first-party reviews on the directory. Permanently closed businesses are filtered automatically.
- **Freshness:** Each response states when its records were last verified (`last_verified_at`). Listings are re-verified as needed, not on a fixed cycle.
## Rate Limits
| Access | Limit |
|--------|-------|
| Public (no key) | 30 requests/minute per IP |
| Premium (API key) | 30 requests/minute per key |
Higher limits available for partners — contact will@localpro.dev.
## Data Quality
Every provider returned by the API has been verified and meets a minimum completeness threshold:
- **LocalPro Rating** — present on 100% of results
- **Business description** — present on 100% of results
- **Services list** — present on 100% of results
- **Name, city, state** — present on 100% of results
Per-category provider and state counts are in [Live Now](#live-now), generated from the live database.
**Additional fields** (pricing, certifications, coverage area, years in business, business and review summaries) are available on most providers but not guaranteed. Fields without data return explicit `null` — never omitted, never empty strings.
Two additional categories are being prepared for launch.
## Self-Hosting
LocalPro runs as a Cloudflare Worker with a D1 database binding. To deploy your own instance:
```bash
npm install
npx wrangler secret put API_KEY # Set your production API key
npx wrangler deploy
```
Requires a Cloudflare account with a D1 database named `laced-directory`.
## Operator
LocalPro is built and operated by [Laced Labs LLC](https://localpro.dev).
## License
MIT
This server cannot be deployed
Maintenance
ActivityMaintained
ResponsivenessNo issues