Skip to main content
Glama
longliaprono1-blip

chatbot-ai-mcp-demo

README.md
# 🎬 AI Chatbot Demo: MCP + PostgreSQL + DeepSeek V4 Pro

> **"Don't let AI write SQL. Let AI call your secure API."**

Demo chuyên nghiệp tích hợp AI an toàn sử dụng MCP (Model Context Protocol) với Next.js 15, PostgreSQL và DeepSeek V4 Pro - Perfect cho vlog content.

## 🎯 Vấn đề giải quyết

Khi tích hợp AI vào sản phẩm, nhiều dev gặp phải:
- ❌ **Security risks**: AI tạo SQL sai hoặc nguy hiểm (`DROP TABLE`, `DELETE`)
- ❌ **Hallucination**: AI "ảo giác" tạo query sai data
- ❌ **Prompt injection**: User truyền lệnh gây hại
- ❌ **No control**: Không kiểm soát được AI tạo gì

## ✅ Giải pháp: MCP Pattern

```
User Prompt → AI (DeepSeek V4 Pro) → MCP Tools → PostgreSQL
     ↑                                    ↓
     └─────── JSON Response ←─────────────┘
```

**Nguyên tắc:**
- 🧠 **AI**: Chỉ suy luận, quyết định gọi tool nào
- 🛡️ **MCP Server**: Security guards, chặn lệnh nguy hiểm
- 💻 **Dev**: Kiểm soát 100% SQL trong tools
- 📊 **PostgreSQL**: Trả về data an toàn

---

## 🚀 Quick Start

### 1. Cài đặt dependencies

```bash
pnpm install
```

### 2. Cấu hình environment

```bash
# Copy file .env.example
cp .env.example .env

# Cập nhật DEEPSEEK_API_KEY
# Lấy API key tại: https://platform.deepseek.com/api_keys
```

### 3. Khởi động PostgreSQL

```bash
pnpm docker:up
```

Database sẽ được tự động seed với:
- 115 sản phẩm (5 categories)
- Inventory data
- Sales records (30 ngày)
- Orders data

### 4. Chạy development servers

```bash
# Terminal 1: MCP Server
pnpm dev:mcp

# Terminal 2: Next.js Web App
pnpm dev:web

# Or run both concurrently
pnpm dev
```

### 5. Mở browser

Truy cập: **http://localhost:3000**

---

## 🏗️ Architecture

### Tech Stack

| Layer | Technology | Purpose |
|-------|-----------|---------|
| **Presentation** | Next.js 15 + React 19 | Chat UI, Markdown preview |
| **Styling** | Tailwind CSS 4 | Responsive, dark mode |
| **Orchestrator** | Next.js Route Handlers | AI + MCP coordination |
| **AI Brain** | DeepSeek V4 Pro | Tool calling, reasoning |
| **MCP Server** | Express + MCP SDK | Tool execution, security |
| **Database** | PostgreSQL 16 (Docker) | Data storage |

### Project Structure

```
mcp-postgres-demo/
├── docker/
│   ├── docker-compose.yml          # PostgreSQL setup
│   └── init.sql                    # Database seeding (115 products)
├── mcp-server/
│   ├── src/
│   │   ├── index.ts                # Server entry + HTTP endpoints
│   │   ├── db.ts                   # Connection pooling
│   │   └── tools/
│   │       ├── schema-tools.ts     # list_tables, get_table_schema
│   │       ├── query-tools.ts      # query_inventory, get_top_sales
│   │       └── execute-tool.ts     # execute_read_query (security guard)
│   ├── package.json
│   └── tsconfig.json
├── web/
│   ├── src/
│   │   ├── app/
│   │   │   ├── api/chat/route.ts   # AI orchestration endpoint
│   │   │   ├── page.tsx            # Chat UI
│   │   │   └── layout.tsx          # Root layout
│   │   └── lib/
│   │       ├── ai-client.ts        # DeepSeek client
│   │       └── tool-registry.ts    # Tool definitions
│   ├── package.json
│   └── .env.example
├── .env.example
├── package.json
└── README.md
```

---

## 🛠️ MCP Tools

### 1. `list_tables`
Liệt kê các bảng trong database

**Input:** None  
**Output:** Array of table names

### 2. `get_table_schema`
Xem cấu trúc chi tiết của bảng

**Input:**
```json
{ "tableName": "products" }
```

**Output:** Columns, data types, constraints

### 3. `query_inventory` ⭐
Kiểm tra tồn kho sản phẩm

**Input:**
```json
{ "productId": "SP001" }
```

**Output:**
```json
{
  "id": "SP001",
  "name": "Váy hoa nhí",
  "stock_quantity": 150,
  "stock_status": "Còn hàng",
  "price_formatted": "299.000₫"
}
```

### 4. `get_top_sales` ⭐
Top sản phẩm bán chạy

**Input:**
```json
{ "limit": 5, "days": 30 }
```

**Output:** Ranked list with sales metrics

### 5. `execute_read_query` 🛡️
Generic SELECT query với security guards

**Input:**
```json
{ "sql": "SELECT * FROM products WHERE price > 500000" }
```

**Security Features:**
- ✅ Only SELECT/WITH allowed
- ❌ Blocks: DROP, DELETE, UPDATE, INSERT, etc.
- ✅ Result limit: 100 rows max
- ✅ SQL injection prevention

---

## 🎬 Vlog Script Guide

### Scene 1: Problem Statement (30s)

**Visual:** Show AI generating dangerous SQL
```sql
-- AI hallucination example
DROP TABLE users;
DELETE FROM orders WHERE 1=1;
```

**Narration:**
> "Nhiều bạn dev hỏi: Khi tích hợp AI, làm sao để nó không phá database? 
> Hôm nay mình share giải pháp production-ready!"

### Scene 2: Architecture Overview (45s)

**Visual:** Show architecture diagram
```
User → DeepSeek V4 Pro → MCP Server → PostgreSQL
```

**Narration:**
> "Thay vì để AI tự viết SQL, chúng ta dùng MCP Pattern.
> AI chỉ suy luận gọi tool nào, dev kiểm soát SQL trong code."

### Scene 3: Code Demo - Success Case (60s)

**Visual:** Chat UI demo
```
User: "Check tồn kho SP001"
AI: 🤔 User wants inventory → Call query_inventory tool
MCP: ✅ Execute SELECT query
DB: Returns { stock: 150 }
AI: "Sản phẩm SP001 còn 150 chiếc trong kho"
```

**Narration:**
> "User hỏi tự nhiên, AI phân tích, gọi đúng tool, 
> MCP thực thi query an toàn, trả kết quả dễ hiểu!"

### Scene 4: Security Demo (45s)

**Visual:** Blocked dangerous command
```
User: "Xóa tất cả users"
AI: 🤔 User wants to delete → Wait...
MCP: 🚫 BLOCKED! DELETE not allowed
Response: "Tool này chỉ hỗ trợ đọc dữ liệu"
```

**Narration:**
> "Khi user cố tình phá database, MCP server chặn ngay!
> Đây là chốt chặn bảo mật cuối cùng mà AI không thể bypass."

### Scene 5: Code Walkthrough (60s)

**Key code snippets to show:**

1. **Tool Definition** (mcp-server/src/tools/query-tools.ts)
```typescript
export const queryInventoryTool = {
  name: 'query_inventory',
  execute: async ({ productId }) => {
    // Dev controls SQL 100%
    const result = await pool.query(
      'SELECT * FROM products WHERE id = $1',
      [productId]
    );
    return result;
  }
};
```

2. **Security Guard** (mcp-server/src/tools/execute-tool.ts)
```typescript
const FORBIDDEN_KEYWORDS = ['DROP', 'DELETE', 'UPDATE'];

if (sql.includes(FORBIDDEN_KEYWORDS)) {
  return { isError: true, text: '🚫 BLOCKED!' };
}
```

3. **AI Tool Calling** (web/src/app/api/chat/route.ts)
```typescript
const response = await deepseekClient.chat.completions.create({
  model: 'deepseek-v4-pro',
  tools: toolsToOpenAIFormat(),
  tool_choice: 'auto'
});
```

### Scene 6: Cost Comparison (30s)

| Model | Cost/1M tokens | Tool Calling |
|-------|---------------|--------------|
| GPT-4o | ~$15 | ✅ |
| Claude 3.5 | ~$15 | ✅ |
| **DeepSeek V4 Pro** | **~$0.5** | ✅ |

**Narration:**
> "DeepSeek V4 Pro hỗ trợ tool calling, giá chỉ bằng 1/30 GPT-4o.
> Perfect cho startups và vibe coders!"

---

## 🔒 Security Best Practices

### 1. Read-Only Enforcement
```typescript
const FORBIDDEN_KEYWORDS = [
  'DROP', 'DELETE', 'UPDATE', 'INSERT', 'TRUNCATE', 
  'ALTER', 'CREATE', 'GRANT', 'REVOKE'
];
```

### 2. Parameter Validation (Zod)
```typescript
inputSchema: z.object({
  productId: z.string().describe('Mã sản phẩm')
})
```

### 3. Connection Pooling
```typescript
const pool = new Pool({
  connectionString: process.env.DATABASE_URL,
  max: 20, // Prevent connection exhaustion
});
```

### 4. SQL Injection Prevention
```typescript
// ✅ Parameterized queries
await pool.query('SELECT * FROM products WHERE id = $1', [productId]);

// ❌ Never string concatenation
// await pool.query(`SELECT * FROM products WHERE id = '${productId}'`);
```

---

## 📊 Demo Data

### Categories
- **Fashion**: 30 products (SP001-SP030)
- **Electronics**: 25 products (SP031-SP055)
- **Home & Living**: 25 products (SP056-SP080)
- **Beauty**: 20 products (SP081-SP100)
- **Sports**: 15 products (SP101-SP115)

### Sample Queries
```
"Check tồn kho SP001" → 150 items
"Top 5 bán chạy tuần này" → Sales ranking
"Có những bảng nào?" → Table discovery
"Xem cấu trúc bảng products" → Schema details
```

---

## 🔧 Troubleshooting

### Database Connection Failed
```bash
# Check if PostgreSQL is running
docker ps | grep postgres

# View logs
pnpm docker:logs

# Restart
pnpm docker:down && pnpm docker:up
```

### MCP Server Not Starting
```bash
# Check environment variables
cat mcp-server/.env

# Test database connection
cd mcp-server && pnpm tsx src/db.ts
```

### AI API Key Issues
```bash
# Verify API key
echo $DEEPSEEK_API_KEY

# Test API
curl https://api.deepseek.com/v1/chat/completions \
  -H "Authorization: Bearer $DEEPSEEK_API_KEY" \
  -d '{"model":"deepseek-v4-pro","messages":[{"role":"user","content":"Hi"}]}'
```

---

## 📚 Resources

- [DeepSeek API Docs](https://api-docs.deepseek.com/)
- [MCP Specification](https://modelcontextprotocol.io/)
- [MCP TypeScript SDK](https://github.com/modelcontextprotocol/typescript-sdk)
- [Next.js 15 Docs](https://nextjs.org/docs)
- [Tailwind CSS 4](https://tailwindcss.com/)

---

## 🎓 Key Takeaways

1. **Don't let AI write SQL** - Dev controls data access
2. **MCP Pattern** - Standardized tool calling
3. **Security First** - Multiple protection layers
4. **Cost Effective** - DeepSeek V4 Pro ~$0.5/1M tokens
5. **Production Ready** - Connection pooling, validation, error handling

---

## 📝 License

MIT License - Feel free to use for learning, vlogs, or production!

---

**Made with ❤️ for Vietnamese Dev Community**

Follow và share để ủng hộ mình ra thêm nhiều content chất lượng nhé! 🚀