Skip to main content
Glama
sales.ts5.18 kB
import type { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js'; import { z, ZodTypeAny } from 'zod'; import { postForm, postJsonRaw } from '../support/http.js'; import { t } from '../i18n/index.js'; import { resolveAuth, type Ctx } from '../context.js'; // util type InferFromShape<S extends Record<string, ZodTypeAny>> = z.infer<z.ZodObject<S>>; /** Item de vente : soit du catalogue, soit une ligne libre */ const SalesItemShape = { type: z.enum(['catalog', 'dept', 'free']).default('catalog'), // catalog productId: z.string().optional(), quantity: z.union([z.number(), z.string()]).optional(), titleOverride: z.string().optional(), priceOverride: z.union([z.number(), z.string()]).optional(), declinaisons: z.array(z.string()).optional(), // free (ligne manuelle) departmentId: z.union([z.string(), z.number()]).optional(), price: z.union([z.number(), z.string()]).optional(), title: z.string().optional(), } satisfies Record<string, ZodTypeAny>; const ClientShape = { firstname: z.string().optional(), lastname: z.string().optional(), email: z.string().email().optional(), phone: z.string().optional(), address: z.string().optional(), zip: z.string().optional(), city: z.string().optional(), country: z.string().optional(), } satisfies Record<string, ZodTypeAny>; /** ⚠️ ZodRawShape (pas z.object) — conforme à ton SDK MCP */ const SalesCreateShape = { payment: z.union([z.number(), z.string()]).transform((v) => Number(v)).optional(), deliveryMethod: z.union([ z.number().int().min(0).max(6), z.enum(['0','1','2','3','4','5','6']) ]).transform((v) => Number(v)).optional(), idtable: z.union([z.number().int(), z.string()]).optional(), idcaisse: z.union([z.number().int(), z.string()]).optional(), numcouverts: z.union([z.number().int(), z.string()]).optional(), publicComment: z.string().optional(), privateComment: z.string().optional(), pagerNum: z.union([z.number().int(), z.string()]).optional(), idUser: z.union([z.number().int(), z.string()]).optional(), idClient: z.union([z.number().int(), z.string()]).optional(), client: z.object(ClientShape).partial().optional(), items: z.array(z.object(SalesItemShape)).min(1), } satisfies Record<string, ZodTypeAny>; type SalesCreateArgs = InferFromShape<typeof SalesCreateShape>; /** Encode le tableau items en format legacy itemsList[] */ function encodeItemsList(items: SalesCreateArgs['items']): string[] { const out: string[] = []; for (const it of items) { if (it.type === 'catalog') { const parts = [ it.productId ?? '', it.quantity ?? 1, it.titleOverride ?? '', it.priceOverride ?? '', ]; if (it.declinaisons?.length) parts.push(...it.declinaisons); out.push(parts.join('_')); } else if (it.type === 'free') { const parts = [ 'Free', it.priceOverride ?? '', it.titleOverride ?? '', ]; out.push(parts.join('_')); } else { // ligne libre : -<departmentId>_<price>_<title> out.push(`-${it.departmentId ?? ''}_${it.price ?? ''}_${it.title ?? ''}`); } } return out; } export function registerSalesTools(server: McpServer | any) { // -- SALES CREATE -- server.registerTool( 'sale_create', { title: t('tools.sale_create.title'), description: t('tools.sale_create.description'), inputSchema: SalesCreateShape, // ✅ ZodRawShape }, async (input: SalesCreateArgs, ctx: Ctx) => { const { shopId, apiKey } = resolveAuth(undefined, ctx); // ---------- Mode legacy ---------- const body: Record<string, unknown> = { idboutique: shopId, key: apiKey }; if (input.payment !== undefined) body.payment = input.payment; if (input.deliveryMethod !== undefined) body.deliveryMethod = String(input.deliveryMethod); if (input.idUser !== undefined) body.idUser = input.idUser; if (input.idtable !== undefined) body.idtable = input.idtable; if (input.idcaisse !== undefined) body.idcaisse = input.idcaisse; if (input.numcouverts !== undefined) body.numcouverts = input.numcouverts; if (input.publicComment !== undefined) body.publicComment = input.publicComment; if (input.privateComment !== undefined) body.privateComment = input.privateComment; if (input.pagerNum !== undefined) body.pagerNum = input.pagerNum; if (input.idClient !== undefined) body.idClient = input.idClient; if (!input.idClient && input.client) { // Le legacy aime les clés client[...] for (const [k, v] of Object.entries(input.client)) { if (v !== undefined && v !== null && v !== '') { body[`client[${k}]`] = String(v); } } } body['itemsList[]'] = encodeItemsList(input.items); const data = await postForm('/workers/webapp.php', body); return { content: [{ type: 'text', text: JSON.stringify(data, null, 2) }], structuredContent: data, }; } ); }

Latest Blog Posts

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/paracetamol951/caisse-enregistreuse-mcp-server'

If you have feedback or need assistance with the MCP directory API, please join our Discord server