This guide provides a step-by-step implementation plan for the DineOS restaurant management platform with MCP integration.
# 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# 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# 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-alpinedineos/
├── 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/
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
}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
)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"# 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- Implement Core Tools: Start with basic CRUD operations for reservations, orders, and payments
- Build Chat Widget: Create the context-aware AI assistant interface
- Add Real-time Features: Implement WebSocket connections for live updates
- Create User Views: Build role-specific dashboards
- Test Integration: Ensure all components communicate properly
- Deploy: Use Docker and Kubernetes for production deployment
- 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
- FastMCP Documentation
- Next.js 15 Documentation
- Prisma Documentation
- Bun Documentation
- uv Documentation
Last Updated: January 2025