Skip to main content
Glama
bbwrl

Shopping List MCP Server

by bbwrl

買い物リストアプリ

Next.js 15(App Router)で構築されたシンプルな買い物リストアプリです。すべての商品は人に紐づき、購入済みのマークや削除が可能です。

このプロジェクトは意図的に小規模に設計されています — IMS Praxis 5 の学習・練習用プロジェクトです。

機能

  • 商品の追加、購入済みマーク、削除

  • 人によるフィルタリング

  • シンプルなJSONファイルによる永続化(データベースサーバー不要)

  • データを操作する3つの方法:

    • サーバーアクション – フロントエンドから直接使用(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サーバーで使用する1つのオプション設定については環境変数を参照してください。

プロジェクト構成

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ルート)は公開されたリポジトリ関数を通じてのみデータにアクセスするため、この置き換えはこの1つのファイルのみに影響します。

フロントエンド ↔ バックエンド

フロントエンド(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サーバー

Model Context Protocol サーバーが買い物リストをMCPクライアント(例:ChatGPT)に公開します。上記のREST APIとのみ通信し、productRepository.ts や data/products.json を直接操作することはありません。そのため、APIが使用する永続化バックエンドから独立しています。

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

エンドポイント: /api/mcp(Streamable HTTPトランスポート)、src/app/api/[transport]/route.ts で mcp-handler を介して実装。

ツール:

ツール

説明

list_products

商品一覧を表示(人でフィルタリング可能)

add_product

人のために商品を追加

update_product

商品の名前/人/購入済みを更新

mark_product_purchased

商品を購入済み(未購入)にする便利ツール

delete_product

商品を削除

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

いいえ

MCPサーバーがREST APIを呼び出す際のベースURL。ローカルではデフォルトで http://localhost:3000、Vercelでは https://$VERCEL_URL。本番でカスタムドメインを使用する場合は明示的に設定。

SHOPPING_API_KEY

はい

REST APIとMCPエンドポイントが Authorization: Bearer <key> として要求する共有シークレット。一致するトークンがないリクエストは拒否。

.env.example を参照。

認証

REST APIとMCPエンドポイントはどちらもベアラートークン(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 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