模拟电商MCP服务器

一个通用的模拟MCP服务器,用于电商AI聊天机器人集成,支持多类别商品和食品配送服务。

  • by arpanm
  • Java
  • 本地部署
  • 更新于
在 GitHub 查看 arpanm/MockEcomMCPServer

使用说明

模拟电子商务MCP服务器

通用型 模拟MCP(模型上下文协议)服务器 建于 Java 21+Spring Boot 3.3.6+Spring AI 1.0.0-M6.

一个使用此服务器的AI聊天机器人可以为跨平台的用户提供服务 杂货、时尚、电子、美容和家居 类别,以及 外卖 (旋转风格的餐厅)。暴露 40+MCP工具 任何兼容MCP的AI客户端(Claude、GPT、Gemini等)都可以发现和调用。


目录

  1. 需求
  2. 建筑
  3. 代码结构
  4. 本地运行时--快速入门
  5. Web UI——数据浏览器
  6. 本地端点
  7. 28种电子商务MCP工具
  8. 餐厅和Swiggy刮刀工具
  9. 种子数据管道
  10. LLM产品数据生成
  11. 测试用例
  12. 在本地运行测试
  13. 生产部署
  14. 连接MCP客户端
  15. 状态 & 全部

需求

功能需求

  • 暴露 28个MCP工具 通过HTTP/SSE实现AI聊天机器人集成
  • 支持 5个产品类别:杂货、时尚、电子、美容、家居
  • 完整的电子商务流程:搜索→ cart → 结账→ 支付→ 订单→ 装运→ 审查
  • 通过电话号码+平台密码进行基于会话的身份验证
  • 模拟数据生成——不需要真正的数据库种子;产品按需生成
  • 支持门票和愿望清单管理

非功能性需求

  • Java 21 最小
  • 用于本地/dev的内存H2数据库;PostgreSQL用于生产
  • 所有工具均以结构化JSON字符串进行响应
  • 会话TTL:24小时
  • 分页:默认10个项目,最多50个
  • 异步生成产品以避免阻止搜索响应

先决条件

工具 版本
Java(JDK) 21+
Maven 3.8+
Docker+Docker Compose 任何最新版本(用于prod模式)

建筑

┌─────────────────────────────────────────────────────────────┐
│                        MCP Client                           │
│          (Claude Desktop / VS Code / Custom App)            │
└─────────────────────┬───────────────────────────────────────┘
                      │  HTTP/SSE  (MCP Protocol)
                      ▼
┌─────────────────────────────────────────────────────────────┐
│              Spring Boot MCP Server  :8080                  │
│  ┌──────────────────────────────────────────────────────┐   │
│  │  MCP Tool Layer  (12 Tool Classes, 28 Tools)         │   │
│  │  ProductSearch · ProductDetail · Delivery · Auth     │   │
│  │  Cart · Address · Payment · Order · Shipment         │   │
│  │  Ticket · Review · Wishlist                          │   │
│  └──────────────────────┬───────────────────────────────┘   │
│  ┌──────────────────────▼───────────────────────────────┐   │
│  │  Service Layer  (12 Services)                        │   │
│  │  Auth · Product · Cart · Checkout · Order · Payment  │   │
│  │  Address · Delivery · Review · Ticket · Wishlist     │   │
│  │  MockDataGenerator                                   │   │
│  └──────────────────────┬───────────────────────────────┘   │
│  ┌──────────────────────▼───────────────────────────────┐   │
│  │  Repository Layer  (16 Spring Data JPA Repos)        │   │
│  └──────────────────────┬───────────────────────────────┘   │
│  ┌──────────────────────▼───────────────────────────────┐   │
│  │  Database: H2 (dev/test)  │  PostgreSQL (prod)       │   │
│  └──────────────────────────────────────────────────────┘   │
└─────────────────────────────────────────────────────────────┘

数据流——端到端购物之旅

Login (phone) → sessionId
  → searchProducts / filterProducts
    → addToCart (sessionId)
      → checkout (cartId, sessionId)
        → selectAddress (checkoutId, addressId, sessionId)
          → initiatePayment (checkoutId, method, sessionId)
            → orderId created automatically
              → getOrderDetails / getShipments
                → submitProductReview / createTicket

关键设计决策

  • 按需模拟数据 --产品是从搜索关键字+类别中确定地生成的;无需人工播种
  • SSE运输 --工具通过服务器发送事件公开,以提供实时流媒体支持
  • 内存中的H2 对于dev意味着零设置;模式在启动时创建,在退出时删除
  • 异步生成 --当搜索没有返回结果时,将在后台异步生成8个产品

代码结构

src/
├── main/java/com/mock/ecom/mcpserver/
│   ├── MockEcomMcpServerApplication.java   # Entry point (@EnableAsync)
│   ├── config/
│   │   ├── AppProperties.java              # App config (session TTL, secret, pagination)
│   │   ├── AsyncConfig.java                # Thread pool (5 core, 20 max, 100 queue)
│   │   └── McpToolsConfig.java             # Registers all 12 tool classes with MCP
│   ├── entity/                             # 16 JPA entities
│   │   ├── Customer, Session, Address
│   │   ├── Product, ProductAttribute
│   │   ├── Cart, CartItem, Checkout
│   │   ├── Order, OrderItem, Payment
│   │   ├── Shipment, Review
│   │   ├── Ticket, TicketComment, WishlistItem
│   ├── repository/                         # 16 Spring Data JPA repositories
│   ├── service/                            # 12 business services
│   │   ├── AuthService.java                # Session create/validate, customer lookup
│   │   ├── ProductService.java             # Search, filter, reviews, lazy generation
│   │   ├── MockDataGeneratorService.java   # Deterministic mock data for 5 categories
│   │   ├── CartService.java                # Add to cart, recalculate totals, checkout
│   │   ├── CheckoutService.java            # Checkout lifecycle
│   │   ├── OrderService.java               # Order creation and status transitions
│   │   ├── PaymentService.java             # Payment initiation and status
│   │   ├── AddressService.java             # Address CRUD
│   │   ├── DeliveryService.java            # Delivery estimate by pincode
│   │   ├── ReviewService.java              # Product and shipment reviews
│   │   ├── TicketService.java              # Support tickets and comments
│   │   └── WishlistService.java            # Wishlist add/view
│   └── tools/                              # 12 MCP tool classes
│       ├── ProductSearchTools.java         # Tools 1-4
│       ├── ProductDetailTools.java         # Tools 5-6
│       ├── DeliveryTools.java              # Tool 7
│       ├── AuthTools.java                  # Tool 8
│       ├── CartTools.java                  # Tools 9-10
│       ├── AddressTools.java               # Tools 11-12
│       ├── PaymentTools.java               # Tools 13-14
│       ├── OrderTools.java                 # Tools 15-19
│       ├── ShipmentTools.java              # Tool 20
│       ├── TicketTools.java                # Tools 21-24
│       ├── ReviewTools.java                # Tools 25-26
│       ├── WishlistTools.java              # Tools 27-28
│       └── ToolResponseHelper.java         # JSON serialization utility
└── main/resources/
    ├── application.yml                     # Dev profile (H2, port 8080)
    ├── application-test.yml                # Test profile (H2, separate DB)
    └── application-prod.yml                # Prod profile (PostgreSQL, env vars)

src/test/java/com/mock/ecom/mcpserver/
├── MockEcomMcpServerApplicationTests.java
└── integration/
    ├── EndToEndShoppingJourneyTest.java    # Full 28-tool flow
    ├── AuthAndCartFlowTest.java            # Tools 8-14
    ├── ProductToolsIntegrationTest.java    # Tools 1-7
    ├── OrderManagementTest.java            # Tools 15-20
    ├── TicketAndReviewTest.java            # Tools 21-26
    ├── WishlistTest.java                   # Tools 27-28
    └── MockDataGeneratorTest.java          # Data generation logic

实体关系

Customer ──< Session
Customer ──< Address
Customer ──< Cart ──< CartItem >── Product
Customer ──< WishlistItem >── Product
Cart ──── Checkout ──── Order ──< OrderItem >── Product
Checkout ──< Payment
Order ──< Shipment ──< OrderItem
Order ──< Ticket ──< TicketComment
Shipment ──< Review (DELIVERY type)
Product ──< Review (PRODUCT type)
Product ──< ProductAttribute

枚举参考

实体 状态值
购物车 ACTIVE, CHECKED_OUT, ABANDONED
结账 PENDING, ADDRESS_SELECTED, PAYMENT_INITIATED, COMPLETED, CANCELLED
订购 PLACED, PROCESSING, PARTIALLY_SHIPPED, SHIPPED, DELIVERED, CANCELLED, PARTIALLY_RETURNED, RETURNED
订单项目 ORDERED, PROCESSING, PACKED, SHIPPED, OUT_FOR_DELIVERY, DELIVERED, CANCELLED, RETURN_INITIATED, RETURNED, REFUNDED
付款方式 PENDING, PROCESSING, SUCCESS, FAILED, REFUND_INITIATED, REFUNDED, PARTIALLY_REFUNDED
装运 PENDING, PROCESSING, PACKED, SHIPPED, OUT_FOR_DELIVERY, DELIVERED, RETURNED, CANCELLED
门票 OPEN, IN_PROGRESS, AWAITING_CUSTOMER, RESOLVED, CLOSED
tickettype DELIVERY_ISSUE, RETURN_REQUEST, PAYMENT_ISSUE, PRODUCT_QUALITY, CANCELLATION, OTHER
地址类型 HOME, WORK, OTHER
审核类型 PRODUCT, DELIVERY
付款方式 UPI, CARD, COD, NETBANKING, WALLET

本地运行时--快速入门

选项1:一个命令脚本(推荐)

这 run-local.sh 脚本会自动查找空闲端口,更新配置,构建并启动服务器。

chmod +x run-local.sh
./run-local.sh

它的作用:

  • 检查端口8080是否可用;如果没有,则查找下一个空闲端口(8081、8082、…)
  • 更新 server.port 在 application.yml 暂时
  • 使用Maven构建(跳过速度测试)
  • 启动Spring Boot应用程序
  • 打印具有实际端口的所有端点URL

选项2:手动步骤

# 1. Build
mvn clean package -DskipTests

# 2. Run (H2 in-memory, dev profile)
mvn spring-boot:run

# Or run the JAR directly
java -jar target/mcp-server-1.0.0-SNAPSHOT.jar

选项3:自定义端口

java -jar target/mcp-server-1.0.0-SNAPSHOT.jar --server.port=9090

选项4:Docker+PostgreSQL

# Build and start all services
mvn clean package -DskipTests
docker-compose up --build

# Stop
docker-compose down

# Stop and remove data volume
docker-compose down -v

环境变量(Docker/生产环境)

变量 默认值 描述
SPRING_PROFILES_ACTIVE dev 设置为 prod 对于PostgreSQL
DB_URL jdbc:postgresql://localhost:5432/mockecomdb JDBC URL
DB_USERNAME postgres 数据库用户名
DB_PASSWORD postgres 数据库密码
SERVER_PORT 8080 HTTP侦听端口
ANTHROPIC_API_KEY (空) Anthropic API密钥-在设置时启用LLM产品生成

Web UI——数据浏览器

React单页应用程序被捆绑到JAR中,并在根URL处自动提供服务。它允许您使用实时的分层过滤器直观地浏览所有抓取和生成的数据。

访问UI

启动服务器(请参阅 本地运行时),然后打开:

http://localhost:8080

不需要额外的设置——预构建的UI已经包含在 src/main/resources/static/ 由Spring Boot供应。

页面

页面 URL 描述
主页/仪表板 http://localhost:8080/#/ 实时统计数据(城市、餐厅、菜单项)、进度条、快速导航
餐厅探索者 http://localhost:8080/#/restaurants 使用分层过滤器和菜单查看器浏览所有餐厅
产品浏览器 http://localhost:8080/#/products 按类别、品牌、子类别浏览模拟生成的产品

餐厅资源管理器功能

  1. 城市过滤器 (左侧边栏)——列出了每个有餐馆的城市,并附有计数徽章。单击以缩小结果范围。
  2. 美食过滤器 --根据所选城市的餐厅数据自动填充。单击一个或多个菜肴进行筛选。
  3. 纯素食开关 --仅显示素食餐厅。
  4. 搜索栏 --按餐厅名称进行反发音搜索。
  5. 菜单项搜索模式 --切换到在所选城市的所有餐厅中搜索特定菜肴(例如“biryani”、“dosa”)。
  6. 餐厅卡 --评级徽章、美食标签、双人价格、配送时间、折扣优惠、关闭/打开指示器。
  7. 餐厅详图面板 --从卡片右侧滑入,单击:
    • 完整信息:评级、评级计数、交货时间、成本、城市、折扣
    • 按类别分组的完整菜单,带有可折叠的部分
    • 类别选项卡可跳转到Starters/Biryani/Desserts等。
    • 每项:蔬菜/非蔬菜指标,⭐ 畅销徽章、价格、缺货标签

产品浏览器功能

  1. 类别筛选器 (左侧边栏)--电子、时尚、杂货、美容、家居。
  2. 子类别筛选器 -从API为当前搜索/类别动态加载。
  3. 品牌过滤器 --动态加载产品计数的品牌。
  4. 搜索栏 --在产品名称和描述之间进行取消发音的全文搜索。
  5. 产品卡片 --品牌、标题、星级、价格(带有原始MRP删除线)、折扣%徽章。
  6. 产品详情面板 --从卡片右侧滑入,单击:
    • 完整描述,类别面包屑,价格优惠
    • 规格表(所有产品属性)
    • 客户评论(可扩展,分页)

构建/重建UI

已建输出(src/main/resources/static/)已提交,因此应用程序可以开箱即用。如果在中修改任何UI源 ui/src/,运行前重建:

先决条件: Node.js 18+和npm。

# Install dependencies (first time only)
cd ui
npm install

# Build — outputs to src/main/resources/static/
npm run build

# Then rebuild the JAR so Spring Boot picks up the new assets
cd ..
mvn clean package -DskipTests
java -jar target/mcp-server-1.0.0-SNAPSHOT.jar

然后可以在以下位置访问UI http://localhost:8080.

热重载UI开发

要在不每次重建JAR的情况下迭代UI,请在Spring Boot服务器旁边运行Vite-dev服务器:

# Terminal 1 — start the backend
java -jar target/mcp-server-1.0.0-SNAPSHOT.jar

# Terminal 2 — start the Vite dev server
cd ui
npm run dev

打开 http://localhost:5173 在您的浏览器中。Vite-dev服务器代理所有 /api 请求 http://localhost:8080,因此UI与实时后端通信。更改为 ui/src/ 通过热模块更换立即反映出来。

开发完成后,重建并提交:

cd ui && npm run build
cd ..
git add src/main/resources/static/
git commit -m "chore: update UI build"

UI技术栈

工具 版本 目的
React 18 用户界面框架
TypeScript 5 类型安全
Vite 5 构建工具+开发服务器
顺风CSS 3 实用优先样式
TanStack查询 5 数据提取、缓存、自动刷新
Axios 1 HTTP客户端
React Router 6 客户端路由(HashRouter)
Lucide React -- 图标

REST API端点(由UI使用)

以下所有端点 /api/v1/ 也可直接使用(curl、Postman、其他客户端)。

方法 端点 参数 描述
得到 /api/v1/stats -- 总计数(城市、餐馆、菜单项)
得到 /api/v1/cities -- 所有拥有餐厅数量和刮擦状态的城市
得到 /api/v1/cuisines cityName (可选) 一个城市(或所有城市)的独特美食列表
得到 /api/v1/restaurants cityName, cuisine, name, isPureVeg, page, size 分页餐厅搜索
得到 /api/v1/restaurants/{swiggyId} -- Swiggy ID的单餐厅
得到 /api/v1/restaurants/{swiggyId}/menu -- 按类别分组的完整菜单
得到 /api/v1/menu-items q (必填), cityName, page, size 在所有餐厅按名称搜索菜肴
得到 /api/v1/products q, category, subCategory, brand, page, size 分页产品搜索
得到 /api/v1/products/filters q 查询的可用类别、子类别、品牌
得到 /api/v1/products/{productId} -- 包含属性的完整产品详细信息
得到 /api/v1/products/{productId}/reviews page, size 分页的产品评论
得到 /api/v1/scraper/status -- 刮板运行状态+计数

curl调用示例:

# All cities with restaurants
curl http://localhost:8080/api/v1/cities

# Restaurants in Bangalore
curl "http://localhost:8080/api/v1/restaurants?cityName=Bangalore"

# Veg restaurants in Mumbai
curl "http://localhost:8080/api/v1/restaurants?cityName=Mumbai&isPureVeg=true"

# Cuisines available in Hyderabad
curl "http://localhost:8080/api/v1/cuisines?cityName=Hyderabad"

# Full menu for Paradise Biryani
curl "http://localhost:8080/api/v1/restaurants/400001/menu"

# Search for "biryani" across all restaurants
curl "http://localhost:8080/api/v1/menu-items?q=biryani"

# Search for "biryani" in Bangalore only
curl "http://localhost:8080/api/v1/menu-items?q=biryani&cityName=Bangalore"

# Electronics products
curl "http://localhost:8080/api/v1/products?category=Electronics&size=5"

# Laptop products
curl "http://localhost:8080/api/v1/products?q=laptop"

本地端点

所有端点均已打开 http://localhost:<PORT> (默认值 8080).

端点 描述
GET / 网页用户界面 --React数据浏览器(餐厅、产品、scraper仪表板)
GET /api/v1/** REST API --由UI使用;也可直接卷曲/邮递员使用
GET /sse MCP SSE端点 --在此处连接您的MCP客户端
POST /mcp/message MCP消息端点(由SSE传输内部使用)
GET /actuator/health 健康检查-退货 {"status":"UP"}
GET /actuator/info 申请信息
GET /actuator/metrics 指标列表
GET /actuator/metrics/{name} 具体度量值
GET /h2-console H2数据库浏览器 (仅限DEV,用户名:SA,无密码)
GET /swagger-ui.html Swagger UI-交互式API文档 (要求 -Pswagger)
GET /v3/api-docs OpenAPI 3.0 JSON规范 (要求 -Pswagger)

API 文档

资源 位置 备注
Swagger 用户界面 http://localhost:8080/swagger-ui.html 实时交互式文档,使用构建 mvn package -Pswagger
OpenAPI JSON http://localhost:8080/v3/api-docs 机器可读规格,要求 -Pswagger
OpenAPI YAML docs/openapi.yaml 静态规范,始终可用(不需要构建标志)
邮差收藏 docs/postman_collection.json 导入邮递员;所有28个工具均已预先配置

启用Swagger UI

构建与 swagger Maven配置文件用于激活实时Swagger UI:

# Build with Swagger
mvn clean package -Pswagger -DskipTests

# Run
java -jar target/mcp-server-1.0.0-SNAPSHOT.jar

# Open in browser
open http://localhost:8080/swagger-ui.html

导入邮差收藏

  1. 打开邮递员→ 导入 → 选择 docs/postman_collection.json
  2. 设置 baseUrl 集合变量(默认值: http://localhost:8080)
  3. 跑 认证→ serverToServerLogin 第一—— sessionId 自动保存
  4. 使用已保存的 sessionId 在所有后续请求中

H2控制台连接

URL:      http://localhost:8080/h2-console
JDBC URL: jdbc:h2:file:./data/mockecomdb
Username: sa
Password: (leave blank)

健康检查示例

curl http://localhost:8080/actuator/health
# {"status":"UP","components":{"db":{"status":"UP"},"diskSpace":{"status":"UP"}}}

28种MCP工具

产品发现--无需授权

# 工具 参数 说明
1 searchProducts query, page, pageSize 所有类别的全文搜索。如果没有找到,则生成模拟产品。
2 filterProducts query, category, subCategory, brand, page, pageSize 按类别/子类别/品牌的任意组合过滤产品。
3 getFilters query 返回可用的过滤器方面(类别、子类别、品牌)和计数。
4 getSortOptions query 返回6个排序选项: price_asc, price_desc, rating_desc, newest, popularity, delivery_asc.
5 getProductDetails productId 完整的产品——标题、描述、品牌、型号、价格、MRP、评级、属性、图片。
6 getProductReviews productId, page, pageSize 评分摘要+带有评分分布的分页评论。
7 getDeliveryTime productId, pincode 给定夹码的交货预估和日期范围。

身份验证--服务器到服务器

# 工具 参数 说明
8 serverToServerLogin phone, platform, secret 获取 sessionId.秘密= mock-platform-secret-key。如果是新客户,则创建客户。

购物车--需要授权

# 工具 参数 说明
9 addToCart productId, quantity, sessionId 将产品添加到活动购物车。如果不存在购物车,则创建购物车。重新计算总数。
10 checkout cartId, sessionId 将购物车转换为结账。退货 checkoutId 总计。

地址--需要授权

# 工具 参数 说明
11 getAddresses sessionId 列出客户的所有已保存地址。
12 selectAddress checkoutId, addressId, sessionId 将收货地址附加到收银台。

付款--需要授权

# 工具 参数 说明
13 initiatePayment checkoutId, paymentMethod, sessionId 启动付款。方法: UPI, CARD, COD, NETBANKING, WALLET。创建订单。
14 getPaymentStatus paymentId, sessionId 返回付款状态和相关信息 orderId.

订单--需要授权

# 工具 参数 说明
15 getOrderDetails orderId, sessionId 包含所有项目、状态和装运信息的完整订单。
16 getOrders sessionId, page, pageSize 分页的订单历史。
17 getShipments sessionId, page, pageSize 带有跟踪号的分页装运清单。
18 cancelOrder orderId, itemId, sessionId 取消整个订单或特定项目。
19 returnOrderItem orderItemId, reason, sessionId 启动特定项目的退货。

发货--需要授权

# 工具 参数 说明
20 sendDeliveryOtp shipmentId, sessionId 生成并发送装运的交货OTP。

支持票--需要授权

# 工具 参数 说明
21 getTickets sessionId, page, pageSize 客户支持票的分页列表。
22 getTicketDetails ticketId, sessionId 带有完整评论线程的工单详细信息。
23 addTicketComment ticketId, comment, sessionId 在工单上添加客户评论。
24 createTicket subject, description, type, orderId, orderItemId, sessionId 创建新票证。类型: DELIVERY_ISSUE, RETURN_REQUEST, PAYMENT_ISSUE, PRODUCT_QUALITY, CANCELLATION, OTHER.

评论-需要授权

# 工具 参数 说明
25 submitProductReview productId, rating, title, description, sessionId 对产品进行评分和评价(1-5颗星)。如果之前订购,则标记为已验证购买。
26 submitShipmentReview shipmentId, rating, title, description, sessionId 对交付体验进行评分。

愿望清单--需要授权

# 工具 参数 说明
27 addToWishlist productId, sessionId 将产品添加到愿望清单中。复制安全。
28 getWishlist sessionId, page, pageSize 返回带有产品详细信息的分页愿望清单。

身份验证流程

# Step 1 — Get a session
sessionId = serverToServerLogin(
  phone    = "9999999999",
  platform = "WEB",
  secret   = "mock-platform-secret-key"
)

# Step 2 — Use sessionId in all authenticated tools
addToCart(productId=<id>, quantity=1, sessionId=<sessionId>)

餐厅和Swiggy刮刀工具

该服务器包括一个完整的Swiggy数据抓取器和餐厅查询层,增加了 12个新的MCP工具 用于食品配送用例。

它在创业中是如何运作的

订单 组件 操作
1 CityDataInitializer 用lat/lng(幂等)为印度50个主要城市播种
2 SeedDataLoader 如果 classpath:db/seed/seed-data.json 存在,餐厅桌子是空的,加载刮餐厅+菜单
3 ProductSeedLoader 如果 classpath:db/seed/products-seed.json 存在,产品表为空,加载70个预生成的产品
4 SampleRestaurantDataSeeder 如果餐厅桌子仍然是空的,则加载10个硬编码的演示餐厅作为后备
5 ScraperAutoStartRunner 如果 app.scraper.auto-start=true,异步启动实时抓取

餐厅查询工具(6个工具)

工具 参数 说明
listRestaurantCities -- 印度所有50个拥有餐厅数量和刮擦状态的城市
searchRestaurants cityName, cuisine, name, isPureVeg, page, pageSize 按任意组合搜索;按评级排序的结果
getRestaurantBySwiggyId swiggyId 餐厅详细信息
getRestaurantMenu swiggyId 按类别分组的完整菜单,包括项目价格(以印度卢比计)
searchMenuItems query, cityName, page, pageSize 按名称查找城市中所有餐厅的菜肴
filterRestaurantMenuItems swiggyId, isVeg, inStock 按蔬菜/非蔬菜、可用性筛选餐厅菜单

刮板控制工具(6个工具)

工具 参数 说明
getScraperStatus -- 城市/餐厅/菜单计数;刮擦是否正在运行
startRestaurantScraping -- 对所有未被抓取的城市开始异步抓取(跳过已完成)
scrapeRestaurantsForCity cityName 同步报废单个城市;返回新餐厅数量
startMenuScraping -- 为所有没有菜单的餐厅启动异步菜单抓取
scrapeRestaurantMenu swiggyId 同步删除一家餐厅的菜单
exportSeedData -- 将所有数据导出到 ./seed-export/seed-data.json 为承诺

从Swiggy抓取实时数据

要求: 网络访问 www.swiggy.com.服务器必须在能够访问Swiggy的API的计算机上运行。

第1步-取消所有餐厅:

{ "name": "startRestaurantScraping", "arguments": {} }

监视器 getScraperStatus每个城市大约需要30-120秒(速率限制为1.5秒)。所有50个城市都需要1~2个小时。

步骤2–废弃菜单:

{ "name": "startMenuScraping", "arguments": {} }

数千家餐厅可能需要几个小时。两个刮刀都是 渐进的 –可以随时中断和恢复。

步骤3–检查进度:

{ "name": "getScraperStatus", "arguments": {} }

退货 totalCities, scrapedCities, totalRestaurants, restaurantsWithMenu以及奔跑的旗帜。


种子数据管道

种子数据管道允许您将抓取的数据提交到git,这样每次新部署都会满载启动,不需要重新抓取。

导出抓取的数据

刮完之后,打电话给 exportSeedData MCP工具:

{ "name": "exportSeedData", "arguments": {} }

这写道 ./seed-export/seed-data.json --一个包含所有餐厅及其完整菜单的便携式JSON文件。

提交种子文件

cp seed-export/seed-data.json src/main/resources/db/seed/seed-data.json
git add src/main/resources/db/seed/seed-data.json
git commit -m "chore: add scraped Swiggy restaurant seed data (N restaurants)"
git push

重建和部署

mvn clean package -DskipTests
java -jar target/mcp-server-1.0.0-SNAPSHOT.jar

在首次使用新数据库启动时, SeedDataLoader 检测种子文件并自动导入所有数据。 SampleRestaurantDataSeeder 当数据已经存在时跳过。

重新抓取后的增量更新

当你重新运行刮刀来挑选新餐厅时:

  • 城市: scrapeRestaurantsForCity Swiggy ID的更新——更新现有餐厅,插入新餐厅
  • 菜单: startMenuScraping 跳过以下餐厅 menuScraped = true;使用 scrapeRestaurantMenu 强制刷新一家餐厅
  • 重新抓取后,致电 exportSeedData 再次复制新文件,并提交

数据持久性(开发)

开发H2数据库持续存在 ./data/mockecomdb.* (基于文件的H2)。数据在服务器重启后仍然有效。这 ./data/ 目录是 .gitignored——仅出口 seed-data.json 在 src/main/resources/db/seed/ 承诺。


LLM产品数据生成

服务器可以使用Anthropic LLM(Claude)来生成 按需提供真实的印度市场产品数据.当产品搜索或筛选器未返回现有结果,并且配置了Anthropic API密钥时,服务器调用 claude-haiku-4-5 生成产品,将其保存到数据库,并将其返回给调用者。

运作原理

MCP call: searchProducts / filterProducts
    │
    ▼
productRepository.searchByQuery(...)  →  results found?
    │ no results                              │ yes
    ▼                                         ▼
LlmProductGeneratorService.isAvailable()?  return existing data
    │ yes (API key set)        │ no
    ▼                          ▼
callAnthropicAPI(...)     MockDataGeneratorService (deterministic fallback)
    │
    ▼
Parse JSON → save Products + ProductAttributes to DB
    │
    ▼
Return newly generated products to MCP caller

生成的产品是 持久化到数据库 立即,所以:

  • 对同一查询的后续调用返回已保存的产品(没有额外的API调用)
  • 数据可以导出为种子JSON并提交,以便新的部署开始完全加载

设置--启用LLM生成

选项A:环境变量(推荐)

export ANTHROPIC_API_KEY=sk-ant-your-key-here
mvn spring-boot:run

选项B:application.yml

app:
  llm:
    api-key: sk-ant-your-key-here
    model: claude-haiku-4-5-20251001   # default, any Claude model works
    enabled: true

注: API密钥故意不提交给git。始终通过环境变量或局部变量传递它 .env 文件已从版本控制中排除。

当 ANTHROPIC_API_KEY 未设置, LlmProductGeneratorService.isAvailable() 回报 false 服务器回退到 MockDataGeneratorService --从哈希种子生成的确定性模拟产品。不会抛出任何错误。

种子产品-Seed.json从LLM输出

通过MCP调用(或直接通过REST API)生成产品后,将其导出到种子文件:

{ "name": "exportProductSeedData", "arguments": {} }

这写道 ./seed-export/products-seed.json。将其复制到resources目录并提交:

cp seed-export/products-seed.json src/main/resources/db/seed/products-seed.json
git add src/main/resources/db/seed/products-seed.json
git commit -m "chore: add LLM-generated product seed data"
git push

在下一次新的部署中, ProductSeedLoader (@Order 3)在调用LLM之前自动加载文件。

加载产品种子的启动订单

订单 组件 操作
1 CityDataInitializer 用lat/lng(幂等)为印度50个主要城市播种
2 SeedDataLoader 负载 classpath:db/seed/seed-data.json (餐厅+菜单)如果DB为空
3 ProductSeedLoader 负载 classpath:db/seed/products-seed.json 如果产品表为空
4 SampleRestaurantDataSeeder 回退:如果仍为空,则加载10个硬编码的演示餐厅
5 ScraperAutoStartRunner 如果 app.scraper.auto-start=true,开始实时抓取

预加载种子数据

承诺 src/main/resources/db/seed/products-seed.json 包含 70产品 在所有类别中:

类别 计数 品牌
电子 15 三星、OnePlus、苹果、boAt、索尼、小米、惠普、戴尔、华硕、JBL、Realme、佳能
时尚 15 Fabindia、巴塔、李维斯、彪马、艾伦·索利、Manyavar、耐克、阿迪达斯、Fossil、W for Women
杂货 15 塔塔、财富、阿穆尔、Aashirvaad、MDH、Haldirams、雀巢、Dabur、Patanjali、Saffola
美丽 13 拉克梅、喜马拉雅、玛玛尔思、哇、欧莱雅、露得清、多芬、卡尼尔、妮维雅、李子
主页 12 威望、飞利浦、巴贾吉、大提琴、戈德雷、弥尔顿、索利莫、鸽子、尼尔卡马尔、蝴蝶

所有产品都使用现实的印度卢比定价,并提供有意义的折扣,并包括3-5个特定类别的属性(例如,电子产品的保修+RAM+处理器;杂货的保质期+FSSAI认证)。

环境变量摘要

变量 默认值 描述
ANTHROPIC_API_KEY (空) 无烟煤API键。设置后,启用LLM产品生成。
app.llm.model claude-haiku-4-5-20251001 用于生成的Claude模型(设置在 application.yml)
app.llm.enabled true 主开关;着手 false 即使存在API密钥,也要强制使用模拟数据

测试用例

测试套件(7个文件,83个测试)

文件 涵盖的工具 测试计数 关键场景
MockEcomMcpServerApplicationTests -- 1 成功加载Spring上下文
ProductToolsIntegrationTest 1–7 ~20 多类别搜索、分页、过滤器、交付时间
AuthAndCartFlowTest 8–14 ~9 登录有效/无效、购物车生命周期、结账、付款
OrderManagementTest 15–20 ~15 订单检索、取消、退货、OTP、发货跟踪
TicketAndReviewTest 21–26 ~18 工单创建(所有类型)、评论、产品和交付评论
WishlistTest 27–28 ~10 添加、查看、分页、防止重复
EndToEndShoppingJourneyTest 1–28 ~10 涵盖所有5个类别的完整购物之旅
MockDataGeneratorTest -- ~10 类别检测、产品生成、属性生成

端到端流程(端到端购物旅程测试)

1.  serverToServerLogin        → sessionId
2.  searchProducts             → productId
3.  filterProducts             → filtered list
4.  getFilters                 → filter facets
5.  getSortOptions             → sort options
6.  getProductDetails          → product info
7.  getProductReviews          → reviews
8.  getDeliveryTime            → estimate
9.  addToWishlist              → wishlistItem
10. getWishlist                → wishlist
11. addToCart (x2 products)    → cartId
12. checkout                   → checkoutId
13. getAddresses               → addressId
14. selectAddress              → confirmed
15. initiatePayment (UPI)      → paymentId, orderId
16. getPaymentStatus           → SUCCESS
17. getOrderDetails            → order + items
18. getOrders                  → history
19. getShipments               → shipmentId
20. sendDeliveryOtp            → OTP sent
21. createTicket               → ticketId
22. getTickets                 → list
23. getTicketDetails           → ticket + comments
24. addTicketComment           → comment added
25. submitProductReview        → review saved
26. submitShipmentReview       → review saved

在本地运行测试

# Run all tests (uses test profile with separate H2 DB)
mvn test

# Run a specific test class
mvn test -Dtest=EndToEndShoppingJourneyTest

# Run a specific test method
mvn test -Dtest=ProductToolsIntegrationTest#testSearchProducts

# Run with verbose output
mvn test -Dsurefire.useFile=false

# Run tests + generate coverage report (if jacoco configured)
mvn verify

# Skip tests during build
mvn clean package -DskipTests

测试配置文件

测试使用 application-test.yml:

  • 在内存DB中分离H2: jdbc:h2:mem:testdb
  • 为每次测试运行创建新的架构(ddl-auto: create-drop)
  • NON_KEYWORDS=VALUE 添加以避免H2 SQL关键字冲突
  • 禁用SQL日志记录以获得更清晰的输出

CI(GitHub操作)

通过以下方式在每次推送/PR上自动运行测试 .github/workflows/build.yml:

  • Java 21(temurin),Maven缓存
  • mvn clean verify -Dspring.profiles.active=test
  • JAR工件上传成功

生产部署

Docker Compose(推荐)

# Build the JAR
mvn clean package -DskipTests

# Start app + PostgreSQL
docker-compose up --build -d

# View logs
docker-compose logs -f app

# Stop
docker-compose down

服务已启动:

  • 应用 --端口上的Spring Boot 8080,个人资料 prod
  • Postgres --PostgreSQL 16端口 5432,DB mockecomdb

PostgreSQL数据保存在Docker卷中 pgdata.

自定义环境变量

docker-compose up \
  -e DB_PASSWORD=supersecret \
  -e SERVER_PORT=9000 \
  --build

或者创建一个 .env 旁边的文件 docker-compose.yml:

DB_URL=jdbc:postgresql://myhost:5432/mydb
DB_USERNAME=myuser
DB_PASSWORD=mysecret
SPRING_PROFILES_ACTIVE=prod

手动JAR部署

# Build
mvn clean package -DskipTests

# Run with prod profile
java -jar target/mcp-server-1.0.0-SNAPSHOT.jar \
  --spring.profiles.active=prod \
  --server.port=8080 \
  --DB_URL=jdbc:postgresql://localhost:5432/mockecomdb \
  --DB_USERNAME=postgres \
  --DB_PASSWORD=postgres

Kubernetes/云

服务器是无状态的(数据库中的所有状态),因此可以水平扩展。关键考虑因素:

  • 集 spring.jpa.hibernate.ddl-auto=update (已设置 application-prod.yml)
  • 使用托管PostgreSQL服务(RDS、Cloud SQL等)
  • 将环境变量挂载为Kubernetes的秘密
  • 活体探针: GET /actuator/health
  • 准备就绪探针: GET /actuator/health

连接MCP客户端

克劳德桌面

编辑 ~/Library/Application Support/Claude/claude_desktop_config.json (macOS)或 %APPDATA%\Claude\claude_desktop_config.json (Windows):

{
  "mcpServers": {
    "mock-ecom": {
      "url": "http://localhost:8080/sse",
      "type": "sse"
    }
  }
}

重新启动克劳德桌面。您将看到28个可用工具。

克劳德代码(CLI)

# Add MCP server
claude mcp add mock-ecom --transport sse http://localhost:8080/sse

# List configured servers
claude mcp list

# Remove
claude mcp remove mock-ecom

或编辑 ~/.claude/settings.json:

{
  "mcpServers": {
    "mock-ecom": {
      "type": "sse",
      "url": "http://localhost:8080/sse"
    }
  }
}

VS代码(复制/继续/临床)

添加到您的VS代码 settings.json:

{
  "mcp": {
    "servers": {
      "mock-ecom": {
        "type": "sse",
        "url": "http://localhost:8080/sse"
      }
    }
  }
}

自定义MCP客户端(Python)

from mcp import ClientSession
from mcp.client.sse import sse_client

async with sse_client("http://localhost:8080/sse") as (read, write):
    async with ClientSession(read, write) as session:
        await session.initialize()
        tools = await session.list_tools()
        result = await session.call_tool("searchProducts", {
            "query": "laptop",
            "page": 0,
            "pageSize": 10
        })

自定义MCP客户端(JavaScript/TypeScript)

import { Client } from "@modelcontextprotocol/sdk/client/index.js";
import { SSEClientTransport } from "@modelcontextprotocol/sdk/client/sse.js";

const transport = new SSEClientTransport(
  new URL("http://localhost:8080/sse")
);
const client = new Client({ name: "my-client", version: "1.0.0" }, {});
await client.connect(transport);

const result = await client.callTool("serverToServerLogin", {
  phone: "9999999999",
  platform: "WEB",
  secret: "mock-platform-secret-key"
});

正在验证连接

# Test SSE endpoint is alive
curl -N http://localhost:8080/sse

# Health check
curl http://localhost:8080/actuator/health

状态 & 全部

当前状态:✅ 工作

功能 状态
28个MCP工具通过SSE暴露 ✅ 完成
模拟数据生成(5类) ✅ 完成
通过Anthropic API生成LLM产品 ✅ 完成
70个产品种子文件(共5个类别) ✅ 完成
新部署时自动加载产品种子 ✅ 完成
基于H2文件的开发数据库(在重新启动后持续存在) ✅ 完成
PostgreSQL生产支持 ✅ 完成
基于会话的身份验证 ✅ 完成
完整的购物流程(搜索→ 顺序) ✅ 完成
支持票和评论 ✅ 完成
产品和装运审核 ✅ 完成
愿望清单 ✅ 完成
Swiggy餐厅摩天大楼(50个城市) ✅ 完成
餐厅+菜单种子数据管道 ✅ 完成
React Web UI(餐厅+产品浏览器) ✅ 完成
用于所有数据(餐厅、产品、统计数据)的REST API ✅ 完成
83次集成测试✅ 完成
Docker+Docker组合✅ 完成
GitHub操作CI ✅ 完成
一个命令本地启动脚本 ✅ 完成

TODO/未来增强功能

优先级 项目
高 通过可配置网关添加真正的OTP交付(短信/电子邮件)
高 添加地址创建工具(当前地址是自动生成的)
高 添加产品图片上传支持
中等 添加优惠券/折扣码工具
中等 添加产品库存管理工具
中等 添加管理工具(更新订单状态、解决工单)
中等 基于JWT的身份验证作为平台秘密的替代方案
中等 REST端点的Swagger/OpenAPI文档
低 为产品搜索结果添加Redis缓存
低 添加Elasticsearch以获得更好的全文搜索
低 多语言/多货币支持
低 MCP工具调用的速率限制
低 订单状态更改的Webhook通知
低 将订单导出为PDF/CSV

已知限制

  • 无法通过MCP工具创建地址(可以使用自动生成的模拟地址)
  • 支付处理完全模拟(UPI/CARD/NETBANKING/WALLET总是成功,COD总是成功)
  • 生成交付OTP,但实际上并没有发送到任何地方
  • 产品图片来源于 picsum.photos (外部依赖性)
  • H2数据 持续 在开发模式下跨重启(基于文件的数据库 ./data/).删除 ./data/ 重置。
  • Live Swiggy抓取需要无限制的互联网访问 www.swiggy.com;沙盒/受限环境必须使用提交的种子文件

文档