APsystems MCP Server
A Model Context Protocol (MCP) server written in Go that wraps the APsystems OpenAPI, giving AI assistants like Claude direct access to your solar monitoring data. Includes an optional web dashboard for visual monitoring.
APsystems MCP Server āļøš°ļø
A production-ready Model Context Protocol (MCP) server written in Go that wraps the APsystems OpenAPI, giving AI assistants like Claude direct access to your solar monitoring data. Includes an optional web dashboard for visual monitoring.
Table of Contents
- APsystems MCP Server āļøš°ļø
Features
- 16 MCP tools covering all APsystems API endpoints: system details, energy summaries, ECU/inverter/meter/storage data
- HMAC-SHA256 signature authentication ā implements the APsystems signature protocol
- Built-in web dashboard ā dark-themed single-page app with Chart.js energy visualizations
- Rate limiting ā configurable request throttling to respect API limits
- Automatic retries ā exponential back-off on transient errors and rate-limit responses
- Dual transport ā stdio (default) or SSE over HTTP, selectable via environment variable
- Structured logging ā JSON logs via
slogwith configurable levels - Podman support ā multi-stage Containerfile for minimal production images
- CI/CD ā GitHub Actions for testing, linting, and cross-platform releases
Quick Start
š Prerequisites
Before you get started, make sure you have:
- 𦫠Go (latest version recommended)
- š APsystems OpenAPI credentials (
APP_ID&APP_SECRET) - š System ID (
SID) ā Find it in the APsystems EMA app under Settings ā Account Details
How to get your API credentials
- āļø Email APsystems support and include:
- Who you are
- Why you need API access
- What you plan to do with the data
- š± Or grab them from the Android / iOS APsystems EMA app:
Install & Run
git clone https://github.com/mjrgr/apsystems-mcp-server.git
cd mcp-server
# Install dependencies
go mod tidy
# Set credentials
export APS_SYS_ID="your_fake_sid_1234567890"
export APS_APP_ID="your_fake_app_id_32charslong1234567890abcd"
export APS_APP_SECRET="your_fake_secret12"
# Build and run
go run ./cmd/server
With SSE Transport
By default the server uses stdio (standard input/output) for MCP communication.
Set APS_MCP_TRANSPORT=sse to start an HTTP server with Server-Sent Events instead:
export APS_MCP_TRANSPORT=sse
export APS_MCP_SSE_ADDR=:8888 # optional, defaults to :8888
go run ./cmd/server
# SSE endpoint: http://localhost:8888/sse
# Message endpoint: http://localhost:8888/message
This is useful when you want to connect remote MCP clients over HTTP rather than running the server as a child process.
With Dashboard
export APS_DASHBOARD=true
export APS_DASH_ADDR=:8080
go run ./cmd/server
# Dashboard available at http://localhost:8080
Dashboard Demo
start with Podman
podman build -t apsystems-mcp -f Containerfile .
podman run --rm \
-e APS_SYS_ID="your_fake_sid_1234567890" \
-e APS_APP_ID="your_fake_app_id_32charslong1234567890abcd" \
-e APS_APP_SECRET="your_fake_secret12" \
-e APS_DASHBOARD=true \
-p 8080:8080 \
apsystems-mcp
To run with SSE transport instead of stdio:
podman run --rm \
-e APS_SYS_ID="your_fake_sid_1234567890" \
-e APS_APP_ID="your_fake_app_id_32charslong1234567890abcd" \
-e APS_APP_SECRET="your_fake_secret12" \
-e APS_MCP_TRANSPORT=sse \
-e APS_MCP_SSE_ADDR=:8888 \
-e APS_DASHBOARD=true \
-p 8888:8888 -p 8080:8080 \
apsystems-mcp
# SSE endpoint: http://localhost:8888/sse
Table of Environment Variables
| Variable | Required | Example Value | Description |
|---|---|---|---|
APS_APP_ID | Yes | your_fake_app_id_32charslong1234567890abcd | 32-character APsystems App ID |
APS_APP_SECRET | Yes | your_fake_secret12 | 12-character APsystems App Secret |
APS_SYS_ID | Yes | your_fake_sid_1234567890 | System ID (SID) from EMA app, Settings ā Account Details |
APS_BASE_URL | No | https://api.apsystemsema.com:9282 | API base URL override |
APS_MCP_TRANSPORT | No | stdio | MCP transport: stdio (default) or sse |
APS_MCP_SSE_ADDR | No | :8888 | SSE server listen address (only when APS_MCP_TRANSPORT=sse) |
APS_DASHBOARD | No | true | Set true to enable web dashboard |
APS_DASH_ADDR | No | :8080 | Dashboard listen address |
APS_LOG_LEVEL | No | info | Log level: debug, info, warn, error |
Security
š Security Best Practices
- Never commit real API credentials or secrets to version control. Use
.env.localor environment variables for local development. - Rotate your APP_SECRET and SID if you suspect they are compromised.
- Report vulnerabilities by opening a security issue or emailing the maintainers.
- For production, use a secrets manager or environment injection (not plaintext files).
| Variable | Required | Default | Description |
|---|---|---|---|
APS_APP_ID | Yes | ā | 32-character APsystems App ID |
APS_APP_SECRET | Yes | ā | 12-character APsystems App Secret |
APS_BASE_URL | No | https://api.apsystemsema.com:9282 | API base URL override |
APS_SYS_ID | No | ā | Default system identifier (sid) for all API calls if not provided in tool arguments |
APS_MCP_TRANSPORT | No | stdio | MCP transport: stdio or sse |
APS_MCP_SSE_ADDR | No | :8888 | SSE server listen address (only when transport is sse) |
APS_DASHBOARD | No | false | Set true to enable web dashboard |
APS_DASH_ADDR | No | :8080 | Dashboard listen address |
APS_LOG_LEVEL | No | info | Log level: debug, info, warn, error |
MCP Tools Reference
System Tools
| Tool | Description |
|---|---|
get_system_details | System info: capacity, timezone, ECUs, status |
get_inverters | List all ECUs and connected micro-inverters |
get_meters | List all meter IDs |
get_system_summary | Energy totals: today, month, year, lifetime (kWh) |
get_system_energy | Energy by period: hourly/daily/monthly/yearly |
ECU Tools
| Tool | Description |
|---|---|
get_ecu_summary | Energy summary for a specific ECU |
get_ecu_energy | Period energy for an ECU (supports minutely telemetry) |
Inverter Tools
| Tool | Description |
|---|---|
get_inverter_summary | Per-channel energy for a single inverter |
get_inverter_energy | Period/minutely data with DC power, current, voltage, AC telemetry |
get_inverter_batch_energy | All inverters under an ECU in one call |
Meter Tools
| Tool | Description |
|---|---|
get_meter_summary | Consumed/exported/imported/produced totals |
get_meter_period | Period energy data for a meter |
Storage Tools
| Tool | Description |
|---|---|
get_storage_latest | Live status: SOC, charge/discharge power |
get_storage_summary | Energy summary for a storage ECU |
get_storage_period | Period energy data for storage |
Using with Claude Desktop
Using with Claude CLI
You can also connect this MCP server to the Claude CLI for direct, scriptable access to your solar data from the terminal.
1. Start the MCP Server
Make sure your MCP server is running and accessible (locally or remotely):
go run ./cmd/server
# or with Podman/Docker as shown above
2. Configure Claude CLI
Add your MCP server to Claude CLI using the built-in command:
Podman/Docker (recommended for containerized use)
claude mcp add apsystems -s local -- podman run -i --rm -p 8888:8080 -e APS_DASHBOARD=true -e APS_SYS_ID=your_fake_sid_1234567890 -e APS_APP_ID=your_fake_app_id_32charslong1234567890abcd -e APS_APP_SECRET=your_fake_secret12 docker.io/mehdijrgr/apsystems-mcp-server 2>&1
Or for Docker:
claude mcp add apsystems -s local -- docker run -i --rm -p 8888:8080 -e APS_DASHBOARD=true -e APS_SYS_ID=your_fake_sid_1234567890 -e APS_APP_ID=your_fake_app_id_32charslong1234567890abcd -e APS_APP_SECRET=your_fake_secret12 docker.io/mehdijrgr/apsystems-mcp-server 2>&1
Replace the environment variables with your actual credentials.
This will automatically update your Claude CLI configuration to include the apsystems MCP server.
3. Example Usage
Ask Claude CLI to query your solar data via the MCP server:
claude ask "Show me my solar production for today"

Or use any supported MCP tool, e.g.:
claude ask "List all my inverters"

claude ask "what's the average monthly solar production?"

You can script and automate queries, integrate with other tools, or use Claude CLI in your workflows!
To use Claude Desktop with Docker or Podman, update your claude_desktop_config.json as follows:
{
"inputs": [
{
"type": "promptString",
"id": "aps_sys_id",
"description": "APsystems System ID"
},
{
"type": "promptString",
"id": "aps_app_id",
"description": "APsystems App ID"
},
{
"type": "promptString",
"id": "aps_app_secret",
"description": "APsystems App Secret",
"password": true
}
],
"mcpServers": {
"apsystems": {
"command": "podman",
"args": [
"run", "-i", "--rm", "-p", "8888:8080",
"-e", "APS_DASHBOARD=true",
"-e", "APS_SYS_ID=${input:aps_sys_id}",
"-e", "APS_APP_ID=${input:aps_app_id}",
"-e", "APS_APP_SECRET=${input:aps_app_secret}",
"docker.io/mehdijrgr/apsystems-mcp-server"
]
}
}
}
Or for Docker:
{
"inputs": [
{
"type": "promptString",
"id": "aps_sys_id",
"description": "APsystems System ID"
},
{
"type": "promptString",
"id": "aps_app_id",
"description": "APsystems App ID"
},
{
"type": "promptString",
"id": "aps_app_secret",
"description": "APsystems App Secret",
"password": true
}
],
"mcpServers": {
"apsystems": {
"command": "docker",
"args": [
"run", "-i", "--rm", "-p", "8888:8080",
"-e", "APS_DASHBOARD=true",
"-e", "APS_SYS_ID=${input:aps_sys_id}",
"-e", "APS_APP_ID=${input:aps_app_id}",
"-e", "APS_APP_SECRET=${input:aps_app_secret}",
"docker.io/mehdijrgr/apsystems-mcp-server"
]
}
}
}
For SSE transport (remote/network mode), use the url field instead of command:
{
"mcpServers": {
"apsystems": {
"url": "http://localhost:8888/sse"
}
}
}
You can also mount a config file or credentials as needed:
{
"mcpServers": {
"apsystems": {
"command": "podman run -i --rm --env-file /path/to/env.local mehdijrgr/apsystems-mcp-server 2>&1",
"env": {}
}
}
}
Then ask Claude things like:
- "Show me my solar production for today"
- "How much energy did my system produce this month?"
- "What's the status of my inverters?"
- "Compare my daily production this week"
Project Structure
āāā cmd/server/ # CLI entry point
āāā internal/
ā āāā api/ # HTTP client with auth, retries, rate limiting
ā āāā auth/ # HMAC-SHA256 signature implementation
ā āāā dashboard/ # Optional web UI (embedded HTML)
ā āāā mcp/ # MCP tool definitions and handlers
ā āāā models/ # Go structs for API responses
āāā .devcontainer/ # VS Code dev container config
āāā .github/workflows/ # CI/CD pipelines
āāā .vscode/ # Editor settings and launch configs
āāā Containerfile # Multi-stage Podman/OCI build
āāā Makefile # Build, test, lint targets
āāā go.mod
Authentication Details
The APsystems API uses HMAC signature authentication. Every request includes five custom headers:
- X-CA-AppId ā your application identifier
- X-CA-Timestamp ā Unix timestamp in milliseconds
- X-CA-Nonce ā unique 32-character hex string (UUID without dashes)
- X-CA-Signature-Method ā
HmacSHA256 - X-CA-Signature ā
Base64(HMAC-SHA256(stringToSign, appSecret))
The string to sign is composed as:
timestamp/nonce/appId/requestPath/HTTPMethod/HmacSHA256
where requestPath is the last segment of the URL path.
Development
# Run tests
make test
# Lint
make lint
# Build for all platforms
make build
API Error Codes
| Code | Description |
|---|---|
| 0 | Success |
| 1000 | Data exception |
| 1001 | No data |
| 2001 | Invalid application account |
| 2002 | Not authorized |
| 2005 | Access limit exceeded |
| 4001 | Invalid request parameter |
| 5000 | Internal server error |
| 7002 | Too many requests (auto-retried) |
| 7003 | System busy (auto-retried) |
Troubleshooting
ā¹ļø Note: If you encounter API errors, check that your credentials (APP_ID, APP_SECRET, SID) are correct and that your account has API access enabled. If you see rate limit errors, try again later or adjust your request frequency.
- Q: I get 'Not authorized' or 'Invalid application account' errors.
- A: Double-check your APP_ID, APP_SECRET, and SID. Make sure your account is approved for API access by APsystems.
- Q: Claude CLI can't connect to the MCP server.
- A: Ensure the server is running and the address/port matches your CLI config. Check firewall or container port mappings.
- Q: The dashboard doesn't load.
- A: Make sure APS_DASHBOARD is set to true and the server is running. Visit the correct port in your browser.
Community & Support
- GitHub Issues ā for bug reports and feature requests
- Discussions ā for Q&A, ideas, and community help
- Email: [email protected] (for API credential requests)
Contributing
Contributions are welcome! To get started:
- Fork the repository
- Create a new branch for your feature or fix
- Make your changes and add tests if needed
- Open a pull request with a clear description
Please see CONTRIBUTING.md if available, or open an issue to discuss major changes first.
Quick Links
Server Terkait
3D Cartoon Generator & File System Tools
Generates 3D-style cartoon images using Google's Gemini AI and provides secure file system operations.
Lido MCP Server
Liquid staking data, stETH metrics, and validator info on Lido.
Teukhos
Spawn production-ready MCP servers from a single YAML file
Airplane.Live MCP Server
MCP server that connects to the Airplanes.live API to provide real-time flight and aircraft data for analysis or visualization.
MCP-HA-Connect
A production-ready Model Context Protocol (MCP) server for Home Assistant integration with AI assistants like Claude.
ThreatByte-MCP
ThreatByte-MCP is a deliberately vulnerable, MCP-based case management web app. It mirrors a realistic SOC analyst workflow with a server-rendered UI and a real MCP server. The MCP tools are intentionally vulnerable for training and demonstration.
Gaggiuino MCP
An MCP server for the Gaggiuino open-source espresso machine, providing real-time local network access to machine status and shot data.
ShapeBridge
MCP Agent to understand 3D models
stella-mcp
MCP server for creating and manipulating Stella system dynamics models (.stmx files in XMILE format)
mycop
AI code security scanner with 100 built-in rules covering OWASP Top 10 and CWE Top 25