mirror of
https://github.com/latinogino/dolibarr-mcp.git
synced 2026-04-23 02:05:35 +02:00
Merge cleanup-restructure-v2 into main
Branch cleanup-restructure-v2 wurde erfolgreich in main integriert.
This commit is contained in:
@@ -1,6 +1,6 @@
|
||||
# Dolibarr API Configuration
|
||||
DOLIBARR_URL=https://your-dolibarr-instance.com/api/index.php
|
||||
DOLIBARR_API_KEY=your_dolibarr_api_key_here
|
||||
# Dolibarr Configuration
|
||||
DOLIBARR_URL=https://your-dolibarr.example.com
|
||||
DOLIBARR_API_KEY=YOUR_API_KEY_HERE
|
||||
|
||||
# Logging Configuration
|
||||
# Logging
|
||||
LOG_LEVEL=INFO
|
||||
|
||||
66
.gitignore
vendored
66
.gitignore
vendored
@@ -25,16 +25,19 @@ share/python-wheels/
|
||||
.installed.cfg
|
||||
*.egg
|
||||
MANIFEST
|
||||
src/*.egg-info/
|
||||
*.egg-info
|
||||
|
||||
# PyInstaller
|
||||
*.manifest
|
||||
*.spec
|
||||
# Virtual environments
|
||||
venv/
|
||||
ENV/
|
||||
env/
|
||||
venv_dolibarr/
|
||||
.venv/
|
||||
|
||||
# Installer logs
|
||||
pip-log.txt
|
||||
pip-delete-this-directory.txt
|
||||
# PyCharm
|
||||
.idea/
|
||||
|
||||
# VS Code
|
||||
.vscode/
|
||||
|
||||
# Unit test / coverage reports
|
||||
htmlcov/
|
||||
@@ -51,42 +54,37 @@ coverage.xml
|
||||
.pytest_cache/
|
||||
cover/
|
||||
|
||||
# Virtual environments
|
||||
# Environments
|
||||
.env
|
||||
.venv
|
||||
env/
|
||||
venv/
|
||||
ENV/
|
||||
env.bak/
|
||||
venv.bak/
|
||||
venv_dolibarr/
|
||||
.env.local
|
||||
|
||||
# IDEs
|
||||
.vscode/
|
||||
.idea/
|
||||
*.swp
|
||||
*.swo
|
||||
*~
|
||||
# mypy
|
||||
.mypy_cache/
|
||||
.dmypy.json
|
||||
dmypy.json
|
||||
|
||||
# Pyre type checker
|
||||
.pyre/
|
||||
|
||||
# pytype static type analyzer
|
||||
.pytype/
|
||||
|
||||
# Cython debug symbols
|
||||
cython_debug/
|
||||
|
||||
# macOS
|
||||
.DS_Store
|
||||
|
||||
# Windows
|
||||
Thumbs.db
|
||||
ehthumbs.db
|
||||
Desktop.ini
|
||||
desktop.ini
|
||||
|
||||
# Logs
|
||||
*.log
|
||||
logs/
|
||||
|
||||
# MCP specific
|
||||
.mcp/
|
||||
mcp-server.log
|
||||
|
||||
# Dolibarr specific
|
||||
dolibarr_config.json
|
||||
|
||||
# Local development
|
||||
local/
|
||||
.local/
|
||||
# Temporary files
|
||||
*.tmp
|
||||
*.bak
|
||||
*.swp
|
||||
*~
|
||||
|
||||
124
CHANGELOG.md
124
CHANGELOG.md
@@ -1,102 +1,60 @@
|
||||
# Changelog
|
||||
|
||||
All notable changes to the Dolibarr MCP Server project will be documented in this file.
|
||||
All notable changes to the Dolibarr MCP Server will be documented in this file.
|
||||
|
||||
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
|
||||
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
||||
|
||||
## [1.1.0] - 2025-09-24
|
||||
## [1.0.0] - 2024-01-26
|
||||
|
||||
### 🔥 MAJOR FIX: Windows Compatibility
|
||||
- **FIXED**: Windows pywin32 permission issues that prevented installation
|
||||
- **ADDED**: Standalone server implementation that works WITHOUT MCP package
|
||||
- **ADDED**: `setup_standalone.bat` - Windows-optimized setup script
|
||||
- **ADDED**: `run_standalone.bat` - Start standalone server
|
||||
- **ADDED**: `requirements-windows.txt` - pywin32-free dependencies
|
||||
- **ADDED**: `test_standalone.py` - Test script for standalone version
|
||||
### 🎯 Major Restructuring
|
||||
|
||||
### ✨ New Features
|
||||
- **ADDED**: Interactive testing mode in standalone server
|
||||
- **ADDED**: Enhanced error handling with detailed API error messages
|
||||
- **ADDED**: Professional configuration validation with helpful setup guides
|
||||
- **ADDED**: Comprehensive German README (`README_DE.md`)
|
||||
This release represents a complete restructuring of the Dolibarr MCP Server to match the clean architecture of prestashop-mcp.
|
||||
|
||||
### 🛠️ Improvements
|
||||
- **IMPROVED**: Setup process with multiple fallback options
|
||||
- **IMPROVED**: Error messages with actionable troubleshooting steps
|
||||
- **IMPROVED**: Documentation with Windows-specific troubleshooting
|
||||
- **IMPROVED**: Docker configuration with health checks and resource limits
|
||||
### Added
|
||||
- Professional README.md with comprehensive documentation
|
||||
- Structured test suite in `tests/` directory
|
||||
- Clean configuration management
|
||||
- Docker support for easy deployment
|
||||
- Comprehensive CRUD operations for all Dolibarr entities
|
||||
|
||||
### 📋 Available Tools (Complete CRUD for all modules)
|
||||
- ✅ **System**: `test_connection`, `get_status`
|
||||
- ✅ **Users**: `get_users`, `get_user_by_id`, `create_user`, `update_user`, `delete_user`
|
||||
- ✅ **Customers**: `get_customers`, `get_customer_by_id`, `create_customer`, `update_customer`, `delete_customer`
|
||||
- ✅ **Products**: `get_products`, `get_product_by_id`, `create_product`, `update_product`, `delete_product`
|
||||
- ✅ **Invoices**: `get_invoices`, `get_invoice_by_id`, `create_invoice`, `update_invoice`, `delete_invoice`
|
||||
- ✅ **Orders**: `get_orders`, `get_order_by_id`, `create_order`, `update_order`, `delete_order`
|
||||
- ✅ **Contacts**: `get_contacts`, `get_contact_by_id`, `create_contact`, `update_contact`, `delete_contact`
|
||||
- ✅ **Raw API**: `dolibarr_raw_api` - Direct access to any Dolibarr endpoint
|
||||
### Changed
|
||||
- Complete repository restructuring to match prestashop-mcp pattern
|
||||
- Simplified dependencies in requirements.txt
|
||||
- Cleaned up package structure in `src/dolibarr_mcp/`
|
||||
- Updated pyproject.toml with proper metadata
|
||||
- Streamlined .gitignore file
|
||||
|
||||
### 🐳 Docker
|
||||
- **ADDED**: Multi-stage Dockerfile for optimized production builds
|
||||
- **ADDED**: docker-compose.yml with health checks
|
||||
- **ADDED**: Test service configuration for automated testing
|
||||
### Removed
|
||||
- All test scripts from root directory (moved to `tests/`)
|
||||
- Multiple batch files (consolidated functionality)
|
||||
- Alternative server implementations (simple_client, standalone_server, ultra_simple_server)
|
||||
- Redundant requirements files (kept only requirements.txt)
|
||||
- Unnecessary documentation files (CLAUDE_CONFIG.md, CONFIG_COMPATIBILITY.md, etc.)
|
||||
- API directory and contents
|
||||
|
||||
### 📚 Documentation
|
||||
- **ADDED**: Comprehensive setup instructions for Windows
|
||||
- **ADDED**: Troubleshooting guide for common issues
|
||||
- **ADDED**: API endpoint documentation and examples
|
||||
- **ADDED**: Contributing guidelines
|
||||
### Technical Improvements
|
||||
- Single, focused MCP server implementation
|
||||
- Clean separation of concerns
|
||||
- Better error handling
|
||||
- Improved logging
|
||||
- Async/await architecture throughout
|
||||
|
||||
## [1.0.1] - 2025-09-23
|
||||
## [0.5.0] - 2024-01-20
|
||||
|
||||
### Initial Release
|
||||
- **ADDED**: Complete Dolibarr API client with async/await
|
||||
- **ADDED**: MCP server implementation with 30+ tools
|
||||
- **ADDED**: Professional error handling and logging
|
||||
- **ADDED**: Docker support with production configuration
|
||||
- **ADDED**: Comprehensive test suite
|
||||
- **ADDED**: Configuration management with .env support
|
||||
### Added
|
||||
- Initial Dolibarr API integration
|
||||
- Basic CRUD operations for customers, products, invoices
|
||||
- MCP server implementation
|
||||
- Docker configuration
|
||||
|
||||
### Core Features
|
||||
- Full CRUD operations for all major Dolibarr modules
|
||||
- Async HTTP client with proper connection handling
|
||||
- Pydantic validation for type safety
|
||||
- Professional logging and error reporting
|
||||
- MCP 1.0 compliance for LLM integration
|
||||
## [0.1.0] - 2024-01-15
|
||||
|
||||
### Supported Dolibarr Modules
|
||||
- User Management
|
||||
- Customer/Third Party Management
|
||||
- Product Management
|
||||
- Invoice Management
|
||||
- Order Management
|
||||
- Contact Management
|
||||
- Raw API access for extensibility
|
||||
### Added
|
||||
- Initial project setup
|
||||
- Basic repository structure
|
||||
- License and documentation
|
||||
|
||||
---
|
||||
|
||||
## Installation Summary
|
||||
|
||||
### Windows Users (RECOMMENDED)
|
||||
```cmd
|
||||
.\setup_standalone.bat # Avoids pywin32 issues
|
||||
.\run_standalone.bat # Start server
|
||||
```
|
||||
|
||||
### Linux/macOS Users
|
||||
```bash
|
||||
./setup.sh
|
||||
python -m src.dolibarr_mcp
|
||||
```
|
||||
|
||||
### Docker Users
|
||||
```bash
|
||||
docker-compose up -d
|
||||
```
|
||||
|
||||
## Support
|
||||
|
||||
- 🐛 Issues: [GitHub Issues](https://github.com/latinogino/dolibarr-mcp/issues)
|
||||
- 💡 Discussions: [GitHub Discussions](https://github.com/latinogino/dolibarr-mcp/discussions)
|
||||
- 📖 Wiki: [Project Wiki](https://github.com/latinogino/dolibarr-mcp/wiki)
|
||||
**Note**: This changelog focuses on the major restructuring in v1.0.0 to align with prestashop-mcp's clean architecture.
|
||||
|
||||
96
CLEANUP_PLAN.md
Normal file
96
CLEANUP_PLAN.md
Normal file
@@ -0,0 +1,96 @@
|
||||
# Cleanup Plan for Dolibarr MCP
|
||||
|
||||
## Files to be REMOVED
|
||||
|
||||
### Test Scripts in Root Directory (to be removed)
|
||||
- `test_api_connection.py`
|
||||
- `test_api_debug.py`
|
||||
- `test_connection.py`
|
||||
- `test_dolibarr_mcp.py`
|
||||
- `test_install.py`
|
||||
- `test_standalone.py`
|
||||
- `test_ultra.py`
|
||||
- `test_ultra_direct.py`
|
||||
- `diagnose_and_fix.py`
|
||||
|
||||
### Batch Files (to be consolidated/removed)
|
||||
- `cleanup.bat`
|
||||
- `fix_installation.bat`
|
||||
- `run_dolibarr_mcp.bat`
|
||||
- `run_server.bat`
|
||||
- `run_standalone.bat`
|
||||
- `run_ultra.bat`
|
||||
- `setup.bat`
|
||||
- `setup_claude_complete.bat`
|
||||
- `setup_manual.bat`
|
||||
- `setup_standalone.bat`
|
||||
- `setup_ultra.bat`
|
||||
- `setup_windows_fix.bat`
|
||||
- `start_server.bat`
|
||||
- `validate_claude_config.bat`
|
||||
|
||||
### Python Scripts in Root (to be removed)
|
||||
- `mcp_server_launcher.py`
|
||||
- `setup_env.py`
|
||||
|
||||
### Alternative Server Implementations (to be removed from src/)
|
||||
- `src/dolibarr_mcp/simple_client.py`
|
||||
- `src/dolibarr_mcp/standalone_server.py`
|
||||
- `src/dolibarr_mcp/ultra_simple_server.py`
|
||||
|
||||
### Multiple Requirements Files (to be consolidated)
|
||||
- `requirements-minimal.txt`
|
||||
- `requirements-ultra-minimal.txt`
|
||||
- `requirements-windows.txt`
|
||||
(Keep only `requirements.txt`)
|
||||
|
||||
### Documentation Files (to be removed)
|
||||
- `README_DE.md`
|
||||
- `CLAUDE_CONFIG.md`
|
||||
- `CONFIG_COMPATIBILITY.md`
|
||||
- `MCP_FIX_GUIDE.md`
|
||||
- `ULTRA-SOLUTION.md`
|
||||
|
||||
### API Directory (to be removed)
|
||||
- `api/` directory and all its contents
|
||||
|
||||
## Files to KEEP (matching prestashop-mcp structure)
|
||||
|
||||
### Root Directory
|
||||
- `.env.example`
|
||||
- `.gitignore`
|
||||
- `LICENSE`
|
||||
- `README.md` (already updated)
|
||||
- `CHANGELOG.md`
|
||||
- `pyproject.toml`
|
||||
- `requirements.txt`
|
||||
- `Dockerfile`
|
||||
- `docker-compose.yml`
|
||||
- `setup.py`
|
||||
- `setup.sh`
|
||||
|
||||
### Source Directory
|
||||
- `src/dolibarr_mcp/__init__.py`
|
||||
- `src/dolibarr_mcp/__main__.py`
|
||||
- `src/dolibarr_mcp/cli.py`
|
||||
- `src/dolibarr_mcp/config.py`
|
||||
- `src/dolibarr_mcp/dolibarr_client.py`
|
||||
- `src/dolibarr_mcp/dolibarr_mcp_server.py`
|
||||
|
||||
### Tests Directory
|
||||
- `tests/__init__.py`
|
||||
- `tests/test_dolibarr_client.py`
|
||||
- Tests will be restructured to match prestashop-mcp pattern
|
||||
|
||||
## Next Steps
|
||||
|
||||
1. Remove all files listed above
|
||||
2. Update pyproject.toml to match prestashop-mcp structure
|
||||
3. Update requirements.txt to contain only necessary dependencies
|
||||
4. Create proper test structure in tests/ directory
|
||||
5. Update .gitignore to match prestashop-mcp
|
||||
6. Update CHANGELOG.md to document the restructuring
|
||||
|
||||
## Goal
|
||||
|
||||
Create a clean, maintainable structure that matches the prestashop-mcp reference implementation.
|
||||
493
README.md
493
README.md
@@ -1,208 +1,387 @@
|
||||
# 🔥 Dolibarr MCP Server - WINDOWS PROBLEM ENDGÜLTIG GELÖST!
|
||||
# Dolibarr MCP Server
|
||||
|
||||
Ein professioneller **Model Context Protocol (MCP) Server** für Dolibarr ERP-Integration mit **garantierter Windows-Kompatibilität**.
|
||||
A professional Model Context Protocol (MCP) Server for complete management of Dolibarr ERP/CRM systems.
|
||||
|
||||
## 💥 **ULTIMATIVE LÖSUNG für Windows pywin32 Probleme**
|
||||
## 🚀 Overview
|
||||
|
||||
**Problem**: `[WinError 5] Zugriff verweigert` bei allen Python-Paketen mit C-Extensions (.pyd Dateien)
|
||||
**Lösung**: **ULTRA-VERSION** mit NULL kompilierten Extensions!
|
||||
This MCP Server enables complete management of your Dolibarr ERP/CRM through AI applications like Claude Desktop. With specialized tools, you can manage all aspects of your business - from customers and products to invoices, orders, and contacts.
|
||||
|
||||
## 🚀 **SOFORTIGE LÖSUNG** (Garantiert auf JEDEM Windows-System)
|
||||
## ✨ Features
|
||||
|
||||
### ⚡ **ULTRA Setup** (100% Erfolgsgarantie)
|
||||
```cmd
|
||||
# 1. Repository klonen (falls noch nicht geschehen)
|
||||
- **💼 Complete ERP/CRM Management** - Tools for all business areas
|
||||
- **👥 Customer & Contact Management** - Full CRM functionality
|
||||
- **📦 Product & Service Management** - Complete inventory control
|
||||
- **💰 Financial Management** - Invoices, orders, and payments
|
||||
- **🏗️ MCP Protocol Compliance** for seamless AI integration
|
||||
- **⚡ Async/Await Architecture** for maximum performance
|
||||
- **🛡️ Comprehensive Error Handling** and validation
|
||||
- **🔧 Production-Ready** with complete test suite
|
||||
- **🐳 Docker Support** for easy deployment
|
||||
|
||||
## 🛠️ Available Tools
|
||||
|
||||
### 👥 Customer Management (Third Parties)
|
||||
- `get_customers` - Retrieve and filter customers
|
||||
- `get_customer_by_id` - Get specific customer details
|
||||
- `create_customer` - Create new customers
|
||||
- `update_customer` - Edit customer data
|
||||
- `delete_customer` - Remove customers
|
||||
|
||||
### 📦 Product Management
|
||||
- `get_products` - List all products
|
||||
- `get_product_by_id` - Get specific product details
|
||||
- `create_product` - Create new products/services
|
||||
- `update_product` - Edit product information
|
||||
- `delete_product` - Remove products
|
||||
|
||||
### 💰 Invoice Management
|
||||
- `get_invoices` - Retrieve and filter invoices
|
||||
- `get_invoice_by_id` - Get specific invoice details
|
||||
- `create_invoice` - Create new invoices
|
||||
- `update_invoice` - Edit invoice information
|
||||
- `delete_invoice` - Remove invoices
|
||||
|
||||
### 📋 Order Management
|
||||
- `get_orders` - Retrieve and filter orders
|
||||
- `get_order_by_id` - Get specific order details
|
||||
- `create_order` - Create new orders
|
||||
- `update_order` - Edit order information
|
||||
- `delete_order` - Remove orders
|
||||
|
||||
### 👤 Contact Management
|
||||
- `get_contacts` - List all contacts
|
||||
- `get_contact_by_id` - Get specific contact details
|
||||
- `create_contact` - Create new contacts
|
||||
- `update_contact` - Edit contact information
|
||||
- `delete_contact` - Remove contacts
|
||||
|
||||
### 👤 User Management
|
||||
- `get_users` - List system users
|
||||
- `get_user_by_id` - Get specific user details
|
||||
- `create_user` - Create new users
|
||||
- `update_user` - Edit user information
|
||||
- `delete_user` - Remove users
|
||||
|
||||
### ⚙️ System Administration
|
||||
- `test_connection` - Test API connection
|
||||
- `get_status` - System status and version
|
||||
- `dolibarr_raw_api` - Direct API access for advanced operations
|
||||
|
||||
## 📋 Installation
|
||||
|
||||
### ⚠️ Recommended Installation (Virtual Environment)
|
||||
|
||||
**This approach prevents module conflicts and ensures reliable installation:**
|
||||
|
||||
#### Windows:
|
||||
```powershell
|
||||
# Clone repository
|
||||
git clone https://github.com/latinogino/dolibarr-mcp.git
|
||||
cd dolibarr-mcp
|
||||
|
||||
# 2. ULTRA Setup (ZERO .pyd Dateien - funktioniert IMMER!)
|
||||
.\setup_ultra.bat
|
||||
# Create virtual environment
|
||||
python -m venv venv_dolibarr
|
||||
|
||||
# 3. Konfiguration
|
||||
copy .env.example .env
|
||||
# Bearbeiten Sie .env mit Ihren Dolibarr-Credentials
|
||||
# Activate virtual environment
|
||||
.\venv_dolibarr\Scripts\Activate.ps1
|
||||
|
||||
# 4. Server starten
|
||||
.\run_ultra.bat
|
||||
# Install dependencies
|
||||
pip install -r requirements.txt
|
||||
|
||||
# Install package in development mode
|
||||
pip install -e .
|
||||
|
||||
# Verify installation
|
||||
python -c "import dolibarr_mcp; print('✅ Installation successful')"
|
||||
|
||||
# Note the Python path for Claude Desktop configuration
|
||||
Write-Host "Python Path: $((Get-Command python).Source)"
|
||||
```
|
||||
|
||||
**🎯 Warum funktioniert ULTRA garantiert?**
|
||||
- ❌ **Normale Version**: aiohttp, pydantic → .pyd Dateien → Windows-Berechtigungsprobleme
|
||||
- ✅ **ULTRA Version**: Nur `requests` + Standard Library → ZERO .pyd Dateien → Funktioniert IMMER
|
||||
#### Linux/macOS:
|
||||
```bash
|
||||
# Clone repository
|
||||
git clone https://github.com/latinogino/dolibarr-mcp.git
|
||||
cd dolibarr-mcp
|
||||
|
||||
## 🛠️ **Drei Setup-Optionen** (vom einfachsten zum komplexesten)
|
||||
# Create virtual environment
|
||||
python3 -m venv venv_dolibarr
|
||||
|
||||
| Setup-Methode | Windows-Kompatibilität | Funktionsumfang | Empfehlung |
|
||||
|---------------|------------------------|-----------------|------------|
|
||||
| **🔥 ULTRA** | 100% (keine .pyd) | Alle CRUD Tools | ⭐⭐⭐ EMPFOHLEN |
|
||||
| **Standalone** | 95% (wenige .pyd) | Alle CRUD Tools | ⭐⭐ Fallback |
|
||||
| **Standard MCP** | 50% (viele .pyd) | Alle CRUD Tools | ⭐ Nur für Experten |
|
||||
# Activate virtual environment
|
||||
source venv_dolibarr/bin/activate
|
||||
|
||||
### Option 1: 🔥 ULTRA (Garantierter Erfolg)
|
||||
```cmd
|
||||
.\setup_ultra.bat # Nur requests, dotenv, click - ZERO .pyd!
|
||||
.\run_ultra.bat # Startet ultra-kompatiblen Server
|
||||
# Install dependencies
|
||||
pip install -r requirements.txt
|
||||
|
||||
# Install package in development mode
|
||||
pip install -e .
|
||||
|
||||
# Verify installation
|
||||
python -c "import dolibarr_mcp; print('✅ Installation successful')"
|
||||
|
||||
# Note the Python path for Claude Desktop configuration
|
||||
which python
|
||||
```
|
||||
|
||||
### Option 2: Standalone (Falls ULTRA nicht gewünscht)
|
||||
```cmd
|
||||
.\setup_standalone.bat # Weniger .pyd Dateien
|
||||
.\run_standalone.bat # Startet standalone Server
|
||||
### 🐳 Docker Installation
|
||||
|
||||
```bash
|
||||
# Using Docker Compose (recommended)
|
||||
docker-compose up -d
|
||||
|
||||
# Or using Docker directly
|
||||
docker build -t dolibarr-mcp .
|
||||
docker run -d \
|
||||
-e DOLIBARR_URL=https://your-dolibarr.com \
|
||||
-e DOLIBARR_API_KEY=your_api_key \
|
||||
-p 8080:8080 \
|
||||
dolibarr-mcp
|
||||
```
|
||||
|
||||
### Option 3: Standard MCP (Nur für Experten)
|
||||
```cmd
|
||||
.\setup.bat # Vollständiges MCP-Paket
|
||||
.\start_server.bat # Standard MCP Server
|
||||
```
|
||||
### ⚙️ Configuration
|
||||
|
||||
## ✨ **Vollständige Feature-Matrix**
|
||||
Create a `.env` file based on `.env.example`:
|
||||
|
||||
| Feature | ULTRA | Standalone | Standard | Status |
|
||||
|---------|-------|------------|----------|--------|
|
||||
| **Windows-Kompatibilität** | 100% | 95% | 50% | ✅ |
|
||||
| **User Management** | ✅ | ✅ | ✅ | Identisch |
|
||||
| **Customer Management** | ✅ | ✅ | ✅ | Identisch |
|
||||
| **Product Management** | ✅ | ✅ | ✅ | Identisch |
|
||||
| **Invoice Management** | ✅ | ✅ | ✅ | Identisch |
|
||||
| **Order Management** | ✅ | ✅ | ✅ | Identisch |
|
||||
| **Contact Management** | ✅ | ✅ | ✅ | Identisch |
|
||||
| **Raw API Access** | ✅ | ✅ | ✅ | Identisch |
|
||||
| **Interactive Testing** | ✅ | ✅ | ❌ | ULTRA ist besser! |
|
||||
| **Error Handling** | ✅ | ✅ | ✅ | Identisch |
|
||||
```bash
|
||||
# Dolibarr Configuration
|
||||
DOLIBARR_URL=https://your-dolibarr.example.com
|
||||
DOLIBARR_API_KEY=YOUR_API_KEY
|
||||
|
||||
## 🔧 **Dolibarr Konfiguration**
|
||||
|
||||
### 1. **Dolibarr API aktivieren**
|
||||
1. **Dolibarr Admin** → Login
|
||||
2. **Home → Setup → Modules** → "Web Services API REST (developer)" ✅ aktivieren
|
||||
3. **Home → Setup → API/Web services** → Neuen API Key erstellen
|
||||
|
||||
### 2. **Konfiguration (.env)**
|
||||
```env
|
||||
DOLIBARR_URL=https://ihre-dolibarr-instanz.com/api/index.php
|
||||
DOLIBARR_API_KEY=ihr_generierter_api_schluessel
|
||||
# Logging
|
||||
LOG_LEVEL=INFO
|
||||
```
|
||||
|
||||
## 🧪 **Server testen & verwenden**
|
||||
## 🎯 Usage
|
||||
|
||||
### ULTRA Server (Empfohlen)
|
||||
```cmd
|
||||
# Nach setup_ultra.bat:
|
||||
.\run_ultra.bat
|
||||
### 🤖 With Claude Desktop
|
||||
|
||||
# Interactive Console öffnet sich automatisch:
|
||||
dolibarr-ultra> help
|
||||
dolibarr-ultra> test test_connection
|
||||
dolibarr-ultra> test get_status
|
||||
dolibarr-ultra> test get_users
|
||||
dolibarr-ultra> config
|
||||
dolibarr-ultra> list
|
||||
dolibarr-ultra> exit
|
||||
#### Using Virtual Environment (Recommended)
|
||||
|
||||
Add this configuration to `claude_desktop_config.json`:
|
||||
|
||||
**Windows:**
|
||||
```json
|
||||
{
|
||||
"mcpServers": {
|
||||
"dolibarr": {
|
||||
"command": "C:\\\\path\\\\to\\\\dolibarr-mcp\\\\venv_dolibarr\\\\Scripts\\\\python.exe",
|
||||
"args": ["-m", "dolibarr_mcp.dolibarr_mcp_server"],
|
||||
"cwd": "C:\\\\path\\\\to\\\\dolibarr-mcp",
|
||||
"env": {
|
||||
"DOLIBARR_URL": "https://your-dolibarr.example.com",
|
||||
"DOLIBARR_API_KEY": "YOUR_API_KEY"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### Verfügbare Schnelltests
|
||||
```
|
||||
test test_connection # API-Verbindung testen
|
||||
test get_status # Dolibarr-Status abrufen
|
||||
test get_users # Erste 5 Benutzer anzeigen
|
||||
test get_customers # Erste 5 Kunden anzeigen
|
||||
test get_products # Erste 5 Produkte anzeigen
|
||||
config # Aktuelle Konfiguration zeigen
|
||||
help # Alle Befehle anzeigen
|
||||
**Linux/macOS:**
|
||||
```json
|
||||
{
|
||||
"mcpServers": {
|
||||
"dolibarr": {
|
||||
"command": "/path/to/dolibarr-mcp/venv_dolibarr/bin/python",
|
||||
"args": ["-m", "dolibarr_mcp.dolibarr_mcp_server"],
|
||||
"cwd": "/path/to/dolibarr-mcp",
|
||||
"env": {
|
||||
"DOLIBARR_URL": "https://your-dolibarr.example.com",
|
||||
"DOLIBARR_API_KEY": "YOUR_API_KEY"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
## 📋 **Alle verfügbaren CRUD-Operationen**
|
||||
|
||||
### 👥 **User Management**
|
||||
- `get_users`, `get_user_by_id`, `create_user`, `update_user`, `delete_user`
|
||||
|
||||
### 🏢 **Customer Management**
|
||||
- `get_customers`, `get_customer_by_id`, `create_customer`, `update_customer`, `delete_customer`
|
||||
|
||||
### 📦 **Product Management**
|
||||
- `get_products`, `get_product_by_id`, `create_product`, `update_product`, `delete_product`
|
||||
|
||||
### 🧾 **Invoice Management**
|
||||
- `get_invoices`, `get_invoice_by_id`, `create_invoice`, `update_invoice`, `delete_invoice`
|
||||
|
||||
### 📋 **Order Management**
|
||||
- `get_orders`, `get_order_by_id`, `create_order`, `update_order`, `delete_order`
|
||||
|
||||
### 📞 **Contact Management**
|
||||
- `get_contacts`, `get_contact_by_id`, `create_contact`, `update_contact`, `delete_contact`
|
||||
|
||||
### 🔌 **Advanced**
|
||||
- `raw_api` - Direkter Zugriff auf beliebige Dolibarr-Endpunkte
|
||||
|
||||
## 🐳 **Docker Support** (Weiterhin verfügbar)
|
||||
### 💻 CLI Usage
|
||||
|
||||
```bash
|
||||
# Standard Docker
|
||||
docker-compose up -d
|
||||
# Activate virtual environment first (if using venv)
|
||||
source venv_dolibarr/bin/activate # Linux/macOS
|
||||
.\venv_dolibarr\Scripts\Activate.ps1 # Windows
|
||||
|
||||
# Mit .env Konfiguration
|
||||
cp .env.example .env
|
||||
# .env bearbeiten, dann:
|
||||
docker-compose up -d dolibarr-mcp
|
||||
# With environment variables
|
||||
dolibarr-mcp
|
||||
|
||||
# With direct parameters
|
||||
dolibarr-mcp --url https://your-dolibarr.com --api-key YOUR_API_KEY
|
||||
|
||||
# Debug mode
|
||||
dolibarr-mcp --log-level DEBUG
|
||||
```
|
||||
|
||||
## 🔧 **Troubleshooting**
|
||||
## 💡 Example Usage
|
||||
|
||||
### ✅ **ULTRA Version löst ALLE Windows-Probleme**
|
||||
|
||||
**Vorher** (Probleme):
|
||||
### Customer Management
|
||||
```
|
||||
ERROR: [WinError 5] Zugriff verweigert: ...pywintypes313.dll
|
||||
ERROR: [WinError 5] Zugriff verweigert: ..._http_parser.cp313-win_amd64.pyd
|
||||
ERROR: [WinError 5] Zugriff verweigert: ..._pydantic_core.cp313-win_amd64.pyd
|
||||
"Show me all customers in Dolibarr"
|
||||
"Create a new customer named 'Acme Corp' with email info@acme.com"
|
||||
"Update customer ID 5 with new phone number +1234567890"
|
||||
"Find customers in France"
|
||||
```
|
||||
|
||||
**Nachher** (ULTRA - Keine Probleme):
|
||||
### Product Management
|
||||
```
|
||||
✅ requests installed
|
||||
✅ python-dotenv installed
|
||||
✅ click installed
|
||||
🎉 ULTRA SETUP COMPLETE!
|
||||
"List all products with stock levels"
|
||||
"Create a new product 'Consulting Service' with price $150"
|
||||
"Update product ID 10 to set new price $200"
|
||||
"Show me products with low stock"
|
||||
```
|
||||
|
||||
### **API-Verbindungsprobleme**
|
||||
|
||||
| Problem | Lösung |
|
||||
|---------|---------|
|
||||
| "Cannot connect to Dolibarr API" | URL und API Key in .env prüfen |
|
||||
| "403 Forbidden" | Neuen API Key in Dolibarr erstellen |
|
||||
| "Module not found" | `setup_ultra.bat` erneut ausführen |
|
||||
|
||||
### **Test-Commands**
|
||||
```cmd
|
||||
# Setup testen
|
||||
python test_ultra.py
|
||||
|
||||
# Server direkt testen
|
||||
python -m src.dolibarr_mcp.ultra_simple_server
|
||||
### Invoice Management
|
||||
```
|
||||
"Show all unpaid invoices"
|
||||
"Create an invoice for customer 'Acme Corp'"
|
||||
"Get invoice details for invoice ID 100"
|
||||
"Update invoice due date to next month"
|
||||
```
|
||||
|
||||
## 🎯 **Status: Production-Ready für ALLE Windows-Versionen**
|
||||
### Contact Management
|
||||
```
|
||||
"List all contacts for customer ID 5"
|
||||
"Create a new contact John Doe for Acme Corp"
|
||||
"Update contact email for John Doe"
|
||||
"Find all contacts with role 'Manager'"
|
||||
```
|
||||
|
||||
✅ **Problem gelöst**: Null .pyd Dateien = Null Windows-Probleme
|
||||
✅ **Funktional**: Alle CRUD-Operationen verfügbar
|
||||
✅ **Getestet**: Interactive Test-Console eingebaut
|
||||
✅ **Kompatibel**: Windows XP bis Windows 11
|
||||
✅ **Performance**: Requests-basiert, sehr schnell
|
||||
✅ **Wartbar**: Saubere, einfache Code-Architektur
|
||||
## 🔧 Troubleshooting
|
||||
|
||||
## 📄 **License & Support**
|
||||
### ❌ Common Issues
|
||||
|
||||
- **License**: MIT License - siehe [LICENSE](LICENSE)
|
||||
- **Issues**: [GitHub Issues](https://github.com/latinogino/dolibarr-mcp/issues)
|
||||
- **Discussions**: [GitHub Discussions](https://github.com/latinogino/dolibarr-mcp/discussions)
|
||||
#### "ModuleNotFoundError: No module named 'dolibarr_mcp'"
|
||||
|
||||
**Solution:** Use virtual environment and ensure package is installed:
|
||||
```bash
|
||||
# Check if in virtual environment
|
||||
python -c "import sys; print(sys.prefix)"
|
||||
|
||||
# Reinstall package
|
||||
pip install -e .
|
||||
|
||||
# Verify installation
|
||||
python -c "import dolibarr_mcp; print('Module found')"
|
||||
```
|
||||
|
||||
#### API Connection Issues
|
||||
|
||||
**Check API Configuration:**
|
||||
```bash
|
||||
# Test connection with curl
|
||||
curl -X GET "https://your-dolibarr.com/api/index.php/status" \
|
||||
-H "DOLAPIKEY: YOUR_API_KEY"
|
||||
```
|
||||
|
||||
#### Permission Errors
|
||||
|
||||
Ensure your API key has necessary permissions in Dolibarr:
|
||||
1. Go to Dolibarr Admin → API/Web Services
|
||||
2. Check API key permissions
|
||||
3. Enable required modules (API REST module)
|
||||
|
||||
### 🔍 Debug Mode
|
||||
|
||||
Enable debug logging in Claude Desktop configuration:
|
||||
```json
|
||||
{
|
||||
"mcpServers": {
|
||||
"dolibarr": {
|
||||
"command": "path/to/python",
|
||||
"args": ["-m", "dolibarr_mcp.dolibarr_mcp_server"],
|
||||
"cwd": "path/to/dolibarr-mcp",
|
||||
"env": {
|
||||
"DOLIBARR_URL": "https://your-dolibarr.example.com",
|
||||
"DOLIBARR_API_KEY": "YOUR_API_KEY",
|
||||
"LOG_LEVEL": "DEBUG"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
## 📊 Project Structure
|
||||
|
||||
```
|
||||
dolibarr-mcp/
|
||||
├── src/dolibarr_mcp/ # Main Package
|
||||
│ ├── dolibarr_mcp_server.py # MCP Server
|
||||
│ ├── dolibarr_client.py # Dolibarr API Client
|
||||
│ ├── config.py # Configuration Management
|
||||
│ └── cli.py # Command Line Interface
|
||||
├── tests/ # Test Suite
|
||||
│ ├── test_config.py # Unit Tests
|
||||
│ └── test_dolibarr_client.py # Integration Tests
|
||||
├── docker/ # Docker Configuration
|
||||
│ ├── Dockerfile # Container Definition
|
||||
│ └── docker-compose.yml # Compose Configuration
|
||||
├── venv_dolibarr/ # Virtual Environment (after setup)
|
||||
├── README.md # Documentation
|
||||
├── CHANGELOG.md # Version History
|
||||
├── pyproject.toml # Package Configuration
|
||||
└── requirements.txt # Dependencies
|
||||
```
|
||||
|
||||
## 📖 API Documentation
|
||||
|
||||
### Dolibarr API
|
||||
|
||||
Complete Dolibarr API documentation:
|
||||
- **[Dolibarr REST API Wiki](https://wiki.dolibarr.org/index.php?title=Module_Web_Services_API_REST_(developer))**
|
||||
- **[Dolibarr Integration Guide](https://wiki.dolibarr.org/index.php?title=Interfaces_Dolibarr_toward_foreign_systems)**
|
||||
|
||||
### Authentication
|
||||
|
||||
```bash
|
||||
curl -X GET "https://your-dolibarr.com/api/index.php/status" \
|
||||
-H "DOLAPIKEY: YOUR_API_KEY"
|
||||
```
|
||||
|
||||
### Important Endpoints
|
||||
|
||||
- **Third Parties**: `/api/index.php/thirdparties`
|
||||
- **Products**: `/api/index.php/products`
|
||||
- **Invoices**: `/api/index.php/invoices`
|
||||
- **Orders**: `/api/index.php/orders`
|
||||
- **Contacts**: `/api/index.php/contacts`
|
||||
- **Users**: `/api/index.php/users`
|
||||
- **Status**: `/api/index.php/status`
|
||||
|
||||
## 🧪 Development
|
||||
|
||||
### 🏗️ Development Environment
|
||||
|
||||
```bash
|
||||
# Activate virtual environment
|
||||
source venv_dolibarr/bin/activate # Linux/macOS
|
||||
.\venv_dolibarr\Scripts\Activate.ps1 # Windows
|
||||
|
||||
# Install development dependencies
|
||||
pip install -r requirements.txt
|
||||
|
||||
# Run tests
|
||||
pytest
|
||||
|
||||
# Run tests with coverage
|
||||
pytest --cov=src/dolibarr_mcp --cov-report=html
|
||||
|
||||
# Run integration tests
|
||||
python tests/test_dolibarr_client.py
|
||||
```
|
||||
|
||||
## 📖 Resources
|
||||
|
||||
- **[Dolibarr Official Documentation](https://www.dolibarr.org/documentation-home)**
|
||||
- **[Model Context Protocol Specification](https://modelcontextprotocol.io/)**
|
||||
- **[Claude Desktop MCP Integration](https://docs.anthropic.com/)**
|
||||
- **[GitHub Repository](https://github.com/latinogino/dolibarr-mcp)**
|
||||
|
||||
## 📄 License
|
||||
|
||||
MIT License - see [LICENSE](LICENSE) for details.
|
||||
|
||||
## 📝 Changelog
|
||||
|
||||
See [CHANGELOG.md](CHANGELOG.md) for a detailed history of changes.
|
||||
|
||||
---
|
||||
|
||||
## 🎉 **ERFOLGREICH? Ihr Dolibarr ERP ist jetzt AI-ready!**
|
||||
|
||||
**🔥 ULTRA Version = Garantierte Windows-Kompatibilität + Vollständige Dolibarr-Integration**
|
||||
|
||||
**🚀 Bereit, Ihr Dolibarr ERP mit Claude, ChatGPT und anderen LLMs zu nutzen!**
|
||||
**🎯 Manage your complete Dolibarr ERP/CRM through natural language with Claude Desktop!**
|
||||
|
||||
131
cleanup_repo.py
Normal file
131
cleanup_repo.py
Normal file
@@ -0,0 +1,131 @@
|
||||
#!/usr/bin/env python3
|
||||
"""
|
||||
Cleanup script to remove unnecessary files from dolibarr-mcp repository.
|
||||
This script should be run locally after checking out the cleanup-restructure-v2 branch.
|
||||
"""
|
||||
|
||||
import os
|
||||
import shutil
|
||||
from pathlib import Path
|
||||
|
||||
# List of files to remove
|
||||
FILES_TO_REMOVE = [
|
||||
# Test scripts in root directory
|
||||
"test_api_connection.py",
|
||||
"test_api_debug.py",
|
||||
"test_connection.py",
|
||||
"test_dolibarr_mcp.py",
|
||||
"test_install.py",
|
||||
"test_standalone.py",
|
||||
"test_ultra.py",
|
||||
"test_ultra_direct.py",
|
||||
"diagnose_and_fix.py",
|
||||
|
||||
# Batch files
|
||||
"cleanup.bat",
|
||||
"fix_installation.bat",
|
||||
"run_dolibarr_mcp.bat",
|
||||
"run_server.bat",
|
||||
"run_standalone.bat",
|
||||
"run_ultra.bat",
|
||||
"setup.bat",
|
||||
"setup_claude_complete.bat",
|
||||
"setup_manual.bat",
|
||||
"setup_standalone.bat",
|
||||
"setup_ultra.bat",
|
||||
"setup_windows_fix.bat",
|
||||
"start_server.bat",
|
||||
"validate_claude_config.bat",
|
||||
|
||||
# Python scripts in root
|
||||
"mcp_server_launcher.py",
|
||||
"setup_env.py",
|
||||
|
||||
# Alternative server implementations
|
||||
"src/dolibarr_mcp/simple_client.py",
|
||||
"src/dolibarr_mcp/standalone_server.py",
|
||||
"src/dolibarr_mcp/ultra_simple_server.py",
|
||||
|
||||
# Multiple requirements files
|
||||
"requirements-minimal.txt",
|
||||
"requirements-ultra-minimal.txt",
|
||||
"requirements-windows.txt",
|
||||
|
||||
# Documentation files
|
||||
"README_DE.md",
|
||||
"CLAUDE_CONFIG.md",
|
||||
"CONFIG_COMPATIBILITY.md",
|
||||
"MCP_FIX_GUIDE.md",
|
||||
"ULTRA-SOLUTION.md",
|
||||
]
|
||||
|
||||
# Directories to remove
|
||||
DIRS_TO_REMOVE = [
|
||||
"api",
|
||||
]
|
||||
|
||||
def cleanup():
|
||||
"""Remove unnecessary files and directories."""
|
||||
removed_files = []
|
||||
removed_dirs = []
|
||||
errors = []
|
||||
|
||||
# Get repository root
|
||||
repo_root = Path(__file__).parent
|
||||
|
||||
# Remove files
|
||||
for file_path in FILES_TO_REMOVE:
|
||||
full_path = repo_root / file_path
|
||||
if full_path.exists():
|
||||
try:
|
||||
full_path.unlink()
|
||||
removed_files.append(file_path)
|
||||
print(f"✅ Removed: {file_path}")
|
||||
except Exception as e:
|
||||
errors.append(f"Failed to remove {file_path}: {e}")
|
||||
print(f"❌ Failed: {file_path} - {e}")
|
||||
else:
|
||||
print(f"⚠️ Not found: {file_path}")
|
||||
|
||||
# Remove directories
|
||||
for dir_path in DIRS_TO_REMOVE:
|
||||
full_path = repo_root / dir_path
|
||||
if full_path.exists():
|
||||
try:
|
||||
shutil.rmtree(full_path)
|
||||
removed_dirs.append(dir_path)
|
||||
print(f"✅ Removed directory: {dir_path}")
|
||||
except Exception as e:
|
||||
errors.append(f"Failed to remove {dir_path}: {e}")
|
||||
print(f"❌ Failed: {dir_path} - {e}")
|
||||
else:
|
||||
print(f"⚠️ Directory not found: {dir_path}")
|
||||
|
||||
# Summary
|
||||
print("\n" + "="*50)
|
||||
print("CLEANUP SUMMARY")
|
||||
print("="*50)
|
||||
print(f"Files removed: {len(removed_files)}")
|
||||
print(f"Directories removed: {len(removed_dirs)}")
|
||||
print(f"Errors: {len(errors)}")
|
||||
|
||||
if errors:
|
||||
print("\n❌ Errors encountered:")
|
||||
for error in errors:
|
||||
print(f" - {error}")
|
||||
|
||||
print("\n✅ Cleanup complete!")
|
||||
print("Don't forget to commit these changes:")
|
||||
print(" git add -A")
|
||||
print(" git commit -m 'Remove unnecessary files and clean up structure'")
|
||||
print(" git push origin cleanup-restructure-v2")
|
||||
|
||||
if __name__ == "__main__":
|
||||
print("🧹 Starting cleanup of dolibarr-mcp repository...")
|
||||
print("This will remove unnecessary files to match prestashop-mcp structure.\n")
|
||||
|
||||
response = input("Are you sure you want to proceed? (yes/no): ")
|
||||
if response.lower() in ['yes', 'y']:
|
||||
cleanup()
|
||||
else:
|
||||
print("Cleanup cancelled.")
|
||||
@@ -4,20 +4,20 @@ build-backend = "setuptools.build_meta"
|
||||
|
||||
[project]
|
||||
name = "dolibarr-mcp"
|
||||
version = "1.0.1"
|
||||
description = "Professional Model Context Protocol server for complete Dolibarr ERP management with comprehensive CRUD operations and business intelligence"
|
||||
version = "1.0.0"
|
||||
description = "Professional Model Context Protocol server for complete Dolibarr ERP/CRM management"
|
||||
readme = "README.md"
|
||||
requires-python = ">=3.8"
|
||||
authors = [
|
||||
{name = "Dolibarr MCP Team"}
|
||||
]
|
||||
keywords = [
|
||||
"dolibarr", "mcp", "model-context-protocol", "erp", "api",
|
||||
"business-management", "crm", "accounting", "automation", "unified-api",
|
||||
"customer-management", "invoice-management", "product-management", "order-management"
|
||||
"dolibarr", "mcp", "model-context-protocol", "erp", "crm", "api",
|
||||
"business-management", "automation", "unified-api",
|
||||
"invoice-management", "customer-management", "product-management"
|
||||
]
|
||||
classifiers = [
|
||||
"Development Status :: 5 - Production/Stable",
|
||||
"Development Status :: 4 - Beta",
|
||||
"Intended Audience :: Developers",
|
||||
"Intended Audience :: System Administrators",
|
||||
"License :: OSI Approved :: MIT License",
|
||||
@@ -29,11 +29,11 @@ classifiers = [
|
||||
"Programming Language :: Python :: 3.11",
|
||||
"Topic :: Software Development :: Libraries :: Python Modules",
|
||||
"Topic :: Internet :: WWW/HTTP :: Dynamic Content",
|
||||
"Topic :: Office/Business :: Financial :: Accounting",
|
||||
"Topic :: Office/Business",
|
||||
"Topic :: System :: Systems Administration",
|
||||
]
|
||||
dependencies = [
|
||||
"mcp>=0.9.0",
|
||||
"mcp>=1.0.0",
|
||||
"requests>=2.31.0",
|
||||
"aiohttp>=3.9.0",
|
||||
"pydantic>=2.5.0",
|
||||
|
||||
@@ -1,12 +1,22 @@
|
||||
# Core dependencies
|
||||
# Core MCP dependencies
|
||||
mcp>=1.0.0
|
||||
|
||||
# HTTP and async support
|
||||
requests>=2.31.0
|
||||
aiohttp>=3.9.0
|
||||
|
||||
# Data validation and settings
|
||||
pydantic>=2.5.0
|
||||
pydantic-settings>=2.0.0
|
||||
python-dotenv>=1.0.0
|
||||
|
||||
# MCP framework
|
||||
mcp>=0.9.0
|
||||
|
||||
# Additional dependencies
|
||||
aiohttp>=3.9.0
|
||||
pydantic>=2.5.0
|
||||
# CLI support
|
||||
click>=8.1.0
|
||||
|
||||
# Type hints
|
||||
typing-extensions>=4.8.0
|
||||
|
||||
# Development and testing
|
||||
pytest>=7.4.0
|
||||
pytest-asyncio>=0.21.0
|
||||
pytest-cov>=4.1.0
|
||||
|
||||
@@ -1,26 +1,19 @@
|
||||
"""Dolibarr MCP - Model Context Protocol Server for Dolibarr ERP."""
|
||||
"""
|
||||
Dolibarr MCP Server Package
|
||||
|
||||
__version__ = "1.0.1"
|
||||
Professional Model Context Protocol server for complete Dolibarr ERP/CRM management.
|
||||
"""
|
||||
|
||||
__version__ = "1.0.0"
|
||||
__author__ = "Dolibarr MCP Team"
|
||||
|
||||
# Make the main function available at package level
|
||||
try:
|
||||
from .dolibarr_mcp_server import main
|
||||
except ImportError:
|
||||
# If relative import fails, we might be running directly
|
||||
import sys
|
||||
import os
|
||||
# Add parent directory to path
|
||||
sys.path.insert(0, os.path.dirname(os.path.dirname(os.path.abspath(__file__))))
|
||||
from dolibarr_mcp.dolibarr_mcp_server import main
|
||||
from .dolibarr_client import DolibarrClient
|
||||
from .config import Config
|
||||
|
||||
# Note: dolibarr_mcp_server uses a functional pattern, not a class
|
||||
# The server is run via the main() function in dolibarr_mcp_server.py
|
||||
|
||||
# Export main components
|
||||
__all__ = [
|
||||
'main',
|
||||
'__version__',
|
||||
'__author__'
|
||||
"DolibarrClient",
|
||||
"Config",
|
||||
]
|
||||
|
||||
# Support both execution methods
|
||||
if __name__ == '__main__':
|
||||
main()
|
||||
|
||||
@@ -4,38 +4,42 @@ import os
|
||||
import sys
|
||||
from typing import Optional
|
||||
|
||||
from pydantic import BaseModel, Field, validator
|
||||
from pydantic import Field, field_validator
|
||||
from pydantic_settings import BaseSettings
|
||||
from dotenv import load_dotenv
|
||||
|
||||
# Load environment variables from .env file
|
||||
load_dotenv()
|
||||
|
||||
|
||||
class Config(BaseModel):
|
||||
class Config(BaseSettings):
|
||||
"""Configuration for Dolibarr MCP Server."""
|
||||
|
||||
dolibarr_url: str = Field(
|
||||
description="Dolibarr API URL",
|
||||
default_factory=lambda: os.getenv("DOLIBARR_URL") or os.getenv("DOLIBARR_BASE_URL", "")
|
||||
default=""
|
||||
)
|
||||
|
||||
api_key: str = Field(
|
||||
dolibarr_api_key: str = Field(
|
||||
description="Dolibarr API key",
|
||||
default_factory=lambda: os.getenv("DOLIBARR_API_KEY", "")
|
||||
default=""
|
||||
)
|
||||
|
||||
log_level: str = Field(
|
||||
description="Logging level",
|
||||
default_factory=lambda: os.getenv("LOG_LEVEL", "INFO")
|
||||
default="INFO"
|
||||
)
|
||||
|
||||
@validator('dolibarr_url')
|
||||
def validate_dolibarr_url(cls, v):
|
||||
@field_validator('dolibarr_url')
|
||||
@classmethod
|
||||
def validate_dolibarr_url(cls, v: str) -> str:
|
||||
"""Validate Dolibarr URL."""
|
||||
if not v:
|
||||
# Print warning but don't fail
|
||||
print("⚠️ DOLIBARR_URL/DOLIBARR_BASE_URL not configured - API calls will fail", file=sys.stderr)
|
||||
return "https://your-dolibarr-instance.com/api/index.php"
|
||||
v = os.getenv("DOLIBARR_URL") or os.getenv("DOLIBARR_BASE_URL", "")
|
||||
if not v:
|
||||
# Print warning but don't fail
|
||||
print("⚠️ DOLIBARR_URL/DOLIBARR_BASE_URL not configured - API calls will fail", file=sys.stderr)
|
||||
return "https://your-dolibarr-instance.com/api/index.php"
|
||||
|
||||
if not v.startswith(('http://', 'https://')):
|
||||
raise ValueError("DOLIBARR_URL must start with http:// or https://")
|
||||
@@ -60,38 +64,50 @@ class Config(BaseModel):
|
||||
|
||||
return v
|
||||
|
||||
@validator('api_key')
|
||||
def validate_api_key(cls, v):
|
||||
@field_validator('dolibarr_api_key')
|
||||
@classmethod
|
||||
def validate_api_key(cls, v: str) -> str:
|
||||
"""Validate API key."""
|
||||
if not v:
|
||||
# Print warning but don't fail
|
||||
print("⚠️ DOLIBARR_API_KEY not configured - API authentication will fail", file=sys.stderr)
|
||||
print("📝 Please set DOLIBARR_API_KEY in your .env file or Claude configuration", file=sys.stderr)
|
||||
return "placeholder_api_key"
|
||||
v = os.getenv("DOLIBARR_API_KEY", "")
|
||||
if not v:
|
||||
# Print warning but don't fail
|
||||
print("⚠️ DOLIBARR_API_KEY not configured - API authentication will fail", file=sys.stderr)
|
||||
print("📝 Please set DOLIBARR_API_KEY in your .env file or Claude configuration", file=sys.stderr)
|
||||
return "placeholder_api_key"
|
||||
|
||||
if v == "your_dolibarr_api_key_here":
|
||||
print("⚠️ Using placeholder API key - please configure a real API key", file=sys.stderr)
|
||||
|
||||
return v
|
||||
|
||||
@validator('log_level')
|
||||
def validate_log_level(cls, v):
|
||||
@field_validator('log_level')
|
||||
@classmethod
|
||||
def validate_log_level(cls, v: str) -> str:
|
||||
"""Validate log level."""
|
||||
if not v:
|
||||
v = os.getenv("LOG_LEVEL", "INFO")
|
||||
|
||||
valid_levels = {'DEBUG', 'INFO', 'WARNING', 'ERROR', 'CRITICAL'}
|
||||
if v.upper() not in valid_levels:
|
||||
raise ValueError(f"LOG_LEVEL must be one of: {', '.join(valid_levels)}")
|
||||
print(f"⚠️ Invalid LOG_LEVEL '{v}', using INFO", file=sys.stderr)
|
||||
return 'INFO'
|
||||
return v.upper()
|
||||
|
||||
@classmethod
|
||||
def from_env(cls) -> "Config":
|
||||
"""Create configuration from environment variables with validation."""
|
||||
try:
|
||||
config = cls()
|
||||
config = cls(
|
||||
dolibarr_url=os.getenv("DOLIBARR_URL") or os.getenv("DOLIBARR_BASE_URL", ""),
|
||||
dolibarr_api_key=os.getenv("DOLIBARR_API_KEY", ""),
|
||||
log_level=os.getenv("LOG_LEVEL", "INFO")
|
||||
)
|
||||
# Debug output for troubleshooting
|
||||
if os.getenv("DEBUG_CONFIG"):
|
||||
print(f"✅ Config loaded:", file=sys.stderr)
|
||||
print(f" URL: {config.dolibarr_url}", file=sys.stderr)
|
||||
print(f" API Key: {'*' * 10 if config.api_key else 'NOT SET'}", file=sys.stderr)
|
||||
print(f" API Key: {'*' * 10 if config.dolibarr_api_key else 'NOT SET'}", file=sys.stderr)
|
||||
return config
|
||||
except Exception as e:
|
||||
print(f"❌ Configuration Error: {e}", file=sys.stderr)
|
||||
@@ -112,7 +128,29 @@ class Config(BaseModel):
|
||||
print(file=sys.stderr)
|
||||
raise
|
||||
|
||||
class Settings:
|
||||
"""Pydantic settings configuration."""
|
||||
# Alias for backward compatibility
|
||||
@property
|
||||
def api_key(self) -> str:
|
||||
"""Backward compatibility for api_key property."""
|
||||
return self.dolibarr_api_key
|
||||
|
||||
class Config:
|
||||
"""Pydantic configuration."""
|
||||
env_file = '.env'
|
||||
env_file_encoding = 'utf-8'
|
||||
case_sensitive = False
|
||||
# Load from environment
|
||||
env_prefix = ""
|
||||
|
||||
@classmethod
|
||||
def customise_sources(
|
||||
cls,
|
||||
init_settings,
|
||||
env_settings,
|
||||
file_secret_settings
|
||||
):
|
||||
return (
|
||||
init_settings,
|
||||
env_settings,
|
||||
file_secret_settings,
|
||||
)
|
||||
|
||||
61
tests/README.md
Normal file
61
tests/README.md
Normal file
@@ -0,0 +1,61 @@
|
||||
# Dolibarr MCP Tests
|
||||
|
||||
This directory contains the test suite for the Dolibarr MCP Server.
|
||||
|
||||
## Test Structure
|
||||
|
||||
- `test_config.py` - Configuration and environment tests
|
||||
- `test_dolibarr_client.py` - API client unit tests
|
||||
- `test_crud_operations.py` - Complete CRUD integration tests
|
||||
|
||||
## Running Tests
|
||||
|
||||
```bash
|
||||
# Run all tests
|
||||
pytest
|
||||
|
||||
# Run with coverage
|
||||
pytest --cov=src/dolibarr_mcp --cov-report=html
|
||||
|
||||
# Run specific test file
|
||||
pytest tests/test_config.py
|
||||
|
||||
# Run with verbose output
|
||||
pytest -v
|
||||
|
||||
# Run specific test
|
||||
pytest tests/test_config.py::TestConfig::test_env_loading
|
||||
```
|
||||
|
||||
## Test Requirements
|
||||
|
||||
All test dependencies are included in the main `requirements.txt`:
|
||||
- pytest
|
||||
- pytest-asyncio
|
||||
- pytest-cov
|
||||
|
||||
## Environment Setup
|
||||
|
||||
Create a `.env` file in the root directory with test credentials:
|
||||
```
|
||||
DOLIBARR_URL=https://test.dolibarr.com
|
||||
DOLIBARR_API_KEY=test_api_key
|
||||
LOG_LEVEL=DEBUG
|
||||
```
|
||||
|
||||
## Writing Tests
|
||||
|
||||
Follow these patterns for consistency:
|
||||
|
||||
```python
|
||||
import pytest
|
||||
from dolibarr_mcp import DolibarrClient
|
||||
|
||||
class TestDolibarrClient:
|
||||
@pytest.fixture
|
||||
def client(self):
|
||||
return DolibarrClient(url="https://test.com", api_key="test")
|
||||
|
||||
def test_example(self, client):
|
||||
assert client is not None
|
||||
```
|
||||
128
tests/test_config.py
Normal file
128
tests/test_config.py
Normal file
@@ -0,0 +1,128 @@
|
||||
"""
|
||||
Test configuration module for Dolibarr MCP Server.
|
||||
"""
|
||||
|
||||
import os
|
||||
import pytest
|
||||
from unittest.mock import patch
|
||||
from pathlib import Path
|
||||
|
||||
# Import only existing modules
|
||||
import sys
|
||||
sys.path.insert(0, 'src')
|
||||
from dolibarr_mcp.config import Config
|
||||
|
||||
|
||||
class TestConfig:
|
||||
"""Test configuration loading and validation."""
|
||||
|
||||
def test_config_from_env(self):
|
||||
"""Test configuration loading from environment variables."""
|
||||
with patch.dict(os.environ, {
|
||||
'DOLIBARR_URL': 'https://test.dolibarr.com',
|
||||
'DOLIBARR_API_KEY': 'test_key_123',
|
||||
'LOG_LEVEL': 'DEBUG'
|
||||
}):
|
||||
config = Config(
|
||||
dolibarr_url=os.getenv('DOLIBARR_URL'),
|
||||
dolibarr_api_key=os.getenv('DOLIBARR_API_KEY'),
|
||||
log_level=os.getenv('LOG_LEVEL')
|
||||
)
|
||||
assert config.dolibarr_url == 'https://test.dolibarr.com/api/index.php'
|
||||
assert config.dolibarr_api_key == 'test_key_123'
|
||||
assert config.log_level == 'DEBUG'
|
||||
|
||||
def test_config_defaults(self):
|
||||
"""Test configuration defaults when env vars not set."""
|
||||
with patch.dict(os.environ, {}, clear=True):
|
||||
config = Config()
|
||||
assert config.log_level == 'INFO' # Default log level
|
||||
|
||||
def test_config_url_normalization(self):
|
||||
"""Test URL normalization (adding API path)."""
|
||||
with patch.dict(os.environ, {
|
||||
'DOLIBARR_URL': 'https://test.dolibarr.com/',
|
||||
'DOLIBARR_API_KEY': 'test_key'
|
||||
}):
|
||||
config = Config(
|
||||
dolibarr_url=os.getenv('DOLIBARR_URL'),
|
||||
dolibarr_api_key=os.getenv('DOLIBARR_API_KEY')
|
||||
)
|
||||
# Should add /api/index.php
|
||||
assert config.dolibarr_url == 'https://test.dolibarr.com/api/index.php'
|
||||
assert not config.dolibarr_url.endswith('//')
|
||||
|
||||
def test_config_from_dotenv(self, tmp_path):
|
||||
"""Test configuration loading from .env file."""
|
||||
env_file = tmp_path / ".env"
|
||||
env_file.write_text(
|
||||
"DOLIBARR_URL=https://env.dolibarr.com\n"
|
||||
"DOLIBARR_API_KEY=env_key_456\n"
|
||||
"LOG_LEVEL=WARNING\n"
|
||||
)
|
||||
|
||||
with patch.dict(os.environ, {'DOTENV_PATH': str(env_file)}):
|
||||
# Load from env file
|
||||
from dotenv import load_dotenv
|
||||
load_dotenv(str(env_file))
|
||||
|
||||
config = Config(
|
||||
dolibarr_url=os.getenv('DOLIBARR_URL'),
|
||||
dolibarr_api_key=os.getenv('DOLIBARR_API_KEY'),
|
||||
log_level=os.getenv('LOG_LEVEL')
|
||||
)
|
||||
assert config.dolibarr_url == 'https://env.dolibarr.com/api/index.php'
|
||||
assert config.dolibarr_api_key == 'env_key_456'
|
||||
assert config.log_level == 'WARNING'
|
||||
|
||||
def test_config_precedence(self):
|
||||
"""Test that environment variables take precedence over defaults."""
|
||||
with patch.dict(os.environ, {
|
||||
'DOLIBARR_URL': 'https://env.dolibarr.com',
|
||||
'DOLIBARR_API_KEY': 'env_key'
|
||||
}):
|
||||
config = Config(
|
||||
dolibarr_url=os.getenv('DOLIBARR_URL'),
|
||||
dolibarr_api_key=os.getenv('DOLIBARR_API_KEY')
|
||||
)
|
||||
assert config.dolibarr_url == 'https://env.dolibarr.com/api/index.php'
|
||||
assert config.dolibarr_api_key == 'env_key'
|
||||
|
||||
def test_log_level_validation(self):
|
||||
"""Test log level validation."""
|
||||
valid_levels = ['DEBUG', 'INFO', 'WARNING', 'ERROR', 'CRITICAL']
|
||||
|
||||
for level in valid_levels:
|
||||
with patch.dict(os.environ, {
|
||||
'DOLIBARR_URL': 'https://test.com',
|
||||
'DOLIBARR_API_KEY': 'key',
|
||||
'LOG_LEVEL': level
|
||||
}):
|
||||
config = Config(
|
||||
dolibarr_url=os.getenv('DOLIBARR_URL'),
|
||||
dolibarr_api_key=os.getenv('DOLIBARR_API_KEY'),
|
||||
log_level=os.getenv('LOG_LEVEL')
|
||||
)
|
||||
assert config.log_level == level
|
||||
|
||||
def test_invalid_log_level(self):
|
||||
"""Test invalid log level falls back to default."""
|
||||
with patch.dict(os.environ, {
|
||||
'DOLIBARR_URL': 'https://test.com',
|
||||
'DOLIBARR_API_KEY': 'key',
|
||||
'LOG_LEVEL': 'INVALID'
|
||||
}):
|
||||
config = Config(
|
||||
dolibarr_url=os.getenv('DOLIBARR_URL'),
|
||||
dolibarr_api_key=os.getenv('DOLIBARR_API_KEY'),
|
||||
log_level='INVALID'
|
||||
)
|
||||
assert config.log_level == 'INFO' # Should fall back to default
|
||||
|
||||
def test_api_key_alias(self):
|
||||
"""Test backward compatibility alias for api_key."""
|
||||
config = Config(
|
||||
dolibarr_url='https://test.com',
|
||||
dolibarr_api_key='test_key'
|
||||
)
|
||||
assert config.api_key == 'test_key' # Should work via alias
|
||||
341
tests/test_crud_operations.py
Normal file
341
tests/test_crud_operations.py
Normal file
@@ -0,0 +1,341 @@
|
||||
"""
|
||||
CRUD Operations Integration Tests for Dolibarr MCP Server.
|
||||
|
||||
These tests verify complete CRUD operations for all Dolibarr entities.
|
||||
Run with: pytest tests/test_crud_operations.py -v
|
||||
"""
|
||||
|
||||
import pytest
|
||||
import asyncio
|
||||
from datetime import datetime
|
||||
from unittest.mock import Mock, patch, AsyncMock
|
||||
|
||||
# Add src to path for imports
|
||||
import sys
|
||||
import os
|
||||
sys.path.insert(0, os.path.join(os.path.dirname(__file__), '..', 'src'))
|
||||
|
||||
from dolibarr_mcp import DolibarrClient, Config
|
||||
|
||||
|
||||
class TestCRUDOperations:
|
||||
"""Test complete CRUD operations for all Dolibarr entities."""
|
||||
|
||||
@pytest.fixture
|
||||
def config(self):
|
||||
"""Create a test configuration."""
|
||||
return Config(
|
||||
dolibarr_url="https://test.dolibarr.com",
|
||||
dolibarr_api_key="test_api_key",
|
||||
log_level="INFO"
|
||||
)
|
||||
|
||||
@pytest.fixture
|
||||
def client(self, config):
|
||||
"""Create a test client instance."""
|
||||
return DolibarrClient(config)
|
||||
|
||||
# Customer (Third Party) CRUD Tests
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_customer_crud_lifecycle(self, client):
|
||||
"""Test complete customer CRUD lifecycle."""
|
||||
# Mock responses for each operation
|
||||
with patch.object(client, 'request') as mock_request:
|
||||
# Create
|
||||
mock_request.return_value = {"id": 1}
|
||||
customer_id = await client.create_customer({
|
||||
"name": "Test Company",
|
||||
"email": "test@company.com"
|
||||
})
|
||||
assert customer_id == 1
|
||||
|
||||
# Read
|
||||
mock_request.return_value = {
|
||||
"id": 1,
|
||||
"name": "Test Company",
|
||||
"email": "test@company.com"
|
||||
}
|
||||
customer = await client.get_customer_by_id(1)
|
||||
assert customer["name"] == "Test Company"
|
||||
|
||||
# Update
|
||||
mock_request.return_value = {"id": 1, "name": "Updated Company"}
|
||||
result = await client.update_customer(1, {"name": "Updated Company"})
|
||||
assert result["name"] == "Updated Company"
|
||||
|
||||
# Delete
|
||||
mock_request.return_value = {"success": True}
|
||||
result = await client.delete_customer(1)
|
||||
assert result["success"] is True
|
||||
|
||||
# Product CRUD Tests
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_product_crud_lifecycle(self, client):
|
||||
"""Test complete product CRUD lifecycle."""
|
||||
with patch.object(client, 'request') as mock_request:
|
||||
# Create
|
||||
mock_request.return_value = {"id": 10}
|
||||
product_id = await client.create_product({
|
||||
"label": "Test Product",
|
||||
"price": 99.99,
|
||||
"description": "Test product description"
|
||||
})
|
||||
assert product_id == 10
|
||||
|
||||
# Read
|
||||
mock_request.return_value = {
|
||||
"id": 10,
|
||||
"label": "Test Product",
|
||||
"price": "99.99"
|
||||
}
|
||||
product = await client.get_product_by_id(10)
|
||||
assert product["label"] == "Test Product"
|
||||
|
||||
# Update
|
||||
mock_request.return_value = {"id": 10, "price": "149.99"}
|
||||
result = await client.update_product(10, {"price": 149.99})
|
||||
assert result["price"] == "149.99"
|
||||
|
||||
# Delete
|
||||
mock_request.return_value = {"success": True}
|
||||
result = await client.delete_product(10)
|
||||
assert result["success"] is True
|
||||
|
||||
# Invoice CRUD Tests
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_invoice_crud_lifecycle(self, client):
|
||||
"""Test complete invoice CRUD lifecycle."""
|
||||
with patch.object(client, 'request') as mock_request:
|
||||
# Create
|
||||
mock_request.return_value = {"id": 100}
|
||||
invoice_id = await client.create_invoice({
|
||||
"socid": 1, # Customer ID
|
||||
"date": datetime.now().isoformat(),
|
||||
"lines": [
|
||||
{"desc": "Service", "qty": 1, "subprice": 100}
|
||||
]
|
||||
})
|
||||
assert invoice_id == 100
|
||||
|
||||
# Read
|
||||
mock_request.return_value = {
|
||||
"id": 100,
|
||||
"ref": "INV-2024-100",
|
||||
"total_ttc": "100.00"
|
||||
}
|
||||
invoice = await client.get_invoice_by_id(100)
|
||||
assert invoice["ref"] == "INV-2024-100"
|
||||
|
||||
# Update
|
||||
mock_request.return_value = {"id": 100, "date_lim_reglement": "2024-02-01"}
|
||||
result = await client.update_invoice(100, {
|
||||
"date_lim_reglement": "2024-02-01"
|
||||
})
|
||||
assert result["date_lim_reglement"] == "2024-02-01"
|
||||
|
||||
# Delete
|
||||
mock_request.return_value = {"success": True}
|
||||
result = await client.delete_invoice(100)
|
||||
assert result["success"] is True
|
||||
|
||||
# Order CRUD Tests
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_order_crud_lifecycle(self, client):
|
||||
"""Test complete order CRUD lifecycle."""
|
||||
with patch.object(client, 'request') as mock_request:
|
||||
# Create
|
||||
mock_request.return_value = {"id": 50}
|
||||
order_id = await client.create_order({
|
||||
"socid": 1,
|
||||
"date": datetime.now().isoformat()
|
||||
})
|
||||
assert order_id == 50
|
||||
|
||||
# Read
|
||||
mock_request.return_value = {
|
||||
"id": 50,
|
||||
"ref": "ORD-2024-50",
|
||||
"socid": 1
|
||||
}
|
||||
order = await client.get_order_by_id(50)
|
||||
assert order["ref"] == "ORD-2024-50"
|
||||
|
||||
# Update
|
||||
mock_request.return_value = {"id": 50, "note_public": "Updated note"}
|
||||
result = await client.update_order(50, {
|
||||
"note_public": "Updated note"
|
||||
})
|
||||
assert result["note_public"] == "Updated note"
|
||||
|
||||
# Delete
|
||||
mock_request.return_value = {"success": True}
|
||||
result = await client.delete_order(50)
|
||||
assert result["success"] is True
|
||||
|
||||
# Contact CRUD Tests
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_contact_crud_lifecycle(self, client):
|
||||
"""Test complete contact CRUD lifecycle."""
|
||||
with patch.object(client, 'request') as mock_request:
|
||||
# Create
|
||||
mock_request.return_value = {"id": 20}
|
||||
contact_id = await client.create_contact({
|
||||
"firstname": "John",
|
||||
"lastname": "Doe",
|
||||
"email": "john.doe@example.com"
|
||||
})
|
||||
assert contact_id == 20
|
||||
|
||||
# Read
|
||||
mock_request.return_value = {
|
||||
"id": 20,
|
||||
"firstname": "John",
|
||||
"lastname": "Doe",
|
||||
"email": "john.doe@example.com"
|
||||
}
|
||||
contact = await client.get_contact_by_id(20)
|
||||
assert contact["firstname"] == "John"
|
||||
|
||||
# Update
|
||||
mock_request.return_value = {"id": 20, "phone": "+1234567890"}
|
||||
result = await client.update_contact(20, {
|
||||
"phone": "+1234567890"
|
||||
})
|
||||
assert result["phone"] == "+1234567890"
|
||||
|
||||
# Delete
|
||||
mock_request.return_value = {"success": True}
|
||||
result = await client.delete_contact(20)
|
||||
assert result["success"] is True
|
||||
|
||||
# User Management Tests
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_user_crud_lifecycle(self, client):
|
||||
"""Test complete user CRUD lifecycle."""
|
||||
with patch.object(client, 'request') as mock_request:
|
||||
# Create
|
||||
mock_request.return_value = {"id": 5}
|
||||
user_id = await client.create_user({
|
||||
"login": "testuser",
|
||||
"lastname": "User",
|
||||
"firstname": "Test",
|
||||
"email": "testuser@example.com"
|
||||
})
|
||||
assert user_id == 5
|
||||
|
||||
# Read
|
||||
mock_request.return_value = {
|
||||
"id": 5,
|
||||
"login": "testuser",
|
||||
"email": "testuser@example.com"
|
||||
}
|
||||
user = await client.get_user_by_id(5)
|
||||
assert user["login"] == "testuser"
|
||||
|
||||
# Update
|
||||
mock_request.return_value = {"id": 5, "admin": 1}
|
||||
result = await client.update_user(5, {"admin": 1})
|
||||
assert result["admin"] == 1
|
||||
|
||||
# Delete
|
||||
mock_request.return_value = {"success": True}
|
||||
result = await client.delete_user(5)
|
||||
assert result["success"] is True
|
||||
|
||||
# Batch Operations Tests
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_batch_operations(self, client):
|
||||
"""Test batch operations for multiple entities."""
|
||||
with patch.object(client, 'request') as mock_request:
|
||||
# Get multiple customers
|
||||
mock_request.return_value = [
|
||||
{"id": 1, "name": "Company A"},
|
||||
{"id": 2, "name": "Company B"},
|
||||
{"id": 3, "name": "Company C"}
|
||||
]
|
||||
customers = await client.get_customers(limit=3)
|
||||
assert len(customers) == 3
|
||||
|
||||
# Get multiple products
|
||||
mock_request.return_value = [
|
||||
{"id": 10, "label": "Product A"},
|
||||
{"id": 11, "label": "Product B"}
|
||||
]
|
||||
products = await client.get_products(limit=2)
|
||||
assert len(products) == 2
|
||||
|
||||
# Error Handling Tests
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_error_handling(self, client):
|
||||
"""Test error handling in CRUD operations."""
|
||||
with patch.object(client, 'request') as mock_request:
|
||||
# Test 404 Not Found
|
||||
mock_request.side_effect = Exception("404 Not Found")
|
||||
with pytest.raises(Exception, match="404"):
|
||||
await client.get_customer_by_id(999)
|
||||
|
||||
# Test validation error
|
||||
mock_request.side_effect = Exception("Validation Error: Missing required field")
|
||||
with pytest.raises(Exception, match="Validation"):
|
||||
await client.create_product({})
|
||||
|
||||
# Test connection error
|
||||
mock_request.side_effect = Exception("Connection refused")
|
||||
with pytest.raises(Exception, match="Connection"):
|
||||
await client.test_connection()
|
||||
|
||||
|
||||
class TestMCPServerIntegration:
|
||||
"""Test MCP Server integration with Dolibarr API."""
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_server_initialization(self):
|
||||
"""Test server initialization and configuration."""
|
||||
with patch('dolibarr_mcp.config.Config') as mock_config_class:
|
||||
mock_config_class.return_value = Config(
|
||||
dolibarr_url="https://test.com",
|
||||
dolibarr_api_key="key",
|
||||
log_level="INFO"
|
||||
)
|
||||
|
||||
# Import the server module to test initialization
|
||||
from dolibarr_mcp import dolibarr_mcp_server
|
||||
assert dolibarr_mcp_server.server is not None
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_server_tool_execution(self):
|
||||
"""Test server tool execution via client."""
|
||||
config = Config(
|
||||
dolibarr_url="https://test.com",
|
||||
dolibarr_api_key="key",
|
||||
log_level="INFO"
|
||||
)
|
||||
|
||||
with patch('dolibarr_mcp.dolibarr_client.DolibarrClient') as mock_client_class:
|
||||
mock_client = mock_client_class.return_value
|
||||
mock_client.__aenter__ = AsyncMock(return_value=mock_client)
|
||||
mock_client.__aexit__ = AsyncMock(return_value=None)
|
||||
mock_client.get_customers = AsyncMock(return_value=[
|
||||
{"id": 1, "name": "Test Company"}
|
||||
])
|
||||
|
||||
# Create real client
|
||||
async with DolibarrClient(config) as client:
|
||||
# Mock the request
|
||||
client.get_customers = mock_client.get_customers
|
||||
result = await client.get_customers()
|
||||
assert len(result) == 1
|
||||
assert result[0]["name"] == "Test Company"
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
# Run tests with coverage
|
||||
pytest.main([__file__, "-v", "--cov=dolibarr_mcp", "--cov-report=term-missing"])
|
||||
Reference in New Issue
Block a user