feat: 初始化 B2B AI Shopping Assistant 项目

- 配置 Docker Compose 多服务编排
- 实现 Chatwoot + Agent 集成
- 配置 Strapi MCP 知识库
- 支持 7 种语言的 FAQ 系统
- 实现 LangGraph AI 工作流

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
This commit is contained in:
wl
2026-01-14 19:25:22 +08:00
commit 3ad6eee0d9
59 changed files with 8078 additions and 0 deletions

View File

@@ -0,0 +1,299 @@
"""
Aftersale MCP Server - Returns, exchanges, and complaints
"""
import sys
import os
from typing import Optional, List
# Add shared module to path
sys.path.insert(0, os.path.dirname(os.path.dirname(os.path.abspath(__file__))))
from fastmcp import FastMCP
from pydantic_settings import BaseSettings
from pydantic import ConfigDict
class Settings(BaseSettings):
"""Server configuration"""
hyperf_api_url: str
hyperf_api_token: str
log_level: str = "INFO"
model_config = ConfigDict(env_file=".env")
settings = Settings()
# Create MCP server
mcp = FastMCP(
"Aftersale Service"
)
# Hyperf client for this server
from shared.hyperf_client import HyperfClient
hyperf = HyperfClient(settings.hyperf_api_url, settings.hyperf_api_token)
@mcp.tool()
async def apply_return(
order_id: str,
user_id: str,
items: List[dict],
description: str,
images: Optional[List[str]] = None
) -> dict:
"""Apply for a return
Args:
order_id: Order ID
user_id: User identifier
items: List of items to return, each with:
- item_id: Order item ID
- quantity: Quantity to return
- reason: Return reason (quality_issue, wrong_item, not_as_described, etc.)
description: Detailed description of the issue
images: Optional list of image URLs showing the issue
Returns:
Return application result with aftersale ID
"""
payload = {
"order_id": order_id,
"user_id": user_id,
"items": items,
"description": description
}
if images:
payload["images"] = images
try:
result = await hyperf.post("/aftersales/return", json=payload)
return {
"success": True,
"aftersale_id": result.get("aftersale_id"),
"status": result.get("status"),
"estimated_refund": result.get("estimated_refund"),
"process_steps": result.get("process_steps", []),
"message": "Return application submitted successfully"
}
except Exception as e:
return {
"success": False,
"error": str(e)
}
@mcp.tool()
async def apply_exchange(
order_id: str,
user_id: str,
items: List[dict],
description: str
) -> dict:
"""Apply for an exchange
Args:
order_id: Order ID
user_id: User identifier
items: List of items to exchange, each with:
- item_id: Order item ID
- reason: Exchange reason
- new_specs: Optional new specifications (size, color, etc.)
description: Detailed description of the issue
Returns:
Exchange application result with aftersale ID
"""
try:
result = await hyperf.post(
"/aftersales/exchange",
json={
"order_id": order_id,
"user_id": user_id,
"items": items,
"description": description
}
)
return {
"success": True,
"aftersale_id": result.get("aftersale_id"),
"status": result.get("status"),
"process_steps": result.get("process_steps", []),
"message": "Exchange application submitted successfully"
}
except Exception as e:
return {
"success": False,
"error": str(e)
}
@mcp.tool()
async def create_complaint(
user_id: str,
complaint_type: str,
title: str,
description: str,
related_order_id: Optional[str] = None,
attachments: Optional[List[str]] = None
) -> dict:
"""Create a complaint
Args:
user_id: User identifier
complaint_type: Type of complaint:
- product_quality: Product quality issues
- service: Service attitude or process issues
- logistics: Shipping/delivery issues
- pricing: Pricing or billing issues
- other: Other complaints
title: Brief complaint title
description: Detailed description
related_order_id: Related order ID (optional)
attachments: Optional list of attachment URLs
Returns:
Complaint creation result
"""
payload = {
"user_id": user_id,
"type": complaint_type,
"title": title,
"description": description
}
if related_order_id:
payload["related_order_id"] = related_order_id
if attachments:
payload["attachments"] = attachments
try:
result = await hyperf.post("/aftersales/complaint", json=payload)
return {
"success": True,
"complaint_id": result.get("complaint_id"),
"status": result.get("status"),
"assigned_to": result.get("assigned_to"),
"expected_response_time": result.get("expected_response_time"),
"message": "Complaint submitted successfully"
}
except Exception as e:
return {
"success": False,
"error": str(e)
}
@mcp.tool()
async def create_ticket(
user_id: str,
category: str,
priority: str,
title: str,
description: str
) -> dict:
"""Create a support ticket
Args:
user_id: User identifier
category: Ticket category (technical_support, account, payment, other)
priority: Priority level (low, medium, high, urgent)
title: Ticket title
description: Detailed description
Returns:
Ticket creation result
"""
try:
result = await hyperf.post(
"/aftersales/ticket",
json={
"user_id": user_id,
"category": category,
"priority": priority,
"title": title,
"description": description
}
)
return {
"success": True,
"ticket_id": result.get("ticket_id"),
"status": result.get("status"),
"assigned_team": result.get("assigned_team"),
"message": "Support ticket created successfully"
}
except Exception as e:
return {
"success": False,
"error": str(e)
}
@mcp.tool()
async def query_aftersale_status(
user_id: str,
aftersale_id: Optional[str] = None
) -> dict:
"""Query aftersale records and status
Args:
user_id: User identifier
aftersale_id: Specific aftersale ID (optional, queries all if not provided)
Returns:
List of aftersale records with progress
"""
params = {"user_id": user_id}
if aftersale_id:
params["aftersale_id"] = aftersale_id
try:
result = await hyperf.get("/aftersales/query", params=params)
return {
"success": True,
"records": result.get("records", [])
}
except Exception as e:
return {
"success": False,
"error": str(e),
"records": []
}
# Health check endpoint
@mcp.tool()
async def health_check() -> dict:
"""Check server health status"""
return {
"status": "healthy",
"service": "aftersale_mcp",
"version": "1.0.0"
}
if __name__ == "__main__":
import uvicorn
# Create FastAPI app from MCP
app = mcp.http_app()
# Add health endpoint
from starlette.responses import JSONResponse
async def health_check(request):
return JSONResponse({"status": "healthy"})
# Add the route to the app
from starlette.routing import Route
app.router.routes.append(Route('/health', health_check, methods=['GET']))
uvicorn.run(app, host="0.0.0.0", port=8003)