rental-data
README.md
# rental-data MCP server
An MCP (Model Context Protocol) server that exposes a multifamily rental
dataset (markets, properties, rent, occupancy) to LLM tools like Claude
Desktop or Claude Code — you ask questions in plain English, the model calls
these tools to get real numbers back.
Built as a portfolio project mapped to: *"Build and maintain MCP server
integrations that expose data to LLM-powered tools."*
> Built as a portfolio project requiring MCP server development. Demonstrates: exposing a real dataset (multifamily rental data) to an LLM client via the Model Context Protocol, with tools for aggregation, anomaly detection, and per-entity summarization — the same patterns used for production data quality and reporting agents.
---
## What's here
- `data/make_data.py` — generates a synthetic-but-realistic rental dataset
(8 markets, 4 properties each, 12 months, 4 unit types = ~1,500 rows), with
two deliberate anomalies baked in so the anomaly tool has something to find.
- `server.py` — the MCP server itself. Three tools:
- `average_rent_by_market(unit_type)` — average rent per market, latest month
- `occupancy_anomalies(threshold_pct)` — flags month-over-month occupancy drops
- `property_summary(property_name)` — rent trend + current occupancy for one property
- `requirements.txt` — one dependency, pinned.
## 1. Setup
```bash
cd mcp-rental-server
python3 -m venv venv
source venv/bin/activate
pip install -r requirements.txt
python3 data/make_data.py # generates data/rentals.csv
```
## 2. Test it standalone
```bash
python3 -c "
from server import average_rent_by_market, occupancy_anomalies, property_summary
print(average_rent_by_market('2BR'))
print(occupancy_anomalies())
print(property_summary('AtlantaRidge1'))
"
```
You should see rent numbers by market, a flagged anomaly at `AtlantaRidge2`,
and a rent trend summary. If that prints cleanly, the server logic works —
the rest is just wiring it into a chat client.
## 3. Connect it to Claude Desktop
Find (or create) Claude Desktop's config file:
- **Mac**: `~/Library/Application Support/Claude/claude_desktop_config.json`
- **Windows**: `%APPDATA%\Claude\claude_desktop_config.json`
Add this (use the **absolute path** to your project + venv python):
```json
{
"mcpServers": {
"rental-data": {
"command": "/absolute/path/to/mcp-rental-server/venv/bin/python3",
"args": ["/absolute/path/to/mcp-rental-server/server.py"]
}
}
}
```
On Mac, get the absolute path with `pwd` while inside the project folder.
Fully quit and reopen Claude Desktop. You should see a small tools/plug icon
in the chat box — click it to confirm `rental-data` is connected with 3 tools.
## 4. Demo prompts (use these in your screen recording)
- "What's the average 2BR rent across all markets?"
- "Are there any properties with anomalous occupancy drops?"
- "Give me a summary of AtlantaRidge2 — what's going on with it?"
- "Which market has the highest 3BR rent, and how does that compare to Charlotte?"
Watch Claude call the tool (it'll show up as a tool-use step) and answer using
the real numbers, not a hallucinated guess. That contrast — grounded vs.
ungrounded answers — is worth narrating out loud in the video.
## 5. Upgrade path: swap SQLite for real Databricks/Delta
This is the part worth mentioning verbally in your interview even if you
don't demo it live: `server.py` loads `data/rentals.csv` into SQLite purely
so the project runs with zero external accounts. The tool *signatures*
(`average_rent_by_market`, etc.) don't change if you point them at a real
warehouse — only `load_data()` and the query strings do.
To do the real version:
1. Spin up Databricks Community Edition (free) at databricks.com/try-databricks
2. Create a Unity Catalog table from the same CSV (or a public Kaggle rental
dataset) as a Delta table
3. Replace the SQLite connection with the `databricks-sql-connector` package:
```python
from databricks import sql
conn = sql.connect(
server_hostname="<your-workspace>.cloud.databricks.com",
http_path="<your-warehouse-http-path>",
access_token="<personal-access-token>",
)
```
4. Swap `_conn.execute(...)` calls to use this connection instead — same SQL,
different backend.
Doing this swap for real (even against a tiny Databricks Community Edition
table) is the single highest-leverage next step if you have extra time,
since it's the literal technology named in the JD.
## Repo structure
```
mcp-rental-server/
├── README.md
├── requirements.txt
├── server.py
└── data/
├── make_data.py
└── rentals.csv (generated, gitignored — see below)
```
Suggested `.gitignore`:
```
venv/
__pycache__/
*.pyc
data/rentals.csv
```
(Keep `make_data.py` in the repo so anyone cloning it can regenerate the
dataset — cleaner than committing generated data.)
This server cannot be deployed
Maintenance
ActivitySlowing
ResponsivenessNo issues