Server data from the Official MCP Registry
Public wine registry and guides: search wines, grapes, regions, appellations. No account.
Public wine registry and guides: search wines, grapes, regions, appellations. No account.
Remote endpoints: streamable-http: https://cellarion.app/api/mcp/public
Valid MCP server (1 strong, 0 medium validity signals). No known CVEs in dependencies. Imported from the Official MCP Registry.
7 tools verified · Open access · No issues found
Security scores are indicators to help you make informed decisions, not guarantees. Always review permissions before connecting any MCP server.
This plugin requests these system permissions. Most are normal for its category.
Remote Plugin
No local installation needed. Your AI client connects to the remote endpoint directly.
Add this to your MCP configuration to connect:
{
"mcpServers": {
"app-cellarion-wine-registry": {
"url": "https://cellarion.app/api/mcp/public"
}
}
}From the project's GitHub README.
Cellarion is a hosted wine cellar app — a ready-to-use online service at cellarion.app. Create a free account and start tracking your bottles, organizing them into cellars and racks, searching a shared wine registry, getting drink-window recommendations, and chatting with an AI sommelier about your collection. No installation, no server, no setup — just sign up and go. Every feature is free, forever.
Just want to use Cellarion? Go to cellarion.app and sign up. You do not need to clone this repository, run Docker, or host anything yourself.
Cellarion is also open-source (AGPL-3.0), so if you'd prefer to run your own private instance, you can self-host it. The rest of this README covers self-hosting — see Quick Start. Most people should just use the hosted service at cellarion.app.
Cellarion is live and publicly available at:
This is the primary way to use Cellarion. Create an account and start using the full service today — every feature is free, forever. No credit card, no trial clock, no paywalled features, nothing to install or maintain.
/api/ to the backend (internal)This section is only for people who want to run their own private instance. If you just want to use Cellarion, head to cellarion.app instead — no setup required.
The app is routed through Traefik, so create the external web Docker network before the first up (compose declares it external — the first command fails otherwise):
git clone https://github.com/jagduvi1/Cellarion.git
cd Cellarion
cp .env.example .env
# Edit .env and set JWT_SECRET and MEILI_MASTER_KEY to strong random strings
docker network create web # once; skip if it already exists
docker-compose up --build
| URL | Description |
|---|---|
| http://localhost | Frontend (React SPA) — served via Traefik |
| http://localhost/api/health | Backend health check |
After the containers are running:
docker exec cellarion-backend node src/seed-demo.js
This creates:
| Account | Password | Role | |
|---|---|---|---|
| Admin | admin@cellarion.app | Admin1234!demo | admin |
| Demo user | user@cellarion.app | User1234!demo | user |
…plus 2 countries, 2 regions, 5 grape varieties, 2 wine definitions, and a demo cellar with sample bottles.
These are local development credentials. Change them before deploying anywhere public.
docker-compose down # keep data
docker-compose down -v # also remove all volumes (wipes database)
Cellarion/
├── backend/
│ ├── src/
│ │ ├── config/
│ │ │ ├── aiConfig.js # AI chat feature flags, model config, daily limits
│ │ │ ├── db.js # MongoDB connection
│ │ │ ├── plans.js # Supporter tier config (all features free)
│ │ │ └── upload.js # Multer config
│ │ ├── middleware/
│ │ │ ├── auth.js # JWT + role middleware (requireAuth, requireAdmin, requireSomm)
│ │ │ └── bottleAccess.js # requireBottleAccess(minRole) factory
│ │ ├── models/ # 22 Mongoose schemas
│ │ │ ├── User.js
│ │ │ ├── WineDefinition.js # Shared wine registry (vintage-neutral)
│ │ │ ├── Bottle.js # User-owned bottle records
│ │ │ ├── Cellar.js
│ │ │ ├── Rack.js # 8×4 grid rack layout
│ │ │ ├── AuditLog.js
│ │ │ ├── BottleImage.js # Bottle photo metadata
│ │ │ ├── WineVintageProfile.js
│ │ │ ├── WineVintagePrice.js
│ │ │ ├── WineRequest.js
│ │ │ ├── WineReport.js # User-submitted wine quality reports
│ │ │ ├── WineEmbedding.js # Vector embedding tracking for RAG
│ │ │ ├── Country.js
│ │ │ ├── Region.js
│ │ │ ├── Appellation.js # Wine appellations (e.g. Barolo, Châteauneuf-du-Pape)
│ │ │ ├── Grape.js
│ │ │ ├── ChatUsage.js # Daily AI chat usage per user
│ │ │ ├── Notification.js # In-app notifications
│ │ │ ├── SupportTicket.js # User support tickets
│ │ │ ├── SiteConfig.js # Global admin settings
│ │ │ ├── ImportSession.js # Persisted bottle import state
│ │ │ └── ExchangeRateSnapshot.js # Cached currency exchange rates
│ │ ├── routes/
│ │ │ ├── auth.js # /api/auth/*
│ │ │ ├── cellars.js # /api/cellars/*
│ │ │ ├── bottles.js # /api/bottles/*
│ │ │ ├── wines.js # /api/wines/*
│ │ │ ├── racks.js # /api/racks/*
│ │ │ ├── wineRequests.js # /api/wine-requests/*
│ │ │ ├── wineReports.js # /api/wine-reports/*
│ │ │ ├── import.js # /api/bottles/import/*
│ │ │ ├── chat.js # /api/chat (AI cellar chat)
│ │ │ ├── stats.js # /api/stats/overview
│ │ │ ├── notifications.js # /api/notifications
│ │ │ ├── support.js # /api/support
│ │ │ ├── settings.js # /api/settings
│ │ │ ├── images.js # /api/images/*
│ │ │ ├── users.js # /api/users/*
│ │ │ ├── health.js # /api/health
│ │ │ ├── superadmin.js # /api/superadmin/* (super admin only)
│ │ │ ├── admin/ # /api/admin/* (admin role)
│ │ │ └── somm/ # /api/somm/* (sommelier features)
│ │ ├── services/
│ │ │ ├── aiChat.js # RAG pipeline: embed → Qdrant → Claude response
│ │ │ ├── audit.js # Audit logging
│ │ │ ├── embedding.js # Voyage AI embedding generation
│ │ │ ├── findOrCreateWine.js # Intelligent wine lookup/creation
│ │ │ ├── imageProcessor.js # Background removal via rembg
│ │ │ ├── labelScan.js # Anthropic Vision API for label scanning
│ │ │ ├── notifications.js # Notification creation for key events
│ │ │ ├── search.js # Meilisearch integration
│ │ │ ├── statsService.js # Stats computation
│ │ │ └── vectorStore.js # Qdrant REST client for vector search
│ │ ├── utils/
│ │ │ ├── cellarAccess.js # Ownership verification
│ │ │ ├── drinkWindow.js # classifyDrinkWindow() shared helper
│ │ │ ├── normalize.js # Wine name dedup & fuzzy matching
│ │ │ └── ratingUtils.js # Rating scale conversion + resolveRating()
│ │ ├── data/ # Taxonomy reference JSON files
│ │ └── seed-demo.js # Demo data seeder
│ └── Dockerfile
├── frontend/
│ ├── src/
│ │ ├── api/ # API client wrappers
│ │ │ ├── admin.js # Admin endpoints (wine reports, rate limits, etc.)
│ │ │ ├── bottles.js # getBottle, updateBottle, consumeBottle, import
│ │ │ ├── cellars.js # getCellar, updateCellar, deleteCellar, …
│ │ │ ├── importSessions.js # Import session management
│ │ │ ├── racks.js # getRacks, deleteRack, updateSlot, clearSlot
│ │ │ ├── support.js # Support tickets & wine reports
│ │ │ └── wines.js # searchWines, getWine, scanLabel
│ │ ├── components/
│ │ │ ├── BottleCard.js # Bottle row/card (list + grid view)
│ │ │ ├── CellarionLogo.js # Brand SVG logo component
│ │ │ ├── Layout.js # Persistent navbar + bottom nav + mobile menu
│ │ │ ├── Modal.js # Shared modal overlay
│ │ │ ├── NotificationBell.js # Notification dropdown with unread badge
│ │ │ ├── ReportWineModal.js # Wine quality report modal
│ │ │ ├── SupportModal.js # Support ticket submission modal
│ │ │ ├── ProtectedRoute.js
│ │ │ └── ErrorBoundary.js
│ │ ├── contexts/
│ │ │ ├── AuthContext.js # Global auth state
│ │ │ ├── ThemeContext.js # Dark/light mode with system preference detection
│ │ │ └── NotificationContext.js # Notification polling & unread count
│ │ ├── pages/ # App screens
│ │ │ ├── LandingPage.js # Public landing page
│ │ │ ├── Login.js # Auth (login/register)
│ │ │ ├── VerifyEmail.js # Email verification
│ │ │ ├── ResetPassword.js # Password reset flow
│ │ │ ├── CellarChat.js # AI cellar chat interface
│ │ │ ├── Statistics.js # Analytics dashboard with charts & world map
│ │ │ ├── DrinkAlerts.js # Drink-window alerts by urgency
│ │ │ ├── Plans.js # Supporter tiers (all features free)
│ │ │ ├── Settings.js # User preferences (currency, language, rating scale)
│ │ │ ├── SupportPage.js # Support tickets & wine reports
│ │ │ ├── SommMaturity.js # Sommelier maturity phase management
│ │ │ ├── SommPrices.js # Sommelier pricing data management
│ │ │ ├── SuperAdmin.js # Platform-wide admin dashboard
│ │ │ ├── AdminSupportTickets.js
│ │ │ ├── AdminWineReports.js
│ │ │ └── … # Cellar, bottle, rack, wine pages
│ │ ├── config/
│ │ │ ├── currencies.js
│ │ │ └── plans.js
│ │ ├── utils/ # Frontend helpers
│ │ └── styles/common.css
│ ├── nginx.conf # nginx config (SPA + /api/ proxy)
│ └── Dockerfile # Multi-stage: Node build → nginx-unprivileged
├── rembg/ # Python background-removal service
└── docker-compose.yml
All external traffic enters through Traefik (runs on the shared web Docker network, external to this Compose file). All services inside this Compose file are internal only.
| Service | Host port | Description |
|---|---|---|
| Traefik | 80 | External reverse proxy (external) |
| nginx | internal | Serves React SPA + proxies /api/ |
| Backend | internal | Express REST API (port 5000) |
| MongoDB | internal | Database (port 27017) |
| Meilisearch | internal | Fuzzy search engine (port 7700) |
| Qdrant | internal | Vector database (port 6333) |
| rembg | internal | Background removal (port 5000) |
Cellarion is designed to sit behind a Traefik reverse proxy on a shared Docker network called web. Traefik handles incoming HTTP on port 80 (SSL termination is handled upstream by Cloudflare or similar).
Requirements:
webweb network must exist before starting Cellarion: docker network create webThe frontend service declares the following Traefik labels in docker-compose.yml:
traefik.enable: "true"
traefik.docker.network: "web"
traefik.http.routers.cellarion.rule: "Host(`cellarion.app`)"
traefik.http.routers.cellarion.entrypoints: "web"
traefik.http.services.cellarion.loadbalancer.server.port: "8080"
The upstream port is 8080 (not 80): the frontend image is built on
nginxinc/nginx-unprivileged, whose non-root nginx cannot bind ports below 1024.
Update the Host(...) rule to match your own domain.
| Entity | Description |
|---|---|
| WineDefinition | Vintage-neutral wine entry in the shared registry. Admins create and manage these. |
| Bottle | A user's bottle: references a WineDefinition and adds vintage, price, rating, notes, rack location. |
| Cellar | Named container of Bottles, owned by a user. Can be shared with other users via role-based access. |
| Rack | 8×4 grid within a Cellar for physical bottle placement. |
| WineRequest | User-submitted wine suggestion. Admins review and fulfil by creating a WineDefinition. |
| Taxonomy | Admin-managed Countries, Regions, Appellations, and Grapes to prevent free-text proliferation. |
| Notification | In-app notification for events like wine requests resolved, images approved, cellars shared. |
| SupportTicket | User support tickets with admin response tracking. |
| WineReport | User-submitted wine quality reports (wrong info, duplicates, inappropriate content). |
| Role | Description |
|---|---|
| user | Standard user — manages own cellars, bottles, and requests |
| sommelier | Can manage maturity profiles and pricing data for wines |
| admin | Full access — wine library, taxonomy, user management, image review, audit log |
| super admin | Platform-level access — system monitor, service health, rate limits, embedding management |
/api/auth| Method | Path | Description |
|---|---|---|
| POST | /register | Create account (sends verification email if Mailgun is configured) |
| POST | /login | Login, returns JWT (blocked until email is verified when Mailgun is configured) |
| GET | /verify-email?token= | Verify email address, returns JWT on success |
| POST | /resend-verification | Resend verification email |
| POST | /forgot-password | Request password reset email |
| POST | /reset-password | Reset password with token |
/api/cellars (auth required)| Method | Path | Description |
|---|---|---|
| GET | / | List user's cellars |
| POST | / | Create cellar |
| GET | /:id | Get cellar + bottles |
| PUT | /:id | Update cellar |
| DELETE | /:id | Delete cellar |
| GET | /:id/statistics | Aggregated stats |
/api/bottles (auth required)| Method | Path | Description |
|---|---|---|
| POST | / | Add bottle to cellar |
| PUT | /:id | Update bottle |
| DELETE | /:id | Remove bottle |
| POST | /import/validate | Validate import data and match wines |
| POST | /import/confirm | Create bottles from validated import |
/api/wines (auth required)All wine registry endpoints require a valid JWT. Behaviour differs by role:
search param is mandatory; results capped at 10.| Method | Path | Description |
|---|---|---|
| GET | / | Search/filter wines. Params: search, type, country, region, grapes, sort, limit, offset |
| GET | /:id | Get a single wine definition by ID |
/api/chat (auth required)| Method | Path | Description |
|---|---|---|
| POST | / | Send a question to the AI cellar chat (RAG pipeline) |
/api/notifications (auth required)| Method | Path | Description |
|---|---|---|
| GET | / | Get user's notifications |
| PUT | /:id/read | Mark notification as read |
| PUT | /read-all | Mark all notifications as read |
/api/stats (auth required)| Method | Path | Description |
|---|---|---|
| GET | /overview | Collection analytics (all cellars) |
/api/support (auth required)| Method | Path | Description |
|---|---|---|
| GET | /tickets | Get user's support tickets |
| POST | /tickets | Submit a support ticket |
/api/wine-reports (auth required)| Method | Path | Description |
|---|---|---|
| GET | / | Get user's wine reports |
| POST | / | Report a wine issue (wrong info, duplicate, etc.) |
/api/wine-requests (auth required)| Method | Path | Description |
|---|---|---|
| GET | / | Get user's wine requests |
| POST | / | Submit a new wine request |
/api/somm/* (somm or admin role)| Method | Path | Description |
|---|---|---|
| GET/POST | /maturity | Manage maturity phases for wine vintages |
| GET/POST | /prices | Manage pricing data for wine vintages |
/api/admin/* (admin role required)| Method | Path | Description |
|---|---|---|
| POST/PUT/DELETE | /wines | Manage wine definitions |
| GET/PUT | /wine-requests | Review user wine requests |
| CRUD | /taxonomy/* | Manage countries, regions, appellations, grapes |
| GET/DELETE | /images | Manage bottle images |
| GET | /audit | View audit log |
| GET | /users | Manage users |
| GET/PUT | /support-tickets | Manage support tickets |
| GET/PUT | /wine-reports | Manage wine reports |
/api/superadmin/* (super admin only)| Method | Path | Description |
|---|---|---|
| GET | /dashboard | Platform analytics (user counts, supporter-tier distribution) |
| GET/PUT | /settings | Rate limits, contact email, AI config |
| POST | /embeddings | Manage embedding jobs |
Copy .env.example to .env in the project root and set the required values:
| Variable | Required | Default | Description |
|---|---|---|---|
JWT_SECRET | Yes | — | Long random string for signing JWTs |
MEILI_MASTER_KEY | Yes | — | Long random string for Meilisearch auth |
MONGO_URI | No | mongodb://mongo:27017/winecellar | MongoDB connection |
ACCESS_TOKEN_EXPIRES_IN | No | 15m | Access-token TTL (sessions refresh via a rotating 30-day cookie) |
PORT | No | 5000 | Backend port |
FRONTEND_URL | No | http://localhost | CORS origin — set to your domain in production |
MEILI_URL | No | http://meilisearch:7700 | Meilisearch URL |
REMBG_URL | No | http://rembg:5000 | Background removal service |
ANTHROPIC_API_KEY | No | — | Enables label scanning and AI cellar chat (get a key) |
VOYAGE_API_KEY | No | — | Required for AI cellar chat embeddings (get a key) |
AI_PROVIDER | No | anthropic | Set to openai to serve all LLM features from an OpenAI-compatible endpoint (see Self-hosted AI) |
OPENAI_BASE_URL | No | — | OpenAI-compatible /v1 root, e.g. http://host.docker.internal:11434/v1 (required when AI_PROVIDER=openai) |
OPENAI_API_KEY | No | — | Bearer token for the endpoint (Ollama/LM Studio ignore it; vLLM may require one) |
AI_MODEL | No | — | Model name to use, e.g. llama3.1:70b (required when AI_PROVIDER=openai) |
AI_VISION_MODEL | No | AI_MODEL | Vision-capable model for label scanning, e.g. qwen2.5-vl:32b |
OPENAI_TIMEOUT_MS | No | 120000 | Per-request timeout for the OpenAI-compatible endpoint |
EMBEDDING_PROVIDER | No | voyage | Set to openai to serve wine embeddings from an OpenAI-compatible endpoint instead of Voyage AI |
EMBEDDING_BASE_URL | No | OPENAI_BASE_URL | /v1 root of the embedding endpoint |
EMBEDDING_API_KEY | No | — | Bearer token for the embedding endpoint (falls back to OPENAI_API_KEY only when EMBEDDING_BASE_URL is also unset — a dedicated embedding host is never sent the chat key) |
EMBEDDING_MODEL | No | — | Embedding model name, e.g. nomic-embed-text (required when EMBEDDING_PROVIDER=openai) |
EMBEDDING_DIMENSION | No | — | The model's vector size, e.g. 768 (required when EMBEDDING_PROVIDER=openai) |
EMBEDDING_TIMEOUT_MS | No | 30000 | Per-request timeout for the embedding endpoint |
QDRANT_URL | No | http://qdrant:6333 | Vector database URL (auto-set in Docker Compose) |
SUPER_ADMIN_EMAIL | No | — | Email of the super admin account |
SUPER_ADMIN_IPS | No | — | Comma-separated IP allowlist for super admin access |
MAILGUN_API_KEY | No | — | Mailgun API key — enables email verification when set |
MAILGUN_DOMAIN | No | — | Mailgun sending domain (e.g. mg.yourdomain.com) |
MAILGUN_FROM | No | Cellarion <no-reply@{DOMAIN}> | Sender address shown in verification emails |
MAILGUN_API_URL | No | https://api.mailgun.net | Use https://api.eu.mailgun.net for EU region |
The AI chat feature requires three services working together:
ANTHROPIC_API_KEY) — generates conversational responses grounded in your cellarVOYAGE_API_KEY) — creates wine embeddings for semantic searchQDRANT_URL) — vector database for fast similarity searchWhen all three are configured, users can ask natural-language questions about their collection (food pairings, occasion picks, cellar insights). The system only surfaces wines the user actually owns — no hallucinated recommendations.
A single daily usage quota — the same for every user, regardless of supporter tier — is configurable by SuperAdmins (default 50 questions/day).
Self-hosters who prefer not to use an Anthropic API key can point every LLM feature (cellar chat, label scan, import lookup, drink-window / price / profile suggestions) at any endpoint that speaks the OpenAI chat-completions API — Ollama, LM Studio, vLLM, LiteLLM, or OpenAI itself:
AI_PROVIDER=openai
OPENAI_BASE_URL=http://host.docker.internal:11434/v1 # your endpoint's /v1 root
AI_MODEL=llama3.1:70b # any model your server hosts
AI_VISION_MODEL=qwen2.5-vl:32b # optional — used for label scanning
Wine embeddings (the semantic-search half of cellar chat) can independently be moved off Voyage AI the same way:
EMBEDDING_PROVIDER=openai
EMBEDDING_MODEL=nomic-embed-text # any embedding model your server hosts
EMBEDDING_DIMENSION=768 # MUST be that model's real vector size
# EMBEDDING_BASE_URL / EMBEDDING_API_KEY default to OPENAI_BASE_URL / OPENAI_API_KEY
Notes:
host.docker.internal resolves out of the box only on Docker Desktop (Windows/macOS). On a Linux server, either add extra_hosts: ["host.docker.internal:host-gateway"] to the backend service in your compose file, or point OPENAI_BASE_URL at the host's LAN IP or a service on the compose network.0/-1 = unlimited) if you don't want your local endpoint metered.AI_MODEL); the configurable AI prompts still apply.EMBEDDING_PROVIDER, EMBEDDING_MODEL, or EMBEDDING_DIMENSION, run a full embedding job (SuperAdmin → AI) — it drops and rebuilds the collection at the new size. Every returned vector is validated against EMBEDDING_DIMENSION, so a wrong value fails loudly instead of corrupting search.When both MAILGUN_API_KEY and MAILGUN_DOMAIN are set, email verification is enabled:
/verify-email page.Existing users: After enabling verification on a running instance, existing accounts will have emailVerified: false and will be locked out. Run this once in the MongoDB shell to restore access:
db.users.updateMany({ emailVerified: { $exists: false } }, { $set: { emailVerified: true } })
Users can import bottles from other wine cellar apps (Vivino, CellarTracker, or any generic CSV). The import flow:
Import sessions are persisted so users can resume later if interrupted. Access the import from any cellar's overflow menu (⋯ → Import Bottles). Requires editor or owner access.
Bottles can also be imported as JSON. Each item supports:
{
"wineName": "Albe",
"producer": "G.D. Vajra",
"vintage": "2019",
"country": "Italy",
"region": "Piedmont",
"appellation": "Barolo",
"type": "red",
"price": 299,
"currency": "SEK",
"bottleSize": "750ml",
"quantity": 2,
"purchaseDate": "2024-03-15",
"purchaseLocation": "Systembolaget",
"notes": "Beautiful nebbiolo",
"rating": 4.2,
"ratingScale": "5",
"rackName": "Rack A",
"rackPosition": 5,
"addToHistory": false
}
To import directly into history (already consumed bottles), add:
{
"addToHistory": true,
"consumedReason": "drank",
"consumedAt": "2025-12-24",
"consumedNote": "Opened for Christmas",
"consumedRating": 4.5,
"consumedRatingScale": "5",
"dateAdded": "2024-06-01"
}
Cellar owners can export their data via a cellar's overflow menu (⋯ → Export) or Settings. Available as JSON, or as a ZIP that also includes your uploaded bottle images. The export covers bottles with rack placement (rackName, rackPosition), rack geometry, the 3D room layout, and your own reviews. The JSON format is directly re-importable.
When an admin creates a wine, the system checks for near-duplicates using:
Score: name × 0.45 + producer × 0.45 + appellation × 0.10
Candidates above the threshold (default 0.75) appear as warnings with a "Use This" option.
cd frontend && npm test -- --watchAll=false
Uses Jest + React Testing Library (bundled with Create React App). Covers drink-window logic, currency conversion, and the shared Modal component.
cd backend && npm test
Uses Jest. Covers auth middleware, cellar access control, wine normalisation/similarity, rating scale conversion, and drink-window classification.
Run both test suites before opening a pull request. PRs with failing tests will not be merged.
maincd frontend && npm test -- --watchAll=false and cd backend && npm test)docker-compose up --buildPlease report security issues privately to: github@cellarion.app
GNU Affero General Public License v3.0 (AGPL-3.0)
You are free to use, modify, and self-host this software. If you run a modified version as a network service, you must make your source code available to users of that service. Commercial hosting of this software as a managed service requires a separate agreement.
This codebase was developed together with Claude Code by Anthropic.
Be the first to review this server!
by Modelcontextprotocol · Developer Tools
Web content fetching and conversion for efficient LLM usage
by Modelcontextprotocol · Developer Tools
Read, search, and manipulate Git repositories programmatically
by Toleno · Developer Tools
Toleno Network MCP Server — Manage your Toleno mining account with Claude AI using natural language.