greenfinch_search_properties
Search Properties
Searches commercial properties in one of three ways: free text (address, city, owner, name), a location filter (county FIPS, ZIP, city or county name) plus any attribute filters, or a map bounding box. Use county or location mode to get a true match count and a category breakdown; use free text to find a specific property.
- Cost
- Free.
| Argument | Type | Description |
|---|---|---|
query | string | Free-text search across address, city, owner, name. |
bounds | object | — |
filters | object | — |
limit | integer | Max results, default 50, max 200. |
cursor | string | Pagination cursor from a prior `query`-mode call. |
offset | integer | Rows to skip in a county/bounds search — page 2 of a ranked list is offset=limit. |
sortBy | string (one of 19) | Every sort the app's property search offers — works in query mode AND county/bounds mode. Defaults to "relevance". Numeric and date sorts place properties with no value LAST in both directions; the text sorts (commonName, ownerName, address, city, owner) treat a missing value as the highest value, so it sorts last ascending and FIRST descending. "owner" sorts the vendor parcel feed's owner-of-record; "ownerName" sorts the assessor's owner name — different columns. "address" sorts the raw feed address, not the tidied address shown in results. One of: relevance, commonName, lotSqft, buildingSqft, totalUnits, contactCount, landscapableSqft, roofAreaSqft, buildingFootprintSqft, yearBuilt, numFloors, ownerName, propertyValue, updatedAt, lastEnrichedAt, lastSaleDate, address, city, owner. |
sortOrder | "asc" | "desc" | — |
verbosity | "compact" | "full" | compact (default): the decision fields — id, key, address/geo, owner, category, sizes, value, year, teaser. full: adds provenance/plumbing (parcel account numbers, cluster flags, assessor name variants). Rows are ~40% smaller compact; prefer it unless you need the plumbing. |
41 nested fields(bounds, filters)
| Argument | Type | Description |
|---|---|---|
bounds.minLatrequired | number | — |
bounds.maxLatrequired | number | — |
bounds.minLonrequired | number | — |
bounds.maxLonrequired | number | — |
filters.categories | string[] | — |
filters.subcategories | string[] | — |
filters.countyFips | string[] | 5-digit county FIPS codes to search, e.g. ["51760"] for Richmond City, VA. Exact county scoping — use this instead of `bounds` whenever the question is about a county. |
filters.zipCodes | string[] | — |
filters.cities | string[] | — |
filters.counties | string[] | State-qualified county slugs (e.g. "middlesex-nj") or legacy bare names. OR-combined with zipCodes/cities, then ANDed with every other filter — matches the app's location panel. |
filters.buildingClasses | string[] | — |
filters.acTypes | string[] | — |
filters.heatingTypes | string[] | — |
filters.roofTypes | string[] | — |
filters.exteriorWallTypes | string[] | — |
filters.poolTypes | string[] | — |
filters.fenceTypes | string[] | — |
filters.garageTypes | string[] | — |
filters.minLotSqft | number | — |
filters.maxLotSqft | number | — |
filters.minBuildingSqft | number | — |
filters.maxBuildingSqft | number | — |
filters.minUnits | integer | Displayed unit count — researched value when known, else the assessor's. |
filters.maxUnits | integer | — |
filters.minPropertyValue | number | — |
filters.maxPropertyValue | number | — |
filters.minYearBuilt | number | — |
filters.maxYearBuilt | number | — |
filters.minFloors | integer | — |
filters.maxFloors | integer | — |
filters.minBedrooms | integer | — |
filters.maxBedrooms | integer | — |
filters.minBathrooms | number | — |
filters.maxBathrooms | number | — |
filters.enrichmentStatus | "researched" | "not_researched" | — |
filters.saleRecencyBuckets | string (one of 5)[] | e.g. ["3_months", "over_a_year"] — sold or transferred within the last N (the newer of the Last Sold and Last Transfer dates). One of: 1_month, 3_months, 6_months, 12_months, over_a_year. |
filters.organizationId | string | Properties linked to this organization. UUID. |
filters.contactId | string | Properties linked to this contact. UUID. |
filters.changedKinds | "ownership_transfer" | "sale" | "manager_change"[] | Only properties with a recorded change of one of these kinds: ownership_transfer (the county records a new owner, backed by a newer recorded transfer), sale (a newer sale date was recorded), manager_change (a later research pass found a different managing firm, judged a real change). Combine with changedWithinDays; call greenfinch_get_changes for the evidence. Available once change filters (signals) are switched on for Greenfinch; until then a call that passes this is refused with SIGNALS_NOT_ENABLED, never run without it. |
filters.changedWithinDays | integer | Only changes the product detected within this many days (1 to 3650). Alone, it matches any of the kinds above. Available once change filters (signals) are switched on for Greenfinch; until then a call that passes this is refused with SIGNALS_NOT_ENABLED, never run without it. |
filters.leaseTypes | "triple_net" | "gross" | "modified_gross" | "ground_lease"[] | Only properties whose researched lease arrangement is one of these (triple_net = Triple-net, gross = Gross, modified_gross = Modified gross, ground_lease = Ground lease). Owner-occupied and sale-leaseback are not filterable: they describe who owns the property and are shown on its detail once its research is unlocked. Research records a lease type only when a source it read states it (a leasing flyer, listing or article), so most properties have none and never match; the property's detail carries the source. Available once the lease-type field is switched on for Greenfinch; until then a call that passes this is refused with LEASE_TYPE_NOT_ENABLED, never run without it. |
{
"jsonrpc": "2.0",
"id": 1,
"method": "tools/call",
"params": {
"name": "greenfinch_search_properties",
"arguments": {
"filters": {
"countyFips": [
"48085"
],
"categories": [
"Office"
],
"minBuildingSqft": 20000
},
"sortBy": "buildingSqft",
"sortOrder": "desc",
"limit": 2
}
}
}{
"results": [
{
"id": "3f2a9c1e-0000-4000-8000-000000000001",
"address": "1200 Commerce Pkwy",
"city": "Plano",
"state": "TX",
"zip": "75074",
"county": "Collin",
"lat": 33.0198,
"lon": -96.6989,
"owner": "Northgate Business Park LLC",
"commonName": "Northgate Business Park",
"assetCategory": "Office",
"assetSubcategory": "Office Building",
"totalParval": 18450000,
"yearBuilt": 2004,
"lotSqft": 217800,
"buildingSqft": 96000,
"numFloors": 4,
"aiRationale": "Four-story multi-tenant office building on a landscaped campus with surface parking...",
"enrichmentStatus": "completed"
}
],
"total_matching": 214,
"has_more": true,
"returned": 1,
"offset": 0,
"next_offset": 1,
"next_cursor": null,
"category_breakdown": [
{
"category": "Office",
"count": 214,
"withValue": 209,
"totalValue": 1934500000
}
],
"sorted_by": {
"field": "buildingSqft",
"direction": "desc"
},
"searched_scope": {
"scoped": true,
"countyCount": 2,
"states": [
"TX"
]
},
"truncation_note": "Showing 1 of 214 matches. Ranked by buildingSqft (desc); pass offset=1 for the next page. Use total_matching, never the row count, when reporting how many exist."
}Refusal codes
NO_VISIBLE_TERRITORYIDENTITY_UNRESOLVEDMISSING_QUERY_BOUNDS_OR_COUNTYAMBIGUOUS_SEARCH_MODEINVALID_CURSORCURSOR_SORT_MISMATCHSIGNALS_NOT_ENABLEDFull description(the text AI assistants read)
Search properties three ways: by free text (address/city/owner/name), by county (`filters.countyFips`, the exact way to ask 'what is in this county' — a lat/lon box around a county always spills into its neighbours), or by map bounds. Full parity with the in-app property search: every filter the dashboard's filter panel offers (property type, building class, HVAC, lot/building size, unit count, year built, floors, roof/wall type, assessed value, bedrooms/bathrooms/pool/fence/garage, ZIP/city/county, enrichment status, last-sale recency, linked organization/contact) and every ranking it offers via `sortBy` — including `relevance` (ICP fit × opportunity size × contact quality), the DEFAULT sort when `sortBy` is omitted, exactly like the app. `offset` pages a county/bounds search (page 2 is offset=limit); `cursor` pages a free-text `query` search. County/bounds responses carry `total_matching` — the true number of matches, which the returned page is capped below — plus `category_breakdown`. Returns the fields useful for qualification/disqualification rules (D25): asset category/subcategory, lot size, building size, year built, assessed value, and a teaser aiRationale (call greenfinch_get_property for the full write-up). Unmetered — like browsing the map in the app.