Skip to main content
Glama
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.)