JEISA-WEBAPP/scripts/mcp-create-po.mjs

155 lines
4.5 KiB
JavaScript
Raw Normal View History

#!/usr/bin/env node
/**
* Create a purchase order through the JEISA PocketBase MCP server.
*
* node scripts/mcp-create-po.mjs
*
* Drives `server/pb-mcp.mjs` over stdio and calls, in order:
* 1. generate_order_number → allocate a fresh PO-YYYYMMDD-NNN
* 2. list_suppliers → pick the first supplier
* 3. list_stock_items → pick the first stock item
* 4. create_purchase_order → submit the draft
* 5. get_purchase_order → read it back to confirm
*/
import { spawn } from "node:child_process";
import { fileURLToPath } from "node:url";
import path from "node:path";
const __dirname = path.dirname(fileURLToPath(import.meta.url));
const ROOT = path.resolve(__dirname, "..");
const child = spawn("node", ["--import", "tsx/esm", "server/pb-mcp.mjs"], {
cwd: ROOT,
stdio: ["pipe", "pipe", "inherit"],
});
let buffer = "";
const pending = new Map();
let nextId = 1;
function send(method, params = {}) {
return new Promise((resolve, reject) => {
const id = nextId++;
pending.set(id, { resolve, reject });
const msg = JSON.stringify({ jsonrpc: "2.0", id, method, params });
child.stdin.write(msg + "\n");
});
}
child.stdout.on("data", (chunk) => {
buffer += chunk.toString("utf8");
let nl;
while ((nl = buffer.indexOf("\n")) !== -1) {
const line = buffer.slice(0, nl).trim();
buffer = buffer.slice(nl + 1);
if (!line) continue;
let parsed;
try {
parsed = JSON.parse(line);
} catch {
console.error("[po] non-JSON line:", line);
continue;
}
if (parsed.id != null && pending.has(parsed.id)) {
const { resolve, reject } = pending.get(parsed.id);
pending.delete(parsed.id);
if (parsed.error) reject(new Error(JSON.stringify(parsed.error)));
else resolve(parsed.result);
}
}
});
const shutdown = () => {
child.kill();
process.exit(0);
};
process.on("SIGINT", shutdown);
process.on("SIGTERM", shutdown);
function firstJsonText(result) {
return JSON.parse(result.content[0].text);
}
try {
console.log("[po] initialize");
const init = await send("initialize", {
protocolVersion: "2024-11-05",
capabilities: {},
clientInfo: { name: "mcp-create-po", version: "0.0.0" },
});
console.log("[po] server:", init.serverInfo);
// 1. Allocate a PO number
console.log("\n[po] generate_order_number");
const gen = await send("tools/call", { name: "generate_order_number", arguments: {} });
const { order_number } = firstJsonText(gen);
console.log("[po] order_number:", order_number);
// 2. Pick a supplier
console.log("\n[po] list_suppliers (perPage=5)");
const sup = await send("tools/call", {
name: "list_suppliers",
arguments: { perPage: 5 },
});
const suppliers = firstJsonText(sup);
if (!suppliers.items?.length) throw new Error("No suppliers in PB");
const supplier = suppliers.items[0];
console.log("[po] supplier:", supplier.id, supplier.supplier_name);
// 3. Pick a stock item
console.log("\n[po] list_stock_items (limit=5)");
const stk = await send("tools/call", {
name: "list_stock_items",
arguments: { limit: 5 },
});
const stock = firstJsonText(stk);
if (!stock.items?.length) throw new Error("No stock items in PB");
const item = stock.items[0];
console.log("[po] stock_item:", item.id, item.name, "sku:", item.sku);
// 4. Build + send the draft
const draft = {
order_number,
supplierName: supplier.id,
orderDate: new Date().toISOString(),
carriage_charge: 0,
status: "Pending",
items: [
{
stockItemId: item.id,
itemName: item.name,
sku: item.sku,
quantity: 1,
costPrice: Number(item.cost_price ?? 0),
costPriceGBP: Number(item.cost_price_gbp ?? item.cost_price ?? 0),
entryMode: "stock",
},
],
};
console.log("\n[po] create_purchase_order");
console.log(JSON.stringify(draft, null, 2));
const created = await send("tools/call", {
name: "create_purchase_order",
arguments: { draft },
});
console.log("\n[po] create result:");
console.log(JSON.stringify(created, null, 2));
// 5. Read it back
const createdJson = firstJsonText(created);
if (createdJson?.id) {
console.log("\n[po] get_purchase_order (read-back)");
const readBack = await send("tools/call", {
name: "get_purchase_order",
arguments: { id: createdJson.id },
});
console.log(JSON.stringify(readBack, null, 2));
}
} catch (err) {
console.error("[po] FAILED:", err?.message || err);
process.exitCode = 1;
} finally {
child.kill();
}