import { Client } from "@modelcontextprotocol/sdk/client/index.js"; import { StdioClientTransport } from "@modelcontextprotocol/sdk/client/stdio.js"; import { join } from "node:path"; async function main() { console.log("Connecting to MCP server..."); const transport = new StdioClientTransport({ command: process.execPath, args: [join(import.meta.dir, "index.ts")], cwd: import.meta.dir, env: { ...process.env, MCP_BACKEND_URL: "http://localhost:3051/api", }, stderr: "pipe", }); const client = new Client({ name: "bom-test-client", version: "1.0.0" }); await client.connect(transport); console.log("Connected to MCP server!"); // 1. List tools and verify BOM tools are registered const tools = (await client.listTools()).tools; console.log(`Total MCP tools registered: ${tools.length}`); const bomTools = ["list_products_bom_status", "get_product_bom", "set_product_bom"]; for (const name of bomTools) { const found = tools.find((t) => t.name === name); if (!found) { throw new Error(`Tool ${name} not found!`); } console.log(`✓ Found tool: ${name}`); } // 2. Call list_products_bom_status console.log("\nCalling list_products_bom_status for search='ซากุระ'..."); const statusRes = await client.callTool({ name: "list_products_bom_status", arguments: { search: "ซากุระ", limit: 5 }, }); console.log("Status result:", (statusRes.content as any)[0].text.slice(0, 300) + "..."); // 3. Call get_product_bom for Product #250 console.log("\nCalling get_product_bom for productId=250..."); const getBomRes = await client.callTool({ name: "get_product_bom", arguments: { productId: 250 }, }); const bomData = JSON.parse((getBomRes.content as any)[0].text); console.log(`Product Name: ${bomData.productName}`); console.log(`Variants count: ${bomData.variants.length}`); console.log(`Available Raw Materials count: ${bomData.availableRawMaterials.length}`); // 4. Call set_product_bom for Product #250 console.log("\nCalling set_product_bom for Product #250 with 4 variants..."); const setBomRes = await client.callTool({ name: "set_product_bom", arguments: { productId: 250, variants: [ { variantId: 3206, sku: "4-1-30ML", bomItems: [ { rawMaterialId: 4, name: "หัวน้ำหอม กลิ่นซากุระ", quantity: 2.4 }, { rawMaterialId: 91, name: "DPG", quantity: 27.6 }, { rawMaterialId: 92, name: "ขวดพร้อมฝา Oilozone 30ml", quantity: 1 }, ], }, { variantId: 3207, sku: "4-1-60ML", bomItems: [ { rawMaterialId: 4, name: "หัวน้ำหอม กลิ่นซากุระ", quantity: 4.8 }, { rawMaterialId: 91, name: "DPG", quantity: 55.2 }, { rawMaterialId: 93, name: "ขวดพร้อมฝา Oilozone 60ml", quantity: 1 }, ], }, { variantId: 3208, sku: "4-1-85ML", bomItems: [ { rawMaterialId: 4, name: "หัวน้ำหอม กลิ่นซากุระ", quantity: 6.8 }, { rawMaterialId: 91, name: "DPG", quantity: 78.2 }, { rawMaterialId: 94, name: "ขวดพร้อมฝา Oilozone 85ml", quantity: 1 }, ], }, { variantId: 3209, sku: "4-1-120ML", bomItems: [ { rawMaterialId: 4, name: "หัวน้ำหอม กลิ่นซากุระ", quantity: 9.6 }, { rawMaterialId: 91, name: "DPG", quantity: 110.4 }, { rawMaterialId: 95, name: "ขวดพร้อมฝา Oilozone 120ml", quantity: 1 }, ], }, ], }, }); const setResult = JSON.parse((setBomRes.content as any)[0].text); console.log("\nSet BOM result:"); console.log(`Success: ${setResult.success}`); console.log(`Message: ${setResult.message}`); for (const v of setResult.variants) { console.log(` - Variant: ${v.option} (SKU: ${v.sku}) | Retail: ฿${v.retailPrice} | BOM Cost: ฿${v.totalBomCost} | Margin: ${v.marginPercent}%`); } await client.close(); console.log("\nAll BOM MCP tests passed successfully!"); } main().catch((err) => { console.error("Test failed:", err); process.exit(1); });