energyops-mcp
Click on "Deploy Server".
Wait a few minutes for the server to deploy. Once ready, it will show a "Started" state.
In the chat, type
@followed by the MCP server name and your instructions, e.g., "@energyops-mcpDetect anomalies in the demo building's target day and summarize the results."
That's it! The server will respond to your query, and you can continue using it as needed.
Here is a step-by-step guide with screenshots.
energyops-mcp
A hand-rolled implementation of the Model Context Protocol over JSON-RPC 2.0 — no MCP SDK — plus a non-trivial local MCP server for building energy analysis: anomaly detection, flexible-load schedule optimization, and battery/solar outage-autonomy simulation.
This package is fully independent: it does not require any other repository, any LLM API key, or any building's real data. Everything it analyzes is a reproducible synthetic dataset generated from a fixed seed.
What's in here
energyops_mcp.protocol— the MCP transport and lifecycle layer, built directly against JSON-RPC 2.0 and the MCP 2025-06-18 spec:jsonrpc.py: message parsing/serialization, standard error codes.client.py: an asyncio MCP client —initialize,ping,tools/list(with pagination),tools/call, timeouts withnotifications/cancelled, clean shutdown. Protocol errors (JsonRpcError) are kept structurally distinct from tool execution failures (CallToolResult(isError=True)).server.py: a synchronous stdio MCP server base class (McpServer) — register tools with a decorator, it handlesinitialize/ping/tools/list/tools/callframing.stdio_transport.py: child-process transport for the client side (newline-delimited JSON over stdin/stdout). Includes a fix for a real Windows issue —asyncio.create_subprocess_execcannot launch a.cmd/.batshim (likenpx) directly; this is routed throughcmd.exe /cautomatically.http_transport.py: a Streamable HTTP client transport (POST/GET to a single endpoint,Mcp-Session-Idhandling, JSON andtext/event-streamresponse modes), for talking to a remote MCP server over HTTPS.
energyops_mcp.energy— the analytical engine, exposed as seven MCP tools byenergy/server.py:
Tool | Purpose |
| List configured buildings and their meters |
| Validate and idempotently import a canonical CSV ( |
| Consumption, generation, peak/average demand and data quality for a period |
| Median-absolute-deviation anomaly detection against the historical same-time-of-day/day-type baseline |
| Brute-force 15-minute-resolution search for the cheapest feasible start time of each flexible load |
| Interval-by-interval battery+solar autonomy simulation during a simulated outage, comparing the full building against critical loads only |
| Assemble selected analysis results into a Markdown report with provenance |
A demo building auto-seeds on first use: five independent consumption circuits (lighting, HVAC, critical services, a pump, and general equipment) plus a solar generation meter, eight weeks of 15-minute-resolution history and one target day, generated from a fixed random seed — fully reproducible, and never double-counting energy (consumption and generation are always summed separately). A known anomaly is deliberately injected into the target day so detect_anomalies has something real to find.
Related MCP server: bim2sim-mcp
Install
Requires Python 3.13+.
git clone https://github.com/iancumes/energyops-mcp.git
cd energyops-mcp
python -m venv .venv
# Windows: .venv\Scripts\activate macOS/Linux: source .venv/bin/activate
pip install -e ".[dev]"No API key, no environment variables, and no other repository are required for anything in this package.
Run the server
energyops-mcp-server --db-path energyops.sqlite3
# or:
python -m energyops_mcp.energy.server --db-path energyops.sqlite3This starts a stdio MCP server: it speaks newline-delimited JSON-RPC on stdin/stdout and writes diagnostics to stderr, so it is meant to be launched by an MCP client/host as a child process, not run interactively. --import-dir (default data/imports) sets the only directory import_readings is allowed to read a CSV from.
Connecting from your own client
Any MCP client that speaks JSON-RPC 2.0 over stdio can talk to this server. Using the client included in this package:
import asyncio
from energyops_mcp.protocol.client import McpClient
from energyops_mcp.protocol.stdio_transport import StdioTransport
async def main():
transport = StdioTransport("python", ["-m", "energyops_mcp.energy.server"])
client = McpClient(transport, server_name="energyops-mcp")
await client.start()
await client.initialize()
tools = await client.list_tools()
print([t.name for t in tools])
result = await client.call_tool("list_buildings", {})
print(result.text())
await client.aclose()
asyncio.run(main())Example: importing readings
result = await client.call_tool("import_readings", {"csv_path": "data/imports/january.csv"})The CSV must have exactly the header timestamp,meter_id,energy_kwh, with UTC ISO-8601 timestamps. Re-importing the same file is a no-op (rows are keyed by (meter_id, timestamp)); unknown meters and malformed rows are reported back, not silently dropped or fatal.
Example: detecting anomalies
result = await client.call_tool(
"detect_anomalies",
{"building_id": "demo-building", "target_date": "2026-03-02"},
)
print(result.structured_content["incidents"])Example: optimizing a flexible load schedule
tariff_bands = [{"start_minute": 0, "end_minute": 24 * 60, "price_per_kwh": 0.2}]
result = await client.call_tool(
"optimize_schedule",
{"building_id": "demo-building", "date": "2026-03-02", "tariff_bands": tariff_bands},
)
print(result.structured_content["proposed"])Design notes
Protocol errors vs. tool failures are structurally distinct. A malformed message, an unknown method, or a transport failure raises
JsonRpcError. A tool that runs but fails (bad input, no data for the period, an infeasible schedule) returns a normal result withisError: trueinstead — this is what lets a host tell "the protocol is broken" apart from "the tool reported a failure."The server-side I/O loop is deliberately synchronous, not asyncio. A local tool server talks to exactly one client over one pipe and processes one request at a time, so blocking line I/O is simpler and sidesteps a well-known fragility of piping a process's own stdin/stdout through asyncio on Windows. The client side is asyncio-based because a host application typically needs to manage the child subprocess concurrently with everything else it's doing (an LLM call, a UI) — which is the well-supported case on every platform via
asyncio.create_subprocess_exec.Every reported figure comes from a real calculation, never from an LLM guessing. The MCP layer only decides which tool to call;
energyops_mcp.energydoes the arithmetic.
Testing
pip install -e ".[dev]"
pytest -v
ruff check src testsThe test suite spawns this server as a real subprocess and drives it over actual stdio pipes — not just mocks — including a hand-checkable acceptance scenario (a 10 kWh battery at 100% state of charge with a 20% reserve, ideal efficiency, a steady 2 kW load and no solar must yield exactly 4 hours of autonomy) and detection of the deliberately injected anomaly through the full protocol round trip.
License
MIT — see LICENSE.
This server cannot be deployed
Maintenance
Related MCP Connectors
Built-environment forecasts, public benchmarks, and permit or zoning readiness through remote MCP.
Public MCP digital twin with synthetic systems and an agent firewall. No customer data.
An MCP server that audits the fairness of construction and renovation estimates in Japan. Provides fair-price ranges, overcharge detection, and verifiable unit-cost data based on JCCDB (65,520 items across 402 categories, CC BY 4.0, DOI-backed).
MCP server for building and testing AI agents with multi-model experimentation and insights.
Related MCP Servers
- AlicenseNot gradedqualityAmaintenanceA lightweight MCP server that connects LLM agents to BACnet devices for building automation, enabling real-time monitoring, actuation, and task orchestration.6MIT
- AlicenseAqualityDmaintenanceMCP server for BIM-to-building-energy simulation workflows with IFC extraction, TEASER integration, scenario modeling, weather binding, and results export for downstream WAT/ROI analysis.11MIT
- AlicenseNot gradedqualityBmaintenanceMCP server for querying and simulating the dispatch plan of a solar PV + battery system in the Chilean electricity market, using deterministic optimization and optional DRL.Academic Free v1.1
- FlicenseNot gradedqualityBmaintenanceAutonomous, carbon-aware building management system that pairs EnergyPlus digital twins with LLMs via the Model Context Protocol (MCP) for dynamic HVAC optimization and grid carbon reduction.-