loading…
Search for a command to run...
loading…
Provides secure, read-only PostgreSQL database access via MCP tools like query_inventory and get_top_sales. Blocks dangerous SQL commands while allowing AI to e
Provides secure, read-only PostgreSQL database access via MCP tools like query_inventory and get_top_sales. Blocks dangerous SQL commands while allowing AI to execute controlled SELECT queries.
"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.
Khi tích hợp AI vào sản phẩm, nhiều dev gặp phải:
DROP TABLE, DELETE)User Prompt → AI (DeepSeek V4 Pro) → MCP Tools → PostgreSQL
↑ ↓
└─────── JSON Response ←─────────────┘
Nguyên tắc:
pnpm install
# 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
pnpm docker:up
Database sẽ được tự động seed với:
# Terminal 1: MCP Server
pnpm dev:mcp
# Terminal 2: Next.js Web App
pnpm dev:web
# Or run both concurrently
pnpm dev
Truy cập: http://localhost:3000
| 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 |
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
list_tablesLiệt kê các bảng trong database
Input: None
Output: Array of table names
get_table_schemaXem cấu trúc chi tiết của bảng
Input:
{ "tableName": "products" }
Output: Columns, data types, constraints
query_inventory ⭐Kiểm tra tồn kho sản phẩm
Input:
{ "productId": "SP001" }
Output:
{
"id": "SP001",
"name": "Váy hoa nhí",
"stock_quantity": 150,
"stock_status": "Còn hàng",
"price_formatted": "299.000₫"
}
get_top_sales ⭐Top sản phẩm bán chạy
Input:
{ "limit": 5, "days": 30 }
Output: Ranked list with sales metrics
execute_read_query 🛡️Generic SELECT query với security guards
Input:
{ "sql": "SELECT * FROM products WHERE price > 500000" }
Security Features:
Visual: Show AI generating dangerous 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!"
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."
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!"
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."
Key code snippets to show:
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;
}
};
const FORBIDDEN_KEYWORDS = ['DROP', 'DELETE', 'UPDATE'];
if (sql.includes(FORBIDDEN_KEYWORDS)) {
return { isError: true, text: '🚫 BLOCKED!' };
}
const response = await deepseekClient.chat.completions.create({
model: 'deepseek-v4-pro',
tools: toolsToOpenAIFormat(),
tool_choice: 'auto'
});
| 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!"
const FORBIDDEN_KEYWORDS = [
'DROP', 'DELETE', 'UPDATE', 'INSERT', 'TRUNCATE',
'ALTER', 'CREATE', 'GRANT', 'REVOKE'
];
inputSchema: z.object({
productId: z.string().describe('Mã sản phẩm')
})
const pool = new Pool({
connectionString: process.env.DATABASE_URL,
max: 20, // Prevent connection exhaustion
});
// ✅ Parameterized queries
await pool.query('SELECT * FROM products WHERE id = $1', [productId]);
// ❌ Never string concatenation
// await pool.query(`SELECT * FROM products WHERE id = '${productId}'`);
"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
# Check if PostgreSQL is running
docker ps | grep postgres
# View logs
pnpm docker:logs
# Restart
pnpm docker:down && pnpm docker:up
# Check environment variables
cat mcp-server/.env
# Test database connection
cd mcp-server && pnpm tsx src/db.ts
# 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"}]}'
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é! 🚀
Добавь это в claude_desktop_config.json и перезапусти Claude Desktop.
{
"mcpServers": {
"mcp-postgresql-secure-query-server": {
"command": "npx",
"args": []
}
}
}