Skip to main content
Glama

solar-plan-mcp

Agente que responde a una pregunta doméstica: ¿podré cubrir mañana este conjunto de consumidores con mi propia generación, y si no — qué traslado?

Tejado con paneles, batería, inversor, calendario de cortes conocido. El agente toma la previsión meteorológica de un servidor MCP ya preparado, calcula la producción esperada por horas en su propio servidor MCP, comprueba el plan contra las reglas físicas y, si no lo cumple, traslada las cargas flexibles y demuestra con números que ha mejorado.

Dos conexiones MCP:

Servidor

Rol

Listo

mschneider82/mcp-openweather, commit e032683

previsión: tipo de cielo y temperatura cada 3 horas

Propio

solar_mcp (este repositorio)

4 herramientas sustantivas del dominio + análisis del texto de la previsión

Documentación: contratos de las herramientas · razón de diseño · escenario de demostración

Qué se necesita

Para qué

Nota

Python 3.13

agente y servidor propio

no se necesitan privilegios de administrador

Go 1.24+

solo para compilar el servidor meteorológico

el proyecto no publica binarios listos; go.mod exige 1.24, aunque el README de allí dice 1.20

Clave de OpenWeather

servidor meteorológico

gratuita, openweathermap.org/api; tarda hasta varias horas en activarse

CLI claude + acceso al modelo

solo el agente; el servidor propio y los tests no lo necesitan

Claude Agent SDK lanza este CLI como proceso hijo — ver Acceso al modelo

Node + npx

opcional — MCP Inspector

npx @modelcontextprotocol/inspector

El conjunto de datos PVGIS ya está en el repositorio (data/pvgis_kyiv_5kwp.csv, 1,1 MB), por lo que el servidor propio funciona sin red. No hay que descargar nada.

Instalación

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

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

Windows, y esto no es cosmético: todos los comandos de abajo son en PowerShell, porque && en PowerShell 5.1 no es un operador en absoluto. En adelante, siempre .venv\Scripts\python.exe.

Dos variables de codificación, y son distintas. PYTHONUTF8=1 le dice a Python que escriba UTF-8; [Console]::OutputEncoding le dice a PowerShell que lo lea igualmente. Sin la segunda, la salida en ucraniano se convierte en ╨▓╨╗╨░╤ü╨╜╨╕╨╣ — medido, y precisamente en la tubería (| Tee-Object, | Select-String), porque allí PowerShell decodifica los bytes con la página de códigos de la consola. Por eso, en cada ventana nueva:

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

Compilar el servidor meteorológico

Go se instala en el perfil del usuario, sin administrador y sin cambios en el registro:

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

El agente busca el binario listo en la ruta vendor\mcp-openweather\mcp-weather.exe. Si lo tienes en otro sitio — no lo muevas, sino indica la variable: $env:WEATHER_MCP_BINARY = "…\mcp-weather.exe" (ver env.example). El agente comprueba la existencia del archivo antes de iniciar la sesión y se niega con una frase, no con un traceback desde dentro del SDK.

vendor/ está en .gitignore: la historia git ajena y 13 MB de binario en este repositorio no tienen nada que ver. El commit está fijado — precisamente sobre él está escrita la documentación del contrato.

Si el curso fija otro commit de mcp-openweather — tómalo y anótalo aquí; la descripción del contrato en docs/TOOLS.md se escribió a partir de main.go en e032683.

Clave

Los secretos no entran en el repositorio: .env y .env.* están en .gitignore, y la plantilla está en env.example sin ningún valor.

La demostración necesita tres terminales, y $env: solo vive en una, por lo que la clave conviene establecerla a nivel de usuario — no se necesitan privilegios de administrador para ello:

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

El nuevo valor lo verán solo las terminales nuevas. Comprobación de que ha llegado, sin revelar la clave: .venv/Scripts/python.exe -c "import os; print(len(os.environ.get('OWM_API_KEY','')))" — debe ser 32. En cámara no ejecutar dir env:: imprime la clave.

La forma de sesión puntual $env:OWM_API_KEY = "…" también funciona, pero tiene aquí un único uso correcto — borrar la clave en una ventana aparte para el escenario de fallo: $env:OWM_API_KEY = "".

La clave se lee solo del entorno — no está ni en el código ni en .mcp.json.example; allí hay una sustitución ${OWM_API_KEY}. El archivo .env nadie lo lee: en el código solo hay os.environ.get, así que copiar env.example a .env es una acción vacía.

Acceso al modelo

El servidor propio y los 57 tests funcionan sin ninguna credencial de Anthropic — son cosas distintas y no conviene confundirlas. El modelo lo necesita exactamente un archivo, agent/run.py.

Claude Agent SDK no se comunica con la API por sí mismo: lanza el CLI claude como proceso hijo, y es ese CLI el que busca la autorización. Por eso se necesitan dos cosas:

  1. claude en PATH. Comprobación: (Get-Command claude).Source. Instalación — según la instrucción oficial; en este proyecto se instaló con WinGet y está en %LOCALAPPDATA%\Microsoft\WinGet\Links\claude.exe.

  2. Autorización — una de dos vías, y el CLI toma la que encuentre:

    • claude login — inicio de sesión interactivo; el CLI guarda el token en ~/.claude/.credentials.json. Precisamente esta vía se usó aquí: en el entorno del proceso no hay ninguna variable ANTHROPIC_*, y el archivo de credenciales existe. La ejecución grabada del 25 de agosto de 2026 pasó así.

    • ANTHROPIC_API_KEY en el entorno — clave de console.anthropic.com. Se establece igual que OWM_API_KEY arriba, y tampoco entra en el repositorio.

Lo que está fijado en el código: el modelo claude-opus-5 (agent/run.py) y claude-agent-sdk==0.2.144 (requirements.txt). Si tienes otro acceso y este id de modelo no resuelve — sustitúyelo en run.py por uno disponible y anota aquí cuál; el resto de la ejecución no depende del id.

Ninguna credencial la lee ni la transmite este código: agent/run.py no accede ni a ANTHROPIC_API_KEY ni al archivo de credenciales — de eso se encarga el CLI. En el repositorio no hay secretos, y env.example está vacío.

Límites de la API externa

El plan gratuito de OpenWeather da 60 llamadas por minuto (documentación). Una ejecución del agente hace una llamada a la herramienta weather; dentro, el servidor meteorológico la convierte en dos peticiones HTTP (tiempo actual + previsión a 5 días). Es decir, hay tres órdenes de margen hasta el techo incluso con ensayos continuos.

En el código no hay ningún bucle de sondeo, reintento ante error ni actualización en segundo plano: el tiempo se consulta exactamente cuando el modelo llama a la herramienta. El servidor propio no sale a la red en absoluto — su conjunto de datos está en data/, por lo que cualquier número de ejecuciones de estimate_pv_generation, validate_energy_plan y el resto no genera ninguna petición externa.

Ejecución: dos procesos independientes

El servidor propio se levanta aparte del agente y no sabe nada del agente.

Terminal 1 — servidor MCP propio:

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

Terminal 2 — agente:

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

Sin --date, el agente planifica la jornada de mañana: la pregunta del producto es precisamente sobre mañana, y la previsión de OpenWeather solo cubre ahora … +5 días, así que la jornada de hoy ya está a medias fuera del horizonte. Una fecha fuera de esta ventana dará NO_FORECAST_FOR_DATE, no ceros silenciosos.

El agente levanta él mismo el servidor meteorológico, por stdio — así está configurada la conexión. El servidor propio también se puede lanzar por stdio (python -m solar_mcp, es el valor por defecto) — así lo esperan clientes como Claude Code, y es precisamente esa variante la descrita en .mcp.json.example. Para la demostración es mejor HTTP: entonces se ve que el servidor es realmente un proceso aparte.

Indicadores útiles del agente:

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

--date solo acepta una jornada dentro del horizonte de la previsiónmañana … hoy + 5. Una fecha fuera de él dará NO_FORECAST_FOR_DATE, y la existencia de una ventana de corte en el calendario no lo salva: el calendario está en el repositorio y conoce cualquier fecha, mientras que la previsión vive cinco días. Comprobar antes de ejecutar: scripts/call_weather.py --city Kyiv --covers YYYY-MM-DD.

Las fechas del calendario de cortes tienen un patrón semanal y procedencia — ver data/outage_windows.json: las ventanas del 22 al 26 de agosto están tomadas del calendario público, y luego el mismo patrón se repite hacia adelante, para que la demostración no dependa de la fecha de grabación.

Comprobación de que todo está vivo

# 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

Los tests no necesitan ni red, ni clave de OpenWeather, ni acceso al modelo: el conjunto de datos está en el repositorio, y las respuestas del servidor ajeno están grabadas en tests/fixtures/.

Qué hay dónde

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

Dos de estos directorios tienen su propio README, y son precisamente los que se buscan bajo «fuente de datos» y «fixtures»: data/README.md — de dónde se tomó la fila de PVGIS, la tarifa y el calendario de cortes; tests/fixtures/README.md — qué exactamente se grabó del servidor ajeno, cuándo y con qué.

Una observación sobre la que se sostiene la mitad del diseño

El servidor meteorológico no distingue un fallo de una respuesta vacía. Sin clave devuelve is_error: false y un texto con ceros y el nombre de ciudad vacío — grabado literalmente en tests/fixtures/owm_no_api_key.txt, aunque su README promete «FATAL: OWM_API_KEY environment variable not set».

Por eso el servidor propio se ha hecho al revés: lista cerrada de códigos de error, field con indicación del campo culpable, y por separado — reason allí donde el vacío es legítimo (noche, ausencia de infracciones). Detalles: 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