solar_mcp
Click on "Install 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_mcpHelp me plan my loads for tomorrow's scheduled outage."
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-plan-mcp
An agent that answers one everyday question: will I get through tomorrow's set of consumers on my own generation, and if not — what should I move?
A roof with panels, a battery, an inverter, a known outage schedule. The agent takes the weather forecast from a ready-made MCP server, calculates expected generation by hour on its own MCP server, checks the plan against physical rules, and if it doesn't pass — moves flexible loads and proves with numbers that things got better.
Two MCP connections:
Server | Role | |
Ready-made |
| forecast: sky class and temperature for every 3 hours |
Own |
| 4 meaningful domain tools + forecast text parsing |
Documentation: tool contracts · design rationale · demo scenario
What you need
What for | Note | |
Python 3.13 | agent and own server | no admin rights needed |
Go 1.24+ | only to build the weather server | the project publishes no prebuilt binaries; |
OpenWeather key | weather server | free, openweathermap.org/api; takes up to a few hours to activate |
| only the agent; the own server and tests don't need it | Claude Agent SDK spawns this CLI as a child process — see Model access |
Node + npx | optional — MCP Inspector |
|
The PVGIS dataset is already in the repository (data/pvgis_kyiv_5kwp.csv, 1.1 MB), so the
own server works without a network. Nothing needs to be downloaded.
Related MCP server: Solar MCP
Installation
Windows, and this isn't cosmetic: all commands are in PowerShell, because && is not an
operator in PowerShell 5.1 at all. From here on, everywhere .venv\Scripts\python.exe.
First, two encoding variables, and they are different. PYTHONUTF8=1 tells Python to
write UTF-8; [Console]::OutputEncoding tells PowerShell to read it the same way.
Without the second one, Ukrainian output turns into ╨▓╨╗╨░╤ü╨╜╨╕╨╣ — measured, and
precisely in the pipe (| Tee-Object, | Select-String), because there PowerShell decodes
bytes with the console code page. Set them in every new window, and before
installation, not after:
[Console]::OutputEncoding = [Text.Encoding]::UTF8
$env:PYTHONUTF8 = "1"git clone https://github.com/prasolantoncp-bot/solar-plan-mcp.git
cd solar-plan-mcp
python -m venv .venv # або: uv venv .venv
.venv\Scripts\python.exe -m pip install -r requirements.txtYou need Python 3.13 — the exact one that python --version answers with, because
venv inherits the version of the interpreter that created it.
Why versions are pinned. The demo must be reproducible, not "work somewhere".
mcp==2.0.0 is already MCPServer instead of FastMCP, and code written for 1.x won't
work here; claude-agent-sdk==0.2.144 — on it the tools and the init-message format from
which the agent prints both connections are verified; tzdata — because Windows has no
system timezone database, and without Europe/Kyiv there won't be a single local hour. The
requirements.txt itself is kept in ASCII deliberately: pip reads it with the locale
encoding, and a single Cyrillic letter in a comment breaks pip install -r with a
UnicodeDecodeError on any machine where the locale isn't UTF-8. Measured on cp1252 from a
clean clone — that's why the explanation lives here, not in that file.
Build the weather server
Go installs into the user profile, without an administrator and without registry changes:
# 1. портативний Go у профіль (один раз). curl.exe є у Windows 10 1803+
curl.exe -Lo go.zip https://go.dev/dl/go1.27.0.windows-amd64.zip
Expand-Archive go.zip -DestinationPath "$env:LOCALAPPDATA\Programs"
# 2. клон і збірка. GOROOT і PATH живуть лише в цьому вікні — так і треба
$env:GOROOT = "$env:LOCALAPPDATA\Programs\go"
$env:PATH = "$env:GOROOT\bin;$env:PATH"
New-Item -ItemType Directory -Force vendor | Out-Null
cd vendor
git clone https://github.com/mschneider82/mcp-openweather.git
cd mcp-openweather
git checkout e032683574a0723591445462ef7104d360ad0889
go build -o mcp-weather.exe .
cd ..\..The agent looks for the ready-made binary at
vendor\mcp-openweather\mcp-weather.exe. If yours is located elsewhere — don't move it,
but point a variable at it: $env:WEATHER_MCP_BINARY = "…\mcp-weather.exe" (see
env.example). The agent checks that the file exists before starting the
session and refuses with a sentence, not a traceback from inside the SDK.
vendor/ is in .gitignore: someone else's git history and a 13 MB binary have nothing to
do in this repository. The commit is pinned — the
contract documentation is
written against exactly that one.
If the course pins a different
mcp-openweathercommit — take it and record it here; the contract description indocs/TOOLS.mdwas written frommain.goate032683.
Key
Secrets never get into the repository: .env and .env.* are in .gitignore, and the
sample lies in env.example without a single value.
The demo needs three terminals, and $env: lives in only one, so the key is worth setting
at the user level — no admin rights are needed for that:
# так ключ не потрапляє ні в скролбек, ні в історію PSReadLine
$s = Read-Host "OWM_API_KEY" -AsSecureString
[Environment]::SetEnvironmentVariable("OWM_API_KEY",
[Runtime.InteropServices.Marshal]::PtrToStringBSTR(
[Runtime.InteropServices.Marshal]::SecureStringToBSTR($s)), "User")Only new terminals will see the new value. A check that it arrived without revealing
the key: .venv/Scripts/python.exe -c "import os; print(len(os.environ.get('OWM_API_KEY','')))"
— should be 32. Don't run dir env: on camera: it prints the key.
The one-off session form $env:OWM_API_KEY = "…" also works, but has exactly one proper
use here — clearing the key in a separate window for the failure scenario:
$env:OWM_API_KEY = "".
The key is read only from the environment — it's not in the code or in
.mcp.json.example; there stands the ${OWM_API_KEY} substitution. The .env file is
read by no one: the code only has os.environ.get, so copying env.example into
.env is an empty action.
Model access
The own server and all 57 tests work without any Anthropic credentials — these are
different things and shouldn't be confused. The model is needed by exactly one file,
agent/run.py.
The Claude Agent SDK doesn't talk to the API itself: it spawns the claude CLI as a
child process, and it's that CLI that looks for authorization. So two things are needed:
claudeinPATH. Check:(Get-Command claude).Source. Installation — per the official instructions; in this project it was installed via WinGet and lives at%LOCALAPPDATA%\Microsoft\WinGet\Links\claude.exe.Authorization — one of two paths, and the CLI takes whichever it finds:
claude login— interactive sign-in; the CLI puts the token in~/.claude/.credentials.json. This is exactly the path used here: the process environment has noANTHROPIC_*variable at all, and the credentials file exists. The recorded run of August 25, 2026 went this way.ANTHROPIC_API_KEYin the environment — a key from console.anthropic.com. Set it the same way asOWM_API_KEYabove, and likewise it never gets into the repository.
What's pinned in the code: the model claude-opus-5 (agent/run.py) and
claude-agent-sdk==0.2.144 (requirements.txt). If you have different
access and this model id doesn't resolve — replace it in run.py with an available one and
record here which one; the rest of the run doesn't depend on the id.
This code reads no credential and passes none anywhere: agent/run.py touches neither
ANTHROPIC_API_KEY nor the credentials file — that's the CLI's job. There are no secrets
in the repository, and env.example lies empty.
External API limits
The free OpenWeather plan gives 60 calls per minute
(documentation). One agent run makes one call
to the weather tool; inside, the weather server turns it into two HTTP requests
(current weather + 5-day forecast). That is, three orders of magnitude of headroom below
the ceiling even with continuous rehearsals.
The code has no polling loop, no retry on error, and no background refresh: the weather is
requested exactly when the model calls the tool. The own server doesn't go to the network
at all — its dataset lies in data/, so any number of runs of estimate_pv_generation,
validate_energy_plan, and the rest create no external request whatsoever.
Running: two independent processes
The own server starts separately from the agent and knows nothing about the agent.
Terminal 1 — the own MCP server:
$env:PYTHONUTF8 = "1"
.venv\Scripts\python.exe -m solar_mcp --transport streamable-http --port 8931Terminal 2 — the agent:
[Console]::OutputEncoding = [Text.Encoding]::UTF8
$env:PYTHONUTF8 = "1"
.venv\Scripts\python.exe agent\run.pyWithout --date the agent plans tomorrow's day: the product question is precisely
about tomorrow, and the OpenWeather forecast only covers now … +5 days, so today's day is
already half outside the horizon. A date outside that window will give
NO_FORECAST_FOR_DATE, not silent zeros.
The agent starts the weather server itself, over stdio — that's how the connection is
configured. The own server can also be run over stdio (python -m solar_mcp, that's the
default) — that's how clients like Claude Code expect it, and that's the variant described
in .mcp.json.example. For the demo, HTTP is better: then it's
visible that the server really is a separate process.
Useful agent flags:
--plan boiler:18:2 --plan aircon:18:3 # свій план замість дефолтного (можна кілька разів)
--date YYYY-MM-DD # інша доба; вт/чт/пт — без відключень, сб/нд — вечірнє вікно
--objective maximize_outage_reserve # інша цільова функція
--city Lviv # інше місто
--width 120 # скільки символів сліду друкувати--date accepts only a day within the forecast horizon — tomorrow … today + 5.
A date outside it will give NO_FORECAST_FOR_DATE, and the presence of an outage window in
the schedule doesn't save it: the schedule lies in the repository and knows any date, while
the forecast lives five days. Check before running: scripts/call_weather.py --city Kyiv --covers YYYY-MM-DD.
The dates in the outage schedule have a weekly pattern and provenance — see
data/outage_windows.json: the windows for August 22–26 are
taken from the public schedule, then the same pattern is repeated forward so the demo
doesn't depend on the recording date.
Checking that everything is alive
# 4 інструменти домену + 1 допоміжний, зі схемами входу І виходу
.venv\Scripts\python.exe scripts\inspect_tools.py
.venv\Scripts\python.exe scripts\inspect_tools.py --url http://127.0.0.1:8931/mcp --schemas
# сервер погоди напряму: сирий текст і те, що з нього вийшло
.venv\Scripts\python.exe scripts\call_weather.py --city Kyiv
# 57 тестів: фізика, правила домену, планувальник, контракт через MCP-клієнта
$env:PYTHONUTF8 = "1"; $env:PYTHONPATH = "."
.venv\Scripts\python.exe -m pytest tests\ -qThe tests need neither a network, nor an OpenWeather key, nor model access: the dataset
lies in the repository, and the foreign server's responses are recorded in
tests/fixtures/.
What lives where
solar_mcp/ власний MCP-сервер (окремий процес)
server.py інструменти й ресурс — увесь контракт
models.py схеми входу й виходу (Pydantic → справжні inputSchema/outputSchema)
errors.py закритий перелік кодів; помилка ≠ порожній результат
pv.py огинаюча ясного неба × прозорість × температурний дерейтинг
rules.py симуляція балансу, порушення, планувальник, порівняння
forecast.py розбір плоского тексту сервера погоди
dataset.py store.py читання датасету; реєстр виданих оцінок
agent/run.py Claude Agent SDK, дві MCP-конекції, слід викликів
scripts/ inspect_tools.py — контракт; call_weather.py — чужий сервер напряму
data/ датасет + fetch_pvgis.py (провенанс)
tests/ 57 тестів; у fixtures/ — три записані відповіді сервера погоди й одна синтетична
docs/ TOOLS.md · DESIGN.md · DEMO.mdTwo of these directories have their own README, and they are exactly what's looked for
under "data source" and "fixtures": data/README.md — where the PVGIS
row, the tariff, and the outage schedule came from; tests/fixtures/README.md —
what exactly was recorded from the foreign server, when, and with what.
One observation on which half the design stands
The weather server doesn't distinguish a failure from an empty response. Without a key
it returns is_error: false and text with zeros and an empty city name — recorded verbatim
in tests/fixtures/owm_no_api_key.txt, although its
README promises "FATAL: OWM_API_KEY environment variable not set".
That's why the own server is built the opposite way: a closed list of error codes, a
field pointing at the guilty field, and separately — a reason where emptiness is
legitimate (night, no violations). Details: DESIGN.md, TOOLS.md.
Tool Schema Changelog
Recent tool additions, removals, and schema changes observed during successful MCP inspections. Dates show when Glama detected each change.
No tool schema history has been recorded yet.
This server cannot be installed
Maintenance
Resources
Unclaimed servers have limited discoverability.
Looking for Admin?
If you are the server author, to access and configure the admin panel.
Related MCP Connectors
EU power dispatch for wallet-enabled compute, DePIN, battery and trading agents.
Free independent solar proposal review tool for California homeowners. Audit your solar quote for pr
31Protocol-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.
Unofficial integration! ## ✨ Key Features ### 💰 Financial Intelligence - **Smart Charging Cost An…
Related MCP Servers
- FlicenseNot gradedqualityDmaintenanceEnables AI-powered analysis and prediction of household energy consumption through machine learning models, providing historical consumption breakdowns, price queries from Spanish electricity markets, and personalized energy optimization recommendations.-
- AlicenseNot gradedqualityDmaintenanceAn MCP server that enables AI assistants to look up solar permitting authorities, estimate solar production via PVWatts, and retrieve irradiance data. It streamlines the creation of solar-aware workflows by integrating industry-standard APIs like NREL.MIT
- FlicenseNot gradedqualityBmaintenanceMCP server for querying and simulating the dispatch plan of a solar PV + battery system in the Chilean electricity market, using deterministic optimization and optional DRL.-
- FlicenseAqualityCmaintenanceEnables solar energy feasibility analysis and ROI calculation for Indian users, including irradiance lookup, system sizing, cost estimation, subsidy calculation, and environmental impact assessment.8-
Latest Blog Posts
- Who's Calling? MCP Hosts Are an Identity Blind Spot (And the Spec Knows It)By Om-Shree-0709 on .mcpAgent IdentityOAuth 2.1
- Your AI Chatbot Just Exposed Your CEO's Salary to an InternBy Om-Shree-0709 on .Agent IdentityMCP SecurityOAuth Delegation
- Why MCP Servers Need Execution Sandboxing (And Why Your Current Stack Isn't Enough)By Om-Shree-0709 on .Agentic AiPrompt InjectionWebAssembly
MCP directory API
We provide all the information about MCP servers via our MCP API.
curl -X GET 'https://glama.ai/api/mcp/v1/servers/prasolantoncp-bot/solar-plan-mcp'
If you have feedback or need assistance with the MCP directory API, please join our Discord server