Skip to main content
Glama
macdroidapps

Weather MCP Server

by macdroidapps
README.md
# 🌤️ MCP Weather Server + Next.js Chat

Полноценное решение для получения погоды через AI-ассистента. Включает MCP сервер на TypeScript и веб-интерфейс чата на Next.js.

## 🔗 MCP Tool Chain (NEW!)

Проект поддерживает **композицию из трёх MCP-инструментов** с автоматической агентной цепочкой:

```
┌────────────────────────────────────────────────────────────────────────────┐
│                         MCP TOOL CHAIN                                      │
├────────────────────────────────────────────────────────────────────────────┤
│                                                                             │
│   User: "Какая погода в Риге и что мне надеть?"                            │
│                           │                                                 │
│                           ▼                                                 │
│   ┌─────────────────────────────────────────────────────────────────────┐  │
│   │                    Claude AI (Orchestrator)                          │  │
│   │         Автоматически определяет цепочку инструментов               │  │
│   └───────────────────────────┬─────────────────────────────────────────┘  │
│                               │                                             │
│   ┌───────────────────────────┼─────────────────────────────────────────┐  │
│   │                           ▼                                          │  │
│   │   1️⃣  get_weather ──► 2️⃣  analyze_weather ──► 3️⃣  save_weather_report │  │
│   │      (Яндекс API)        (Рекомендации)          (Файл отчёта)       │  │
│   └─────────────────────────────────────────────────────────────────────┘  │
│                               │                                             │
│                               ▼                                             │
│   Response: "В Риге -2°C. Рекомендую зимнюю куртку. [Скачать отчёт]"       │
│                                                                             │
└────────────────────────────────────────────────────────────────────────────┘
```

### Три MCP инструмента

| Инструмент | Описание | Входные параметры | Выход |
|------------|----------|-------------------|-------|
| `get_weather` | Получение погоды из Яндекс API | `city` | температура, условия, влажность, давление |
| `analyze_weather` | Анализ и рекомендации | `weather_data`, `analysis_type` | рекомендации по одежде/активностям/здоровью |
| `save_weather_report` | Сохранение отчёта | `city`, `weather_data`, `analysis`, `format` | путь к файлу, URL для скачивания |

### Типы анализа

- **clothing** — что надеть (куртка, шапка, зонт и т.д.)
- **activity** — подходящие активности (пробежка, велосипед, пикник)
- **health** — влияние на здоровье (давление, влажность, риски)

### Форматы отчётов

- **md** — Markdown с таблицами и эмодзи
- **txt** — простой текстовый файл
- **json** — структурированные данные

## 📐 Архитектура

```
┌─────────────────────────────────────────────────────────────────────────────┐
│                              АРХИТЕКТУРА                                     │
├─────────────────────────────────────────────────────────────────────────────┤
│                                                                              │
│  ВАРИАНТ A: Claude Desktop + MCP (stdio)                                    │
│  ┌─────────────────┐     ┌─────────────────┐     ┌─────────────────────────┐│
│  │  Claude Desktop │────▶│   MCP Server    │────▶│  Яндекс Weather API    ││
│  │                 │◀────│   (stdio)       │◀────│                        ││
│  └─────────────────┘     └─────────────────┘     └─────────────────────────┘│
│                                                                              │
│  ВАРИАНТ B: Web Interface + MCP Tool Chain                                  │
│  ┌─────────────────┐     ┌─────────────────┐     ┌─────────────────────────┐│
│  │     Browser     │────▶│    Next.js      │────▶│   Claude API           ││
│  │                 │◀────│   (tool_use)    │◀────│   (Orchestrator)       ││
│  └─────────────────┘     └────────┬────────┘     └─────────────────────────┘│
│                                   │                                          │
│                                   ▼                                          │
│                          ┌─────────────────┐     ┌─────────────────────────┐│
│                          │  MCP Server     │────▶│  Яндекс Weather API    ││
│                          │  (HTTP :3001)   │◀────│  + File System         ││
│                          │  3 MCP Tools    │     │                        ││
│                          └─────────────────┘     └─────────────────────────┘│
│                                                                              │
└─────────────────────────────────────────────────────────────────────────────┘
```

**Claude автоматически выбирает инструменты** на основе запроса пользователя!

## 📁 Структура проекта

```
mcp-server/
├── src/                          # MCP Server (TypeScript)
│   ├── server.ts                 # MCP сервер (stdio для Claude Desktop)
│   ├── server-http.ts            # MCP сервер (HTTP) с 3 инструментами
│   ├── weather-service.ts        # Сервис работы с Yandex API
│   ├── tools/                    # MCP инструменты
│   │   ├── weather-analyzer.ts   # Анализ погоды (clothing/activity/health)
│   │   └── report-saver.ts       # Сохранение отчётов (txt/json/md)
│   ├── cities.ts                 # База координат городов
│   ├── cache.ts                  # In-memory кэширование
│   ├── logger.ts                 # Логгер
│   └── types.ts                  # TypeScript типы
├── weather-chat/                 # Next.js приложение
│   ├── app/                      # App Router
│   │   ├── api/chat/             # API чата с Claude (tool_use)
│   │   ├── api/weather/          # API погоды
│   │   ├── api/analyze/          # API анализа
│   │   ├── api/save-report/      # API сохранения отчётов
│   │   ├── api/tool-chain/       # API полной цепочки
│   │   ├── tools/page.tsx        # Страница Tool Chain UI
│   │   └── page.tsx              # Главная страница
│   ├── components/
│   │   ├── Chat.tsx              # Компонент чата
│   │   └── WeatherToolChain.tsx  # Визуализация цепочки
│   ├── lib/mcp-client.ts         # Клиент для MCP HTTP сервера
│   ├── types/weather.ts          # TypeScript типы
│   └── public/reports/           # Директория для отчётов
├── nginx/                        # Nginx конфигурация
├── scripts/                      # Скрипты развёртывания
├── ecosystem.config.cjs          # PM2 конфигурация
└── claude_desktop_config.json    # Конфиг для Claude Desktop
```

## 🚀 Быстрый старт

### 1. Установка MCP сервера

```bash
# Установка зависимостей
npm install

# Сборка TypeScript
npm run build

# Создание .env.local файла
cp .env.local.example .env.local
# Отредактируйте .env.local и добавьте YANDEX_WEATHER_API_KEY
```

### 2. Установка Next.js приложения

```bash
cd weather-chat

# Установка зависимостей
npm install

# Создание .env.local.local
cat > .env.local.local << EOF
YANDEX_WEATHER_API_KEY=ваш-ключ-яндекс
ANTHROPIC_API_KEY=ваш-ключ-anthropic
EOF

# Запуск в режиме разработки
npm run dev
```

### 3. Получение API ключей

#### Яндекс Weather API
1. Перейдите на https://developer.tech.yandex.ru/
2. Создайте приложение
3. Включите API "Яндекс Погода"
4. Скопируйте ключ

#### Anthropic API
1. Перейдите на https://console.anthropic.com/
2. Создайте API ключ
3. Скопируйте ключ

## 🔧 Варианты подключения

### Вариант A: Claude Desktop + MCP Server

Для локального использования с Claude Desktop:

1. Соберите MCP сервер:
```bash
npm run build
```

2. Найдите конфигурацию Claude Desktop:
   - macOS: `~/Library/Application Support/Claude/claude_desktop_config.json`
   - Windows: `%APPDATA%\Claude\claude_desktop_config.json`

3. Добавьте конфигурацию:
```json
{
  "mcpServers": {
    "weather": {
      "command": "node",
      "args": ["/полный/путь/к/mcp-server/dist/server.js"],
      "env": {
        "YANDEX_WEATHER_API_KEY": "ваш-api-ключ",
        "LOG_LEVEL": "info",
        "CACHE_TTL": "300"
      }
    }
  }
}
```

4. Перезапустите Claude Desktop

5. Теперь можно спрашивать: *"Какая погода в Риге?"*

### Вариант B: Next.js Web Interface

Для веб-интерфейса с чатом (через MCP HTTP сервер):

1. Настройте переменные окружения в `weather-chat/.env.local`:
```env
YANDEX_WEATHER_API_KEY=ваш-ключ
ANTHROPIC_API_KEY=ваш-ключ
MCP_SERVER_URL=http://127.0.0.1:3001
```

2. Запустите MCP HTTP сервер:
```bash
# В корне проекта
npm run build
npm run start:http
# или для разработки: npm run dev:http
```

3. Запустите Next.js (в другом терминале):
```bash
cd weather-chat
npm run dev
```

4. Откройте http://localhost:3000

**Важно:** MCP HTTP сервер должен быть запущен на порту 3001!

## 🖥️ Развёртывание на VPS

### Требования
- Ubuntu 20.04+ / Debian 11+
- Node.js 18+
- Nginx
- PM2

### Шаги развёртывания

1. **Подготовка сервера:**
```bash
# Обновление системы
sudo apt update && sudo apt upgrade -y

# Установка Node.js 20
curl -fsSL https://deb.nodesource.com/setup_20.x | sudo -E bash -
sudo apt install -y nodejs

# Установка PM2
sudo npm install -g pm2

# Установка Nginx
sudo apt install -y nginx
```

2. **Клонирование и настройка:**
```bash
# Клонируем проект
git clone https://github.com/your-repo/mcp-server.git /var/www/mcp-server
cd /var/www/mcp-server

# Настраиваем права
sudo chown -R $USER:$USER /var/www/mcp-server
```

3. **Настройка переменных окружения:**
```bash
# MCP Server
cat > .env.local << EOF
YANDEX_WEATHER_API_KEY=ваш-ключ
LOG_LEVEL=info
CACHE_TTL=300
EOF

# Next.js
cat > weather-chat/.env.local.local << EOF
YANDEX_WEATHER_API_KEY=ваш-ключ
ANTHROPIC_API_KEY=ваш-ключ
EOF
```

4. **Запуск через скрипт:**
```bash
chmod +x scripts/deploy.sh
./scripts/deploy.sh deploy
```

5. **Настройка Nginx:**
```bash
# Копируем конфигурацию
sudo cp nginx/weather-chat.conf /etc/nginx/sites-available/weather-chat

# Редактируем домен
sudo nano /etc/nginx/sites-available/weather-chat

# Активируем
sudo ln -s /etc/nginx/sites-available/weather-chat /etc/nginx/sites-enabled/

# Проверяем и перезапускаем
sudo nginx -t
sudo systemctl reload nginx
```

6. **SSL сертификат (Let's Encrypt):**
```bash
sudo apt install certbot python3-certbot-nginx
sudo certbot --nginx -d weather.yourdomain.com
```

### PM2 команды

```bash
# Статус
pm2 status

# Логи
pm2 logs weather-chat

# Перезапуск
pm2 restart weather-chat

# Остановка
pm2 stop weather-chat

# Мониторинг
pm2 monit
```

## 🧪 Тестирование

### Тестирование MCP сервера

```bash
# Сборка
npm run build

# Тест через echo (stdin)
echo '{"jsonrpc":"2.0","id":1,"method":"tools/list"}' | YANDEX_WEATHER_API_KEY=ваш-ключ node dist/server.js
```

### Тестирование API погоды

```bash
# GET запрос
curl "http://localhost:3000/api/weather?city=Рига"

# POST запрос
curl -X POST http://localhost:3000/api/weather \
  -H "Content-Type: application/json" \
  -d '{"city": "Москва"}'
```

### Тестирование чата

```bash
curl -X POST http://localhost:3000/api/chat \
  -H "Content-Type: application/json" \
  -d '{"message": "Какая сейчас погода в Риге?"}'
```

### Тестирование MCP Tool Chain (curl)

```bash
# 1. Получить погоду (MCP Server)
curl -X POST http://localhost:3001/api/weather \
  -H "Content-Type: application/json" \
  -d '{"city": "Рига"}'

# 2. Анализ погоды (с результатом шага 1)
curl -X POST http://localhost:3001/api/analyze \
  -H "Content-Type: application/json" \
  -d '{
    "weather_data": {
      "temperature": -2,
      "condition": "облачно",
      "humidity": 87,
      "pressure": 760,
      "city": "Рига",
      "feels_like": -6,
      "wind_speed": 4
    },
    "analysis_type": "clothing"
  }'

# 3. Сохранить отчёт
curl -X POST http://localhost:3001/api/save-report \
  -H "Content-Type: application/json" \
  -d '{
    "city": "Рига",
    "weather_data": {"temperature": -2, "condition": "облачно", "humidity": 87, "pressure": 760, "city": "Рига"},
    "analysis": {"type": "clothing", "city": "Рига", "temperature": -2, "condition": "облачно", "summary": "Тест", "timestamp": "2024-12-18T12:00:00Z"},
    "format": "md"
  }'

# 4. Выполнить всю цепочку (Next.js)
curl -X POST http://localhost:3000/api/tool-chain \
  -H "Content-Type: application/json" \
  -d '{"city": "Рига", "analysis_type": "clothing", "format": "md"}'
```

### Ожидаемый ответ погоды

```json
{
  "success": true,
  "data": {
    "temperature": -2,
    "condition": "облачно с прояснениями",
    "humidity": 87,
    "pressure": 760,
    "city": "Рига",
    "feels_like": -6,
    "wind_speed": 4
  }
}
```

### Ожидаемый ответ анализа

```json
{
  "success": true,
  "data": {
    "type": "clothing",
    "city": "Рига",
    "temperature": -2,
    "condition": "облачно с прояснениями",
    "summary": "В Рига сейчас -2°C, облачно с прояснениями. ❄️ Морозно. Нужна тёплая зимняя одежда",
    "clothing": {
      "main": "❄️ Морозно. Нужна тёплая зимняя одежда",
      "items": ["Зимняя куртка", "Тёплый свитер", "Джинсы/тёплые штаны", "Шапка", "Шарф", "Перчатки", "Зимняя обувь"]
    },
    "timestamp": "2024-12-18T12:00:00.000Z"
  }
}
```

### Ожидаемый ответ сохранения отчёта

```json
{
  "success": true,
  "data": {
    "file_path": "/reports/weather_riga_2024-12-18_14-30.md",
    "file_url": "/reports/weather_riga_2024-12-18_14-30.md",
    "file_name": "weather_riga_2024-12-18_14-30.md",
    "file_size": 1234,
    "format": "md",
    "timestamp": "2024-12-18T12:30:00.000Z"
  }
}
```

## 💬 Примеры диалогов с агентом

### Пример 1: Что надеть

```
User: Какая погода в Риге и что мне надеть?

Claude вызывает:
1. get_weather({city: "Рига"})
   → {temperature: -5, condition: "снег", feels_like: -10, ...}

2. analyze_weather({weather_data: {...}, analysis_type: "clothing"})
   → {main: "❄️ Морозно. Нужна тёплая зимняя одежда", items: [...]}

Response: 
🌨️ В Риге сейчас -5°C, идёт снег. Ощущается как -10°C.

👔 Рекомендую надеть:
• Зимняя куртка или пуховик
• Тёплый свитер
• Шапка и перчатки обязательно!
• Зимняя обувь

❄️ На улице снег - выбирайте непромокаемую обувь.
```

### Пример 2: Пробежка

```
User: Можно ли сегодня бегать в Москве?

Claude вызывает:
1. get_weather({city: "Москва"})
   → {temperature: 5, condition: "ясно", wind_speed: 3, ...}

2. analyze_weather({weather_data: {...}, analysis_type: "activity"})
   → {suitable: ["🏃 Пробежка"], tips: [...]}

Response:
☀️ В Москве 5°C, ясно. Отличные условия для пробежки!

🏃 Рекомендации:
• Идеальная температура для бега
• Ветер слабый (3 м/с) — не помешает
• Возьмите ветровку на всякий случай
```

### Пример 3: Полная цепочка с отчётом

```
User: Сделай отчёт о погоде в Париже для здоровья

Claude вызывает:
1. get_weather({city: "Париж"})
   → {temperature: 12, pressure: 745, humidity: 75, ...}

2. analyze_weather({weather_data: {...}, analysis_type: "health"})
   → {risk_level: "medium", warnings: ["📉 Низкое давление"], ...}

3. save_weather_report({city: "Париж", ..., format: "md"})
   → {file_url: "/reports/weather_parizh_2024-12-18.md", ...}

Response:
🌤️ В Париже 12°C. 

❤️ Влияние на здоровье:
🟡 Уровень риска: средний

⚠️ Предупреждения:
• 📉 Низкое атмосферное давление (745 мм) — возможны головные боли

💡 Рекомендации:
• Избегайте физических нагрузок
• Пейте больше воды

📄 [Скачать полный отчёт](/reports/weather_parizh_2024-12-18.md)
```

## 🔒 Безопасность

- ✅ API ключи только на сервере (не передаются клиенту)
- ✅ Rate limiting через Nginx
- ✅ HTTPS обязателен в продакшене
- ✅ Валидация входных данных через Zod
- ✅ Логирование без секретов
- ✅ Автоматическая оркестрация инструментов через Claude

## 📊 Структурированный ответ погоды

```typescript
interface WeatherResponse {
  temperature: number;    // °C
  condition: string;      // "ясно", "дождь", etc.
  humidity: number;       // %
  pressure: number;       // мм рт.ст.
  city: string;          // Название города
  feels_like?: number;   // Ощущаемая температура
  wind_speed?: number;   // м/с
  icon?: string;         // Код иконки
}
```

## 📄 Пример сгенерированного отчёта (Markdown)

```markdown
# 🌤️ Отчёт о погоде: Рига

> Сгенерировано: 18.12.2024, 14:30:00

---

## 📊 Текущая погода

| Параметр | Значение |
|----------|----------|
| 🌡️ Температура | **-2°C** |
| 🤒 Ощущается как | -6°C |
| ☁️ Условия | облачно с прояснениями |
| 💧 Влажность | 87% |
| 📊 Давление | 760 мм рт.ст. |
| 💨 Ветер | 4 м/с |

---

## 👔 Рекомендации по одежде

**В Рига сейчас -2°C, облачно с прояснениями. ❄️ Морозно. Нужна тёплая зимняя одежда**

### 📋 Что надеть

- Зимняя куртка
- Тёплый свитер
- Джинсы/тёплые штаны
- Шапка
- Шарф
- Перчатки
- Зимняя обувь

---

*Источник данных: Яндекс Weather API*

*Сгенерировано MCP Weather Server*
```

## 🌍 Поддерживаемые города

- **Россия:** Москва, Санкт-Петербург, Казань, Сочи, Владивосток, +20 городов
- **Прибалтика:** Рига, Таллин, Вильнюс
- **СНГ:** Минск, Киев, Алматы, Астана
- **Европа:** Берлин, Париж, Лондон, Амстердам, +15 городов
- **Азия:** Токио, Пекин, Сингапур, Дубай
- **Америка:** Нью-Йорк, Лос-Анджелес, Торонто

## 📝 Лицензия

ISC

## 🤝 Контрибуция

Pull requests приветствуются! Для крупных изменений сначала откройте issue.