Skip to main content
Glama

solar-plan-mcp

Ein Agent, der eine alltägliche Frage beantwortet: schaffe ich morgen diesen Satz Verbraucher mit meiner eigenen Erzeugung, und wenn nicht – was verschiebe ich?

Dach mit Modulen, Batterie, Wechselrichter, bekannter Abschaltplan. Der Agent holt die Wettervorhersage von einem fertigen MCP-Server, berechnet die erwartete Erzeugung stundenweise auf einem eigenen MCP-Server, prüft den Plan gegen physikalische Regeln, und wenn dieser nicht durchgeht – verschiebt er flexible Lasten und belegt mit Zahlen, dass es besser geworden ist.

Zwei MCP-Verbindungen:

Server

Rolle

Fertig

mschneider82/mcp-openweather, Commit e032683

Vorhersage: Himmelsklasse und Temperatur alle 3 Stunden

Eigen

solar_mcp (dieses Repository)

4 inhaltliche Domänen-Tools + Analyse des Vorhersagetexts

Dokumentation: Tool-Verträge · Design-Rationale · Demonstrationsszenario

Was benötigt wird

Wofür

Anmerkung

Python 3.13

Agent und eigener Server

keine Administratorrechte nötig

Go 1.24+

nur um den Wetterserver zu bauen

das Projekt veröffentlicht keine fertigen Binaries; go.mod verlangt 1.24, obwohl das README dort 1.20 schreibt

OpenWeather-Schlüssel

Wetterserver

kostenlos, openweathermap.org/api; Aktivierung dauert bis zu einigen Stunden

claude CLI + Modellzugang

nur Agent; eigener Server und Tests benötigen ihn nicht

Claude Agent SDK startet diese CLI als Kindprozess – siehe Modellzugang

Node + npx

optional – MCP Inspector

npx @modelcontextprotocol/inspector

Der PVGIS-Datensatz liegt bereits im Repository (data/pvgis_kyiv_5kwp.csv, 1,1 MB), daher arbeitet der eigene Server ohne Netzwerk. Es muss nichts heruntergeladen werden.

Installation

git clone <цей-репозиторій>
cd solar-plan-mcp

python -m venv .venv                       # або: uv venv .venv
.venv\Scripts\python.exe -m pip install -r requirements.txt

Windows, und das ist keine Kosmetik: alle Befehle unten sind in PowerShell, denn && ist in PowerShell 5.1 überhaupt kein Operator. Weiterhin überall .venv\Scripts\python.exe.

Zwei Kodierungsvariablen, und sie sind verschieden. PYTHONUTF8=1 sagt Python, UTF-8 zu schreiben; [Console]::OutputEncoding sagt PowerShell, es ebenso zu lesen. Ohne die zweite wird die ukrainische Ausgabe zu ╨▓╨╗╨░╤ü╨╜╨╕╨╣ – gemessen, und genau in der Pipe (| Tee-Object, | Select-String), weil PowerShell dort die Bytes mit der Konsolen-Codepage dekodiert. Daher in jedem neuen Fenster:

[Console]::OutputEncoding = [Text.Encoding]::UTF8
$env:PYTHONUTF8 = "1"

Wetterserver bauen

Go wird im Benutzerprofil installiert, ohne Administrator und ohne Änderungen an der Registry:

# 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 ..\..

Das fertige Binary sucht der Agent unter dem Pfad vendor\mcp-openweather\mcp-weather.exe. Wenn es bei dir anders liegt – verschiebe es nicht, sondern setze die Variable: $env:WEATHER_MCP_BINARY = "…\mcp-weather.exe" (siehe env.example). Der Agent prüft die Existenz der Datei vor dem Start der Sitzung und lehnt mit einem Satz ab, nicht mit einem Traceback aus dem SDK-Inneren.

vendor/ in .gitignore: fremde git-Geschichte und 13 MB Binary haben in diesem Repository nichts zu suchen. Der Commit ist fixiert – genau auf ihm basiert die Vertragsdokumentation.

Wenn der Kurs einen anderen Commit von mcp-openweather festlegt – nimm ihn und notiere ihn hier; die Vertragsbeschreibung in docs/TOOLS.md wurde mit main.go auf e032683 geschrieben.

Schlüssel

Geheimnisse gelangen nicht ins Repository: .env und .env.* sind in .gitignore, und die Vorlage liegt in env.example ohne jeden Wert.

Die Demonstration benötigt drei Terminals, und $env: lebt nur in einem, daher lohnt es sich, den Schlüssel auf Benutzerebene zu setzen – Administratorrechte sind dafür nicht nötig:

# так ключ не потрапляє ні в скролбек, ні в історію PSReadLine
$s = Read-Host "OWM_API_KEY" -AsSecureString
[Environment]::SetEnvironmentVariable("OWM_API_KEY",
  [Runtime.InteropServices.Marshal]::PtrToStringBSTR(
    [Runtime.InteropServices.Marshal]::SecureStringToBSTR($s)), "User")

Den neuen Wert sehen nur neue Terminals. Die Prüfung, dass er angekommen ist, ohne den Schlüssel preiszugeben: .venv/Scripts/python.exe -c "import os; print(len(os.environ.get('OWM_API_KEY','')))" – muss 32 ergeben. Vor der Kamera nicht dir env: ausführen: das druckt den Schlüssel.

Die einmalige Sitzungsform $env:OWM_API_KEY = "…" funktioniert ebenfalls, hat hier aber genau eine richtige Anwendung – den Schlüssel in einem separaten Fenster für das Fehlerszenario zurücksetzen: $env:OWM_API_KEY = "".

Der Schlüssel wird nur aus der Umgebung gelesen – weder im Code noch in .mcp.json.example gibt es ihn; dort steht die Substitution ${OWM_API_KEY}. Die Datei .env liest niemand: im Code gibt es nur os.environ.get, daher ist das Kopieren von env.example nach .env eine leere Handlung.

Modellzugang

Der eigene Server und alle 57 Tests funktionieren ohne jegliche Anthropic-Zugangsdaten – das sind verschiedene Dinge und sollte man nicht verwechseln. Das Modell braucht genau eine Datei, agent/run.py.

Das Claude Agent SDK greift nicht selbst auf die API zu: Es startet die claude CLI als Kindprozess, und genau diese CLI sucht die Autorisierung. Daher werden zwei Dinge benötigt:

  1. claude im PATH. Prüfung: (Get-Command claude).Source. Installation – gemäß offizieller Anleitung; in diesem Projekt wurde es über WinGet installiert und liegt unter %LOCALAPPDATA%\Microsoft\WinGet\Links\claude.exe.

  2. Autorisierung – einer von zwei Wegen, und die CLI nimmt den, den sie findet:

    • claude login – interaktive Anmeldung; das CLI legt das Token in ~/.claude/.credentials.json. Genau dieser Weg wurde hier verwendet: In der Prozessumgebung gibt es keine einzige Variable ANTHROPIC_*, die Zugangsdatendatei ist aber vorhanden. Der aufgezeichnete Lauf vom 25. August 2026 lief so ab.

    • ANTHROPIC_API_KEY in der Umgebung – Schlüssel von console.anthropic.com. Wird genauso gesetzt wie OWM_API_KEY oben und gelangt ebenso nicht ins Repository.

Was im Code fest verdrahtet ist: das Modell claude-opus-5 (agent/run.py) und claude-agent-sdk==0.2.144 (requirements.txt). Wenn du einen anderen Zugang hast und diese Modell-ID nicht aufgelöst wird – ersetze sie in run.py durch eine verfügbare und notiere hier, welche; der Rest des Laufs hängt nicht von der ID ab.

Keine einzige Zugangsdatei liest oder übergibt dieser Code: agent/run.py greift weder auf ANTHROPIC_API_KEY noch auf die Zugangsdatendatei zu – das erledigt die CLI. Im Repository gibt es keine Geheimnisse, und env.example liegt leer vor.

Limits der externen API

Der kostenlose OpenWeather-Plan bietet 60 Aufrufe pro Minute (Dokumentation). Ein Agentenlauf macht einen Aufruf des Tools weather; im Inneren wandelt der Wetterserver ihn in zwei HTTP-Anfragen um (aktuelles Wetter + 5-Tage-Vorhersage). Das heißt, bis zur Obergrenze sind selbst bei ununterbrochenen Proben drei Größenordnungen Reserve.

Im Code gibt es keine einzige Abfrageschleife, keinen Wiederholungsversuch bei Fehlern und kein Hintergrund-Update: Das Wetter wird genau dann abgefragt, wenn das Modell das Tool aufruft. Der eigene Server geht überhaupt nicht ins Netz – sein Datensatz liegt in data/, daher erzeugen beliebig viele Läufe von estimate_pv_generation, validate_energy_plan und der übrigen keinerlei externe Anfrage.

Start: zwei unabhängige Prozesse

Der eigene Server wird getrennt vom Agenten gestartet und weiß nichts über den Agenten.

Terminal 1 – eigener MCP-Server:

$env:PYTHONUTF8 = "1"
.venv\Scripts\python.exe -m solar_mcp --transport streamable-http --port 8931

Terminal 2 – Agent:

[Console]::OutputEncoding = [Text.Encoding]::UTF8
$env:PYTHONUTF8 = "1"
.venv\Scripts\python.exe agent\run.py

Ohne --date plant der Agent den morgigen Tag: Die Produktfrage betrifft genau morgen, und die OpenWeather-Vorhersage deckt nur jetzt … +5 Tage ab, daher liegt der heutige Tag schon zur Hälfte außerhalb des Horizonts. Ein Datum außerhalb dieses Fensters ergibt NO_FORECAST_FOR_DATE, nicht stille Nullen.

Den Wetterserver startet der Agent selbst, über stdio – so ist die Verbindung konfiguriert. Den eigenen Server kann man ebenfalls über stdio starten (python -m solar_mcp, das ist der Standard) – so erwarten ihn Clients wie Claude Code, und genau diese Variante ist in .mcp.json.example beschrieben. Für die Demonstration ist HTTP besser: Dann sieht man, dass der Server wirklich ein separater Prozess ist.

Nützliche Agenten-Flags:

--plan boiler:18:2 --plan aircon:18:3    # свій план замість дефолтного (можна кілька разів)
--date YYYY-MM-DD                        # інша доба; вт/чт/пт — без відключень, сб/нд — вечірнє вікно
--objective maximize_outage_reserve      # інша цільова функція
--city Lviv                              # інше місто
--width 120                              # скільки символів сліду друкувати

--date akzeptiert nur einen Tag innerhalb des Vorhersagehorizontsmorgen … heute + 5. Ein Datum außerhalb ergibt NO_FORECAST_FOR_DATE, und das Vorhandensein eines Abschaltfensters im Plan rettet das nicht: Der Plan liegt im Repository und kennt jedes beliebige Datum, die Vorhersage lebt fünf Tage. Vor dem Start prüfen: scripts/call_weather.py --city Kyiv --covers YYYY-MM-DD.

Die Daten im Abschaltplan haben ein wöchentliches Muster und eine Herkunft – siehe data/outage_windows.json: Die Fenster vom 22.–26. August stammen aus dem öffentlichen Zeitplan, danach wird dasselbe Muster nach vorne wiederholt, damit die Demonstration nicht vom Aufnahmedatum abhängt.

Prüfung, dass alles lebt

# 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\ -q

Die Tests benötigen weder Netzwerk noch OpenWeather-Schlüssel noch Modellzugang: Der Datensatz liegt im Repository, und die Antworten des fremden Servers sind in tests/fixtures/ aufgezeichnet.

Was wo liegt

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.md

Zwei dieser Verzeichnisse haben ein eigenes README, und genau sie sucht man unter „Datenquelle" und „Fixtures": data/README.md – woher die PVGIS-Zeile, der Tarif und der Abschaltplan stammen; tests/fixtures/README.md – was genau vom fremden Server aufgezeichnet wurde, wann und womit.

Eine Beobachtung, auf der die Hälfte des Designs steht

Der Wetterserver unterscheidet einen Fehler nicht von einer leeren Antwort. Ohne Schlüssel gibt er is_error: false und einen Text mit Nullen und leerem Stadtnamen zurück – wörtlich aufgezeichnet in tests/fixtures/owm_no_api_key.txt, obwohl sein README „FATAL: OWM_API_KEY environment variable not set" verspricht.

Deshalb wurde der eigene Server umgekehrt gebaut: eine geschlossene Liste von Fehlercodes, field mit Angabe des verantwortlichen Feldes, und separat – reason dort, wo Leere legitim ist (Nacht, keine Verstöße). Details: DESIGN.md, TOOLS.md.

-
license - not tested
Not graded
quality - not tested
B
maintenance

Maintenance

Maintainers
Response time
Release cycle
Releases (12mo)
Commit activity

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?'

View all MCP Connectors

Latest Blog Posts

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