Drivo MCP
Click on "Deploy Server".
Wait a few minutes for the server to deploy. Once ready, it will show a "Started" state.
In the chat, type
@followed by the MCP server name and your instructions, e.g., "@Drivo MCPFind available 2023 Toyota RAV4 hybrids under $35k"
That's it! The server will respond to your query, and you can continue using it as needed.
Here is a step-by-step guide with screenshots.
Drivo MCP
A secure, domain-oriented Model Context Protocol server for the Drivo — Dealer Business Platform (Odoo-based DMS for vehicle inventory, CRM, deals, finance, service). Works with Claude, ChatGPT, Cursor and any MCP client.
Drivo MCP deliberately exposes business tools (
drivo_search_vehicles,drivo_create_lead, …). There is noodoo_execute_kw,odoo_write, SQL, Python or shell tool, and there never will be.
Registry name: biz.drivo/drivo-erp · Remote endpoint: https://mcp.drivo.biz/mcp
Architecture
MCP client (Claude / ChatGPT / Cursor)
│ Streamable HTTP (Authorization: Bearer <MCP key>) or stdio
▼
┌───────────────────────── Drivo MCP ─────────────────────────┐
│ authN → scope check → zod validation → company scope │
│ → rate limit → [confirmation] → [idempotency] → handler │
│ → company filter → internal-figure stripping → audit │
└───────────────┬─────────────────────────────────────────────┘
│ HTTPS, per-principal Drivo bearer token
▼
Drivo API / service layer (/api/v1/*, RBAC + company scope)
▼
Odoo ORM / business logic → PostgreSQL (never reachable from MCP)Related MCP server: openapi-to-mcp
Tools
Tool | Scope | Kind |
|
| read |
|
| read |
|
| read |
|
| write (idempotent) |
|
| read |
|
| high-risk write (confirmation + idempotent) |
|
| read |
|
| read |
|
| write (idempotent) |
|
| read |
Resources: drivo://vehicle/{id}, drivo://customer/{id} (same authorisation path as the tools).
drivo.admin implies all scopes but never bypasses company scope.
Security model
AuthN:
Authorization: Bearer <key>orX-API-Key. Keys are matched by SHA-256 hash, constant-time.AuthZ: per-tool scope. Upstream RBAC stays authoritative: each principal maps to a dedicated Drivo user whose bearer token is used for every upstream call, so Drivo's own role + company rules apply.
Company isolation: a principal has a company allowlist. A call naming another company is refused before any upstream request; responses are additionally filtered/denied if any record carries a
company_idoutside the active company (foreign records surface asnot_found). Limitation: the Drivo API derives company from the token's user, socompany_idacts as an assertion + filter, not a switch. Use one principal (user) per company for multi-company dealers.Writes:
idempotency_keyrequired (replays return the stored result; same key + different args →idempotency_conflict; failures are not cached; writes are never auto-retried).High-risk writes (
drivo_create_booking): step 1 returns a preview and an HMAC-signed 5-minute token bound to principal + tool + exact arguments; step 2 repeats the call with the token.Output hygiene: cost / landed cost / commission / margin / profit fields are stripped unless the principal holds
drivo.finance.read.Safe errors: clients only see stable error codes and short messages; upstream bodies, stack traces, hostnames and tokens never leave the server.
Audit: one structured JSON event per call (request id, principal, user, company, tool, outcome, duration, idempotency key, redacted + length-capped input). Secrets are redacted by key and value shape.
Rate limiting: per-principal read and write budgets (pluggable
RateLimiter), plus per-IP throttling of failed authentication.Transport guards: Host/Origin allowlists, 1 MB body cap, stateless sessions.
See SECURITY.md.
Install & configure
Requires Node ≥ 20.
npm ci
cp .env.example .env # fill in; never commit
cp principals.example.json principals.json # never commit
npm run hash-key # prints a new key + its hash for principals.jsonprincipals.json entry fields: id, keyHash, userId, scopes[], companyIds[],
defaultCompanyId, upstreamTokenEnv (name of the env var holding that principal's Drivo bearer
token, obtained from POST /api/v1/auth/login for a least-privilege Drivo user).
Environment variables
Variable | Required | Purpose |
| ✔ | Drivo API base, e.g. |
| ✔ | Path to principals JSON |
| ✔ | ≥16-char secret signing confirmation tokens |
| ✔ | One per principal: its Drivo bearer token |
|
| |
| stdio | The key to authenticate as in stdio mode |
| default | |
| comma lists; set in production | |
| default 15000 | |
| default 60 / 20 | |
| `debug |
Run
npm run build && npm start # remote mode on :3000 (GET /healthz, /readyz; POST /mcp)
npm run dev # tsx, no buildDocker
docker build -t drivo-mcp .
docker run --rm -p 3000:3000 --env-file .env \
-v $PWD/principals.json:/run/secrets/drivo-mcp-principals.json:ro drivo-mcpThe image runs as non-root, has a HEALTHCHECK on /healthz, and uses tini so SIGTERM
triggers graceful shutdown (readiness flips to 503, in-flight requests drain ≤10 s).
Client configuration
Claude Desktop / Claude Code (remote):
claude mcp add --transport http drivo https://mcp.drivo.biz/mcp --header "Authorization: Bearer $DRIVO_MCP_KEY"Cursor (~/.cursor/mcp.json):
{ "mcpServers": { "drivo": { "url": "https://mcp.drivo.biz/mcp", "headers": { "Authorization": "Bearer ${env:DRIVO_MCP_KEY}" } } } }Local stdio:
{ "mcpServers": { "drivo": { "command": "node", "args": ["/path/to/drivo-mcp/dist/index.js"],
"env": { "MCP_TRANSPORT": "stdio", "DRIVO_API_BASE_URL": "https://demo.drivo.biz",
"DRIVO_MCP_PRINCIPALS_FILE": "/path/principals.json", "DRIVO_MCP_API_KEY": "…",
"DRIVO_MCP_CONFIRM_SECRET": "…", "DRIVO_UPSTREAM_TOKEN_EXAMPLE_PRINCIPAL": "…" } } } }Development & testing
npm run typecheck
npm test # unit + security + end-to-end over real HTTP with a fake Drivo upstreamTests cover authentication, permission denial, company isolation, invalid inputs, read/write tools, idempotency (incl. concurrency), API failure, timeouts, rate limiting, secret leakage and audit logging.
MCP Inspector
npm run build
MCP_TRANSPORT=stdio DRIVO_MCP_API_KEY=… … npx @modelcontextprotocol/inspector node dist/index.js
# remote: npx @modelcontextprotocol/inspector → Streamable HTTP → https://mcp.drivo.biz/mcp, header AuthorizationRegistry publishing
server.json follows the current schema (2025-12-11) and registers biz.drivo/drivo-erp
(npm package @dynaz/drivo-mcp + the remote https://mcp.drivo.biz/mcp).
One-time: prove ownership of drivo.biz (the biz.drivo namespace) by DNS:
openssl genpkey -algorithm Ed25519 -out key.pem
openssl pkey -in key.pem -pubout -outform DER | tail -c 32 | base64 # -> TXT: drivo.biz. "v=MCPv1; k=ed25519; p=<that>"
openssl pkey -in key.pem -noout -text | grep -A3 "priv:" | tail -n +2 | tr -d ' :\n' # -> GitHub secret MCP_REGISTRY_DNS_PRIVATE_KEYRelease: bump versions in package.json + server.json (all must match), then git tag vX.Y.Z && git push --tags.
publish-mcp.yml runs tests → build → npm publish → mcp-publisher login dns → validate → publish.
Needs the mcp-registry-publish GitHub environment with NPM_TOKEN and MCP_REGISTRY_DNS_PRIVATE_KEY.
Known limits (v0.1)
Idempotency + rate-limit stores are in-memory (single replica). Interfaces are in
src/runtime/.Drivo's POST routes have no server-side idempotency key (except the "open service job already exists" rule), so MCP-level idempotency protects against client retries, not against a lost MCP process restart.
Hosting:
mcp.drivo.bizDNS / reverse proxy are not part of this repo.
License
MIT
This server cannot be deployed
Maintenance
Related MCP Connectors
Let AI agents query data and act across all your business apps via MCP.
API-first CRM for LLMs - contacts, companies, deals and activities over a native MCP server.
Zero-setup MCP gateway securely connecting AI to your tools with authentication and workflows
MCP server unifying ERPs, CRMs, APIs and knowledge base for Claude, ChatGPT and Gemini.
Related MCP Servers
- FlicenseNot gradedqualityCmaintenanceProvides AI agents with 220+ tools for building websites, sending email, managing contacts, invoicing, databases, automation, and more through a single secure connection. Features hardware-bound authentication and works with Claude Desktop, Claude Code, Cursor, and other MCP-compatible clients.-
- AlicenseNot gradedqualityCmaintenanceTurns any OpenAPI/Swagger or REST API into callable MCP tools for Claude, ChatGPT, Copilot, and Cursor, with secure authentication and role-based access control.22 npmAGPL 3.0
- AlicenseAqualityCmaintenanceEnables Claude, ChatGPT and other MCP clients to read an Amiqus ID account—clients, onboarding records and steps, check results, templates, case status counts and webhooks—and, when writes are enabled, create records.9MIT
- AlicenseBqualityCmaintenanceEnables Claude, ChatGPT and other MCP clients to read practice-management data including organization, clinicians, diaries, availability, bookings, patients, invoices, payments, staff tasks, services, and locations, and optionally create staff tasks, create bookings, and cancel bookings.15MIT