# 🌤️ MCP Сервер Погоды с Deepseek
Простой MCP сервер для получения погоды через OpenWeatherMap API с использованием Deepseek API в качестве интерфейса и поддержкой модульной архитектуры.
## 📋 Что это делает?
- 🌍 Получает текущую погоду для любого города через OpenWeatherMap API
- 📅 Показывает прогноз погоды на несколько дней
- 🤖 Использует Deepseek для естественного общения и вызова инструментов с реальными данными
- 📦 Интегрирован с удалённой PostgreSQL базой и FastAPI для работы с данными о начислениях
- 🔧 Реализует протокол MCP для подключения AI к внешним данным
- 🏗️ Модульная архитектура с асинхронными операциями
## 📁 Структура проекта
```
OpenWeatherMap_MCP/
├── modules/ # Пакет модулей приложения
│ ├── __init__.py # Инициализация пакета модулей
│ ├── config.py # Конфигурация (загрузка переменных окружения)
│ ├── weather_api.py # Функции для работы с OpenWeatherMap API
│ ├── deepseek_api.py # Функции для работы с Deepseek API
│ └── file_api.py # Функции для файловых операций
├── fastapi_udalennii/ # Удалённый FastAPI проект (на другом хосте)
│ ├── app/
│ │ ├── main.py # FastAPI приложение с endpoints
│ │ ├── models.py # SQLAlchemy таблицы (users, accruals)
│ │ ├── schemas.py # Pydantic схемы для валидации
│ │ ├── crud.py # CRUD операции для БД
│ │ ├── db.py # Подключение к БД
│ │ └── config.py # Конфигурация
│ ├── alembic/ # Миграции БД
│ │ └── versions/
│ │ ├── 0001_create_users_table.py
│ │ └── 0002_create_accruals_table.py
│ ├── requirements.txt # Зависимости FastAPI
│ ├── .env # Конфиг БД для удалённого сервера
│ └── README.md # Инструкции для удалённого FastAPI
├── deepseek_client.py # Клиент для интерактивного чата с Deepseek
├── server.py # MCP сервер с инструментами погоды
├── test_project.py # Тесты
├── .env # API ключи (не добавляйте в Git!)
├── requirements.txt # Python зависимости для локального клиента
├── DEPLOYMENT_INSTRUCTIONS.md # Инструкции по развёртыванию FastAPI
└── README.md # Эта инструкция
```
## 🚀 Быстрый старт
### 1. Установка зависимостей
```bash
# Создайте виртуальное окружение
python3 -m venv venv
# Активируйте его
# На macOS/Linux:
source venv/bin/activate
# На Windows:
venv\Scripts\activate
# Установите зависимости
pip3 install -r requirements.txt
```
### 2. Настройка API ключей и подключений
Создайте файл `.env` в корне проекта:
```bash
# ===== OpenWeatherMap =====
OPENWEATHER_API_KEY=ваш_ключ_здесь
OPENWEATHER_BASE_URL=https://api.openweathermap.org/data/2.5
# ===== Deepseek =====
DEEPSEEK_API_KEY=ваш_ключ_здесь
# ===== Database (PostgreSQL) =====
DATABASE_URL=postgresql://username:password@192.168.0.134:5432/mydb
# ===== Accruals API (Remote FastAPI) =====
ACCRUALS_API_URL=http://192.168.0.137:8000
# ===== File Operations =====
ALLOWED_BASE_DIR=/path/to/allowed/dir
# ===== Logging =====
LOG_LEVEL=INFO
```
**Получение API ключей:**
- **OpenWeatherMap**:
1. Зарегистрируйтесь на https://openweathermap.org
2. Перейдите в раздел API Keys
3. Скопируйте ключ (бесплатный план: 1000 запросов/день)
- **Deepseek**:
1. Зарегистрируйтесь на https://platform.deepseek.com
2. Создайте новый API ключ
3. Пополните баланс (бесплатный кредит ~$5)
### 3. Запуск Deepseek клиента
```bash
python3 deepseek_client.py
```
### 4. (Опционально) Работа через удалённый API для начислений
Deepseek может запрашивать данные о начислениях через REST API (FastAPI) — если у вас уже развернут удалённый API, укажите его базовый URL в переменной `ACCRUALS_API_URL`.
```
ACCRUALS_API_URL=http://192.168.0.137:8000
```
Убедитесь, что удалённая база и API содержат необходимые данные — локальные утилиты для загрузки Excel (`modules/db_loader.py`) удалены из репозитория. После настройки `ACCRUALS_API_URL` Deepseek сможет запрашивать статистику и списки начислений у удалённого сервера.
Теперь в клиенте Deepseek можно спрашивать о начислениях (см. примеры ниже).
## 💬 Примеры использования
### Работа с погодой
После запуска `deepseek_client.py` просто спрашивайте о погоде на естественном языке:
```
👤 Вы: Какая погода в Москве?
🤖 Deepseek: [Проверяет текущую погоду в Москве через API и показывает результат]
👤 Вы: А какой прогноз на 5 дней для Санкт-Петербурга?
🤖 Deepseek: [Показывает прогноз на 5 дней]
👤 Вы: Что лучше надеть в Лондоне сегодня?
🤖 Deepseek: [Проверяет погоду и дает рекомендации]
👤 Вы: выход
👋 До свидания!
```
### Работа с данными о начислениях (Ozon)
После запуска API (см. раздел "Запуск API для работы с БД") можно запрашивать данные:
```
👤 Вы: Покажи статистику по начислениям
🤖 Deepseek: [Запрашивает /stats/summary и показывает общую сводку: кол-во записей, платформы, типы]
👤 Вы: Сколько начислений по услугам доставки?
🤖 Deepseek: [Запрашивает /stats/accruals?service_group=Услуги+доставки и показывает статистику]
👤 Вы: Покажи список последних начислений с платформы Ozon
🤖 Deepseek: [Запрашивает /accruals?sales_platform=Ozon&limit=50 и показывает записи]
👤 Вы: выход
👋 До свидания!
```
## 🔧 Описание модулей
### `modules/config.py`
**Отвечает за:** конфигурацию приложения, загрузку переменных окружения, валидацию ключей API.
**Основные компоненты:**
- `Config` - класс с константами конфигурации
- `validate()` - проверяет наличие критических переменных окружения
- `get_config_summary()` - возвращает сводку конфигурации для логирования
### `modules/weather_api.py`
**Отвечает за:** взаимодействие с OpenWeatherMap API для получения данных о погоде.
**Основные функции:**
- `make_weather_request()` - вспомогательная функция для HTTP запросов к API
- `get_current_weather()` - получает текущую погоду для города
- `get_forecast()` - получает прогноз на несколько дней
- `format_day_forecast()` - форматирует прогноз на один день
### `modules/deepseek_api.py`
**Отвечает за:** взаимодействие с Deepseek API для обработки запросов пользователя с использованием инструментов (функций).
**Основные функции:**
- `get_weather_tools()` - возвращает определение инструментов для Deepseek
- `call_deepseek_with_tools()` - вызывает Deepseek с поддержкой инструментов (function calling)
- `process_deepseek_response()` - обрабатывает ответ от Deepseek, выполняет вызовы инструментов
- `get_weather_response()` - главная функция для получения ответа о погоде
**Поддерживаемые инструменты:**
- Погода: `get_current_weather`, `get_forecast`
- Файлы: `read_file`, `create_file`, `update_file`, `append_to_file`, `delete_file`, `list_files`
### `modules/file_api.py`
**Отвечает за:** безопасную работу с файлами по определённому пути.
**Основные функции:**
- `read_file()` - чтение содержимого файла
- `create_file()` - создание нового файла
- `update_file()` - обновление содержимого файла
- `append_to_file()` - добавление содержимого в файл
- `delete_file()` - удаление файла
- `list_files()` - просмотр содержимого директории
- `is_path_safe()` - проверка безопасности пути (предотвращает path traversal атаки)
**Примеры команд для Deepseek:**
- "Создай файл test.txt с текстом 'Hello World'"
- "Прочитай содержимое файла README.md"
- "Обнови файл config.py на новый код"
- "Покажи список файлов в папке modules"
- "Добавь новую строку в файл notes.txt"
- "Удали временный файл temp.txt"
### `server.py`
**Отвечает за:** запуск MCP сервера с инструментами для интеграции с другими приложениями.
**Основные инструменты MCP:**
- `current_weather()` - инструмент для получения текущей погоды
- `weather_forecast()` - инструмент для получения прогноза
**Для запуска только MCP сервера (для интеграции с другими приложениями):**
```bash
uv run mcp dev server.py
```
### Удалённые локальные модули
Ранее в репозитории были утилиты для локальной загрузки данных и локальный API:
- `modules/db.py` — локальная SQLAlchemy модель и хелперы для создания таблиц
- `modules/db_loader.py` — скрипт загрузки Excel (pandas → БД)
- `modules/api.py` — FastAPI приложение для доступа к данным о начислениях
Эти файлы удалены из текущего репозитория в пользу использования удалённых сервисов (базы данных и API). Если вам нужно восстановить локальную загрузку или локальный API, можно восстановить соответствующие модули и добавить в `requirements.txt` зависимости: `pandas`, `openpyxl`, `sqlalchemy`, `psycopg2-binary`, `uvicorn`.
### `deepseek_client.py`
**Отвечает за:** главную точку входа приложения - интерактивный чат с пользователем.
**Основные функции:**
- `chat_with_deepseek()` - интерактивный цикл чата с естественным языком
- `main()` - инициализация и запуск приложения
**Для запуска полного приложения:**
```bash
python3 deepseek_client.py
```
Это команда, которая вам нужна! Она запускает интерактивный чат с Deepseek, который использует реальные данные о погоде из OpenWeatherMap API и может запрашивать данные о начислениях (если API запущен).
## 🌐 Схема взаимодействия
```
Пользователь
↓
deepseek_client.py (chat_with_deepseek)
↓
modules/deepseek_api.py (get_weather_response)
↓
Deepseek API
├─ Анализирует запрос
└─ Вызывает инструменты (function calling)
↓
modules/weather_api.py
├─ get_current_weather()
└─ get_forecast()
↓
OpenWeatherMap API
↓
Возвращает реальные данные о погоде
↓
Deepseek API (обработка результатов инструментов)
↓
Финальный ответ пользователю
```
## 🔌 Добавление новых функций
Чтобы добавить новый инструмент (например, получение качества воздуха):
1. **Добавьте функцию в модуль `modules/weather_api.py`:**
```python
async def get_air_quality(city: str) -> str:
"""Получить качество воздуха для города"""
# Реализация...
return result
```
2. **Добавьте определение инструмента в `modules/deepseek_api.py`:**
```python
def get_weather_tools() -> List[Dict[str, Any]]:
tools = [
# ... существующие инструменты ...
{
"type": "function",
"function": {
"name": "get_air_quality",
"description": "Получить качество воздуха",
# ... параметры ...
}
}
]
return tools
```
3. **Добавьте обработку в `process_deepseek_response()`:**
```python
if tool_name == "get_air_quality":
result = await get_air_quality(tool_args.get("city"))
```
4. **Добавьте инструмент в MCP сервер `server.py`:**
```python
@mcp.tool()
async def air_quality(city: str) -> str:
"""Инструмент MCP для получения качества воздуха"""
return await get_air_quality(city)
```
## 📊 Логирование
Приложение использует встроенный модуль `logging` для отслеживания всех операций. Логи записываются в файл `app.log` и выводятся в консоль.
**Уровни логирования:**
- `DEBUG` - подробная информация для отладки
- `INFO` - основная информация о работе
- `WARNING` - предупреждения
- `ERROR` - ошибки
- `CRITICAL` - критические ошибки
Уровень логирования можно настроить через переменную окружения `LOG_LEVEL` в `.env`.
## 🧪 Тестирование только сервера
Если хотите протестировать MCP сервер без клиента:
```bash
# Используйте MCP Inspector
uv run mcp dev server.py
# Или установите в Claude Desktop
uv run mcp install server.py --name "Weather Service"
```
## 🐛 Поиск и решение проблем
### Ошибка: "OPENWEATHER_API_KEY не найден"
**Решение:** Убедитесь, что файл `.env` находится в корне проекта и содержит `OPENWEATHER_API_KEY=ваш_ключ`
### Ошибка: "Не удалось получить погоду для города"
**Решение:**
- Проверьте написание названия города
- Убедитесь, что у вас есть интернет подключение
- Проверьте, не исчерпан ли лимит бесплатного плана OpenWeatherMap
### Ошибка: "Ошибка при обращении к Deepseek API"
**Решение:**
- Проверьте, что DEEPSEEK_API_KEY скопирован правильно
- Убедитесь, что на вашем счёте есть баланс для API запросов
- Проверьте статус Deepseek API на https://status.deepseek.com/
## 📝 Лицензия
Этот проект лицензирован под MIT License.
## 🤝 Контрибьютинг
Приветствуются pull requests! Для больших изменений сначала откройте issue для обсуждения.
## 🛠️ Доступные инструменты
### `get_current_weather`
Получает текущую погоду для города
**Параметры:**
- `city` (обязательный): Название города
- `units` (опционально): "metric" или "imperial"
### `get_forecast`
Получает прогноз погоды на несколько дней
**Параметры:**
- `city` (обязательный): Название города
- `days` (опционально): Количество дней (1-5)
- `units` (опционально): "metric" или "imperial"
## 🌐 Архитектура с удалённым FastAPI
Проект использует **двухуровневую архитектуру**:
### Локальный слой (ваша машина)
- **deepseek_client.py** - интерактивный чат с Deepseek
- **modules/deepseek_api.py** - интеграция с Deepseek для обработки запросов
- **modules/weather_api.py** - получение данных о погоде
- **modules/file_api.py** - файловые операции
### Удалённый слой (другой хост 192.168.0.137:8000)
- **fastapi_udalennii/app/main.py** - REST API для работы с начислениями (accruals)
- **fastapi_udalennii/app/models.py** - SQLAlchemy таблицы (users, accruals)
- **fastapi_udalennii/app/crud.py** - операции БД
- **fastapi_udalennii/app/schemas.py** - валидация данных (Pydantic)
### База данных (PostgreSQL)
- Хост: 192.168.0.134:5432
- База: mydb
- Пользователь: asx
### Схема взаимодействия:
```
Пользователь
↓
deepseek_client.py
↓
Deepseek API (обработка запроса)
├─ Погода → modules/weather_api.py → OpenWeatherMap API
├─ Файлы → modules/file_api.py → локальная ФС
└─ Начисления → httpx HTTP запрос → fastapi_udalennii (192.168.0.137:8000)
├─ GET /accruals/ → fastapi_udalennii/app/crud.py → PostgreSQL
├─ GET /stats/summary → fastapi_udalennii/app/crud.py → PostgreSQL
└─ POST /accruals/ → fastapi_udalennii/app/crud.py → PostgreSQL
↓
Deepseek API (формирует ответ)
↓
Пользователю
```
### Новые endpoints в FastAPI:
После развёртывания на удалённом сервере (см. `DEPLOYMENT_INSTRUCTIONS.md`) доступны:
**Accruals endpoints:**
- `POST /accruals/` - создание новой записи о начислении
- `GET /accruals/` - получение списка с фильтрацией
**Stats endpoints:**
- `GET /stats/summary` - общая статистика по всем начислениям
- `GET /stats/accruals` - статистика с фильтрацией
**Примеры запросов:**
```bash
# Получить все начисления
curl http://192.168.0.137:8000/accruals/
# Получить начисления по платформе Ozon
curl "http://192.168.0.137:8000/accruals/?sales_platform=Ozon&limit=50"
# Получить статистику
curl http://192.168.0.137:8000/stats/summary
# Создать новое начисление
curl -X POST http://192.168.0.137:8000/accruals/ \
-H "Content-Type: application/json" \
-d '{
"id_accrual": "ACC001",
"accrual_date": "2025-12-08",
"service_group": "Доставка",
"accrual_type": "Комиссия",
"sales_platform": "Ozon",
"total_amount_rub": 1234.56
}'
```
## ⚙️ Развёртывание и обновления
Для развёртывания обновлённого FastAPI на удалённом сервере смотрите инструкции в `DEPLOYMENT_INSTRUCTIONS.md`.
Краткая схема:
1. Синхронизация кода через `rsync`
2. Активация venv на удалённом сервере
3. Установка зависимостей (если добавлены новые)
4. Запуск миграций Alembic
5. Перезагрузка FastAPI сервиса
## ⚠️ Важные замечания
1. **Не используйте `print()` в server.py** - это сломает STDIO транспорт
2. **Храните `.env` в безопасности** - добавьте в `.gitignore`
3. **Лимиты API**:
- OpenWeatherMap Free: 1000 запросов/день
- Deepseek: зависит от вашего плана
4. **Стоимость Deepseek**: Более дешевая чем OpenAI
5. **Миграции БД**: После обновления FastAPI кода обязательно запустите `alembic upgrade head`
## 🐛 Решение проблем
**Ошибка: "OPENWEATHER_API_KEY не найден"**
- Проверьте, что файл `.env` создан и содержит ключ
- Убедитесь, что файл находится в той же папке, что и скрипты
**Ошибка: "Не удалось получить погоду"**
- Проверьте правильность написания города
- Попробуйте английское название города
**Сервер не запускается**
- Убедитесь, что виртуальное окружение активировано
- Проверьте, что все зависимости установлены
## 📚 Полезные ссылки
- [MCP Documentation](https://modelcontextprotocol.io/)
- [OpenWeatherMap API](https://openweathermap.org/api)
- [Канал "Черный треугольник"](https://t.me/black_triangle_tg)