woow-odoo-mcp-server
by WOOWTECH
README.md
<p align="center">
<img src="https://odoo-community.org/logo.png" alt="Odoo MCP" width="100"/>
</p>
<h1 align="center">Woow Odoo MCP Server</h1>
<p align="center">
<strong>Production-Ready Admin Bundle for Odoo MCP Server</strong><br/>
Web GUI + MCP Reverse Proxy + Process Manager — all in one container
</p>
<p align="center">
<a href="#overview">Overview</a> •
<a href="#features">Features</a> •
<a href="#architecture">Architecture</a> •
<a href="#quick-start">Quick Start</a> •
<a href="#installation">Installation</a> •
<a href="#configuration">Configuration</a> •
<a href="#screenshots">Screenshots</a> •
<a href="#api-reference">API</a> •
<a href="#security">Security</a> •
<a href="#testing">Testing</a> •
<a href="#changelog">Changelog</a> •
<a href="README_zh-TW.md">中文文件</a>
</p>
<p align="center">
<img src="https://img.shields.io/badge/Odoo-18.0-purple?logo=odoo" alt="Odoo 18"/>
<img src="https://img.shields.io/badge/Python-3.12+-blue?logo=python" alt="Python 3.12+"/>
<img src="https://img.shields.io/badge/FastAPI-0.115+-009688?logo=fastapi" alt="FastAPI"/>
<img src="https://img.shields.io/badge/React-19-61DAFB?logo=react" alt="React 19"/>
<img src="https://img.shields.io/badge/Tailwind_CSS-3.x-06B6D4?logo=tailwindcss" alt="Tailwind CSS"/>
<img src="https://img.shields.io/badge/MCP-Protocol-FF6B35" alt="MCP Protocol"/>
<img src="https://img.shields.io/badge/Docker-Ready-2496ED?logo=docker" alt="Docker"/>
<img src="https://img.shields.io/badge/Kubernetes-Ready-326CE5?logo=kubernetes" alt="Kubernetes"/>
<img src="https://img.shields.io/badge/License-MIT-green" alt="MIT License"/>
</p>
---
## Overview
**Woow Odoo MCP Server** is a complete administration bundle for managing [Odoo MCP Server](https://pypi.org/project/odoo-mcp-server/) deployments. It provides a modern web interface to configure Odoo connections, manage MCP tools, rotate authentication tokens, stream real-time logs, and proxy MCP protocol requests — all packaged into a single container image.
The bundle eliminates the need for separate nginx proxies, manual config file editing, or kubectl commands. Everything is managed through a clean, responsive web UI.
### Why This Package?
| Challenge | Solution |
|-----------|----------|
| MCP server config requires editing JSON files or K8s secrets by hand | Web-based GUI with live validation and one-click save |
| Token rotation involves manual secret updates + pod restarts | One-click token rotation with automatic MCP server restart |
| MCP proxy requires a separate nginx + auth config | Built-in reverse proxy with URL-path token authentication |
| Monitoring MCP server logs requires `kubectl logs` or SSH | Real-time SSE log streaming in the browser with search |
| Enabling/disabling MCP tools needs config edits + restarts | Visual tool manager with 10 categories and toggle switches |
| Testing Odoo connectivity needs XML-RPC scripting | One-click connection test with Odoo 18 auth format support |
| Deploying all components separately is complex | Single container with everything included |
---
## Features
### Dashboard
Real-time health monitoring for all components in the stack:
- **Odoo Status** — Checks `/web/health` endpoint; shows version, database name, and installed module count
- **MCP Server Status** — Subprocess health, PID, restart count
- **MCP Proxy Status** — Built-in proxy always healthy when admin is running
- **Overall Status** — Aggregated `ok` / `degraded` / `error` indicator
### Connection Configuration
Manage Odoo XML-RPC connection credentials:
- Configure Odoo URL, database name, username, and password
- **One-click connection test** with full error reporting
- Supports both **Odoo 18** (new `authenticate()` signature) and **Odoo 17** (legacy format)
- Auto-restart MCP server when connection config changes
### Tool Manager
Visual management of all **39 MCP tools** organized into **10 categories**:
| Category | Count | Description |
|----------|-------|-------------|
| Read & Discover | 11 | Schema browsing, record search, employee/holiday lookup |
| Write & Operate | 5 | Preview, validate, execute writes, chatter posts |
| Diagnose | 3 | Error analysis, access rights debugging, relationship inspection |
| Migrate | 3 | JSON2 payloads, upgrade risk reports, version history |
| Audit & Plan | 3 | Addon source scanning, fit/gap analysis, business pack reports |
| Knowledge | 3 | Knowledge base indexing, semantic search, coverage stats |
| Accounting | 2 | AR/AP aging, accounting health summaries |
| Background Tasks | 4 | Async task submission, status, cancellation, listing |
| Cross-Instance | 3 | Multi-instance search, aggregation, health comparison |
| Utility | 2 | Health check, instance listing |
Each tool can be individually enabled or disabled. Dangerous (write) tools are clearly marked with a warning indicator.
### Token Manager
Manage MCP proxy authentication tokens:
- View current token (masked) with prefix identification
- **One-click token rotation** with cryptographically secure generation
- Configurable token length (16-128 bytes, output is 2x hex)
- Rotation history with timestamps (last 10 rotations)
- Optional automatic MCP server restart after rotation
### Log Viewer
Real-time MCP server log streaming:
- **Server-Sent Events (SSE)** for zero-latency log delivery
- In-memory ring buffer (5000 lines) with configurable tail
- **Full-text search** with plain text and regex support
- Timestamped log entries with source identification
- Auto-scroll with pause on user interaction
### Settings
Full configuration management:
- View and edit the complete `config.json` through the GUI
- Per-section editing: connection, mcp_server, proxy, tools
- Admin password management
- MCP auth token rotation
- **MCP server restart** and status monitoring
### MCP Reverse Proxy
Built-in reverse proxy replacing the traditional nginx auth proxy:
- **URL-path token authentication**: `/private_{token}/sse`, `/private_{token}/messages`
- Compatible with Claude Desktop, Cursor, and all MCP clients
- Full SSE streaming support for MCP protocol
- Long timeout (86400s default) for long-running tool calls
- Bearer token forwarding for upstream auth
---
## Architecture
```mermaid
graph LR
Browser["Browser<br/>(React SPA)"]
FastAPI["FastAPI<br/>(Admin API + Proxy)"]
ConfigStore["ConfigStore<br/>(config.json)"]
ProcessMgr["Process Manager"]
MCPServer["odoo-mcp-server<br/>(subprocess)"]
Odoo["Odoo 18<br/>(XML-RPC)"]
Browser -->|"REST API<br/>/api/*"| FastAPI
Browser -->|"MCP Protocol<br/>/private_TOKEN/*"| FastAPI
FastAPI --> ConfigStore
FastAPI --> ProcessMgr
FastAPI -->|"HTTP forward"| MCPServer
ProcessMgr -->|"start/stop/restart"| MCPServer
MCPServer -->|"XML-RPC"| Odoo
```
The application follows a clean layered architecture:
```
┌─────────────────────────────────────────────────────┐
│ Browser (React SPA) │
│ Login → Dashboard → Connection → Tools → Tokens │
│ → Logs → Settings │
├─────────────────────────────────────────────────────┤
│ FastAPI Application │
│ ┌──────────┐ ┌──────────┐ ┌──────────┐ │
│ │ Auth │ │ Admin │ │ MCP │ │
│ │ Middle- │ │ Routers │ │ Proxy │ │
│ │ ware │ │ (7 sets) │ │ Router │ │
│ └────┬─────┘ └────┬─────┘ └────┬─────┘ │
│ │ │ │ │
│ ┌────▼────────────▼────────────▼─────┐ │
│ │ Core Services │ │
│ │ ConfigStore │ ProcessManager │ │
│ └────────────────────────────────────┘ │
├─────────────────────────────────────────────────────┤
│ odoo-mcp-server (subprocess on :8000) │
│ 39 MCP tools │ SSE transport │ XML-RPC client │
├─────────────────────────────────────────────────────┤
│ Odoo 18 (external, :8069) │
│ PostgreSQL │ Business Logic │ ORM │
└─────────────────────────────────────────────────────┘
```
**Key packages:**
| Package | Description |
|---------|-------------|
| `mcp_admin_core` | Shared foundation: FastAPI app factory, JWT auth middleware, file-based config store, subprocess process manager, MCP reverse proxy |
| `odoo_mcp_admin` | Odoo-specific routers: connection config, health dashboard, 39-tool registry, token manager, SSE log viewer |
| `frontend` | React 19 SPA with Tailwind CSS, built with Vite |
For detailed architecture documentation with Mermaid diagrams, see [docs/architecture.md](docs/architecture.md).
---
## Quick Start
### One-Liner (Podman or Docker)
```bash
# Podman
podman run -d --name mcp-admin \
-p 8080:8080 \
-v mcp-data:/data \
ghcr.io/woowtech/woow-odoo-mcp-server:latest
# Docker
docker run -d --name mcp-admin \
-p 8080:8080 \
-v mcp-data:/data \
ghcr.io/woowtech/woow-odoo-mcp-server:latest
```
Open `http://localhost:8080` and log in with the password you passed as
`ADMIN_PASSWORD`. There is no built-in default: if `ADMIN_PASSWORD` is unset on
first boot the console seeds a random password that nobody can read, and you have
to re-create `/data/config.json` to get in.
### Docker Compose (Full Stack)
Spin up Odoo 18 + PostgreSQL + MCP Admin in one command:
```bash
git clone https://github.com/WOOWTECH/woow_odoo_mcp_server.git
cd woow_odoo_mcp_server
docker compose up -d
```
This starts three services:
| Service | Port | Description |
|---------|------|-------------|
| `postgres` | 5432 (internal) | PostgreSQL 16 with health checks |
| `odoo` | 8069 | Odoo 18 Community |
| `mcp-admin` | 8080 | MCP Admin Bundle |
After Odoo finishes initializing, open `http://localhost:8080` and configure the connection:
- **Odoo URL**: `http://odoo:8069`
- **Database**: `odoo`
- **Username**: `admin`
- **Password**: the `POSTGRES_PASSWORD` you set in `.env`
---
## Installation
### Option 1: Podman (Recommended)
Podman is rootless and daemonless, making it ideal for MCP server deployments.
```bash
# Build from source
podman build -t woow-odoo-mcp-server .
# Run with persistent config
podman run -d --name mcp-admin \
-p 8080:8080 \
-v mcp-data:/data \
woow-odoo-mcp-server
# View logs
podman logs -f mcp-admin
```
### Option 2: Docker
```bash
# Build
docker build -t woow-odoo-mcp-server .
# Run
docker run -d --name mcp-admin \
-p 8080:8080 \
-v mcp-data:/data \
-e JWT_SECRET=your-secret-here \
woow-odoo-mcp-server
```
### Option 3: Docker Compose
```bash
# Full stack (PostgreSQL + Odoo + MCP Admin)
docker compose up -d
# MCP Admin only (connect to existing Odoo)
docker compose up -d mcp-admin
```
### Option 4: Kubernetes (K3s) — Helm chart
[`charts/odoo-mcp`](charts/odoo-mcp/README.md) deploys one Odoo tenant's MCP
server: the patched `odoo-mcp` streamable-HTTP server, the nginx token gate in
front of it, the side-effect policy file, and optionally this admin console.
```bash
# A new tenant. Nothing secret is stored in the repo.
ODOO_PASSWORD=...
MCP_AUTH_TOKEN=$(python3 -c 'import secrets;print(secrets.token_hex(10))')
helm install mcp-odoo charts/odoo-mcp -n <tenant> --create-namespace \
--set odoo.url=https://<tenant>-odoo.woowtech.io \
--set odoo.db=<tenant> \
--set "server.allowedHosts={<tenant>-mcp-odoo.woowtech.io,localhost,mcp-odoo-proxy.<tenant>.svc.cluster.local,mcp-odoo.<tenant>.svc.cluster.local,127.0.0.1}" \
--set secrets.create=true --set secrets.odooPassword="$ODOO_PASSWORD" \
--set proxy.config.create=true --set proxy.config.authToken="$MCP_AUTH_TOKEN" \
--set admin.enabled=true \
--set secrets.admin.adminPassword="$ADMIN_PASSWORD" \
--set secrets.admin.mcpAuthToken="$MCP_AUTH_TOKEN" \
--set secrets.admin.jwtSecret="$JWT_SECRET"
# A tenant that already exists (values without secrets live in the repo)
helm install mcp-odoo charts/odoo-mcp -n komibright \
-f deploy/woow-k3s/komibright.yaml
helm test mcp-odoo -n <tenant> --logs
```
The chart includes:
- **Readiness/liveness probes** on `/healthz` for the console
- **Resource limits**: 100m-500m CPU, 128Mi-512Mi memory
- **`helm uninstall` never deletes data**: the Namespace, the PVC and any
chart-created Secret carry `helm.sh/resource-policy: keep`
- **No credential in git**: `secrets.create=false` by default, and the MCP proxy
token stays in the cluster ConfigMap
- **A read-only `helm test` smoke pod**
- **No ServiceAccount**: the console never calls the Kubernetes API, so unlike
the old `k8s-deploy.yaml` nothing grants it read access to every Secret in the
namespace
> The old root-level `k8s-deploy.yaml` has been removed. It was a copy of a
> manifest applied by hand to one namespace, pointed at an image this repo does
> not build, exposed ports `9001`/`9002` while the image listens on `8080`, and
> also redefined an unrelated product (`n8n-mcp-admin`) so applying it clobbered
> that Deployment too.
### Option 5: Development Mode
```bash
# Backend
python -m venv .venv
source .venv/bin/activate
pip install -e ".[dev]"
uvicorn odoo_mcp_admin.main:app --host 0.0.0.0 --port 8080 --reload
# Frontend (separate terminal)
cd frontend
npm install
npm run dev
```
---
## Configuration
### Web GUI Walkthrough
After starting the container:
1. **Login** — Navigate to `http://localhost:8080` and enter the admin password (the `ADMIN_PASSWORD` seed; there is no default)
2. **Connection** — Go to the Connection page, enter your Odoo URL, database, username, and password, then click **Test Connection**
3. **Tools** — Browse all 39 MCP tools, toggle individual tools on/off as needed
4. **Tokens** — Generate an MCP auth token by clicking **Rotate Token** -- save it for your MCP client configuration
5. **Settings** — Configure MCP server command, port, and environment variables
6. **Dashboard** — Verify all components show green healthy status
### config.json Format
The configuration file is automatically created on first run at `/data/config.json`:
```json
{
"admin_password": "<seeded from ADMIN_PASSWORD on first boot>",
"mcp_auth_token": "<20 hex chars, generated on first boot>",
"connection": {
"odoo_url": "http://odoo:8069",
"odoo_db": "mydb",
"odoo_username": "admin",
"odoo_password": "<REPLACE_ME>"
},
"mcp_server": {
"command": "odoo-mcp-server",
"args": ["--transport", "sse"],
"port": 8000,
"env": {
"ODOO_URL": "http://odoo:8069",
"ODOO_DB": "mydb"
}
},
"proxy": {
"timeout": 86400,
"bearer_token": null
},
"tools": {
"disabled": ["execute_method"],
"disabled_operations": {}
},
"token_history": []
}
```
### Environment Variables
| Variable | Default | Description |
|----------|---------|-------------|
| `MCP_ADMIN_CONFIG` | `/data/config.json` | Path to the configuration file |
| `JWT_SECRET` | (auto-generated) | Secret key for JWT token signing. Set this for token persistence across restarts |
| `JWT_EXPIRY_HOURS` | `24` | JWT token expiry time in hours |
### MCP Client Configuration
After generating a token through the admin UI, configure your MCP client:
**Claude Desktop / Cursor:**
```json
{
"mcpServers": {
"odoo": {
"url": "http://your-server:8080/private_YOUR_TOKEN_HERE/sse"
}
}
}
```
**Claude Code CLI:**
```bash
claude mcp add odoo --transport sse \
http://your-server:8080/private_YOUR_TOKEN_HERE/sse
```
---
## Screenshots
### Login
<p align="center">
<img src="docs/screenshots/login.png" alt="Login Page" width="720"/>
</p>
JWT-based authentication. The password is seeded from `ADMIN_PASSWORD` on first boot — there is no default password. Supports cookie-based and Authorization header auth.
### Dashboard
<p align="center">
<img src="docs/screenshots/dashboard.png" alt="Dashboard" width="720"/>
</p>
Real-time health monitoring for Odoo, MCP Server, and MCP Proxy. Shows Odoo version, database name, installed module count, and overall system status.
### Connection Configuration
<p align="center">
<img src="docs/screenshots/connection.png" alt="Connection Config" width="720"/>
</p>
Configure and test Odoo XML-RPC connectivity. Supports both Odoo 18 (new credential dict format) and Odoo 17 (positional arguments). One-click test with detailed error reporting.
### Tool Manager
<p align="center">
<img src="docs/screenshots/tools.png" alt="Tool Manager" width="720"/>
</p>
Visual management of all 39 MCP tools across 10 categories. Toggle individual tools on/off. Dangerous (write) tools are clearly marked. Changes are persisted immediately.
### Token Manager
<p align="center">
<img src="docs/screenshots/tokens.png" alt="Token Manager" width="720"/>
</p>
Manage MCP proxy authentication tokens. One-click rotation with cryptographic token generation. Rotation history with timestamps. Token is displayed once after rotation.
### Log Viewer
<p align="center">
<img src="docs/screenshots/logs.png" alt="Log Viewer" width="720"/>
</p>
Real-time SSE log streaming from the MCP server subprocess. In-memory ring buffer with full-text and regex search. Auto-scroll with manual pause support.
### Settings
<p align="center">
<img src="docs/screenshots/settings.png" alt="Settings" width="720"/>
</p>
Full configuration management. Edit MCP server command, arguments, port, environment variables. Admin password management. MCP server restart with status monitoring.
---
## API Reference
All API endpoints require JWT authentication (except login and health check).
### Authentication
| Method | Endpoint | Description |
|--------|----------|-------------|
| `POST` | `/api/auth/login` | Authenticate with admin password, returns JWT |
### Health & Dashboard
| Method | Endpoint | Description |
|--------|----------|-------------|
| `GET` | `/healthz` | Basic health check (no auth required) |
| `GET` | `/api/health` | Full dashboard health data (Odoo, MCP, Proxy status) |
### Connection Configuration
| Method | Endpoint | Description |
|--------|----------|-------------|
| `GET` | `/api/config` | Get current Odoo connection config (password masked) |
| `PUT` | `/api/config/connection` | Update Odoo connection credentials |
| `POST` | `/api/config/test` | Test XML-RPC connectivity to Odoo |
### Tool Management
| Method | Endpoint | Description |
|--------|----------|-------------|
| `GET` | `/api/tools` | List all 39 tools with categories and enabled status |
| `PUT` | `/api/tools` | Update tool enable/disable states |
### Token Management
| Method | Endpoint | Description |
|--------|----------|-------------|
| `GET` | `/api/tokens` | Get current token (masked) and rotation history |
| `POST` | `/api/tokens/rotate` | Generate new token, update config, restart server |
### Settings
| Method | Endpoint | Description |
|--------|----------|-------------|
| `GET` | `/api/settings` | Get full config (passwords masked) |
| `PUT` | `/api/settings/{section}` | Update a config section |
| `GET` | `/api/settings/{section}` | Get a single config section |
| `POST` | `/api/settings/mcp_auth_token/rotate` | Rotate MCP auth token |
| `GET` | `/api/settings/mcp/status` | MCP server process status |
| `POST` | `/api/settings/mcp/restart` | Restart MCP server process |
### Log Streaming
| Method | Endpoint | Description |
|--------|----------|-------------|
| `GET` | `/api/logs/stream` | SSE endpoint for real-time log streaming |
| `GET` | `/api/logs/search` | Search in-memory log buffer (text or regex) |
### MCP Proxy
| Method | Endpoint | Description |
|--------|----------|-------------|
| `*` | `/private_{token}/{path}` | Reverse proxy to MCP server (all HTTP methods) |
---
## Security
### Authentication
- **JWT-based authentication** with configurable expiry (default: 24 hours)
- Admin password stored in `config.json` (change from default immediately)
- JWT secret auto-generated on startup if `JWT_SECRET` env var is not set
- Cookie-based auth with `httponly`, `samesite=strict` flags
- SSE endpoints support query parameter token for EventSource compatibility
### MCP Token Authentication
- MCP proxy validates URL-path tokens against the config store
- Tokens are cryptographically generated using `secrets.token_hex()`
- Token rotation invalidates the previous token immediately
- Token history maintains last 10 rotation records for audit
- Sensitive values are masked in all API responses
### Network Security
- CORS middleware configured (default: allow all origins -- restrict in production)
- Auth middleware enforces JWT on all `/api/*` routes except login
- MCP proxy paths (`/private_*`) bypass JWT auth (token validated by proxy itself)
- Kubernetes deployment includes RBAC with namespace-scoped permissions only
### Best Practices
1. **Set `ADMIN_PASSWORD` and `JWT_SECRET`** before the first boot; without `JWT_SECRET` every restart invalidates all sessions
2. **Set `JWT_SECRET`** environment variable for token persistence across restarts
3. **Restrict CORS origins** in production deployments
4. **Use Kubernetes NetworkPolicy** to limit pod-to-pod communication
5. **Disable dangerous tools** (Write & Operate category) unless explicitly needed
6. **Rotate MCP tokens** regularly using the Token Manager
---
## Testing
### Test Coverage Summary
The admin bundle has been validated with a comprehensive 22-point test matrix:
| # | Test Case | Status |
|---|-----------|--------|
| 1 | Container builds successfully | Pass |
| 2 | Container starts and listens on port 8080 | Pass |
| 3 | `/healthz` returns 200 | Pass |
| 4 | Login with correct password returns JWT | Pass |
| 5 | Login with wrong password returns 401 | Pass |
| 6 | API endpoints return 401 without token | Pass |
| 7 | Dashboard endpoint returns health data | Pass |
| 8 | Connection config GET returns masked password | Pass |
| 9 | Connection config PUT updates and persists | Pass |
| 10 | Connection test against live Odoo succeeds | Pass |
| 11 | Tool list returns 39 tools in 10 categories | Pass |
| 12 | Tool toggle persists disabled state | Pass |
| 13 | Token rotation generates new token | Pass |
| 14 | Token rotation restarts MCP server | Pass |
| 15 | Log stream SSE endpoint connects | Pass |
| 16 | Log search returns filtered results | Pass |
| 17 | Settings GET returns full config | Pass |
| 18 | Settings PUT updates individual sections | Pass |
| 19 | MCP proxy forwards to subprocess | Pass |
| 20 | MCP proxy rejects invalid token | Pass |
| 21 | Config persists across container restart | Pass |
| 22 | Frontend SPA loads and renders | Pass |
**Result: 22/22 tests passing**
### Running Tests
```bash
# Install dev dependencies
pip install -e ".[dev]"
# Run tests
pytest -v
# Run with coverage
pytest --cov=mcp_admin_core --cov=odoo_mcp_admin -v
```
---
## Project Structure
```
woow_odoo_mcp_server/
├── mcp_admin_core/ # Shared core library
│ ├── __init__.py
│ ├── app.py # FastAPI application factory
│ ├── process.py # MCP subprocess manager
│ ├── proxy.py # MCP reverse proxy router
│ ├── mcp_sse_wrapper.py # SSE transport wrapper
│ ├── auth/
│ │ ├── __init__.py
│ │ └── middleware.py # JWT auth middleware + login router
│ ├── config/
│ │ ├── __init__.py
│ │ └── store.py # File-based config store
│ ├── routers/
│ │ ├── __init__.py
│ │ └── settings.py # Settings CRUD router
│ └── k8s/
│ ├── __init__.py
│ └── client.py # Kubernetes API client
├── odoo_mcp_admin/ # Odoo-specific admin backend
│ ├── __init__.py
│ ├── main.py # FastAPI app entry point
│ ├── tool_registry.py # 39 Odoo MCP tool definitions
│ └── routers/
│ ├── __init__.py
│ ├── config.py # Odoo connection config
│ ├── health.py # Dashboard health endpoint
│ ├── tools.py # Tool management
│ ├── tokens.py # Token rotation
│ └── logs.py # SSE log streaming
├── frontend/ # React 19 SPA
│ ├── package.json
│ ├── vite.config.js
│ ├── index.html
│ └── src/
│ ├── main.jsx
│ ├── App.jsx
│ ├── api.js
│ ├── index.css
│ ├── components/
│ │ ├── Sidebar.jsx
│ │ └── StatusCard.jsx
│ └── pages/
│ ├── LoginPage.jsx
│ ├── Dashboard.jsx
│ ├── ConnectionConfig.jsx
│ ├── ToolManager.jsx
│ ├── TokenManager.jsx
│ ├── LogViewer.jsx
│ ├── SettingsPage.jsx
│ └── PermissionEditor.jsx
├── docs/
│ ├── architecture.md # Detailed architecture docs
│ └── screenshots/ # UI screenshots
│ ├── login.png
│ ├── dashboard.png
│ ├── connection.png
│ ├── tools.png
│ ├── tokens.png
│ ├── logs.png
│ └── settings.png
├── Dockerfile # Multi-stage build (Node + Python)
├── docker-compose.yml # Full stack: PostgreSQL + Odoo + Admin
├── charts/
│ └── odoo-mcp/ # Helm chart: one Odoo tenant's MCP server
├── scripts/
│ └── check-drift.sh # chart vs. live objects, field by field
├── .env.example # local stack credentials (values empty)
├── pyproject.toml # Python package configuration
├── LICENSE # MIT License
├── CONTRIBUTING.md # Contribution guide
├── README.md # This file
└── README_zh-TW.md # Traditional Chinese documentation
```
---
## Changelog
### v1.0.0 (2026-06-26)
**Initial Release**
- Complete admin web GUI with 7 pages (Login, Dashboard, Connection, Tools, Tokens, Logs, Settings)
- Built-in MCP reverse proxy with URL-path token authentication
- MCP server subprocess process manager with auto-restart
- File-based configuration store (`config.json`) for full portability
- JWT authentication middleware with cookie and header support
- 39 Odoo MCP tool registry organized into 10 categories
- Real-time SSE log streaming with in-memory ring buffer (5000 lines)
- Token rotation with cryptographic generation and rotation history
- Odoo connection testing with Odoo 18 and Odoo 17 compatibility
- Multi-stage Docker build (Node 20 + Python 3.12)
- Docker Compose full-stack deployment (PostgreSQL + Odoo + Admin)
- Kubernetes deployment with RBAC, health probes, and resource limits
- Comprehensive 22-point test validation
---
## Troubleshooting
### MCP Server Won't Start
1. Check the **Settings** page to ensure `mcp_server.command` is set (e.g., `odoo-mcp-server`)
2. Verify `odoo-mcp-server` is installed in the container: `pip list | grep odoo-mcp`
3. Check **Logs** page for startup errors
### Connection Test Fails
1. Verify the Odoo URL is reachable from the container (use service names in Docker/K8s)
2. Check database name matches exactly (case-sensitive)
3. For Odoo 18, ensure credentials are correct -- the auth format changed from Odoo 17
### Token Not Working for MCP Client
1. Ensure you copied the full token (64 hex characters)
2. The MCP URL format must be: `http://host:8080/private_TOKEN/sse`
3. Check the proxy timeout if long-running tool calls time out
### Container Exits Immediately
1. Check if port 8080 is already in use
2. Verify the `/data` volume is writable
3. Check container logs: `docker logs mcp-admin`
---
## Use Case & Permission Model
### Recommended Use: Multi-User Application Server
This bundle is designed to be deployed as a **shared MCP endpoint for multiple users**, where each user's access is controlled by the **Odoo account** used for the MCP connection — not by the MCP server itself.
```
Sales Rep → MCP instance (Odoo: sales_user account) → sees own orders only
Accountant → MCP instance (Odoo: accountant account) → sees invoices, no HR
HR Manager → MCP instance (Odoo: hr_manager account) → sees employees, leaves
Admin → MCP instance (Odoo: admin account) → full access
```
### How Permissions Work
The MCP server passes every request through Odoo's XML-RPC layer. **Odoo enforces three permission layers automatically**, regardless of MCP server settings:
| Layer | What It Controls | Example |
|-------|-----------------|---------|
| **ir.model.access** (ACL) | Which models can be accessed and with what operations (read/create/write/delete) | Sales user cannot access `purchase.order` |
| **ir.rule** (Record Rules) | Which records are visible within accessible models | "Own Documents Only" means sales user sees only their own orders |
| **Field-level access** | Which fields are visible to which groups | Salary fields hidden from non-HR users |
**The MCP server cannot bypass these permissions.** If the connected Odoo account doesn't have access to a model or record, the MCP tool call will return an access error — just as if the user tried to access it through the Odoo web interface.
### Deployment for Different User Roles
Deploy separate instances with different Odoo accounts for different permission levels:
```yaml
# Instance for sales team (read-only on most modules)
- name: ODOO_USERNAME
value: "sales_mcp_user"
- name: ODOO_PASSWORD
valueFrom:
secretKeyRef:
name: mcp-odoo-secrets # REPLACE_ME: your Secret
key: odoo-password
# Instance for admin team (full access)
- name: ODOO_USERNAME
value: "admin"
- name: ODOO_PASSWORD
valueFrom:
secretKeyRef:
name: mcp-odoo-admin-secrets # REPLACE_ME: your Secret
key: odoo-password
```
Never put an Odoo password in a manifest literal: keep it in a Secret and
reference it, which is what `charts/odoo-mcp` does (`secrets.existingSecret`).
Each instance gets its own MCP proxy token, so you can distribute different tokens to different teams.
### Tool-Level Control
In addition to Odoo ACL, this bundle provides **per-tool enable/disable** through the Admin GUI:
- Disable all `Write & Operate` tools (preview_write, validate_write, execute_approved_write, execute_method, chatter_post) for read-only instances
- Keep only `Read & Discover` tools (search_records, list_models, aggregate_records, etc.) for reporting users
- The 39 tools can be individually toggled to match each deployment's needs
### Comparison with Woow Odoo Manage MCP Server
| Aspect | This Bundle (A款) | [Manage MCP Server](https://github.com/WOOWTECH/woow_odoo_manage_mcp_server) (B款) |
|--------|-------------------|-------------------|
| **Best for** | Multi-user application server | Single admin management console |
| **Permission model** | Odoo account ACL (per-user) | YOLO=true (full access, admin only) |
| **Tools** | 39 tools with per-tool toggle | 10 tools with master toggle |
| **Write safety** | 3-step approval (preview→validate→execute) | Direct CRUD |
| **Connection auth** | Username + Password | API Key or Password |
| **Use case** | Distribute to team members | Admin-only operations console |
---
## Related Projects
- [odoo-mcp-server](https://pypi.org/project/odoo-mcp-server/) — The MCP server that provides 39 tools for interacting with Odoo via XML-RPC
- [Woow Odoo AI Assistant Package](https://github.com/WOOWTECH/Woow_odoo_ai_assistant_package) — Enterprise AI assistant suite for Odoo 18 with ChatGPT, Claude, Gemini integration
- [Model Context Protocol (MCP)](https://modelcontextprotocol.io/) — The open protocol for connecting AI models to data sources
---
## License
This project is licensed under the [MIT License](LICENSE).
Copyright (c) 2026 WOOWTECH
---
## Support
- **GitHub Issues**: [github.com/WOOWTECH/woow_odoo_mcp_server/issues](https://github.com/WOOWTECH/woow_odoo_mcp_server/issues)
- **Email**: dev@woowtech.io
- **Website**: [woowtech.io](https://woowtech.io)
---
<p align="center">
Built with care by <a href="https://woowtech.io">WOOWTECH</a>
</p>
This server cannot be deployed
Maintenance
ActivityMaintained
ResponsivenessNo issues