nexusflex-mcp 3.77.0 → 3.78.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/.claude-plugin/plugin.json +1 -1
- package/docs.mjs +2 -2
- package/package.json +1 -1
- package/server.mjs +8 -1
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "nexusflex",
|
|
3
3
|
"description": "Nexus Flex en Claude: el MCP (altas, consultas, control por foto; nunca mueve dinero) y las skills (control por foto, alta inicial del nodo) en un solo instalable.",
|
|
4
|
-
"version": "3.
|
|
4
|
+
"version": "3.78.0",
|
|
5
5
|
"author": {
|
|
6
6
|
"name": "Nexus Flex",
|
|
7
7
|
"url": "https://nexusflex.com.ar"
|
package/docs.mjs
CHANGED
|
@@ -268,8 +268,8 @@ const TOOL_DOCS = {
|
|
|
268
268
|
productos_nodo: { que: "Cat\xE1logo del dep\xF3sito del nodo (WMS).", uso: "cliente opcional.", ej: "productos_nodo.", no: "Requiere WMS activo." },
|
|
269
269
|
producto_crear: { que: "Alta de producto en el dep\xF3sito (WMS).", uso: "nombre + sku/codigoBarra/peso/volumen opcionales; staff pasa idCliente due\xF1o. Admin global: `nodo` para elegir/acotar el nodo.", ej: "producto_crear nombre:'Remera M' sku:'REM-M' idCliente:'130'.", no: "No mueve dinero; requiere WMS activo." },
|
|
270
270
|
clientes_del_nodo: { que: "Clientes/vendedores del nodo con su lista de precio.", uso: "Sin par\xE1metros. Scopeado a tu nodo.", ej: "clientes_del_nodo \u2192 ver a qui\xE9n factur\xE1s y con qu\xE9 lista.", no: "No los crea/edita (cliente_crear/editar)." },
|
|
271
|
-
cliente_crear: { que: "Alta de cliente/vendedor en tu nodo.", uso: "nombre obligatorio; telefono/dni/direccion/idLista opcionales. Admin global: `nodo` para elegir/acotar el nodo.", ej: "cliente_crear nombre:'Nueva Distri' idLista:'ID12'.", no: "No toca dinero; no cruza nodos." },
|
|
272
|
-
cliente_editar: { que: "Edita un cliente de tu nodo cambiando SOLO los campos que pas\xE1s (lista de precio, tel\xE9fono, email con el que entra, DNI, direcci\xF3n, nombre de pago, activo).", uso: 'id + los campos a cambiar. Lo que no pas\xE1s queda igual; "" vac\xEDa el campo. `email` = el del usuario del cliente (requiere permiso de usuarios). Admin global: `nodo` mueve el cliente a ese nodo.', ej: "cliente_editar id:130 idLista:'ID12' \xB7 cliente_editar id:50 email:'nuevo@mail.com'.", no: "No toca dinero ni la clave (cliente_resetear_clave)." },
|
|
271
|
+
cliente_crear: { que: "Alta de cliente/vendedor en tu nodo.", uso: "nombre obligatorio; telefono/dni/direccion/idLista/horarioCorte (HH:MM, corte de la colecta) opcionales. Admin global: `nodo` para elegir/acotar el nodo.", ej: "cliente_crear nombre:'Nueva Distri' idLista:'ID12'.", no: "No toca dinero; no cruza nodos." },
|
|
272
|
+
cliente_editar: { que: "Edita un cliente de tu nodo cambiando SOLO los campos que pas\xE1s (lista de precio, tel\xE9fono, email con el que entra, DNI, direcci\xF3n, nombre de pago, horario de corte, activo).", uso: 'id + los campos a cambiar. Lo que no pas\xE1s queda igual; "" vac\xEDa el campo. `email` = el del usuario del cliente (requiere permiso de usuarios). `horarioCorte` = HH:MM (corte de la colecta). Admin global: `nodo` mueve el cliente a ese nodo.', ej: "cliente_editar id:130 idLista:'ID12' \xB7 cliente_editar id:50 email:'nuevo@mail.com' \xB7 cliente_editar id:50 horarioCorte:'13:00'.", no: "No toca dinero ni la clave (cliente_resetear_clave)." },
|
|
273
273
|
sucursales_cliente: { que: "Lista las sucursales (puntos de retiro) de un cliente de tu nodo con su id, nombre, direcci\xF3n y perfil de zona.", uso: "cliente (id, de clientes_del_nodo). Requiere permiso 'gestion'.", ej: "sucursales_cliente cliente:130 \u2192 ver las sucursales y sus perfiles.", no: "No las crea/edita (eso lo hace el vendedor en su portal); solo el PERFIL lo setea el staff con sucursal_perfil." },
|
|
274
274
|
sucursal_perfil: { que: "Setea (o limpia) el perfil de zona de UNA sucursal: la liquidaci\xF3n cotiza los env\xEDos que salen de ah\xED seg\xFAn SU distancia, no la del cliente.", uso: "sucursalId (de sucursales_cliente) + perfilZona (vac\xEDo = hereda el del cliente). Requiere permiso 'gestion'. Config de staff (el vendedor NO lo toca).", ej: "sucursal_perfil sucursalId:12 perfilZona:'MORENO'.", no: "No mueve dinero, pero afecta el tramo/precio; no crea la sucursal." },
|
|
275
275
|
precios_ver: { que: "Listas de precios por zona de tu nodo.", uso: "Sin par\xE1metros. Requiere permiso 'precios'.", ej: "precios_ver \u2192 ver tarifas por zona.", no: "No las edita (precio_actualizar)." },
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "nexusflex-mcp",
|
|
3
|
-
"version": "3.
|
|
3
|
+
"version": "3.78.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.78.0"; // bumpear junto con package.json + backend/services/mcp-remote.ts
|
|
60
60
|
const NOVEDADES = [
|
|
61
|
+
"3.78.0 — HORARIO DE CORTE DEL CLIENTE (sugerencia #57): `cliente_crear` y `cliente_editar` aceptan `horarioCorte` (HH:MM, ej. 13:00), la hora de corte de la colecta del cliente. En `cliente_editar` sigue siendo parcial: si no lo pasás queda como está y vacío (\"\") lo borra. Es el mismo campo Horario de corte de la ficha del cliente en la app (antes por MCP solo se podía en `sucursal_guardar`). No mueve dinero.",
|
|
61
62
|
"3.77.0 — COTIZADOR DE ENVÍOS (sugerencia #68): `envio_cotizar` te dice, ANTES de cargar un envío que no es de Mercado Libre, la ZONA y el PRECIO que paga ese cliente con SU lista — el mismo que después sale en la liquidación (usa la misma lógica, no un cálculo aparte). Con la dirección y/o la localidad y/o el CP; con la dirección ubica la puerta y la zona sale del mapa, como al cobrar. Sirve para que el vendedor le cobre el envío al comprador por adelantado. Vendedor: para vos; staff con permiso precios: pasá `cliente` de tu nodo. Si la zona no se resuelve devuelve precio null con el motivo (nunca un precio inventado). Es la pantalla Cotizar de la app, con el botón Cargar este envío. Solo lectura: no mueve dinero.",
|
|
62
63
|
"3.76.1 — `comision_liquidar` sale del MCP (decisión del dueño): registrar el pago de comisiones a un afiliado es mover plata y el MCP nunca mueve plata. Se liquida desde la app (Afiliados), y la ruta quedó en la lista de dinero de los dos lados para que no vuelva a entrar por error.",
|
|
63
64
|
"3.76.0 — ALTA INICIAL DEL NODO (migración): el DUEÑO de un nodo carga de una vez su equipo (dueños, operadores, choferes), sus vendedores con los 4 precios (mismos precios = una lista) y los SALDOS de apertura que trae de su sistema anterior, en su propio nodo. `alta_nodo_columnas` (qué va en cada columna), `alta_nodo_previsualizar` (arma y valida sin escribir: errores por hoja y fila) y `alta_nodo_confirmar` (carga todo o nada y devuelve las claves provisorias). Armalo con lo que el dueño tenga: una planilla vieja, una lista, un chat. Los saldos con otros nodos se arreglan entre ellos: los confirma el otro nodo en su app (si todavía no tiene cuenta, valen). Es la misma pantalla Datos del nodo → 📥 Alta inicial (Excel), donde también se baja la planilla. No es un pago ni un cobro. Además: el MCP de la PC ya no le muestra a un cadete herramientas de staff (trabados, provisorios, afiliados), `cuentas_vinculadas` vuelve a andar en la PC (solo lectura), y un admin con nodo ya no ve herramientas de toda la red.",
|
|
@@ -174,6 +175,10 @@ const zNum = () => z.union([z.number(), z.string()]).optional();
|
|
|
174
175
|
// cross-nodo). Se manda al backend como `logisticaId`. Ver sugerencia MCP #20.
|
|
175
176
|
const NODO_OVERRIDE_DESC = "Solo admin global: nodo (id) sobre el que operás. El operador de nodo lo ignora (siempre opera en el suyo).";
|
|
176
177
|
const zNodo = () => z.number().int().positive().optional().describe(NODO_OVERRIDE_DESC);
|
|
178
|
+
// Horario de corte del cliente (HH:MM 24 h). Al editar, "" lo vacía (PATCH parcial). Sugerencia #57.
|
|
179
|
+
const zHorarioCorte = (vaciable) =>
|
|
180
|
+
z.string().trim().regex(vaciable ? /^(([01]\d|2[0-3]):[0-5]\d)?$/ : /^([01]\d|2[0-3]):[0-5]\d$/, "Horario de corte en formato HH:MM (ej. 13:00).").optional()
|
|
181
|
+
.describe(vaciable ? "Horario de corte de la colecta, HH:MM (ej. 13:00). \"\" lo borra." : "Horario de corte de la colecta, HH:MM (ej. 13:00).");
|
|
177
182
|
|
|
178
183
|
const q = (params) => {
|
|
179
184
|
const s = Object.entries(params).filter(([, v]) => v != null && v !== "").map(([k, v]) => `${k}=${encodeURIComponent(v)}`).join("&");
|
|
@@ -1423,6 +1428,7 @@ if (ALLOW_WRITE) {
|
|
|
1423
1428
|
dni: z.string().optional(),
|
|
1424
1429
|
direccion: z.string().optional(),
|
|
1425
1430
|
idLista: z.string().optional().describe("ID de la lista de precios a asignar (ej. 'B'). Consultá 'clientes_del_nodo' / 'precios_ver'. Si falta, el alta queda incompleta."),
|
|
1431
|
+
horarioCorte: zHorarioCorte(false),
|
|
1426
1432
|
nodo: zNodo(),
|
|
1427
1433
|
},
|
|
1428
1434
|
}, async ({ nodo, ...rest }) => {
|
|
@@ -1448,6 +1454,7 @@ if (ALLOW_WRITE) {
|
|
|
1448
1454
|
dni: z.string().optional(),
|
|
1449
1455
|
direccion: z.string().optional(),
|
|
1450
1456
|
mensajeroNombre: z.string().optional().describe("Nombre con el que cobra si también reparte"),
|
|
1457
|
+
horarioCorte: zHorarioCorte(true),
|
|
1451
1458
|
activo: z.boolean().optional(),
|
|
1452
1459
|
nodo: zNodo(),
|
|
1453
1460
|
},
|