solar_mcp
solar-plan-mcp
가정의 한 가지 실용적인 질문에 답하는 에이전트: 내일 이 소비자 세트를 자체 발전으로 감당할 수 있을까, 안 되면 무엇을 옮겨야 할까?
패널이 있는 지붕, 배터리, 인버터, 알려진 정전 일정. 에이전트는 준비된 MCP 서버에서 날씨 예보를 가져오고, 자체 MCP 서버에서 시간별 예상 발전량을 계산하며, 계획을 물리적 규칙에 대비해 검증하고, 통과하지 못하면 유연한 부하를 옮기고 숫자로 개선되었음을 증명합니다.
두 개의 MCP 연결:
서버 | 역할 | |
준비됨 |
| 예보: 3시간 간격 하늘 상태와 기온 |
자체 |
| 도메인의 4가지 실질적 도구 + 예보 텍스트 파싱 |
필요 사항
용도 | 비고 | |
Python 3.13 | 에이전트 및 자체 서버 | 관리자 권한 불필요 |
Go 1.24+ | 오직 날씨 서버 빌드용 | 프로젝트가 준비된 바이너리를 배포하지 않음; |
OpenWeather 키 | 날씨 서버 | 무료, openweathermap.org/api; 활성화에 최대 몇 시간 소요 |
| 오직 에이전트; 자체 서버와 테스트는 불필요 | Claude Agent SDK가 이 CLI를 자식 프로세스로 실행함 — 모델 접근 참조 |
Node + npx | 선택 사항 — MCP Inspector |
|
PVGIS 데이터셋은 이미 저장소에 있습니다 (data/pvgis_kyiv_5kwp.csv, 1.1MB), 따라서 자체 서버는 네트워크 없이 작동합니다. 다운로드할 것이 없습니다.
Related MCP server: KinSwitch
설치
Windows, 그리고 이것은 단순한 장식이 아닙니다: 모든 명령은 PowerShell에서 실행됩니다. PowerShell 5.1에서 &&는 연산자가 아니기 때문입니다. 이후 모든 곳에서 .venv\Scripts\python.exe를 사용합니다.
먼저 두 개의 인코딩 변수, 그리고 서로 다릅니다. PYTHONUTF8=1은 Python에게 UTF-8로 쓰라고 지시합니다; [Console]::OutputEncoding은 PowerShell에게 동일하게 읽으라고 지시합니다. 두 번째가 없으면 우크라이나어 출력이 ╨▓╨╗╨░╤ü╨╜╨╕╨╣로 변합니다 — 측정된 결과이며, 특히 파이프(| Tee-Object, | Select-String)에서 그렇습니다. PowerShell이 콘솔 코드 페이지로 바이트를 디코딩하기 때문입니다. 모든 새 창에서, 그리고 설치 전에 설정해야 합니다:
[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.txtPython 3.13이 필요합니다 — python --version이 응답하는 바로 그 버전입니다. venv는 생성에 사용된 인터프리터의 버전을 상속하기 때문입니다.
버전이 고정된 이유. 데모는 "어딘가에서 작동하는" 것이 아니라 재현 가능해야 합니다.
mcp==2.0.0은 이미 FastMCP 대신 MCPServer이며, 1.x용 코드는 여기서 작동하지 않습니다;
claude-agent-sdk==0.2.144 — 이 버전에서 tools와 에이전트가 두 연결을 출력하는 init 메시지 형식이 검증되었습니다; tzdata — Windows에는 시스템 시간대 데이터베이스가 없고, Europe/Kyiv가 없으면 현지 시간이 전혀 없기 때문입니다. requirements.txt 자체는 의도적으로 ASCII로 유지됩니다: pip는 로케일 인코딩으로 읽으며, 주석의 키릴 문자 하나가 UTF-8이 아닌 로케일의 모든 머신에서 pip install -r을 UnicodeDecodeError로 실패시킵니다. 깨끗한 클론에서 cp1252로 측정되었습니다 — 그래서 설명이 여기 있고 그 파일에 없는 것입니다.
날씨 서버 빌드
Go는 사용자 프로필에 설치되며, 관리자 권한이나 레지스트리 변경이 필요 없습니다:
# 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 ..\..준비된 바이너리를 에이전트는 vendor\mcp-openweather\mcp-weather.exe 경로에서 찾습니다. 다른 위치에 있다면 — 이동하지 말고 변수를 지정하세요: $env:WEATHER_MCP_BINARY = "…\mcp-weather.exe" (env.example 참조). 에이전트는 세션 시작 전에 파일 존재를 확인하고 SDK 내부의 트레이스가 아닌 문장으로 거부합니다.
vendor/는 .gitignore에 있습니다: 외부 git 히스토리와 13MB 바이너리가 이 저장소와 무관합니다. 커밋은 고정되어 있습니다 — 계약 문서가 바로 이 커밋을 기준으로 작성되었습니다.
과정이 다른
mcp-openweather커밋을 고정한다면 — 그것을 사용하고 여기에 기록하세요;docs/TOOLS.md의 계약 설명은e032683의main.go를 기준으로 작성되었습니다.
키
비밀은 저장소에 들어가지 않습니다: .env와 .env.*는 .gitignore에 있고, 샘플은 값 없이 env.example에 있습니다.
데모에는 세 개의 터미널이 필요하고 $env:는 하나에서만 살아있으므로, 키는 사용자 수준에서 설정하는 것이 좋습니다 — 관리자 권한이 필요하지 않습니다:
# так ключ не потрапляє ні в скролбек, ні в історію PSReadLine
$s = Read-Host "OWM_API_KEY" -AsSecureString
[Environment]::SetEnvironmentVariable("OWM_API_KEY",
[Runtime.InteropServices.Marshal]::PtrToStringBSTR(
[Runtime.InteropServices.Marshal]::SecureStringToBSTR($s)), "User")새 값은 새로운 터미널에서만 보입니다. 키를 노출하지 않고 도착했는지 확인: .venv/Scripts/python.exe -c "import os; print(len(os.environ.get('OWM_API_KEY','')))" — 32여야 합니다. 카메라 앞에서 dir env:를 실행하지 마세요: 키를 출력합니다.
일회성 세션 형식 $env:OWM_API_KEY = "…"도 작동하지만, 여기서는 한 가지 올바른 용도가 있습니다 — 실패 시나리오를 위해 별도 창에서 키를 재설정하는 것입니다: $env:OWM_API_KEY = "".
키는 환경에서만 읽힙니다 — 코드에도 .mcp.json.example에도 없습니다; 거기에는 ${OWM_API_KEY} 대체가 있습니다. .env 파일은 아무도 읽지 않습니다: 코드에는 os.environ.get만 있으므로 env.example를 .env로 복사하는 것은 무의미한 행동입니다.
모델 접근
자체 서버와 57개 테스트 모두 어떤 Anthropic 자격 증명 없이 작동합니다 — 이는 서로 다른 것이며 혼동해서는 안 됩니다. 모델은 정확히 하나의 파일, agent/run.py에만 필요합니다.
Claude Agent SDK는 API에 직접 접근하지 않습니다: claude CLI를 자식 프로세스로 실행하며, 그 CLI가 인증을 찾습니다. 따라서 두 가지가 필요합니다:
PATH에claude. 확인:(Get-Command claude).Source. 설치 — 공식 지침에 따름; 이 프로젝트에서는 WinGet으로 설치되었고%LOCALAPPDATA%\Microsoft\WinGet\Links\claude.exe에 있습니다.인증 — 두 가지 방법 중 하나, CLI는 찾는 것을 사용합니다:
claude login— 대화형 로그인; CLI 토큰을~/.claude/.credentials.json에 저장합니다. 여기서 사용된 것은 바로 이 방법입니다: 프로세스 환경에ANTHROPIC_*변수가 없고 자격 증명 파일이 있습니다. 2026년 8월 25일 기록된 실행이 이렇게 통과했습니다.환경의
ANTHROPIC_API_KEY— console.anthropic.com의 키. 위의OWM_API_KEY와 같은 방식으로 설정되며, 마찬가지로 저장소에 들어가지 않습니다.
코드에 고정된 것: 모델 claude-opus-5 (agent/run.py) 및 claude-agent-sdk==0.2.144 (requirements.txt). 다른 접근 권한이 있고 이 모델 id가 해석되지 않으면 — run.py에서 사용 가능한 것으로 교체하고 여기에 어떤 것인지 기록하세요; 나머지 실행은 id와 무관합니다.
이 코드는 어떤 자격 증명도 읽거나 전달하지 않습니다: agent/run.py는 ANTHROPIC_API_KEY도 자격 증명 파일도 접근하지 않습니다 — 이는 CLI가 담당합니다. 저장소에 비밀이 없고 env.example은 비어 있습니다.
외부 API 한도
OpenWeather 무료 플랜은 분당 60회 호출을 제공합니다
(문서). 에이전트 실행 한 번은 weather 도구를 한 번 호출합니다; 내부적으로 날씨 서버는 이를 두 개의 HTTP 요청으로 변환합니다 (현재 날씨 + 5일 예보). 즉, 연속 리허설에도 한도까지 세 자리 수의 여유가 있습니다.
코드에는 폴링 루프, 오류 시 재시도, 백그라운드 갱신이 없습니다: 날씨는 모델이 도구를 호출할 때 정확히 요청됩니다. 자체 서버는 네트워크에 전혀 가지 않습니다 — 데이터셋이 data/에 있으므로 estimate_pv_generation, validate_energy_plan 및 나머지의 실행 횟수와 무관하게 외부 요청이 생성되지 않습니다.
실행: 두 개의 독립 프로세스
자체 서버는 에이전트와 별도로 시작되며 에이전트에 대해 아무것도 모릅니다.
터미널 1 — 자체 MCP 서버:
$env:PYTHONUTF8 = "1"
.venv\Scripts\python.exe -m solar_mcp --transport streamable-http --port 8931터미널 2 — 에이전트:
[Console]::OutputEncoding = [Text.Encoding]::UTF8
$env:PYTHONUTF8 = "1"
.venv\Scripts\python.exe agent\run.py--date 없이 에이전트는 내일 하루를 계획합니다: 제품 질문이 바로 내일에 대한 것이고, OpenWeather 예보는 지금 … +5일만 덮으므로 오늘 하루는 이미 절반이 범위 밖입니다. 이 창 밖의 날짜는 조용한 0이 아닌 NO_FORECAST_FOR_DATE를 반환합니다.
날씨 서버는 에이전트가 stdio로 직접 시작합니다 — 연결이 그렇게 구성되어 있습니다. 자체 서버도 stdio로 실행할 수 있습니다 (python -m solar_mcp, 기본값) — Claude Code 같은 클라이언트가 그렇게 기대하며, .mcp.json.example에 설명된 것도 바로 이 방식입니다. 데모에는 HTTP가 더 좋습니다: 서버가 실제로 별도 프로세스임을 볼 수 있기 때문입니다.
유용한 에이전트 플래그:
--plan boiler:18:2 --plan aircon:18:3 # свій план замість дефолтного (можна кілька разів)
--date YYYY-MM-DD # інша доба; вт/чт/пт — без відключень, сб/нд — вечірнє вікно
--objective maximize_outage_reserve # інша цільова функція
--city Lviv # інше місто
--width 120 # скільки символів сліду друкувати--date는 예보 범위 내의 하루만 허용합니다 — 내일 … 오늘 + 5.
범위 밖의 날짜는 NO_FORECAST_FOR_DATE를 반환하며, 일정에 정전 창이 있다고 해결되지 않습니다: 일정은 저장소에 있고 어떤 날짜든 알지만 예보는 5일만 살아있습니다. 실행 전 확인: scripts/call_weather.py --city Kyiv --covers YYYY-MM-DD.
정전 일정의 날짜는 주간 패턴과 출처가 있습니다 — data/outage_windows.json 참조: 8월 22–26일 창은 공개 일정에서 가져왔고, 이후 동일한 패턴이 앞으로 반복되어 데모가 녹화 날짜에 의존하지 않습니다.
모든 것이 살아있는지 확인
# 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테스트는 네트워크, OpenWeather 키, 모델 접근이 필요 없습니다: 데이터셋은 저장소에 있고 외부 서버의 응답은 tests/fixtures/에 기록되어 있습니다.
파일 구조
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이 중 두 디렉토리는 자체 README가 있으며 "데이터 소스"와 "픽스처"로 찾는 곳입니다: data/README.md — PVGIS 행, 요금, 정전 일정의 출처; tests/fixtures/README.md — 외부 서버에서 정확히 무엇을, 언제, 무엇으로 기록했는지.
디자인 절반의 기반이 되는 한 가지 관찰
날씨 서버는 고장과 빈 응답을 구분하지 않습니다. 키 없이 is_error: false와 0과 빈 도시 이름이 있는 텍스트를 반환합니다 — tests/fixtures/owm_no_api_key.txt에 그대로 기록되어 있지만, README는 "FATAL: OWM_API_KEY environment variable not set"을 약속합니다.
따라서 자체 서버는 반대로 만들어졌습니다: 닫힌 오류 코드 목록, 잘못된 필드를 가리키는 field, 그리고 빈 값이 합법적인 곳(밤, 위반 없음)에는 별도로 reason. 자세한 내용: DESIGN.md, TOOLS.md.
This server cannot be deployed
Maintenance
Related MCP Connectors
Home energy for AI assistants: live Power flow, Energy history, solar forecast, and device control.
Solar, weatherization, EV charging, battery and heat-pump decision tools for AI agents.
EU power dispatch for wallet-enabled compute, DePIN, battery and trading agents.
Solar power estimates from the electricity bill, and the service area check, for São Paulo, Brazil.
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 gradedqualityBmaintenanceEnables AI agents to manage household schedules by checking availability, proposing minimal changes, and requiring explicit human approval before executing any action.MIT
- AlicenseNot gradedqualityBmaintenanceEnables conversational home power management by providing real-time solar, battery, and grid status, plus forecasts to answer questions like whether you can run an appliance. It supports Victron and Growatt inverters, remembers household appliances and grid events, and renders an interactive dashboard card in MCP-compatible clients.6 npmMIT
- AlicenseNot gradedqualityAmaintenanceEnables AI assistants to size hybrid renewable energy systems by simulating candidate designs hour-by-hour for a full year, filtering out constraint violations, and ranking remaining options by net present cost and related techno-economic metrics.Apache 2.0