Skip to main content
Glama

Odoo MCP Server Advanced

by AlanOgic
TRANSPORTS.mdβ€’18.9 kB
# MCP Transport Options The Odoo MCP Server supports three transport mechanisms for different use cases: | Transport | Use Case | Port | Clients | |-----------|----------|------|---------| | **STDIO** | Claude Desktop, CLI tools | N/A | Process pipes | | **SSE** | Web browsers, HTTP clients | 8009 | EventSource, curl | | **Streamable HTTP** | API integrations, programmatic | 8008 | httpx, fetch API | ## STDIO Transport (Default) **Best for:** Claude Desktop, command-line tools, local integrations **Characteristics:** - Process-to-process communication via stdin/stdout - No network exposure - Lowest latency - Default transport for Claude Desktop ### Setup ```bash # Install package pip install -e . # Run directly python run_server.py # Or use installed command odoo-mcp ``` ### Claude Desktop Configuration ```json { "mcpServers": { "odoo": { "command": "python", "args": ["-m", "odoo_mcp"], "env": { "ODOO_URL": "https://your-instance.odoo.com", "ODOO_DB": "your-database", "ODOO_USERNAME": "your-username", "ODOO_PASSWORD": "your-password" } } } } ``` ## SSE Transport (Server-Sent Events) **Best for:** Web browsers, real-time dashboards, streaming updates **Characteristics:** - One-way server-to-client streaming over HTTP - Works with EventSource API in browsers - Simple HTTP GET requests - No WebSocket required ### Setup ```bash # Install package pip install -e . # Run SSE server python run_server_sse.py # With custom configuration MCP_HOST=localhost MCP_PORT=9000 MCP_SSE_PATH=/events python run_server_sse.py ``` ### Environment Variables | Variable | Default | Description | |----------|---------|-------------| | `MCP_HOST` | 0.0.0.0 | Host to bind to | | `MCP_PORT` | 8009 | Port to listen on | | `MCP_SSE_PATH` | /sse | SSE endpoint path | ### Docker ```bash # Build docker build -t alanogic/mcp-odoo-adv:sse -f Dockerfile.sse . # Run docker run -p 8009:8009 \ -e ODOO_URL=https://your-instance.odoo.com \ -e ODOO_DB=your-database \ -e ODOO_USERNAME=your-username \ -e ODOO_PASSWORD=your-password \ alanogic/mcp-odoo-adv:sse # Or with .env file docker run -p 8009:8009 --env-file .env alanogic/mcp-odoo-adv:sse ``` ### Client Examples **JavaScript (Browser)** ```javascript const eventSource = new EventSource('http://localhost:8009/sse'); eventSource.onmessage = (event) => { const data = JSON.parse(event.data); console.log('Received:', data); }; eventSource.onerror = (error) => { console.error('SSE Error:', error); }; ``` **Python** ```python import requests with requests.get('http://localhost:8009/sse', stream=True) as response: for line in response.iter_lines(): if line: print(line.decode('utf-8')) ``` **curl** ```bash curl -N http://localhost:8009/sse ``` ## Streamable HTTP Transport **Best for:** API integrations, programmatic access, bidirectional streaming **Characteristics:** - Full bidirectional streaming over HTTP - Works with standard HTTP clients - POST requests with streaming bodies - Suitable for server-to-server communication ### Setup ```bash # Install package pip install -e . # Run HTTP server python run_server_http.py # With custom configuration MCP_HOST=localhost MCP_PORT=9000 MCP_HTTP_PATH=/api python run_server_http.py ``` ### Environment Variables | Variable | Default | Description | |----------|---------|-------------| | `MCP_HOST` | 0.0.0.0 | Host to bind to | | `MCP_PORT` | 8008 | Port to listen on | | `MCP_HTTP_PATH` | /mcp | HTTP endpoint path | ### Docker ```bash # Build docker build -t alanogic/mcp-odoo-adv:http -f Dockerfile.http . # Run docker run -p 8008:8008 \ -e ODOO_URL=https://your-instance.odoo.com \ -e ODOO_DB=your-database \ -e ODOO_USERNAME=your-username \ -e ODOO_PASSWORD=your-password \ alanogic/mcp-odoo-adv:http # Or with .env file docker run -p 8008:8008 --env-file .env alanogic/mcp-odoo-adv:http ``` ### Client Examples **Python (httpx)** ```python import httpx import json async with httpx.AsyncClient() as client: request_data = { "jsonrpc": "2.0", "method": "tools/list", "params": {}, "id": 1 } async with client.stream( 'POST', 'http://localhost:8008/mcp', json=request_data, headers={'Content-Type': 'application/json'} ) as response: async for line in response.aiter_lines(): if line: print(json.loads(line)) ``` **JavaScript (fetch)** ```javascript const response = await fetch('http://localhost:8008/mcp', { method: 'POST', headers: {'Content-Type': 'application/json'}, body: JSON.stringify({ jsonrpc: '2.0', method: 'tools/list', params: {}, id: 1 }) }); const reader = response.body.getReader(); while (true) { const {done, value} = await reader.read(); if (done) break; console.log(new TextDecoder().decode(value)); } ``` **curl** ```bash curl -X POST http://localhost:8008/mcp \ -H "Content-Type: application/json" \ -d '{"jsonrpc":"2.0","method":"tools/list","params":{},"id":1}' ``` ## Production Deployment ### Nginx Reverse Proxy For production deployments, use Nginx as a reverse proxy to add SSL, authentication, and rate limiting. ```nginx # /etc/nginx/sites-available/mcp-odoo upstream mcp_sse { server 127.0.0.1:8009; } upstream mcp_http { server 127.0.0.1:8008; } server { listen 443 ssl http2; server_name mcp.yourdomain.com; ssl_certificate /etc/letsencrypt/live/mcp.yourdomain.com/fullchain.pem; ssl_certificate_key /etc/letsencrypt/live/mcp.yourdomain.com/privkey.pem; # SSE endpoint location /sse { proxy_pass http://mcp_sse; proxy_http_version 1.1; proxy_set_header Upgrade $http_upgrade; proxy_set_header Connection ''; proxy_set_header Host $host; proxy_cache_bypass $http_upgrade; # SSE-specific settings proxy_buffering off; proxy_read_timeout 24h; chunked_transfer_encoding off; } # Streamable HTTP endpoint location /mcp { proxy_pass http://mcp_http; proxy_http_version 1.1; proxy_set_header Host $host; proxy_set_header X-Real-IP $remote_addr; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; proxy_set_header X-Forwarded-Proto $scheme; # Streaming settings proxy_buffering off; proxy_request_buffering off; client_max_body_size 100M; } } ``` ### Security Configurations #### Option 1: API Key Authentication Secure endpoints with custom API key headers. ```nginx # /etc/nginx/sites-available/mcp-odoo-secure # Define API key (store in separate file for production) map $http_x_api_key $api_key_valid { default 0; "your-secret-api-key-here" 1; } upstream mcp_http { server 127.0.0.1:8008; } server { listen 443 ssl http2; server_name mcp.yourdomain.com; ssl_certificate /etc/letsencrypt/live/mcp.yourdomain.com/fullchain.pem; ssl_certificate_key /etc/letsencrypt/live/mcp.yourdomain.com/privkey.pem; # Streamable HTTP endpoint with API key auth location /mcp { # Validate API key if ($api_key_valid = 0) { return 401 '{"error": "Unauthorized - Invalid or missing API key"}'; } proxy_pass http://mcp_http; proxy_http_version 1.1; proxy_set_header Host $host; proxy_set_header X-Real-IP $remote_addr; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; # Streaming settings proxy_buffering off; proxy_request_buffering off; client_max_body_size 100M; } } ``` **Client Usage:** ```bash # curl with API key curl -X POST https://mcp.yourdomain.com/mcp \ -H "X-API-Key: your-secret-api-key-here" \ -H "Content-Type: application/json" \ -d '{"jsonrpc":"2.0","method":"tools/list","params":{},"id":1}' ``` ```python # Python with API key import httpx headers = { "X-API-Key": "your-secret-api-key-here", "Content-Type": "application/json" } async with httpx.AsyncClient() as client: response = await client.post( "https://mcp.yourdomain.com/mcp", headers=headers, json={"jsonrpc": "2.0", "method": "tools/list", "params": {}, "id": 1} ) ``` #### Option 2: Basic Authentication Simple username/password authentication. ```nginx # /etc/nginx/sites-available/mcp-odoo-basic-auth upstream mcp_http { server 127.0.0.1:8008; } server { listen 443 ssl http2; server_name mcp.yourdomain.com; ssl_certificate /etc/letsencrypt/live/mcp.yourdomain.com/fullchain.pem; ssl_certificate_key /etc/letsencrypt/live/mcp.yourdomain.com/privkey.pem; location /mcp { # Basic authentication auth_basic "MCP Server - Restricted Access"; auth_basic_user_file /etc/nginx/.htpasswd; proxy_pass http://mcp_http; proxy_http_version 1.1; proxy_set_header Host $host; # Streaming settings proxy_buffering off; proxy_request_buffering off; } } ``` **Setup Basic Auth:** ```bash # Install apache2-utils for htpasswd sudo apt-get install apache2-utils # Create password file (first user) sudo htpasswd -c /etc/nginx/.htpasswd mcpuser # Add additional users sudo htpasswd /etc/nginx/.htpasswd anotheruser # Set proper permissions sudo chmod 640 /etc/nginx/.htpasswd sudo chown root:www-data /etc/nginx/.htpasswd ``` **Client Usage:** ```bash # curl with basic auth curl -X POST https://mcp.yourdomain.com/mcp \ -u mcpuser:password \ -H "Content-Type: application/json" \ -d '{"jsonrpc":"2.0","method":"tools/list","params":{},"id":1}' ``` ```python # Python with basic auth import httpx async with httpx.AsyncClient() as client: response = await client.post( "https://mcp.yourdomain.com/mcp", auth=("mcpuser", "password"), json={"jsonrpc": "2.0", "method": "tools/list", "params": {}, "id": 1} ) ``` #### Option 3: Mutual TLS (mTLS) Certificate-based authentication for maximum security. ```nginx # /etc/nginx/sites-available/mcp-odoo-mtls upstream mcp_http { server 127.0.0.1:8008; } server { listen 443 ssl http2; server_name mcp.yourdomain.com; # Server certificate ssl_certificate /etc/nginx/certs/server.crt; ssl_certificate_key /etc/nginx/certs/server.key; # Client certificate validation ssl_client_certificate /etc/nginx/certs/ca.crt; ssl_verify_client on; ssl_verify_depth 2; # Optional: Pass client certificate info to backend proxy_set_header X-SSL-Client-Cert $ssl_client_cert; proxy_set_header X-SSL-Client-DN $ssl_client_s_dn; location /mcp { proxy_pass http://mcp_http; proxy_http_version 1.1; proxy_set_header Host $host; # Streaming settings proxy_buffering off; proxy_request_buffering off; } } ``` **Setup mTLS Certificates:** ```bash # 1. Create CA (Certificate Authority) openssl genrsa -out ca.key 4096 openssl req -new -x509 -days 365 -key ca.key -out ca.crt # 2. Create server certificate openssl genrsa -out server.key 4096 openssl req -new -key server.key -out server.csr openssl x509 -req -days 365 -in server.csr -CA ca.crt -CAkey ca.key -set_serial 01 -out server.crt # 3. Create client certificate openssl genrsa -out client.key 4096 openssl req -new -key client.key -out client.csr openssl x509 -req -days 365 -in client.csr -CA ca.crt -CAkey ca.key -set_serial 02 -out client.crt # 4. Create client .p12 bundle (for browser/applications) openssl pkcs12 -export -out client.p12 -inkey client.key -in client.crt -certfile ca.crt # 5. Copy certificates to Nginx sudo cp ca.crt server.crt server.key /etc/nginx/certs/ sudo chmod 600 /etc/nginx/certs/*.key ``` **Client Usage:** ```bash # curl with client certificate curl -X POST https://mcp.yourdomain.com/mcp \ --cert client.crt \ --key client.key \ -H "Content-Type: application/json" \ -d '{"jsonrpc":"2.0","method":"tools/list","params":{},"id":1}' ``` ```python # Python with client certificate import httpx async with httpx.AsyncClient( cert=("client.crt", "client.key"), verify="ca.crt" ) as client: response = await client.post( "https://mcp.yourdomain.com/mcp", json={"jsonrpc": "2.0", "method": "tools/list", "params": {}, "id": 1} ) ``` #### Option 4: Combined Security (Recommended) Combine multiple security layers for production. ```nginx # /etc/nginx/sites-available/mcp-odoo-production # Rate limiting limit_req_zone $binary_remote_addr zone=mcp_limit:10m rate=10r/s; # API key validation map $http_x_api_key $api_key_valid { default 0; "prod-api-key-12345" 1; } upstream mcp_http { server 127.0.0.1:8008; } server { listen 443 ssl http2; server_name mcp.yourdomain.com; # SSL configuration ssl_certificate /etc/letsencrypt/live/mcp.yourdomain.com/fullchain.pem; ssl_certificate_key /etc/letsencrypt/live/mcp.yourdomain.com/privkey.pem; ssl_protocols TLSv1.2 TLSv1.3; ssl_ciphers HIGH:!aNULL:!MD5; ssl_prefer_server_ciphers on; # Security headers add_header Strict-Transport-Security "max-age=31536000; includeSubDomains" always; add_header X-Content-Type-Options "nosniff" always; add_header X-Frame-Options "DENY" always; add_header X-XSS-Protection "1; mode=block" always; # Logging access_log /var/log/nginx/mcp_access.log; error_log /var/log/nginx/mcp_error.log; location /mcp { # IP whitelist (adjust for your network) allow 10.0.0.0/8; allow 172.16.0.0/12; allow 192.168.0.0/16; deny all; # Rate limiting limit_req zone=mcp_limit burst=20 nodelay; # API key validation if ($api_key_valid = 0) { return 401 '{"error": "Unauthorized"}'; } # Proxy to MCP server proxy_pass http://mcp_http; proxy_http_version 1.1; proxy_set_header Host $host; proxy_set_header X-Real-IP $remote_addr; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; proxy_set_header X-Forwarded-Proto $scheme; # Streaming settings proxy_buffering off; proxy_request_buffering off; proxy_read_timeout 300s; proxy_send_timeout 300s; client_max_body_size 100M; } } ``` ### Systemd Service Create `/etc/systemd/system/mcp-odoo-sse.service`: ```ini [Unit] Description=Odoo MCP Server (SSE Transport) After=network.target [Service] Type=simple User=mcp WorkingDirectory=/opt/mcp-odoo-adv Environment="ODOO_URL=https://your-instance.odoo.com" Environment="ODOO_DB=your-database" Environment="ODOO_USERNAME=your-username" Environment="ODOO_PASSWORD=your-password" Environment="MCP_HOST=127.0.0.1" Environment="MCP_PORT=8009" ExecStart=/opt/mcp-odoo-adv/.venv/bin/python run_server_sse.py Restart=always RestartSec=10 [Install] WantedBy=multi-user.target ``` Enable and start: ```bash sudo systemctl enable mcp-odoo-sse sudo systemctl start mcp-odoo-sse sudo systemctl status mcp-odoo-sse ``` ## Security Considerations ### Network Exposure | Transport | Network Risk | Recommendations | |-----------|--------------|-----------------| | **STDIO** | None | No network exposure, safe for local use | | **SSE** | High | Use reverse proxy with SSL, authentication, rate limiting | | **HTTP** | High | Use reverse proxy with SSL, authentication, rate limiting | ### Best Practices 1. **Never expose MCP servers directly to the internet** - Always use a reverse proxy (Nginx, Caddy, Traefik) - Implement SSL/TLS for encrypted transport - Add authentication (API keys, OAuth, mTLS) 2. **Implement rate limiting** ```nginx limit_req_zone $binary_remote_addr zone=mcp:10m rate=10r/s; limit_req zone=mcp burst=20 nodelay; ``` 3. **Restrict access by IP** ```nginx allow 10.0.0.0/8; allow 192.168.0.0/16; deny all; ``` 4. **Use environment variables for secrets** - Never hardcode credentials - Use `.env` files or secret management systems - Rotate credentials regularly 5. **Monitor and log** - Enable request logging - Monitor for unusual patterns - Set up alerts for errors ## Troubleshooting ### SSE Connection Issues **Problem:** EventSource connection fails **Solutions:** ```bash # Check if server is running curl -v http://localhost:8009/sse # Verify port is listening netstat -an | grep 8009 # Check firewall rules sudo ufw status # Review logs tail -f logs/mcp_server_sse_*.log ``` ### HTTP Streaming Issues **Problem:** Stream terminates prematurely **Solutions:** ```bash # Disable proxy buffering in Nginx proxy_buffering off; proxy_request_buffering off; # Increase timeouts proxy_read_timeout 300s; proxy_send_timeout 300s; # Check client timeout settings ``` ### Port Already in Use **Problem:** `Address already in use` **Solutions:** ```bash # Find process using port 8009 (SSE) or 8008 (HTTP) lsof -i :8009 lsof -i :8008 # Kill the process kill -9 <PID> # Or use a different port MCP_PORT=8010 python run_server_sse.py MCP_PORT=8007 python run_server_http.py ``` ### CORS Issues (Browser Clients) **Problem:** CORS errors in browser console **Solutions:** Add CORS headers in Nginx: ```nginx add_header Access-Control-Allow-Origin *; add_header Access-Control-Allow-Methods 'GET, POST, OPTIONS'; add_header Access-Control-Allow-Headers 'Content-Type'; ``` Or configure in FastMCP (if supported in future versions). ## Performance Comparison | Metric | STDIO | SSE | Streamable HTTP | |--------|-------|-----|-----------------| | **Latency** | <1ms | 10-50ms | 10-50ms | | **Throughput** | Very High | High | High | | **Overhead** | Minimal | HTTP headers | HTTP headers | | **Scalability** | 1 client | Many clients | Many clients | | **Network** | None | Required | Required | ## Choosing the Right Transport ```mermaid graph TD A[Choose Transport] --> B{Local only?} B -->|Yes| C[STDIO] B -->|No| D{Client type?} D -->|Browser| E[SSE] D -->|API/Server| F[Streamable HTTP] D -->|CLI Tool| C ``` **Use STDIO when:** - Integrating with Claude Desktop - Building CLI tools - No network access needed - Maximum performance required **Use SSE when:** - Building web dashboards - Real-time browser updates - Simple client implementation - One-way data flow sufficient **Use Streamable HTTP when:** - Building API integrations - Server-to-server communication - Bidirectional streaming needed - Standard HTTP client compatibility required ## Additional Resources - [FastMCP Documentation](https://github.com/jlowin/fastmcp) - [MCP Specification](https://modelcontextprotocol.io) - [SSE MDN Documentation](https://developer.mozilla.org/en-US/docs/Web/API/Server-sent_events) - [HTTP Streaming Best Practices](https://web.dev/streams/)

Latest Blog Posts

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/AlanOgic/mcp-odoo-adv'

If you have feedback or need assistance with the MCP directory API, please join our Discord server