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 reschedule?
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 — reschedules 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 doesn't publish ready 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.
Installation
git clone <цей-репозиторій>
cd solar-plan-mcp
python -m venv .venv # або: uv venv .venv
.venv\Scripts\python.exe -m pip install -r requirements.txtWindows, and this isn't cosmetic: all commands below are in PowerShell, because && in
PowerShell 5.1 isn't an operator at all. From here on, everywhere .venv\Scripts\python.exe.
Two encoding variables, and they're 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. So in every new window:
[Console]::OutputEncoding = [Text.Encoding]::UTF8
$env:PYTHONUTF8 = "1"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 binary at
vendor\mcp-openweather\mcp-weather.exe. If yours is elsewhere — don't move it, but
point a variable at it: $env:WEATHER_MCP_BINARY = "…\mcp-weather.exe" (see
env.example). The agent checks for the file's existence 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 with this repository. The commit is pinned — the
contract documentation is
written against exactly that commit.
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 sits 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 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's a ${OWM_API_KEY} substitution there. The .env file is
read by no one: the code only has os.environ.get, so copying env.example to .env
is a no-op.
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.
Claude Agent SDK doesn't call the API itself: it spawns the claude CLI as a child
process, and that CLI is what 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 sits in%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, and the credentials file exists. The recorded run on August 25, 2026 passed 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 — the CLI handles that. There are no secrets
in the repository, and env.example sits 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, there's 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 touch the network
at all — its dataset sits in data/, so any number of estimate_pv_generation,
validate_energy_plan, and other runs create zero external requests.
Running: two independent processes
The own server comes up separately from the agent and knows nothing about the agent.
Terminal 1 — own MCP server:
$env:PYTHONUTF8 = "1"
.venv\Scripts\python.exe -m solar_mcp --transport streamable-http --port 8931Terminal 2 — 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 this 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 sits 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 were
entered 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
sits in the repository, and the third-party 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 those are exactly what to look 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 third-party 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, even though 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 offending field, and separately — a reason where empty is legitimate
(night, no violations). Details: DESIGN.md, TOOLS.md.
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
Unofficial integration! ## ✨ Key Features ### 💰 Financial Intelligence - **Smart Charging Cost An…
One-call installer quote review plus energy incentives, estimates, scores, and routing for agents.
Personalized timing intelligence for AI agents — ask 'should I do X on this date?'
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