Skip to main content
Glama

GeoAVM MCP

Geospatial automated valuation model (AVM) server over the Model Context Protocol. Four MCP tools (health, distance_km, select_comps, value_parcel) and a matching CLI, with JSON in/out for scripting.

Status

Stages 1–8 complete, documentation in progress (v0.1.0).

  • 56 tests, 99% statement coverage of src/, enforced at a 95% floor in CI on Python 3.10–3.14, plus a wheel build and installed-wheel smoke test.

  • No live data providers. Comps come from a JSON file you supply, with distance_km already measured. The .env.example geocoder keys are reserved, not read — see Reality check.

  • Valuation is transparent but narrow: inverse-distance weighting with no time or attribute adjustments. Read docs/AVM_METHOD.md before trusting a number.

Related MCP server: assessor-lookup-mcp

Install

uv venv && uv pip install -e ".[dev]"      # or: python -m venv .venv && .venv\Scripts\activate

Two entry points, same CLI: geoavm and geoavm-mcp.

MCP client setup

stdio is the default and works everywhere. Install the package into an environment your client can reach, then point the client at the console script.

Claude Desktop (claude_desktop_config.json):

{
  "mcpServers": {
    "geoavm": { "command": "geoavm-mcp", "args": ["serve"] }
  }
}

opencode (opencode.json):

{
  "mcp": {
    "geoavm": { "type": "local", "command": ["geoavm-mcp", "serve"], "enabled": true }
  }
}

If the script is not on the client's PATH, use the interpreter instead:

{ "command": "/path/to/.venv/bin/python", "args": ["-m", "geoavm_mcp", "serve"] }

HTTP instead of stdio:

geoavm serve --transport streamable-http --host 127.0.0.1 --port 8000
# endpoint: http://127.0.0.1:8000/mcp

--transport sse serves /sse for older clients. Both bind 127.0.0.1:8000 by default (GEOAVM_HOST / GEOAVM_PORT override). There is no auth layer — do not expose the HTTP transports to an untrusted network.

CLI

geoavm serve                      # stdio MCP server (default)
geoavm info                       # version + defaults
geoavm distance "30.2504,-97.7601" "30.2672,-97.7431"
2.4811 km

Comps: query.json is a CompsQuery, candidates.json a ComparableSale[].

geoavm comps query.json candidates.json            # table
geoavm comps query.json candidates.json --json     # machine-readable
                         Comps (3 of 4)
+--------------------------------------------------------------+
| apn | sale_date  | distance_km | sale_price | adjusted_price |
|-----+------------+-------------+------------+----------------|
| A-1 | 2025-11-04 | 0.420       | 715,000    | -              |
| A-2 | 2026-02-19 | 1.150       | 830,000    | -              |
| A-3 | 2025-08-27 | 1.620       | 655,000    | -              |
+--------------------------------------------------------------+

Valuation: parcel.json is a Parcel.

geoavm value parcel.json candidates.json --currency USD
geoavm value parcel.json candidates.json --json
         AVM 0205-0004-0031
+----------------------------------+
| Key          | Value             |
|--------------+-------------------|
| estimate     | 829,959 USD       |
| 90% interval | 662,717 - 997,202 |
| confidence   | 0.70              |
| method       | idw_ppsf          |
| comps used   | 4                 |
+----------------------------------+

Either file argument may be - to read from stdin, so a pipeline works:

curl -s https://example.com/comps.json | geoavm comps query.json -

Invalid input exits non-zero with the pydantic message; missing files and bad JSON are reported by path. python -m geoavm_mcp is equivalent to geoavm.

Example payloads for both commands are in docs/TOOLS.md.

Tools

Tool

Purpose

health

server name, version, timestamp

distance_km

great-circle distance between two WGS84 points

select_comps

filter + rank comps for a CompsQuery (nearest first, capped)

value_parcel

AVM estimate for a Parcel from comps: point value, 90% interval, confidence, warnings

Full signatures, field tables, JSON examples, and gotchas: docs/TOOLS.md.

How it values

select_comps filters by radius/type/date/area and sorts by distance (newest breaks ties); value_parcel weights the comps by 1 / (distance_km + 0.25), scales $/sqft to the subject when areas are known, and reports a weighted 90% interval plus data-quality warnings. No time adjustment, no attribute adjustment, no outlier rejection — the details and the caveats are in docs/AVM_METHOD.md.

Reality check

Honest limits, in the order they bite:

  1. You supply the comps and their distance_km. Nothing geocodes, fetches MLS data, or measures subject-to-comp distance for you. select_comps trusts the field.

  2. No market-time adjustment. Recent and stale sales weigh the same.

  3. The interval is a normal approximation, not a calibrated confidence interval. Treat confidence as a heuristic.

  4. Coordinates are metadata. A parcel without location still values.

Layout

src/geoavm_mcp/
  __init__.py      # public surface + __version__
  types.py         # pydantic models (Coordinates, BoundingBox, Parcel, ComparableSale, ...)
  geo.py           # pure geospatial math
  comps.py         # comp filtering + ranking (select_comps)
  valuation.py     # weighted valuation -> ValuationEstimate
  server.py        # create_mcp_server() factory + MCP tools
  cli.py           # click CLI (serve / info / distance / comps / value)
docs/
  TOOLS.md         # MCP tool reference
  AVM_METHOD.md    # valuation maths and limits
tests/             # types, comps, valuation, server tools, CLI, scaffold

Development

python -m pytest -q
python -m pytest -q --cov=geoavm_mcp --cov-report=term-missing --cov-fail-under=95
ruff check .
python -m build        # wheel + sdist

CI (.github/workflows/ci.yml) runs lint, the matrix above, and a wheel smoke test that imports the package, checks py.typed and entry points, then runs geoavm-mcp info and geoavm-mcp distance.

Config

Copy .env.example to .env. Secrets stay in the environment, never in the repo. Only GEOAVM_HOST and GEOAVM_PORT are read today; the rest is reserved for future provider stages.

License

MIT — see LICENSE. Changes: CHANGELOG.md.

Related MCP Connectors

Related MCP Servers

  • F
    license
    Not graded
    quality
    C
    maintenance
    A production-grade MCP server for querying U.S. Census Bureau data (ACS 5-Year and Decennial) with tools for geographic fuzzy matching, variable search, and batched data retrieval, backed by a PostgreSQL cache for performance.
    -
  • A
    license
    Not graded
    quality
    C
    maintenance
    Enables AI agents to look up county assessor public records for properties, check MLS discrepancies against public data, and discover new county assessor sources, all via a local MCP server for real-estate appraisal workflows.
    6
    MIT
  • 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.
    -
  • F
    license
    Not graded
    quality
    B
    maintenance
    Enables comparison of residential candidate areas by land price, station walking time, and public transit commute, with PMTiles-powered interactive maps. Provides MCP tools for listing layers, retrieving land prices, computing commutes, finding and comparing areas, and building area maps.
    -