Skip to main content
Glama
bbwrl

Shopping List MCP Server

by bbwrl

Приложение «Список покупок»

Простое приложение для списка покупок, созданное с помощью Next.js 15 (App Router). Каждый продукт принадлежит человеку, может быть отмечен как купленный и удалён.

Этот проект намеренно небольшой — это учебный/тренировочный проект для IMS Praxis 5.

Возможности

  • Добавлять продукты, отмечать их как купленные, удалять

  • Фильтровать по человеку

  • Хранение данных в простом JSON-файле (не требуется сервер базы данных)

  • Три способа работы с данными:

    • Server Actions – используется напрямую фронтендом (src/app/actions.ts)

    • REST API – доступен по адресу /api/products, например, для внешних клиентов или curl

    • MCP server – предоставляет те же данные в виде инструментов MCP (например, для ChatGPT), вызывая REST API

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 transport

Начало работы

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 — ни пользовательский интерфейс, ни маршруты API не читают и не записывают файл напрямую. Репозиторий предоставляет:

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

Примечание: Это файловое хранение намеренно является лишь прототипным/разработочным решением. На Vercel (и других серверных платформах) локальная файловая система не обеспечивает надёжного сохранения данных между запросами или развёртываниями — записи могут быть потеряны. Для production-использования productRepository.ts следует заменить на настоящую постоянную базу данных (например, Turso). Поскольку остальная часть приложения (UI, Server Actions, маршруты API) взаимодействует с данными только через экспортированные функции репозитория, такая замена затрагивает лишь один этот файл.

Фронтенд ↔ Бэкенд

Фронтенд (page.tsx, ProductForm, ProductList) использует Next.js Server Actions (src/app/actions.ts) для создания, обновления и удаления продуктов. В клиенте нет вызова fetch — Server Actions напрямую вызывают репозиторий, а затем запускают обновление серверно отрисованных данных через revalidatePath("/").

REST API по адресу /api/products независим и может использоваться отдельно (например, внешними инструментами, скриптами или для тестирования) — он читает и записывает тот же источник данных.

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" }

Случай

Status

Некорректный/пустой запрос

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 Server

Сервер Model Context Protocol предоставляет список покупок MCP-клиентам (например, ChatGPT). Он общается только с вышеуказанным REST API — никогда напрямую с productRepository.ts или data/products.json — поэтому остаётся независимым от используемого бэкенда хранения данных.

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

Конечная точка: /api/mcp (Streamable HTTP transport), реализована в src/app/api/[transport]/route.ts через mcp-handler.

Инструменты:

Инструмент

Описание

list_products

Список продуктов, опционально отфильтрованных по человеку

add_product

Добавить продукт для человека

update_product

Обновить имя/человека/куплен у продукта

mark_product_purchased

Удобный инструмент для отметки продукта как (не) купленного

delete_product

Удалить продукт

Требует тот же bearer-токен, что и REST API (см. Аутентификация). Протестируйте локально с помощью MCP Inspector:

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

Переменные окружения

Переменная

Обязательная

Описание

SHOPPING_API_BASE_URL

Нет

Базовый URL, который MCP-сервер использует для вызова REST API. По умолчанию http://localhost:3000 локально или https://$VERCEL_URL на Vercel. Установите явно, если в production используется собственный домен.

SHOPPING_API_KEY

Да

Общий секрет, требуемый в виде Authorization: Bearer <key> для REST API и конечной точки MCP. Запросы без соответствующего токена отклоняются.

См. .env.example.

Аутентификация

REST API и конечная точка MCP требуют bearer-токен — единый общий секрет, задаваемый через SHOPPING_API_KEY. Логин для каждого пользователя отсутствует; это простая проверка статического токена, подходящая для прототипа, а не для полноценного OAuth.

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

Запрос с отсутствующим или неверным токеном получает 401 Unauthorized. Если SHOPPING_API_KEY вообще не установлен на сервере, запросы отклоняются с кодом 500 (закрытый отказ, а не открытый).

Server Actions (src/app/actions.ts) не затрагиваются — они вызывают productRepository напрямую на сервере и никогда не проходят через REST API, поэтому им не нужен токен.

Известные ограничения

  • Отсутствие аутентификации/авторизации как на REST API, так и на MCP-сервере — любой может просматривать и редактировать все продукты. Планируется как последующее улучшение.

  • Одновременные записи сериализуются в рамках одного процесса (простая очередь в productRepository.ts), что хорошо для прототипа, но не для production-развёртываний с несколькими экземплярами.

  • Как отмечено выше, хранение данных небезопасно при развёртывании на бессерверных платформах, таких как Vercel — следующем шагом предусмотрена настоящая база данных (например, Turso).

Развёртывание

Приложение можно развернуть как любой проект Next.js, например, на Vercel. Перед использованием в production следует заменить уровень хранения данных (см. выше) на настоящую базу данных.

Подробнее о Next.js: Next.js Documentation · Learn Next.js

Related MCP Connectors

Related MCP Servers

  • A
    license
    Not graded
    quality
    B
    maintenance
    MCP 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.
    4
    MIT
  • F
    license
    A
    quality
    D
    maintenance
    Enables AI assistants to manage shopping lists and items (create, edit, delete, mark as purchased) via integration with a backend API.
    8
    -
  • A
    license
    Not graded
    quality
    B
    maintenance
    Enables 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
  • A
    license
    Not graded
    quality
    A
    maintenance
    Enables 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