Files
homaroma/apps/mcp-server
..
x
2026-10-11 06:43:08 +07:00
x
2026-10-11 06:43:08 +07:00
x
2026-06-07 07:33:41 +07:00
x
2026-10-11 06:43:08 +07:00
x
2026-10-11 06:43:08 +07:00
x
2026-06-07 07:33:41 +07:00
x
2026-07-25 01:41:21 -04:00
x
2026-07-25 01:41:21 -04:00
x
2026-07-23 04:41:35 -04:00
2026-06-17 21:08:24 -04:00
x
2026-10-11 06:43:08 +07:00
2026-06-17 21:08:24 -04:00
x
2026-10-11 06:43:08 +07:00
x
2026-10-16 06:26:13 +07:00
x
2026-06-07 07:33:41 +07:00
x
2026-06-07 07:33:41 +07:00
x
2026-10-11 06:43:08 +07:00
x
2026-10-11 06:43:08 +07:00
x
2026-10-11 06:43:08 +07:00
x
2026-10-11 06:43:08 +07:00
x
2026-10-11 06:43:08 +07:00
x
2026-06-28 20:18:07 -04:00
x
2026-07-24 04:04:32 -04:00
x
2026-10-11 06:43:08 +07:00
x
2026-10-11 06:43:08 +07:00
x
2026-06-07 07:33:41 +07:00

DBK Platform MCP Server

HomAroma is the reference tenant. This server exposes shared MCP capabilities; a tool call must use the active tenant's data and configuration.

MCP server สำหรับเชื่อม AI tools เข้ากับ backend ของ DBK Platform ผ่าน stdio transport โดยใช้ข้อมูลและการตั้งค่าของ tenant ที่กำลังเชื่อมต่อ

Run

bun install
bun run --cwd apps/mcp-server dev

หรือรันตรงจาก package:

cd apps/mcp-server
bun run dev

Environment

MCP process เดียวสลับ backend ลูกค้าหลายรายได้ด้วย allowlist ใน private JSON registry ตัวอย่างโครงสร้างอยู่ที่ target-profiles.example.json ให้คัดลอกไปยัง absolute path นอก Git แล้วกำหนด:

  • MCP_TARGET_PROFILES_FILE = absolute path ของ registry
  • MCP_DEFAULT_TARGET_PROFILE = profile ID ที่เริ่มใช้งานทุกครั้งหลัง restart
  • ตัวแปร username/password ที่แต่ละ profile ระบุใน usernameEnv และ passwordEnv ผ่าน secret store หรือ environment ของ MCP client

Registry เก็บเพียง id, displayName, kind (local/staging/production), baseUrl, และ ชื่อตัวแปร credential; ห้ามใส่รหัสผ่านจริงใน JSON หรือ Git แต่ละ profile ต้องใช้ชื่อตัวแปร credential แยกกัน ไม่รับ URL ซ้ำกัน และตรวจว่าทุก secret มีค่าก่อนเริ่ม server URL ระยะไกลต้องเป็น HTTPS; HTTP อนุญาตเฉพาะ loopback หาก config ผิด server จะไม่เริ่ม

ใน profile mode ใช้ list_target_profiles → select_target_profile ด้วย ID → get_target_environment เพื่อยืนยัน URL ก่อนเขียน ทุก backend-facing tool ต้องส่ง expectedProfileId ให้ตรงกับ active profile; หากแชตอื่นสลับเป้าหมายระหว่างนั้น คำขอจะถูกปฏิเสธก่อนแตะ backend คำขอ MCP ถูกประมวลผลแบบเรียงลำดับเพื่อไม่ให้การสลับ target ตัดกลางคำขอ; auth token เก็บแยกตาม profile การเรียก set_target_environment รวมทั้ง customUrl จะถูกปฏิเสธ และไม่ fallback ไป URL หรือ admin credential ชุด legacy การเปลี่ยน active profile มีผลเฉพาะ process ปัจจุบัน; restart กลับไป MCP_DEFAULT_TARGET_PROFILE

Registry เป็น allowlist ของปลายทาง ไม่ใช่ระบบ authorization แยกตามแชต/ผู้ใช้ ทุก client ที่เข้าถึง MCP process เดียวกันสามารถเลือกทุก profile ใน registry ได้ และ expectedProfileId ป้องกันการส่งคำขอไปผิดเป้าหมายโดยไม่ตั้งใจเท่านั้น หากลูกค้าอยู่คนละ trust group ให้ใช้ MCP process และ registry แยกกัน

upload_product_image_from_url ถูกซ่อนและปฏิเสธใน profile mode เพราะตัวดาวน์โหลดเดิมรับ URL ภายนอกโดยไม่มี outbound allowlist หรือ resource limits; legacy mode ยังคง behavior เดิม ระหว่างนี้ให้ใช้ workflow อัปโหลดที่ผ่านการตรวจความปลอดภัยจากระบบอื่น

Migration: ตั้ง registry และ secret environment ทุก profile ให้ครบก่อนเปิด MCP_TARGET_PROFILES_FILE แล้ว restart MCP client ตรวจ get_target_environment ว่า mode เป็น profiles และ ID/URL ถูกต้องก่อนใช้ tool เขียนข้อมูล อย่าคัดลอก URL หรือ credential ของลูกค้าจริงลงตัวอย่างใน repository

Legacy mode (no registry)

รองรับตัวแปรต่อไปนี้เพื่อความเข้ากันได้:

  • MCP_BACKEND_URL สำหรับกำหนด backend target ตรง ๆ
  • MCP_BACKEND_URL_LOCAL ค่าเริ่มต้นสำหรับ local
  • MCP_BACKEND_URL_PRODUCTION ค่าเริ่มต้นสำหรับ production
  • MCP_ADMIN_USERNAME
  • MCP_ADMIN_PASSWORD

ถ้าไม่ตั้งค่า MCP_BACKEND_URL server จะเริ่มที่ local backend และสลับเป็น production ได้ด้วย tool set_target_environment

ชื่อ homaroma ที่ยังอยู่ใน package, server identity, config key หรือ URL เป็น legacy runtime identifier เพื่อความเข้ากันได้ ไม่ใช่ชื่อแพลตฟอร์มหรือค่าแบรนด์สำหรับทุก tenant การเปลี่ยน identifier เหล่านี้ต้องทำเป็น migration แยกต่างหาก

ข้อควรระวังใน legacy mode: set_target_environment ยังใช้ admin credential ชุดเดียวกับทุก backend; production ยังมี HomAroma URL เป็น fallback หากไม่ได้กำหนด MCP_BACKEND_URL_PRODUCTION และ customUrl รับ URL อิสระ จึงไม่ควรใช้ legacy mode เพื่อสลับหลายลูกค้า

legacy mode ยังมีค่า admin สำรองในโค้ดตามการตัดสินใจชั่วคราวของเจ้าของโปรเจกต์ ควรกำหนด MCP_ADMIN_USERNAME และ MCP_ADMIN_PASSWORD ในสภาพแวดล้อมของ MCP client และย้ายออกจากค่าสำรองในรอบ migration ถัดไป อย่าใส่รหัสผ่านในแชตหรือ commit ลง repository ค่า fallback นี้ ไม่ถูกใช้ใน profile mode

Available tools

  • upload_cms_asset อัปโหลด JPEG/PNG/WebP/GIF จากไฟล์ในเครื่องเข้า Media Library ของ backend ปัจจุบัน แล้วคืน url และ path สำหรับ ARTICLE_MEDIA / ARTICLE_GALLERY โดยไม่ผูกกับสินค้า ต้องตั้ง MCP_ASSET_ROOT เป็น absolute directory ของไฟล์ที่อนุญาตก่อน restart; ส่ง filePath แบบ absolute ภายใน directory นั้น ขนาดไม่เกิน 10 MiB และใน profile mode ต้องส่ง expectedProfileId ด้วย Tool ตรวจ real path, ชนิดไฟล์จากนามสกุลและ magic bytes; ไม่รับ URL ภายนอก, SVG หรือ base64 การอัปโหลดสร้าง Media record แม้ยังไม่เพิ่มภาพลงหน้า CMS ให้ตรวจ target ด้วย get_target_environment ก่อนเสมอ
  • update_brand_name เปลี่ยนชื่อแบรนด์กลางที่ใช้ใน header/footer ของ apps/spa และ apps/website
  • update_store_settings_translation อัปเดตข้อความแปลของ store settings
  • update_footer_content อัปเดตคำอธิบายแบรนด์และ social links เท่านั้น
  • get_footer_brand / update_footer_brand อ่านและแก้ Footer Brand block โดยตรง (brand name, logo, คำอธิบายแยกภาษา, social links) พร้อม dryRun และ expectedVersion
  • get_footer_layout / patch_footer_layout อ่านและแก้โครง Footer พร้อม preview และการตรวจ version ก่อนเขียน
  • get_category_sections / seed_category_sections / add_category_section / update_category_section / reorder_category_sections / delete_category_section จัดการ section ของหน้า Category

Tool definitions มี annotation บอกการอ่านอย่างเดียวหรือการลบ และผลลัพธ์ JSON มี structuredContent เพิ่มจากข้อความเดิมเพื่อให้ LLM ใช้ง่ายขึ้น โดยยังเข้ากันได้กับ client ที่อ่าน content อยู่

ตัวอย่างจาก get_page_block_schema เป็นโครง payload สำหรับเริ่มต้น ไม่ใช่เนื้อหาที่ควรเผยแพร่ทันที ให้แทน URL ตัวอย่าง ข้อความ ผู้เขียน และช่องทางติดต่อด้วยข้อมูลที่ตรวจสอบแล้วของ tenant ปัจจุบันก่อนเขียนจริง โดยเฉพาะ CONTACT_INFO ที่มี email และ LINE ID เป็น placeholder

Safe editing workflow

  1. เรียก get_target_environment ก่อนแก้ข้อมูล โดยเฉพาะหลัง restart; ใน profile mode ยืนยันทั้ง profile ID และ URL อย่าเขียน production ถ้าผู้ใช้ไม่ได้ขอชัดเจน
  2. อ่านข้อมูลเป้าหมายก่อน แล้วเลือก tool ที่เฉพาะงาน
  3. ใช้ dryRun: true เมื่อมี, ตรวจผล preview แล้วค่อยเขียนจริง
  4. ส่ง expectedVersion สำหรับ Footer layout และงานอื่นที่รองรับ version
  5. อ่านข้อมูลซ้ำหลังเขียนเพื่อตรวจผล

Category section tools ทำ preview ฝั่ง MCP เท่านั้น เพราะ backend ปัจจุบันยังไม่มี dryRun หรือ version check แบบ atomic สำหรับ endpoint กลุ่มนี้ ข้อมูลอาจเปลี่ยนระหว่าง preview กับการเขียนจริง; ให้ตรวจรายการล่าสุดก่อนเขียนเสมอ

Footer Explore and Footer Support are flat item menus, not Mega Menu payload trees. Supported menu names are:

footer-explore
footer-support

Use this workflow for every Footer menu edit:

  1. Call get_footer_menu with the target language.
  2. Keep the returned version.
  3. Call one item-level write tool with dryRun: true and expectedVersion.
  4. Review the compact preview.
  5. Apply the same operation with dryRun: false and the same version.
  6. Call get_footer_menu again to verify and obtain the next version.

If an allowed Footer menu does not exist yet, get_footer_menu returns exists: false, version: null, and an empty item list. Previewing the first add returns willCreateMenu: true; applying that add creates the menu as active and inserts the first item atomically.

Available item-level tools:

  • add_footer_menu_item
  • update_footer_menu_item
  • delete_footer_menu_item
  • reorder_footer_menu_items
  • update_footer_menu_item_translation

Every reorder request must include every current item ID exactly once. A MENU_VERSION_CONFLICT response means Admin or another agent changed the menu after it was read; fetch it again before retrying.

Do not pass exploreLinks, collectionLinks, or supportLinks to legacy update_footer_content. Full menu-array replacement is rejected because it can delete item IDs and translations. Website Collections are populated from Categories rather than a footer-collections menu.

Mega Menu LLM Workflow

Header Mega Menu uses the main menu payload tree. The website renders this structure:

Root -> Column -> Link -> Child Link

Supported localized text keys are:

th, en, ja, zh, vi, ko, lo, it

LLM agents should use this workflow for every menu edit:

  1. capture_menu_snapshot for main
  2. get_mega_menu_tree
  3. validate_mega_menu_tree
  4. Plan operations from diagnostics and current nodeId values
  5. bulk_menu_operations with dryRun: true
  6. Review preview.diff, preview.before, preview.after, issues, and warnings
  7. Apply only after approval
  8. Run validate_mega_menu_tree again
  9. Use restore_menu_snapshot if the applied result is wrong

Do not add a Link directly under root. Add a Column under Root first, then add Links under that Column.

Dry-run responses are expected to include path-based diffs such as:

{
  "path": "payload[0].columns[0].links[0].label.it",
  "before": null,
  "after": "Candele"
}

validate_mega_menu_tree reports:

  • missing locale keys, especially lo and it
  • unsupported translation keys
  • duplicate or missing nodeId
  • invalid URL shape
  • placeholder text
  • empty columns
  • featured card issues
  • desktop render limits such as hidden columns or links

Category Management LLM Workflow

Product categories are managed by backend /categories APIs through MCP. Supported localized text keys are:

th, en, ja, zh, vi, ko, lo, it

LLM agents should use this workflow for category edits:

  1. list_categories with lang: "all" to discover category IDs and current translations
  2. create_category, update_category, update_category_media, update_category_translations, or delete_category with dryRun: true
  3. Review the preview and product counts
  4. Apply only after the intended change is clear
  5. Run list_categories again to verify

Category media uses semantic roles: thumbnail, hero_desktop, hero_mobile, card_portrait, and social_share. update_category_media replaces the complete media set, so omitted roles are removed. update_category_image remains available only as a legacy thumbnail compatibility tool.

Backend category support currently covers:

  • base name
  • imageUrl
  • localized names
  • product-count guarded soft delete (deletedAt)

Backend category support does not currently cover:

  • slug
  • nested parent/child hierarchy
  • sort order
  • active/inactive state
  • restore/undelete workflow

Scripts

  • bun run dev
  • bun run start
  • bun run check