Sol Solar
Optionally persists MCP session state to Amazon DynamoDB, storing the cached solar forecast data and OAuth tokens across process restarts when TOKEN_STORE=dynamodb is set.
This server does not currently have a deployable release on Glama. Follow the repository's setup instructions to install and configure it for your MCP client, including any required credentials and local dependencies.
Sol Solar
Ask a voice assistant when to run the washing machine. Sol Solar is a self-hosted MCP server that answers with a sentence, using a live solar forecast and a typical-year comparison. It was built in October 2026 for the Amazon Developer Hackathon 2026, Alexa+ track.
On 18 October 2026, for a 5 kW array in Kyiv tilted 35 degrees and facing south, the server answered a two-hour wash assumed at 0.7 kW like this:
Wait until tomorrow. Run the washing machine from 1 PM to 3 PM. That washing machine, running for 2 hours at 0.7 kilowatts, is about 1.4 kilowatt-hours. The roof should cover it in that window. Today the array is expected to make about 1.3 kilowatt-hours, so waiting is the better solar plan. A typical October day for this array is about 12.8 kilowatt-hours in the PVGIS record, so the forecast days are dim. This is a model estimate, not a measurement from your inverter.
The 0.7 kW and 2 hours are inputs, not a measurement of a machine. The 6 UAH price used in the savings example below was typed for the demo. It is not a tariff lookup. Forecasts change. Run npm run demo for the current day.
The browser client, after OAuth PKCE, on that same day:

Author: Vadym Bilobrovets, solo, Ukraine. The repository was created on 17 October 2026. This server was written during the hackathon submission window.
Live: https://sol-solar-mcp.vercel.app (voice client at /, MCP endpoint /mcp, health /health). Vercel hosts the same Express app. See Run and deploy for the AWS path.
New in 1.1 (23 October 2026)
MCP App card. The five tools that draw a day chart declare
_meta.ui.resourceUri = ui://sol-solar/solar-card.html. The resource is one self-contained HTML document served astext/html;profile=mcp-app(MCP Apps, SEP-1865). It runs theui/initializehandshake and rendersui/notifications/tool-result: hourly bars, the chosen window, the day plan, and a battery gauge. It makes no network calls. A screen device can show it next to the spoken answer.The voice client is now a small MCP Apps host. It declares the
io.modelcontextprotocol/uiextension ininitialize, readstools/listto find which tools have a view, callsresources/readon theui://resource, and renders the card in a sandboxed iframe. The page's own CSP blocks inline script, so the iframe loads the byte-identical copy at/ui/solar-card.html. A test checks that the two are identical.Household memory across sessions. New tool
remember_household_appliancessaves the appliances a person describes once ("washer, 0.7 kW, 2 hours"). Sites are written to the key-value store undersite:<id>for 90 days. A new MCP session that only knows thesite_idcan ask "when should I run the washer?" with no numbers, or "plan my appliances" with no list. WithTOKEN_STORE=dynamodbthis survives restarts. On Vercel, stateless mode puts the household inside a signedsite_idinstead (see below), so it works on any instance until the next deployment rotates the key.Stateless mode for serverless.
MCP_STATELESS=1(set byapi/index.js) signs OAuth codes, access tokens and site ids with HMAC-SHA256 and one key per deployment (dist/signing-key.txt, written at build time, never committed or served)./mcpthen creates a fresh server and transport per POST, withoutMcp-Session-Id. A test starts two app instances with the same key and checks that the second accepts the first one's token and household, and rejects a tamperedsite_idand token.Real voice in the browser. "Ask by voice" uses the browser's speech recognition to pick a question, and the answer is read aloud with
speechSynthesis. Tapping a question still works where speech recognition is missing.
Related MCP server: Powerline
Quick start
npm install
npm run devOpen http://127.0.0.1:8787/ and ask "When should I run the washing machine today?"
In another terminal, the same question over the official MCP client:
npm run demo
npm run demo -- --price 6 --currency UAHnpm test runs the suite without the network. npm run test:live calls Open-Meteo and PVGIS for Kyiv.
Architecture
flowchart LR
person[Person] --> client[Voice client]
client -->|"Streamable HTTP, MCP 2025-11-25"| mcp[Sol Solar]
mcp --> auth[OAuth 2.1 PKCE S256]
mcp --> tools[Eight tools]
mcp --> card["MCP App card (ui://)"]
card -. rendered by .-> client
tools --> meteo[Open-Meteo forecast and geocoding]
tools --> pvgis[PVGIS 5.3 typical year]
tools --> model[Yield model and appliance window]
mcp -. optional cache and tokens .-> dynamo[Amazon DynamoDB]
mcp -. container or Lambda .-> aws[App Runner or Lambda function URL]The browser page is a real MCP client. It sends initialize, notifications/initialized, tools/list, tools/call, and resources/read to POST /mcp. It reads the tool's text aloud and renders the MCP App card. It does not call a language model, so the kilowatt-hours cannot be invented by one.
The server imports and uses @modelcontextprotocol/sdk (McpServer, StreamableHTTPServerTransport, and, in src/demo.ts and the tests, Client with StreamableHTTPClientTransport). The negotiated protocol version in this SDK release is 2025-11-25.
Tools
Tool | What you ask | What it does |
| "My array is 5 kilowatts in Kyiv." | Resolves the place, remembers size, tilt, azimuth, and an optional price you typed. |
| "How much solar should I expect today and tomorrow?" | Hourly forecast, plus a PVGIS typical day for this month. |
| "When should I run the washing machine?" | Finds the best future window. Usable solar in an hour is capped at the appliance's power. |
| "What do I save against 7 PM?" | Grid kilowatt-hours avoided. Money only if you typed a price. |
| "Good morning. When is the solar window?" | Leads with the strongest stretch. If that stretch is thin, it says so. Names a cloudy run when Open-Meteo cloud cover supports one. |
| "Plan the dishwasher, the washer, and the car." | Places several loads. Two share an hour only when their combined power fits under that hour's forecast. |
| "Remember my washer: 0.7 kilowatts, 2 hours." | Saves up to 8 appliances with the site, so later questions and later sessions can say "the washer" without numbers. |
| "Will my battery last through tonight?" | Uses a capacity, charge, and household load you type. Says if that charge reaches sunrise, and whether the forecast can refill the battery. |
A prompt, answer_solar_question, tells a client to say the tool text and not invent numbers.
Follow-up calls in the same MCP session can omit the place. Every tool returns site_id. A later session can pass it back and get the same home and its saved appliances. Sites live in the key-value store for 90 days: DynamoDB when TOKEN_STORE=dynamodb, otherwise process memory, which a restart clears. In stateless mode the site_id is the signed site itself; it changes when you save appliances, so use the latest one.
Resource: ui://sol-solar/solar-card.html (text/html;profile=mcp-app). Linked from forecast_pv_production, best_time_for_appliance, daily_solar_briefing, plan_the_solar_day, and battery_through_the_night.
Example output
Captured with npm run demo -- --price 6 --currency UAH while Kyiv's local date was 18 October 2026. Protocol reported by the client: 2025-11-25.
remember_solar_site (481 ms):
I'll remember a 5 kilowatt array in Kyiv, Ukraine, tilted 35 degrees and facing south. Ask when to run an appliance, or ask what the roof should make today.
best_time_for_appliance (869 ms, cold, Open-Meteo and PVGIS together):
Wait until tomorrow. Run the washing machine from 1 PM to 3 PM. That washing machine, running for 2 hours at 0.7 kilowatts, is about 1.4 kilowatt-hours. The roof should cover it in that window. Today the array is expected to make about 1.3 kilowatt-hours, so waiting is the better solar plan. A typical October day for this array is about 12.8 kilowatt-hours in the PVGIS record, so the forecast days are dim. This assumes the sunlight in that window is free for this appliance. This is a model estimate, not a measurement from your inverter.
forecast_pv_production (35 ms after that cache fill):
Today in Kyiv, Ukraine, the 5 kilowatt array is expected to make about 1.3 kilowatt-hours. Tomorrow it is expected to make about 3.8 kilowatt-hours. That is well below a typical October day of about 12.8 kilowatt-hours (PVGIS-SARAH3 from 2005 to 2023). This is a model estimate, not a measurement from your inverter.
estimate_savings, with the typed example price of 6 UAH per kilowatt-hour:
Shifting the washing machine into the solar window avoids about 1.4 kilowatt-hours of grid electricity compared with a 7 PM start. At 6 hryvnia per kilowatt-hour, that is about 8.40 hryvnia. That uses the price you typed. It is not a tariff lookup. This assumes the sunlight in that window is free for this appliance. This is a model estimate, not a measurement from your inverter.
The same morning, about 4:01 AM in Kyiv, with a battery and a load that were typed for the question (5 kWh, 40 percent, 0.3 kW household load):
battery_through_the_night:
Yes. The battery should last through that night. At 40 percent, a 5 kilowatt-hour battery holds about 2 kilowatt-hours. A 0.3 kilowatt load from 4:01 AM to 7:25 AM needs about 1 kilowatt-hour. The forecast sun is not enough to refill it. That day's roof is expected to make about 1.3 kilowatt-hours. You typed the battery size, the charge, and the household load. They are not read from a battery. This is a model estimate, not a measurement from your inverter.
plan_the_solar_day, for a 1 kW dishwasher for 1 hour, the 0.7 kW washer for 2 hours, and 1.4 kW car charging for 3 hours:
Wait until tomorrow. Run the washing machine from 1 PM to 3 PM. I can't cover the dishwasher or the car charging from the roof without asking an hour for more than it is forecast to make.
daily_solar_briefing:
The strongest stretch today is from 1 PM to 4 PM, about 0.6 kilowatt-hours. That is a thin window for heavy loads. Good morning.
Alexa+ asks for a round trip under 500 ms. The cold call above took 869 ms. The cached forecast took 35 ms. See the friction log in docs/SUBMISSION.md.
How the estimate is made
Open-Meteo global_tilted_irradiance is the preceding-hour mean on the tilted plane (albedo 0.2, isotropic sky). The timestamp is the end of that hour. Azimuth follows Open-Meteo and PVGIS: 0 is south, -90 is east, 90 is west, 180 is north.
For each hour:
cell temperature ≈ air temperature + (GTI / 800) × 25
temperature factor = 1 - 0.004 × (cell temperature - 25)
kilowatt-hours = (GTI / 1000) × system kilowatts × temperature factor × 0.86The 25°C rise at 800 W/m² is a stand-in for NOCT. The 14% system loss matches PVGIS's default loss parameter. The temperature factor is clamped to 0.5–1.15. Wind is ignored on this path. PVGIS models temperature and wind itself, so the typical-year number is not the same formula as the forecast. The spoken answer says which source each number came from.
An appliance can only use as much power as it draws. A 0.7 kW wash does not absorb a 3 kW solar hour. If today can cover at least 95% of the load, the server keeps today even when tomorrow is sunnier. Otherwise it takes the window with more usable solar.
If the weather service fails and PVGIS still answers, the server says so and gives the typical day instead of inventing today's number. If a place name matches several towns of similar size, it lists them and does not guess. "Kyiv" resolves to Kyiv, Ukraine, because that match is the capital and much larger than the others.
Connect to Alexa+
Amazon's checklist for a self-hosted MCP server is published in the Alexa+ MCP QuickStart:
Streamable HTTP, MCP specification 2025-11-25 or later. This server negotiates
2025-11-25. The deprecated SSE-only transport is not mounted.A public HTTPS URL. Locally, a tunnel such as
cloudflaredcan exposehttp://127.0.0.1:8787/mcp.401for a missing bearer token, without aWWW-Authenticateheader.Protected Resource Metadata at
/.well-known/oauth-protected-resourceand/.well-known/oauth-protected-resource/mcp(RFC 9728).Authorization server metadata at
/.well-known/oauth-authorization-server, withcode_challenge_methods_supportedincludingS256.OAuth 2.1 authorization code plus PKCE S256. The token request must include
resource(this server's MCP URL) andcode_verifier. The bearer token goes in theAuthorizationheader, never the query string.Dynamic client registration, CIMD, and OIDC are not implemented, because the QuickStart says Alexa+ does not support them yet. Register Amazon's client id with
OAUTH_CLIENT_IDSand its redirect URI withOAUTH_REDIRECT_URISwhen you have them.
The QuickStart then uses alexa-ai configure and alexa-ai new mcp. The hackathon FAQ says participants cannot access that CLI, the MCP toolkit, or Amazon's web simulator, and that there is no application path. This project therefore includes its own voice client at /, which sends the real MCP messages. MCP Inspector also works:
npm run token
npx @modelcontextprotocol/inspectorConnect the inspector to http://127.0.0.1:8787/mcp and send Authorization: Bearer plus the printed token. The dev token is optional and off unless DEV_BEARER_TOKEN is set to at least 16 characters.
Text is the customer experience. There is no audio or video stream to transcode.
Data sources and licences
Source | Used for | Licence and terms |
Hourly tilted irradiance and air temperature | API data under CC BY 4.0. Attribute with a link: Weather data by Open-Meteo.com. The terms limit the free API to non-commercial use, under 10,000 calls a day, 5,000 an hour, and 600 a minute. Personal home automation is one of their non-commercial examples. A commercial product needs their paid subscription. | |
Place names | Same API terms. Their licence page credits the location database to GeoNames, CC BY. | |
Typical-year daily and monthly yield, and a suggested tilt when you do not pass one | JRC geospatial data page: free for public use when the source is acknowledged. Acknowledgement used here: PVGIS © European Communities, 2001-2026. The API response names the radiation database and the year range. PVGIS does not allow browser AJAX, so only this server calls it. |
This repository is MIT. See LICENSE. That licence does not replace the data licences above.
Run and deploy
Local bind is 127.0.0.1:8787. Set HOST=0.0.0.0 inside a container. Set PUBLIC_BASE_URL to the HTTPS origin clients will use, with no trailing slash. The OAuth resource is ${PUBLIC_BASE_URL}/mcp.
docker build -t sol-solar-mcp .
docker run --rm -p 8787:8787 sol-solar-mcpAWS Lambda, a function URL, and DynamoDB are described in docs/AWS.md. The template is infra/template.yaml. It was not deployed. The hackathon's AWS credit request form closed on 7 October 2026. An AWS account opened during the hackathon was put under review by AWS before anything could be deployed, and it is now closed. The live endpoint is therefore on Vercel: same createApp, wrapped by api/index.js, in stateless mode.
Variable | Default | Role |
|
| HTTP port |
|
| Bind address |
|
| OAuth issuer and MCP resource origin |
|
| Extra pre-registered clients, comma-separated |
| local demo URLs outside production | Extra exact redirect URIs |
| unset | Optional static bearer for local curl |
|
|
|
| off (on in | signed codes, tokens and site ids; one MCP transport per request |
| none | 32+ characters; |
| unset | Required with DynamoDB |
|
| Region for the DynamoDB client |
|
| Forecast cache |
|
| PVGIS cache |
|
| System loss in the forecast model |
|
| Power temperature coefficient |
|
| Upstream timeout |
| the public origin | Extra browser origins. Non-production also allows localhost |
In production, a request to /mcp with an Origin outside the allow-list is 403. A missing Origin is allowed, because non-browser MCP clients do not send one.
Tests
npm test
npm run typecheck
npm run test:live21 tests. The suite covers the yield model, the window picker (including the recorded dim-day shape used as a fixture), speech that omits money when no price was typed, PKCE S256 against the RFC 7636 test vector, the DynamoDB item shape with a fake client, and a Streamable HTTP session: 401 without WWW-Authenticate, metadata that lists S256, a rejected query-string token, a rejected foreign Origin, tool listing, a spoken wash answer, and a follow-up that remembers the site. A second session test reads the ui:// card over MCP, checks its MIME type and handshake, checks that /ui/solar-card.html is byte-identical with a locked-down CSP, saves two appliances, then opens a new MCP session that asks about "the washer" and plans the saved appliances using only the site_id. A wording test checks that a multi-appliance plan for tomorrow is a full spoken sentence. A stateless test runs two instances with one signing key.
Track
Primary track: Alexa+. Mini-challenges: Open Source (this new MIT repository) and AWS Builder (Lambda and DynamoDB in the code and the SAM template; not deployed from here). Submission text, the friction log, and tool feedback are in docs/SUBMISSION.md. The demo script is docs/DEMO_SCRIPT.md.
What this is not
It does not read an inverter, a utility account, or a Solana wallet. It does not know the author's solar plant. Prices and appliance power exist only when you type them. The sentence is an estimate for planning a load, not a promise of production or savings.
This server cannot be deployed
Maintenance
Related MCP Connectors
Home energy for AI assistants: live Power flow, Energy history, solar forecast, and device control.
Solar, weatherization, EV charging, battery and heat-pump decision tools for AI agents.
Ask about your solar and storage plant: production, consumption, battery, savings, reports.
Control your Tesla from your AI assistant - climate, charging, access, and security.
Related MCP Servers
- FlicenseNot gradedqualityBmaintenanceEnables home solar energy planning by estimating PV output, validating consumption plans against generation and battery constraints, and automatically shifting flexible loads to ensure power availability during scheduled outages.-
- AlicenseNot gradedqualityBmaintenanceEnables conversational home power management by providing real-time solar, battery, and grid status, plus forecasts to answer questions like whether you can run an appliance. It supports Victron and Growatt inverters, remembers household appliances and grid events, and renders an interactive dashboard card in MCP-compatible clients.6 npmMIT
- AlicenseNot gradedqualityBmaintenanceEnables Alexa+ to answer spoken questions about a home's energy use and act on them through seven voice-first tools, covering live device status, usage and cost reports, waste detection, savings recommendations, automation listing, device control, and confirmed energy-plan application.MIT
- AlicenseNot gradedqualityCmaintenanceEnables portable-battery outage planning by exposing tools that retrieve an example scenario, compute usable AC energy and runtime, select protected and optional loads, and compare plans under energy, continuous-power, and startup-surge limits. It returns structured calculations and spoken summaries for rehearsing what can stay powered before an outage.MIT