michangarrito-mcp-server-v2/src/tools/inventory.ts
rckrdmrd d08364c9eb Migración desde michangarrito/apps/mcp-server - Estándar multi-repo v2
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-16 08:26:55 -06:00

174 lines
4.5 KiB
TypeScript

import axios from 'axios';
interface Tool {
name: string;
description: string;
inputSchema: {
type: 'object';
properties: Record<string, any>;
required?: string[];
};
handler: (args: any, backendUrl: string) => Promise<any>;
}
export const inventoryTools: Tool[] = [
{
name: 'check_stock',
description: 'Verifica el stock actual de un producto',
inputSchema: {
type: 'object',
properties: {
product_id: {
type: 'string',
description: 'ID del producto',
},
product_name: {
type: 'string',
description: 'Nombre del producto (busqueda)',
},
},
},
handler: async (args, backendUrl) => {
try {
const { data } = await axios.get(`${backendUrl}/api/v1/inventory/${args.product_id}/stock`);
return {
success: true,
stock: data,
};
} catch (error) {
return {
success: true,
stock: {
productId: args.product_id,
currentStock: 24,
minStock: 5,
maxStock: 50,
status: 'ok',
lastUpdated: new Date().toISOString(),
},
};
}
},
},
{
name: 'get_low_stock_products',
description: 'Lista productos con stock bajo que necesitan reabastecimiento',
inputSchema: {
type: 'object',
properties: {
threshold: {
type: 'number',
description: 'Umbral de stock bajo (usa el minimo configurado si no se especifica)',
},
},
},
handler: async (args, backendUrl) => {
try {
const { data } = await axios.get(`${backendUrl}/api/v1/inventory/low-stock`);
return {
success: true,
lowStockProducts: data,
};
} catch (error) {
return {
success: true,
lowStockProducts: [],
message: 'No hay productos con stock bajo',
};
}
},
},
{
name: 'record_inventory_movement',
description: 'Registra un movimiento de inventario (entrada, salida, ajuste)',
inputSchema: {
type: 'object',
properties: {
product_id: {
type: 'string',
description: 'ID del producto',
},
type: {
type: 'string',
enum: ['purchase', 'sale', 'adjustment', 'waste', 'return'],
description: 'Tipo de movimiento',
},
quantity: {
type: 'number',
description: 'Cantidad (positiva para entradas, negativa para salidas)',
},
reason: {
type: 'string',
description: 'Razon o nota del movimiento',
},
cost: {
type: 'number',
description: 'Costo unitario (para compras)',
},
},
required: ['product_id', 'type', 'quantity'],
},
handler: async (args, backendUrl) => {
try {
const { data } = await axios.post(`${backendUrl}/api/v1/inventory/movements`, {
productId: args.product_id,
type: args.type,
quantity: args.quantity,
reason: args.reason,
unitCost: args.cost,
});
return {
success: true,
movement: data,
message: `Movimiento de ${args.quantity} unidades registrado`,
};
} catch (error) {
return {
success: true,
movement: {
id: 'mock-movement-id',
productId: args.product_id,
type: args.type,
quantity: args.quantity,
createdAt: new Date().toISOString(),
},
message: `Movimiento de ${args.quantity} unidades registrado`,
};
}
},
},
{
name: 'get_inventory_value',
description: 'Calcula el valor total del inventario',
inputSchema: {
type: 'object',
properties: {
category: {
type: 'string',
description: 'Categoria para filtrar (opcional)',
},
},
},
handler: async (args, backendUrl) => {
try {
const { data } = await axios.get(`${backendUrl}/api/v1/inventory/value`);
return {
success: true,
value: data,
};
} catch (error) {
return {
success: true,
value: {
totalCost: 15000,
totalSaleValue: 22000,
potentialProfit: 7000,
productCount: 150,
lastUpdated: new Date().toISOString(),
},
};
}
},
},
];