Skip to content

Latest commit

 

History

History
501 lines (419 loc) · 12.2 KB

File metadata and controls

501 lines (419 loc) · 12.2 KB

DineOS Project Implementation Guide

Overview

This guide provides a step-by-step implementation plan for the DineOS restaurant management platform with MCP integration.

Quick Start Commands

Frontend Setup (Bun)

# Install Bun if not already installed
curl -fsSL https://bun.sh/install | bash

# Create Next.js project
bunx create-next-app@latest dineos-frontend \
  --typescript \
  --tailwind \
  --app \
  --src-dir=false \
  --import-alias="@/*"

cd dineos-frontend

# Install dependencies with Bun
bun add @prisma/client prisma
bun add next-auth@beta
bun add @tanstack/react-query zustand
bun add socket.io-client
bun add tailwindcss@next @headlessui/react
bun add lucide-react framer-motion
bun add -d @types/node

# Initialize Tailwind CSS v4 config
bunx tailwindcss init -p --ts

Backend Setup (Python with uv)

# Install uv
curl -LsSf https://astral.sh/uv/install.sh | sh

# Create Python project
mkdir dineos-mcp && cd dineos-mcp
uv init

# Create virtual environment and install dependencies
uv venv
source .venv/bin/activate  # On Windows: .venv\Scripts\activate

# Install FastMCP and dependencies
uv pip install fastmcp
uv pip install prisma-client-py
uv pip install redis
uv pip install python-dotenv
uv pip install httpx
uv pip install pydantic

# Create project structure
mkdir -p src/{tools,resources,prompts,services,models}
touch src/__init__.py
touch src/main.py

Database Setup

# PostgreSQL with Docker
docker run --name dineos-postgres \
  -e POSTGRES_DB=dineos \
  -e POSTGRES_USER=dineos_user \
  -e POSTGRES_PASSWORD=secure_password \
  -p 5432:5432 \
  -d postgres:15-alpine

# Redis with Docker
docker run --name dineos-redis \
  -p 6379:6379 \
  -d redis:7-alpine

Project Structure

dineos/
├── frontend/                    # Next.js application (Bun)
│   ├── app/                    # App Router pages
│   │   ├── (auth)/            # Auth pages
│   │   ├── customer/          # Customer views
│   │   ├── staff/             # Staff views
│   │   ├── kitchen/           # Kitchen displays
│   │   ├── manager/           # Manager dashboard
│   │   └── api/               # API routes
│   ├── components/             # React components
│   ├── hooks/                  # Custom hooks
│   ├── lib/                    # Utilities
│   ├── prisma/                 # Database schema
│   └── public/                 # Static assets
│
├── mcp-server/                 # Python MCP server (uv)
│   ├── src/
│   │   ├── tools/             # MCP tools
│   │   ├── resources/         # MCP resources
│   │   ├── prompts/           # MCP prompts
│   │   ├── services/          # Business logic
│   │   └── models/            # Data models
│   ├── tests/                  # Test files
│   └── pyproject.toml         # Python config
│
└── docker/                     # Docker configs
    ├── docker-compose.yml
    └── kubernetes/

Implementation Steps

Step 1: Database Schema (Prisma)

Create frontend/prisma/schema.prisma:

// This is your Prisma schema file
generator client {
  provider = "prisma-client-js"
}

datasource db {
  provider = "postgresql"
  url      = env("DATABASE_URL")
}

model Restaurant {
  id        String   @id @default(cuid())
  name      String
  address   Json
  settings  Json
  createdAt DateTime @default(now())
  updatedAt DateTime @updatedAt
  
  tables       Table[]
  menuItems    MenuItem[]
  orders       Order[]
  reservations Reservation[]
  staff        Staff[]
}

model Customer {
  id           String   @id @default(cuid())
  phone        String   @unique
  email        String?  @unique
  name         String?
  preferences  Json     @default("{}")
  loyaltyTier  String   @default("bronze")
  loyaltyPoints Int     @default(0)
  createdAt    DateTime @default(now())
  lastVisit    DateTime @updatedAt
  
  orders       Order[]
  reservations Reservation[]
  reviews      Review[]
}

model Table {
  id           String     @id @default(cuid())
  number       Int
  capacity     Int
  section      String
  features     String[]
  status       TableStatus @default(AVAILABLE)
  restaurantId String
  restaurant   Restaurant @relation(fields: [restaurantId], references: [id])
  
  orders       Order[]
  reservations Reservation[]
  
  @@unique([restaurantId, number])
}

model MenuItem {
  id            String   @id @default(cuid())
  name          String
  description   String
  price         Decimal  @db.Decimal(10, 2)
  category      String
  ingredients   Json
  allergens     String[]
  dietaryTags   String[]
  available     Boolean  @default(true)
  restaurantId  String
  restaurant    Restaurant @relation(fields: [restaurantId], references: [id])
  
  orderItems    OrderItem[]
}

model Order {
  id                String      @id @default(cuid())
  orderNumber       String      @unique
  tableId           String?
  table             Table?      @relation(fields: [tableId], references: [id])
  customerId        String?
  customer          Customer?   @relation(fields: [customerId], references: [id])
  restaurantId      String
  restaurant        Restaurant  @relation(fields: [restaurantId], references: [id])
  type              OrderType
  status            OrderStatus @default(PENDING)
  subtotal          Decimal     @db.Decimal(10, 2)
  tax               Decimal     @db.Decimal(10, 2)
  tip               Decimal     @db.Decimal(10, 2) @default(0)
  total             Decimal     @db.Decimal(10, 2)
  specialInstructions String?
  createdAt         DateTime    @default(now())
  updatedAt         DateTime    @updatedAt
  
  items             OrderItem[]
  payment           Payment?
}

model OrderItem {
  id           String   @id @default(cuid())
  orderId      String
  order        Order    @relation(fields: [orderId], references: [id])
  menuItemId   String
  menuItem     MenuItem @relation(fields: [menuItemId], references: [id])
  quantity     Int
  modifications Json    @default("[]")
  status       ItemStatus @default(QUEUED)
  station      String?
  prepTime     Int?
  notes        String?
}

model Reservation {
  id               String   @id @default(cuid())
  confirmationCode String   @unique
  customerId       String
  customer         Customer @relation(fields: [customerId], references: [id])
  restaurantId     String
  restaurant       Restaurant @relation(fields: [restaurantId], references: [id])
  tableId          String?
  table            Table?   @relation(fields: [tableId], references: [id])
  partySize        Int
  dateTime         DateTime
  duration         Int      @default(90)
  status           ReservationStatus @default(CONFIRMED)
  specialRequests  String?
  dietaryRestrictions String[]
  createdAt        DateTime @default(now())
}

model Staff {
  id           String   @id @default(cuid())
  email        String   @unique
  name         String
  role         StaffRole
  restaurantId String
  restaurant   Restaurant @relation(fields: [restaurantId], references: [id])
  pin          String?
  active       Boolean  @default(true)
  createdAt    DateTime @default(now())
}

model Payment {
  id          String   @id @default(cuid())
  orderId     String   @unique
  order       Order    @relation(fields: [orderId], references: [id])
  amount      Decimal  @db.Decimal(10, 2)
  method      PaymentMethod
  status      PaymentStatus @default(PENDING)
  processedAt DateTime?
  reference   String?
}

model Review {
  id         String   @id @default(cuid())
  customerId String
  customer   Customer @relation(fields: [customerId], references: [id])
  orderId    String?
  rating     Int
  comment    String?
  createdAt  DateTime @default(now())
}

// Enums
enum TableStatus {
  AVAILABLE
  OCCUPIED
  RESERVED
  CLEANING
  MAINTENANCE
}

enum OrderType {
  DINE_IN
  TAKEOUT
  DELIVERY
}

enum OrderStatus {
  PENDING
  CONFIRMED
  PREPARING
  READY
  SERVED
  COMPLETED
  CANCELLED
}

enum ItemStatus {
  QUEUED
  PREPARING
  READY
  SERVED
}

enum ReservationStatus {
  PENDING
  CONFIRMED
  SEATED
  COMPLETED
  CANCELLED
  NO_SHOW
}

enum StaffRole {
  OWNER
  MANAGER
  HOST
  SERVER
  BARTENDER
  CHEF
  COOK
}

enum PaymentMethod {
  CASH
  CREDIT_CARD
  DEBIT_CARD
  MOBILE_PAY
  GIFT_CARD
}

enum PaymentStatus {
  PENDING
  PROCESSING
  COMPLETED
  FAILED
  REFUNDED
}

Step 2: MCP Server Core

Create mcp-server/src/main.py:

from fastmcp import FastMCP
from contextlib import asynccontextmanager
import asyncio
from dotenv import load_dotenv
import os

# Load environment variables
load_dotenv()

# Import our tools, resources, and prompts
from tools import reservation_tools, order_tools, payment_tools
from resources import menu_resources, table_resources, analytics_resources
from prompts import workflow_prompts

# Initialize the MCP server
restaurant_mcp = FastMCP(
    "DineOS Restaurant Management System",
    version="1.0.0"
)

# Lifespan management
@asynccontextmanager
async def lifespan(app: FastMCP):
    # Startup
    print("Starting DineOS MCP Server...")
    # Initialize database connections, Redis, etc.
    
    yield
    
    # Shutdown
    print("Shutting down DineOS MCP Server...")
    # Close connections

restaurant_mcp.lifespan = lifespan

# Register all tools
restaurant_mcp.add_tool(reservation_tools.create_reservation)
restaurant_mcp.add_tool(reservation_tools.modify_reservation)
restaurant_mcp.add_tool(order_tools.create_order)
restaurant_mcp.add_tool(order_tools.update_order_status)
restaurant_mcp.add_tool(payment_tools.process_payment)

# Register all resources
restaurant_mcp.add_resource(menu_resources.get_menu_categories)
restaurant_mcp.add_resource(table_resources.get_table_status)
restaurant_mcp.add_resource(analytics_resources.get_live_operations)

# Register all prompts
restaurant_mcp.add_prompt(workflow_prompts.complete_reservation_flow)
restaurant_mcp.add_prompt(workflow_prompts.rush_hour_coordination)

if __name__ == "__main__":
    import uvicorn
    uvicorn.run(
        "main:restaurant_mcp",
        host="0.0.0.0",
        port=8000,
        reload=True
    )

Step 3: Environment Configuration

Create .env files:

Frontend .env.local:

# Database
DATABASE_URL="postgresql://dineos_user:secure_password@localhost:5432/dineos"

# NextAuth
NEXTAUTH_URL="http://localhost:3000"
NEXTAUTH_SECRET="your-secret-key-here"

# MCP Server
MCP_SERVER_URL="http://localhost:8000"
MCP_API_KEY="your-mcp-api-key"

# Redis
REDIS_URL="redis://localhost:6379"

# WebSocket
NEXT_PUBLIC_WS_URL="ws://localhost:3000"

MCP Server .env:

# Database
DATABASE_URL="postgresql://dineos_user:secure_password@localhost:5432/dineos"

# Redis
REDIS_URL="redis://localhost:6379"

# API Keys
OPENAI_API_KEY="your-openai-key"

Step 4: Running the Development Environment

# Terminal 1: Database & Redis
docker-compose up

# Terminal 2: MCP Server (Python)
cd mcp-server
source .venv/bin/activate
uv pip install -r requirements.txt
python src/main.py

# Terminal 3: Frontend (Next.js with Bun)
cd frontend
bun run dev

# Terminal 4: Prisma Studio (Database GUI)
cd frontend
bunx prisma studio

Next Steps

  1. Implement Core Tools: Start with basic CRUD operations for reservations, orders, and payments
  2. Build Chat Widget: Create the context-aware AI assistant interface
  3. Add Real-time Features: Implement WebSocket connections for live updates
  4. Create User Views: Build role-specific dashboards
  5. Test Integration: Ensure all components communicate properly
  6. Deploy: Use Docker and Kubernetes for production deployment

Development Tips

  • Use TypeScript strict mode for better type safety
  • Implement error boundaries in React components
  • Add comprehensive logging in the MCP server
  • Use Prisma migrations for database schema changes
  • Test MCP tools individually before integration
  • Monitor WebSocket connections for memory leaks
  • Implement rate limiting on API endpoints
  • Use environment variables for all configuration

Resources


Last Updated: January 2025