Skip to main content
Glama

king-county-permit-status

Server Details

Live permit history + status for any King County, WA address, parcel or permit number. Read-only.

Ownership verified
Status
Healthy
Uptime
100.0% over 21 days
Last Tested
Transport
Streamable HTTP · MCP 2025-06-18
URL
Repository
chaoz23/king-county-permit-status
GitHub Stars
1

TDQS

A4.4/5.0

Scored across 1 tool

Disambiguation5/5

There is only one tool, so no selection ambiguity is possible. Its purpose (permit lookup by address, parcel, or permit number) is explicit and singular.

Naming Consistency5/5

The single tool uses clear snake_case (king_county_permit_status) and matches the server name's domain. With one tool there is no risk of mixed conventions.

Tool Count3/5

One tool is thin for a server aggregating many disparate data sources; batch lookups or separate search modes are absent. It is defensible as a single-purpose lookup endpoint, but the surface feels under-built.

Completeness4/5

Input flexibility (address, parcel, permit number) and broad source coverage (MyBuildingPermit, city open data, L&I, Assessor index) make the read path thorough. Gaps are minor: no batch/multi-address lookup, no parameters for filtering or paging results.

Available Tools

1 tool
king_county_permit_statusKing County permit statusA
Read-onlyIdempotent
Inspect

Look up building permit history and status for any King County, WA property. Accepts a street address, 10-digit parcel number, or permit number. Live sources: MyBuildingPermit (14 cities + unincorporated King County), Seattle and Bellevue open data, Renton EnerGov, Redmond Civic Access, Shoreline eTRAKiT, Woodinville + King County Accela, Normandy Park and Carnation SmartGov, SeaTac LAMA, WA State L&I (electrical), plus the King County Assessor's issued-permit index for every parcel (covers the 19 cities without a public portal; history only, no status). Jurisdiction is derived from the city-limits polygon, not the mailing city. Returns all matching permits sorted newest-first. Use for due diligence, permit tracking, or verifying contractor pull history.

NameRequiredDescriptionDefault
limitNoMax permits to return (newest first). summary always covers the whole matched set, so start small and raise only if you need the rows.
queryNoOne of: street address ('1817 Morris Ave S, Renton WA 98055'), 10-digit parcel number (plain '7222000353' or formatted '722200-0353'), or permit number ('B25000947', 'ADDC21-0275', '23-127651-LP', '6145915-CN'). Input type is auto-detected.
sinceNoOnly permits applied/issued on or after this date (YYYY-MM-DD).
typesNoCase-insensitive substrings matched against each permit's type, e.g. ['electrical', 'mechanical'].
licenseNoWA L&I contractor license number — same search by license. Use instead of query.
contractorNoContractor company name (substring) — returns what they have pulled across the MyBuildingPermit cities. Use instead of query.

Output Schema

NameRequiredDescription
actionYesfound — permits[] is populated; none — no permits found; refine — connection issue, retry; reject — bad input
errorsNoSource errors when a search is incomplete; may accompany permits from sources that succeeded.
cite_asNoOne-line attribution string for generated text
filtersNoThe limit/since/types that produced this response
messageYes
permitsNoUp to `limit` permit records, newest first (applied_date, else issued_date).
summaryNoComputed over every permit matching since/types (not just the returned rows): total, matched, returned, truncated, open, closed, status_unknown, open_basis_counts {finaled_date, status-vocabulary} (how many open/closed verdicts rest on a fact vs the status-word heuristic), by_type, by_status, by_year, years [oldest, newest], latest {permit_number,type,status,date,jurisdiction}. Answer from this; drill into permits only when you need rows.
searchedNoJurisdictions searched (e.g. ['King County', 'Renton (EnerGov)']).
next_stepNoStructured twin of separate_portal: the exact follow-up an agent can take. kind=manual_portal_search; reason in no_feed|electrical_only|parcel_resolution_failed|source_incomplete; portal_url (the portal's search page when known); vendor; search_by (inputs that page accepts, empty when login-gated); query/query_type to re-use; covers_electrical; hint.
parcel_idNoCounty-namespaced parcel id, e.g. 'king:7222000353' or 'pierce:5985002900', when the query was or resolved to a parcel
fetched_atNoUTC ISO-8601 timestamp of this query; records are live, not cached
trust_levelNolive — every applicable source answered; partial — a source errored or hit its result cap (see errors); fallback — nothing searchable, use next_step. A city needing manual follow-up (next_step) does not by itself lower trust.
jurisdictionNoWhich authority the query was routed to and why. basis: city-limits (geocoded point inside the city's polygon — authoritative), geocoder-city (locator's city, outside King County's polygon layer), address-text (the mailing city in the query), parcel-site-address (a parcel query, resolved through the Assessor's site address), null (none). unincorporated=true means county permits only.
permit_countNoUnique permits found before any since/types filter (= summary.total)
coverage_noteNoContractor searches only: which cities were (and were not) searched
routing_by_typeNoPer permit type (building, mechanical_plumbing, electrical, land_use, engineering_row, fire, grading, septic) for the resolved jurisdiction: {system, portal, live, note}. live=true means that system is searched by this tool; otherwise the portal is where to look. Present for address queries and parcel queries that resolved a city.
separate_portalNoPresent when manual follow-up at a city portal is needed, including when a live city search is incomplete. Includes city, portal URL, note.
address_resolutionNoHow well the geocoder matched an address query. match_type: point (exact address point), interpolated (number placed along the street; no parcel), street (street only). partial_match is true for anything but point; street_number_snapped when the matched house number differs from the one given.

TDQS

A4.4/5.0
Behavior5/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already establish read-only, idempotent, non-destructive, open-world behavior, and the description adds substantial context on top: the live source list, the fact that jurisdiction is derived from the city-limits polygon rather than mailing city, and the important coverage caveat that the Assessor index for 19 portal-less cities is 'history only, no status'. These are material behavioral facts an agent cannot infer from annotations.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Purpose, accepted inputs, and sources are front-loaded, and the final sentence cleanly states when to use it. The enumeration of a dozen named source systems is long, but each entry maps to real coverage an agent needs to reason about, so most of the length earns its place.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

An output schema exists, so return-value detail is unnecessary, and the description instead supplies the things that actually matter for correct use: input modes, sorting order, jurisdiction resolution logic, and explicit coverage gaps. Nothing an agent needs before calling is missing.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema coverage is 100% and every parameter already carries examples and format guidance, so the baseline is 3. The description reinforces the accepted input types and the polygon-based jurisdiction resolution, but most of that is duplicative of the schema's own parameter descriptions, adding no format or constraint detail beyond it.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

Specific verb ('look up') plus resource ('building permit history and status') plus explicit geographic scope ('any King County, WA property'). The three accepted identifier forms and the sorted result set make the tool's contract unambiguous, far beyond a restatement of the name.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

Names concrete use cases — 'due diligence, permit tracking, or verifying contractor pull history' — and pairs them with the matching input mode (query vs. contractor/license). It does not state when to avoid the tool or what to do when a jurisdiction has no portal beyond the implicit note that Assessor history lacks status, so it stops short of full alternative routing.

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.

  1. 1 tool update
    • Changedking_county_permit_status13 fields changed
      • addedInput schema / description
        Added value: +"Give `query` (address / parcel / permit number) OR `contractor` / `license` for a contractor pull-history search; never both."
      • addedInput schema / properties / contractor
        Added value: +{
        +  "description": "Contractor company name (substring) — returns what they have pulled across the MyBuildingPermit cities. Use instead of query.",
        +  "type": "string"
        +}
      • addedInput schema / properties / license
        Added value: +{
        +  "description": "WA L&I contractor license number — same search by license. Use instead of query.",
        +  "type": "string"
        +}
      • changedInput schema / required
        Previous value: -[
        -  "query"
        -]New value: +[]
      • addedOutput schema / properties / coverage_note
        Added value: +{
        +  "description": "Contractor searches only: which cities were (and were not) searched",
        +  "type": "string"
        +}
      • changedOutput schema / properties / jurisdiction / description
        Previous value: -"Which authority the query was routed to and why. basis: city-limits (geocoded point inside the city's polygon — authoritative), geocoder-city (locator's city, outside King County's polygon layer), address-text (the mailing city in the query), null (none). unincorporated=true means county permits only."New value: +"Which authority the query was routed to and why. basis: city-limits (geocoded point inside the city's polygon — authoritative), geocoder-city (locator's city, outside King County's polygon layer), address-text (the mailing city in the query), parcel-site-address (a parcel query, resolved through the Assessor's site address), null (none). unincorporated=true means county permits only."
      • changedOutput schema / properties / jurisdiction / properties / basis / enum
        Previous value: -[
        -  "city-limits",
        -  "geocoder-city",
        -  "address-text",
        -  null
        -]New value: +[
        +  "city-limits",
        +  "geocoder-city",
        +  "address-text",
        +  "parcel-site-address",
        +  null
        +]
      • changedOutput schema / properties / next_step / properties / query_type / enum
        Previous value: -[
        -  "address",
        -  "parcel",
        -  "permit"
        -]New value: +[
        +  "address",
        +  "parcel",
        +  "permit",
        +  "contractor"
        +]
      • changedOutput schema / properties / next_step / properties / reason / enum
        Previous value: -[
        -  "no_feed",
        -  "electrical_only",
        -  "parcel_resolution_failed",
        -  "source_incomplete",
        -  "source_blocked"
        -]New value: +[
        +  "no_feed",
        +  "electrical_only",
        +  "parcel_resolution_failed",
        +  "source_incomplete",
        +  "source_blocked",
        +  "source_capped"
        +]
      • changedOutput schema / properties / permits / items / properties / is_open / description
        Previous value: -"Normalized across vendor status vocabularies: false when finaled/closed/expired/withdrawn/etc., null when the source exposes no status"New value: +"Heuristic, census-tested weekly: false when finaled/closed/expired/withdrawn/etc. (or a finaled_date exists), true for issued/pending/review words, null when the source exposes no status. Check is_open_basis before relying on it."
      • addedOutput schema / properties / permits / items / properties / is_open_basis
        Added value: +{
        +  "description": "finaled_date = certain (the record carries a final date); status-vocabulary = regex over the vendor's status word (heuristic); null = no status available",
        +  "enum": [
        +    "finaled_date",
        +    "status-vocabulary",
        +    null
        +  ],
        +  "type": [
        +    "string",
        +    "null"
        +  ]
        +}
      • addedOutput schema / properties / routing_by_type
        Added value: +{
        +  "description": "Per permit type (building, mechanical_plumbing, electrical, land_use, engineering_row, fire, grading, septic) for the resolved jurisdiction: {system, portal, live, note}. live=true means that system is searched by this tool; otherwise the portal is where to look. Present for address queries and parcel queries that resolved a city.",
        +  "type": "object"
        +}
      • changedOutput schema / properties / summary / description
        Previous value: -"Computed over every permit matching since/types (not just the returned rows): total, matched, returned, truncated, open, closed, status_unknown, by_type, by_status, by_year, years [oldest, newest], latest {permit_number,type,status,date,jurisdiction}. Answer from this; drill into permits only when you need rows."New value: +"Computed over every permit matching since/types (not just the returned rows): total, matched, returned, truncated, open, closed, status_unknown, open_basis_counts {finaled_date, status-vocabulary} (how many open/closed verdicts rest on a fact vs the status-word heuristic), by_type, by_status, by_year, years [oldest, newest], latest {permit_number,type,status,date,jurisdiction}. Answer from this; drill into permits only when you need rows."
  2. 1 tool update
    • Changedking_county_permit_status1 field changed
      • changedOutput schema / properties / next_step / properties / reason / enum
        Previous value: -[
        -  "no_feed",
        -  "electrical_only",
        -  "parcel_resolution_failed",
        -  "source_incomplete"
        -]New value: +[
        +  "no_feed",
        +  "electrical_only",
        +  "parcel_resolution_failed",
        +  "source_incomplete",
        +  "source_blocked"
        +]
  3. 1 tool update
    • Changedking_county_permit_status10 fields changed
      • addedInput schema / properties / limit
        Added value: +{
        +  "default": 50,
        +  "description": "Max permits to return (newest first). summary always covers the whole matched set, so start small and raise only if you need the rows.",
        +  "minimum": 0,
        +  "type": "integer"
        +}
      • addedInput schema / properties / since
        Added value: +{
        +  "description": "Only permits applied/issued on or after this date (YYYY-MM-DD).",
        +  "pattern": "^\\d{4}-\\d{2}-\\d{2}$",
        +  "type": "string"
        +}
      • addedInput schema / properties / types
        Added value: +{
        +  "description": "Case-insensitive substrings matched against each permit's type, e.g. ['electrical', 'mechanical'].",
        +  "items": {
        +    "type": "string"
        +  },
        +  "type": "array"
        +}
      • addedOutput schema / properties / address_resolution / properties / candidate_parcels
        Added value: +{
        +  "description": "Present when several parcels sit within 40 ft of an interpolated point; the first was used",
        +  "items": {
        +    "type": "string"
        +  },
        +  "type": "array"
        +}
      • addedOutput schema / properties / address_resolution / properties / parcel_basis
        Added value: +{
        +  "description": "How the parcel was found: the locator's address point; the parcel polygon under an interpolated point; or the nearest parcel within 40 ft (check candidate_parcels)",
        +  "enum": [
        +    "address-point",
        +    "parcel-polygon",
        +    "nearby-parcel",
        +    null
        +  ],
        +  "type": [
        +    "string",
        +    "null"
        +  ]
        +}
      • addedOutput schema / properties / filters
        Added value: +{
        +  "description": "The limit/since/types that produced this response",
        +  "type": "object"
        +}
      • addedOutput schema / properties / permit_count / description
        Added value: +"Unique permits found before any since/types filter (= summary.total)"
      • changedOutput schema / properties / permits / description
        Previous value: -"Permit records sorted newest applied_date first."New value: +"Up to `limit` permit records, newest first (applied_date, else issued_date)."
      • addedOutput schema / properties / summary
        Added value: +{
        +  "description": "Computed over every permit matching since/types (not just the returned rows): total, matched, returned, truncated, open, closed, status_unknown, by_type, by_status, by_year, years [oldest, newest], latest {permit_number,type,status,date,jurisdiction}. Answer from this; drill into permits only when you need rows.",
        +  "type": "object"
        +}
      • changedOutput schema / properties / trust_level / description
        Previous value: -"live — every applicable source answered; partial — some source errored or a city portal needs manual follow-up; fallback — nothing searchable, use separate_portal"New value: +"live — every applicable source answered; partial — a source errored or hit its result cap (see errors); fallback — nothing searchable, use next_step. A city needing manual follow-up (next_step) does not by itself lower trust."
  4. 1 tool update
    • First observedking_county_permit_status

Publisher details

Operator
Second Landings LLC · Publisher source
Vendor relationship
Not applicable
Trust center
Not applicable
Restrictions
Not applicable

Related MCP Connectors

Related MCP Servers

  • A
    license
    A
    quality
    A
    maintenance
    A read-only MCP server that exposes SF Peninsula building-permit and parcel-buildability data, enabling queries on permits, SB 9 eligibility, ADU potential, and redevelopment leads.
    6
    24 npm
    MIT
  • F
    license
    Not graded
    quality
    B
    maintenance
    Provides read-only MCP tools to query building construction approval lifecycle data, covering project discovery, bidding, contracts, drawing review, permits, and completion records.
    1
    -
  • F
    license
    Not graded
    quality
    C
    maintenance
    Read-only MCP server providing direct, credentialed access to parcel data via Regrid and county ArcGIS sources, with tools for querying by point, owner, size, and county.
    -
Try in Browser

Glama MCP Gateway

Add one secure layer between your agents and this server.