nexusflex-mcp 3.70.0 → 3.71.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/api.mjs +13 -2
- package/docs.mjs +1 -1
- package/package.json +1 -1
- package/server.mjs +5 -4
package/api.mjs
CHANGED
|
@@ -47,8 +47,19 @@ if (EMAIL && PASSWORD && !/^https:\/\//i.test(API_URL)) {
|
|
|
47
47
|
log("ADVERTENCIA: NEXUSFLEX_API_URL no es HTTPS y hay email/contraseña — viajarían sin cifrar.");
|
|
48
48
|
}
|
|
49
49
|
|
|
50
|
-
|
|
50
|
+
// Operaciones habilitadas dentro de rutas financieras (decisión del dueño, 29/09), con su
|
|
51
|
+
// MÉTODO exacto — mismas que RUTAS_MCP_OPERACION_OK en backend/src/middleware/auth.ts.
|
|
52
|
+
// Ninguna paga, cobra ni transfiere: excluir/reincluir un envío de una liquidación (con
|
|
53
|
+
// motivo) y ver/preparar los datos de facturación de un cliente (no emite comprobantes).
|
|
54
|
+
const OPERACIONES_OK = [
|
|
55
|
+
{ metodo: "POST", ruta: /^\/liquidaciones\/anteriores\/\d+\/(excluir|reincluir)\/?$/i },
|
|
56
|
+
{ metodo: "GET", ruta: /^\/afip\/estado\/?$/i },
|
|
57
|
+
{ metodo: "POST", ruta: /^\/afip\/preparar-cliente\/?$/i },
|
|
58
|
+
];
|
|
59
|
+
|
|
60
|
+
function guard(method, path) {
|
|
51
61
|
const clean = path.split("?")[0];
|
|
62
|
+
if (OPERACIONES_OK.some((o) => o.metodo === String(method).toUpperCase() && o.ruta.test(clean))) return;
|
|
52
63
|
if (RUTAS_PROHIBIDAS.some((re) => re.test(clean))) {
|
|
53
64
|
throw new Error(`Ruta bloqueada por política del MCP (endpoints de dinero deshabilitados): ${clean}`);
|
|
54
65
|
}
|
|
@@ -96,7 +107,7 @@ async function ensureToken() {
|
|
|
96
107
|
|
|
97
108
|
/** Llamada autenticada a la API. Reintenta UNA vez si el token venció/se revocó. */
|
|
98
109
|
export async function api(method, path, body) {
|
|
99
|
-
guard(path);
|
|
110
|
+
guard(method, path);
|
|
100
111
|
let token = await ensureToken();
|
|
101
112
|
const doFetch = (t) =>
|
|
102
113
|
fetch(`${API_URL}${path}`, {
|
package/docs.mjs
CHANGED
|
@@ -158,7 +158,7 @@ const GROUPS = [
|
|
|
158
158
|
{ titulo: "WMS del nodo", tools: ["stock_nodo", "productos_nodo", "producto_crear"] },
|
|
159
159
|
{ titulo: "Gesti\xF3n del nodo", tools: ["clientes_del_nodo", "cliente_crear", "cliente_editar", "sucursales_cliente", "sucursal_perfil", "precios_ver", "precio_actualizar", "cuentas_vinculadas", "generar_enlace_vinculacion", "facturacion_estado", "facturacion_preparar_cliente"] },
|
|
160
160
|
{ titulo: "Marketing / atribuci\xF3n", tools: ["marketing_config_ver", "marketing_config_guardar"] },
|
|
161
|
-
{ titulo: "Liquidaciones
|
|
161
|
+
{ titulo: "Liquidaciones", tools: ["liquidacion_buscar", "liquidacion_detalle", "liquidaciones_sin_recibir", "liquidacion_excluir_envio", "liquidacion_reincluir_envio", "cuenta_semanal_nodos"] },
|
|
162
162
|
{ titulo: "Usuarios / choferes", tools: ["chofer_listar", "chofer_crear", "chofer_editar", "usuario_editar", "operador_crear", "cliente_generar_usuario", "cliente_resetear_clave", "usuario_habilitar_reparto"] },
|
|
163
163
|
{ titulo: "Administraci\xF3n (red)", tools: ["nodos_listar", "nodo_crear", "usuario_habilitar_rol", "grupo_crear", "logo_subir", "sugerencias_listar", "cierre_semanal_links", "nodo_renombrar", "grupo_miembros", "grupo_sumar_nodo", "grupo_expulsar_nodo", "grupo_admin_permiso"] }
|
|
164
164
|
];
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "nexusflex-mcp",
|
|
3
|
-
"version": "3.
|
|
3
|
+
"version": "3.71.0",
|
|
4
4
|
"description": "MCP de Nexus Flex: operá tu nodo/cuenta desde un asistente de IA (altas de clientes, stock, KPIs). Login por autorización web (device-flow). NO toca dinero.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"license": "MIT",
|
package/server.mjs
CHANGED
|
@@ -56,8 +56,9 @@ const ALLOW_PRECIOS = truthy(process.env.NEXUSFLEX_MCP_ALLOW_PRECIOS);
|
|
|
56
56
|
|
|
57
57
|
// ATADO CON: backend/src/services/mcp-remote.ts (MCP_VERSION + NOVEDADES + mismos tools, salvo SOLO_REMOTO)
|
|
58
58
|
// y mcp/package.json. Lo verifica backend/src/coherencia.test.ts. Ver CLAUDE.md → "Cosas que van juntas".
|
|
59
|
-
const MCP_VERSION = "3.
|
|
59
|
+
const MCP_VERSION = "3.71.0"; // bumpear junto con package.json + backend/services/mcp-remote.ts
|
|
60
60
|
const NOVEDADES = [
|
|
61
|
+
"3.71.0 — Habilitadas por el dueño: `liquidacion_excluir_envio` / `liquidacion_reincluir_envio` (sacar o devolver UN envío del cobro de una liquidación emitida, con motivo obligatorio) y `facturacion_estado` / `facturacion_preparar_cliente` (qué falta para facturar y cargar los datos fiscales de un cliente) ya funcionan por MCP: el filtro de dinero las deja pasar con su método exacto. Siguen sin pagar, cobrar ni emitir comprobantes, y piden permiso finanzas. Además `mis_envios` ahora sí filtra por `estado`.",
|
|
61
62
|
"3.70.0 — Descripciones al día: textos de las herramientas corregidos para que digan lo que hacen hoy (`envio_entregar`, `envio_asignar_mensajero`, `generar_enlace_vinculacion` vence en 48 hs, `grupo_miembros` y `provisorio_conciliar` apuntan a `grupos_tarifas`), `flujo` lista todos los flujos disponibles, `sugerencias_listar` solo para el superadmin, `envio_cargar` exige `telefono`, parámetros con formato (fechas YYYY-MM-DD, montos en ARS, nombre o id) y las instrucciones del conector más cortas (la guía sigue en `guia`). `liquidacion_excluir_envio`/`reincluir` avisan que hoy el filtro de dinero los bloquea por MCP (se hace desde la PWA).",
|
|
62
63
|
"3.69.1 — AYUDA completa: `ayuda` ahora tiene la ficha (qué hace, cómo usarlo, ejemplo, qué NO hace) de los 20 tools que no la tenían (cierre semanal, zonas de grupo, tarifas de grupo, sin vendedor, corregir estado, pago al cadete, retiros…) y los 26 que no aparecían en el índice. La ayuda del paquete npm se genera desde la del conector, así que ya no se desincronizan. No mueve dinero.",
|
|
63
64
|
"3.69.0 — Control por foto de la TANDA DE UN CADETE (propios + de otros nodos mezclados): en `envio_desde_etiqueta_ml` alcanza con el `mlQr` crudo — de ahí sale el número de ML y el vendedor, y el vendedor se reconoce igual que en el escáner (cuenta vinculada O cuenta aprendida en juntadas/escaneos; antes solo la vinculada). `nodoEntrega` ya no necesita `grupo`: si el cliente es del mismo nodo que entrega es un paquete propio (sin traspaso) y si es de otro nodo se usa el grupo que comparten. Si no conoce al vendedor, contesta 404 con el senderId para que preguntes de qué nodo/cliente es. Si el envío ya existía, no lo duplica: lo completa y lo avanza. No mueve dinero.",
|
|
@@ -254,7 +255,7 @@ if (isCliente) {
|
|
|
254
255
|
tool("mis_envios", {
|
|
255
256
|
title: "Mis envíos",
|
|
256
257
|
description: "Tus envíos/paquetes (solo los tuyos), los 300 más recientes, cada uno con su `estado`. No incluye datos de otros clientes ni del nodo.",
|
|
257
|
-
inputSchema: { estado: z.string().optional().describe("Estado: 'A retirar', 'Colectado', 'En centro de distribución', 'En camino', 'Entregado' (o una novedad, ej. 'Comprador ausente').
|
|
258
|
+
inputSchema: { estado: z.string().optional().describe("Estado: 'A retirar', 'Colectado', 'En centro de distribución', 'En camino', 'Entregado' (o una novedad, ej. 'Comprador ausente'). Filtra por los que EMPIEZAN con ese texto ('Entregado' incluye 'Entregado (Flex)'); los 300 más recientes de ese estado.") },
|
|
258
259
|
}, async ({ estado }) => run(() => api("GET", `/portal/envios${q({ estado })}`)));
|
|
259
260
|
|
|
260
261
|
tool("mis_kpis", {
|
|
@@ -1192,7 +1193,7 @@ if (ALLOW_WRITE) {
|
|
|
1192
1193
|
tool("liquidacion_excluir_envio", {
|
|
1193
1194
|
title: "No cobrar un envío de una liquidación",
|
|
1194
1195
|
description:
|
|
1195
|
-
"Saca UN envío (por tracking) del cobro de una liquidación YA emitida y re-suma el total, ajustando el cargo en la cuenta corriente del cliente. El `motivo` es OBLIGATORIO: queda en el historial del envío y el vendedor lo ve en su portal. Si esa liquidación ya está en una factura de ARCA emitida, lo rechaza (haría falta una nota de crédito, que el sistema no emite). Scopeada a tu nodo.
|
|
1196
|
+
"Saca UN envío (por tracking) del cobro de una liquidación YA emitida y re-suma el total, ajustando el cargo en la cuenta corriente del cliente. El `motivo` es OBLIGATORIO: queda en el historial del envío y el vendedor lo ve en su portal. Si esa liquidación ya está en una factura de ARCA emitida, lo rechaza (haría falta una nota de crédito, que el sistema no emite). Scopeada a tu nodo.",
|
|
1196
1197
|
inputSchema: {
|
|
1197
1198
|
id: z.number().int().positive().describe("id de la liquidación"),
|
|
1198
1199
|
tracking: z.string().min(1),
|
|
@@ -1202,7 +1203,7 @@ if (ALLOW_WRITE) {
|
|
|
1202
1203
|
tool("liquidacion_reincluir_envio", {
|
|
1203
1204
|
title: "Volver a cobrar un envío de una liquidación",
|
|
1204
1205
|
description:
|
|
1205
|
-
"Lo inverso de `liquidacion_excluir_envio`: devuelve al cobro un envío que se había excluido, re-suma y ajusta la cuenta corriente. El `motivo` es OBLIGATORIO. Mismo guard de factura emitida.
|
|
1206
|
+
"Lo inverso de `liquidacion_excluir_envio`: devuelve al cobro un envío que se había excluido, re-suma y ajusta la cuenta corriente. El `motivo` es OBLIGATORIO. Mismo guard de factura emitida.",
|
|
1206
1207
|
inputSchema: {
|
|
1207
1208
|
id: z.number().int().positive().describe("id de la liquidación"),
|
|
1208
1209
|
tracking: z.string().min(1),
|