Koskamo

PermitStack MCP

An official MCP server provided by PermitStack that allows AI agents to query U.S. building permit data, including searches by address, contractor, or category, and retrieve property histories and contractor information without scraping.

Endpoint and access

No sign-in to connect and list tools. Individual tools may still need a vendor account, credentials, or permissions; check the documented prerequisites.

PermitStack MCP logo, by PermitStackVendor evidenceStreamable HTTPNo sign-inEndpoint checked 2026-11-01Operated by PermitStack
You need:A PermitStack accountAccess to the email inbox of that accountCreate a free account first
MCP endpoint (Streamable HTTP)
https://mcp.permit-stack.com/mcp
Vendor documentation

What you can do with it

  • Search permits by city, state, ZIP, or category
  • Look up permit history for a specific property address
  • Find contractors by name or trade classification
  • Retrieve coverage data and freshness status

Source and maintenance

Vendor evidenceRegistry 1.0.0

Protocol and capabilities

Server
permitstack 0.1.0
MCP protocol
2025-06-18
Tools
6 advertised
Resources
Not advertised
Resource templates
Not advertised
Prompts
Not advertised
Server-advertised capabilities
{
  "tools": {}
}

Tools

6 advertised

search_permits — Search building permits
Advertised by the server during the last successful anonymous check.
Advertised read-only

Search U.S. building permits by location (city, state, ZIP code, or a lat/lng radius), category, status, property type, filing or issue date range, estimated project value, contractor name, or free text. Returns up to 25 permits per call with address, dates, category, status, estimated value, contractor and description, plus the total number of matches. Response fields: `total` is exact unless `total_capped` is true, in which case it is a lower bound; when `total_unknown` is true the count could not be computed and `total` is null. `account_window_clamped`, `account_window_days` and `account_window_from` are set when the connected account covers a limited date range, and the results then cover only that range. Category HVAC also matches MECHANICAL, and MECHANICAL also matches HVAC. date_after/date_before match whichever date a permit has (issued, else filed), for feeds that publish only one of the two. Results carry no property owner name, owner mailing address or permit applicant name fields.

search_permits input schema
{
  "type": "object",
  "properties": {
    "q": {
      "type": "string",
      "description": "Free-text search over description, address, and permit number"
    },
    "lat": {
      "type": "number",
      "description": "Latitude for radius search (use with lng)"
    },
    "lng": {
      "type": "number",
      "description": "Longitude for radius search (use with lat)"
    },
    "city": {
      "type": "string",
      "description": "City name, e.g. 'Austin', 'Boston', 'Miami-Dade County'"
    },
    "page": {
      "type": "integer",
      "default": 1,
      "minimum": 1,
      "description": "Page number, 1-based (default 1)"
    },
    "start": {
      "type": "integer",
      "minimum": 1,
      "description": "Instead of page: 1-based position of the first result to return, e.g. start=24 continues after result 23 (as named in `_notes`)"
    },
    "state": {
      "type": "string",
      "description": "Two-letter US state code, e.g. 'TX', 'MA', 'FL'"
    },
    "status": {
      "type": "string",
      "description": "Permit status, e.g. 'ISSUED', 'FINAL', 'EXPIRED', 'FILED'"
    },
    "category": {
      "type": "string",
      "description": "Permit category (case-insensitive). Common values: SOLAR, ROOFING, HVAC, NEW_CONSTRUCTION, POOL, ELECTRICAL, PLUMBING, DEMOLITION, MECHANICAL, RENOVATION."
    },
    "per_page": {
      "type": "integer",
      "default": 25,
      "maximum": 25,
      "minimum": 1,
      "description": "Results per page (default 25, max 25)"
    },
    "zip_code": {
      "type": "string",
      "description": "5-digit ZIP code"
    },
    "max_value": {
      "type": "number",
      "description": "Maximum estimated project value in dollars"
    },
    "min_value": {
      "type": "number",
      "description": "Minimum estimated project value in dollars"
    },
    "date_after": {
      "type": "string",
      "description": "ISO date (YYYY-MM-DD): only permits dated on or after this date, using the issue date, else the filing date"
    },
    "date_before": {
      "type": "string",
      "description": "ISO date (YYYY-MM-DD): only permits dated on or before this date, using the issue date, else the filing date"
    },
    "filed_after": {
      "type": "string",
      "description": "ISO date (YYYY-MM-DD): only permits filed on or after this date"
    },
    "filed_before": {
      "type": "string",
      "description": "ISO date (YYYY-MM-DD): only permits filed on or before this date"
    },
    "issued_after": {
      "type": "string",
      "description": "ISO date (YYYY-MM-DD): only permits issued on or after this date"
    },
    "jurisdiction": {
      "type": "string",
      "description": "Jurisdiction name or partial name, e.g. 'Wake County', 'Tacoma'"
    },
    "radius_miles": {
      "type": "number",
      "description": "Radius in miles for lat/lng search (max 50, default 5)"
    },
    "issued_before": {
      "type": "string",
      "description": "ISO date (YYYY-MM-DD): only permits issued on or before this date"
    },
    "property_type": {
      "type": "string",
      "description": "Property type, one of: residential, commercial, industrial, mixed_use, institutional, unknown (case-insensitive)"
    },
    "contractor_name": {
      "type": "string",
      "description": "Filter by contractor name (partial match supported)"
    }
  },
  "additionalProperties": false
}
search_permits annotations
{
  "title": "Search building permits",
  "readOnlyHint": true,
  "openWorldHint": false,
  "idempotentHint": true,
  "destructiveHint": false
}
get_permit — Look up a permit by number
Advertised by the server during the last successful anonymous check.
Advertised read-only

Look up a permit by the permit number assigned by the issuing jurisdiction, optionally narrowed by city and state. The number is matched exactly (ignoring case), and the same number can exist in several jurisdictions, so up to 5 matching permits are returned; give the city or state to tell them apart. If nothing matches exactly and a city or state was given, permits in that place whose number contains the text are returned instead, and `match` says "partial". When the connected account covers a limited date range, `account_window_from` is set and only permits from that date onward are searched. Results carry no property owner name, owner mailing address or permit applicant name fields.

get_permit input schema
{
  "type": "object",
  "required": [
    "permit_number"
  ],
  "properties": {
    "city": {
      "type": "string",
      "description": "City where the permit was issued (optional, narrows the match)"
    },
    "state": {
      "type": "string",
      "description": "Two-letter state code (optional, narrows the match)"
    },
    "permit_number": {
      "type": "string",
      "description": "The permit number from the issuing jurisdiction"
    }
  },
  "additionalProperties": false
}
get_permit annotations
{
  "title": "Look up a permit by number",
  "readOnlyHint": true,
  "openWorldHint": false,
  "idempotentHint": true,
  "destructiveHint": false
}
get_property_history — Property permit history
Advertised by the server during the last successful anonymous check.
Advertised read-only

Permit history for one property, looked up by street address (house number and street name, e.g. '123 Main St'). Optional city, state and ZIP narrow the match when the same street address exists in several places. Returns a property profile (permit timeline, category breakdown, contractors) and up to 25 permit records per page, newest first; `has_more` says whether the next page has more. Covers all permit categories. When the connected account covers a limited date range, the profile and records cover only that range, `account_window_from` is set, and `_notes` says so: the result is then not the property's full permit history. Results carry no property owner name, owner mailing address or permit applicant name fields.

get_property_history input schema
{
  "type": "object",
  "required": [
    "address"
  ],
  "properties": {
    "zip": {
      "type": "string",
      "description": "Optional ZIP code (prefix-matched)"
    },
    "city": {
      "type": "string",
      "description": "Optional city, to tell identical street addresses apart"
    },
    "page": {
      "type": "integer",
      "default": 1,
      "minimum": 1,
      "description": "Page number, 1-based (default 1)"
    },
    "start": {
      "type": "integer",
      "minimum": 1,
      "description": "Instead of page: 1-based position of the first result to return, e.g. start=24 continues after result 23 (as named in `_notes`)"
    },
    "state": {
      "type": "string",
      "description": "Optional two-letter state code"
    },
    "address": {
      "type": "string",
      "description": "Street address with house number, e.g. '123 Main St' (min 3 characters)"
    },
    "per_page": {
      "type": "integer",
      "default": 25,
      "maximum": 25,
      "minimum": 1,
      "description": "Results per page (default 25, max 25)"
    }
  },
  "additionalProperties": false
}
get_property_history annotations
{
  "title": "Property permit history",
  "readOnlyHint": true,
  "openWorldHint": false,
  "idempotentHint": true,
  "destructiveHint": false
}
search_contractors — Search contractors
Advertised by the server during the last successful anonymous check.
Advertised read-only

Search contractors by name, city, state or specialty. Returns up to 25 contractors per call with the contractor UUID, name, licence number and licence state, home city and state, total permit count, first and last permit dates, specialties and activity score (0-100), sorted by activity score (highest first). Project values are not included; get_contractor_permits lists a contractor's permits with their estimated values.

search_contractors input schema
{
  "type": "object",
  "properties": {
    "city": {
      "type": "string",
      "description": "City where the contractor has worked"
    },
    "name": {
      "type": "string",
      "description": "Contractor name (partial match)"
    },
    "page": {
      "type": "integer",
      "default": 1,
      "minimum": 1,
      "description": "Page number, 1-based (default 1)"
    },
    "start": {
      "type": "integer",
      "minimum": 1,
      "description": "Instead of page: 1-based position of the first result to return, e.g. start=24 continues after result 23 (as named in `_notes`)"
    },
    "state": {
      "type": "string",
      "description": "Two-letter state code"
    },
    "per_page": {
      "type": "integer",
      "default": 25,
      "maximum": 25,
      "minimum": 1,
      "description": "Results per page (default 25, max 25)"
    },
    "specialty": {
      "type": "string",
      "description": "Specialty/trade to filter by, e.g. 'solar', 'roofing', 'hvac'"
    },
    "min_permits": {
      "type": "integer",
      "minimum": 0,
      "description": "Only contractors with at least this many permits"
    }
  },
  "additionalProperties": false
}
search_contractors annotations
{
  "title": "Search contractors",
  "readOnlyHint": true,
  "openWorldHint": false,
  "idempotentHint": true,
  "destructiveHint": false
}
get_contractor_permits — Contractor's permits
Advertised by the server during the last successful anonymous check.
Advertised read-only

List the permits pulled by one contractor, identified by the contractor UUID from search_contractors. Returns up to 25 permits per page with the contractor's work history fields (dates, categories, values). Results carry no property owner name, owner mailing address or permit applicant name fields.

get_contractor_permits input schema
{
  "type": "object",
  "required": [
    "contractor_id"
  ],
  "properties": {
    "page": {
      "type": "integer",
      "default": 1,
      "minimum": 1,
      "description": "Page number, 1-based (default 1)"
    },
    "start": {
      "type": "integer",
      "minimum": 1,
      "description": "Instead of page: 1-based position of the first result to return, e.g. start=24 continues after result 23 (as named in `_notes`)"
    },
    "per_page": {
      "type": "integer",
      "default": 25,
      "maximum": 25,
      "minimum": 1,
      "description": "Results per page (default 25, max 25)"
    },
    "contractor_id": {
      "type": "string",
      "description": "Contractor UUID from search_contractors results"
    }
  },
  "additionalProperties": false
}
get_contractor_permits annotations
{
  "title": "Contractor's permits",
  "readOnlyHint": true,
  "openWorldHint": false,
  "idempotentHint": true,
  "destructiveHint": false
}
get_coverage — Data coverage
Advertised by the server during the last successful anonymous check.
Advertised read-only

Describe PermitStack's coverage: total permits, jurisdictions (active, archive, frozen) and states. On a signed-in connection it also lists covered jurisdictions with their permit counts, county and `data_through` (the date of the newest permit held), filterable by state and by name, up to 25 per call, largest first. Without sign-in it returns the platform totals only.

get_coverage input schema
{
  "type": "object",
  "properties": {
    "name": {
      "type": "string",
      "description": "Optional text matched against jurisdiction names, e.g. 'Austin' or 'County'"
    },
    "state": {
      "type": "string",
      "description": "Optional two-letter state code to list only that state's jurisdictions"
    }
  },
  "additionalProperties": false
}
get_coverage annotations
{
  "title": "Data coverage",
  "readOnlyHint": true,
  "openWorldHint": false,
  "idempotentHint": true,
  "destructiveHint": false
}

Prompts

Not advertised

No prompt definitions available.

Resources

Not advertised

No resource definitions available.

30-day availability

Aggregated from read-only remote checks; this is not a tool-execution or security guarantee.

Successful checks
1 of 1 (100%)
Average latency
616 ms
95th percentile latency
616 ms

Maintenance history

Public check and source-refresh events. Editorial and ownership records remain private.

  • · probe · passed · 616 ms · metadata changed · 6 tool(s)

Connect from your client

Each snippet registers the same endpoint; pick the client you use.

This server is operated by the named third party. Listing and endpoint checks are not an endorsement or a security audit. Review the operator's permissions, terms, and data handling before connecting. How listings are checked and corrected.

Claude Code

Run this once in a terminal. It registers the remote server. Use --scope project to write .mcp.json for the repo.
Claude Code configuration
claude mcp add --transport http permitstack-mcp https://mcp.permit-stack.com/mcp

Codex

Run this once. Codex stores MCP servers in ~/.codex/config.toml (or .codex/config.toml in a trusted project).
Codex configuration
codex mcp add permitstack-mcp --url https://mcp.permit-stack.com/mcp

Cursor

Merge this server into .cursor/mcp.json in your project, then enable permitstack-mcp in your MCP settings.
Cursor configuration
{
  "mcpServers": {
    "permitstack-mcp": {
      "url": "https://mcp.permit-stack.com/mcp"
    }
  }
}

Cline

Merge this into cline_mcp_settings.json (Cline → MCP Servers → Configure).
Cline configuration
{
  "mcpServers": {
    "permitstack-mcp": {
      "type": "streamableHttp",
      "url": "https://mcp.permit-stack.com/mcp",
      "disabled": false
    }
  }
}

VS Code

Merge this server into .vscode/mcp.json. Use MCP: List Servers to start permitstack-mcp and inspect its tools.
VS Code configuration
{
  "servers": {
    "permitstack-mcp": {
      "type": "http",
      "url": "https://mcp.permit-stack.com/mcp"
    }
  }
}

Gemini CLI

Run this once. It writes .gemini/settings.json in the current project; pass --scope user for ~/.gemini/settings.json.
Gemini CLI configuration
gemini mcp add --transport http permitstack-mcp https://mcp.permit-stack.com/mcp

Claude Desktop

Merge this into claude_desktop_config.json (macOS: ~/Library/Application Support/Claude/, Windows: %APPDATA%\Claude\), then restart Claude Desktop.
Claude Desktop configuration
{
  "mcpServers": {
    "permitstack-mcp": {
      "url": "https://mcp.permit-stack.com/mcp"
    }
  }
}

Windsurf

Merge this into ~/.codeium/windsurf/mcp_config.json, then refresh MCP in Cascade. Windsurf remote servers use serverUrl, not url.
Windsurf configuration
{
  "mcpServers": {
    "permitstack-mcp": {
      "serverUrl": "https://mcp.permit-stack.com/mcp"
    }
  }
}

Let your agent find its tools

Find servers like PermitStack MCP from your agent. Add Koskamo once to search the index for endpoints, access requirements, and client setup. Public discovery needs no key.

Do you run PermitStack MCP?

Prove ownership with a DNS record, a well-known file, or your Official MCP Registry entry, and your edits publish immediately. Proofs are re-checked weekly; admins can still hide or remove a listing.

Claim this listing