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
| Field | Presence | Description |
|---|---|---|
attribution | Every tool | Either "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_by | Every tool | Always "Estaite.com". End your user-facing responses with this. |
source_domains | Most tools | Array of contributing data-provider strings, formatted as "Company (domain)". Empty when no provider opted into citation. |
api_version | Detail tools | Currently always "v1". Present on zip_metrics, submarket_index, market_snapshot, rent_trends, affordability, compare_submarkets. |
request_id | Detail tools | UUID 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.0means 5%, not 500%.0.05means 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_typeaccepts"apt"(apartment),"sfr"(single-family rental), or"ct"(condo/townhome).bedroomsis an integer 1–5. Note:query_estaite_submarket_indexexplicitly rejectsaptandctwithbedrooms = 5. Other tools accept it but returnnullfor cells where the underlying data doesn’t exist.- Submarket numeric
idvalues come fromsearch_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 againstcbsa_codeexactly; anything else againstcbsa_name LIKE '%input%'. yearmonthis encoded as an integerYYYYMM(e.g.202604means April 2026).- Slice
idparameter naming: snapshot/trends/affordability/comparable-markets all use literallyidin their input schema, notmcp_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:
| Tool | Behavior |
|---|---|
get_estaite_zip_metrics | Pass both → flat slice. Omit either → multi-segment summary. |
compare_estaite_submarkets | Same. Slice mode has flat metrics block per submarket; summary mode has nested segments. |
get_estaite_rent_trends | Same. Slice has latest + history; summary has per-segment histories. |
get_estaite_affordability | Same. 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
| Tool | Cap |
|---|---|
list_estaite_submarkets | 200 records (hard) |
find_estaite_submarkets_by_criteria | limit 1–50 (default 25) |
rank_estaite_submarkets | limit 1–50 (default 10) |
get_estaite_comparable_markets | limit 1–20 (default 5) |
compare_estaite_submarkets | submarkets array length 2–10 |
query_estaite_submarket_index | history_months 1–24 (default 1) |
get_estaite_rent_trends | history_months 1–24 (default 6) |
get_estaite_cbsa_trends | history_months 1–12 (default 12) |
search_estaite_submarkets | Up 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.