Skip to main content
Glama
README.md
# 侘茶點餐系統 MCP Server

以台南侘茶飲料店真實菜單為基礎的教學用 MCP Server,透過 stdio 傳輸與 LLM Client(如 Claude Desktop)溝通,完整涵蓋 MCP 三大核心概念:**Tools**、**Resources**、**Prompts**,並以 `get_menu` Tool 示範 MCP Apps 的互動式 UI 擴充。

## 特色

- **86 款飲品、11 大分類、8 種加料**,資料庫首次啟動自動 seed
- 6 個 Tools、5 個 Resources、2 個 Prompts,一站式體驗 MCP 全功能
- `get_menu` 內建互動式菜單 UI(MCP Apps),在支援的 Host 中會直接渲染 iframe
- SQLite(WAL 模式)本機持久化,免額外部署資料庫

## 技術棧

- TypeScript(ESM,`NodeNext` module resolution)
- [`@modelcontextprotocol/sdk`](https://www.npmjs.com/package/@modelcontextprotocol/sdk) v1.x — MCP Server SDK
- [`@modelcontextprotocol/ext-apps`](https://www.npmjs.com/package/@modelcontextprotocol/ext-apps) — MCP Apps 擴充(互動式 UI)
- `better-sqlite3` — SQLite 嵌入式資料庫
- `zod` v4 — Tool 參數 schema 驗證
- `vite` + `vite-plugin-singlefile` — UI 打包為單一 HTML
- `vitest` + `@vitest/coverage-v8` — 測試與覆蓋率
- `pnpm` 套件管理

## 環境需求

- Node.js 22(見 `.node-version`)
- pnpm

## 快速開始

```bash
# 安裝依賴
pnpm install

# 開發模式(tsx 直接執行,會自動建立並 seed data/cha-cha.db)
pnpm run dev

# 打包(先打包 UI 再編譯 TypeScript)
pnpm run build

# 執行編譯後的版本
pnpm run start
```

首次執行 `pnpm run dev` 或 `pnpm run start` 時,會自動在專案根目錄建立 `data/cha-cha.db` 並寫入完整菜單資料,無需手動初始化。

## 常用指令

| 指令 | 說明 |
| --- | --- |
| `pnpm install` | 安裝依賴 |
| `pnpm run build` | 先打包 UI(Vite)再 `tsc` 編譯到 `dist/` |
| `pnpm run build:ui` | 僅打包 UI(`ui/` → `dist/ui/menu-app.html`) |
| `pnpm run dev` | `tsx` 直接執行 `src/index.ts`(開發用) |
| `pnpm run start` | 執行編譯後的 `dist/index.js` |
| `pnpm test` | `vitest run`(執行全部測試) |
| `pnpm vitest run tests/get-orders.test.ts` | 執行單一測試檔 |
| `pnpm vitest run -t "篩選"` | 依測試名稱片段過濾 |
| `pnpm vitest run --coverage` | 產生覆蓋率報告 |

## 接入 Client

- **Claude Desktop**:見 [`docs/claude-desktop-guide.md`](docs/claude-desktop-guide.md)
- **MCP Inspector**(除錯用):見 [`docs/inspector-guide.md`](docs/inspector-guide.md)

```bash
# 快速用 Inspector 測試
pnpm build
npx @modelcontextprotocol/inspector node dist/index.js
```

## 架構

進入點 `src/index.ts` 建立 `McpServer` 後,分別呼叫三個 register 函式注入功能:

```
src/
├── index.ts              進入點:建立 McpServer、註冊 Tools/Resources/Prompts、連接 stdio
├── db.ts                 SQLite 初始化、菜單 seed、共用查詢 helper
├── types.ts               共用型別(MenuItem、Topping、Order)與常數(甜度、冰量選項)
├── helpers.ts             菜單格式化函式
├── tools/                 6 個 Tool:查詢與操作
├── resources/              5 個 Resource:Client 端可主動讀取的資料
└── prompts/                2 個 Prompt:預定義提示模板
```

資料庫檔案存放於 `data/cha-cha.db`(不納入版控)。

### MCP Apps UI

`get_menu` Tool 使用 `registerAppTool` 加掛互動式菜單 UI,支援 MCP Apps 的 Host(如 Claude Desktop)會自動渲染 iframe。UI 原始碼在 `ui/`,透過 Vite 打包為 `dist/ui/menu-app.html` 單一檔案。

## 提供的功能

### Tools

| Tool | 說明 |
| --- | --- |
| `get_menu` | 查詢菜單(分類、飲品、加料、甜度冰量選項),支援 MCP Apps 的 Host 會渲染互動式菜單 UI |
| `get_orders` | 查詢訂單,可依 ID 精確查找,或依訂購人、領取狀態、日期篩選 |
| `create_order` | 建立訂單 |
| `pickup_order` | 標記訂單為已領取 |
| `cancel_order` | 取消尚未領取的訂單 |
| `recommend_drinks` | 依心情、咖啡因、預算、杯數推薦飲品 |

### Resources

| Resource | URI | 說明 |
| --- | --- | --- |
| `menu-categories` | `cha-cha://menu/categories` | 所有菜單分類列表 |
| `menu-category`(template) | `cha-cha://menu/category/{category}` | 指定分類的飲品清單(含價格與屬性) |
| `orders-list` | `cha-cha://orders/list` | 所有訂單列表 |
| `order-detail`(template) | `cha-cha://orders/{id}` | 單筆訂單詳情 |
| `orders-unpicked` | `cha-cha://orders/unpicked` | 未領取訂單清單 |

### Prompts

| Prompt | 參數 | 說明 |
| --- | --- | --- |
| `recommend` | `mood`(可選) | 帶入完整菜單,推薦 3 杯飲品並說明理由 |
| `order_summary` | 無 | 彙整目前所有訂單:每人明細、飲品統計、總金額、未領取提醒 |

## 業務規則

- `sugar_fixed = 1` 的飲品忽略使用者甜度參數,強制設為「固定甜度」
- 單杯總價 = 飲品價格 + Σ(加料價格);加料有免費項目(小珍珠、波霸、混珠,price = 0)
- 顧客常用口語簡稱點餐(如「波霸奶綠」其實是「茉香奶綠」加「波霸」加料),呼叫 `create_order` 前建議先用 `get_menu` 確認正確品名
- Tool 錯誤統一回傳 `{ content: [{ type: 'text', text }], isError: true }`

## 測試

測試檔案放在 `tests/` 目錄,使用 vitest。Tool handler 邏輯抽為獨立可匯出函式(如 `handleGetOrders`),與 `registerXxx` 註冊函式分離,方便直接測試 handler 而不需啟動 MCP Server。

覆蓋率設定於 `vitest.config.ts`,目前 `coverage.include` 限定在 `src/tools/get-orders.ts`,新增其他模組測試時需同步調整。

```bash
pnpm test
```

## 規格文件

- [`spec/spec.md`](spec/spec.md) — 完整技術規格書(SSOT:資料庫 schema、MCP 功能設計、菜單資料)
- [`spec/change/`](spec/change/) — 變更請求(CR-001 ~ CR-004)及對應任務清單

## 授權

ISC

TDQS

A3.9/5.0

Scored across 6 tools

Disambiguation5/5

Each tool targets a distinct action: menu browsing, recommendations, order creation, order query, pickup, and cancellation. There is no meaningful overlap; get_menu and recommend_drinks serve different selection purposes.

Naming Consistency4/5

Most tool names follow a clear lower_snake_case verb_noun pattern (create_order, get_menu, cancel_order). pickup_order is a slight deviation since 'pickup' is used as a verb-like noun, but it remains readable and consistent in style.

Tool Count5/5

Six tools is well-scoped for a focused beverage-ordering server. Each tool covers a necessary part of the workflow without redundancy.

Completeness4/5

The core ordering lifecycle is covered: menu lookup, recommendation, create, query, cancel, and pickup. A minor gap is the lack of an order update/modify tool for changing items before pickup.

Maintenance

ActivityMaintained
ResponsivenessNo issues