@ssolis-ti/mcp-compra-agil 1.0.3 → 2.3.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/README.md +111 -23
- package/dist/api/compra-agil-client.d.ts +37 -2
- package/dist/api/compra-agil-client.d.ts.map +1 -1
- package/dist/api/compra-agil-client.js +76 -5
- package/dist/api/compra-agil-client.js.map +1 -1
- package/dist/index.js +32 -8
- package/dist/index.js.map +1 -1
- package/dist/reports/components.d.ts +59 -0
- package/dist/reports/components.d.ts.map +1 -0
- package/dist/reports/components.js +125 -0
- package/dist/reports/components.js.map +1 -0
- package/dist/reports/export.d.ts +27 -0
- package/dist/reports/export.d.ts.map +1 -0
- package/dist/reports/export.js +47 -0
- package/dist/reports/export.js.map +1 -0
- package/dist/reports/format.d.ts +24 -0
- package/dist/reports/format.d.ts.map +1 -0
- package/dist/reports/format.js +74 -0
- package/dist/reports/format.js.map +1 -0
- package/dist/reports/render.d.ts +18 -0
- package/dist/reports/render.d.ts.map +1 -0
- package/dist/reports/render.js +30 -0
- package/dist/reports/render.js.map +1 -0
- package/dist/reports/templates/radar-oportunidades.d.ts +41 -0
- package/dist/reports/templates/radar-oportunidades.d.ts.map +1 -0
- package/dist/reports/templates/radar-oportunidades.js +170 -0
- package/dist/reports/templates/radar-oportunidades.js.map +1 -0
- package/dist/reports/theme.d.ts +83 -0
- package/dist/reports/theme.d.ts.map +1 -0
- package/dist/reports/theme.js +284 -0
- package/dist/reports/theme.js.map +1 -0
- package/dist/resources/compras-template.d.ts.map +1 -1
- package/dist/resources/compras-template.js +2 -1
- package/dist/resources/compras-template.js.map +1 -1
- package/dist/resources/documentacion.d.ts.map +1 -1
- package/dist/resources/documentacion.js +5 -36
- package/dist/resources/documentacion.js.map +1 -1
- package/dist/resources/estados.d.ts.map +1 -1
- package/dist/resources/estados.js +24 -10
- package/dist/resources/estados.js.map +1 -1
- package/dist/services/monitor.js +38 -3
- package/dist/services/monitor.js.map +1 -1
- package/dist/tools/analizar-precios-mercado.d.ts +21 -0
- package/dist/tools/analizar-precios-mercado.d.ts.map +1 -0
- package/dist/tools/analizar-precios-mercado.js +217 -0
- package/dist/tools/analizar-precios-mercado.js.map +1 -0
- package/dist/tools/auditar-desiertas.d.ts.map +1 -1
- package/dist/tools/auditar-desiertas.js +66 -48
- package/dist/tools/auditar-desiertas.js.map +1 -1
- package/dist/tools/buscar-compras.d.ts.map +1 -1
- package/dist/tools/buscar-compras.js +2 -1
- package/dist/tools/buscar-compras.js.map +1 -1
- package/dist/tools/detalle-compra.d.ts.map +1 -1
- package/dist/tools/detalle-compra.js +6 -5
- package/dist/tools/detalle-compra.js.map +1 -1
- package/dist/tools/detalle-oc.js +6 -6
- package/dist/tools/detalle-oc.js.map +1 -1
- package/dist/tools/documentos.d.ts.map +1 -1
- package/dist/tools/documentos.js +75 -81
- package/dist/tools/documentos.js.map +1 -1
- package/dist/tools/estadisticas-uso.d.ts.map +1 -1
- package/dist/tools/estadisticas-uso.js +12 -2
- package/dist/tools/estadisticas-uso.js.map +1 -1
- package/dist/tools/generar-borrador.d.ts +25 -1
- package/dist/tools/generar-borrador.d.ts.map +1 -1
- package/dist/tools/generar-borrador.js +111 -82
- package/dist/tools/generar-borrador.js.map +1 -1
- package/dist/tools/generar-informe.d.ts +13 -0
- package/dist/tools/generar-informe.d.ts.map +1 -0
- package/dist/tools/generar-informe.js +111 -0
- package/dist/tools/generar-informe.js.map +1 -0
- package/dist/tools/monitorear-cambios.d.ts +32 -2
- package/dist/tools/monitorear-cambios.d.ts.map +1 -1
- package/dist/tools/monitorear-cambios.js +79 -10
- package/dist/tools/monitorear-cambios.js.map +1 -1
- package/dist/tools/radar-oportunidades.d.ts +42 -1
- package/dist/tools/radar-oportunidades.d.ts.map +1 -1
- package/dist/tools/radar-oportunidades.js +123 -103
- package/dist/tools/radar-oportunidades.js.map +1 -1
- package/dist/tools/recomendar-precio.d.ts +13 -0
- package/dist/tools/recomendar-precio.d.ts.map +1 -1
- package/dist/tools/recomendar-precio.js +53 -57
- package/dist/tools/recomendar-precio.js.map +1 -1
- package/dist/tools/verificar-oc.d.ts.map +1 -1
- package/dist/tools/verificar-oc.js +36 -8
- package/dist/tools/verificar-oc.js.map +1 -1
- package/dist/tools/verificar-ticket.d.ts +13 -0
- package/dist/tools/verificar-ticket.d.ts.map +1 -0
- package/dist/tools/verificar-ticket.js +79 -0
- package/dist/tools/verificar-ticket.js.map +1 -0
- package/dist/utils/cache.d.ts +53 -0
- package/dist/utils/cache.d.ts.map +1 -0
- package/dist/utils/cache.js +131 -0
- package/dist/utils/cache.js.map +1 -0
- package/dist/utils/doc-search.d.ts +52 -0
- package/dist/utils/doc-search.d.ts.map +1 -0
- package/dist/utils/doc-search.js +97 -0
- package/dist/utils/doc-search.js.map +1 -0
- package/dist/utils/docs-locator.d.ts +41 -0
- package/dist/utils/docs-locator.d.ts.map +1 -0
- package/dist/utils/docs-locator.js +82 -0
- package/dist/utils/docs-locator.js.map +1 -0
- package/dist/utils/error-handler.d.ts.map +1 -1
- package/dist/utils/error-handler.js +8 -7
- package/dist/utils/error-handler.js.map +1 -1
- package/dist/utils/logger.d.ts.map +1 -1
- package/dist/utils/logger.js +9 -6
- package/dist/utils/logger.js.map +1 -1
- package/dist/utils/quotation.d.ts +71 -0
- package/dist/utils/quotation.d.ts.map +1 -0
- package/dist/utils/quotation.js +140 -0
- package/dist/utils/quotation.js.map +1 -0
- package/dist/utils/rate-limiter.d.ts +44 -2
- package/dist/utils/rate-limiter.d.ts.map +1 -1
- package/dist/utils/rate-limiter.js +125 -13
- package/dist/utils/rate-limiter.js.map +1 -1
- package/dist/utils/redact.d.ts +48 -0
- package/dist/utils/redact.d.ts.map +1 -0
- package/dist/utils/redact.js +100 -0
- package/dist/utils/redact.js.map +1 -0
- package/package.json +55 -53
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { z } from 'zod';
|
|
2
2
|
import { CompraAgilApiError } from '../utils/error-handler.js';
|
|
3
3
|
import { logger } from '../utils/logger.js';
|
|
4
|
+
import { safeError } from '../utils/redact.js';
|
|
4
5
|
const TOOL_NAME = 'radar_oportunidades_calientes';
|
|
5
6
|
const TOOL_DESCRIPTION = `Escanea, califica y clasifica de forma priorizada los procesos de Compra Ágil activos (publicados).
|
|
6
7
|
Utiliza una fórmula ponderada (Hot Score) basada en la falta de oferentes, el presupuesto disponible y las horas restantes de cierre para destacar los llamados más convenientes y fáciles de ganar.`;
|
|
@@ -9,23 +10,131 @@ const inputSchema = {
|
|
|
9
10
|
q: z.string().optional().describe('Término de búsqueda opcional para acotar a un rubro o producto específico (ej: "licencias").'),
|
|
10
11
|
presupuesto_minimo: z.number().optional().describe('Filtrar solo procesos con presupuesto disponible mayor o igual a este monto en CLP.'),
|
|
11
12
|
limite_resultados: z.number().min(1).max(20).default(10).optional().describe('Cantidad máxima de oportunidades destacadas a retornar (1-20, default 10).'),
|
|
13
|
+
max_paginas: z.number().min(1).max(10).default(3).optional().describe('Cuántas páginas de 50 resultados escanear antes de rankear (1-10, default 3 = hasta 150 procesos). Más páginas = más cobertura pero más consumo de cuota.'),
|
|
12
14
|
};
|
|
15
|
+
/**
|
|
16
|
+
* Calcula el "Hot Score" de una oportunidad de forma pura (sin efectos secundarios).
|
|
17
|
+
* Retorna null si el proceso debe omitirse (ya cerrado o bajo el presupuesto mínimo).
|
|
18
|
+
* Ponderación: baja competencia (máx 50) + urgencia (máx 30) + presupuesto (máx 20) + facilidad (máx 5).
|
|
19
|
+
*/
|
|
20
|
+
export function evaluarOportunidad(item, now, minBudget = 0) {
|
|
21
|
+
const budget = item.montos?.monto_disponible_clp || item.montos?.monto_disponible || 0;
|
|
22
|
+
if (budget < minBudget)
|
|
23
|
+
return null;
|
|
24
|
+
let hoursLeft = 0;
|
|
25
|
+
if (item.fechas?.fecha_cierre) {
|
|
26
|
+
const cierreTime = new Date(item.fechas.fecha_cierre).getTime();
|
|
27
|
+
hoursLeft = (cierreTime - now) / (1000 * 60 * 60);
|
|
28
|
+
}
|
|
29
|
+
if (hoursLeft <= 0)
|
|
30
|
+
return null;
|
|
31
|
+
let score = 0;
|
|
32
|
+
const factors = [];
|
|
33
|
+
// Factor 1: Baja Competencia — Máx 50 pts
|
|
34
|
+
const bids = item.resumen?.total_ofertas_recibidas ?? 0;
|
|
35
|
+
if (bids === 0) {
|
|
36
|
+
score += 50;
|
|
37
|
+
factors.push('Sin oferentes activos (+50 pts)');
|
|
38
|
+
}
|
|
39
|
+
else if (bids === 1) {
|
|
40
|
+
score += 30;
|
|
41
|
+
factors.push('Baja competencia: solo 1 oferente (+30 pts)');
|
|
42
|
+
}
|
|
43
|
+
else if (bids === 2) {
|
|
44
|
+
score += 15;
|
|
45
|
+
factors.push('Competencia moderada: 2 oferentes (+15 pts)');
|
|
46
|
+
}
|
|
47
|
+
// Factor 2: Urgencia del Cierre — Máx 30 pts
|
|
48
|
+
if (hoursLeft <= 4) {
|
|
49
|
+
score += 30;
|
|
50
|
+
factors.push('Urgencia crítica: cierra en menos de 4 horas (+30 pts)');
|
|
51
|
+
}
|
|
52
|
+
else if (hoursLeft <= 12) {
|
|
53
|
+
score += 20;
|
|
54
|
+
factors.push('Cierre inminente: cierra en menos de 12 horas (+20 pts)');
|
|
55
|
+
}
|
|
56
|
+
else if (hoursLeft <= 24) {
|
|
57
|
+
score += 10;
|
|
58
|
+
factors.push('Cierre cercano: cierra en menos de 24 horas (+10 pts)');
|
|
59
|
+
}
|
|
60
|
+
// Factor 3: Tamaño de Presupuesto — Máx 20 pts
|
|
61
|
+
if (budget >= 5000000) {
|
|
62
|
+
score += 20;
|
|
63
|
+
factors.push('Presupuesto de alto valor (>= $5.000.000 CLP) (+20 pts)');
|
|
64
|
+
}
|
|
65
|
+
else if (budget >= 2000000) {
|
|
66
|
+
score += 15;
|
|
67
|
+
factors.push('Presupuesto medio-alto (>= $2.000.000 CLP) (+15 pts)');
|
|
68
|
+
}
|
|
69
|
+
else if (budget >= 500000) {
|
|
70
|
+
score += 10;
|
|
71
|
+
factors.push('Presupuesto medio (>= $500.000 CLP) (+10 pts)');
|
|
72
|
+
}
|
|
73
|
+
else {
|
|
74
|
+
score += 5;
|
|
75
|
+
factors.push('Presupuesto bajo (< $500.000 CLP) (+5 pts)');
|
|
76
|
+
}
|
|
77
|
+
// Factor 4: Facilidad de Postulación — Máx 5 pts
|
|
78
|
+
const docsCount = item.documentos?.length || 0;
|
|
79
|
+
if (docsCount === 0) {
|
|
80
|
+
score += 5;
|
|
81
|
+
factors.push('Sin documentos adjuntos (postulación rápida sin leer bases) (+5 pts)');
|
|
82
|
+
}
|
|
83
|
+
return {
|
|
84
|
+
codigo: item.codigo,
|
|
85
|
+
nombre: item.nombre,
|
|
86
|
+
organismo: item.institucion?.organismo_comprador || 'No especificado',
|
|
87
|
+
region: item.institucion?.nombre_region || 'No especificada',
|
|
88
|
+
presupuesto_disponible: budget,
|
|
89
|
+
ofertas_recibidas: bids,
|
|
90
|
+
horas_restantes: Math.round(hoursLeft * 10) / 10,
|
|
91
|
+
fecha_cierre: item.fechas?.fecha_cierre,
|
|
92
|
+
puntuacion_caliente: score,
|
|
93
|
+
factores_calificacion: factors,
|
|
94
|
+
};
|
|
95
|
+
}
|
|
96
|
+
/**
|
|
97
|
+
* Recolecta y rankea las oportunidades del radar.
|
|
98
|
+
*
|
|
99
|
+
* Función pura de datos (sin formato de salida): la comparten la tool
|
|
100
|
+
* `radar_oportunidades_calientes` (que emite JSON para el LLM) y el informe
|
|
101
|
+
* HTML/PDF, garantizando que ambos muestren exactamente lo mismo.
|
|
102
|
+
*/
|
|
103
|
+
export async function recolectarDatosRadar(client, params, now = Date.now()) {
|
|
104
|
+
const maxPaginas = params.max_paginas || 3;
|
|
105
|
+
logger.info(`radar: escaneando procesos activos (hasta ${maxPaginas} pág.) region="${params.region || 'Todas'}" q="${params.q || 'Todos'}"`);
|
|
106
|
+
// Auto-paginación: escanear varias páginas para no perder oportunidades en páginas 2+
|
|
107
|
+
const items = await client.buscarTodo({
|
|
108
|
+
estado: 'publicada',
|
|
109
|
+
region: params.region || undefined,
|
|
110
|
+
q: params.q || undefined,
|
|
111
|
+
tamano_pagina: 50,
|
|
112
|
+
}, maxPaginas);
|
|
113
|
+
const minBudget = params.presupuesto_minimo || 0;
|
|
114
|
+
const opportunities = [];
|
|
115
|
+
for (const item of items) {
|
|
116
|
+
const evaluada = evaluarOportunidad(item, now, minBudget);
|
|
117
|
+
if (evaluada)
|
|
118
|
+
opportunities.push(evaluada);
|
|
119
|
+
}
|
|
120
|
+
// Ordenar descendentemente por puntuación caliente
|
|
121
|
+
opportunities.sort((a, b) => b.puntuacion_caliente - a.puntuacion_caliente);
|
|
122
|
+
const limite = params.limite_resultados || 10;
|
|
123
|
+
return {
|
|
124
|
+
oportunidades: opportunities.slice(0, limite),
|
|
125
|
+
totalAnalizadas: opportunities.length,
|
|
126
|
+
limite,
|
|
127
|
+
paginasEscaneadas: maxPaginas,
|
|
128
|
+
};
|
|
129
|
+
}
|
|
13
130
|
export function registerRadarOportunidades(server, client) {
|
|
14
131
|
server.registerTool(TOOL_NAME, {
|
|
15
132
|
description: TOOL_DESCRIPTION,
|
|
16
133
|
inputSchema: inputSchema,
|
|
17
134
|
}, async (args) => {
|
|
18
135
|
try {
|
|
19
|
-
const
|
|
20
|
-
|
|
21
|
-
region: args.region || undefined,
|
|
22
|
-
q: args.q || undefined,
|
|
23
|
-
tamano_pagina: 50, // Obtener un lote amplio de 50 para poder rankear
|
|
24
|
-
numero_pagina: 1,
|
|
25
|
-
};
|
|
26
|
-
logger.info(`radar_oportunidades_calientes: Escaneando procesos activos para region="${args.region || 'Todas'}" q="${args.q || 'Todos'}"`);
|
|
27
|
-
const searchResponse = await client.buscar(queryParams);
|
|
28
|
-
if (!searchResponse.items || searchResponse.items.length === 0) {
|
|
136
|
+
const datos = await recolectarDatosRadar(client, args);
|
|
137
|
+
if (datos.totalAnalizadas === 0) {
|
|
29
138
|
return {
|
|
30
139
|
content: [{
|
|
31
140
|
type: 'text',
|
|
@@ -33,99 +142,10 @@ export function registerRadarOportunidades(server, client) {
|
|
|
33
142
|
}],
|
|
34
143
|
};
|
|
35
144
|
}
|
|
36
|
-
const now = Date.now();
|
|
37
|
-
const opportunities = [];
|
|
38
|
-
const minBudget = args.presupuesto_minimo || 0;
|
|
39
|
-
for (const item of searchResponse.items) {
|
|
40
|
-
const budget = item.montos?.monto_disponible_clp || item.montos?.monto_disponible || 0;
|
|
41
|
-
// Filtrar por presupuesto mínimo si corresponde
|
|
42
|
-
if (budget < minBudget) {
|
|
43
|
-
continue;
|
|
44
|
-
}
|
|
45
|
-
// Calcular tiempo restante en horas
|
|
46
|
-
let hoursLeft = 0;
|
|
47
|
-
if (item.fechas?.fecha_cierre) {
|
|
48
|
-
const cierreTime = new Date(item.fechas.fecha_cierre).getTime();
|
|
49
|
-
hoursLeft = (cierreTime - now) / (1000 * 60 * 60);
|
|
50
|
-
}
|
|
51
|
-
// Omitir procesos que ya cerraron o están en negativo por zona horaria
|
|
52
|
-
if (hoursLeft <= 0) {
|
|
53
|
-
continue;
|
|
54
|
-
}
|
|
55
|
-
let score = 0;
|
|
56
|
-
const factors = [];
|
|
57
|
-
// Factor 1: Baja Competencia (total_ofertas_recibidas) - Máx 50 pts
|
|
58
|
-
const bids = item.resumen?.total_ofertas_recibidas ?? 0;
|
|
59
|
-
if (bids === 0) {
|
|
60
|
-
score += 50;
|
|
61
|
-
factors.push('Sin oferentes activos (+50 pts)');
|
|
62
|
-
}
|
|
63
|
-
else if (bids === 1) {
|
|
64
|
-
score += 30;
|
|
65
|
-
factors.push('Baja competencia: solo 1 oferente (+30 pts)');
|
|
66
|
-
}
|
|
67
|
-
else if (bids === 2) {
|
|
68
|
-
score += 15;
|
|
69
|
-
factors.push('Competencia moderada: 2 oferentes (+15 pts)');
|
|
70
|
-
}
|
|
71
|
-
// Factor 2: Urgencia del Cierre (horas restantes) - Máx 30 pts
|
|
72
|
-
if (hoursLeft <= 4) {
|
|
73
|
-
score += 30;
|
|
74
|
-
factors.push('Urgencia crítica: cierra en menos de 4 horas (+30 pts)');
|
|
75
|
-
}
|
|
76
|
-
else if (hoursLeft <= 12) {
|
|
77
|
-
score += 20;
|
|
78
|
-
factors.push('Cierre inminente: cierra en menos de 12 horas (+20 pts)');
|
|
79
|
-
}
|
|
80
|
-
else if (hoursLeft <= 24) {
|
|
81
|
-
score += 10;
|
|
82
|
-
factors.push('Cierre cercano: cierra en menos de 24 horas (+10 pts)');
|
|
83
|
-
}
|
|
84
|
-
// Factor 3: Tamaño de Presupuesto - Máx 20 pts
|
|
85
|
-
if (budget >= 5000000) {
|
|
86
|
-
score += 20;
|
|
87
|
-
factors.push('Presupuesto de alto valor (>= $5.000.000 CLP) (+20 pts)');
|
|
88
|
-
}
|
|
89
|
-
else if (budget >= 2000000) {
|
|
90
|
-
score += 15;
|
|
91
|
-
factors.push('Presupuesto medio-alto (>= $2.000.000 CLP) (+15 pts)');
|
|
92
|
-
}
|
|
93
|
-
else if (budget >= 500000) {
|
|
94
|
-
score += 10;
|
|
95
|
-
factors.push('Presupuesto medio (>= $500.000 CLP) (+10 pts)');
|
|
96
|
-
}
|
|
97
|
-
else {
|
|
98
|
-
score += 5;
|
|
99
|
-
factors.push('Presupuesto bajo (< $500.000 CLP) (+5 pts)');
|
|
100
|
-
}
|
|
101
|
-
// Factor 4: Facilidad de Postulación - Máx 5 pts
|
|
102
|
-
const docsCount = item.documentos?.length || 0;
|
|
103
|
-
if (docsCount === 0) {
|
|
104
|
-
score += 5;
|
|
105
|
-
factors.push('Sin documentos adjuntos (postulación rápida sin leer bases) (+5 pts)');
|
|
106
|
-
}
|
|
107
|
-
opportunities.push({
|
|
108
|
-
codigo: item.codigo,
|
|
109
|
-
nombre: item.nombre,
|
|
110
|
-
organismo: item.institucion?.organismo_comprador || 'No especificado',
|
|
111
|
-
region: item.institucion?.nombre_region || 'No especificada',
|
|
112
|
-
presupuesto_disponible: budget,
|
|
113
|
-
ofertas_recibidas: bids,
|
|
114
|
-
horas_restantes: Math.round(hoursLeft * 10) / 10,
|
|
115
|
-
fecha_cierre: item.fechas?.fecha_cierre,
|
|
116
|
-
puntuacion_caliente: score,
|
|
117
|
-
factores_calificacion: factors,
|
|
118
|
-
});
|
|
119
|
-
}
|
|
120
|
-
// Ordenar descendentemente por puntuación caliente
|
|
121
|
-
opportunities.sort((a, b) => b.puntuacion_caliente - a.puntuacion_caliente);
|
|
122
|
-
// Aplicar límite
|
|
123
|
-
const limit = args.limite_resultados || 10;
|
|
124
|
-
const rankedOpportunities = opportunities.slice(0, limit);
|
|
125
145
|
const result = {
|
|
126
|
-
total_oportunidades_analizadas:
|
|
127
|
-
radar_limite_resultados:
|
|
128
|
-
oportunidades_calientes:
|
|
146
|
+
total_oportunidades_analizadas: datos.totalAnalizadas,
|
|
147
|
+
radar_limite_resultados: datos.limite,
|
|
148
|
+
oportunidades_calientes: datos.oportunidades,
|
|
129
149
|
};
|
|
130
150
|
return {
|
|
131
151
|
content: [{
|
|
@@ -137,7 +157,7 @@ export function registerRadarOportunidades(server, client) {
|
|
|
137
157
|
catch (error) {
|
|
138
158
|
const message = error instanceof CompraAgilApiError
|
|
139
159
|
? error.actionableMessage
|
|
140
|
-
: `Error inesperado en radar de oportunidades: ${
|
|
160
|
+
: `Error inesperado en radar de oportunidades: ${safeError(error)}`;
|
|
141
161
|
return {
|
|
142
162
|
content: [{ type: 'text', text: message }],
|
|
143
163
|
isError: true,
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"radar-oportunidades.js","sourceRoot":"","sources":["../../src/tools/radar-oportunidades.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAGxB,OAAO,EAAE,kBAAkB,EAAE,MAAM,2BAA2B,CAAC;AAC/D,OAAO,EAAE,MAAM,EAAE,MAAM,oBAAoB,CAAC;
|
|
1
|
+
{"version":3,"file":"radar-oportunidades.js","sourceRoot":"","sources":["../../src/tools/radar-oportunidades.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,4 +1,17 @@
|
|
|
1
1
|
import { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';
|
|
2
2
|
import { CompraAgilClient } from '../api/compra-agil-client.js';
|
|
3
3
|
export declare function registerRecomendarPrecio(server: McpServer, client: CompraAgilClient): void;
|
|
4
|
+
interface EstadisticasPrecio {
|
|
5
|
+
muestras: number;
|
|
6
|
+
minimo: number;
|
|
7
|
+
maximo: number;
|
|
8
|
+
promedio: number;
|
|
9
|
+
mediana: number;
|
|
10
|
+
}
|
|
11
|
+
/**
|
|
12
|
+
* Calcula min/max/promedio/mediana de una serie de precios.
|
|
13
|
+
* Retorna null si la serie está vacía (para poder distinguir "sin datos").
|
|
14
|
+
*/
|
|
15
|
+
export declare function calcularEstadisticas(valores: number[]): EstadisticasPrecio | null;
|
|
16
|
+
export {};
|
|
4
17
|
//# sourceMappingURL=recomendar-precio.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"recomendar-precio.d.ts","sourceRoot":"","sources":["../../src/tools/recomendar-precio.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,SAAS,EAAE,MAAM,yCAAyC,CAAC;AACpE,OAAO,EAAE,gBAAgB,EAAE,MAAM,8BAA8B,CAAC;
|
|
1
|
+
{"version":3,"file":"recomendar-precio.d.ts","sourceRoot":"","sources":["../../src/tools/recomendar-precio.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,SAAS,EAAE,MAAM,yCAAyC,CAAC;AACpE,OAAO,EAAE,gBAAgB,EAAE,MAAM,8BAA8B,CAAC;AAoBhE,wBAAgB,wBAAwB,CAAC,MAAM,EAAE,SAAS,EAAE,MAAM,EAAE,gBAAgB,GAAG,IAAI,CAgK1F;AAED,UAAU,kBAAkB;IAC1B,QAAQ,EAAE,MAAM,CAAC;IACjB,MAAM,EAAE,MAAM,CAAC;IACf,MAAM,EAAE,MAAM,CAAC;IACf,QAAQ,EAAE,MAAM,CAAC;IACjB,OAAO,EAAE,MAAM,CAAC;CACjB;AAED;;;GAGG;AACH,wBAAgB,oBAAoB,CAAC,OAAO,EAAE,MAAM,EAAE,GAAG,kBAAkB,GAAG,IAAI,CAWjF"}
|
|
@@ -1,10 +1,13 @@
|
|
|
1
1
|
import { z } from 'zod';
|
|
2
2
|
import { CompraAgilApiError } from '../utils/error-handler.js';
|
|
3
3
|
import { logger } from '../utils/logger.js';
|
|
4
|
+
import { esGanador, extraerPrecioUnitario, extraerMontoNeto } from '../utils/quotation.js';
|
|
5
|
+
import { safeError } from '../utils/redact.js';
|
|
4
6
|
const TOOL_NAME = 'recomendar_precio_ganador';
|
|
5
|
-
const TOOL_DESCRIPTION = `Analiza procesos históricos similares de Compra Ágil que ya fueron cerrados y adjudicados para estimar y sugerir un precio
|
|
7
|
+
const TOOL_DESCRIPTION = `Analiza procesos históricos similares de Compra Ágil que ya fueron cerrados y adjudicados para estimar y sugerir un precio competitivo para postular.
|
|
6
8
|
Admite ingresar el código de una compra activa para extraer automáticamente las palabras clave o un término de búsqueda genérico.
|
|
7
|
-
|
|
9
|
+
Distingue entre precio UNITARIO (comparable directamente) y monto NETO total adjudicado, reportando cada estadística por separado.
|
|
10
|
+
Nota: Las consultas históricas se realizan de forma secuencial y respetan el límite de tasa (throttle) interno para no agotar la cuota diaria de la API.`;
|
|
8
11
|
const inputSchema = {
|
|
9
12
|
codigo_compra: z.string().optional().describe('Código de la Compra Ágil activa para analizar (ej: "1057539-228-COT26"). Opcional si se especifica "q".'),
|
|
10
13
|
q: z.string().optional().describe('Término de búsqueda de producto/servicio a cotizar (ej: "resmas papel", "soporte computadores"). Opcional si se especifica "codigo_compra".'),
|
|
@@ -65,61 +68,43 @@ export function registerRecomendarPrecio(server, client) {
|
|
|
65
68
|
}],
|
|
66
69
|
};
|
|
67
70
|
}
|
|
68
|
-
// 3. Consultar
|
|
69
|
-
|
|
71
|
+
// 3. Consultar los detalles (secuencial, respetando el throttle del client) para obtener el ganador.
|
|
72
|
+
// IMPORTANTE (C2): se mantienen DOS series separadas — precios unitarios y montos netos totales —
|
|
73
|
+
// porque no son comparables entre sí y mezclarlos corrompe las estadísticas.
|
|
74
|
+
const unitPrices = [];
|
|
75
|
+
const totalPrices = [];
|
|
70
76
|
const processedItems = [];
|
|
71
77
|
const itemsToProcess = searchResponse.items.slice(0, limit);
|
|
72
78
|
logger.info(`recomendar_precio_ganador: Analizando detalles de ${itemsToProcess.length} procesos adjudicados`);
|
|
73
79
|
for (const item of itemsToProcess) {
|
|
74
80
|
try {
|
|
75
81
|
const detail = await client.detalle(item.codigo);
|
|
76
|
-
// Buscar al adjudicado/ganador
|
|
77
|
-
const winner = detail.proveedores_cotizando?.find(
|
|
78
|
-
if (prov.proveedor_seleccionado === true || prov.proveedor_seleccionado === 1)
|
|
79
|
-
return true;
|
|
80
|
-
if (prov.seleccion && prov.seleccion.proveedor_seleccionado === true)
|
|
81
|
-
return true;
|
|
82
|
-
return false;
|
|
83
|
-
});
|
|
82
|
+
// Buscar al adjudicado/ganador con la heurística centralizada (C1)
|
|
83
|
+
const winner = detail.proveedores_cotizando?.find(esGanador);
|
|
84
84
|
if (winner) {
|
|
85
|
-
const
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
else if (winner.productos_cotizados && winner.productos_cotizados.length > 1) {
|
|
92
|
-
// Buscar el producto cotizado que más coincida con la keyword original
|
|
93
|
-
const matchedProd = winner.productos_cotizados.find(p => p.nombre_producto.toLowerCase().includes(keyword.toLowerCase()));
|
|
94
|
-
if (matchedProd) {
|
|
95
|
-
unitPrice = matchedProd.precio_unitario;
|
|
96
|
-
}
|
|
97
|
-
else {
|
|
98
|
-
// Fallback: usar el precio del primer item
|
|
99
|
-
unitPrice = winner.productos_cotizados[0].precio_unitario;
|
|
100
|
-
}
|
|
101
|
-
}
|
|
102
|
-
const priceValue = unitPrice || totalNeto;
|
|
103
|
-
if (priceValue > 0) {
|
|
104
|
-
prices.push(priceValue);
|
|
105
|
-
}
|
|
85
|
+
const unitPrice = extraerPrecioUnitario(winner, keyword);
|
|
86
|
+
const totalNeto = extraerMontoNeto(winner);
|
|
87
|
+
if (unitPrice !== null)
|
|
88
|
+
unitPrices.push(unitPrice);
|
|
89
|
+
if (totalNeto !== null)
|
|
90
|
+
totalPrices.push(totalNeto);
|
|
106
91
|
processedItems.push({
|
|
107
92
|
codigo: item.codigo,
|
|
108
93
|
institucion: item.institucion.organismo_comprador,
|
|
109
94
|
fecha_cierre: item.fechas.fecha_cierre,
|
|
110
95
|
ganador: winner.razon_social,
|
|
111
96
|
es_emt: winner.es_emt,
|
|
112
|
-
|
|
97
|
+
monto_neto_adjudicado: totalNeto,
|
|
113
98
|
precio_unitario_adjudicado: unitPrice,
|
|
114
99
|
criterio_seleccion: winner.seleccion?.criterio_seleccion || 'No especificado',
|
|
115
100
|
});
|
|
116
101
|
}
|
|
117
102
|
}
|
|
118
103
|
catch (detailError) {
|
|
119
|
-
logger.warn(`recomendar_precio_ganador: Error al consultar detalle de ${item.codigo}: ${
|
|
104
|
+
logger.warn(`recomendar_precio_ganador: Error al consultar detalle de ${item.codigo}: ${safeError(detailError)}`);
|
|
120
105
|
}
|
|
121
106
|
}
|
|
122
|
-
if (
|
|
107
|
+
if (unitPrices.length === 0 && totalPrices.length === 0) {
|
|
123
108
|
return {
|
|
124
109
|
content: [{
|
|
125
110
|
type: 'text',
|
|
@@ -127,31 +112,25 @@ export function registerRecomendarPrecio(server, client) {
|
|
|
127
112
|
}],
|
|
128
113
|
};
|
|
129
114
|
}
|
|
130
|
-
// 4. Calcular estadísticas
|
|
131
|
-
|
|
132
|
-
const
|
|
133
|
-
const
|
|
134
|
-
const
|
|
135
|
-
const
|
|
136
|
-
//
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
let recommended = Math.round(avg * 0.95);
|
|
141
|
-
if (recommended < min) {
|
|
142
|
-
recommended = min;
|
|
115
|
+
// 4. Calcular estadísticas por serie. Se prioriza la serie de precios UNITARIOS
|
|
116
|
+
// para la recomendación (comparable directamente); si no hay, se usa el monto neto.
|
|
117
|
+
const statsUnitarios = calcularEstadisticas(unitPrices);
|
|
118
|
+
const statsTotales = calcularEstadisticas(totalPrices);
|
|
119
|
+
const baseStats = statsUnitarios ?? statsTotales;
|
|
120
|
+
const baseTipo = statsUnitarios ? 'precio_unitario' : 'monto_neto_total';
|
|
121
|
+
// 5. Sugerir precio competitivo (5% por debajo del promedio, acotado por el mínimo)
|
|
122
|
+
let recommended = Math.round(baseStats.promedio * 0.95);
|
|
123
|
+
if (recommended < baseStats.minimo) {
|
|
124
|
+
recommended = baseStats.minimo;
|
|
143
125
|
}
|
|
144
126
|
const result = {
|
|
145
127
|
proceso_activo: targetProductDetail || undefined,
|
|
146
128
|
termino_clave_utilizado: keyword,
|
|
147
129
|
region_analisis: region ? `Región ${region}` : 'Todas las regiones',
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
promedio_historico: avg,
|
|
153
|
-
mediana_historica: median,
|
|
154
|
-
},
|
|
130
|
+
procesos_adjudicados_analizados: processedItems.length,
|
|
131
|
+
estadisticas_precio_unitario: statsUnitarios,
|
|
132
|
+
estadisticas_monto_neto_total: statsTotales,
|
|
133
|
+
base_de_la_recomendacion: baseTipo,
|
|
155
134
|
sugerencia_de_precio_competitivo: recommended,
|
|
156
135
|
rango_sugerido: {
|
|
157
136
|
min: Math.round(recommended * 0.95),
|
|
@@ -169,7 +148,7 @@ export function registerRecomendarPrecio(server, client) {
|
|
|
169
148
|
catch (error) {
|
|
170
149
|
const message = error instanceof CompraAgilApiError
|
|
171
150
|
? error.actionableMessage
|
|
172
|
-
: `Error inesperado al recomendar precio: ${
|
|
151
|
+
: `Error inesperado al recomendar precio: ${safeError(error)}`;
|
|
173
152
|
return {
|
|
174
153
|
content: [{ type: 'text', text: message }],
|
|
175
154
|
isError: true,
|
|
@@ -177,4 +156,21 @@ export function registerRecomendarPrecio(server, client) {
|
|
|
177
156
|
}
|
|
178
157
|
});
|
|
179
158
|
}
|
|
159
|
+
/**
|
|
160
|
+
* Calcula min/max/promedio/mediana de una serie de precios.
|
|
161
|
+
* Retorna null si la serie está vacía (para poder distinguir "sin datos").
|
|
162
|
+
*/
|
|
163
|
+
export function calcularEstadisticas(valores) {
|
|
164
|
+
if (!valores || valores.length === 0)
|
|
165
|
+
return null;
|
|
166
|
+
const sorted = [...valores].sort((a, b) => a - b);
|
|
167
|
+
const min = sorted[0];
|
|
168
|
+
const max = sorted[sorted.length - 1];
|
|
169
|
+
const avg = Math.round(sorted.reduce((acc, v) => acc + v, 0) / sorted.length);
|
|
170
|
+
const mid = Math.floor(sorted.length / 2);
|
|
171
|
+
const median = sorted.length % 2 !== 0
|
|
172
|
+
? sorted[mid]
|
|
173
|
+
: Math.round((sorted[mid - 1] + sorted[mid]) / 2);
|
|
174
|
+
return { muestras: sorted.length, minimo: min, maximo: max, promedio: avg, mediana: median };
|
|
175
|
+
}
|
|
180
176
|
//# sourceMappingURL=recomendar-precio.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"recomendar-precio.js","sourceRoot":"","sources":["../../src/tools/recomendar-precio.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAGxB,OAAO,EAAE,kBAAkB,EAAE,MAAM,2BAA2B,CAAC;AAC/D,OAAO,EAAE,MAAM,EAAE,MAAM,oBAAoB,CAAC;
|
|
1
|
+
{"version":3,"file":"recomendar-precio.js","sourceRoot":"","sources":["../../src/tools/recomendar-precio.ts"],"names":[],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"verificar-oc.d.ts","sourceRoot":"","sources":["../../src/tools/verificar-oc.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAGH,OAAO,EAAE,SAAS,EAAE,MAAM,yCAAyC,CAAC;AACpE,OAAO,EAAE,gBAAgB,EAAE,MAAM,8BAA8B,CAAC;
|
|
1
|
+
{"version":3,"file":"verificar-oc.d.ts","sourceRoot":"","sources":["../../src/tools/verificar-oc.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAGH,OAAO,EAAE,SAAS,EAAE,MAAM,yCAAyC,CAAC;AACpE,OAAO,EAAE,gBAAgB,EAAE,MAAM,8BAA8B,CAAC;AAkBhE,wBAAgB,mBAAmB,CAAC,MAAM,EAAE,SAAS,EAAE,MAAM,EAAE,gBAAgB,GAAG,IAAI,CA0GrF"}
|
|
@@ -10,10 +10,12 @@
|
|
|
10
10
|
import { z } from 'zod';
|
|
11
11
|
import { CompraAgilApiError } from '../utils/error-handler.js';
|
|
12
12
|
import { logger } from '../utils/logger.js';
|
|
13
|
+
import { esGanador } from '../utils/quotation.js';
|
|
14
|
+
import { safeError } from '../utils/redact.js';
|
|
13
15
|
const TOOL_NAME = 'verificar_orden_compra';
|
|
14
|
-
const TOOL_DESCRIPTION = `
|
|
15
|
-
|
|
16
|
-
|
|
16
|
+
const TOOL_DESCRIPTION = `Informa si una Compra Ágil tiene Orden de Compra emitida, leyendo id_orden_compra del detalle.
|
|
17
|
+
⚠ LIMITACIÓN VERIFICADA (julio 2026, re-confirmada en septiembre): en 45 procesos inspeccionados NINGUNO traía id_orden_compra, y el filtro "proveedor_seleccionado" devuelve 0 resultados. La API de Compra Ágil no publica adjudicaciones. Por eso esta herramienta NO consulta la API por su cuenta —sería gastar cuota para responder "no puedo saberlo"—: reutiliza el detalle si ya se pidió con "obtener_detalle_compra", y en cualquier caso indica cómo confirmarlo en la ficha pública.
|
|
18
|
+
Un "sin OC" NO prueba que la OC no exista: significa que la API no la expone.`;
|
|
17
19
|
const inputSchema = {
|
|
18
20
|
codigo: z.string().describe('Código único de la Compra Ágil a verificar. Formato: XXXXXX-YYY-COTXX. Ej: "1057539-228-COT26".'),
|
|
19
21
|
};
|
|
@@ -23,7 +25,33 @@ export function registerVerificarOC(server, client) {
|
|
|
23
25
|
inputSchema: inputSchema,
|
|
24
26
|
}, async (args) => {
|
|
25
27
|
try {
|
|
26
|
-
|
|
28
|
+
// ⚠ NO se consulta la API si el detalle no está ya en caché.
|
|
29
|
+
// Esta herramienta gastaba una consulta de cuota para responder algo
|
|
30
|
+
// que la API estructuralmente no publica: en 45 procesos inspeccionados
|
|
31
|
+
// más las verificaciones de septiembre 2026, NINGUNO trajo
|
|
32
|
+
// id_orden_compra. Pagar cuota por un "no puedo saberlo" garantizado
|
|
33
|
+
// es el peor negocio posible cuando el balde de tokens es escaso.
|
|
34
|
+
//
|
|
35
|
+
// Si el detalle ya se pagó antes (flujo natural: obtener_detalle_compra
|
|
36
|
+
// y luego preguntar por la OC), se aprovecha y la respuesta va completa
|
|
37
|
+
// sin costo. Si no, se responde igual con la explicación y la ficha.
|
|
38
|
+
const detalle = client.detalleEnCache(args.codigo);
|
|
39
|
+
if (!detalle) {
|
|
40
|
+
return {
|
|
41
|
+
content: [{
|
|
42
|
+
type: 'text',
|
|
43
|
+
text: JSON.stringify({
|
|
44
|
+
codigo: args.codigo,
|
|
45
|
+
verificacion_oc: {
|
|
46
|
+
tiene_orden_compra: null,
|
|
47
|
+
motivo: 'No se consultó la API a propósito, para no gastar cuota en una respuesta que se conoce de antemano: la API de Compra Ágil no publica adjudicaciones ni órdenes de compra (0 de 45 procesos inspeccionados traían id_orden_compra, re-verificado en septiembre de 2026).',
|
|
48
|
+
como_confirmarlo: `Abre la ficha pública del proceso, que sí muestra el estado real: https://buscador.mercadopublico.cl/ficha?code=${args.codigo}`,
|
|
49
|
+
si_quieres_los_datos_del_proceso: 'Llama primero a "obtener_detalle_compra"; después esta herramienta reutiliza ese detalle sin costo adicional y te informa lo que la API sí trae.',
|
|
50
|
+
},
|
|
51
|
+
}, null, 2),
|
|
52
|
+
}],
|
|
53
|
+
};
|
|
54
|
+
}
|
|
27
55
|
const idOrdenCompra = detalle.id_orden_compra ?? detalle.orden_compra?.id_orden_compra ?? null;
|
|
28
56
|
const idOc = detalle.orden_compra?.id_oc ?? null;
|
|
29
57
|
const tieneOC = idOrdenCompra !== null && idOrdenCompra !== undefined;
|
|
@@ -45,7 +73,7 @@ export function registerVerificarOC(server, client) {
|
|
|
45
73
|
}
|
|
46
74
|
}
|
|
47
75
|
catch (e) {
|
|
48
|
-
logger.warn(`No se pudo obtener el detalle de la OC ${idOrdenCompra} desde la API: ${
|
|
76
|
+
logger.warn(`No se pudo obtener el detalle de la OC ${idOrdenCompra} desde la API: ${safeError(e)}`);
|
|
49
77
|
}
|
|
50
78
|
}
|
|
51
79
|
const result = {
|
|
@@ -62,10 +90,10 @@ export function registerVerificarOC(server, client) {
|
|
|
62
90
|
detalle_orden: detalleOCInfo,
|
|
63
91
|
nota: tieneOC
|
|
64
92
|
? `La OC fue emitida. Código: ${detalleOCInfo?.codigo_oc ?? 'Desconocido'}. Usa la herramienta obtener_detalle_orden_compra para profundizar.`
|
|
65
|
-
:
|
|
93
|
+
: `La API no reporta Orden de Compra para este proceso (id_orden_compra = null). ⚠ Ojo: esto NO prueba que la OC no exista. Se verificó que la API de Compra Ágil no está publicando adjudicaciones (45 procesos inspeccionados, 0 con id_orden_compra). Para confirmarlo consulta la ficha pública: https://buscador.mercadopublico.cl/ficha?code=${detalle.codigo}`,
|
|
66
94
|
},
|
|
67
95
|
proveedor_seleccionado: detalle.proveedores_cotizando
|
|
68
|
-
.filter(
|
|
96
|
+
.filter(esGanador)
|
|
69
97
|
.map((p) => ({
|
|
70
98
|
rut: p.rut_proveedor,
|
|
71
99
|
razon_social: p.razon_social,
|
|
@@ -83,7 +111,7 @@ export function registerVerificarOC(server, client) {
|
|
|
83
111
|
catch (error) {
|
|
84
112
|
const message = error instanceof CompraAgilApiError
|
|
85
113
|
? error.actionableMessage
|
|
86
|
-
: `Error inesperado: ${
|
|
114
|
+
: `Error inesperado: ${safeError(error)}`;
|
|
87
115
|
return {
|
|
88
116
|
content: [{ type: 'text', text: message }],
|
|
89
117
|
isError: true,
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"verificar-oc.js","sourceRoot":"","sources":["../../src/tools/verificar-oc.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAEH,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAGxB,OAAO,EAAE,kBAAkB,EAAE,MAAM,2BAA2B,CAAC;AAC/D,OAAO,EAAE,MAAM,EAAE,MAAM,oBAAoB,CAAC;
|
|
1
|
+
{"version":3,"file":"verificar-oc.js","sourceRoot":"","sources":["../../src/tools/verificar-oc.ts"],"names":[],"mappings":"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"}
|