# Weather MCP Server & Client
A Model Context Protocol (MCP) implementation that exposes weather alerts from the [National Weather Service API](https://api.weather.gov) as tools. Includes an interactive chat client powered by Groq LLM and test scripts for both STDIO and SSE transports.
## Table of Contents
- [Prerequisites](#prerequisites)
- [Setup](#setup)
- [Configuration Files](#configuration-files)
- [Use Cases & How to Run](#use-cases--how-to-run)
- [Project Structure](#project-structure)
- [Troubleshooting](#troubleshooting)
---
## Prerequisites
- **Python 3.13+** (see pyproject.toml)
- **uv** – Python package manager ([install](https://docs.astral.sh/uv/))
- **Groq API Key** – for the LLM ([get one](https://console.groq.com/))
## Setup
1. **Clone or navigate to the project:**
```bash
cd /path/to/MCP
```
2. **Create a `.env` file** with your Groq API key:
```
GROQ_API_KEY=your_groq_api_key_here
```
3. **Install dependencies with uv:**
```bash
uv sync
```
This creates a `.venv` and installs all dependencies from `pyproject.toml`.
The project uses `langchain>=1.2.0,<2.0.0` for compatibility with mcp-use.
---
## Configuration Files
| File | Purpose |
|------|---------|
| `server/weather_mcp.json` | Default config for stdio: spawns `uv run server/weather.py` |
| `server/weather_stdio_config.json` | Same as above; used by stdio test script |
| `server/weather_sse_config.json` | SSE config: connects to `http://127.0.0.1:8000/sse` |
### Config Format
**STDIO (command-based):**
```json
{
"mcpServers": {
"weather": {
"command": "uv",
"args": ["run", "server/weather.py"]
}
}
}
```
**SSE (URL-based):**
```json
{
"mcpServers": {
"weather": {
"url": "http://127.0.0.1:8000/sse"
}
}
}
```
---
## Use Cases & How to Run
All commands use `uv run` to execute scripts with the project's virtual environment and dependencies.
### Case 1: Interactive Chat Client (STDIO)
Run an interactive chat that connects to the weather MCP server. The agent can call `get_alerts` when you ask about weather.
**Run:**
```bash
uv run client_chatbot.py
```
**Commands:**
- Type any question (e.g., "What are the weather alerts for California?")
- `exit` or `quit` – end the session
- `clear` – clear conversation history
**What happens:**
- Client reads `server/weather_mcp.json`
- Spawns `uv run server/weather.py` as a subprocess
- Communicates via stdin/stdout (stdio transport)
- Agent uses Groq LLM and calls `get_alerts` when needed
---
### Case 2: STDIO Transport Test
Explicit test of the stdio transport. Same behavior as Case 2 but uses a dedicated config file.
**Run:**
```bash
uv run test_weather_stdio.py
```
**What happens:**
- Uses `server/weather_stdio_config.json`
- Client spawns `uv run server/weather.py`
- Runs one query and exits
---
### Case 3: SSE Transport Test
Test the SSE (HTTP) transport. The script starts the server in HTTP mode, connects via URL, runs a query, then shuts down the server.
**Run:**
```bash
uv run test_weather_sse.py
```
**What happens:**
1. Starts `server/weather_sse.py` in the background (listens on port 8000)
2. Waits for the server to be ready
3. Connects to `http://127.0.0.1:8000/sse`
4. Runs one query
5. Terminates the server process
---
### Case 4: Run Weather Server Manually (SSE)
Run the weather server as a standalone HTTP process. Useful for debugging or when multiple clients need to connect.
**Run:**
```bash
# Terminal 1: Start the server
uv run server/weather_sse.py
```
Then in another terminal, use a client configured with `url: "http://127.0.0.1:8000/sse"` (e.g., `test_weather_sse.py` or a custom client with `weather_sse_config.json`).
---
### Case 6: Run Weather Server Manually (STDIO)
Running the stdio server directly is rarely useful because it expects JSON-RPC on stdin. It's normally spawned by the client.
For debugging:
```bash
uv run server/weather.py
# Server waits for stdin; won't do anything useful without a client
```
---
## Project Structure
```
MCP/
├── README.md # This file
├── .env # GroQ API key (create this)
├── pyproject.toml # Project dependencies
├── client_chatbot.py # Interactive chat client (stdio)
├── test_weather.py # Quick one-shot test (stdio)
├── test_weather_stdio.py # STDIO transport test
├── test_weather_sse.py # SSE transport test
├── server/
│ ├── weather.py # MCP server (STDIO transport)
│ ├── weather_sse.py # MCP server (SSE transport)
│ ├── weather_mcp.json # Default client config (stdio)
│ ├── weather_stdio_config.json
│ └── weather_sse_config.json
└── src/
└── app_mcp/
└── __init__.py # Package init
```
### MCP Tools Exposed
| Tool | Description | Args |
|------|-------------|------|
| `get_alerts` | Get active weather alerts for a US state | `state` (e.g., "CA", "NY") |
### MCP Resources
| URI | Description |
|-----|-------------|
| `echo://{message}` | Echo a message (for testing) |
---
## Troubleshooting
### "No module named 'mcp_use'"
Run `uv sync` to install dependencies, then use `uv run` for all scripts:
```bash
uv sync
uv run client_chatbot.py
```
### "ModuleNotFoundError: No module named 'httpx'"
Dependencies are in `pyproject.toml`. Run `uv sync` to install.
### "qwen-qwq-32b has been decommissioned"
The project uses `llama-3.3-70b-versatile`. If you see references to `qwen-qwq-32b`, update the model in the client/test scripts.
### "Connection closed" or "Invalid JSON"
Avoid printing to stdout from code that runs in the MCP server process. Stdio uses stdin/stdout for JSON-RPC; any extra output breaks the protocol.
### Port 8000 already in use
Stop the process using port 8000, or change the port in `server/weather_sse.py`:
```python
mcp = FastMCP("weather", host="127.0.0.1", port=8001)
```
Then update `SSE_SERVER_PORT` in `test_weather_sse.py` and the URL in `weather_sse_config.json`.
### Sandbox / uv cache errors
Run with full permissions if you see "Operation not permitted" for uv cache:
```bash
uv run client_chatbot.py # may need to run outside sandbox
```