mlsgrid-mcp
A Model Context Protocol server that lets AI
agents query real-estate (RESO / MLS Grid) data — search listings, pull comps,
read market stats — over a database you populate with its companion project,
mlsgrid-sync.
Status: pre-release (v0). The architecture is in place — the public
mls.Sourceseam, a stdio server on the official Go SDK, and the Postgres adapter — and the full curated tool set works end to end: freshness, search, listing detail, comps, price history, market stats, and open houses, plus an opt-in read-only SQL escape hatch. What remains before v0.1.0 is release polish; see the roadmap.
How it fits together
MLS Grid API ──▶ mlsgrid-sync ──▶ PostgreSQL ──▶ mlsgrid-mcp ──▶ your AI agent
(replication) (your data) (this repo) (Claude, …)
mlsgrid-sync does the replication and owns the schema
contract.
mlsgrid-mcp is a thin, read-only projection of that schema onto MCP tools.
It pins the contract's major version and checks it at startup, so the two
projects release independently.
Compliance — read this first
This server ships no MLS data and no credentials. It reads a database you populated under your own license. When you expose that data to an agent:
- You must hold an executed MLS Grid Data License Agreement and per-MLS approval for the feeds in your database.
- Anything an agent produces from the data is still bound by your license tier's display and distribution rules (IDX/VOW/back-office).
- The server is read-only by construction — it opens read-only database sessions and never writes to your feed.
Quickstart
Install a release binary or:
go install github.com/piotrsenkow/mlsgrid-mcp/cmd/mlsgrid-mcp@latest
Or run the released container image (published per release to GitHub Container Registry):
docker run --rm -i \
-e MLSGRID_MCP_DATABASE_URL=postgres://user:pass@host:5432/mls \
ghcr.io/piotrsenkow/mlsgrid-mcp:latest
Point it at the database mlsgrid-sync produced and verify the connection:
export MLSGRID_MCP_DATABASE_URL=postgres://user:pass@host:5432/mls?sslmode=disable
mlsgrid-mcp check
check asserts the schema-contract version and prints a data-freshness readout
(the same information the get_data_freshness tool returns). Running the binary
with no arguments serves the MCP protocol over stdio — that is how MCP clients
launch it.
Use it from Claude Code
claude mcp add mlsgrid -- \
env MLSGRID_MCP_DATABASE_URL=postgres://user:pass@host:5432/mls mlsgrid-mcp
Use it from Claude Desktop
Add to your claude_desktop_config.json:
{
"mcpServers": {
"mlsgrid": {
"command": "mlsgrid-mcp",
"env": {
"MLSGRID_MCP_DATABASE_URL": "postgres://user:pass@host:5432/mls"
}
}
}
}
For production, point the URL at a read-only database role — see docs/adapters.md.
query_sql (opt-in SQL escape hatch)
Beyond the curated tools, mlsgrid-mcp can expose a single tool, query_sql,
that runs a caller-supplied read-only SELECT. It is off by default and
meant for one-off questions the curated tools don't cover. Because it hands an
agent raw SQL, it is gated on three things at once:
- You enable it —
MLSGRID_MCP_SQL_ENABLED=true(orsql.enabled: true). - A least-privilege role — the server refuses to expose it over a
superuser connection, and every query runs in a read-only transaction under
a statement timeout (
MLSGRID_MCP_SQL_TIMEOUT, default5s) with a row cap (MLSGRID_MCP_SQL_MAX_ROWS, default1000). - A lexical guard — input that isn't a lone
SELECT/WITH, or that contains writes, DDL, multiple statements, or server-side file/IO functions, is rejected before it reaches the database.
Provision a dedicated read-only role and point the server at it (adjust the
schema if you changed it from the default mlsgrid):
CREATE ROLE mlsgrid_ro LOGIN PASSWORD '…'; -- not a superuser
GRANT CONNECT ON DATABASE mls TO mlsgrid_ro;
GRANT USAGE ON SCHEMA mlsgrid TO mlsgrid_ro;
GRANT SELECT ON ALL TABLES IN SCHEMA mlsgrid TO mlsgrid_ro;
-- so future mlsgrid-sync tables are readable too:
ALTER DEFAULT PRIVILEGES IN SCHEMA mlsgrid GRANT SELECT ON TABLES TO mlsgrid_ro;
export MLSGRID_MCP_DATABASE_URL=postgres://mlsgrid_ro:…@host:5432/mls
export MLSGRID_MCP_SQL_ENABLED=true
mlsgrid-mcp check # the features line shows sql=true when it will be exposed
check prints why the tool is withheld if the connection is a superuser or the
source can't back it. Leave MLSGRID_MCP_SQL_ENABLED unset to keep only the
curated tools.
Tools
Structured JSON out, whole-dollar money, a data-as-of timestamp on every response. Full catalog in docs/tools.md.
Extending it
The tools are written against one interface, mls.Source, with no knowledge of
where the data lives. Implement that interface over your own store — in a
separate, even private, repository — and reuse every tool via plain Go
composition. See docs/adapters.md and
docs/architecture.md.
License
Apache-2.0. Not affiliated with or endorsed by MLS Grid LLC.