Inspiration
What it does
How we built it
Challenges we ran into
Accomplishments that we're proud of
What we learned
What's next for Sol Solar
Inspiration
I build solar infrastructure in Ukraine under Solar DePin, and a voice assistant, Solarchik. The question is the same at a house and at a small solar node: when is the power actually there? "When should I run the washing machine?" is the version a person will say out loud. I wanted Alexa+ to answer that in a sentence, from public weather and solar data, on a server I can host myself. No API key. No invented kilowatt-hours.
What it does
Sol Solar is a self-hosted MCP server. You tell it a place and an array size. It answers, in speech:
- what the roof is expected to make today and tomorrow
- when to run one appliance, given the power and duration you type
- a plan for several appliances that never asks one hour for more power than the roof is forecast to make
- whether a battery you describe will last until sunrise, and whether tomorrow's sun can refill it
- a morning briefing that names the strongest stretch, and says when that stretch is too thin for heavy loads
- how many grid kilowatt-hours a shift avoids compared with 7 PM
- a money figure only if you also type a price
On 18 October 2026 a 5 kW array in Kyiv, tilted 35 degrees and facing south, got this answer for a washing machine assumed at 0.7 kW for 2 hours:
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.
The dim forecast is the point. A wrapper that always says "midday" would have been wrong that day. The server compared the live forecast with PVGIS and said the days were dim.
Just after 4 AM that morning, the same array was asked about a typed 5 kWh battery at 40 percent, with a typed 0.3 kW household load. The charge covers the hours left until the 7:25 AM sunrise. The day's 1.3 kWh forecast does not refill the battery. A day plan for a 1 kW dishwasher, the washer, and 1.4 kW car charging can place only the washer, tomorrow from 1 PM to 3 PM. The other two would ask an hour for more than the forecast shows. None of those inputs were read from a meter or a battery.
The web page at / is the voice client. It speaks the tool text. It does not call a language model.
The Devpost cut is 1:19, 1280×888. The picture is a continuous screen capture in the top of the frame, with short fades between the browser and the terminal. English captions from docs/DEMO_CAPTIONS.srt are burned into a band under the picture, so they do not cover the form or the trace. It opens on power cuts in Ukraine and the battery question, then the washer, the day plan, and the morning briefing, from this same Kyiv morning. The terminal shows npm run tools, npm run demo, and npm test typed in full and then run. It has no music and no Amazon logo. It is on YouTube: https://youtu.be/z5L9N9QEfYA
New in 1.1 (23 October 2026)
- An MCP App card. Five tools (forecast, best time, briefing, day plan, battery) link to a
ui://sol-solar/solar-card.htmlresource with MIME typetext/html;profile=mcp-app, following the MCP Apps extension (SEP-1865). A host that supports MCP Apps shows the spoken answer as a card: the decision, the chosen window highlighted on hourly bars, today and tomorrow against the PVGIS typical day, a battery gauge, and appliances the roof cannot cover. The web client at/includes a minimal MCP Apps host: it reads the resource over MCP, renders it in a sandboxed iframe, and sendsui/initialize,tool-inputandtool-result. The voice answer is still the product. The card is for screens like the Echo Show. - A household that persists across sessions. New tool
remember_household_appliances. Say "the washer is 0.7 kW for 2 hours" once. Later, in a new session, "when should I run the washer?" and "plan my appliances" need no numbers. The answer says it used the numbers you saved, and that they were typed, not measured. - Voice in the browser client. A microphone button (Web Speech API, in Chrome) maps a spoken question to a tool, and a "Speak answers" toggle reads the tool's sentence aloud. No language model is involved.
- Stateless on serverless. OAuth codes, tokens and site ids are HMAC-signed, so any Vercel instance can answer the next call.
How I built it
- TypeScript, Node.js 22, Express, Zod, and
@modelcontextprotocol/sdk1.32.1. McpServerandStreamableHTTPServerTransportservePOST,GET, andDELETEon/mcp. The client negotiates protocol2025-11-25.- Tests and
npm run demouseClientandStreamableHTTPClientTransportfrom the same SDK. - OAuth 2.1 authorization code with PKCE S256, Protected Resource Metadata, and authorization-server metadata, matching the Alexa+ MCP QuickStart. Unauthenticated
/mcpreturns401with noWWW-Authenticateheader. Tokens in the query string are rejected. - Open-Meteo for geocoding and tilted-irradiance forecasts. PVGIS 5.3
PVcalcfor the typical year. Both are called only from the server. PVGIS blocks browser AJAX. - A small yield model, documented in the README, with system losses aligned to PVGIS's default 14%. Usable solar in an hour is capped at the appliance's power.
- Every tool returns a
site_id. On a stateful server, sites and saved appliances live in the key-value store for 90 days (DynamoDB withTOKEN_STORE=dynamodb). In stateless mode (MCP_STATELESS=1, used on Vercel) thesite_idis the household itself, HMAC-SHA256 signed with a per-deployment key, and/mcpcreates a fresh server and transport per POST. OAuth codes and tokens are signed the same way. A test runs two app instances with one key and checks that the second accepts the first one's token and household, and rejects a tampered one. - The MCP App card is one self-contained HTML file (no external scripts, CSP
default-src 'none') registered withregisterResourceand linked from tools with_meta.ui.resourceUri. 21 tests in total. - Dockerfile for a container.
infra/template.yamlis an AWS SAM stack: Lambda function URL plus DynamoDB for the cache and tokens. That stack was not deployed. The AWS Builder section below says exactly what was and was not run.
Live deployment: https://sol-solar-mcp.vercel.app (MCP endpoint https://sol-solar-mcp.vercel.app/mcp, health at /health). It runs the same Express app and MCP server on Vercel, in stateless mode. A full OAuth (PKCE S256) → initialize → tools/call run against that URL returns live Kyiv answers. The AWS path (Lambda function URL + DynamoDB, infra/template.yaml) is in the repository but was not deployed. The AWS account I opened during the hackathon was put under review before anything was deployed, and it is now closed.
Challenges
The Alexa+ add-on CLI, toolkit, and web simulator are partner-only. The hackathon FAQ says participants cannot apply for them. I could not complete account linking or record a session inside Amazon's simulator. The demo is a real MCP client instead, which the FAQ accepts.
Alexa+ also wants a round trip under 500 ms, and it wants OAuth behavior that differs from a typical resource server: no WWW-Authenticate on 401, no dynamic client registration, and a required resource parameter. A cold forecast plus PVGIS took 869 ms in the 18 October demo. A cached forecast took 35 ms.
Open-Meteo's free API is non-commercial. That fits a hackathon and home automation, and it is the wrong licence for a paid product. I documented the boundary instead of hiding it.
Accomplishments
- Eight tools with spoken answers, input validation and 21 tests: a multi-appliance day plan, a night-battery check, a morning briefing, and saved household appliances.
- A live answer for Kyiv that uses both a forecast and a typical year, and that recommends waiting when today is too dark.
- An MCP App view (
ui://resource,text/html;profile=mcp-app) on five tools, rendered by the included web host. - A household that carries over between sessions and between serverless instances, so a follow-up never repeats the city or the appliance numbers.
- An OAuth surface that matches the published Alexa+ checklist, exercised by the tests.
- An open-source MIT repository created during the hackathon window.
What's next
- Replace the typed appliance power with a measurement when a household wants to connect an inverter or a smart plug. This submission does not pretend to have that feed.
- Keep the spoken contract: the tool text stays the sentence Alexa says, so a model cannot invent a kilowatt-hour.
- Deploy the SAM stack once I have a working AWS account, and test the MCP App card in an Alexa+ multimodal host when one is available to independent developers.
- Register Amazon's OAuth client id when the partner tools are available to independent developers.
Built With
- amazon-dynamodb
- aws-lambda
- docker
- express.js
- mcp-apps
- model-context-protocol
- node.js
- oauth
- open-meteo
- pvgis
- typescript
- vercel
- web-speech-api
- zod
Log in or sign up for Devpost to join the conversation.