Skip to main content
Glama

Microburbs Australian Property Data

Suburb · Street-level price forecasts

suburbs_street_forecasts
Read-onlyIdempotent

2/4/8-year price forecasts for every street in the suburb, anchored to the real sold median.

Unpaged by default. Large suburbs are large — Point Cook has 943 streets (~1.4 MB) — so pass limit/offset when you don't need the lot. total reports how many exist. Flat price per call regardless of page size.

Input Schema

TableJSON Schema
NameRequiredDescriptionDefault
limitNoStreets to return (default: all).
offsetNoStreet offset — page with `limit`.
suburb_nameYes

Schema Changelog

Changes observed during successful MCP inspections.

  1. Changed1 schema field changed
    • changedOutput schema / (root)
      Previous value: -{
      -  "properties": {
      -    "available": {
      -      "anyOf": [
      -        {
      -          "type": "boolean"
      -        },
      -        {
      -          "type": "null"
      -        }
      -      ],
      -      "description": "`false` on no-data responses. Omitted on success — branch on `data !== null` if you want a single discriminator.",
      -      "title": "Available"
      -    },
      -    "data": {
      -      "anyOf": [
      -        {
      -          "additionalProperties": true,
      -          "description": "Projected house-price paths for the streets of one suburb, 2, 4 and\n8 years out.\n\nTwo suburbs can share a median and still be made of streets that behave\nvery differently; this endpoint is the street-by-street breakdown behind\nthe suburb-level number. Each row gives a street's current median, where\nthe model expects it in 2/4/8 years (in dollars and as a per-year growth\nrate), the year-by-year path it took to get here, and a little context\nabout the street itself — size, rent, how often it turns over.\n\nCoverage is deliberately partial: a street only appears if there is a\nreal sold median to anchor it to, so `streets` is a subset of the\nsuburb's streets, and `total` counts only those.",
      -          "example": {
      -            "area_level": "suburb",
      -            "area_name": "Belmont North",
      -            "metric": "street_price_forecasts",
      -            "streets": [
      -              {
      -                "annual_2y": 8,
      -                "annual_4y": 6.3,
      -                "annual_8y": 5,
      -                "current_price": 1159000,
      -                "history": [
      -                  {
      -                    "price": 1038603.34,
      -                    "suburb_med": 866399,
      -                    "year": 2024
      -                  },
      -                  {
      -                    "price": 1083975.34,
      -                    "suburb_med": 948908,
      -                    "year": 2025
      -                  },
      -                  {
      -                    "price": 1159000,
      -                    "suburb_med": 1040068,
      -                    "year": 2026
      -                  }
      -                ],
      -                "houses_on_street": 146,
      -                "median_house_rent_week": 791.2,
      -                "n_sales": 289,
      -                "rental_turnover": "Every 5.9 years (quite tightly held)",
      -                "renters_pct": "18%",
      -                "sale_turnover": "Every 12.0 years (average turnover)",
      -                "street": "Wommara Ave",
      -                "target_2y": 1352652.97,
      -                "target_4y": 1480849.45,
      -                "target_8y": 1718217.61,
      -                "units_on_street": 4
      -              }
      -            ]
      -          },
      -          "properties": {
      -            "area_level": {
      -              "description": "Geographic level of `area_name`. Always 'suburb' here; present so responses across the area endpoints share one shape.",
      -              "title": "Area Level",
      -              "type": "string"
      -            },
      -            "area_name": {
      -              "description": "Suburb these streets belong to, as the canonical ABS SAL name — the resolved form of whatever suburb was requested, so echo this back rather than the caller's input.",
      -              "title": "Area Name",
      -              "type": "string"
      -            },
      -            "metric": {
      -              "description": "Identifies which dataset this payload is, for callers routing several area responses through common code. Always 'street_price_forecasts'.",
      -              "title": "Metric",
      -              "type": "string"
      -            },
      -            "streets": {
      -              "description": "One entry per forecastable street. Order is the stored order — stable between calls (so `offset` paging is safe) but not sorted by price, growth or name; sort client-side if you need a ranking.",
      -              "items": {
      -                "additionalProperties": true,
      -                "description": "Projected house-price path for one street in the suburb.\n\n**How to read a row.** `current_price` is where the street is today\n(an observed sold median). The three `target_*` fields are that same\nquantity projected 2, 4 and 8 years out, in dollars. The three\n`annual_*` fields are the same three projections expressed as a\ncompound annual growth rate in percent — they are a restatement of\nthe targets, not extra information, so\n`target_2y ≈ current_price × (1 + annual_2y/100) ** 2` (8.0 in\n`annual_2y` means 8% a year, not 0.08 and not 8% in total). The\nhorizons are cumulative from today, so `annual_4y` covers years 1–4\nincluding the years `annual_2y` already covered; they are three views\nof one path, not three consecutive segments.\n\n**Everything in dollars is anchored to the real sold median.** The\nforecast model carries its own estimate of what a street is worth\ntoday, and on tightly-held high-end streets that estimate can sit far\nbelow the price houses actually change hands at. So every dollar\nfigure in this row — `current_price`, the targets, and\n`history[].price` — is rescaled by one factor per street\n(`sold median ÷ model estimate`), which leaves the growth *shape*\nexactly as the model produced it while putting the levels on the real\nprice scale. The percentages are untouched by that rescale, because\na ratio cancels it out.",
      -                "example": {
      -                  "annual_2y": 8,
      -                  "annual_4y": 6.3,
      -                  "annual_8y": 5,
      -                  "current_price": 1159000,
      -                  "history": [
      -                    {
      -                      "price": 1038603.34,
      -                      "suburb_med": 866399,
      -                      "year": 2024
      -                    },
      -                    {
      -                      "price": 1083975.34,
      -                      "suburb_med": 948908,
      -                      "year": 2025
      -                    },
      -                    {
      -                      "price": 1159000,
      -                      "suburb_med": 1040068,
      -                      "year": 2026
      -                    }
      -                  ],
      -                  "houses_on_street": 146,
      -                  "median_house_rent_week": 791.2,
      -                  "n_sales": 289,
      -                  "rental_turnover": "Every 5.9 years (quite tightly held)",
      -                  "renters_pct": "18%",
      -                  "sale_turnover": "Every 12.0 years (average turnover)",
      -                  "street": "Wommara Ave",
      -                  "target_2y": 1352652.97,
      -                  "target_4y": 1480849.45,
      -                  "target_8y": 1718217.61,
      -                  "units_on_street": 4
      -                },
      -                "properties": {
      -                  "annual_2y": {
      -                    "anyOf": [
      -                      {
      -                        "type": "number"
      -                      },
      -                      {
      -                        "type": "null"
      -                      }
      -                    ],
      -                    "description": "The `target_2y` projection expressed as a compound annual growth rate, in percent per year — `8.0` means 8% a year (a decimal fraction like 0.08 is not what this field carries), compounding to roughly 16.6% in total over the two years. Same growth as `target_2y`, stated per-annum.",
      -                    "title": "Annual 2Y"
      -                  },
      -                  "annual_4y": {
      -                    "anyOf": [
      -                      {
      -                        "type": "number"
      -                      },
      -                      {
      -                        "type": "null"
      -                      }
      -                    ],
      -                    "description": "The `target_4y` projection as a compound annual growth rate, in percent per year, averaged across all four years (not the growth in years 3–4 alone). Typically lower than `annual_2y`: near-term momentum is assumed to fade toward a long-run rate.",
      -                    "title": "Annual 4Y"
      -                  },
      -                  "annual_8y": {
      -                    "anyOf": [
      -                      {
      -                        "type": "number"
      -                      },
      -                      {
      -                        "type": "null"
      -                      }
      -                    ],
      -                    "description": "The `target_8y` projection as a compound annual growth rate, in percent per year, averaged across all eight years. This is the closest thing here to the street's long-run trend rate.",
      -                    "title": "Annual 8Y"
      -                  },
      -                  "current_price": {
      -                    "description": "The street's current median house price in AUD, and the base every `target_*` and `annual_*` figure below is measured from. This is an observed sold median — what houses on the street actually sold for — not the forecast model's own estimate of present value. Streets with no sold-median on record are dropped from `streets` entirely rather than falling back to a model estimate, so this field is never a guess and never null.",
      -                    "title": "Current Price",
      -                    "type": "number"
      -                  },
      -                  "history": {
      -                    "description": "Where the street has come from: one entry per year, oldest first, each pairing the street's modelled price with the suburb median for that year. The final entry is the present and its `price` equals `current_price`, so `history` and the `target_*` fields join into one continuous line through today.",
      -                    "items": {
      -                      "additionalProperties": true,
      -                      "description": "One year of the street's modelled price history, with the suburb\nmedian alongside it as a baseline.\n\nTwo series, two different things. `price` is *this street* — a\nmodelled house-price level, because most streets do not sell enough\nhouses in a year to have a real median of their own. `suburb_med` is\nthe whole suburb's median for the same year, included so you can see\nwhether the street ran ahead of or behind its suburb. Compare the two\nas a *shape* over time, not as a like-for-like pair of medians.",
      -                      "example": {
      -                        "price": 970000,
      -                        "suburb_med": 1040068,
      -                        "year": 2026
      -                      },
      -                      "properties": {
      -                        "price": {
      -                          "anyOf": [
      -                            {
      -                              "type": "number"
      -                            },
      -                            {
      -                              "type": "null"
      -                            }
      -                          ],
      -                          "description": "Modelled median house price for this street in `year`, in AUD. Not an observed median — the street model's yearly level, rescaled by the same `current_price / model_estimate` factor applied to the targets, so the final year of `history` equals `current_price` and the chart line lands on the headline figure. Null when the model has no level for that year.",
      -                          "title": "Price"
      -                        },
      -                        "suburb_med": {
      -                          "anyOf": [
      -                            {
      -                              "type": "number"
      -                            },
      -                            {
      -                              "type": "null"
      -                            }
      -                          ],
      -                          "description": "Median house price for the whole suburb in `year`, in AUD. A context baseline only: it is the suburb's own observed median and is NOT rescaled, so it is on a different footing from `price`. Use it to judge relative direction (street outpacing the suburb or not), not to compute a precise street-vs-suburb premium.",
      -                          "title": "Suburb Med"
      -                        },
      -                        "year": {
      -                          "description": "Calendar year the two prices below refer to.",
      -                          "title": "Year",
      -                          "type": "integer"
      -                        }
      -                      },
      -                      "required": [
      -                        "year"
      -                      ],
      -                      "title": "StreetHistoryPoint",
      -                      "type": "object"
      -                    },
      -                    "title": "History",
      -                    "type": "array"
      -                  },
      -                  "houses_on_street": {
      -                    "anyOf": [
      -                      {
      -                        "type": "integer"
      -                      },
      -                      {
      -                        "type": "null"
      -                      }
      -                    ],
      -                    "description": "Number of separate houses on the street — the size of the pool the median and turnover figures describe. A street with a dozen houses will have noisier numbers than one with two hundred.",
      -                    "title": "Houses On Street"
      -                  },
      -                  "median_house_rent_week": {
      -                    "anyOf": [
      -                      {
      -                        "type": "number"
      -                      },
      -                      {
      -                        "type": "null"
      -                      }
      -                    ],
      -                    "description": "Median advertised rent for a house on this street in AUD per week (Australian convention) — multiply by 52 for an annual figure. Houses only, and independent of the price forecast.",
      -                    "title": "Median House Rent Week"
      -                  },
      -                  "n_sales": {
      -                    "description": "Count of sales the street's price model was fitted on. Read it as a confidence weight — a street with a handful of sales behind it has a much softer forecast than one with hundreds — rather than as sales in any particular period.",
      -                    "title": "N Sales",
      -                    "type": "integer"
      -                  },
      -                  "rental_turnover": {
      -                    "anyOf": [
      -                      {
      -                        "type": "string"
      -                      },
      -                      {
      -                        "type": "null"
      -                      }
      -                    ],
      -                    "description": "The same idea for tenancies rather than sales — how often rentals on the street turn over, as display text, e.g. 'Every 5.9 years (quite tightly held)'. A long interval suggests tenants who stay.",
      -                    "title": "Rental Turnover"
      -                  },
      -                  "renters_pct": {
      -                    "anyOf": [
      -                      {
      -                        "type": "string"
      -                      },
      -                      {
      -                        "type": "null"
      -                      }
      -                    ],
      -                    "description": "Share of dwellings on the street occupied by renters rather than owners, as a preformatted string including the '%' sign (e.g. '18%') — not a number, and not a fraction. Strip the sign before doing arithmetic with it.",
      -                    "title": "Renters Pct"
      -                  },
      -                  "sale_turnover": {
      -                    "anyOf": [
      -                      {
      -                        "type": "string"
      -                      },
      -                      {
      -                        "type": "null"
      -                      }
      -                    ],
      -                    "description": "How often a typical house on the street changes hands, already written out for display — e.g. 'Every 12.0 years (average turnover)'. A sentence, not a number: the interval and its plain-language reading (tightly held vs. average vs. frequently traded) are baked into the one string. Parse it only if you must; the wording is not a stable enum.",
      -                    "title": "Sale Turnover"
      -                  },
      -                  "street": {
      -                    "description": "Street name as stored, e.g. 'Wommara Ave'. May be a shortened form of the full name (leading words only), so match it loosely rather than as an exact address component.",
      -                    "title": "Street",
      -                    "type": "string"
      -                  },
      -                  "target_2y": {
      -                    "anyOf": [
      -                      {
      -                        "type": "number"
      -                      },
      -                      {
      -                        "type": "null"
      -                      }
      -                    ],
      -                    "description": "Projected median house price for this street two years from now, in AUD. A price level, not a change and not a multiplier: compare it directly against `current_price` to see the implied gain. Two years runs from the latest year in `history` (which equals today's `current_price`). Null when the model produced no 2-year figure.",
      -                    "title": "Target 2Y"
      -                  },
      -                  "target_4y": {
      -                    "anyOf": [
      -                      {
      -                        "type": "number"
      -                      },
      -                      {
      -                        "type": "null"
      -                      }
      -                    ],
      -                    "description": "Projected median house price for this street four years from now, in AUD — same basis as `target_2y`, longer horizon. Cumulative from today, so it includes the two years `target_2y` covers.",
      -                    "title": "Target 4Y"
      -                  },
      -                  "target_8y": {
      -                    "anyOf": [
      -                      {
      -                        "type": "number"
      -                      },
      -                      {
      -                        "type": "null"
      -                      }
      -                    ],
      -                    "description": "Projected median house price for this street eight years from now, in AUD — same basis as `target_2y`. The longest horizon offered and correspondingly the least certain.",
      -                    "title": "Target 8Y"
      -                  },
      -                  "units_on_street": {
      -                    "anyOf": [
      -                      {
      -                        "type": "integer"
      -                      },
      -                      {
      -                        "type": "null"
      -                      }
      -                    ],
      -                    "description": "Number of units/apartments on the street. Note that the price fields in this row are house prices; a high unit count tells you the street's character but does not feed the forecast.",
      -                    "title": "Units On Street"
      -                  }
      -                },
      -                "required": [
      -                  "street",
      -                  "current_price",
      -                  "n_sales",
      -                  "history"
      -                ],
      -                "title": "StreetForecastRow",
      -                "type": "object"
      -              },
      -              "title": "Streets",
      -              "type": "array"
      -            },
      -            "total": {
      -              "description": "How many forecastable streets the suburb has in all — counted before `limit`/`offset` are applied, so it is the figure to page against and will exceed `len(streets)` on a paged request. Streets with no sold median are already excluded, so this is usually fewer than the suburb's true street count.",
      -              "title": "Total",
      -              "type": "integer"
      -            }
      -          },
      -          "required": [
      -            "area_name",
      -            "area_level",
      -            "metric",
      -            "total",
      -            "streets"
      -          ],
      -          "title": "StreetForecasts",
      -          "type": "object"
      -        },
      -        {
      -          "type": "null"
      -        }
      -      ],
      -      "description": "The endpoint's payload, or `null` when Microburbs has no value."
      -    },
      -    "message": {
      -      "anyOf": [
      -        {
      -          "type": "string"
      -        },
      -        {
      -          "type": "null"
      -        }
      -      ],
      -      "description": "Human-readable explanation. Omitted on success.",
      -      "title": "Message"
      -    },
      -    "reason": {
      -      "anyOf": [
      -        {
      -          "type": "string"
      -        },
      -        {
      -          "type": "null"
      -        }
      -      ],
      -      "description": "Machine-readable slug naming the no-data condition (e.g. `no_avm_for_GANSW704074813`). Stable per endpoint. Omitted on success.",
      -      "title": "Reason"
      -    }
      -  },
      -  "title": "ApiResponse[StreetForecasts]",
      -  "type": "object",
      -  "x-fastmcp-top-level-schema": "ApiResponse_StreetForecasts_"
      -}New value: +null
  2. First observed

TDQS

A4.5/5.0
Behavior4/5

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

Annotations already declare readOnlyHint, idempotentHint, and destructiveHint, so the description's additional behavior is a bonus. It usefully discloses that the endpoint is 'Unpaged by default', can return ~1.4 MB, provides a `total` count, and has flat pricing. This goes beyond the annotations and helps agents avoid oversized calls.

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

Conciseness5/5

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

Two tight paragraphs: the first front-loads the core purpose and data anchor, the second adds only high-value operational details. Every sentence earns its place, and there is no filler or repetition of schema structure.

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?

For a listing-style endpoint with no output schema, the description covers the essential operational context: time horizons, scope, default unpaged behavior, size risk, pagination fields, total count, and pricing. An agent has enough to decide whether and how to call it correctly.

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

Parameters4/5

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

Schema coverage is 67%, with `suburb_name` left undescribed, but the description helps by explaining why `limit`/`offset` matter and that `total` reports the full count. It adds practical meaning to pagination parameters beyond the schema's terse descriptions. A clearer definition of `suburb_name` would be needed for full compensation, but the remaining gap is minor.

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?

The description states a specific scope: '2/4/8-year price forecasts for every street in the suburb', which clearly identifies the resource and granularity. It distinguishes itself from suburb-level siblings by explicitly using 'every street in the suburb'. The title and description align without tautology.

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?

The description gives actionable guidance: 'pass `limit`/`offset` when you don't need the lot' and warns about large payloads using Point Cook as an example. It also notes 'Flat price per call regardless of page size', which helps callers decide on paging strategy. It does not name a specific sibling alternative for suburb-level forecasts, but the usage context is clear.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

Try in Browser

Glama MCP Gateway

Add one secure layer between your agents and this server.

Resources