solar-mcp
Provides read-only telemetry from Huawei SUN2000 inverters over local Modbus TCP, exposing inverter model, firmware version, active power, daily and lifetime generation, and operating status without allowing control or configuration changes.
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., "@solar-mcpHow much power is my solar inverter producing right now?"
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.
solar-mcp
A local, read-only, stdio Model Context Protocol
server for Huawei SUN2000 inverter telemetry. It exposes exactly one tool:
get_solar_status.
This release monitors generation; it cannot adjust the inverter. Generation is not household consumption, grid export, or available surplus. There are no control, arbitrary-register, login, heartbeat, discovery, HTTP, or automation tools.
Requirements
Python 3.12 or newer and uv.
A Huawei SUN2000 inverter reachable through a compatible local Modbus TCP connection, with Modbus access enabled by the device owner/installer.
The inverter's unit ID. The verified SUN2000-8KTL-M0 / SDongleA-05 installation uses unit 1, not the library's unit-0 default.
Only that inverter/dongle combination has been exercised on hardware. Other SUN2000 models must provide the same registers; missing data is an error rather than an invented reading. Software updates and commissioning are outside this server's scope. Do not start it during an active firmware update.
Run one server instance per inverter endpoint, not separate instances in several MCP clients. Close competing commissioning sessions when troubleshooting. The server serializes its own requests, but does not coordinate other processes. Keep Modbus on a trusted LAN; never expose port 502 to the internet.
Related MCP server: fronius-mcp
Install and configure
git clone https://github.com/vasilyevstan/solar.git
cd solar
uv sync --frozen --no-dev
cp .env.example .envEdit the ignored .env with your actual address. 192.0.2.10 in the example
is a documentation placeholder, not a discoverable device.
Setting | Default | Meaning |
| Required | Hostname or LAN IP, without a URL scheme |
|
| Modbus TCP port |
|
| Inverter unit, between 0 and 247 |
| Unset | Optional expected inverter serial; kept local and never returned by the tool |
The server reads environment variables, not .env files itself. For a direct
stdio launch, let uv load the local file:
uv run --frozen --no-dev --env-file .env solar-mcpThis starts an MCP protocol process, not an interactive dashboard. Use an MCP
client to send requests. Host, port, and unit can alternatively be set with
--inverter-host, --inverter-port, and --unit-id; command-line values take
precedence over environment variables.
MCP client configuration
Use the following stdio entry in your client's MCP server configuration, replacing
the directory and placeholder IP. The exact outer configuration file is
client-specific. Ensure uv is on the client's executable search path.
{
"mcpServers": {
"solar-mcp": {
"command": "uv",
"args": [
"run", "--directory", "/absolute/path/to/solar",
"--frozen", "--no-dev", "solar-mcp"
],
"env": {
"SOLAR_INVERTER_HOST": "192.0.2.10",
"SOLAR_INVERTER_UNIT_ID": "1"
}
}
}
}Tool result
get_solar_status takes no arguments. It returns structured data with:
Field | Meaning |
| Inverter model and running inverter firmware, not dongle firmware |
| Signed active power in watts; zero is a valid observation |
| Daily inverter generation counter |
| Accumulated inverter generation counter |
| Raw operating code and description |
| UTC time at the start of the telemetry read sequence |
| Age since that observation, measured with a monotonic clock |
| Whether this call reused an observation less than 30 seconds old |
| Always |
Readings are sequential, not an atomic meter snapshot. The daily counter follows the inverter's own day boundary; the observation timestamp is UTC. The server does not persist telemetry or contact FusionSolar.
Successful readings are cached on demand for less than 30 seconds. Cache hits do not move the observation timestamp. There is no background polling. A known disconnected connection invalidates cache use. Call again after the cache window for another live observation.
Each new connection waits one second before reading and verifies the model and
serial. The first accepted identity is retained for the process lifetime, so a
different device after reconnect is rejected. Set SOLAR_EXPECTED_SERIAL to
enforce that identity across process restarts as well.
Connection/response timeouts are 10 seconds. A tool call, including waiting for another request, has a 30-second deadline, plus at most two seconds for connection cleanup. There are no hidden reconnect/retry loops: after a failed read, the connection is closed and the next tool call makes one fresh attempt.
Failures produce an MCP isError response, never successful stale values or
fabricated zeroes. Invalid register sentinels and missing/unsupported data are
errors. Unknown operating codes are preserved and explicitly labelled unknown.
Logs go to stderr; stdout is reserved for MCP messages.
Development
uv sync --frozen --group dev
uv run --frozen pytest
uv buildTests use fake clients and a loopback Modbus server, not physical hardware. The stdio integration test exercises the actual SDK and Huawei library, verifies the result schema and errors, and asserts that all device traffic is function-03 holding-register reads to the intended addresses.
License and dependencies
Licensed under AGPL-3.0-only; see LICENSE.
Register decoding and Modbus operations use
huawei-solar (AGPLv3). The transport is
composed with its tmodbus dependency so automatic
reconnect cannot bypass identity checks. The official
MCP Python SDK is MIT-licensed.
Dependency versions are pinned and resolved in uv.lock.
Vendor documents and firmware, local settings, device identifiers, and diagnostic
artifacts are not distributed here. The local docs/ directory is ignored.
Available Tools
1 toolget_solar_statusARead-onlyIdempotent
Read inverter identity, software, power, energy, and status; cache for at most 30 seconds.
| Name | Required | Description | Default |
|---|---|---|---|
No parameters | |||
Output Schema
| Name | Required | Description |
|---|---|---|
| model | Yes | |
| source | No | |
| from_cache | Yes | |
| age_seconds | Yes | |
| observed_at | Yes | |
| generation_w | Yes | |
| device_status | Yes | |
| daily_yield_kwh | Yes | |
| software_version | Yes | |
| device_status_code | Yes | |
| lifetime_yield_kwh | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare readOnlyHint, idempotentHint, destructiveHint=false, and openWorldHint, so safety is covered. The description adds genuinely new behavioral context beyond them: a 30-second cache bound that tells the agent data may be slightly stale.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
A single tight sentence that front-loads the resource and payload, then appends the caching caveat. Every clause earns its place with no redundancy.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a no-arg read-only tool with a full output schema and rich annotations, the description covers the remaining gap (cache staleness) that structured fields do not. Nothing an agent needs to call it correctly is missing.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
The tool takes no parameters, so there is nothing to document; baseline is 4. The description correctly spends no words on parameters, focusing instead on output and caching.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
States a specific verb (Read) and resource (inverter) and enumerates exactly what is returned: identity, software, power, energy, and status. An agent can tell immediately what this tool yields; with no siblings, no differentiation is needed.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
There is no explicit when-to-use/when-not statement, but with zero sibling tools there is no alternative to route between. The 'cache for at most 30 seconds' clause gives implicit freshness guidance, which is the closest thing to usage context here.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
Tool Schema Changelog
Recent tool additions, removals, and schema changes observed during successful MCP inspections.
1 tool update
v0.1.0- First observed
get_solar_status
TDQS
Scored across 1 tool
Only one tool is exposed, so there is no possibility of confusing it with another tool. Its purpose—reading solar inverter status—is clearly distinct.
The single tool follows a clear snake_case verb_noun pattern: get_solar_status. With only one name, there is no inconsistency across the set.
One tool is borderline thin for a server named solar-mcp. It may be sufficient if the server is intentionally scoped to status retrieval only, but it offers little surface for broader solar operations.
The tool covers a comprehensive current snapshot: identity, software, power, energy, and status. However, it lacks notable related operations such as historical data, fault/alert listing, device discovery, or configuration/control.
Maintenance
Related MCP Connectors
Read-only MCP access to a documented IT fleet: state, changes, posture. 15 tools.
Protocol-native energy infrastructure orchestration for AI data centers. Provides 46 MCP tools across 8 grid protocols (IEC-61850, DNP3, Modbus, OCPP, OpenADR, IEEE 2030.5, IEC 60870-5-104, ICCP) with 5 core API primitives: connect, dispatch, settle, comply, and intel. Enables AI agents to programmatically interact with substations, grid interfaces, and energy assets for real-time workload-grid coordination.
Read-only electricity, gas, and weather data with structured provenance and units.
Signed internet telemetry, read-only: DNS, TLS, WHOIS, reachability. Every record Ed25519-signed.
Related MCP Servers
- FlicenseNot gradedqualityDmaintenanceProvides access to Tesla vehicle telemetry data via the Tessie API, enabling real-time monitoring of battery status, charging state, climate controls, location, and other vehicle metrics through 30+ tools with intelligent caching.-
- AlicenseAqualityDmaintenanceEnables real-time solar data from Fronius inverters via Claude, allowing natural language queries about solar production, battery, and grid exchange.51Apache 2.0
- AlicenseAqualityDmaintenanceEnables access to Fronius solar inverter data via the MCP protocol, allowing real-time monitoring of energy production, consumption, and battery storage through natural language.1426 npm4MIT
- AlicenseAqualityBmaintenanceProvides real-time access to solar inverter data from the SolaX Cloud API, enabling queries of power output, energy yields, battery status, and grid import/export data.2MIT