Skip to content

Common Patterns

This page documents the conventions every Estaite MCP tool follows. Read it once and you can skip the boilerplate in every per-tool reference.

Envelope fields shared by every response

FieldPresenceDescription
attributionEvery toolEither "Data via Estaite Submarket Index" (default) or "Data provided by <Company> (<domain>)" when one or more contributing data providers cite the underlying submarket(s). Echo this string verbatim in any user-facing output.
powered_byEvery toolAlways "Estaite.com". End your user-facing responses with this.
source_domainsMost toolsArray of contributing data-provider strings, formatted as "Company (domain)". Empty when no provider opted into citation.
api_versionDetail toolsCurrently always "v1". Present on zip_metrics, submarket_index, market_snapshot, rent_trends, affordability, compare_submarkets.
request_idDetail toolsUUID for support and log correlation. Same presence as api_version.

Percent values are whole-percent everywhere

The single most common pitfall. Every percent field returned by an Estaite tool is in whole-percent, not decimal:

  • 5.0 means 5%, not 500%.
  • 0.05 means 0.05%, not 5%.

Applies to: every field with _yoy, _change, _growth, vacancy_rate, saturation, rent_to_income, rti, and the like. Don’t multiply by 100 before display.

The one place this matters in inputs too: find_estaite_submarkets_by_criteria.min_yoy_growth and .max_vacancy — pass 5 for 5%, not 0.05. (Note: the MCP server’s input-schema description for those two parameters currently says “decimal” — that description is wrong; the actual filter expects whole-percent.)

Shared input conventions

  • property_type accepts "apt" (apartment), "sfr" (single-family rental), or "ct" (condo/townhome).
  • bedrooms is an integer 1–5. Note: query_estaite_submarket_index explicitly rejects apt and ct with bedrooms = 5. Other tools accept it but return null for cells where the underlying data doesn’t exist.
  • Submarket numeric id values come from search_estaite_submarkets. Don’t infer or hand-roll ids.
  • CBSA inputs accept either a numeric code (e.g. "19100") or a partial name (e.g. "Dallas"). Anything that’s all digits gets matched against cbsa_code exactly; anything else against cbsa_name LIKE '%input%'.
  • yearmonth is encoded as an integer YYYYMM (e.g. 202604 means April 2026).
  • Slice id parameter naming: snapshot/trends/affordability/comparable-markets all use literally id in their input schema, not mcp_submarket_id. Send {"id": 1}, not {"mcp_submarket_id": 1}.

Read-only, idempotent

Every tool is annotated as:

{
"readOnlyHint": true,
"destructiveHint": false,
"idempotentHint": true,
"openWorldHint": true
}

There are no write operations on the public Estaite MCP server. Calling the same tool with the same arguments returns the same data within a given month’s publication window.

Slice vs summary mode

Several tools return different shapes depending on whether you supply property_type AND bedrooms:

ToolBehavior
get_estaite_zip_metricsPass both → flat slice. Omit either → multi-segment summary.
compare_estaite_submarketsSame. Slice mode has flat metrics block per submarket; summary mode has nested segments.
get_estaite_rent_trendsSame. Slice has latest + history; summary has per-segment histories.
get_estaite_affordabilitySame. Slice has flat fields; summary has per-segment cells.

Summary mode always returns the shape segments.{apartments|single_family|condo_townhome}.br{1..4}.

get_estaite_comparable_markets does not expose property_type/bedrooms via the MCP schema, so it always returns the multi-segment shape regardless of what you pass.

Caps and limits

ToolCap
list_estaite_submarkets200 records (hard)
find_estaite_submarkets_by_criterialimit 1–50 (default 25)
rank_estaite_submarketslimit 1–50 (default 10)
get_estaite_comparable_marketslimit 1–20 (default 5)
compare_estaite_submarketssubmarkets array length 2–10
query_estaite_submarket_indexhistory_months 1–24 (default 1)
get_estaite_rent_trendshistory_months 1–24 (default 6)
get_estaite_cbsa_trendshistory_months 1–12 (default 12)
search_estaite_submarketsUp to 20 matches (hard, no input cap)

Errors

Tools return errors as { isError: true, content: [{ type: "text", text: "<stringified error JSON>" }] }. The text is a JSON object with at least error: "<CODE>". Some errors include valid_values or warnings arrays. See Errors for the consolidated list.

Pacing

The Free tier allows 2 tool calls per second. Most multi-tool workflows need a short sleep(0.6) (or your language equivalent) between calls, or proper 429 handling with Retry-After. See Rate Limits for details and per-plan limits.