Shopping List MCP Server

Shopping List MCP Server

Enables AI assistants to manage a shared shopping list by adding, viewing, updating, and deleting products for different people via MCP tools.

Category
访问服务器

README

Shopping List App

A simple shopping list app built with Next.js 15 (App Router). Every product belongs to a person, can be marked as purchased, and can be deleted.

This project is intentionally small — it's a learning/exercise project for IMS Praxis 5.

Features

  • Add products, mark them as purchased, delete them
  • Filter by person
  • Persistence via a simple JSON file (no database server required)
  • Three ways to work with the data:
    • Server Actions – used directly by the frontend (src/app/actions.ts)
    • REST API – available under /api/products, e.g. for external clients or curl
    • MCP server – exposes the same data as MCP tools (e.g. for ChatGPT) by calling the REST API

Tech Stack

  • Next.js 15 / React 19, App Router
  • TypeScript
  • No database, no ORM – persistence via a JSON file (data/products.json)
  • MCP TypeScript SDK via mcp-handler, using the Streamable HTTP transport

Getting Started

npm install
npm run dev

Open the app at http://localhost:3000.

No configuration or .env file is needed to run the app locally. See Environment Variables for the one optional setting used by the MCP server.

Project Structure

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)

Data Model

interface Product {
  id: string;
  name: string;
  person: string;
  purchased: boolean;
  createdAt: string; // ISO date
}

Persistence

All products live in data/products.json. All file access is encapsulated in src/lib/productRepository.ts — neither the UI nor the API routes read or write the file directly. The repository exposes:

getProducts()
getProductsByPerson(person)
getProductById(id)
addProduct(product)
updateProduct(id, changes)
deleteProduct(id)

Note: This file-based persistence is intentionally just a prototype/development solution. On Vercel (and other serverless platforms) the local filesystem is not reliably persistent across requests or deployments — writes can be lost. For production use, productRepository.ts should be replaced with a real, persistent database (e.g. Turso). Since the rest of the app (UI, Server Actions, API routes) only ever talks to the data through the exported repository functions, that swap only touches this one file.

Frontend ↔ Backend

The frontend (page.tsx, ProductForm, ProductList) uses Next.js Server Actions (src/app/actions.ts) to create, update, and delete products. There is no fetch call in the client — the Server Actions call the repository directly and then trigger a refresh of the server-rendered data via revalidatePath("/").

The REST API under /api/products is independent and can be used separately (e.g. by external tools, scripts, or for testing) — it reads and writes the same data source.

REST API

Read products

GET /api/products
GET /api/products?person=Rinaldo   # filter by person, case-insensitive
GET /api/products/:id

Add a product

POST /api/products
Content-Type: application/json

{ "name": "Milk", "person": "Rinaldo" }

id, purchased (false), and createdAt are set automatically.

Update a product

PATCH /api/products/:id
Content-Type: application/json

{ "purchased": true }

Not all fields need to be provided (name, person, purchased are each optional and independently updatable).

Delete a product

DELETE /api/products/:id

Error responses

{ "error": "Product not found" }
Case Status
Invalid/empty request 400
Unknown ID 404
Internal error 500

curl examples

# 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 Server

A Model Context Protocol server exposes the shopping list to MCP clients (e.g. ChatGPT). It talks only to the REST API above — never to productRepository.ts or data/products.json directly — so it stays independent of whatever persistence backend the API uses.

MCP client → MCP server → REST API → productRepository → data/products.json

Endpoint: /api/mcp (Streamable HTTP transport), implemented in src/app/api/[transport]/route.ts via mcp-handler.

Tools:

Tool Description
list_products List products, optionally filtered by person
add_product Add a product for a person
update_product Update name/person/purchased of a product
mark_product_purchased Convenience tool to mark a product as (not) purchased
delete_product Delete a product

Requires the same bearer token as the REST API (see Authentication). Test it locally with the MCP Inspector:

npx @modelcontextprotocol/inspector --cli http://localhost:3000/api/mcp --method tools/list \
  --header "Authorization: Bearer $SHOPPING_API_KEY"

Environment Variables

Variable Required Description
SHOPPING_API_BASE_URL No Base URL the MCP server uses to call the REST API. Defaults to http://localhost:3000 locally, or https://$VERCEL_URL on Vercel. Set explicitly if you use a custom domain in production.
SHOPPING_API_KEY Yes Shared secret required as Authorization: Bearer <key> by the REST API and the MCP endpoint. Requests without a matching token are rejected.

See .env.example.

Authentication

The REST API and the MCP endpoint both require a bearer token — a single shared secret configured via SHOPPING_API_KEY. There is no per-user login; this is a simple static-token check suitable for a prototype, not full OAuth.

curl http://localhost:3000/api/products \
  -H "Authorization: Bearer $SHOPPING_API_KEY"

A request with a missing or wrong token gets 401 Unauthorized. If SHOPPING_API_KEY isn't set on the server at all, requests are rejected with 500 (fail closed, not open).

Server Actions (src/app/actions.ts) are unaffected — they call productRepository directly on the server and never go through the REST API, so they don't need a token.

Known Limitations

  • No authentication/authorization on either the REST API or the MCP server — anyone can see and edit all products. Planned as a follow-up.
  • Concurrent writes are serialized within a single process (a simple queue in productRepository.ts), which is fine for a prototype but not for production multi-instance deployments.
  • As noted above, persistence is not deployment-safe on serverless platforms like Vercel — a real database (e.g. Turso) is the intended next step.

Deploy

The app can be deployed like any Next.js project, e.g. on Vercel. Before using it in production, the data persistence layer (see above) should be swapped out for a real database.

More on Next.js: Next.js Documentation · Learn Next.js

推荐服务器

Baidu Map

Baidu Map

百度地图核心API现已全面兼容MCP协议,是国内首家兼容MCP协议的地图服务商。

官方
精选
JavaScript
Playwright MCP Server

Playwright MCP Server

一个模型上下文协议服务器,它使大型语言模型能够通过结构化的可访问性快照与网页进行交互,而无需视觉模型或屏幕截图。

官方
精选
TypeScript
Magic Component Platform (MCP)

Magic Component Platform (MCP)

一个由人工智能驱动的工具,可以从自然语言描述生成现代化的用户界面组件,并与流行的集成开发环境(IDE)集成,从而简化用户界面开发流程。

官方
精选
本地
TypeScript
Audiense Insights MCP Server

Audiense Insights MCP Server

通过模型上下文协议启用与 Audiense Insights 账户的交互,从而促进营销洞察和受众数据的提取和分析,包括人口统计信息、行为和影响者互动。

官方
精选
本地
TypeScript
VeyraX

VeyraX

一个单一的 MCP 工具,连接你所有喜爱的工具:Gmail、日历以及其他 40 多个工具。

官方
精选
本地
graphlit-mcp-server

graphlit-mcp-server

模型上下文协议 (MCP) 服务器实现了 MCP 客户端与 Graphlit 服务之间的集成。 除了网络爬取之外,还可以将任何内容(从 Slack 到 Gmail 再到播客订阅源)导入到 Graphlit 项目中,然后从 MCP 客户端检索相关内容。

官方
精选
TypeScript
Kagi MCP Server

Kagi MCP Server

一个 MCP 服务器,集成了 Kagi 搜索功能和 Claude AI,使 Claude 能够在回答需要最新信息的问题时执行实时网络搜索。

官方
精选
Python
e2b-mcp-server

e2b-mcp-server

使用 MCP 通过 e2b 运行代码。

官方
精选
Neon MCP Server

Neon MCP Server

用于与 Neon 管理 API 和数据库交互的 MCP 服务器

官方
精选
Exa MCP Server

Exa MCP Server

模型上下文协议(MCP)服务器允许像 Claude 这样的 AI 助手使用 Exa AI 搜索 API 进行网络搜索。这种设置允许 AI 模型以安全和受控的方式获取实时的网络信息。

官方
精选