**Podnimaet DB — FastAPI service**
- **Назначение:** минимальное API на FastAPI для демонстрации подключения к PostgreSQL и управления простыми сущностями (пользователи).
- **База данных:** проект использует переменную окружения `DATABASE_URL` с PostgreSQL (пример: `postgresql://asx:asxAdmin1@192.168.0.134:5432/mydb`).
**Структура проекта**
- `app/` — исходники FastAPI-приложения
- `main.py` — точка входа приложения
- `config.py` — конфигурация (через `.env` поддерживается)
- `db.py` — подключение к базе (package `databases` + SQLAlchemy metadata)
- `models.py` — SQLAlchemy таблицы
- `schemas.py` — Pydantic-схемы
- `crud.py` — простые операции над БД
- `requirements.txt` — зависимости
- `.env.example` — пример переменных окружения
**Как использовать (локально / на сервере)**
1. Клонируйте репозиторий на сервер/локально.
2. Создайте виртуальное окружение и установите зависимости:
```bash
python3 -m venv .venv
source .venv/bin/activate
pip install -r requirements.txt
```
3. Создайте файл `.env` рядом с `README.md` (или экспортируйте переменную `DATABASE_URL`):
```ini
DATABASE_URL=postgresql://asx:asxAdmin1@192.168.0.134:5432/mydb
```
4. Запустить сервер (пример):
```bash
uvicorn app.main:app --host 0.0.0.0 --port 8000 --reload
```
5. Простейшие эндпоинты:
- `POST /users/` — создать пользователя (json: `{"email":"..","name":".."}`)
- `GET /users/` — получить список пользователей
**Деплой на Ubuntu (рекомендация)**
1. На сервере установите Python 3.10+ и создайте виртуальное окружение.
2. Настройте системную службу `systemd` для запуска `uvicorn` через Gunicorn/uvicorn workers или запускать uvicorn напрямую.
Пример unit-файла `podnimaet.service`:
```ini
[Unit]
Description=Podnimaet FastAPI
After=network.target
[Service]
User=www-data
Group=www-data
WorkingDirectory=/path/to/project
Environment=DATABASE_URL=postgresql://asx:asxAdmin1@192.168.0.134:5432/mydb
ExecStart=/path/to/.venv/bin/uvicorn app.main:app --host 0.0.0.0 --port 8000
Restart=always
[Install]
WantedBy=multi-user.target
```
3. `sudo systemctl daemon-reload && sudo systemctl enable --now podnimaet.service`.
Если потребуется помощь с настройкой systemd/nginx/reverse-proxy или добавлением миграций (Alembic), напишите — добавлю инструкции.
# 🌤️ MCP Сервер Погоды с Deepseek
Простой MCP сервер для получения погоды через OpenWeatherMap API с использованием Deepseek API в качестве интерфейса и поддержкой модульной архитектуры.
## 📋 Что это делает?
- 🌍 Получает текущую погоду для любого города через OpenWeatherMap API
- 📅 Показывает прогноз погоды на несколько дней
- 🤖 Использует Deepseek для естественного общения и вызова инструментов с реальными данными
- 🔧 Реализует протокол MCP для подключения AI к внешним данным
- 📦 Модульная архитектура для легкого добавления новых функций
## 📁 Структура проекта
```
OpenWeatherMap_MCP/
├── modules/ # Пакет модулей приложения
│ ├── __init__.py # Инициализация пакета модулей
│ ├── config.py # Конфигурация (загрузка переменных окружения)
│ ├── weather_api.py # Функции для работы с OpenWeatherMap API
│ └── deepseek_api.py # Функции для работы с Deepseek API
├── server.py # MCP сервер с инструментами погоды
├── deepseek_client.py # Клиент для интерактивного чата с Deepseek
├── client.py # Альтернативный клиент для тестирования
├── .env # API ключи (не добавляйте в Git!)
├── requirements.txt # Python зависимости
└── 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
# API ключ OpenWeatherMap (бесплатный)
# Получите на: https://openweathermap.org/api
OPENWEATHER_API_KEY=ваш_ключ_здесь
# API ключ Deepseek
# Получите на: https://platform.deepseek.com/api-keys
DEEPSEEK_API_KEY=ваш_ключ_здесь
# Опционально: уровень логирования (INFO, DEBUG, WARNING, ERROR)
LOG_LEVEL=INFO
# Опционально: базовый URL для OpenWeatherMap API
OPENWEATHER_BASE_URL=https://api.openweathermap.org/data/2.5
# Опционально: базовая директория для файловых операций (ALLOWED_BASE_DIR)
ALLOWED_BASE_DIR=/path/to/allowed/dir
```
## База данных и загрузка отчётов
В проект добавлены утилиты для развёртывания PostgreSQL в Docker и загрузки отчётов Excel.
- `docker-compose.yml` — образец для запуска Postgres (порт `5432`).
- `modules/db.py` — модель SQLAlchemy и функции для создания таблицы `accruals`.
- `modules/db_loader.py` — скрипт загрузки Excel (файлы такого формата, как `Отчет по начислениям_*.xlsx`) в таблицу `accruals`.
Пример быстрого запуска (локально):
```bash
# Запустить Postgres
docker compose up -d
# Установить зависимости (если ещё не установлены)
/path/to/venv/bin/python -m pip install sqlalchemy psycopg2-binary
# Создать таблицы
/path/to/venv/bin/python -c "import modules.db as m; m.create_tables()"
# Загрузить Excel в БД
/path/to/venv/bin/python modules/db_loader.py "Отчет по начислениям_01.11.2025-30.11.2025.xlsx"
```
Переменные окружения для подключения (можно указать в `.env`):
```
POSTGRES_USER=weather_user
POSTGRES_PASSWORD=weather_pass
POSTGRES_DB=weather_db
POSTGRES_HOST=localhost
POSTGRES_PORT=5432
# Или DATABASE_URL=postgresql://user:pass@host:port/db
```
После размещения базы на удалённом сервере — укажите `DATABASE_URL` в окружении сервера/сервисов и Deepseek сможет подключаться к ней (в Deepseek нужно будет определить инструмент, который обращается к 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 работал с данными из PostgreSQL (например, с отчётами о начислениях), запустите FastAPI сервер:
```bash
# В отдельном терминале:
uvicorn modules.api:app --host 0.0.0.0 --port 8000 --reload
```
Убедитесь, что:
- PostgreSQL запущен (см. раздел "База данных и загрузка отчётов")
- Данные загружены в БД (через `modules/db_loader.py`)
- Переменная окружения `ACCRUALS_API_URL` = `http://localhost:8000` (по умолчанию)
Теперь в клиенте 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
```
### `modules/db.py`
**Отвечает за:** подключение к PostgreSQL, определение модели SQLAlchemy для таблицы `accruals`, создание таблиц.
**Основные функции:**
- `get_database_url()` - собирает строку подключения из `.env`
- `get_engine()` - возвращает engine SQLAlchemy
- `create_tables()` - создаёт все таблицы в БД
- `get_session()` - возвращает сессию для работы с БД
**Модель:**
- `Accrual` - ORM модель таблицы `accruals` с полями из Excel отчёта
### `modules/db_loader.py`
**Отвечает за:** загрузку данных из Excel в PostgreSQL.
**Использование:**
```bash
# Убедитесь, что Postgres запущен и таблицы созданы
python3 -c "import modules.db as m; m.create_tables()"
# Загрузите Excel
python3 modules/db_loader.py "Отчет по начислениям_01.11.2025-30.11.2025.xlsx"
```
### `modules/api.py`
**Отвечает за:** FastAPI приложение для REST доступа к данным о начислениях. Интегрируется с Deepseek через инструмент `query_accruals`.
**Основные endpoints:**
- `GET /health` — проверка статуса
- `GET /accruals` — список начислений с фильтрацией и пагинацией
- `GET /accruals/{id}` — одна запись по БД ID
- `GET /accruals/search/by-id-accrual?id_accrual=...` — поиск по ID начисления
- `GET /stats/accruals` — статистика (сумма, среднее, мин, макс)
- `GET /stats/summary` — общая сводка (кол-во, платформы, типы услуг)
**Для запуска:**
```bash
uvicorn modules.api:app --host 0.0.0.0 --port 8000 --reload
```
API будет доступен на `http://localhost:8000`. Документация (Swagger) на `http://localhost:8000/docs`.
### `deepseek_client.py`
**Отвечает за:** главную точку входа приложения - интерактивный чат с пользователем.
**Основные функции:**
- `chat_with_deepseek()` - интерактивный цикл чата с естественным языком
- `main()` - инициализация и запуск приложения
**Для запуска полного приложения:**
```bash
python3 deepseek_client.py
```
Это команда, которая вам нужна! Она запускает интерактивный чат с Deepseek, который использует реальные данные о погоде из OpenWeatherMap API и может запрашивать данные о начислениях (если API запущен).
## 🌐 Схема взаимодействия
```
```
## Запуск в Docker (рекомендуется для Ubuntu серверов)
В проект уже добавлены `Dockerfile` и `docker-compose.yml`, которые позволяют запустить приложение и PostgreSQL в контейнерах.
1. Скопируйте `.env.example` в `.env` и при необходимости измените `DATABASE_URL`:
```bash
cp .env.example .env
# Редактируйте .env, чтобы при необходимости подключиться к внешней БД
```
2. Соберите и запустите сервисы:
```bash
docker compose build --pull
docker compose up -d
```
3. Проверки и адреса:
- Приложение: `http://<server-ip>:8000`
- Swagger UI: `http://<server-ip>:8000/docs`
Примечания:
- По умолчанию `docker-compose.yml` создаёт локальный Postgres сервис `db`. Если хотите использовать внешнюю БД (например `192.168.0.134`), укажите соответствующий `DATABASE_URL` в `.env` перед запуском.
- Данные Postgres хранятся в volume `pgdata` (см. `docker-compose.yml`).
Если нужно, добавлю оптимизированный multi-stage `Dockerfile`, конфигурацию nginx как reverse-proxy или `Makefile` для удобных команд.
Пользователь
↓
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"
## ⚠️ Важные замечания
1. **Не используйте `print()` в server.py** - это сломает STDIO транспорт
2. **Храните `.env` в безопасности** - добавьте в `.gitignore`
3. **Лимиты API**:
- OpenWeatherMap Free: 1000 запросов/день
- Deepseek: зависит от вашего плана
4. **Стоимость Deepseek**: Более дешевая чем OpenAI
## 🐛 Решение проблем
**Ошибка: "OPENWEATHER_API_KEY не найден"**
- Проверьте, что файл `.env` создан и содержит ключ
- Убедитесь, что файл находится в той же папке, что и скрипты
**Ошибка: "Не удалось получить погоду"**
- Проверьте правильность написания города
- Попробуйте английское название города
**Сервер не запускается**
- Убедитесь, что виртуальное окружение активировано
- Проверьте, что все зависимости установлены
## 📚 Полезные ссылки
- [MCP Documentation](https://modelcontextprotocol.io/)
- [OpenWeatherMap API](https://openweathermap.org/api)
- [Канал "Черный треугольник"](https://t.me/black_triangle_tg)