# Ambient Weather MCP Server An [MCP (Model Context Protocol)](https://modelcontextprotocol.io/) server that connects AI assistants to [Ambient Weather](https://ambientweather.com/) personal weather station data. Ask natural language questions about your weather station instead of parsing raw JSON from the API. ## What It Does This server exposes your Ambient Weather station data as MCP tools. Connect it to Claude Desktop, VS Code, or Kiro, and you can ask things like: - "List my weather stations" - "What's the current temperature at my station?" - "What are the conditions at CC:7B:5C:51:EC:52?" The AI calls the tool, the server fetches live data from the Ambient Weather REST API, and the AI presents the result in natural language. ## Architecture ``` ┌──────────────────┐ stdio (JSON-RPC) ┌────────────────────┐ │ MCP Client │◄─────────────────────►│ MCP Server │ │ Claude Desktop │ │ (this project) │ │ VS Code / Kiro │ │ │ └──────────────────┘ │ src/server.py │ │ ↓ calls │ │ src/ambient_client │ │ ↓ HTTPS │ └────────┬───────────┘ │ ┌────────▼───────────┐ │ Ambient Weather │ │ REST API │ │ rt.ambientweather │ │ .net/v1 │ └────────────────────┘ ``` ## Available Tools | Tool | Description | Parameters | |------|-------------|------------| | `ping` | Health check — confirms server is running and keys are configured | None | | `get_devices` | Lists all weather stations on the account with latest readings | None | | `get_current_weather` | Full weather report from a specific station | `mac_address` | ## Prerequisites 1. **Ambient Weather API keys** — generate both at https://dashboard.ambientweather.net/account - **Application Key**: identifies the MCP server app - **API Key**: grants read access to device data 2. **Python 3.13+** installed 3. **uv** — modern Python package manager. Install: `curl -LsSf https://astral.sh/uv/install.sh | sh` 4. **An Ambient Weather station** reporting to ambientweather.net (or access to someone's API key who has one) ## Setup (Local Development) ```bash # Clone the repo git clone https://github.com/NanaGyamfiPrempeh30/ambient-weather-mcp.git cd ambient-weather-mcp # Install dependencies (uv creates .venv automatically) uv sync # Configure API keys cp .env.example .env # Edit .env with your actual keys # Test the server uv run python -c "from src.server import ping; import asyncio; print(asyncio.run(ping()))" ``` You should see: ``` Ambient Weather MCP server is running. API Key: configured Application Key: configured API Client: ready ``` ## Connecting to Claude Desktop ### Windows (with batch file) 1. Create `run_mcp.bat` in the project root: ```bat @echo off cd /d C:\Users\YourUsername\ambient-weather-mcp C:\Python313\python.exe -m src ``` 2. Add to `claude_desktop_config.json` (found at `%APPDATA%\Claude\claude_desktop_config.json`): ```json { "mcpServers": { "ambient-weather": { "command": "cmd.exe", "args": ["/c", "C:\\Users\\YourUsername\\ambient-weather-mcp\\run_mcp.bat"], "env": { "AMBIENT_API_KEY": "your-api-key", "AMBIENT_APP_KEY": "your-application-key" } } } } ``` ### macOS / Linux (direct) Add to Claude Desktop config: ```json { "mcpServers": { "ambient-weather": { "command": "uv", "args": ["run", "python", "-m", "src"], "cwd": "/path/to/ambient-weather-mcp", "env": { "AMBIENT_API_KEY": "your-api-key", "AMBIENT_APP_KEY": "your-application-key" } } } } ``` 3. Restart Claude Desktop fully (quit from system tray, reopen). 4. Check Settings → Developer → ambient-weather shows **running**. 5. In a new chat, ask: "Use the get_devices tool to list my weather stations" ## Running with Docker ```bash # Build docker build -t ambient-weather-mcp . # Run docker run -i --rm \ -e AMBIENT_API_KEY="your-api-key" \ -e AMBIENT_APP_KEY="your-app-key" \ ambient-weather-mcp ``` The Docker image is also published to GitHub Container Registry on every push to main: ```bash docker pull ghcr.io/nanagyamfiprempeh30/ambient-weather-mcp:latest ``` ## CI/CD Every push to `main` triggers two GitHub Actions workflows: - **Build and Push** — builds the Docker image, runs a smoke test, and pushes to ghcr.io with `latest` and commit SHA tags - **Secret Scanning** — runs TruffleHog to detect accidentally committed secrets A pre-commit hook (TruffleHog) also scans locally before every commit. See `.pre-commit-config.yaml` for setup instructions. ## Project Structure ``` ambient-weather-mcp/ ├── .github/ │ └── workflows/ │ ├── build-and-push.yml # Docker build + push to ghcr.io │ └── secret-scan.yml # TruffleHog secret scanning ├── .kiro/ │ └── specs/ │ ├── requirements.md # EARS-format requirements │ ├── design.md # Technical architecture │ └── tasks.md # Implementation tasks ├── kubernetes/ │ ├── namespace.yaml │ ├── deployment.yaml │ ├── service.yaml │ ├── ingress.yaml │ ├── servicemonitor.yaml │ └── secret.yaml.example # Secret template (safe to commit) ├── src/ │ ├── __init__.py # Package marker │ ├── __main__.py # Entry point for python -m src │ ├── server.py # MCP server + tool definitions │ └── ambient_client.py # Ambient Weather REST API client ├── .env.example # API key template (safe to commit) ├── .gitignore # Excludes .env, .venv, __pycache__ ├── .dockerignore # Excludes secrets from Docker image ├── .pre-commit-config.yaml # TruffleHog pre-commit hook ├── Dockerfile # Container build recipe (uses uv) ├── pyproject.toml # Python dependencies (managed by uv) ├── uv.lock # Locked dependency versions ├── run_mcp.bat # Windows launcher for Claude Desktop ├── DEBUG_LOG.md # Error tracking log └── README.md # This file ``` ## API Rate Limits The Ambient Weather API enforces: - 1 request/second per API key - 3 requests/second per Application key The server includes a 60-second TTL cache to stay within these limits automatically. Weather stations only report every 5 minutes, so caching loses nothing. ## Environment Variables | Variable | Required | Description | |----------|----------|-------------| | `AMBIENT_API_KEY` | Yes | Ambient Weather API key | | `AMBIENT_APP_KEY` | Yes | Ambient Weather Application key | | `CACHE_TTL_SECONDS` | No | Cache duration in seconds (default: 60) | | `LOG_LEVEL` | No | DEBUG, INFO, WARNING, ERROR (default: INFO) | ## Troubleshooting **"No module named src"** — Make sure you're running from the project root directory. On Windows with Claude Desktop, use the `cmd.exe` + batch file method shown above. **"Server disconnected" in Claude Desktop** — On Windows, use the `cmd.exe` + batch file method. Direct Python execution has working directory issues with Claude Desktop on Windows. **"401 Unauthorized"** — API keys are invalid. Regenerate at https://dashboard.ambientweather.net/account **"No weather stations found"** — The API key doesn't have any stations attached. You need a physical Ambient Weather station registered to the account. **"429 Too Many Requests"** — Rate limit hit. Wait a few seconds. Increase `CACHE_TTL_SECONDS` if it keeps happening. See `DEBUG_LOG.md` for a full history of issues encountered and their resolutions. ## What's Next - [x] CI/CD pipeline (GitHub Actions → ghcr.io) - [x] Kubernetes manifests for ArgoCD deployment - [x] Kiro spec-driven workflow (requirements, design, tasks) - [x] TruffleHog secret scanning (pre-commit + GitHub Actions) - [x] Migrate from pip to uv - [ ] `get_weather_history` tool for historical data queries - [ ] Security scanning tools (ruff, bandit, semgrep, safety) - [ ] Replace .env with proper secrets management - [ ] HTTP transport for network-based deployment - [ ] Publish to MCP marketplaces (mcp.so, Smithery, Sevalla) - [ ] MCP OAuth authorization for secure multi-user access - [ ] Medium article as Claude Partner Network case study ## Credits - [Ambient Weather API](https://ambientweather.docs.apiary.io/) - [Model Context Protocol](https://modelcontextprotocol.io/) - [FastMCP](https://github.com/jlowin/fastmcp) - Built by [Yaw Nana Gyamfi Prempeh](https://github.com/NanaGyamfiPrempeh30) - Wilson Mar — mentorship, weather station access, [MCP reference](https://wilsonmar.github.io/mcp/), [weather-info](https://wilsonmar.github.io/weather-info/) ## License MIT