An open-source MCP (Model Context Protocol) server that connects Claude directly to your Energy Star Portfolio Manager account. Explore what's possible when AI meets sustainability data in plain language instead of exporting spreadsheets.
Built by Nikolas Mirando as an independent prototype exploring AI + sustainability data infrastructure in CRE.
Once connected, you can ask things like:
- "What is the average ENERGY STAR score for my office properties?"
- "Which of my properties are below a score of 50?"
- "Show me energy use intensity across my multifamily assets, ranked worst to best."
- "How many of my properties have ENERGY STAR certification?"
- "Give me a portfolio summary — scores and EUI across all my properties."
Your credentials stay on your machine. The MCP server runs locally, calls the ESPM API using your credentials, and returns your data to Claude. Nothing touches any third-party server. For demonstration and educational purposes only. This is not an official ENERGY STAR, EPA, or employer-sponsored system. Users authenticate with their own ENERGY STAR credentials locally; no data is stored or transmitted by this project.
Claude (your question)
→ MCP server (runs locally on your machine)
→ ESPM API (using your credentials from accounts.csv)
→ Your portfolio data only
→ Claude answers your question
- Node.js v18 or higher
- Claude Desktop
- An Energy Star Portfolio Manager account with API access enabled (see below)
You need to enable web services on your ESPM account before the API will work.
For the test environment (try it immediately with sample data):
- Log in to the ESPM Test environment
- Go to Account Settings → Software Development tab
- Select "Yes" for "Will this account be used to test web services?"
- Click Start Using the Test Environment
For your live portfolio (requires EPA approval):
- Log in to Portfolio Manager
- Go to Account Settings → Software Development tab
- Fill out the registration form to request live API access
- EPA will review and approve — typically within a few business days
git clone https://github.com/nikmirando1/ESPM_MCP.git
cd ESPM_MCP
npm installCredentials live in a read-only CSV file.
-
Copy the example:
cp accounts.csv.example accounts.csv
-
Edit
accounts.csv. Columns areusername,password,env(setenvtotestorliveper row):username,password,env alice@example.com,pass1,test bob@example.com,pass2,live
-
By default the server looks for
accounts.csvin the repo root. Override with theESPM_ACCOUNTS_CSVenv var if you'd rather keep it elsewhere (e.g. in.env, seeenv.example). -
Every tool accepts an
account_nameparameter — pass theusernamevalue from the CSV to pick which account to use. If the CSV contains exactly one account, you can omitaccount_nameand the server uses that account; otherwiseaccount_nameis required.
The CSV is only ever read; the server never writes to it. Restart the server after editing it.
Option A: Claude Code (CLI)
If you use Claude Code, register the server with one command (update the path to where you cloned the repo):
claude mcp add espm -- node /absolute/path/to/ESPM_MCP/src/main.jsAdd -s user to make it available across all projects, or -s project to
share it with collaborators via a checked-in .mcp.json. Verify with
claude mcp list.
Option B: Claude Desktop
Open your Claude Desktop config file:
- Mac:
~/Library/Application Support/Claude/claude_desktop_config.json - Windows:
%APPDATA%\Claude\claude_desktop_config.json
Add this entry (update the path to where you cloned the repo):
{
"mcpServers": {
"espm": {
"type": "stdio",
"command": "node",
"args": ["/absolute/path/to/ESPM_MCP/src/main.js"]
}
}
}Restart Claude Desktop (or reload your Claude Code session). You'll see the ESPM tools available. Start asking questions about your portfolio.
The server also speaks the MCP Streamable HTTP transport, so you can run it as a long-lived process and point any HTTP-capable MCP client (hosted Claude, custom clients, etc.) at it instead of spawning a stdio subprocess.
npm run start:http
# ESPM MCP HTTP server listening on http://127.0.0.1:3000/mcpOr directly: node src/main.js http
Env vars (all optional, see env.example):
MCP_HTTP_PORT— port to listen on (default3000)MCP_HTTP_HOST— interface to bind (default127.0.0.1)MCP_HTTP_BASIC_AUTH_USER/MCP_HTTP_BASIC_AUTH_PASS— enable HTTP Basic auth on/mcp(must be set together; see "Enable HTTP Basic auth" below)
The endpoint is POST /mcp. The server runs stateless — no session IDs,
one request/response per call — which keeps things simple and works for every
ESPM tool this server exposes.
curl -sS -X POST http://127.0.0.1:3000/mcp \
-H 'Content-Type: application/json' \
-H 'Accept: application/json, text/event-stream' \
-d '{"jsonrpc":"2.0","id":1,"method":"tools/list"}'You should get back the list of all ESPM tools.
The /mcp endpoint is unauthed by default. To require HTTP Basic auth, set
both MCP_HTTP_BASIC_AUTH_USER and MCP_HTTP_BASIC_AUTH_PASS before starting
the server. They can be exported, passed inline, or put in .env
(see env.example). Setting only one of them fails fast at startup.
MCP_HTTP_BASIC_AUTH_USER=alice MCP_HTTP_BASIC_AUTH_PASS=secret npm run start:http
# ESPM MCP HTTP server listening on http://127.0.0.1:3000/mcp (Basic auth enabled)Hit the protected endpoint with curl -u:
curl -sS -u alice:secret -X POST http://127.0.0.1:3000/mcp \
-H 'Content-Type: application/json' \
-H 'Accept: application/json, text/event-stream' \
-d '{"jsonrpc":"2.0","id":1,"method":"tools/list"}'Missing or wrong credentials return 401 with a
WWW-Authenticate: Basic realm="ESPM MCP" challenge. Basic auth is cleartext
over HTTP, so if you're exposing the server beyond localhost put it behind a
reverse proxy that terminates TLS.
With the HTTP server running, register it with Claude Code using the http
transport:
claude mcp add --transport http espm http://127.0.0.1:3000/mcpIf you enabled Basic auth, pass the credentials as a header:
claude mcp add --transport http espm http://127.0.0.1:3000/mcp \
--header "Authorization: Basic $(printf '%s:%s' alice secret | base64)"Add -s user or -s project to change the scope. Verify with
claude mcp list.
There is no built-in auth unless you opt in via MCP_HTTP_BASIC_AUTH_USER
/ MCP_HTTP_BASIC_AUTH_PASS (see above). By default the server binds to
127.0.0.1, so only processes on the same machine can reach it. If you want
to expose it more broadly, enable Basic auth and put it behind a reverse
proxy (nginx, Caddy, Cloudflare Tunnel, etc.) that terminates TLS — Basic auth
alone is cleartext and offers no protection in transit. Don't bind to a public
interface without a proxy.
Credentials still come from accounts.csv the same way they do in stdio mode.
A Dockerfile is included that runs the server in HTTP mode.
docker build -t espm-mcp .
docker run --rm -p 3000:3000 \
-v "$(pwd)/accounts.csv:/app/accounts.csv:ro" \
espm-mcpThe container binds to 0.0.0.0:3000 inside the container (published on the
host via -p). accounts.csv is mounted read-only so credentials aren't baked
into the image. Override port/host with -e MCP_HTTP_PORT=... /
-e MCP_HTTP_HOST=..., and enable Basic auth with
-e MCP_HTTP_BASIC_AUTH_USER=... -e MCP_HTTP_BASIC_AUTH_PASS=... if needed.
Basic auth alone is cleartext, so don't publish the port to a public interface without a reverse proxy terminating TLS in front.
| Tool | What it does |
|---|---|
list_accounts |
List the ESPM accounts configured in accounts.csv (does not hit the API) |
get_account |
Confirm you're connected and see your account info |
list_properties |
List all property IDs in your account |
get_property |
Get details for a specific property |
get_property_metrics |
Get score, EUI, and GHG emissions for a property |
list_property_groups |
List all your property groups |
get_property_group |
Get details for a specific group |
get_group_score_summary |
Average score, min/max, and full breakdown for a group |
get_portfolio_summary |
Portfolio-wide summary across all properties |
get_energy_star_certification_summary |
Count properties certified in a specific year using ESPM certification metrics |
- This repo: Free
- ESPM API: Free
- Claude Desktop: Requires a Claude subscription (Pro or above)
- Hosting: None — runs entirely on your machine
Your ESPM credentials are stored only in the accounts.csv file on your local machine. They are never transmitted to any server other than the official ESPM API (portfoliomanager.energystar.gov). This MCP has no backend, no telemetry, and no external dependencies beyond the ESPM API itself.
As of early 2026, there is ongoing uncertainty around federal funding for the ENERGY STAR program. This MCP was partly built to illustrate a broader point: the AI tooling is ready, but the data access layer is often the bottleneck. Whether ESPM continues as-is or evolves, the pattern demonstrated here, connecting sustainability data to conversational AI, is one the CRE industry should be building toward.
PRs welcome. Particularly interested in:
- Additional metrics endpoints (water, waste, carbon)
- Support for sharing/connection workflows
- Better error handling for large portfolios
MIT