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:
299
mcp_servers/aftersale_mcp/server.py
Normal file
299
mcp_servers/aftersale_mcp/server.py
Normal 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)
|
||||
Reference in New Issue
Block a user