MOHAN 198b5f1b90 Migrate MCP transport to Streamable HTTP, add session sweeper, CORS, public URL config
Replaces the old SseServerTransport (broken against current MCP clients —
405s on POST, session-id redirects, no protocol negotiation) with
StreamableHTTPServerTransport. Adds an idle-session sweeper to prevent
abandoned client connections from leaking memory indefinitely, CORS
middleware for browser-based frontend access, and PUBLIC_URL/CORS_ORIGINS
settings so signup responses show the correct connection URL instead of a
placeholder.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-07-01 13:43:34 +05:30

8.3 KiB

Multi-Tenant ODOO MCP — Project Handoff

Live Server

  • Backend URL: https://odoo-mcp.thedomainnest.com/
  • Stack: Python 3.11, FastAPI, uvicorn, SQLite, MCP (SSE transport)
  • Local repo path: e:\MCS_Repos\nodejs_web_dev\mcp_multitenant\Multi-Tenant-ODOO-MCP

Project Structure

Multi-Tenant-ODOO-MCP/
├── src/mt_odoo_mcp/
│   ├── api/routes.py          # REST API endpoints (signup, login, credentials)
│   ├── auth/                  # Auth service, models, crypto (bcrypt + Fernet)
│   ├── client/                # Odoo XML-RPC connection + RPC helpers
│   ├── tools/                 # 60+ MCP tools (connection, discovery, CRUD, workflow, smart)
│   ├── config.py              # Settings loaded from .env
│   ├── server.py              # FastAPI app + MCP SSE transport
│   ├── database.py            # SQLite init
│   └── registry.py            # Per-user connection manager registry
├── frontend/                  # Next.js 14 frontend (see below)
├── .env                       # Server environment variables
├── pyproject.toml             # Python dependencies
└── HANDOFF.md                 # This file

What's Been Done

Backend (Python/FastAPI)

# Fix / Feature File
Fixed bcrypt 5.0 compatibility — replaced passlib with direct bcrypt auth/service.py
Fixed missing email-validator dependency pyproject.toml
Fixed bad config import in auth service auth/service.py
Added CORSMiddleware — allows browser requests from frontend server.py
Added public_url and cors_origins config fields config.py
Fixed hardcoded http://<your-vps-host>:<port>/mcp/sse in signup & regen-key API responses api/routes.py

Frontend (Next.js 14)

Location: frontend/

# Page / File Description
Landing page Hero, Features, How It Works, Pricing, Footer
Navbar Responsive with mobile menu
Pricing section 4 tiers — Starter $19, Pro $49, Agency $149, Enterprise Custom
Signup page Form → API key reveal with copy-to-clipboard
Login page Email + password form
Dashboard layout Dark sidebar, all nav items, mobile responsive
Dashboard home Stats cards, usage chart, quick actions, recent activity log
Odoo Connections page List, add, and delete Odoo instances
MCP Endpoints page URL + token copy buttons, Claude/Codex/Cursor setup JSON config
Billing page Current plan, plan switcher, invoice history
Stripe Checkout API route Creates Stripe Checkout session with 7-day trial
Stripe Webhook API route Handles subscription created/updated/cancelled events
Typed API client All calls wired to live backend
.env.local Configured to point to https://odoo-mcp.thedomainnest.com
Production build next build passes with zero errors

What Still Needs To Be Done

🔴 Critical — Must Do Before Frontend Works

1. Deploy backend changes to the server

Three Python files were changed locally and must be pushed to the server:

  • src/mt_odoo_mcp/server.py
  • src/mt_odoo_mcp/config.py
  • src/mt_odoo_mcp/api/routes.py

Add these 2 lines to the server .env file:

PUBLIC_URL=https://odoo-mcp.thedomainnest.com
CORS_ORIGINS=http://localhost:3000,https://YOUR-FRONTEND-DOMAIN.com

Then restart the service:

# whichever process manager is used on the server:
systemctl restart odoo-mcp
# or
pm2 restart odoo-mcp

2. Change SECRET_KEY on the server

The current SECRET_KEY in .env is still the default placeholder — this is a security risk.

SECRET_KEY=<replace with a long random string, e.g. output of: openssl rand -hex 32>

🟡 Stripe Integration

3. Create Stripe products and prices

In the Stripe Dashboard → Products, create 3 recurring monthly products:

Product Price
Starter $19/month
Pro $49/month
Agency $149/month

Copy the price_xxx IDs and fill in frontend/.env.local:

NEXT_PUBLIC_STRIPE_PUBLISHABLE_KEY=pk_live_...
STRIPE_SECRET_KEY=sk_live_...
STRIPE_WEBHOOK_SECRET=whsec_...
STRIPE_PRICE_STARTER=price_...
STRIPE_PRICE_PRO=price_...
STRIPE_PRICE_AGENCY=price_...

4. Add subscription fields to the backend users table

Add these columns to the SQLite users table:

ALTER TABLE users ADD COLUMN plan TEXT DEFAULT 'free';
ALTER TABLE users ADD COLUMN subscription_status TEXT DEFAULT 'inactive';
ALTER TABLE users ADD COLUMN stripe_customer_id TEXT;

Add a new API endpoint PATCH /api/admin/subscription (internal, called by the webhook) that updates these fields when Stripe confirms payment.

5. Wire Stripe webhook to backend

The webhook handler at frontend/src/app/api/stripe/webhook/route.ts already parses Stripe events. Add a fetch() call inside the switch cases to hit the backend endpoint from step 4.

6. Gate MCP access on subscription status

In server.py, inside the /mcp/sse endpoint, after the user is looked up, add a check:

if user.subscription_status not in ('active', 'trialing'):
    raise HTTPException(status_code=403, detail="Active subscription required.")

🟢 Remaining Dashboard Pages

Page Route Description
AI Setup Guides /dashboard/guides Step-by-step setup for Claude, Codex, Cursor, Windsurf
Tools & Permissions /dashboard/tools Toggle which Odoo tools are enabled per module
Usage /dashboard/usage Detailed usage graphs with date range filter
Logs /dashboard/logs Activity log table with search and filters
API Tokens /dashboard/tokens View key prefix, rotate API key button
Team /dashboard/team Invite team members (needs backend multi-user support)
Settings /dashboard/settings Change password, account preferences

🟢 Deploy Frontend

cd frontend
npm install -g vercel
vercel --prod
  • Set all env vars from frontend/.env.local inside Vercel project settings
  • After deploy, add the Vercel domain to CORS_ORIGINS in the server .env and restart

How to Run Locally

Backend (already running on server — skip if not developing backend)

pip install -e .
cp .env.example .env   # fill in values
python -m mt_odoo_mcp

Frontend

cd frontend
npm install
npm run dev
# → http://localhost:3000
# API calls go to https://odoo-mcp.thedomainnest.com

API Reference (Backend)

Method Endpoint Auth Description
GET /health None Health check
POST /api/signup None Create account, returns API key
POST /api/login None Verify credentials
GET /api/me Bearer Current user + Odoo instances
POST /api/api-key/regenerate Bearer Rotate API key
POST /api/credentials Bearer Add/update Odoo instance
GET /api/credentials Bearer List Odoo instances
DELETE /api/credentials/{name} Bearer Remove Odoo instance
GET /mcp/sse Bearer MCP SSE connection (used by AI clients)

Auth header format: Authorization: Bearer mtom_xxxxx...


MCP Client Config (Claude Code / Claude Desktop)

{
  "mcpServers": {
    "odoo-mcp": {
      "type": "sse",
      "url": "https://odoo-mcp.thedomainnest.com/mcp/sse",
      "headers": {
        "Authorization": "Bearer YOUR_API_KEY"
      }
    }
  }
}

Or via CLI:

claude mcp add --transport sse odoo-mcp https://odoo-mcp.thedomainnest.com/mcp/sse \
  -H "Authorization: Bearer YOUR_API_KEY"

Implementation Priority for Colleague

  1. Deploy backend changes + update .env on server → restart ← unblocks everything
  2. Test signup → dashboard → add Odoo connection end to end
  3. Set up Stripe, fill in price IDs in frontend/.env.local
  4. Add subscription columns to SQLite + /api/admin/subscription endpoint
  5. Wire webhook to backend endpoint
  6. Deploy frontend to Vercel
  7. Build remaining dashboard pages (guides, tools, usage, logs, tokens, settings)