Skip to main content
Glama
README.md
# SlimWeb-MCP

SlimWeb-MCP 是 SlimWeb / Webless 電商後台的 Remote MCP 閘道。主要目標是讓使用者透過自己的 AI Client,例如 Codex、ChatGPT、Claude、Gemini、Grok,直接操作 SlimWeb 後台,而不是被迫學習 SlimWeb 內部的頁面編輯邏輯、資料欄位或管理流程。

這個 repo 是 MCP 架構與實作的入口。SlimWeb / Webless 仍然是商品、訂單、頁面、素材、設定、會員與權限的 source of truth。

## 目標

- 提供 SlimWeb 後台可用的 Remote MCP Server。
- 透過 Google 登入驗證使用者身份。
- 讓每一次 MCP tool 呼叫都綁定使用者、帳號、站台與權限。
- 以明確的 MCP tools 開放常見電商後台操作。
- 讓 AI Client 只透過 tools 操作 SlimWeb,不直接碰資料庫、Storage 或內部後台路由。
- 將這份 README 當作持續維護的 tool contract。每新增或修改 MCP tool,都必須同步更新本文件。

## 非目標

- 不取代 SlimWeb / Webless 後端。
- 不另存一份商品、訂單、頁面或會員資料。
- 不繞過 SlimWeb 原本的角色與權限檢查。
- 不綁定單一 AI Client。
- 不提供 raw SQL、raw database、raw storage credential 類型的 MCP tool。
- 不把整個後台 UI 自動化暴露成不受控的瀏覽器操作。

## 架構總覽

```mermaid
flowchart LR
    Client["使用者 AI Client<br/>Codex / ChatGPT / Claude / Gemini / Grok"]
    MCP["SlimWeb Remote MCP Server"]
    Auth["Google 登入<br/>OAuth / OIDC"]
    Session["SlimWeb MCP Session<br/>Token Broker"]
    Policy["權限與站台 Scope Guard"]
    SlimWeb["SlimWeb / Webless Backend"]
    Storage["SlimWeb Data + Assets"]

    Client -->|"MCP over HTTPS"| MCP
    MCP --> Auth
    MCP --> Session
    MCP --> Policy
    Policy --> SlimWeb
    SlimWeb --> Storage
```

Remote MCP Server 是 SlimWeb 前方的受控 adapter。AI Client 不直接連資料庫、Cloud Storage 或內部 admin route。Client 先完成 Google 登入,取得被限制範圍的 MCP session,再透過 tool discovery 得到可用工具,最後用 tools 操作 SlimWeb。

## 核心元件

### Remote MCP Server

Remote MCP Server 是 AI Client 對外連線的入口。

職責:

- 以 HTTPS 提供 MCP discovery 與 tool invocation。
- 對需要保護的 tools 強制要求登入。
- 驗證 tool input schema。
- 將 MCP request 轉成 SlimWeb 可執行的 application service 或 API 呼叫。
- 將 SlimWeb response 正規化成穩定的 MCP tool output。
- 回傳明確錯誤,例如未登入、權限不足、驗證失敗、需要確認、SlimWeb upstream error。

### Google 登入

Google 登入是 Remote MCP 的主要身份驗證方式。

職責:

- 透過 OAuth / OIDC 驗證 Google identity。
- 將 Google account 對應到 SlimWeb user。
- 建立或更新 SlimWeb MCP session。
- 將 session scope 限制在使用者可操作的 account、site、role、permissions。

預期登入流程:

1. AI Client 連到 SlimWeb Remote MCP Server。
2. 如果沒有有效 MCP session,server 回傳 authentication required 與 login URL。
3. 使用者在瀏覽器完成 Google 登入。
4. SlimWeb 驗證 Google identity,並綁定 SlimWeb user。
5. MCP Server 建立 scoped MCP session。
6. AI Client 重新進行 tool discovery 或 tool invocation。

### Session 與 Token Broker

Session layer 負責把 Google 驗證後的身份轉成 SlimWeb 可以接受的 MCP access。

規則:

- MCP session 必須是短效或可安全 refresh。
- token 不可包含 SlimWeb 內部 secret。
- MCP 驗證以 Web admin 為準,不以 webless 主會員 `accounts` 作為授權主體。
- Google 登入後必須能在 `site_admins` 找到至少一個擁有 `backend_ai_assistant` 權限的管理員身份,否則拒絕登入 MCP。
- session claims 至少要包含 Google `email`、`google_id`/`sub`、名稱與過期時間;站台與權限在每次 tool call 依公開 `site_code` 解析內部 `site_id` 後重新查 `site_admins`。
- 每次 tool 呼叫都要重新檢查權限,不可只依賴 discovery 時的結果。

### 權限與站台 Scope Guard

每個 tool 都必須在明確 scope 內執行。

最低 scope 欄位:

- `site_code`
- 內部解析後的 `site_id`
- `site_admin_id`
- `google_email`
- `google_sub`
- `permissions`

以下情況必須拒絕 request:

- 使用者未登入。
- MCP session 已過期。
- 指定站台內找不到對應 Google 帳號的 Web admin 身份。
- 該 Web admin 沒有 `backend_ai_assistant` 權限。
- 該 Web admin 沒有 tool 所需 permission。
- tool 嘗試修改指定 `site_code` 解析站台以外的資料。
- 高風險操作需要 confirmation,但 request 沒有 confirmation token。

### SlimWeb Backend Adapter

Adapter 是 MCP Server 與 SlimWeb / Webless 後端之間的唯一連接層。

職責:

- 將 MCP tool request 對應到 SlimWeb application service 或 HTTP API。
- 優先重用 SlimWeb 現有 business rule,不在 MCP Server 重寫一份規則。
- 隔離 SlimWeb 內部 controller、model、route 的變化。
- 對外提供穩定 output,讓 AI Client 可以可靠推理。
- 記錄 tool execution audit log,方便追蹤與客服支援。

## 資料流

### Site Selection 與歧義處理

同一個 Google 帳號可能在多個 SlimWeb site 裡是 Web admin。AI Client 不可在無法判斷目標網站時自行猜測。

規則:

- 使用者登入後,AI 應先呼叫 `slimweb_sites_list` 取得可操作網站的 `site_code` 與站台名稱。
- 若只有一個 site,可自動選定該 site。
- 若有多個 site,且使用者沒有明確說出網站名稱、網域、site code 或足以唯一識別的線索,AI 必須向使用者確認要操作哪個網站。
- 若使用者描述能比對到多個 site,AI 必須列出候選網站並要求使用者選擇。
- MCP 不保存 active site;所有 site-scoped tools 都必須明確帶入 `site_code`。
- 如果 AI 傳錯 `site_code`,server 會以 `NOT_FOUND` 或 `FORBIDDEN` 拒絕,不替 AI 猜測。
- AI Client 不需要知道 SlimWeb 的目錄結構,只需要透過 tools 查詢資料、選擇目標、提交結構化操作。

建議 AI 操作順序:

1. `slimweb_auth_status`
2. `slimweb_sites_list`
3. `slimweb_site_select`,或在無法唯一判斷時先問使用者
4. 依任務組合 read tools 與 write tools

### Tool Discovery

1. AI Client 連到 Remote MCP endpoint。
2. MCP Server 檢查 session。
3. MCP Server 查詢該 Google 身份可使用 MCP 的 Web admin sites,彙整 permissions 後回傳可用 tools。
4. AI Client 將 tools 提供給模型或使用者操作。

### Read Tool

1. Client 呼叫 read-only tool,例如列出商品、類別、訂單或優惠。
2. MCP Server 驗證 session 與 site scope。
3. Scope Guard 檢查 read permission。
4. Adapter 呼叫 SlimWeb。
5. MCP Server 回傳正規化結果。

### Write Tool

1. Client 呼叫 write tool,例如更新商品文案、替換商品圖片、調整訂單狀態或建立優惠。
2. MCP Server 驗證 input schema。
3. Scope Guard 檢查 write permission。
4. 高影響操作要求 confirmation。
5. Adapter 呼叫 SlimWeb。
6. MCP Server 回傳更新後摘要、warnings、audit ID。

## 初始 MCP Tools 規劃

第一階段先建立小而安全的 tool surface。每個 tool 都要具備權限檢查、input validation、錯誤處理、audit log 與文件更新,再進入可用狀態。

| Tool | 狀態 | 權限 | 用途 |
| --- | --- | --- | --- |
| `slimweb_auth_status` | Available | authenticated user | 回傳登入狀態、使用者摘要、目前 account。 |
| `slimweb_sites_list` | Available | account read | 列出使用者可操作的 SlimWeb sites。 |
| `slimweb_site_select` | Available | account read | 驗證並回傳 AI 後續 tool 呼叫要操作的 site。 |
| `slimweb_themes_list` | Available | content read | 列出站台自訂版型;Default 會被忽略。 |
| `slimweb_site_theme_mode_get` | Available | content read | 讀取站台層級色系;Default 與所有自訂版型都沿用這個 light/dark 設定。 |
| `slimweb_design_context_get` | Available | content read | 回傳目前啟用版型的設計摘要、站台明暗色系與固定框架 `Tailwind`,供 AI 在視覺設計或畫圖前先讀取。 |
| `slimweb_site_theme_mode_update` | Available | content write | 將站台層級色系切換為 light 或 dark。 |
| `slimweb_themes_create_from_default` | Available | content write | 建立空白的非 Default 版型;不複製 Default root elements,未客製的 shell slot 使用系統 runtime fallback。 |
| `slimweb_themes_create_from_theme` | Available | content write | 從指定的非 Default 來源版型複製 shell、root assets 與 style profile;不複製 page body。 |
| `slimweb_themes_activate` | Available | content write | 將指定版型設為前台啟用版型;會影響實際前台呈現。 |
| `slimweb_themes_delete` | Available | content write | 刪除非 Default 版型與其 template 內容;Default 不能刪除。 |
| `slimweb_theme_shell_get_context` | Available | content read | 回傳設計用 reference-only JSON,包含固定的 navbar、floating_actions、footer slots、navbar 必備的 `data-storefront-primary-navigation-slot`、`data-storefront-member-auth-slot`、`data-storefront-cart-slot` 三個呈現插槽、實際 shell 資料、`website_type` 事實資料與目前 MCP-managed root CSS。 |
| `slimweb_themes_update_root_elements` | Available | content write | 更新版型的 navbar、floating_actions、footer 與 root CSS;每個 Theme navbar 都必須各有一個容器型 `data-storefront-primary-navigation-slot`,以及可點擊的 `data-storefront-member-auth-slot` 與 `data-storefront-cart-slot`,外觀與配置可依參考網站調整,功能及是否顯示由 Webless runtime 決定。Navbar 必須是 static HTML;禁止 Blade、PHP、components 與 bound attributes,必須形成 balanced tree,primary slot 只能使用 div、nav 或 header 且須 structurally empty。每個 anchor 只能使用 literal href:`#`、relative/root path 或通過驗證的 http/https/protocol-relative URL。自訂內容只能加入使用者明確指定的 slot,不可挪用其他區域資料。`css` 會替換 MCP-managed root CSS 檔。Theme 不載入 JavaScript 或 `enabled_libraries`。 |
| `slimweb_theme_style_profile_get` | Available | content read | 讀取版型風格摘要與需求歷史。 |
| `slimweb_theme_style_profile_upsert` | Available | content write | 建立或更新版型風格摘要、色彩、字體、版面、插圖與避免事項。 |
| `slimweb_theme_style_profile_append_request` | Available | content write | 追加一筆使用者風格需求或變更紀錄。 |
| `slimweb_site_readiness_get` | Available | site readiness read | 回傳站台目前缺少或不完整的設定區塊,讓 AI 可主動回答開站缺口。 |
| `slimweb_site_launch_progress_get` | Available | site launch progress read | 回傳從 0 到正式上線的建站進度、必要項目、建議項目與下一步,供 AI 引導新手用戶。 |
| `slimweb_seo_settings_get` | Available | content read | 讀取後台 SEO 設定頁也會顯示的 SEO / AEO / GEO 欄位。 |
| `slimweb_seo_settings_update` | Available | content write | 更新站台層級 SEO、AEO、GEO、OG、llms.txt 與 GA4 流量追蹤 Measurement ID 設定。 |
| `slimweb_facebook_settings_get` | Available | settings read | 讀取後台 Facebook 串接欄位,包含 App ID、Page ID 與留言板開關。 |
| `slimweb_facebook_settings_update` | Available | settings write | 更新後台 Facebook 串接欄位,包含 App ID、Page ID 與留言板開關。 |
| `slimweb_notion_settings_get` | Available | settings read | 讀取後台 Notion API token 欄位。 |
| `slimweb_notion_settings_update` | Available | settings write | 更新後台 Notion API token 欄位。 |
| `slimweb_notion_pages_search` | Available | content read | 依標題搜尋已授權的 Notion 頁面,區分完全與部分符合並回傳導入狀態。 |
| `slimweb_notion_page_get_content` | Available | content read | 讀取指定 Notion 頁面並轉換成安全 HTML,不直接導入。 |
| `slimweb_contact_settings_get` | Available | settings read | 讀取後台所有聯絡資訊欄位。 |
| `slimweb_contact_settings_update` | Available | settings write | 以 patch 語意更新或清除後台聯絡資訊欄位。 |
| `slimweb_mail_delivery_settings_get` | Available | mail settings read | 讀取後台郵件寄送設定頁的 SMTP 與通知欄位。 |
| `slimweb_mail_delivery_settings_update` | Available | mail settings write | 更新後台郵件寄送設定頁的 SMTP 與通知欄位。 |
| `slimweb_mail_templates_get` | Available | mail settings read | 讀取各寄送時機的郵件標題與內容;內容會套用單一共用郵件版型。 |
| `slimweb_mail_templates_update` | Available | mail settings write | 更新各寄送時機的郵件標題、HTML 內容與啟用狀態。 |
| `slimweb_mail_layout_get` | Available | mail settings read | 讀取站台唯一共用郵件版型與預設版型 HTML。 |
| `slimweb_mail_layout_update` | Available | mail settings write | 更新站台唯一共用郵件版型;呼叫前必須先用 `slimweb_mail_layout_get` 取得同站台目前版型,再基於回傳 HTML 修改並保留 `{content}`、`{site_name}`、`{site_url}`、`{logo_url}`。 |
| `slimweb_payment_logistics_get` | Available | payment/logistics read | 讀取 SlimWeb 目前支援的金物流供應商與站台設定。 |
| `slimweb_payment_logistics_update` | Available | payment/logistics write | 更新支援的金物流資料與啟用狀態;線上刷卡金流只能啟用一家,LINE Pay 例外。 |
| `slimweb_dashboard_summary` | Available | dashboard read | 讀取 KPI、最新訂單、最新會員、低庫存提醒等後台首頁摘要。 |
| `slimweb_settings_get` | Available | settings read | 讀取網站名稱、網站狀態、Logo、國別、商品載入方式、允許退貨天數與 `category_navigation_mode` 等基本設定,並回傳可給消費者安裝使用的站台專屬 MCP 網址。 |
| `slimweb_settings_update` | Available | settings write | 更新網站顯示名稱與允許由 MCP 修改的基本設定欄位,包含 `category_navigation_mode` 與單一作用中的網站 Logo;改名不變更 slug、site code、callback code 或網域。 |
| `slimweb_admins_list` | Available | admin read | 列出站台管理員與權限摘要;第一個 admin 為受保護系統管理員。 |
| `slimweb_admins_upsert` | Available | admin write | 新增或更新站台管理員與權限;第一個 admin 永遠保留系統管理員。 |
| `slimweb_admins_delete` | Available | admin write | 刪除站台管理員;第一個系統管理員不能刪除。 |
| `slimweb_external_assets_list` | Available | page read | 列出頁面與版型使用的外部 CSS/JavaScript assets。 |
| `slimweb_external_assets_delete` | Available | page write | 刪除指定外部 asset。 |
| `slimweb_categories_list` | Available | product read | 列出商品分類樹、leaf 狀態與商品數。 |
| `slimweb_categories_upsert` | Available | product write | 新增或更新商品分類;新建時必須同時有 AI 生成 SVG icon 與已提交的 16:9 示意圖。 |
| `slimweb_categories_delete` | Available | product write | 刪除沒有任何商品的商品分類與其空子分類。 |
| `slimweb_nav_items_list` | Available | page read | 列出導覽項目樹、類型、URL 與 icon 狀態。 |
| `slimweb_nav_items_upsert` | Available | page write | 新增或更新導覽項目名稱、父層、類型、URL、排序與 AI 生成 SVG icon。 |
| `slimweb_nav_items_delete` | Available | page write | 刪除導覽項目與其子項目。 |
| `slimweb_products_list` | Available | product read | 依狀態、分類、關鍵字與庫存條件列出商品。 |
| `slimweb_products_get` | Available | product read | 讀取單一商品,包含圖片、影片、規格與數量折扣。 |
| `slimweb_product_image_reference_prepare` | Available | product read | 將 `slimweb_products_get` 回傳的商品圖片 URL 或 media path 準備成 ChatGPT 實驗性視覺參考;Codex/Hermes 等可自行讀取圖片 bytes 的 client 不需使用。 |
| `slimweb_products_upsert` | Available | product write | 新增或更新商品;主圖至少一張,缺必要資訊時 AI 必須先詢問。 |
| `slimweb_products_delete` | Available | product write | 刪除商品與已儲存商品圖片。 |
| `slimweb_products_import_inspect` | Available | product read | 解析 CSV/XLSX/SQL,回傳欄位、樣本列與分類,讓 AI Client 自行分析 mapping。 |
| `slimweb_products_import_validate` | Available | product read | 驗證 AI Client 產生的 mapping 是否可匯入,失敗時回傳原因。 |
| `slimweb_products_import_commit` | Available | product write | 使用已確認 mapping 將商品寫入 SlimWeb,不在後端呼叫 OpenAI。 |
| `slimweb_uploads_create` | Available | asset write | 向 Webless 申請短效 signed upload URL,讓 AI client Python sandbox 直接 PUT 圖片 bytes。 |
| `slimweb_uploads_commit` | Available | asset write | 提交已上傳圖片,讓 Webless 走後台同一套圖片驗證與 resize,回傳 `media_path`。 |
| `slimweb_media_library_stats` | Available | asset read | 回傳素材總數/容量與未使用素材數量/容量。 |
| `slimweb_media_library_delete_unused` | Available | asset write | 重新檢查引用後,只刪除當下仍未使用的素材。 |
| `slimweb_pages_delete` | Available | content write | 刪除自訂頁面內容;固定系統頁不可刪除。 |
| `slimweb_invoice_settings_get` | Available | invoice settings | 讀取獨立電子發票設定;金鑰只回傳存在狀態。 |
| `slimweb_invoice_settings_update` | Available | invoice settings | 設定綠界/ezPay、測試/正式、啟用與自動開票及加密憑證。 |
| `slimweb_invoices_list` | Available | invoice read | 依狀態、環境、服務商、日期或關鍵字查詢。 |
| `slimweb_invoices_get` | Available | invoice read | 讀取原票快照及狀態,不回傳供應商金鑰。 |
| `slimweb_invoices_create` | Available | invoice draft | 從訂單或獨立交易建立待確認草稿,不直接開票。 |
| `slimweb_invoices_issue` | Available | invoice financial write | 使用者明確要求後開立;必填穩定 idempotency_key 與 confirmed=true。 |
| `slimweb_invoices_sync` | Available | invoice sync | 查證原供應商狀態,未知結果先查證。 |
| `slimweb_invoices_void` | Available | invoice financial write | 使用者明確要求後作廢,必填原因、穩定請求鍵及 confirmed=true。 |
| `slimweb_invoices_allowance` | Available | invoice financial write | 使用者明確要求後折讓,必填整數台幣金額、原因、穩定請求鍵及 confirmed=true。 |
| `slimweb_orders_list` | Available | order read | 用後台同一套搜尋參數查正常訂單;「待處理」請用 `logistics_status=pending`,代表金流完成但物流未完成。超過 20 筆時 AI 應請用戶到後台縮小條件。 |
| `slimweb_orders_profit_statistics` | Available | order read | 計算已付款且未取消訂單的純利;不帶日期代表全部,問「這個月」時由 AI 帶入當月起訖日期。 |
| `slimweb_orders_get` | Available | order read | 讀取單一訂單,包含品項、付款、物流、退貨、退款與 `available_actions`。 |
| `slimweb_orders_create_logistics` | Available | order write | 依 `available_actions` 建立正物流單。 |
| `slimweb_orders_mark_shipped` | Available | order write | 無物流單時手動標記出貨完成。 |
| `slimweb_orders_update_status` | Available | order write | 依用戶當次指令明確提供的完整訂單單號更新主狀態。 |
| `slimweb_orders_update_recipient` | Available | order write | 依用戶當次指令明確提供的完整訂單單號更新收件人。 |
| `slimweb_orders_delete` | Available | order write | 永久刪除用戶當次指令逐筆提供完整單號的訂單。 |
| `slimweb_orders_get_waybill_url` | Available | order read | 回傳單筆或查詢所得訂單集合的正物流托運單列印網址。 |
| `slimweb_returns_get_waybill_url` | Available | order read | 回傳指定退貨訂單集合的逆物流托運單列印網址。 |
| `slimweb_returns_pending_list` | Available | order read | 列出待處理退貨單,包含可取消、手動完成或建立逆物流的操作。 |
| `slimweb_returns_create_logistics` | Available | order write | 依 `available_actions` 建立逆物流單。 |
| `slimweb_returns_cancel` | Available | order write | 取消退貨並回到正常完成訂單。 |
| `slimweb_returns_complete` | Available | order write | 無逆物流時手動標記已完成退貨。 |
| `slimweb_refunds_complete` | Available | order write | 手動標記已完成退款。 |
| `slimweb_refunds_create` | Available | order write | 依 `available_actions` 建立綠界或藍新刷退。 |
| `slimweb_members_list` | Available | member read | 列出會員與篩選會員資料。 |
| `slimweb_members_get` | Available | member read | 讀取單一會員摘要、訂單摘要、優惠券與等級。 |
| `slimweb_members_coupons_issue` | Available | member write + promotion write | 手動發券給指定會員,只接受 active manual coupon template。 |
| `slimweb_members_coupons_revoke` | Available | member write + promotion write | 撤銷指定會員已發優惠券並保留歷史。 |
| `slimweb_members_delete` | Available | member write | 刪除指定會員。 |
| `slimweb_member_email_preview` | Available | member read | 預覽一次性的非行銷會員通知信,不寄送、不排程。 |
| `slimweb_member_email_send` | Available | member write | 同步寄送一次性的非行銷會員通知信,可指定 CC/BCC,合計最多 5 個信箱。 |
| `slimweb_newsletters_create` | Available | member write | 建立寄給當下所有有效會員的電子報排程,不保存收件名單;未指定時間時預設為當下時間 + 5 分鐘。 |
| `slimweb_newsletters_list` | Available | member read | 列出既有電子報。 |
| `slimweb_newsletters_get` | Available | member read | 讀取單一全會員電子報。 |
| `slimweb_newsletters_update` | Available | member write | 更新既有電子報內容與排程。 |
| `slimweb_newsletters_delete` | Available | member write | 刪除既有電子報。 |
| `slimweb_posters_create` | Available | product read | 依商品名稱與繪圖需求產生 AI 商品海報,後端以商品主圖作為 image edit 參考並存成素材庫媒體;商品名稱模糊搜尋若有多筆結果會先返回候選讓使用者確認。 |
| `slimweb_coupon_templates_list` | Available | promotion read | 列出優惠券模板,含 manual、all_members、order_threshold、birthday、product_bundle。 |
| `slimweb_coupon_templates_upsert` | Available | promotion write | 新增或更新優惠券模板,套用與後台優惠券表單一致的發放規則。 |
| `slimweb_discount_codes_list` | Available | promotion read | 列出折扣碼。 |
| `slimweb_discount_codes_upsert` | Available | promotion write | 新增或更新折扣碼。 |
| `slimweb_discount_codes_delete` | Available | promotion write | 刪除折扣碼。 |
| `slimweb_member_tiers_list` | Available | promotion read | 列出會員等級與門檻。 |
| `slimweb_member_tiers_upsert` | Available | promotion write | 新增或更新會員等級。 |
| `slimweb_member_tiers_delete` | Available | promotion write | 刪除會員等級。 |
| `slimweb_threshold_gifts_list` | Available | promotion read | 列出滿額禮。 |
| `slimweb_threshold_gifts_upsert` | Available | promotion write | 新增或更新滿額禮。 |
| `slimweb_threshold_gifts_delete` | Available | promotion write | 刪除滿額禮。 |
| `slimweb_product_add_ons_list` | Available | promotion read | 列出單品加購規則。 |
| `slimweb_product_add_ons_upsert` | Available | promotion write | 新增或更新單品加購規則。 |
| `slimweb_product_add_ons_delete` | Available | promotion write | 刪除單品加購規則。 |
| `slimweb_articles_list` | Available | content read | 列出文章,讓 AI 避免重複建立或挑選要更新的文章。 |
| `slimweb_articles_check_title` | Available | content read | 檢查文章標題是否撞名。 |
| `slimweb_articles_get_content` | Available | content read | 讀取單一文章內容與中繼資訊。 |
| `slimweb_articles_create` | Available | content write + asset write | 新增文章,建立時必須有 16:9 主圖,也可附加內容圖;若 ChatGPT Remote MCP 沒有可用附圖或可直接下載的圖片 URL,先停止並請使用者貼圖。 |
| `slimweb_articles_update` | Available | content write + asset write | 修改既有文章,固定流程與頁面修改相同;若 ChatGPT Remote MCP 沒有可用附圖或可直接下載的圖片 URL,先停止並請使用者貼圖。 |
| `slimweb_articles_delete` | Available | content write | 刪除指定文章與其封面素材。 |
| `slimweb_content_seo_update` | Available | content write | 更新單一頁面或文章的內容層級 SEO / AEO / GEO;不能單獨執行,只能接在建立/編輯頁面或文章流程後。 |
| `slimweb_customer_service_logs_list` | Available | customer service read | 查詢 AI 客服紀錄。 |
| `slimweb_customer_service_logs_delete` | Available | customer service write | 刪除指定 AI 客服紀錄。 |
| `slimweb_customer_service_settings_get` | Available | customer service read | 讀取 AI 客服設定摘要。 |
| `slimweb_customer_service_settings_update` | Available | customer service write | 更新 AI 客服設定。 |
| `slimweb_exports_create` | Available | export read | 建立會員、訂單或退貨匯出檔。 |
| `slimweb_images_import_chatgpt_attachment` | Available | asset write | 匯入 ChatGPT web/desktop 對話附件圖片,回傳可用於商品、文章或頁面的 `media_path`。 |
| `slimweb_debug_attachment_refs` | Available | diagnostic read | 診斷 ChatGPT Remote MCP 實際傳入的附件參數形狀;只回傳去敏摘要,不下載、不上傳、不寫入素材庫。 |
| `slimweb_assets_upload` | Available | asset write | 只有當 AI flow 明確需要保存可重用素材時才寫入 asset。 |
| `slimweb_pages_check_title` | Available | content read | 檢查指定頁面標題是否已存在,固定頁會同時比對英文別名,採用 trim + 大小寫不敏感規則。 |
| `slimweb_pages_list` | Available | content read | 列出站台所有固定頁與自訂頁;可選填 `theme_id` 讓回傳連結使用指定版型預覽。 |
| `slimweb_pages_get_content` | Available | content read | 依頁面名稱讀取單一可編輯頁面的內容與中繼資訊;包含自訂頁與首頁 `index`,其他固定頁不可編輯。 |
| `slimweb_pages_create` | Available | content write | 建立新的自訂頁面;頁面標題需先過 `slimweb_pages_check_title`。若 ChatGPT Remote MCP 的頁面需求需要圖片但沒有可用附圖或可直接下載的圖片 URL,先停止並請使用者貼圖。 |
| `slimweb_pages_update` | Available | content write | 修改既有可編輯頁面,包含自訂頁與首頁 `index`;其他固定頁不可編輯。若 ChatGPT Remote MCP 的頁面需求需要圖片但沒有可用附圖或可直接下載的圖片 URL,先停止並請使用者貼圖。 |
| `slimweb_preview_get_page_url` | Available | content read | 回傳指定 site、page、theme 的預覽 URL,供 AI 自行截圖與檢查。 |
| `slimweb_audit_list` | Available | audit read | 列出近期 MCP tool execution 紀錄。 |

## Tool 文件維護規範

每新增或修改一個 tool,都必須在同一個 PR 更新本 README。格式如下:

```md
### `tool.name`

- 狀態:
- 權限:
- Scope:
- 用途:
- Input:
- Output:
- Side effects:
- 是否需要 confirmation:
- 錯誤情境:
- Audit fields:
```

規則:

- 實作 tool 的 PR 必須同步更新文件。
- experimental tool 要清楚標示。
- tool 尚未進入 MCP discovery 前,不可標成可用。
- 任何會修改客戶可見內容的 input,都要寫明 validation 與 rollback / recovery 行為。
- 任何會處理圖片的 tool,都要寫明圖片是 reference-only,還是會保存成 reusable asset。

## Tool Contracts

### 共通 Tool Rules

- 所有 tools 預設都需要有效 Google 登入與 MCP session。
- 除 `slimweb_auth_status`、`slimweb_sites_list`、`slimweb_site_select` 之外,tools 都需要明確 `site_code`。
- MCP 只接受有 `backend_ai_assistant` 權限的 Web admin 身份。各 tool 仍會再檢查該模組權限。
- 若 active site 無法從使用者語意唯一判斷,AI 必須先問使用者,不可猜測。
- Read tools 應回傳 stable IDs,讓 AI 後續 write tools 能精準指定目標。
- Write tools 不接受模糊目標,例如「第一個商品」;AI 必須先用 read tool 取得候選,再讓使用者或語意唯一指定。
- 需要圖片的 tools 不接受 inline base64、image URL、file URL、`/mnt/data`、attachment handle、data ref、placeholder URL 或任何本地路徑。
- 圖片流程固定為:AI 必須先判斷自己所在 runtime 是否能讀取圖片 bytes 並對外做 HTTPS `PUT`。Codex / Hermes 這類有本地或 code execution access 的 client 可以先呼叫 `slimweb_uploads_create`,讀取使用者上傳圖片或 AI 生成圖片的 binary,對 returned `upload_url` 做 raw bytes `PUT`,再呼叫 `slimweb_uploads_commit`,最後把回傳 `asset.media_path` 傳給商品、文章或 asset tools。
- ChatGPT Remote MCP 不可假設能把 AI 生成中的暫存圖片、`/mnt/data` 或 hidden attachment rewrite 轉成 remote MCP 可讀 bytes。若使用者已經把圖片作為 ChatGPT 對話附件貼上或重新上傳,AI 應改用 `slimweb_images_import_chatgpt_attachment` 匯入;若圖片仍只是 AI 生成結果而未成為對話附件,必須請使用者把核准的圖片貼回來後再匯入。
- 當 ChatGPT 需要先看既有商品圖再做圖片編輯、延伸生成或視覺判斷時,先用 `slimweb_products_get` 取得商品圖片,再用 `slimweb_product_image_reference_prepare` 準備實驗性的 visual reference;若 ChatGPT 無法把回傳 reference 當作 image-edit input,必須請使用者貼上或上傳商品圖。Codex/Hermes 等可自行讀取圖片 bytes 的 client 直接用自己的 runtime 看圖,不需依賴此工具。
- Webless 端負責與後台手動上傳一致的驗證、decode/re-encode、等比例縮圖與公開媒體 URL 產生;MCP 不再承接大段圖片 payload。
- Write tools 應拒絕未經 allowlist 的 `<script>`、`<link rel="stylesheet">`、inline event handler 與可執行片段,除非該 tool 明確標示支援且通過安全驗證。
- AI 不需要知道 SlimWeb 檔案目錄或後端 route,只需依 tool contract 使用 tools。

### `slimweb_auth_status`

- 狀態: Available
- 權限: authenticated Web admin with `backend_ai_assistant`
- Scope: Google identity session
- 用途: 回傳目前登入與 scope 狀態。
- Input: none
- Output: login status、admin identity summary、session expiry
- Side effects: none
- 是否需要 confirmation: no
- 錯誤情境: expired session、invalid token
- Audit fields: request ID、user ID、session ID

### `slimweb_sites_list`

- 狀態: Available
- 權限: authenticated Web admin with `backend_ai_assistant`
- Scope: Google identity across `site_admins`
- 用途: 列出此 Google 帳號可透過 MCP 操作的 Web admin sites。
- Input: optional pagination、keyword filter
- Output: site IDs、site admin IDs、names、domains、permissions、`site_status` (`active` or `maintenance`)、`site_status_label`、多站台時的 selection instruction
- Side effects: none
- 是否需要 confirmation: no
- 錯誤情境: unauthorized、no linked SlimWeb account
- Audit fields: request ID、user ID、account ID

### `slimweb_site_select`

- 狀態: Available
- 權限: authenticated Web admin with `backend_ai_assistant`
- Scope: selected `site_code`
- 用途: 驗證使用者可操作指定 site,並回傳 site summary 與可用 theme/page scheme。AI Client 不可在多站台歧義時自行猜測。
- Input: `site_code`
- Output: selected site summary、themes、mutation scope hints
- Side effects: none;目前不把 active site 寫入 session,write tools 仍必須明確帶 `site_code`
- 是否需要 confirmation: no
- 錯誤情境: site not found、site not accessible
- Audit fields: request ID、user ID、account ID、site ID

### `slimweb_themes_list`

- 狀態: Available
- 權限: content read
- Scope: active site
- 用途: 列出目前站台可用版型,讓 AI 知道 Default、active theme 與可設計的自訂版型。
- Input: `site_code`
- Output: site summary、site-level theme mode、theme IDs、names、is default、is active、inherits site theme mode
- Side effects: none
- 是否需要 confirmation: no
- 錯誤情境: site not found、site not accessible
- Audit fields: request ID、user ID、account ID、site ID

### `slimweb_site_theme_mode_get`

- 狀態: Available
- 權限: content read
- Scope: active site
- 用途: 讀取站台層級色系。此設定是 Default 與所有自訂版型的唯一 light/dark 來源。
- Input: `site_code`
- Output: site summary、`theme_mode` (`light` 或 `dark`)、scope
- Side effects: none
- 是否需要 confirmation: no

### `slimweb_design_context_get`

- 狀態: Available
- 權限: content read
- Scope: active site
- 用途: 在 AI 開始任何頁面視覺設計、版型設計、插圖或畫圖前,先回傳目前啟用版型的設計摘要、站台明暗色系與固定框架資訊,避免風格走偏。
- Input: `site_code`
- Output: site summary、active theme summary、`design_summary`、`color_mode` (`light` 或 `dark`)、`color_mode_label`(明亮或黑暗)、`framework` (`Tailwind`)
- Side effects: none
- 是否需要 confirmation: no
- 重要規則: 若是視覺設計相關任務,AI 應先讀這個 tool,再視需要補讀 `slimweb_theme_shell_get_context`。

### `slimweb_site_theme_mode_update`

- 狀態: Available
- 權限: content write
- Scope: active site
- 用途: 更新站台層級色系。使用者要求 neon、螢光字、暗色高對比或明亮極簡時,AI 應先確認色調屬於 `light` 或 `dark`,必要時呼叫此 tool。
- Input: `site_code`、`theme_mode` (`light` 或 `dark`)
- Output: updated site summary、`theme_mode`、scope
- Side effects: updates `sites.theme_mode`; custom style schemes inherit this value.
- 是否需要 confirmation: yes when changing an existing site color mode

### `slimweb_themes_create_from_default`

- 狀態: Available
- 權限: content write
- Scope: active site
- 用途: 建立新版型。此 tool 只新增一筆非 Default `site_pages` 記錄,不複製 Default 的 root elements 或 style profile;未客製的 shell slot 由系統 Default runtime fallback 呈現。
- Input: `site_code`、`name`
- Output: site summary、created theme summary、copied flag、`copied_scope`、`content_fallback`、`inherits_site_theme_mode`、preview URL
- Side effects: creates a site page style scheme without copying Default storage objects or `pages/*` body/content files.
- 色系規則: 此 tool 不選擇 light/dark;新版型沿用 `sites.theme_mode`。若設計需求跟色調有關,先用 `slimweb_site_theme_mode_get/update`。
- 是否需要 confirmation: yes when user did not explicitly ask to create a new theme
- 錯誤情境: site not found、invalid name、storage adapter not configured、upstream write failed
- Audit fields: request ID、user ID、account ID、site ID、theme ID

### `slimweb_themes_create_from_theme`

- 狀態: Available
- 權限: content write
- Scope: active site
- 用途: 使用者在目前啟用非 Default 版型上選擇「建立新版型」時,複製該來源版型的 root fragments、root assets 與 style profile。
- Input: `site_code`、非 Default 的 `source_theme_id`、`name`
- Side effects: creates an inactive custom Theme and copies only Theme shell data; page body 不會複製。
- 錯誤情境: source is Default、theme not found、invalid name、storage write failed

### `slimweb_themes_activate`

- 狀態: Available
- 權限: content write
- Scope: active site and selected theme
- 用途: 將指定版型設為前台啟用版型。AI 必須在使用者明確確認要切換前台版型後才呼叫。
- Input: `site_code`、`theme_id`
- Output: site summary、activated theme summary、updated themes list、preview URL
- Side effects: sets all other site themes inactive and selected theme active
- 是否需要 confirmation: yes
- 錯誤情境: site not found、theme not found、database write failed
- Audit fields: request ID、user ID、account ID、site ID、theme ID

### `slimweb_theme_shell_get_context`

- 狀態: Available
- 權限: content read
- Scope: active site and selected theme
- 用途: 在建立或修改版型前,讓 AI 取得實際會接上的資料摘要 JSON,例如 nav item 數量/名稱/樹狀結構、商品分類數量/名稱、目前 `category_navigation_mode`、兩種 runtime states、canonical CSS hooks,以及每個 Theme navbar 必備的 `primary_navigation`/`member_auth`/`cart` 呈現插槽。
- Input: `site_code`、`theme_id`
- Output: `reference_only: true`、site summary、theme summary、`theme_scope`、`navbar`、`product_categories`、`storefront_actions`、`floating_actions`、`footer`
- Side effects: none
- 重要規則: 此 JSON 僅供設計參考,不可直接把 nav/footer/contact 寫死進 root element 或 page body。Runtime category/nav labels and URLs are not serialized into Theme HTML;AI 只需提供插槽與 CSS,實際標籤、URL、樹狀資料與互動由 Webless runtime 注入。Navbar 必須是 static HTML;禁止 Blade、PHP、components 與 bound attributes。Markup 必須形成 balanced tree;primary slot 只能使用 div、nav 或 header,且必須 structurally empty。三個 required slots 必須位於不同元素且不可放在 interactive ancestor 內。
- 是否需要 confirmation: no
- 錯誤情境: site not found、theme not found、database read failed
- Audit fields: request ID、user ID、account ID、site ID、theme ID

### `slimweb_themes_update_root_elements`

- 狀態: Available
- 權限: content write
- Scope: active site and theme
- 用途: 更新固定的 `navbar`、`floating_actions`、`footer` root elements 與 root-level CSS。每個 Theme navbar 都必須各有一個不可點擊的容器型 `data-storefront-primary-navigation-slot`、一個可點擊的 `data-storefront-member-auth-slot` 與一個可點擊的 `data-storefront-cart-slot`;primary slot 只能使用 div、nav 或 header 且須 structurally empty,後兩者必須是啟用的 button 或具有有效 href 的 anchor。Navbar 必須是 static HTML;禁止 Blade、PHP、components 與 bound attributes,且 markup 必須形成 balanced tree。三個 required slots 必須位於不同元素、不得在 interactive ancestor 內,member/cart 也不得位於 primary slot 內。Every anchor must use a literal href:`#`/fragment、relative/root path、`//host/path`,或通過驗證的 `http://`/`https://` URL;route helper、其他 scheme 與動態 URL expression 都會被拒絕。AI 可依參考網站調整插槽外觀與響應式配置,但不可加入 Webless 保留的 runtime attributes,也不可把 live category/nav labels 或 URLs 寫進 Theme HTML。功能、資料與是否顯示完全由 Webless runtime 依網站設定處理。When navbar markup or theme CSS is created or modified, CSS must style category_menu, navbar_categories, and recursive ordinary navigation through the canonical hooks. Footer-only fragment updates that do not modify CSS do not require rewriting navigation CSS. 只有使用者明確指定某個自訂 slot 時才加入對應內容,不可把 Footer、頁面或其他位置提供的資料自行挪用。`css` 不是局部 patch,會替換 `assets/root-elements/css/00-mcp-theme.css`。
- Input: `site_code`、`theme_id`、optional `fragments.navbar`、`fragments.floating_actions`、`fragments.footer`、optional `css`、active custom Theme 直接修改時必須為 true 的 `confirmed_active_theme_edit`
- Output: write summary、theme summary、updated fragments、CSS updated flag、preview URL
- Side effects: writes root element Blade fragments and replaces `assets/root-elements/css/00-mcp-theme.css`
- JavaScript: Theme 不支援 inline JavaScript 或 Theme-level `enabled_libraries`;動畫程式與 library 選擇只能放在 page scope。
- 最小 navbar 插槽格式:

```html
<div data-storefront-primary-navigation-slot></div>
<div data-storefront-commerce-actions>
  <button type="button" data-storefront-member-auth-slot>註冊/登入</button>
  <button type="button" data-storefront-cart-slot aria-label="購物車">
    <svg aria-hidden="true"><!-- Theme cart icon --></svg>
    <span data-cart-count>0</span>
  </button>
</div>
```

- CSS runtime hooks: `[data-storefront-primary-navigation-runtime]`、`[data-storefront-primary-navigation]`、`[data-storefront-category-menu]`、`[data-storefront-navbar-categories]`、`[data-storefront-nav-items]`、`[data-storefront-nav-node]`、`[data-storefront-nav-trigger]`、`[data-storefront-nav-panel]`、`[data-storefront-nav-children]`、`[data-storefront-nav-depth]`。

- 是否需要 confirmation: Default 永遠不可修改;active custom Theme 必須取得使用者明確確認,inactive custom Theme 不需要。
- 錯誤情境: Default target、active custom without confirmation、theme not found、unsafe HTML、storage adapter not configured
- Audit fields: request ID、user ID、account ID、site ID、theme ID、updated fragments

### `slimweb_theme_style_profile_get`

- 狀態: Available
- 權限: content read
- Scope: active site and selected theme
- 用途: 讀取版型風格摘要,讓 AI 在視覺設計前知道既有方向、限制與使用者曾提出的變更。
- Input: `site_code`、`theme_id`
- Output: site summary、theme summary、nullable `profile`
- Side effects: none
- 是否需要 confirmation: no
- 錯誤情境: site not found、theme not found、profile table not migrated
- Audit fields: request ID、user ID、account ID、site ID、theme ID

### `slimweb_theme_style_profile_upsert`

- 狀態: Available
- 權限: content write
- Scope: active site and selected theme
- 用途: 建立或更新版型風格摘要,包含 `summary`、`target_audience`、`visual_keywords`、`color_notes`、`typography_notes`、`layout_notes`、`illustration_notes`、`avoid_notes`、`user_request(s)`、`ai_design_notes`。
- Input: `site_code`、`theme_id` and at least one style/profile field
- Output: write summary、theme summary、profile
- Side effects: upserts `site_theme_style_profiles`
- 是否需要 confirmation: no, unless changing an active customer-facing theme's declared direction against the user's current request
- 錯誤情境: site not found、theme not found、profile table not migrated、invalid JSON field
- Audit fields: request ID、user ID、account ID、site ID、theme ID

### `slimweb_theme_style_profile_append_request`

- 狀態: Available
- 權限: content write
- Scope: active site and selected theme
- 用途: 追加一筆使用者需求或變更紀錄,不覆蓋既有風格摘要。適合記錄「文青一點」、「字體不要那麼粗」、「背景補手繪插圖」等要求。
- Input: `site_code`、`theme_id`、`request`、optional `ai_notes`
- Output: write summary、theme summary、updated profile
- Side effects: appends to `site_theme_style_profiles.user_requests` and increments profile version
- 是否需要 confirmation: no
- 錯誤情境: site not found、theme not found、profile table not migrated
- Audit fields: request ID、user ID、account ID、site ID、theme ID

### `slimweb_site_readiness_get`

- 狀態: Available
- 權限: site readiness read
- Scope: active site
- 用途: 讀取站台開站/營運準備度,回傳目前缺少或不完整的地方,讓 AI 可以主動告知使用者「還缺什麼」。
- Input: `site_code`, optional `include_optional`
- Output: site summary、summary (`status`, `readiness_score`, issue counts)、categories、missing_categories、next_actions、evidence counts
- 檢查範圍:
  - 金物流: 是否啟用、憑證是否完整、是否仍全為 test mode
  - 商品資料: 商品類別、商品數、上架商品、未分類商品
  - 第三方登入: Google Client ID、LINE Channel ID / Secret
  - 對外資訊: SEO、AEO、GEO、llms.txt
  - 導覽與內容: navbar、文章
  - 客服與權限: AI 客服、後台管理員、backend_ai_assistant 權限
  - Optional: 優惠券模板、折扣碼
- Side effects: none
- 是否需要 confirmation: no
- 錯誤情境: site not found、permission denied
- Audit fields: request ID、user ID、account ID、site ID

### `slimweb_site_launch_progress_get`

- 狀態: Available
- 權限: site launch progress read
- Scope: active site
- 用途: 將站台 readiness 轉成「從 0 到正式上線」的引導式進度,讓 AI 可以判斷下一步該協助用戶設定什麼,而不是每次都把使用者當成完全新手。
- Input: `site_id`, optional `include_optional`
- Output: site summary、launch_status (`stage`, `can_launch`, `completion_percent`, required counts)、required、recommended、growth、next_step、ai_guidance
- Required launch blockers:
  - 商品與分類
  - 金流、物流與運費
  - 首頁內容
- Recommended setup:
  - SEO / AEO / GEO
  - 導覽與頁面入口
  - Email 通知與版型
  - 文章與品牌內容
  - AI 客服與常見問題
- Optional/growth setup:
  - 優惠券與促銷
  - 會員經營、電子報、加價購、滿額贈等
- Side effects: none
- 是否需要 confirmation: no
- 錯誤情境: site not found、permission denied
- Audit fields: request ID、user ID、account ID、site ID

### `slimweb_seo_settings_get`

- 狀態: Available
- 權限: content read
- Scope: active site
- 用途: 讀取站台層級 SEO / AEO / GEO 設定,這些欄位會顯示在 SlimWeb 後台的 SEO 設定頁。
- Input: `site_code`
- Output: site summary、settings (`seo_title`, `seo_description`, `seo_keywords`, `google_analytics_measurement_id`, `canonical_url`, `robots_policy`, `og_title`, `og_description`, `og_image_url`, `llms_txt`, `aeo_business_summary`, `aeo_target_audience`, `aeo_products_services`, `aeo_customer_questions`, `aeo_answer_style`, `aeo_entity_facts`, `geo_citation_targets`, `geo_verifiable_claims`, `geo_trust_signals`, `geo_same_as_profiles`, `geo_comparison_positioning`)
- Side effects: none
- 是否需要 confirmation: no
- 錯誤情境: site not found、permission denied
- Audit fields: request ID、user ID、account ID、site ID

### `slimweb_seo_settings_update`

- 狀態: Available
- 權限: content write
- Scope: active site
- 用途: 更新站台層級 SEO、OG、llms.txt、AEO、GEO 與 GA4 流量追蹤 Measurement ID 欄位。適合「我是賣服飾的,幫我做好 SEO / AEO / GEO」或「幫我設定 Google Analytics」這類需求,由 AI 產生或填入結構化設定後寫入同一份後台資料。
- Input: `site_code` plus any subset of SEO/AEO/GEO fields; for Google Analytics, fill only `google_analytics_measurement_id` such as `G-ABC1234567`, not full script tags
- Output: updated settings、site summary
- Side effects: updates `sites` SEO/AEO/GEO and GA4 Measurement ID columns; published fields feed the shared storefront SEO head and merchant sitemap/robots/llms output
- Canonical rule: `canonical_url` must be HTTP(S) and use either the site's configured custom domain or its Webless site path; Webless removes query/fragment values and rejects unrelated hosts.
- Publishing rule: `seo_keywords` remains in the management contract but is not emitted as a meta keywords tag. AEO/GEO text is factual context for llms/structured output, not a set of invented meta tags.
- 是否需要 confirmation: yes when changing robots policy to noindex or replacing existing customer-facing metadata
- 錯誤情境: validation failed、site not found、permission denied、conflict
- Audit fields: request ID、user ID、account ID、site ID、changed fields

### `slimweb_facebook_settings_get`

- 狀態: Available
- 權限: settings read
- Scope: active site
- 用途: 讀取後台 Facebook 串接欄位,包含會員登入 App ID、Facebook Page ID,以及商品頁 / 文章頁 Facebook 留言板開關。
- Input: `site_code`
- Output: site summary、settings (`facebook_app_id`, `facebook_page_id`, `facebook_comment_on_products`, `facebook_comment_on_posts`)
- Side effects: none
- 是否需要 confirmation: no
- 錯誤情境: site not found、permission denied
- Audit fields: request ID、user ID、account ID、site ID

### `slimweb_facebook_settings_update`

- 狀態: Available
- 權限: settings write
- Scope: active site
- 用途: 更新後台 Facebook 串接欄位,包含會員登入 App ID、Facebook Page ID,以及商品頁 / 文章頁 Facebook 留言板開關。
- Input: `site_code` plus any subset of Facebook settings fields
- Output: updated settings、site summary
- Side effects: updates `sites` Facebook integration columns that SlimWeb admin displays
- 是否需要 confirmation: yes when changing login App ID, customer-facing Page ID, or enabling/disabling Facebook comments
- 錯誤情境: validation failed、site not found、permission denied、conflict
- Audit fields: request ID、user ID、account ID、site ID、changed fields

### `slimweb_notion_settings_get`

- 狀態: Available
- 權限: settings read
- Scope: active site
- 用途: 讀取後台 Notion API token 欄位。
- Input: `site_code`
- Output: site summary、settings (`notion_token`)
- Side effects: none
- 是否需要 confirmation: no
- 錯誤情境: site not found、permission denied
- Audit fields: request ID、user ID、account ID、site ID

### `slimweb_notion_settings_update`

- 狀態: Available
- 權限: settings write
- Scope: active site
- 用途: 更新後台 Notion API token 欄位。
- Input: `site_code`、`notion_token`
- Output: updated settings、site summary
- Side effects: updates `sites.notion_token`
- 是否需要 confirmation: yes when changing the Notion API token
- 錯誤情境: validation failed、site not found、permission denied、conflict
- Audit fields: request ID、user ID、account ID、site ID、changed fields

### `slimweb_mail_delivery_settings_get`

- 狀態: Available
- 權限: mail settings read
- Scope: active site
- 用途: 讀取後台郵件寄送設定頁的 SMTP 與通知欄位,包含 SMTP host、username、password、port、from email、SSL,以及出貨/提醒通知設定。
- Input: `site_code`
- Output: site summary、settings (`notification_new_order_sms_numbers`, `notification_sms_on_shipped`, `notification_auto_send_reminder_sms`, `notification_reminder_sms_content`, `notification_smtp_host`, `notification_smtp_username`, `notification_smtp_password`, `notification_smtp_port`, `notification_smtp_from_email`, `notification_smtp_ssl`)
- Side effects: none
- 是否需要 confirmation: no
- 錯誤情境: site not found、permission denied
- Audit fields: request ID、user ID、account ID、site ID

### `slimweb_mail_delivery_settings_update`

- 狀態: Available
- 權限: mail settings write
- Scope: active site
- 用途: 更新後台郵件寄送設定頁的 SMTP 與通知欄位。當使用者要啟用 email 會員註冊驗證時,應先用此 tool 完成 SMTP 設定。
- Input: `site_code` plus any subset of mail delivery fields
- Output: updated settings、site summary
- Side effects: updates `sites` mail delivery columns that SlimWeb admin displays
- 是否需要 confirmation: yes when changing SMTP credentials, sender email, or customer-facing reminder behavior
- 錯誤情境: validation failed、site not found、permission denied、conflict
- Audit fields: request ID、user ID、account ID、site ID、changed fields

### `slimweb_mail_templates_get`

- 狀態: Available
- 權限: mail settings read
- Scope: active site
- 用途: 讀取各事件郵件內容。這些是「內容模板」,不是共用外框;寄送時 SlimWeb 會把內容放進唯一共用郵件版型的 `{content}`。
- 支援事件: `order_created`、`order_shipped`、`store_arrived`、`return_requested`、`return_logistics`、`registration_code`、`password_reset`
- Input: `site_code`
- Output: templates、layout rule
- Side effects: none
- 是否需要 confirmation: no
- 錯誤情境: site not found、permission denied
- Audit fields: request ID、user ID、account ID、site ID

### `slimweb_mail_templates_update`

- 狀態: Available
- 權限: mail settings write
- Scope: active site
- 用途: 更新各事件郵件的 subject、HTML content 與啟用狀態。AI 可依使用者商品、品牌語氣、訂單流程設計郵件內容,但不應在這裡修改整體版型。
- Input: `site_code`、`templates[]`,每筆包含 `trigger_event` 與 optional `subject`、`content`、`is_active`
- Output: updated templates
- Side effects: upserts `mail_templates`
- Rule: `member_name` 會在寄送時替換為會員/買家名稱;訂單相關事件會由 Webless 自動附上訂單明細。
- 是否需要 confirmation: yes when changing customer-facing copy or disabling a mail event
- 錯誤情境: validation failed、unsupported trigger_event、site not found、permission denied
- Audit fields: request ID、user ID、account ID、site ID、trigger events

### `slimweb_mail_layout_get`

- 狀態: Available
- 權限: mail settings read
- Scope: active site
- 用途: 讀取站台唯一共用郵件版型。所有事件郵件都共用這一個外框。
- Input: `site_code`
- Output: current layout、default layout HTML、available placeholders (`{content}`, `{site_name}`, `{site_url}`, `{logo_url}`)
- Side effects: none
- 是否需要 confirmation: no
- 錯誤情境: site not found、permission denied
- Audit fields: request ID、user ID、account ID、site ID

### `slimweb_mail_layout_update`

- 狀態: Available
- 權限: mail settings write
- Scope: active site
- 用途: 更新站台唯一共用郵件版型。預設版型為網站 logo + 網站名稱、分隔線、內容、分隔線、footer 網站網址。呼叫本工具前必須先用 `slimweb_mail_layout_get` 讀取同一個 `site_code` 對應站台的目前版型,再以回傳的 current/default HTML 為基礎修改;不要憑空重寫整份 HTML,以免遺失 logo、站名、footer、placeholder 或既有結構。
- Input: `site_code`、`html`、`is_active`
- Output: updated layout、default layout HTML
- Side effects: upserts `site_mail_layouts`
- Rule: `html` 是完整替換。每次更新前都要先呼叫 `slimweb_mail_layout_get`,基於回傳 HTML 做最小修改;必須保留 `{content}`、`{site_name}`、`{site_url}`、`{logo_url}`。
- 是否需要 confirmation: yes
- 錯誤情境: validation failed、site not found、permission denied
- Audit fields: request ID、user ID、account ID、site ID

### `slimweb_payment_logistics_get`

- 狀態: Available
- 權限: payment/logistics read
- Scope: active site
- 用途: 讀取 SlimWeb 支援的金流與物流供應商,以及目前站台的啟用狀態與設定摘要。AI 回答「我的 SlimWeb 網站能用什麼金流?」時必須以此 tool 回傳的 `supported_payment_providers` 為準,不可自行補充未支援供應商。
- 支援金流: `ecpay` (綠界 ECPay)、`newebpay` (藍新 NewebPay)、`linepay` (LINE Pay)
- LINE Pay 支援測試環境與付款等待頁語系設定;後台欄位以 Channel ID / Channel Secret 對應 `merchant_id` / `hash_key`,不使用 `hash_iv`。
- 支援物流: `ecpay` (綠界物流)、`newebpay` (藍新物流)、`hct` (新竹物流)
- Input: `site_code`
- Output: supported payment/logistics providers、online card exclusivity rule、answer policy、current provider states、provider Notify URL / Return URL、store-map callback URL
- Side effects: none
- 是否需要 confirmation: no
- 錯誤情境: site not found、permission denied
- Audit fields: request ID、user ID、account ID、site ID

### `slimweb_payment_logistics_update`

- 狀態: Available
- 權限: payment/logistics write
- Scope: active site
- 用途: 更新支援的金流與物流供應商設定。金流包含 mode、啟用狀態、merchant ID、HashKey、HashIV、語系;物流包含啟用狀態、寄件資訊、超商通路、綠界 C2C/B2C 型態與新竹物流代收設定。綠界/藍新物流沿用同家金流的環境與商店代號,不另外儲存 HashKey/HashIV。
- Input: `site_code`、optional `payments[]`、optional `logistics[]`
- Output: updated provider states、supported provider list、answer policy
- Side effects: upserts `site_payment_providers` / `site_logistics_providers`; writes encrypted provider settings compatible with Webless Laravel `encrypted:array`
- Rule: `ecpay` 與 `newebpay` 屬於線上刷卡金流,同一站台只能啟用其中一家;啟用其中一家會停用另一家。`linepay` 可同時啟用,不受此限制。
- Logistics rule: 綠界物流與藍新物流沒有獨立啟用開關,啟用同家的金流時即視為一併啟用同家物流;停用同家金流時物流也會停用。綠界物流超商通路為 `seven`、`family`、`hilife`、`ok`,並可設定 `logistics_type` = `c2c` 或 `b2c`;C2C/B2C 必須與綠界後台申請項目一致,若需要建立逆物流請使用 B2C。藍新物流超商通路目前使用 `seven`、`family`、`hilife`,不把 OK 當成預設可用通路;可用通路與寄件模式以藍新後台啟用項目為準。新竹物流使用 `merchant_id` 作為 API 公司名稱、`password` 作為 API 密碼、optional `customer_id` 作為客代;新竹物流沒有後台測試/正式模式下拉,測試時使用文件提供的測試公司名稱 `test` 與密碼 `test1`。新竹物流保留自己的 `is_enabled`,`collect_payment_enabled` 為 true 時前台可顯示貨到付款。
- AI answer rule: 使用者問自己的 SlimWeb 站台支援哪些金物流時,先呼叫 `slimweb_payment_logistics_get`,並只依支援清單回答。使用者問一般「電商網站用什麼金流」時,不把未支援供應商描述成 SlimWeb 可用。
- 是否需要 confirmation: yes when enabling/disabling providers or changing credentials
- 錯誤情境: validation failed、unsupported provider、missing credentials、multiple online card providers enabled、encryption key not configured、site not found、permission denied
- Audit fields: request ID、user ID、account ID、site ID、provider IDs、changed fields

### `slimweb_dashboard_summary`

- 狀態: Available
- 權限: dashboard read
- Scope: active site
- 用途: 回傳後台首頁摘要,讓 AI 快速理解目前站台狀況。
- Input: optional date range
- Output: KPI summary、latest orders、latest members、low stock products、traffic summary if available
- Side effects: none
- 是否需要 confirmation: no
- 錯誤情境: missing active site、permission denied
- Audit fields: request ID、user ID、account ID、site ID

### `slimweb_settings_get`

- 狀態: Available
- 權限: settings read
- Scope: active site
- 用途: 讀取 AI 後台操作需要的網站名稱、站台基本設定、目前網站 Logo,並取得可放在首頁給消費者安裝使用的站台專屬 MCP 網址。
- Input: optional fields list
- Output: `name`、site status、website type、country、product loading mode、return days allowed、`category_navigation_mode`、`logo`(`media_path`、`public_url`、`mime_type`)與 `client_mcp_url`
- Side effects: none
- 是否需要 confirmation: no
- Consumer MCP guidance: `client_mcp_url` 是此站台的消費者端 MCP endpoint,可提供給支援 MCP 的 AI 工具,讓顧客連接後以 AI 查詢商品、會員、訂單與客服支援。AI 應向商家說明這個入口的用途,並建議把連結或安裝按鈕放在首頁、會員中心或客服區,讓消費者容易找到。
- 錯誤情境: missing active site、permission denied
- Audit fields: request ID、user ID、account ID、site ID

### `slimweb_settings_update`

- 狀態: Available
- 權限: settings write
- Scope: active site
- 用途: 更新網站顯示名稱與允許 MCP 修改的基本設定,包含分類在前台導覽中的呈現模式,並可直接更換網站唯一作用中的 Logo;不另開名稱或 Logo 專用 public tool。
- Input: patch object,僅允許 allowlist 欄位,例如 `name`、site status、member verification、country、product loading mode、return days allowed、`category_navigation_mode`,以及可選的 `logo`。`name` 必須是 1 至 255 字的非空字串,改名只更新顯示名稱,不變更 slug、site code、callback code 或網域。`category_navigation_mode` 可為 `category_menu`(以單一「商品分類」入口呈現 grouped categories)或 `navbar_categories`(把 recursive category entries 排進 navbar);此欄位只改呈現,絕不建立 nav item。`logo` 必須且只能提供 `media_path`(由 `slimweb_uploads_commit` 回傳的 PNG/JPEG/WebP)或 `svg_base64` 其中之一。
- Output: updated settings summary、changed fields、warnings、audit ID
- Side effects: modifies site settings
- Logo rule: 點陣圖會轉為 WebP、保留透明背景、不放大、依比例將高度限制為最多 96px;SVG 會保留 SVG 格式並經安全清理,同樣依比例限制最高 96px。新 Logo 會覆蓋舊 Logo,且點陣圖的 committed 暫存檔會被移除,因此 Logo 不會進入素材庫或留下多份作用中檔案。
- Category/navigation intent rule: Category and nav item intents are separate;商品分類與 nav item 是分開的資料,分類建立/更新不得隱含建立導覽項目。只有使用者另外明確要求頁面、外部連結或選單項目時,才使用 nav-item tools。若只要求分類擺放方式,僅更新 `category_navigation_mode`。
- 是否需要 confirmation: yes for disabling site、changing return policy、or settings that affect storefront behavior
- 錯誤情境: validation failed、permission denied、unsupported field、conflict
- Audit fields: request ID、user ID、account ID、site ID、changed fields

### `slimweb_admins_list`

- 狀態: Available
- 權限: admin read
- Scope: active site
- 用途: 列出站台管理員與權限摘要,讓 AI 在權限問題上能先查清楚現況。
- Input: optional keyword、role、pagination
- Output: admin summaries、roles、permission summary、status、last updated time
- Side effects: none
- 是否需要 confirmation: no
- 錯誤情境: missing active site、permission denied
- Audit fields: request ID、user ID、account ID、site ID

### `slimweb_admins_upsert`

- 狀態: Available
- 權限: admin write
- Scope: active site
- 用途: 新增或更新站台管理員與權限。
- Input: optional admin ID、`google_email`、permissions
- Output: admin summary、changed permissions、audit ID
- Side effects: creates or modifies admin access
- 是否需要 confirmation: yes
- 錯誤情境: validation failed、admin not found、duplicate admin、cannot modify owner、permission denied、conflict
- Audit fields: request ID、user ID、account ID、site ID、target admin ID、changed permissions

### `slimweb_categories_list`

- 狀態: Available
- 權限: product read
- Scope: active site
- 用途: 列出商品分類,支援「目前商品有哪些類別?」這類問題。
- Input: site ID
- Output: category tree、flat categories、leaf flag、product counts
- Side effects: none
- 是否需要 confirmation: no
- 錯誤情境: missing active site、permission denied
- Audit fields: request ID、user ID、account ID、site ID

### `slimweb_categories_upsert`

- 狀態: Available
- 權限: product write
- Scope: active site
- 用途: 新增或更新商品分類。
- Input: optional category ID、optional current name、new name、optional parent category ID、optional icon SVG base64、optional 16:9 image、optional sort order
- Output: action (`created` / `updated`)、matched_by、changed fields、category summary
- Side effects: creates or modifies category
- Intent rule: 商品分類與 nav item 是分開的 semantic intents;分類 upsert 不會也不應自動呼叫 nav-item upsert,除非使用者另外明確要求導覽項目。
- Rename rule: 使用者說「把 A 改名為 B」時,AI 必須先用 `slimweb_categories_list` 找到 category ID;若沒有 ID,傳 `current_name: "A"` 與 `name: "B"`,不可只傳新名稱後宣稱已更新舊分類。
- Parent rule: 建立時使用者沒有明確指定父項目,AI 應省略 `parent_id` 或傳 `null`,表示 root category;例如「建立男裝類別」不應自行推斷到「服飾」底下。更新時省略 `parent_id` 會保留原父層,明確傳 `null` 才移到 root。
- Icon rule: 建立分類時 AI 必須依照使用者文字生成 SVG icon,base64 encode 後放入 `icon_svg_base64`;使用者未指定顏色時使用 `#9ca3af`。更新時若要重畫 icon,再傳新的 `icon_svg_base64`。
- 錯誤情境: validation failed、duplicate name、parent not found、cycle detected、missing icon on create、permission denied
- Audit fields: request ID、user ID、account ID、site ID、category ID、changed fields

### `slimweb_nav_items_list`

- 狀態: Available
- 權限: page read
- Scope: active site
- 用途: 列出導覽項目,支援「目前導覽列有哪些項目?」與修改前確認。
- Input: site ID
- Output: nav item tree、flat nav items、item type、URL、icon state
- Side effects: none
- 是否需要 confirmation: no
- 錯誤情境: missing active site、permission denied
- Audit fields: request ID、user ID、account ID、site ID

### `slimweb_nav_items_upsert`

- 狀態: Available
- 權限: page write
- Scope: active site
- 用途: 新增或更新導覽項目。
- Input: optional nav item ID、name、item type (`dropdown` or `link`)、optional URL、optional parent nav item ID、optional icon SVG base64、optional sort order
- Output: nav item summary
- Side effects: creates or modifies nav item data
- Parent rule: 建立時使用者沒有明確指定父項目,AI 應省略 `parent_id` 或傳 `null`,表示 root nav item;例如「建立男裝導覽項目」不應自行推斷到「服飾」底下。更新時省略 `parent_id` 會保留原父層,明確傳 `null` 才移到 root。
- Icon rule: 建立導覽項目時 AI 必須依照使用者文字生成 SVG icon,base64 encode 後放入 `icon_svg_base64`;使用者未指定顏色時使用 `#9ca3af`。更新時若要重畫 icon,再傳新的 `icon_svg_base64`。
- 錯誤情境: validation failed、duplicate name、parent not found、parent is not dropdown、cycle detected、missing icon on create、link without URL、permission denied
- Audit fields: request ID、user ID、account ID、site ID、nav item ID、changed fields

### `slimweb_nav_items_delete`

- 狀態: Available
- 權限: page write
- Scope: active site
- 用途: 刪除導覽項目與其子項目。
- Input: nav item ID
- Output: deleted nav item IDs、updated nav item tree
- Side effects: deletes nav item rows and stored icon assets
- 是否需要 confirmation: yes for customer-facing active site navigation.
- 錯誤情境: nav item not found、permission denied
- Audit fields: request ID、user ID、account ID、site ID、deleted nav item IDs

### `slimweb_products_list`

- 狀態: Available
- 權限: product read
- Scope: active site
- 用途: 列出商品,讓 AI 可協助搜尋、審查與編輯前確認。
- Input: status、category、keyword、max stock、pagination
- Output: product summaries、stable IDs、editable field hints
- Side effects: none
- 是否需要 confirmation: no
- 錯誤情境: missing active site、unauthorized
- Audit fields: request ID、user ID、account ID、site ID

### `slimweb_products_get`

- 狀態: Available
- 權限: product read
- Scope: active site
- 用途: 讀取單一商品完整可編輯摘要,讓 AI 在修改前知道目前資料。
- Input: product ID
- Output: product fields、categories、primary images、content images、videos、variants、quantity discounts、add-ons、editable field hints
- Side effects: none
- 是否需要 confirmation: no
- 錯誤情境: product not found、permission denied
- Audit fields: request ID、user ID、account ID、site ID、product ID

### `slimweb_products_upsert`

- 狀態: Available
- 權限: product write
- Scope: active site
- 用途: 新增或更新單一商品,對齊 `products`、`product_images`、`product_videos`、`product_variants`、`product_quantity_discounts` 欄位。
- Input: site ID、optional product ID、leaf category ID、SKU/name/summary/description、base price、sale price、stock、status、primary images、content images、videos、variants、quantity discounts
- Output: product summary with images、videos、variants、quantity discounts
- Side effects: creates or modifies product data and child rows
- 是否需要 confirmation: yes for creating products, changing price, changing inventory, or changing publication status.
- AI 必須先補齊或詢問的條件:
  - `site_category_id`: 必須是 leaf category;如果分類不存在,先用 `slimweb_categories_upsert` 建立。
  - `name`: 商品名稱必填。
  - `base_price`: 售價必填。
  - `primary_images`: 建立商品時至少一張主圖。更新既有商品時搭配 `primary_images_mode` 判斷是 `append` 還是 `replace`;預設更新為 `append`、建立為 `replace`。圖片必須先確認 AI runtime 具備讀取圖片 bytes 與 outbound HTTPS `PUT` 能力,再走 `slimweb_uploads_create` -> raw bytes `PUT` -> `slimweb_uploads_commit`,最後把 `asset.media_path` 放進 `source.media_path`。不可傳 base64、`image_url`、`file_url`、`/mnt/data`、attachment handle 或 placeholder URL;ChatGPT Remote MCP 若只有對話附件則應向使用者說明目前不能代傳圖片。
  - `primary_images_mode` / `content_images_mode`: `append` 保留既有圖片並把這次圖片加到最後,若 AI 同時傳入既有圖片 path 會自動略過避免重複;`replace` 先移除同類型既有圖片再插入這次圖片。使用者說「新增、補一張、再放一張」時用 `append`;說「換掉、取代、改成這張」時用 `replace`,若只是替換第一張圖可優先用 `slimweb_products_images_replace`。
  - `status`: 預設 active;若使用者不確定,可說明 active/hidden/sold_out 差異。
- 錯誤情境: validation failed、duplicate SKU、category not found、category is not leaf、missing primary image、conflict、unauthorized、product not found
- Audit fields: request ID、user ID、account ID、site ID、product ID、changed fields

### `slimweb_products_images_replace`

- 狀態: Available
- 權限: product write + asset write
- Scope: active site
- 用途: 替換商品圖片,例如「把商品 xxx 的第一張圖換成這張」。
- Input: product ID、image target、replacement image、optional alt text、optional client note
- Input 條件:
  - `image target` 必須指定 `primary_image`、`content_image` 或 `variant_image`
  - 若指定第一張主圖,使用 `image target = primary_image` 與 `position = 1`
  - `replacement image` 必須先完成 `slimweb_uploads_create` / Python sandbox raw bytes PUT / `slimweb_uploads_commit`,再傳入 `source.media_path`
  - 若使用者只說商品名稱,AI 必須先呼叫 `slimweb_products_list` 或 `slimweb_products_get` 找到唯一 `product_id`
- Output: updated product image summary、old image reference、new image reference、warnings、audit ID
- Side effects: uploads or links image、updates product image list、may affect storefront
- 是否需要 confirmation: yes when replacing customer-facing image、removing old image、or product match is based on fuzzy search
- 錯誤情境: product not found、image missing、unsupported file type、file too large、target image not found、permission denied、validation failed
- Audit fields: request ID、user ID、account ID、site ID、product ID、image target、old image ID、new image ID

### `slimweb_products_variants_update`

- 狀態: Available
- 權限: product write
- Scope: active site
- 用途: 更新商品規格模式、規格名稱、規格價格、特價與庫存。
- Input: product ID、variant mode、variants patch、optional client note
- Output: updated variants summary、stock sync result、warnings、audit ID
- Side effects: modifies product variants and may sync product total stock
- 是否需要 confirmation: yes for price changes、stock changes、or switching variant mode
- 錯誤情境: product not found、invalid variant mode、validation failed、conflict、permission denied
- Audit fields: request ID、user ID、account ID、site ID、product ID、changed variants

### `slimweb_products_quantity_discounts_update`

- 狀態: Planned
- 權限: product write
- Scope: active site
- 用途: 更新商品數量折扣。
- Input: product ID、quantity discount rules
- Output: updated discount rules、warnings、audit ID
- Side effects: modifies product pricing behavior
- 是否需要 confirmation: yes
- 錯誤情境: product not found、validation failed、overlapping rules、permission denied
- Audit fields: request ID、user ID、account ID、site ID、product ID

### `slimweb_products_import_inspect`

- 狀態: Available
- 權限: product read
- Scope: active site
- 用途: 解析使用者提供的 CSV/XLSX/SQL 商品資料,回傳欄位、樣本列、目前分類與 target schema,讓 AI Client 自行產生 mapping。
- Input: `site_code`、`source`(data_base64 或 file_url、filename/original_name)
- Output: dataset summary、available categories、target schema、`ai_mapping_prompt`、AI guidance
- Side effects: none
- 是否需要 confirmation: no
- 錯誤情境: unsupported file type、download failed、parse failed、permission denied
- AI mapping prompt: 對齊 Web 後台原本 `ProductImportService::requestMapping()` 的規則,要求 AI Client 回傳 JSON only,包含 `field_mapping`、`category_mapping`、`image_mapping`、`warnings`、`confidence`,並沿用忽略來源 id、使用目前 `site_code` 對應的站台、分類不準視為 warning 的 import policy。
- Audit fields: request ID、user ID、account ID、site ID

### `slimweb_products_import_validate`

- 狀態: Available
- 權限: product read
- Scope: active site
- 用途: 驗證 AI Client 產生的 mapping 是否能匯入。後端不呼叫 OpenAI。
- Input: site ID、source、mapping
- Output: validation、convertible、failure reasons
- Side effects: none
- 是否需要 confirmation: no
- 錯誤情境: missing name mapping、missing price mapping、row validation failed、permission denied
- AI 行為: 如果 `convertible=false`,直接向使用者說明 `failure_reasons`,不要呼叫 commit。
- Audit fields: request ID、user ID、account ID、site ID

### `slimweb_products_import_commit`

- 狀態: Available
- 權限: product write
- Scope: active site
- 用途: 將已確認 mapping 的商品資料寫入 SlimWeb;沿用後台匯入規則,但分析由 AI Client 負責。
- Input: site ID、source、mapping、confirmation token
- Output: created products、matched category count、unmatched category count、validation
- Side effects: creates products、creates product image rows、creates `轉入商品` category when needed
- 是否需要 confirmation: yes
- 錯誤情境: validation failed、unsupported file type、parse failed、permission denied
- AI 行為: commit 前必須先讓使用者確認匯入筆數、名稱欄、價格欄、圖片欄與分類處理方式。
- Side effects: creates or updates products、categories、images、variants depending on confirmed draft
- 是否需要 confirmation: yes
- 錯誤情境: import draft not found、expired draft、validation failed、conflict、permission denied
- Audit fields: request ID、user ID、account ID、site ID、import draft ID

### Order, Return, and Refund Operations

- 狀態: Available
- 權限: order read / order write
- Scope: active site
- Read tools:
  - `slimweb_orders_list`: 列出正常訂單。
  - `slimweb_orders_get`: 讀取單一訂單與品項。
  - `slimweb_returns_pending_list`: 列出仍需處理的退貨單。
- Write tools:
  - `slimweb_orders_create_logistics`: 建立正物流。
  - `slimweb_orders_mark_shipped`: 無物流單時手動標記出貨完成。
  - `slimweb_returns_create_logistics`: 建立逆物流。
  - `slimweb_returns_cancel`: 取消退貨,回到正常訂單。
  - `slimweb_returns_complete`: 無逆物流時手動標記已完成退貨。
  - `slimweb_refunds_complete`: 手動標記已完成退款。
  - `slimweb_refunds_create`: 建立綠界/藍新刷退。
- AI rule: 所有 order/return/refund write tools 都必須先依 `slimweb_orders_get`、`slimweb_orders_list` 或 `slimweb_returns_pending_list` 回傳的 `available_actions` 執行。若 `available_actions` 中多個物流選項帶有 `requires_user_choice: true`,必須先詢問用戶要使用哪一家物流,不可自行選。
- 物流規則摘要:
  - 7-11/全家/萊爾富/OK 超商取貨訂單只能建立同一通路的超商物流單。
  - 宅配貨到付款只能建立新竹物流,且新竹物流需啟用代收貨款。
  - 宅配線上付款可依啟用狀態建立綠界宅配或新竹物流;若兩者皆可用,AI 必須詢問用戶。
  - 退貨逆物流與退款互不掛勾;退款另用 refund tools 處理。
- 錯誤情境: order not found、requested action not in `available_actions`、permission denied、provider not enabled、logistics/refund already created。
追蹤欄位: site ID、order ID/order no、provider、store type/type、status labels、raw provider status。

### `slimweb_members_list`

- 狀態: Available
- 權限: member read
- Scope: active site
- 用途: 列出會員,支援客服、行銷與訂單查詢。
- Input: keyword、tier、created date range、pagination、sort
- Output: member summaries、tier、total spent、coupon count、latest order summary
- Side effects: none
- 是否需要 confirmation: no
- 錯誤情境: missing active site、permission denied
- Audit fields: request ID、user ID、account ID、site ID

### `slimweb_members_get`

- 狀態: Available
- 權限: member read
- Scope: active site
- 用途: 讀取單一會員摘要。
- Input: member ID
- Output: member profile summary、tier、total spent、orders summary、available coupons
- Side effects: none
- 是否需要 confirmation: no
- 錯誤情境: member not found、permission denied
- Audit fields: request ID、user ID、account ID、site ID、member ID

### `slimweb_members_coupons_issue`

- 狀態: Available
- 權限: member write + promotion write
- Scope: active site
- 用途: 手動發券給指定會員;只用於 `issue_trigger=manual` 的有效優惠券模板。
- Input: site ID、member ID、coupon template ID、optional reason、confirmation token
- Output: site、member summary、coupon template summary、issued member coupon summary、AI guidance
- Side effects: creates member coupon records
- 是否需要 confirmation: yes。若使用者沒有指定會員,AI 必須先詢問;不能把手動發放猜成發給所有會員。
- 錯誤情境: member not found、coupon template not found、non-manual template、inactive template、duplicate active coupon、validation failed、permission denied
- Audit fields: request ID、user ID、account ID、site ID、member ID、coupon template ID

### `slimweb_member_email_preview` / `slimweb_member_email_send`

- 狀態: Available
- 權限: member read / member write
- Scope: active site
- 用途: 寄送訂單異動、等待通知等一次性且非行銷的會員信;先 preview,使用者確認後再 send。
- Input: `site_code`、`member_ids`、optional `cc_emails`、optional `bcc_emails`、`subject`、`rendered_html`
- 收件規則: `member_ids` 對應 active 會員的 To;CC/BCC 可填任意有效 Email;To、CC、BCC 依序去重後合計最多 5 個信箱。
- Side effects: preview 不寄送;send 在同一個 MCP request 內同步呼叫 SMTP,不建立 queue、電子報或專用寄送紀錄,也不自動 BCC 網站聯絡信箱。
- 錯誤回報: SMTP 當下若指出拒絕的收件信箱,結果會包含該地址;SMTP 接受後才發生的 delayed bounce 無法由同步結果得知。

### `slimweb_newsletters_create`

- 狀態: Available
- 權限: member write
- Scope: active site
- 用途: 建立 Webless 後台電子報資料;此工具只儲存電子報與排程,不直接寄送 email。
- 收件範圍: 固定為排程執行當下所有 active 且 Email 有效的會員,不接受對象或指定會員欄位。
- Input: `site_code`、`title`、`html_content`、optional `scheduled_at`
- Output: site summary、newsletter summary、recipient summary、delivery guidance
- Side effects: creates `site_newsletters`; does not store recipient rows or send email directly.
- 發送時間: 如果使用者沒有指定 `scheduled_at`,AI 應省略欄位,由 MCP 端自動填入「當下時間 + 5 分鐘」。
- 安全規則: 移除 `<script>`、`<iframe>` 與 inline event handler;內容為電子報 HTML,之後由 Webless 後台寄送流程處理。
- 錯誤情境: empty title/content、past scheduled time、permission denied
- Audit fields: request ID、user ID、account ID、site ID、newsletter ID

### `slimweb_posters_create`

- 狀態: Available
- 權限: product read
- Scope: active site
- 用途: 產生商品海報預覽;Webless 後端使用 `gpt-image-2` 圖片編輯/生成並記入 AI 用量,圖片會存成素材庫媒體並回傳可重用的 `image_url` 與 `asset.media_path`。
- Input: `site_code`、`product_names`(1-5 個)、optional `aspect_ratio=9:16|1:1|16:9`、`drawing_prompt`
- 流程: MCP 先依每個 `product_names` 做商品名稱模糊搜尋;若任一名稱查到多筆商品,工具會停止並回傳候選商品讓使用者確認。
- 繪圖資料: 後端使用網站名稱、網站 logo、商品名稱、各商品第一張主圖與 `drawing_prompt` 組成海報 prompt;若商品主圖可下載,會以商品圖作為 image edit 參考以維持商品外觀一致性。
- Output: site summary、product summaries、aspect ratio、durable `image_url`、`asset.media_path`、generation mode、AI usage
- 錯誤情境: product not found、ambiguous product name、too many products、missing drawing prompt、AI generation failed、permission denied
- Audit fields: request ID、user ID、account ID、site ID、product names、aspect ratio

### `slimweb_coupon_templates_list`

- 狀態: Available
- 權限: promotion read
- Scope: active site
- 用途: 列出優惠券模板。
- Input: status、issue trigger、keyword、pagination
- Output: coupon template summaries、issue trigger、minimum spend、threshold amount、date range、expired status、AI guidance
- Side effects: none
- 是否需要 confirmation: no
- 錯誤情境: missing active site、permission denied
- Audit fields: request ID、user ID、account ID、site ID

### `slimweb_coupon_templates_upsert`

- 狀態: Available
- 權限: promotion write
- Scope: active site
- 用途: 新增或更新優惠券模板。
- Input: optional coupon template ID、name、discount amount、minimum spend、issue trigger、trigger amount、starts at、ends at、confirmation token
- Output: coupon template summary、AI guidance
- Side effects: creates or modifies coupon template
- 是否需要 confirmation: yes when creating/updating discount value, validity range, all-members rules, or ambiguous targeting.
- AI 必須先補齊或詢問的條件:
  - `issue_trigger`: `manual` 手動發放、`all_members` 發給所有會員、`order_threshold` 消費滿額自動送、`birthday` 生日禮券、`product_bundle` 商品搭配。
  - `starts_at` / `ends_at`: 除 `birthday` 外必填。
  - `trigger_amount`: `order_threshold` 必填。
  - 手動發放目標: 若使用者沒有說是個別會員或所有會員,必須先詢問並解釋差異。
  - 商品搭配: 目前此工具建立優惠券模板,商品關聯仍沿用商品管理的 `gift_coupon_template_id` 規則。
- 錯誤情境: validation failed、template not found、permission denied、conflict
- Audit fields: request ID、user ID、account ID、site ID、coupon template ID、changed fields

### `slimweb_discount_codes_list`

- 狀態: Available
- 權限: promotion read
- Scope: active site
- 用途: 列出折扣碼。
- Input: status、keyword、platform、pagination
- Output: discount code summaries、ratio、platform、active status、usage summary
- Side effects: none
- 是否需要 confirmation: no
- 錯誤情境: missing active site、permission denied
- Audit fields: request ID、user ID、account ID、site ID

### `slimweb_discount_codes_upsert`

- 狀態: Available
- 權限: promotion write
- Scope: active site
- 用途: 新增或更新折扣碼。
- Input: optional discount code ID、code、ratio or amount、platform、active status、validity rule
- Output: discount code summary、changed fields、audit ID
- Side effects: creates or modifies discount code
- 是否需要 confirmation: yes when activating or changing discount value
- 錯誤情境: duplicate code、validation failed、discount code not found、permission denied、conflict
- Audit fields: request ID、user ID、account ID、site ID、discount code ID、changed fields

### `slimweb_member_tiers_list`

- 狀態: Available
- 權限: promotion read
- Scope: active site
- 用途: 列出會員等級、門檻、折抵百分比與各等級會員數。
- Input: none or pagination
- Output: member tier summaries、thresholds、discount percentages、member counts
- Side effects: none
- 是否需要 confirmation: no
- 錯誤情境: missing active site、permission denied
- Audit fields: request ID、user ID、account ID、site ID

### `slimweb_member_tiers_upsert`

- 狀態: Available
- 權限: promotion write
- Scope: active site
- 用途: 新增或更新會員等級。
- Input: optional tier ID、name、threshold amount、discount percentage、sort order
- Output: member tier summary、affected members estimate if available、audit ID
- Side effects: creates or modifies member tier and may affect future cart discount behavior
- 是否需要 confirmation: yes
- 錯誤情境: validation failed、tier not found、overlapping threshold、permission denied、conflict
- Audit fields: request ID、user ID、account ID、site ID、tier ID、changed fields

### `slimweb_threshold_gifts_list`

- 狀態: Available
- 權限: promotion read
- Scope: active site
- 用途: 列出滿額禮規則。
- Input: status、pagination
- Output: threshold gift summaries、threshold amount、gift product summary、active status
- Side effects: none
- 是否需要 confirmation: no
- 錯誤情境: missing active site、permission denied
- Audit fields: request ID、user ID、account ID、site ID

### `slimweb_threshold_gifts_upsert`

- 狀態: Available
- 權限: promotion write
- Scope: active site
- 用途: 新增或更新滿額禮規則。
- Input: optional threshold gift ID、threshold amount、gift product ID、active status
- Output: threshold gift summary、changed fields、audit ID
- Side effects: creates or modifies threshold gift behavior in cart and orders
- 是否需要 confirmation: yes when activating or changing gift product
- 錯誤情境: validation failed、gift product not found、threshold gift not found、permission denied、conflict
- Audit fields: request ID、user ID、account ID、site ID、threshold gift ID、changed fields

### `slimweb_product_add_ons_list`

- 狀態: Available
- 權限: promotion read
- Scope: active site
- 用途: 列出單品加購規則。
- Input: product ID、status、pagination
- Output: add-on summaries、main product、add-on product、add-on price、max quantity、active status
- Side effects: none
- 是否需要 confirmation: no
- 錯誤情境: missing active site、permission denied
- Audit fields: request ID、user ID、account ID、site ID

### `slimweb_product_add_ons_upsert`

- 狀態: Available
- 權限: promotion write
- Scope: active site
- 用途: 新增或更新單品加購規則。
- Input: optional add-on ID、main product ID、add-on product ID、add-on price、max quantity、active status
- Output: add-on summary、changed fields、audit ID
- Side effects: creates or modifies product add-on behavior on product page and cart
- 是否需要 confirmation: yes when activating or changing price
- 錯誤情境: product not found、invalid relation、validation failed、permission denied、conflict
- Audit fields: request ID、user ID、account ID、site ID、add-on ID、changed fields

### `slimweb_articles_list`

- 狀態: Available
- 權限: content read
- Scope: active site
- 用途: 列出文章,支援 AI 查詢既有內容、避免重複建立,或挑選要更新的文章。
- Input: `site_code`、optional `page`、optional `per_page`
- Output: article summaries、pagination
- Side effects: none
- 是否需要 confirmation: no
- 錯誤情境: site not found、permission denied
- Audit fields: request ID、user ID、account ID、site ID

### `slimweb_articles_check_title`

- 狀態: Available
- 權限: content read
- Scope: active site
- 用途: 檢查文章標題是否撞名。
- Input: `site_code`、`title`
- Output: article title check result、matches
- Side effects: none
- 是否需要 confirmation: no
- 錯誤情境: site not found、permission denied
- Audit fields: request ID、user ID、account ID、site ID

### `slimweb_articles_get_content`

- 狀態: Available
- 權限: content read
- Scope: active site
- 用途: 讀取單一文章內容與中繼資訊。
- Input: `site_code`、`article_id`
- Output: article、cover URL、article URL、content body
- Side effects: none
- 是否需要 confirmation: no
- 錯誤情境: article not found、site not found、permission denied
- Audit fields: request ID、user ID、account ID、site ID、article ID

### `slimweb_articles_create`

- 狀態: Available
- 權限: content write + asset write
- Scope: active site
- 用途: 新增文章。建立時必須有 16:9 主圖,也可附加內容圖。若使用者沒有給圖且沒有描述主圖,AI 會依文章標題或內容先畫主圖;若目前是 ChatGPT Remote MCP 而且沒有可用附圖或可直接下載的圖片 URL,就先終止任務並請使用者貼圖,等圖是 AI 產出且還沒轉成可上傳附件時再建立文章。
- Input: `site_code`、`title`、`content_html`、`cover_image`、optional `notion_page_id`、optional `content_images`
- Output: article summary、article URL、cover URL、content image URLs
- Side effects: creates `articles`; writes article cover and content images under site article storage paths
- 是否需要 confirmation: yes when the cover image was AI-generated and still needs user re-upload in ChatGPT clients
- 錯誤情境: validation failed、article title exists、permission denied、conflict
- Audit fields: request ID、user ID、account ID、site ID、article ID、changed fields

### `slimweb_articles_update`

- 狀態: Available
- 權限: content write + asset write
- Scope: active site
- 用途: 修改既有文章。流程與頁面修改相同,讀取現有內容後再決定要不要更新標題、主圖或內容圖;若目前是 ChatGPT Remote MCP 而且沒有可用附圖或可直接下載的圖片 URL,就先終止任務並請使用者貼圖。
- Input: `site_code`、`article_id`、optional `title`、optional `content_html`、optional `cover_image`、optional `notion_page_id`、optional `content_images`
- Output: article summary、article URL、cover URL、content image URLs
- Side effects: modifies `articles`; can replace article cover and content images under site article storage paths
- 是否需要 confirmation: yes when replacing an existing article body or cover image
- 錯誤情境: validation failed、article not found、permission denied、conflict
- Audit fields: request ID、user ID、account ID、site ID、article ID、changed fields

### `slimweb_content_seo_update`

- 狀態: Available
- 權限: content write
- Scope: active site
- 用途: 更新單一自訂頁面或單一文章的內容層級 SEO / AEO / GEO metadata。此工具不能單獨執行,必須接在 `slimweb_pages_create`、`slimweb_pages_update`、`slimweb_articles_create` 或 `slimweb_articles_update` 之後。
- Input: `site_code`、`content_type` (`page` or `article`)、`workflow_context` (`page_create`、`page_update`、`article_create`、`article_update`)、page target (`page_name` or `page_key`) or `article_id`,以及 optional SEO / AEO / GEO fields
- Output: updated content target、SEO / AEO / GEO metadata、metadata path
- Side effects: updates custom page `.page.json` SEO metadata or MCP-managed article SEO metadata JSON
- 是否需要 confirmation: no when it is part of a confirmed create/edit content workflow
- 錯誤情境: missing workflow_context、workflow/content type mismatch、page not found、article not found、validation failed、permission denied
- Rule: 不可用 `slimweb_content_seo_update` 處理全站 SEO;全站 SEO 必須使用 `slimweb_seo_settings_update`。
- Storage contract:
  - Page: `sites/{site_id}/templates/default/pages/{page_key}/.page.json`
  - Article: `sites/{site_id}/articles/{article_id}/seo.json`
  - Both store the complete nested `seo` object plus `seo_updated_at`.
- Publication contract: content values override site settings field by field. Content `robots_policy` can narrow a public page, but it cannot override platform-forced `noindex` routes or preview/expired/private states.
- URL rule: content `canonical_url` must stay on the authoritative storefront host and platform site prefix; query/fragment are removed. `og_image_url` must be HTTP(S).

### `slimweb_customer_service_logs_list`

- 狀態: Available
- 權限: customer service read
- Scope: active site
- 用途: 查詢 AI 客服紀錄,支援客服追蹤與品質檢查。
- Input: keyword、date range、customer identifier、pagination
- Output: log summaries、customer summary、message excerpts、resolution status、timestamps
- Side effects: none
- 是否需要 confirmation: no
- 錯誤情境: missing active site、permission denied、invalid filter
- Audit fields: request ID、user ID、account ID、site ID

### `slimweb_customer_service_settings_get`

- 狀態: Available
- 權限: customer service read
- Scope: active site
- 用途: 讀取 AI 客服設定摘要。
- Input: none or fields list
- Output: enabled status、response policy summary、knowledge source summary、handoff settings、editable field hints
- Side effects: none
- 是否需要 confirmation: no
- 錯誤情境: missing active site、permission denied
- Audit fields: request ID、user ID、account ID、site ID

### `slimweb_customer_service_settings_update`

- 狀態: Available
- 權限: customer service write
- Scope: active site
- 用途: 更新 AI 客服設定。
- Input: patch object for allowlisted customer service settings
- Output: updated settings summary、changed fields、warnings、audit ID
- Side effects: modifies customer service behavior
- 是否需要 confirmation: yes when enabling/disabling AI customer service or changing response policy
- 錯誤情境: validation failed、unsupported field、permission denied、conflict
- Audit fields: request ID、user ID、account ID、site ID、changed fields

### `slimweb_exports_create`

- 狀態: Available
- 權限: export read
- Scope: active site
- 用途: 建立會員、訂單或退貨資料匯出檔。
- Input: export type (`members`, `orders`, `returns`)、filters、format (`xlsx`, `csv`, `sql`)
- Output: export job ID、download URL if ready、expires at、row count if available
- Side effects: creates export job or file
- 是否需要 confirmation: yes for exports containing member personal data
- 錯誤情境: unsupported export type、permission denied、too many rows、export failed
- Audit fields: request ID、user ID、account ID、site ID、export type、export job ID

### `slimweb_assets_upload`

- 狀態: Available
- 權限: asset write
- Scope: active site
- 用途: 只有在 AI flow 明確需要登記已上傳圖片或檔案時,才建立 reusable asset reference。
- Input: `site_code`、`source.media_path`、`target_usage`、`asset_scope`、optional `theme_id`、`suggested_filename`、`alt_text`
- 圖片規則: 圖片 bytes 不進 MCP tool JSON。AI runtime 必須能讀取圖片 bytes 並對外 `PUT`;符合時先使用 `slimweb_uploads_create` 取得 signed upload URL,對 URL 做 raw bytes `PUT`,再用 `slimweb_uploads_commit` 回傳的 `media_path` 登記 asset。若 runtime 是 ChatGPT Remote MCP 且只有對話附件,應告知使用者改用 Codex / Hermes 或提供可下載圖片 URL。
- Output: storage path、public URL、usage、alt text、mime type
- Side effects: registers committed Webless media path for later page/theme/product/article use
- 是否需要 confirmation: replacing existing customer-facing asset 時需要
- 錯誤情境: unsupported source、file too large、missing usage、unauthorized、storage adapter not configured
- Audit fields: request ID、user ID、account ID、site ID、asset ID、usage

### `slimweb_pages_check_title`

- 狀態: Available
- 權限: content read
- Scope: active site
- 用途: 檢查頁面標題是否已存在,固定頁除了中文標題,也會比對英文別名與 `home` 相關別名,採用 trim + 大小寫不敏感規則。
- Input: `site_code`、`title`
- Output: site summary、original title、normalized title、exists flag、matched pages
- Side effects: none
- 是否需要 confirmation: no
- 錯誤情境: missing title、site not found、permission denied
- Audit fields: request ID、user ID、account ID、site ID、title

### `slimweb_pages_get_content`

- 狀態: Available
- 權限: content read
- Scope: active site
- 用途: 依 `page_name` 讀取單一可編輯頁面的內容與中繼資訊;包含自訂頁與首頁 `index`,其他固定頁不可編輯。
- Input: `site_code`、`page_name`
- Output: site summary、page summary、content HTML、storage path、metadata path、public URL、preview URL
- Side effects: none
- 是否需要 confirmation: no
- 錯誤情境: page not found、site not found、storage adapter not configured
- Audit fields: request ID、user ID、account ID、site ID、page name、page key

### `slimweb_pages_create`

- 狀態: Available
- 權限: content write
- Scope: active site
- 用途: 建立新的自訂頁面。AI 應先確認標題不撞名,再依設計摘要與圖片素材建立單頁 HTML/CSS;頁面 JavaScript 只能放在 `content.javascript`,由 SlimWeb 寫入固定的 `assets/js/90-mcp-page.js`,固定頁不可透過這個工具建立或覆寫。若目前是 ChatGPT Remote MCP 而且沒有可用附圖或可直接下載的圖片 URL,就先終止任務並請使用者貼圖。
- Input: `site_code`、`title`、`content.html` or `content.body_html`、optional `content.javascript`、`enabled_libraries`、optional `page_key`、optional `confirmation_token`
- Output: write summary、site summary、theme summary、page key、title、public URL、preview URL、HTML/JavaScript bytes written
- Side effects: writes custom page body, metadata, and at most one MCP-owned page JavaScript asset to Webless template storage
- 是否需要 confirmation: yes when creating customer-facing content
- 錯誤情境: title already exists、unsafe content、site not found、storage adapter not configured
- Audit fields: request ID、user ID、account ID、site ID、page key、title

### `slimweb_pages_update`

- 狀態: Available
- 權限: content write
- Scope: active site
- 用途: 修改既有可編輯頁面,包含自訂頁與首頁 `index`。流程會先用 `slimweb_pages_get_content` 讀取目前頁面內容、正式 JavaScript 與 `enabled_libraries`;其他固定系統頁不可編輯。更新時省略 `content.javascript` 會保留既有程式,傳入非空內容會取代,傳入空字串會刪除。若目前是 ChatGPT Remote MCP 而且沒有可用附圖或可直接下載的圖片 URL,就先終止任務並請使用者貼圖。
- Input: `site_code`、`page_name`、`content.html` or `content.body_html`、optional `content.javascript`、`enabled_libraries`、optional `title`、optional `confirmation_token`
- Output: write summary、site summary、theme summary、page key、title、public URL、preview URL、bytes written
- Side effects: overwrites page body in configured Webless template storage and may preserve, replace, or delete `assets/js/90-mcp-page.js`; custom pages also update metadata, while homepage `index` keeps fixed-page metadata
- 是否需要 confirmation: yes when replacing customer-facing content
- 錯誤情境: page not found、unsafe content、site not found、storage adapter not configured
- Audit fields: request ID、user ID、account ID、site ID、page key、title

### `slimweb_preview_get_page_url`

- 狀態: Available
- 權限: content read
- Scope: active site
- 用途: 回傳 AI 可開啟並自行截圖的頁面預覽 URL。`page_key=index` 會回傳站台唯一首頁預覽;可依 theme 檢視該頁的基底樣式。
- Input: `site_code`、`page_key`、optional `theme_id` for non-home pages、optional `mode`
- Output: site summary、page key、theme summary、preview URL、mode、theme parameter support hint
- Side effects: none
- 是否需要 confirmation: no
- 錯誤情境: site not found、theme not found、invalid page key
- Audit fields: request ID、user ID、account ID、site ID、theme ID、page key

### 頁面可用外部視覺支援

`slimweb_pages_create` 與 `slimweb_pages_update` 都必須傳入 `enabled_libraries`。沒有使用外部支援時傳 `[]`。AI 可依頁面需求自行選用下列 allowlist;不要在 `content.html` 內自行加入 CDN `<script src>`、`<link>`、inline event handler 或 JavaScript。SlimWeb 會依參數載入固定 library,頁面自訂程式則只使用 `content.javascript`,並集中管理在單一 `assets/js/90-mcp-page.js`,避免 GSAP、Swiper 與臨時動畫檔互相覆蓋或重複初始化。

| key | 類型 | 名稱 | 用途 | AI 使用建議 |
| --- | --- | --- | --- | --- |
| `animate_css` | CSS | Animate.css | 現成進場/提示動畫 | 少量強調元素可用,不適合整頁到處套 |
| `aos` | JS + CSS | AOS | scroll reveal,元素進入視窗時淡入/位移 | 比 GSAP 簡單,適合一般形象頁 |
| `swiper` | JS + CSS | Swiper | 輪播、商品滑動、案例 slider | 只在真的有 slider/carousel 時開 |
| `gsap` | JS | GSAP core | 複雜時間軸動畫 | 高階選項,AI 要有明確動畫需求才用 |
| `scrolltrigger` | JS | GSAP plugin | 滾動觸發 GSAP 動畫 | 依賴 `gsap`,適合進階 scroll storytelling |
| `scrollsmoother` | JS | GSAP plugin | 平滑滾動、沉浸式滾動頁 | 第一版視為進階選項,除非使用者明確需要,否則不要自動開 |

### `slimweb_audit_list`

- 狀態: Available
- 權限: audit read
- Scope: active site
- 用途: 列出近期 MCP tool execution 紀錄,支援追蹤、除錯與客服。
- Input: tool name、date range、actor user ID、result、pagination
- Output: audit entries、tool names、actors、targets、results、timestamps、request IDs
- Side effects: none
- 是否需要 confirmation: no
- 錯誤情境: missing active site、permission denied、invalid filter
- Audit fields: request ID、user ID、account ID、site ID

## 圖片與素材政策

AI Client 收到或引用的圖片預設是 reference-only。只有當 tool call 明確要求保存,且使用情境合理時,MCP Server 才應該把圖片寫入 SlimWeb reusable asset。

圖片相關 tools 建議使用下列欄位:

- `image_usage`: `reference`、`product_image`、`brand_asset`
- `save_image`: boolean
- `asset_scope`: `site`、`product`
- `target`: product 或 site 的 stable ID
- `suggested_filename`
- `alt_text`

頁面與版型相關素材會在 page/template tools 定義時再補充。

- 若 Default 頁面內容需要外部資源,AI 應優先使用 page scope,並說明為何該頁需要該資源。
- 當使用者要求 AI 建立或修改非 Default 版型時,theme scope 可用,但必須明確指定目標 theme。
- 版型與內容分離:版型是每一頁的基底;Default 與自訂版型都會影響頁面的基礎外觀,包含首頁與其他頁面。
- 色系與版型分離:`sites.theme_mode` 是唯一 light/dark 來源。AI 不應在一般版型或頁面任務中硬寫文字顏色、按鈕底色等全域 theme CSS;除非使用者明確指定。若使用者要求 neon、螢光、暗色高對比等風格,先確認或切換為 `dark`。
- 建立或修改版型、頁面視覺、插圖或其他畫圖任務前,AI 必須先讀 `slimweb_design_context_get`;若需要真實 nav/footer/分類資料形狀,再補讀 `slimweb_theme_shell_get_context` 與 `slimweb_theme_style_profile_get`。
- `slimweb_theme_shell_get_context` 回傳的是 reference-only JSON。AI 可以用它決定 spacing、icon、容器容量與 responsive 行為,但不可把 nav/footer/contact 等真實資料寫死到版型片段。
- `slimweb_theme_shell_get_context.root_css.current_css` 是目前 MCP-managed root CSS;修改版型 CSS 時先讀這份 CSS,改完後把完整 CSS 傳給 `slimweb_themes_update_root_elements.css` 存回。
- 在 ChatGPT Remote MCP 中,如果頁面或文章需求需要圖片,但使用者沒有附圖,也沒有可直接下載的圖片 URL,AI 必須先終止任務並請使用者貼上或重新上傳圖片,再繼續後面的建立或修改流程。

### 必要執行的通用規則

- 執行任何 MCP 工具前,必須先執行 `SlimWeb.slimweb_sites_list` 取得可操作網站的 `site_code` 與站台名稱。
- 如果超過一個以上的網站,終止任務,列出站台名稱讓用戶選擇。
- 禁止使用 `SlimWeb.slimweb_sites_list` 結果內不存在的 `site_code`,也不要要求使用者提供 numeric `site_id`。

### 通用圖片規則

- 如果任務需要圖片素材,AI 必須先取得可用的圖片 URL 或 media path,才能建立或修改頁面、文章。
- 如果圖片已經是公開可存取的 URL,可以直接使用該 URL。
- 如果 Client 具備本地端檔案操作與上傳能力,使用 `slimweb_uploads_create` 與 `slimweb_uploads_commit` 將圖片上傳至 server,取得可用的 media path / URL。
- 如果 Client 不具備本地端檔案操作或無法直接上傳圖片,但使用者已在對話中貼上圖片附件,使用 `slimweb_images_import_chatgpt_attachment` 匯入附件並取得圖片 URL 或 media path。
- 如果 Client 不具備本地端檔案操作或無法直接上傳圖片,且使用者尚未貼上圖片附件或圖片 URL,必須停止任務,請使用者先貼上圖片或提供圖片 URL。
- 如果圖片由 AI 產生,產生圖片時應參考 `slimweb_design_context_get` 取得的網站色系與設計方向,讓圖片與目前版型一致。
- 如果圖片由 AI 產生且 Client 不具備本地端檔案操作與上傳能力,必須停止任務,要求用戶將 AI 所繪製的圖片貼回對話框。

### 內容 SEO / AEO / GEO 規則

- 建立或編輯頁面、文章後,AI 應預設產生內容層級 SEO / AEO / GEO metadata。
- 即使使用者沒有明確要求 SEO,也應依照頁面或文章的主題、標題、內容與圖片自動產生。
- 只有在使用者明確表示「不用 SEO」、「不要改 SEO」、「只改內容」時,才跳過此步驟。
- 使用 `slimweb_content_seo_update` 更新單一頁面或單一文章的內容層級 SEO / AEO / GEO。
- `slimweb_content_seo_update` 不能單獨執行,必須搭配建立/編輯頁面,或建立/編輯文章流程。
- 頁面建立後使用 `workflow_context: page_create`;頁面編輯後使用 `workflow_context: page_update`。
- 文章建立後使用 `workflow_context: article_create`;文章編輯後使用 `workflow_context: article_update`。
- 不可使用 `slimweb_seo_settings_update` 來處理單一頁面或單一文章的 SEO,因為那是全站設定。
- 頁面 metadata 正式路徑是 `sites/{site_id}/templates/default/pages/{page_key}/.page.json`;文章是 `sites/{site_id}/articles/{article_id}/seo.json`。
- `robots_policy` 的繼承順序是平台強制狀態、內容公開狀態、內容設定、全站設定。登入、會員、購物車、結帳、付款、AI、callback、API、預覽、過期與未知 route 不可被改成可索引。
- canonical 只能使用商家的自訂網域或該站的 SlimWeb platform path;OG 圖片只能使用 HTTP(S)。
- 寫入完成後若需要驗證發布結果,應讀取公開 storefront HTML 或對應的 sitemap/robots/llms 文件,而不是只把工具成功回應當成已發布證據。

### 建立頁面

- 建立頁面前必須有 `title`,沒有就先詢問使用者。
- 使用 `slimweb_pages_check_title` 檢查標題是否撞名;如果 `exists` 為 `true`,立刻停止並告知使用者。
- 使用 `slimweb_design_context_get` 取得目前網站版型摘要、色系與框架。
- 頁面如果有圖片需求,依照通用圖片規則處理。
- 以網站版型摘要、色系、使用框架為基礎進行設計。
- HTML 可以自訂 CSS 以及頁面範圍 inline JavaScript;互動元素如 accordion、FAQ、tabs 優先用 HTML + Tailwind + 自訂 CSS,不必開大型 JS。
- 依需求決定 `enabled_libraries`,沒有外部支援時傳 `[]`;少量提示動畫優先用 `animate_css`,scroll reveal 優先用 `aos`,輪播才用 `swiper`,進階滾動敘事才使用 `gsap` / `scrolltrigger` / `scrollsmoother`。
- 使用 `slimweb_pages_create` 建立頁面。
- 除非使用者明確表示不用 SEO,建立後使用 `slimweb_content_seo_update` 搭配 `workflow_context: page_create` 更新內容層級 SEO / AEO / GEO。
- 建立完成後回傳頁面 URL,可用 `slimweb_preview_get_page_url` 做預覽驗證。

### 編輯頁面

- 編輯頁面前必須有 `page_name`,沒有就先詢問使用者。
- 使用 `slimweb_pages_get_content` 取得目前頁面內容。
- 如果找不到頁面,立刻停止並告知使用者。
- 如果需要新增或替換圖片,依通用圖片規則處理。
- 參考目前內容與 `slimweb_design_context_get` 的設計摘要修改 HTML。
- 依修改後頁面的實際需求保留或調整 `enabled_libraries`,沒有外部支援時傳 `[]`。
- 使用 `slimweb_pages_update` 回存頁面。
- 除非使用者明確表示不用 SEO,編輯後使用 `slimweb_content_seo_update` 搭配 `workflow_context: page_update` 更新內容層級 SEO / AEO / GEO。
- 編輯完成後回傳頁面 URL,可用 `slimweb_preview_get_page_url` 做預覽驗證。

### 建立文章

- 建立文章前必須有 `title`,沒有就先詢問使用者。
- 使用 `slimweb_articles_check_title` 檢查標題是否撞名;如果 `exists` 為 `true`,立刻停止並告知使用者。
- 使用 `slimweb_design_context_get` 取得目前網站版型摘要、色系與框架。
- 新文章一定要有 16:9 主圖。
- 如果使用者沒有提供主圖,也沒有描述主圖怎麼畫,AI 就依文章標題或內容先畫主圖。
- 如果使用者要求內容圖,也依通用圖片規則處理。
- 參考 `slimweb_design_context_get` 的設計摘要排版文章 HTML;文章標題由系統欄位顯示,`content_html` 不應重複放同名 `h1`。
- 使用 `slimweb_articles_create` 建立文章。
- 除非使用者明確表示不用 SEO,建立後使用 `slimweb_content_seo_update` 搭配 `workflow_context: article_create` 更新內容層級 SEO / AEO / GEO。
- 建立完成後回傳文章 URL。

### 從 Notion 導入或更新文章

- 使用者以 Notion 頁面標題指定來源;先呼叫 `slimweb_notion_pages_search`。
- 只有一筆完全符合時才能直接繼續;多筆完全符合或只有部分符合時,列出候選並請使用者確認;沒有結果時請使用者檢查標題及 Notion integration 授權。
- 以 `notion_page_id` 判斷是否已導入。一般導入要求發現既有文章時,先詢問是否更新;使用者明確要求更新且已導入時可直接繼續。
- 呼叫 `slimweb_notion_page_get_content` 取得標題與安全 HTML;此工具不直接寫入文章。
- 優先使用使用者已提供的圖片。需要 AI 畫 16:9 主圖時,可讀取圖片 bytes 並 PUT 的 runtime 直接完成 upload/commit;Remote MCP 無法傳送生成圖片 bytes 時,先畫圖並等待使用者把核准圖片貼回,再匯入並續接。
- 最後依導入狀態呼叫 `slimweb_articles_create` 或 `slimweb_articles_update`。

### 編輯文章

- 編輯文章前必須有文章識別資訊;使用者可以提供 `article_id` 或文章標題,兩者都沒有就先詢問使用者。
- 如果使用者提供的是文章標題,先使用 `slimweb_articles_list` 取得文章列表,依標題比對目標文章並取得 `article_id`;如果找不到或有多筆相近結果,立刻停止並請使用者確認。
- 使用 `slimweb_articles_get_content` 取得目前文章內容。
- 如果找不到文章,立刻停止並告知使用者。
- 使用 `slimweb_design_context_get` 取得目前網站版型摘要、色系與框架。
- 如果需要新增或替換主圖、內容圖,依照通用圖片規則處理。
- 參考目前文章內容與 `slimweb_design_context_get` 的設計摘要修改 `content_html`。
- 如果修改文章標題,必須先使用 `slimweb_articles_check_title` 檢查新標題是否撞名;如果 `exists` 為 `true`,立刻停止並告知使用者。
- `content_html` 不應重複放同名 `h1`,因為 SlimWeb 會另外渲染文章標題。
- 使用 `slimweb_articles_update` 回存文章。
- 除非使用者明確表示不用 SEO,編輯後使用 `slimweb_content_seo_update` 搭配 `workflow_context: article_update` 更新內容層級 SEO / AEO / GEO。
- 編輯完成後回傳文章 URL。

### 刪除文章

- 先以 `slimweb_articles_list` 或 `slimweb_articles_get_content` 取得唯一、穩定的 `article_id`。
- 標題有多筆相近候選時必須請使用者確認,不可猜測。
- 使用 `slimweb_articles_delete` 刪除指定文章與後台同樣會刪除的封面素材。

### 建立版型

- 建立版型前必須有 `name`,沒有就先詢問使用者。
- 使用 `slimweb_themes_list` 檢查是否已有同名或近似自訂版型;如果已有明確同名版型,立刻停止並告知使用者。
- 如果使用者要求暗色、螢光、neon、高對比等明顯依賴明暗模式的風格,先使用 `slimweb_site_theme_mode_get` 確認目前色系;必要時使用 `slimweb_site_theme_mode_update` 切換 light / dark。
- 使用 `slimweb_themes_create_from_default` 建立新的自訂版型;不複製 Default root storage,未修改的 slots 使用 canonical runtime fallback。
- 使用 `slimweb_theme_shell_get_context` 取得 navbar、floating_actions、footer、分類模式與 canonical hooks、固定 `primary_navigation`/`member_auth`/`cart` 插槽等真實 shell reference 資料,以及目前 MCP-managed root CSS。
- 每個 Theme navbar 一律包含一個容器型 `data-storefront-primary-navigation-slot`、一個可點擊的 `data-storefront-member-auth-slot` 與一個可點擊的 `data-storefront-cart-slot`;參考網站與 `website_type` 只影響設計背景,不改變 Theme schema。
- CSS 必須涵蓋 `[data-storefront-category-menu]`、`[data-storefront-navbar-categories]` 與 `[data-storefront-nav-items]` 的遞迴節點/trigger/panel/children/depth 狀態。Theme HTML 不複製 live category/nav labels、URLs 或樹狀資料,Webless runtime 會注入它們。
- 使用 `slimweb_design_context_get` 取得目前網站設計摘要、色系與框架。
- 依照使用者需求、網站色系、shell reference 與框架設計版型基底,包含 navbar、floating_actions、footer、root CSS、body background、全站視覺氛圍等。
- 修改 `slimweb_theme_shell_get_context.root_css.current_css` 後,使用 `slimweb_themes_update_root_elements` 寫入新版型的 navbar、floating_actions、footer 與完整 root CSS;不可用此工具修改單一頁面內容。
- `slimweb_themes_update_root_elements.css` 會替換 MCP-managed root CSS 檔,不是 patch 單一 selector;回存時要包含所有需要保留的 navbar、floating_actions、footer、body background 等 root CSS。
- Theme slot 內內容由使用者自行定義,不綁定既有聯絡資料;Theme 不載入 JavaScript 或 `enabled_libraries`。
- 使用 `slimweb_theme_style_profile_upsert` 保存此版型的風格摘要,例如色彩、字體、版面、插圖方向、避免事項與使用者需求。
- 建立完成後回傳版型名稱與 `theme_id`;只有在使用者明確要求啟用時,才使用 `slimweb_themes_activate` 啟用新版型。

### 修改版型

- navbar、floating_actions、footer、root CSS 與 style profile 都是 Theme-managed elements。修改前先用 `slimweb_design_context_get` 讀取目前啟用版型與 `theme_edit_policy`。
- 目前啟用版型是 Default 時,不提供直接修改選項;直接以 `slimweb_themes_create_from_default` 建立新版型,再把修改寫入新版型。
- 目前啟用版型是非 Default 時,必須先詢問使用者要建立新版型或直接修改目前版型。選擇建立時用 `slimweb_themes_create_from_theme` 複製目前版型;選擇直接修改時,每個 root/style-profile write 都傳 `confirmed_active_theme_edit: true`。
- 使用 `slimweb_themes_list` 找到精確目標;如果找不到或有多個可能目標,立刻停止並請使用者確認。
- 使用 `slimweb_theme_style_profile_get` 取得目前版型風格摘要與歷史需求。
- 使用 `slimweb_theme_shell_get_context` 取得 navbar、floating_actions、footer、分類模式、canonical hooks 與三個固定呈現插槽等真實 shell reference 資料,以及目前 MCP-managed root CSS。
- 使用 `slimweb_design_context_get` 取得目前網站設計摘要、色系與框架。
- 如果使用者要求暗色、螢光、neon、高對比等明顯依賴明暗模式的風格,先使用 `slimweb_site_theme_mode_get` 確認目前色系;必要時使用 `slimweb_site_theme_mode_update` 切換 light / dark。
- 依照使用者需求、既有風格摘要、網站色系、shell reference 與框架修改版型基底,包含 navbar、floating_actions、footer、root CSS、body background、全站視覺氛圍等。
- 保留唯一 `data-storefront-primary-navigation-slot` 容器與可點擊的 member/cart slots;CSS 同時保留 grouped categories、navbar categories 與 ordinary recursive navigation 的 styling,且不可把 live labels/URLs 寫進 Theme HTML。
- 修改 `slimweb_theme_shell_get_context.root_css.current_css` 後,使用 `slimweb_themes_update_root_elements` 回存 navbar、floating_actions、footer 與完整 root CSS;不可用此工具修改單一頁面內容。
- `slimweb_themes_update_root_elements.css` 會替換 MCP-managed root CSS 檔,不是 patch 單一 selector;修改局部視覺時要一併保留既有 navbar、floating_actions、footer、body background 等 root CSS。
- 使用 `slimweb_theme_style_profile_upsert` 更新版型風格摘要。
- 使用 `slimweb_theme_style_profile_append_request` 追加本次使用者修改需求與 AI 設計說明。
- 修改完成後回傳版型名稱與 `theme_id`;只有在使用者明確要求啟用時,才使用 `slimweb_themes_activate` 啟用該版型。

### Email 共用版型編輯

- Email 共用版型只有編輯流程,沒有建立流程;使用者要求建立 email 版型時,應視為編輯站台唯一共用 email 版型。
- 使用 `slimweb_mail_layout_get` 取得目前共用 email 版型、預設版型 HTML 與可用 placeholders。
- Email 共用版型是所有 email 內容外層共用的 layout,例如背景、logo、站名、外框、footer、整體容器與全域按鈕樣式。
- 必須以 `slimweb_mail_layout_get` 回傳的 current layout 或 default layout 為基礎修改,不可憑空重寫整份 HTML。
- 必須保留 `{content}` placeholder,因為各事件 email 內容會被插入 `{content}`。
- 必須保留 `{site_name}`、`{site_url}`、`{logo_url}` 等既有 placeholders。
- Email HTML 應使用 email client 友善寫法:簡單結構、inline style、固定寬度容器、保守 CSS;避免 JavaScript、外部 CSS、複雜互動與一般網頁 layout 技術。
- 如果共用版型需要圖片,依照通用圖片規則處理,且圖片應使用穩定可公開存取的 URL。
- 使用 `slimweb_mail_layout_update` 回存完整 HTML,並設定 `is_active`。
- 編輯完成後告知使用者:此共用 email 版型會套用到所有 email 內容。

### Email 內容編輯

- Email 內容編輯前,必須先確認使用者要修改哪一種 email 內容;如果沒有明確指定,就先詢問使用者。
- 使用 `slimweb_mail_templates_get` 取得目前所有 email 內容模板。
- AI 必須從使用者語意判斷目標 email 類型,不可猜測或受歷史紀錄影響。
- 可編輯項目包含:email 標題、email 內容 HTML、內容內部版型、內容圖片,以及是否啟用。
- 如果需要新增或替換圖片,依照通用圖片規則處理。
- 修改內容 HTML 時,只處理該 email 事件的內容本身,不可在這裡修改全站共用 email 外框。
- Email 內容 HTML 應使用 email client 友善寫法:inline style、簡單表格或區塊、保守 CSS;避免 JavaScript、外部 CSS 與複雜互動。
- 如果只是修改標題,使用 `slimweb_mail_templates_update` 更新對應 `trigger_event` 的 `subject`。
- 如果修改內容或內容版型,使用 `slimweb_mail_templates_update` 更新對應 `trigger_event` 的 `content`。
- 如果使用者要求啟用或停用某封 email,使用 `slimweb_mail_templates_update` 更新對應 `trigger_event` 的 `is_active`。
- 編輯完成後回傳修改的 email 類型、標題與更新結果。

## 安全要求

- Remote MCP traffic 必須使用 HTTPS。
- 除非明確文件化為 public tool,所有 tool calls 都必須登入。
- 每次 tool call 都要做 authorization。
- MCP Server 不可暴露 SlimWeb secrets、database credentials、storage credentials。
- Write tools 必須有 server-side schema validation。
- 高影響 write tools 必須有 confirmation 機制。
- Tool execution 必須記錄 request ID、user ID、account ID、site ID、tool name、result、timestamp。
- Error message 要可供使用者修正問題,但不可洩漏內部實作細節。

## 錯誤模型

MCP tools 應回傳可預期的錯誤類型:

| Code | 意義 |
| --- | --- |
| `AUTH_REQUIRED` | 使用者需要完成 Google 登入。 |
| `SESSION_EXPIRED` | MCP session 已過期,需要 refresh 或重新登入。 |
| `PERMISSION_DENIED` | 使用者沒有足夠 SlimWeb 權限。 |
| `SITE_SCOPE_REQUIRED` | tool 需要 active site。 |
| `VALIDATION_FAILED` | input 未通過 schema 或 business validation。 |
| `CONFIRMATION_REQUIRED` | 操作需要明確 confirmation。 |
| `CONFLICT` | 目標資料在讀取後已被其他操作修改。 |
| `UPSTREAM_ERROR` | SlimWeb / Webless 回傳非預期錯誤。 |

## 開發原則

- SlimWeb / Webless 是資料與商業規則的 source of truth。
- 優先做 structured tools,不做不受控的 free-form admin automation。
- 先做 read tools,再逐步加入窄範圍 write tools。
- Tool output 要穩定,讓 AI Client 可以可靠推理。
- Tool surface 要保持小,直到權限、audit、validation、rollback 行為可靠。
- 每次新增或改動 tool,都要更新這份 README。

## Repo 狀態

此 repo 目前包含初版 MCP 架構文件,以及可部署到 Cloud Run 的最小 Remote MCP HTTP service。

目前服務入口:

- `GET /`: service metadata
- `GET /readyz`: readiness check
- `GET /healthz`: local health check path; Cloud Run public URL may reserve this path, use `/readyz` for online verification
- `GET /.well-known/oauth-protected-resource`: OAuth protected resource metadata for ChatGPT remote MCP discovery
- `GET /.well-known/oauth-protected-resource/mcp`: OAuth protected resource metadata variant for the `/mcp` resource path
- `GET /.well-known/oauth-authorization-server`: OAuth authorization server metadata
- `GET /.well-known/openid-configuration`: OAuth/OpenID metadata compatibility endpoint
- `POST /oauth/register`: dynamic OAuth client registration for ChatGPT developer mode
- `GET /oauth/authorize`: OAuth authorization code endpoint
- `POST /oauth/token`: OAuth token endpoint; exchanges authorization code + PKCE verifier for MCP bearer token
- `GET /auth/login`: SlimWeb MCP Google 登入頁
- `POST /auth/google`: 接收 Google Identity credential,並由 Webless Backend API 驗證其可管理的網站
- `GET /auth/success`: 登入完成頁
- `POST /mcp`: MCP JSON-RPC endpoint,目前支援 `initialize`、`tools/list` 與 `tools/call`

目前已進入 MCP discovery 的 tools:

- `slimweb_auth_status`
- `slimweb_sites_list`
- `slimweb_site_select`
- `slimweb_themes_list`
- `slimweb_site_theme_mode_get`
- `slimweb_site_theme_mode_update`
- `slimweb_themes_create_from_default`
- `slimweb_themes_create_from_theme`
- `slimweb_themes_activate`
- `slimweb_themes_update_root_elements`
- `slimweb_assets_upload`
- `slimweb_pages_check_title`
- `slimweb_pages_get_content`
- `slimweb_pages_create`
- `slimweb_pages_update`
- `slimweb_preview_get_page_url`

主工具表以目前 `tools/list` discovery 為準;尚未出現在主表的舊 contracts 不應視為已實作。

首頁、資產、資料庫與第三方整合寫入全部由 Webless Backend API 執行。SlimWeb-MCP 不持有資料庫、Cloud SQL、GCS、Webless Laravel app key 或其他 provider credentials,也不會寫入自己的 Cloud Run ephemeral disk。

## 登入與 webless 帳號系統

MCP service 使用與 webless 相同的 Google Client ID 驗證 Google Identity token。SaaS Backend API 遷移採領域分批進行,目前執行路徑如下:

| Domain | Current SaaS execution path |
| --- | --- |
| Google admin site list and site permission resolution | Webless `/internal/mcp/v1` API |
| All 123 site data/storage tools | Webless `/internal/mcp/v1` API |
| Edge-only authentication/status tools | SlimWeb-MCP process |

SaaS MCP 使用以下設定:

- `WEBLESS_BACKEND_API_BASE_URL`: Webless Backend API origin,正式環境為 `https://webless-aakwcbp2ca-de.a.run.app`。
- `WEBLESS_MCP_SECRET`: MCP service 與 Webless 共用的 service credential;它不代表商家身分,Webless 仍會重新驗證 Google actor、站點歸屬與 endpoint permission。
- Backend API request timeout 預設為 15 秒。Backend API 連線失敗、逾時或回傳錯誤時,該操作直接失敗,不會 fallback 到 SQL、storage 或其他舊路徑。
- 每個 request 帶 request ID;設定寫入另帶 idempotency key,由 Webless PostgreSQL 保存完成結果,避免 Cloud Run 多實例重複寫入。
- SlimWeb-MCP 部署不需要 Cloud SQL、PostgreSQL、GCS、VPC connector 或 storage driver 設定;這些基礎設施只屬於 Webless。

- 登入時不以 webless 主會員 `accounts` 授權 MCP。
- 登入時由 Webless API 依 Google `sub` 或 `google_email` 查 `site_admins`,只允許至少一個 Web admin 身份有 `backend_ai_assistant` 或 `system_admin` 權限的使用者進入 MCP。
- MCP session 使用 `MCP_SESSION_SECRET` 簽章
- session 可透過 HttpOnly cookie 或 `Authorization: Bearer <token>` 使用
- `slimweb_sites_list` 由 Webless API 列出該 Google 帳號可用 MCP 操作的網站
- 每個 site-scoped tool call 會透過 Webless API 重新驗證該 Google 帳號在指定 `site_code` 對應站台的 Web admin 權限
- ChatGPT / Claude remote MCP 使用同一套 OAuth 驗證流程。未授權 `tools/call` 會回 HTTP 401 與 `WWW-Authenticate: Bearer resource_metadata="..."`,讓 client 透過 discovery / dynamic client registration / authorization code + PKCE 取得 bearer token;使用者不需要手動複製 MCP token。

Cloud Run 入口是 public HTTPS,但 MCP tools 需要有效 MCP session。未登入呼叫 protected tools 會回 `AUTH_REQUIRED`。

ChatGPT developer mode 設定:

- MCP server URL: `https://slimweb-mcp-aakwcbp2ca-de.a.run.app/mcp`
- Authentication: `OAuth`
- 若 ChatGPT 顯示 OAuth discovery 失敗,先檢查以下 URL 是否回 200:

```text
https://slimweb-mcp-aakwcbp2ca-de.a.run.app/.well-known/oauth-protected-resource
https://slimweb-mcp-aakwcbp2ca-de.a.run.app/.well-known/oauth-authorization-server
```

如果 Google 登入頁顯示 origin/client 錯誤,需在 Google OAuth client 加入 Cloud Run URL:

```text
https://slimweb-mcp-aakwcbp2ca-de.a.run.app
```

## Docker 與 Cloud Run 部署

本專案使用 Dockerfile 部署,不依賴 Cloud Run source deploy 自動偵測 runtime。

本機啟動:

```bash
npm test
PORT=8080 npm start
```

建立 image:

```bash
docker build -t slimweb-mcp:local .
```

Cloud Run 設定:

- GCP project: `webless-489821`
- Region: `asia-east1`
- Cloud Run service: `slimweb-mcp`
- Artifact Registry repository: `cloud-run-source-deploy`

GitHub push 自動部署目前使用 GitHub Actions:

- Workflow: `.github/workflows/deploy.yml`
- Trigger: push to `main`
- Secret: `GCP_SA_KEY`
- Deploy target: Cloud Run `slimweb-mcp`

`cloudbuild.yaml` 仍保留為 Cloud Build 部署設定。若之後在 GCP Cloud Build 完成 GitHub repo mapping 與 webhook secret IAM 設定,可改用 Cloud Build Trigger。

Cloud Run 使用 `--allow-unauthenticated`,讓 AI Client 與使用者可開啟登入頁;實際 MCP tool 權限由 MCP session 與後續 tool guard 控制。

## 下一步

1. 等待 GitHub Actions 首次部署完成,確認 Cloud Run `slimweb-mcp` revision ready。
2. 定義 Google Login callback、session model、token refresh 策略。
3. 將 planned tools 逐步接進 MCP discovery。
4. 實作 `slimweb_auth_status`、`slimweb_sites_list`、`slimweb_site_select`。
5. 建立 SlimWeb Backend Adapter,連接現有 Webless / SlimWeb application service 或 API。
6. 補上 authentication、permission、validation、error mapping 的 tests。
7. 每新增一個 tool,同步更新本 README 的 tool matrix 與 tool contract。