Shopping List MCP Server
购物清单应用
一个基于 Next.js 15(App Router)构建的简单购物清单应用。每个商品归属于一个人,可以标记为已购买,也可以删除。
该项目特意设计得小巧——它是 IMS Praxis 5 的学习/练习项目。
功能
添加商品、标记为已购买、删除商品
按人员筛选
通过简单的 JSON 文件持久化(无需数据库服务器)
三种操作数据的方式:
服务器操作(Server Actions) – 由前端直接使用(
src/app/actions.ts)REST API – 通过
/api/products提供,例如供外部客户端或curl使用MCP 服务器 – 通过调用 REST API,将相同的数据以 MCP 工具的形式暴露(例如供 ChatGPT 使用)
Related MCP server: lista-compras-mcp
技术栈
Next.js 15 / React 19,App Router
TypeScript
无数据库,无 ORM – 通过 JSON 文件持久化(
data/products.json)MCP TypeScript SDK 通过
mcp-handler使用,采用 Streamable HTTP 传输
快速开始
npm install
npm run dev在 http://localhost:3000 打开应用。
本地运行应用无需配置或 .env 文件。关于 MCP 服务器使用的一个可选设置,请参见环境变量。
项目结构
src/
app/
page.tsx # Home page (Server Component), loads products server-side
actions.ts # Server Actions: addProductAction, togglePurchasedAction, deleteProductAction
api/
products/
route.ts # GET /api/products, POST /api/products
[id]/route.ts # GET/PATCH/DELETE /api/products/:id
[transport]/
route.ts # MCP endpoint (Streamable HTTP), served at /api/mcp
components/
ProductForm.tsx # Add-product form (uses a Server Action)
ProductList.tsx # List incl. toggle/delete (uses Server Actions)
lib/
productRepository.ts # the only place that touches the filesystem (data/products.json)
mcp/
server.ts # registers the MCP tools
shoppingApiClient.ts # MCP's only way to reach the data — calls the REST API, never the repository directly
types/
product.ts # Product type
data/
products.json # data store (created automatically if missing)数据模型
interface Product {
id: string;
name: string;
person: string;
purchased: boolean;
createdAt: string; // ISO date
}持久化
所有商品存放在 data/products.json 中。所有文件访问封装在 src/lib/productRepository.ts 中——无论是 UI 还是 API 路由都不会直接读写该文件。该仓库暴露:
getProducts()
getProductsByPerson(person)
getProductById(id)
addProduct(product)
updateProduct(id, changes)
deleteProduct(id)注意: 这种基于文件的持久化仅作为原型/开发解决方案。在 Vercel(以及其他无服务器平台)上,本地文件系统在请求或部署之间并不可靠持久——写入可能会丢失。对于生产环境,应将 productRepository.ts 替换为真正的持久化数据库(例如 Turso)。由于应用的其余部分(UI、服务器操作、API 路由)仅通过导出的仓库函数与数据交互,因此这种替换只涉及这一个文件。
前端 ↔ 后端
前端(page.tsx、ProductForm、ProductList)使用 Next.js 服务器操作(src/app/actions.ts)来创建、更新和删除商品。客户端没有 fetch 调用——服务器操作直接调用仓库,然后通过 revalidatePath("/") 触发服务器渲染数据的刷新。
/api/products 下的 REST API 是独立的,可以单独使用(例如供外部工具、脚本或测试使用)——它读写相同的数据源。
REST API
读取商品
GET /api/products
GET /api/products?person=Rinaldo # filter by person, case-insensitive
GET /api/products/:id添加商品
POST /api/products
Content-Type: application/json
{ "name": "Milk", "person": "Rinaldo" }id、purchased(false)和 createdAt 会自动设置。
更新商品
PATCH /api/products/:id
Content-Type: application/json
{ "purchased": true }无需提供所有字段(name、person、purchased 各自可选且可独立更新)。
删除商品
DELETE /api/products/:id错误响应
{ "error": "Product not found" }情况 | 状态码 |
无效/空请求 | 400 |
未知 ID | 404 |
内部错误 | 500 |
curl 示例
# Add a product
curl -X POST http://localhost:3000/api/products \
-H "Authorization: Bearer $SHOPPING_API_KEY" \
-H "Content-Type: application/json" \
-d '{"name":"Milk","person":"Rinaldo"}'
# List a person's products
curl "http://localhost:3000/api/products?person=Rinaldo" \
-H "Authorization: Bearer $SHOPPING_API_KEY"
# Mark a product as purchased
curl -X PATCH http://localhost:3000/api/products/PRODUCT_ID \
-H "Authorization: Bearer $SHOPPING_API_KEY" \
-H "Content-Type: application/json" \
-d '{"purchased":true}'
# Delete a product
curl -X DELETE http://localhost:3000/api/products/PRODUCT_ID \
-H "Authorization: Bearer $SHOPPING_API_KEY"MCP 服务器
一个模型上下文协议服务器将购物清单暴露给 MCP 客户端(例如 ChatGPT)。它仅与上述 REST API 通信——从不直接访问 productRepository.ts 或 data/products.json——因此它独立于 API 所使用的任何持久化后端。
MCP client → MCP server → REST API → productRepository → data/products.json端点: /api/mcp(Streamable HTTP 传输),通过 mcp-handler 在 src/app/api/[transport]/route.ts 中实现。
工具:
工具 | 描述 |
| 列出商品,可选按人员筛选 |
| 为某人添加商品 |
| 更新商品的名称/人员/已购买状态 |
| 便捷工具,将商品标记为(未)已购买 |
| 删除商品 |
需要与 REST API 相同的 bearer token(参见身份验证)。使用 MCP Inspector 在本地测试:
npx @modelcontextprotocol/inspector --cli http://localhost:3000/api/mcp --method tools/list \
--header "Authorization: Bearer $SHOPPING_API_KEY"环境变量
变量 | 必需 | 描述 |
| 否 | MCP 服务器用于调用 REST API 的基础 URL。本地默认为 |
| 是 | REST API 和 MCP 端点所需的共享密钥,作为 |
参见 .env.example。
身份验证
REST API 和 MCP 端点都需要一个 bearer token——一个通过 SHOPPING_API_KEY 配置的共享密钥。没有按用户登录;这是一个适用于原型的简单静态令牌检查,并非完整的 OAuth。
curl http://localhost:3000/api/products \
-H "Authorization: Bearer $SHOPPING_API_KEY"缺少或错误的令牌请求将返回 401 Unauthorized。如果服务器上根本没有设置 SHOPPING_API_KEY,请求将被拒绝并返回 500(故障关闭,而非开放)。
服务器操作(src/app/actions.ts)不受影响——它们直接在服务器上调用 productRepository,从不经过 REST API,因此不需要令牌。
已知限制
REST API 和 MCP 服务器均无身份验证/授权——任何人都可以查看和编辑所有商品。计划作为后续改进。
并发写入在单个进程内串行化(
productRepository.ts中的简单队列),这对原型来说没问题,但不适用于生产环境的多实例部署。如上所述,在 Vercel 等无服务器平台上,持久化在部署中不安全——真正的数据库(例如 Turso)是下一步计划。
部署
该应用可以像任何 Next.js 项目一样部署,例如在 Vercel 上。在生产环境中使用之前,应将数据持久化层(见上文)替换为真正的数据库。
更多关于 Next.js 的信息:Next.js 文档 · 学习 Next.js
This server cannot be deployed
Maintenance
Related MCP Connectors
Manage Superlist tasks and lists in plain language from any MCP-compatible AI agent.
Persistent shopping memory for AI assistants. The AI reasons; Kaufliste stores and executes.
Hosted MCP for e-commerce: live product catalog, stock, and pricing for AI agents.
Cross-tool persistent memory and context for AI assistants over MCP.
Related MCP Servers
- AlicenseNot gradedqualityBmaintenanceMCP server that gives AI agents full control over grocery lists, todos, and packing lists. Your AI creates lists, adds items, checks them off, and shares with family/friends.4MIT
- FlicenseAqualityDmaintenanceEnables AI assistants to manage shopping lists and items (create, edit, delete, mark as purchased) via integration with a backend API.8-
- AlicenseNot gradedqualityBmaintenanceEnables AI assistants to read current pantry inventory and low-stock shopping needs, export a shopping queue, and perform idempotent inventory adjustments and catalog link management through remote MCP tools.MIT
- AlicenseNot gradedqualityAmaintenanceEnables AI assistants to manage Bring! shopping lists through MCP, including adding, removing, renaming, and batch-updating items while resolving them against Bring's real catalog so they render with the correct language, icon, and aisle.MIT