Skip to main content
Glama
vasilyevstan

solar-mcp

by vasilyevstan

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 .env

Edit 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

SOLAR_INVERTER_HOST

Required

Hostname or LAN IP, without a URL scheme

SOLAR_INVERTER_PORT

502

Modbus TCP port

SOLAR_INVERTER_UNIT_ID

1

Inverter unit, between 0 and 247

SOLAR_EXPECTED_SERIAL

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-mcp

This 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

model, software_version

Inverter model and running inverter firmware, not dongle firmware

generation_w

Signed active power in watts; zero is a valid observation

daily_yield_kwh

Daily inverter generation counter

lifetime_yield_kwh

Accumulated inverter generation counter

device_status_code, device_status

Raw operating code and description

observed_at

UTC time at the start of the telemetry read sequence

age_seconds

Age since that observation, measured with a monotonic clock

from_cache

Whether this call reused an observation less than 30 seconds old

source

Always huawei_modbus

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 build

Tests 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 tool
get_solar_statusA
Read-onlyIdempotent

Read inverter identity, software, power, energy, and status; cache for at most 30 seconds.

ParametersJSON Schema
NameRequiredDescriptionDefault

No parameters

Output Schema

ParametersJSON Schema
NameRequiredDescription
modelYes
sourceNo
from_cacheYes
age_secondsYes
observed_atYes
generation_wYes
device_statusYes
daily_yield_kwhYes
software_versionYes
device_status_codeYes
lifetime_yield_kwhYes

TDQS

A4.3/5.0
Behavior4/5

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.

Conciseness5/5

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.

Completeness5/5

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.

Parameters4/5

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.

Purpose5/5

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.

Usage Guidelines3/5

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. 1 tool updatev0.1.0
    • First observedget_solar_status

TDQS

A4.2/5.0

Scored across 1 tool

Disambiguation5/5

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.

Naming Consistency5/5

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.

Tool Count3/5

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.

Completeness3/5

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

ActivityMaintained
ResponsivenessNo issues

Related MCP Connectors

Related MCP Servers

  • F
    license
    Not graded
    quality
    D
    maintenance
    Provides 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.
    -
  • A
    license
    A
    quality
    D
    maintenance
    Enables real-time solar data from Fronius inverters via Claude, allowing natural language queries about solar production, battery, and grid exchange.
    5
    1
    Apache 2.0
  • A
    license
    A
    quality
    D
    maintenance
    Enables access to Fronius solar inverter data via the MCP protocol, allowing real-time monitoring of energy production, consumption, and battery storage through natural language.
    14
    26 npm
    4
    MIT
  • A
    license
    A
    quality
    B
    maintenance
    Provides 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.
    2
    MIT