@ssolis-ti/mcp-compra-agil 2.1.0 → 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 +3 -2
- package/dist/api/compra-agil-client.d.ts +35 -1
- package/dist/api/compra-agil-client.d.ts.map +1 -1
- package/dist/api/compra-agil-client.js +69 -4
- package/dist/api/compra-agil-client.js.map +1 -1
- package/dist/index.js +1 -1
- package/dist/index.js.map +1 -1
- package/dist/services/monitor.js +1 -1
- package/dist/services/monitor.js.map +1 -1
- package/dist/tools/analizar-precios-mercado.js +2 -2
- package/dist/tools/auditar-desiertas.js +2 -2
- package/dist/tools/detalle-oc.d.ts.map +1 -1
- package/dist/tools/detalle-oc.js +2 -3
- package/dist/tools/detalle-oc.js.map +1 -1
- package/dist/tools/documentos.d.ts.map +1 -1
- package/dist/tools/documentos.js +68 -37
- 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 +96 -78
- package/dist/tools/generar-borrador.js.map +1 -1
- package/dist/tools/verificar-oc.d.ts.map +1 -1
- package/dist/tools/verificar-oc.js +30 -4
- package/dist/tools/verificar-oc.js.map +1 -1
- 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/error-handler.d.ts.map +1 -1
- package/dist/utils/error-handler.js +4 -6
- package/dist/utils/error-handler.js.map +1 -1
- package/dist/utils/rate-limiter.d.ts +37 -2
- package/dist/utils/rate-limiter.d.ts.map +1 -1
- package/dist/utils/rate-limiter.js +101 -13
- package/dist/utils/rate-limiter.js.map +1 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -75,7 +75,8 @@ Este servidor MCP maneja datos públicos de la API de Compra Ágil de Mercado P
|
|
|
75
75
|
* **Integración del Detalle de OC:** Resuelve de forma dinámica el código alfanumérico o ID numérico de las Órdenes de Compra utilizando la API legada de Mercado Público.
|
|
76
76
|
* **Validado contra la API real:** El comportamiento documentado por ChileCompra difiere del real en varios puntos. Este servidor implementa lo que la API **hace**, no lo que promete, y lo documenta en [Limitaciones conocidas](#-limitaciones-conocidas-de-la-api). Hay tests de regresión que blindan cada hallazgo.
|
|
77
77
|
* **Redacción de credenciales:** Todo texto que sale del proceso (logs, errores, respuestas) pasa por un punto único de redacción que borra el ticket. Es relevante porque `sendLoggingMessage` envía los logs al cliente MCP — es decir, al contexto del modelo y a la transcripción.
|
|
78
|
-
* **Rate Limiting Local:** Throttle proactivo que espacia las solicitudes bajo un máximo por minuto **antes** de enviarlas, además de reaccionar al error 429 para evitar la inhabilitación temporal del ticket.
|
|
78
|
+
* **Rate Limiting Local:** Throttle proactivo que espacia las solicitudes bajo un máximo por minuto **antes** de enviarlas, además de reaccionar al error 429 para evitar la inhabilitación temporal del ticket. El estado de cuota persiste entre reinicios, y ante un 429 se honra el header `Retry-After` con espera creciente en vez de bloquear hasta el día siguiente: la cuota es un *token bucket* que se recarga solo (verificado: la API respondió con normalidad 13 min después de un 429).
|
|
79
|
+
* **Caché de respuestas:** Las consultas repetidas se sirven desde disco sin gastar cuota (15 min para detalles, 5 min para búsquedas). Es lo que hace viable el flujo completo de análisis: repetir `generar_borrador_cotizacion` pasó de 6 consultas y 11 s a **0 consultas y 41 ms**. El ticket nunca entra en la caché.
|
|
79
80
|
* **Informes imprimibles:** Genera documentos HTML autocontenidos con diseño de impresión real (`@page`, saltos controlados, cabeceras de tabla repetidas) en formatos **Carta, Oficio y A4**.
|
|
80
81
|
* **Logs Nativos en el Protocolo:** Inyección de la notificación `sendLoggingMessage` de MCP para registrar y depurar la actividad del servidor directamente dentro de la interfaz del cliente.
|
|
81
82
|
* **Manejo Seguro de Documentos (UUID):** Evita errores de tipo `Authentication parameters missing` al tratar con archivos adjuntos protegidos de Compra Ágil (UUIDs) redirigiendo al usuario a la ficha pública del buscador (`https://buscador.mercadopublico.cl/ficha?code={codigo}`) en lugar de entregar enlaces de descarga directa inaccesibles.
|
|
@@ -339,7 +340,7 @@ const resources = await client.listResources();
|
|
|
339
340
|
| `buscar_compras_agiles` | Busca procesos utilizando palabras clave (con filtros inteligentes locales), región (1-16), estado y ventana temporal. Parámetros `q` e `id` son excluyentes. |
|
|
340
341
|
| `obtener_detalle_compra` | Detalle exhaustivo de una cotización: descripción, ítems y cotizaciones recibidas (confidenciales hasta el estado *Cerrada*). |
|
|
341
342
|
| `monitorear_cambios_recientes` | Sincronización reactiva e incremental por ventana de cambios, con soporte para paginación. Dos modos excluyentes: **relativo** (`minutos`, máx 1440 / 24 h) o **absoluto** (`cambio_desde`/`cambio_hasta` en ISO-8601, sin techo de 24 h) para resincronizar un período arbitrario. |
|
|
342
|
-
| `verificar_orden_compra` |
|
|
343
|
+
| `verificar_orden_compra` | Informa si un proceso tiene OC emitida. **No consulta la API por su cuenta** (gastaba cuota para responder siempre "no puedo saberlo"): reutiliza el detalle si ya está en caché e indica cómo confirmarlo en la ficha pública — ver [Limitaciones](#-limitaciones-conocidas-de-la-api). |
|
|
343
344
|
| `obtener_detalle_orden_compra` | Consulta detallada del desglose de productos y facturación de una OC utilizando su código alfanumérico o ID numérico. |
|
|
344
345
|
| `obtener_estadisticas_uso` | Retorna las estadísticas del limitador de solicitudes local (`requestsToday`, `isLimited`) para optimizar el consumo de la cuota del ticket. |
|
|
345
346
|
| `verificar_ticket` | Comprueba que el ticket configurado funcione contra la API real **sin revelar su valor** (solo muestra `••••1234`). Primer diagnóstico recomendado. |
|
|
@@ -226,15 +226,49 @@ export interface CompraAgilDetalle {
|
|
|
226
226
|
considera_requisitos_impacto_social_economico: boolean;
|
|
227
227
|
};
|
|
228
228
|
}
|
|
229
|
+
/** Archivo donde se reutilizan respuestas entre reinicios del servidor. */
|
|
230
|
+
export declare const RUTA_CACHE_POR_DEFECTO: string;
|
|
229
231
|
export declare class CompraAgilClient {
|
|
230
232
|
private readonly baseUrl;
|
|
231
233
|
private readonly ticket;
|
|
232
234
|
private readonly rateLimiter;
|
|
233
|
-
|
|
235
|
+
private readonly cache;
|
|
236
|
+
/**
|
|
237
|
+
* @param opciones.persistir Rutas en disco para la cuota y la caché.
|
|
238
|
+
*
|
|
239
|
+
* ⚠ La persistencia es OPT-IN y por defecto está apagada: quien decide
|
|
240
|
+
* escribir en disco es el punto de entrada (`index.ts`, `monitor.ts`), no
|
|
241
|
+
* la librería. Si el cliente persistiera siempre, los tests compartirían
|
|
242
|
+
* el archivo real del proyecto y dejarían de ser herméticos —una entrada
|
|
243
|
+
* en caché de una corrida anterior hacía que `fetch` no se llamara y el
|
|
244
|
+
* test que vigila que el ticket viaje por header fallaba sin que hubiera
|
|
245
|
+
* nada roto—.
|
|
246
|
+
*/
|
|
247
|
+
constructor(ticket: string, baseUrl?: string, opciones?: {
|
|
248
|
+
persistir?: boolean;
|
|
249
|
+
});
|
|
234
250
|
/**
|
|
235
251
|
* Realiza un GET autenticado a la API.
|
|
236
252
|
*/
|
|
237
253
|
private request;
|
|
254
|
+
/**
|
|
255
|
+
* Devuelve el detalle SOLO si ya está en caché; nunca sale a la red.
|
|
256
|
+
*
|
|
257
|
+
* Permite que una herramienta enriquezca su respuesta cuando el dato ya se
|
|
258
|
+
* pagó, sin gastar cuota si no lo está. Lo usa `verificar_orden_compra`,
|
|
259
|
+
* que de otro modo consumiría una consulta para responder algo que la API
|
|
260
|
+
* estructuralmente no publica.
|
|
261
|
+
*/
|
|
262
|
+
detalleEnCache(codigo: string): CompraAgilDetalle | undefined;
|
|
263
|
+
/** Estadísticas de reutilización de respuestas (cuánta cuota se ahorró). */
|
|
264
|
+
getCacheStats(): {
|
|
265
|
+
entradas: number;
|
|
266
|
+
aciertos: number;
|
|
267
|
+
fallos: number;
|
|
268
|
+
ahorroPorcentaje: number;
|
|
269
|
+
};
|
|
270
|
+
/** Descarta las respuestas guardadas y fuerza consultas frescas. */
|
|
271
|
+
limpiarCache(): void;
|
|
238
272
|
/**
|
|
239
273
|
* Buscar Compras Ágiles con filtros y paginación.
|
|
240
274
|
*/
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"compra-agil-client.d.ts","sourceRoot":"","sources":["../../src/api/compra-agil-client.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;
|
|
1
|
+
{"version":3,"file":"compra-agil-client.d.ts","sourceRoot":"","sources":["../../src/api/compra-agil-client.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAWH,MAAM,WAAW,YAAY;IAE3B,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,YAAY,CAAC,EAAE,MAAM,CAAC;IAEtB,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,eAAe,CAAC,EAAE,MAAM,CAAC;IAEzB,MAAM,CAAC,EAAE,MAAM,CAAC;IAEhB,MAAM,CAAC,EAAE,MAAM,CAAC;IAEhB,EAAE,CAAC,EAAE,MAAM,CAAC;IACZ,CAAC,CAAC,EAAE,MAAM,CAAC;IAEX,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,aAAa,CAAC,EAAE,MAAM,CAAC;IAEvB,WAAW,CAAC,EAAE,MAAM,CAAC;CACtB;AAED,MAAM,WAAW,UAAU;IACzB,aAAa,EAAE,MAAM,CAAC;IACtB,aAAa,EAAE,MAAM,CAAC;IACtB,aAAa,EAAE,MAAM,CAAC;IACtB,gBAAgB,EAAE,MAAM,CAAC;CAC1B;AAED,MAAM,WAAW,cAAc;IAC7B,MAAM,EAAE,MAAM,CAAC;IACf,MAAM,EAAE,MAAM,CAAC;IACf,MAAM,EAAE;QAAE,SAAS,EAAE,MAAM,CAAC;QAAC,MAAM,EAAE,MAAM,CAAC;QAAC,KAAK,EAAE,MAAM,CAAA;KAAE,CAAC;IAC7D,YAAY,EAAE;QAAE,mBAAmB,EAAE,MAAM,CAAC;QAAC,WAAW,EAAE,MAAM,CAAA;KAAE,CAAC;IACnE,UAAU,EAAE,KAAK,CAAC;QAAE,EAAE,EAAE,MAAM,CAAC;QAAC,MAAM,EAAE,MAAM,CAAA;KAAE,CAAC,CAAC;IAClD,MAAM,EAAE;QACN,iBAAiB,EAAE,MAAM,CAAC;QAC1B,YAAY,EAAE,MAAM,CAAC;QACrB,mBAAmB,EAAE,MAAM,CAAC;QAC5B,iBAAiB,EAAE,MAAM,GAAG,IAAI,CAAC;KAClC,CAAC;IACF,MAAM,EAAE;QACN,MAAM,EAAE,MAAM,CAAC;QACf,gBAAgB,EAAE,MAAM,CAAC;QACzB,oBAAoB,EAAE,MAAM,CAAC;KAC9B,CAAC;IACF,WAAW,EAAE;QACX,mBAAmB,EAAE,MAAM,CAAC;QAC5B,GAAG,EAAE,MAAM,CAAC;QACZ,aAAa,EAAE,MAAM,CAAC;QACtB,MAAM,EAAE,MAAM,GAAG,IAAI,CAAC;QACtB,aAAa,EAAE,MAAM,GAAG,IAAI,CAAC;KAC9B,CAAC;IACF,OAAO,EAAE;QAAE,uBAAuB,EAAE,MAAM,CAAA;KAAE,CAAC;IAC7C,OAAO,EAAE;QACP,kBAAkB,EAAE,MAAM,GAAG,IAAI,CAAC;QAClC,eAAe,EAAE,MAAM,GAAG,IAAI,CAAC;QAC/B,gBAAgB,EAAE,MAAM,GAAG,IAAI,CAAC;KACjC,CAAC;IACF,KAAK,EAAE;QAAE,OAAO,EAAE,MAAM,CAAA;KAAE,CAAC;CAC5B;AAED,MAAM,WAAW,cAAc;IAC7B,KAAK,EAAE,cAAc,EAAE,CAAC;IACxB,UAAU,EAAE,UAAU,CAAC;CACxB;AAED,MAAM,WAAW,kBAAkB;IACjC,MAAM,EAAE,MAAM,CAAC;IACf,MAAM,EAAE,MAAM,CAAC;IACf,YAAY,EAAE,MAAM,CAAC;IACrB,MAAM,EAAE,MAAM,CAAC;IACf,gBAAgB,EAAE,MAAM,GAAG,IAAI,CAAC;IAChC,WAAW,EAAE,MAAM,GAAG,IAAI,CAAC;IAC3B,aAAa,EAAE,MAAM,CAAC;IACtB,eAAe,EAAE,MAAM,GAAG,IAAI,CAAC;IAC/B,SAAS,EAAE,MAAM,CAAC;IAClB,SAAS,EAAE,MAAM,CAAC;IAClB,KAAK,EAAE,MAAM,CAAC;IACd,SAAS,EAAE;QACT,eAAe,EAAE,MAAM,CAAC;QACxB,YAAY,EAAE,MAAM,CAAC;QACrB,aAAa,EAAE,MAAM,CAAC;KACvB,CAAC;IACF,SAAS,EAAE;QACT,MAAM,EAAE,MAAM,CAAC;QACf,GAAG,EAAE,MAAM,CAAC;KACb,CAAC;IACF,KAAK,EAAE;QACL,OAAO,EAAE,KAAK,CAAC;YACb,QAAQ,EAAE,MAAM,CAAC;YACjB,QAAQ,EAAE,MAAM,CAAC;YACjB,UAAU,EAAE,MAAM,CAAC;YAEnB,SAAS,CAAC,EAAE,MAAM,CAAC;YACnB,UAAU,CAAC,EAAE,MAAM,CAAC;SACrB,CAAC,CAAC;KACJ,CAAC;CACH;AAED,MAAM,WAAW,mBAAmB;IAClC,QAAQ,EAAE,MAAM,CAAC;IACjB,OAAO,EAAE,kBAAkB,EAAE,CAAC;CAC/B;AAED,MAAM,WAAW,kBAAkB;IACjC,eAAe,EAAE,MAAM,GAAG,MAAM,CAAC;IACjC,MAAM,EAAE,MAAM,CAAC;IACf,WAAW,EAAE,MAAM,GAAG,IAAI,CAAC;IAC3B,QAAQ,EAAE,MAAM,CAAC;IACjB,aAAa,EAAE,MAAM,CAAC;CACvB;AAED,MAAM,WAAW,gBAAgB;IAC/B,eAAe,EAAE,MAAM,GAAG,MAAM,CAAC;IACjC,eAAe,EAAE,MAAM,CAAC;IACxB,WAAW,EAAE,MAAM,GAAG,IAAI,CAAC;IAC3B,QAAQ,EAAE,MAAM,CAAC;IACjB,eAAe,EAAE,MAAM,GAAG,IAAI,CAAC;IAC/B,oBAAoB,EAAE,MAAM,GAAG,IAAI,CAAC;CACrC;AAED,MAAM,WAAW,kBAAkB;IACjC,aAAa,EAAE,MAAM,CAAC;IACtB,YAAY,EAAE,MAAM,CAAC;IACrB,MAAM,EAAE,OAAO,CAAC;IAChB,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,uBAAuB,CAAC,EAAE,MAAM,CAAC;IACjC,iBAAiB,CAAC,EAAE;QAAE,EAAE,EAAE,MAAM,CAAC;QAAC,KAAK,EAAE,MAAM,CAAA;KAAE,CAAC;IAClD,oBAAoB,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IACrC,MAAM,CAAC,EAAE,OAAO,CAAC;IACjB,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,cAAc,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAC/B,UAAU,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAC3B,cAAc,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAC/B,cAAc,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAC/B,WAAW,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAC5B,eAAe,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAChC,mBAAmB,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IACpC,sBAAsB,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IACvC,WAAW,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAC5B,6BAA6B,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAC9C,sBAAsB,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC;IAC1C,SAAS,CAAC,EAAE;QACV,sBAAsB,EAAE,OAAO,CAAC;QAChC,gBAAgB,EAAE,MAAM,GAAG,IAAI,CAAC;QAChC,kBAAkB,EAAE,MAAM,GAAG,IAAI,CAAC;KACnC,CAAC;IACF,mBAAmB,CAAC,EAAE,gBAAgB,EAAE,CAAC;CAC1C;AAED,MAAM,WAAW,iBAAiB;IAChC,MAAM,EAAE,MAAM,CAAC;IACf,MAAM,EAAE,MAAM,CAAC;IACf,WAAW,EAAE,MAAM,CAAC;IAEpB,eAAe,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAChC,MAAM,EAAE;QAAE,SAAS,EAAE,MAAM,CAAC;QAAC,MAAM,EAAE,MAAM,CAAC;QAAC,KAAK,EAAE,MAAM,CAAA;KAAE,CAAC;IAC7D,YAAY,EAAE;QACZ,mBAAmB,EAAE,MAAM,CAAC;QAC5B,WAAW,EAAE,MAAM,CAAC;QACpB,2BAA2B,EAAE,MAAM,GAAG,IAAI,CAAC;QAC3C,4BAA4B,EAAE,MAAM,GAAG,IAAI,CAAC;KAC7C,CAAC;IACF,MAAM,EAAE;QACN,iBAAiB,EAAE,MAAM,CAAC;QAC1B,YAAY,EAAE,MAAM,CAAC;QACrB,mBAAmB,EAAE,MAAM,CAAC;QAC5B,iBAAiB,EAAE,MAAM,GAAG,IAAI,CAAC;KAClC,CAAC;IACF,OAAO,EAAE;QACP,iBAAiB,EAAE,MAAM,CAAC;QAC1B,kBAAkB,EAAE,MAAM,GAAG,IAAI,CAAC;KACnC,CAAC;IACF,UAAU,EAAE,KAAK,CAAC;QAAE,EAAE,EAAE,MAAM,CAAC;QAAC,MAAM,EAAE,MAAM,CAAA;KAAE,CAAC,CAAC;IAClD,WAAW,EAAE;QACX,gBAAgB,EAAE,MAAM,CAAC;QACzB,MAAM,EAAE,MAAM,CAAC;QACf,oBAAoB,EAAE,MAAM,GAAG,IAAI,CAAC;QACpC,gBAAgB,EAAE,MAAM,GAAG,IAAI,CAAC;QAChC,oBAAoB,EAAE,MAAM,GAAG,IAAI,CAAC;QACpC,mBAAmB,EAAE,MAAM,GAAG,IAAI,CAAC;QACnC,mBAAmB,EAAE,MAAM,GAAG,IAAI,CAAC;KACpC,CAAC;IAEF,YAAY,CAAC,EAAE;QACb,eAAe,EAAE,MAAM,GAAG,IAAI,CAAC;QAC/B,KAAK,EAAE,MAAM,GAAG,IAAI,CAAC;QACrB,mBAAmB,EAAE,MAAM,GAAG,IAAI,CAAC;QACnC,mBAAmB,EAAE,MAAM,GAAG,IAAI,CAAC;KACpC,CAAC;IACF,WAAW,EAAE;QACX,mBAAmB,EAAE,MAAM,CAAC;QAC5B,GAAG,EAAE,MAAM,CAAC;QACZ,aAAa,EAAE,MAAM,CAAC;QACtB,MAAM,EAAE,MAAM,GAAG,IAAI,CAAC;QACtB,aAAa,EAAE,MAAM,GAAG,IAAI,CAAC;KAC9B,CAAC;IACF,qBAAqB,EAAE,kBAAkB,EAAE,CAAC;IAC5C,qBAAqB,EAAE,kBAAkB,EAAE,CAAC;IAC5C,OAAO,EAAE;QACP,aAAa,EAAE,MAAM,GAAG,IAAI,CAAC;QAC7B,uBAAuB,EAAE,MAAM,CAAC;QAChC,cAAc,EAAE,MAAM,CAAC;KACxB,CAAC;IACF,OAAO,EAAE;QACP,kBAAkB,EAAE,MAAM,GAAG,IAAI,CAAC;QAClC,eAAe,EAAE,MAAM,GAAG,IAAI,CAAC;KAChC,CAAC;IACF,KAAK,EAAE;QACL,qCAAqC,EAAE,OAAO,CAAC;QAC/C,6CAA6C,EAAE,OAAO,CAAC;KACxD,CAAC;CACH;AAID,2EAA2E;AAC3E,eAAO,MAAM,sBAAsB,QAAiD,CAAC;AAarF,qBAAa,gBAAgB;IAC3B,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAS;IACjC,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAS;IAChC,OAAO,CAAC,QAAQ,CAAC,WAAW,CAAc;IAC1C,OAAO,CAAC,QAAQ,CAAC,KAAK,CAAgB;IAEtC;;;;;;;;;;OAUG;gBAED,MAAM,EAAE,MAAM,EACd,OAAO,CAAC,EAAE,MAAM,EAChB,QAAQ,GAAE;QAAE,SAAS,CAAC,EAAE,OAAO,CAAA;KAAO;IAcxC;;OAEG;YACW,OAAO;IAqErB;;;;;;;OAOG;IACH,cAAc,CAAC,MAAM,EAAE,MAAM,GAAG,iBAAiB,GAAG,SAAS;IAK7D,4EAA4E;IAC5E,aAAa;;;;;;IAIb,oEAAoE;IACpE,YAAY,IAAI,IAAI;IAIpB;;OAEG;IACG,MAAM,CAAC,MAAM,EAAE,YAAY,GAAG,OAAO,CAAC,cAAc,CAAC;IAmB3D;;;OAGG;IACG,UAAU,CAAC,MAAM,EAAE,YAAY,EAAE,QAAQ,SAAK,GAAG,OAAO,CAAC,cAAc,EAAE,CAAC;IA0BhF;;OAEG;IACG,OAAO,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,iBAAiB,CAAC;IAIzD;;OAEG;IACG,gBAAgB,CAAC,KAAK,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,OAAO,CAAC,YAAY,CAAC,GAAG,OAAO,CAAC,cAAc,CAAC;IAO/F;;OAEG;IACH,iBAAiB;;;;;IAIjB;;;OAGG;IACG,gBAAgB,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,GAAG,OAAO,CAAC,mBAAmB,CAAC;CAK5E"}
|
|
@@ -8,17 +8,47 @@
|
|
|
8
8
|
*/
|
|
9
9
|
import { logger } from '../utils/logger.js';
|
|
10
10
|
import { handleApiResponse, CompraAgilApiError } from '../utils/error-handler.js';
|
|
11
|
-
import { RateLimiter } from '../utils/rate-limiter.js';
|
|
11
|
+
import { RateLimiter, RUTA_ESTADO_POR_DEFECTO } from '../utils/rate-limiter.js';
|
|
12
|
+
import { ResponseCache } from '../utils/cache.js';
|
|
13
|
+
import path from 'path';
|
|
12
14
|
import { registrarSecreto } from '../utils/redact.js';
|
|
13
15
|
// ─── Cliente ────────────────────────────────────────────────────────
|
|
16
|
+
/** Archivo donde se reutilizan respuestas entre reinicios del servidor. */
|
|
17
|
+
export const RUTA_CACHE_POR_DEFECTO = path.resolve(process.cwd(), '.api-cache.json');
|
|
18
|
+
/**
|
|
19
|
+
* Vigencia por tipo de consulta, en segundos.
|
|
20
|
+
*
|
|
21
|
+
* El detalle vive más que la búsqueda porque es lo que más se repite: las
|
|
22
|
+
* herramientas de análisis piden el detalle de los mismos procesos históricos
|
|
23
|
+
* una y otra vez, y un proceso ya cerrado o desierto no cambia. La búsqueda
|
|
24
|
+
* caduca antes porque sí aparecen procesos nuevos durante el día.
|
|
25
|
+
*/
|
|
26
|
+
const TTL_DETALLE_SEG = 15 * 60;
|
|
27
|
+
const TTL_BUSQUEDA_SEG = 5 * 60;
|
|
14
28
|
export class CompraAgilClient {
|
|
15
29
|
baseUrl;
|
|
16
30
|
ticket;
|
|
17
31
|
rateLimiter;
|
|
18
|
-
|
|
32
|
+
cache;
|
|
33
|
+
/**
|
|
34
|
+
* @param opciones.persistir Rutas en disco para la cuota y la caché.
|
|
35
|
+
*
|
|
36
|
+
* ⚠ La persistencia es OPT-IN y por defecto está apagada: quien decide
|
|
37
|
+
* escribir en disco es el punto de entrada (`index.ts`, `monitor.ts`), no
|
|
38
|
+
* la librería. Si el cliente persistiera siempre, los tests compartirían
|
|
39
|
+
* el archivo real del proyecto y dejarían de ser herméticos —una entrada
|
|
40
|
+
* en caché de una corrida anterior hacía que `fetch` no se llamara y el
|
|
41
|
+
* test que vigila que el ticket viaje por header fallaba sin que hubiera
|
|
42
|
+
* nada roto—.
|
|
43
|
+
*/
|
|
44
|
+
constructor(ticket, baseUrl, opciones = {}) {
|
|
19
45
|
this.ticket = ticket;
|
|
20
46
|
this.baseUrl = baseUrl || 'https://api2.mercadopublico.cl';
|
|
21
|
-
|
|
47
|
+
const persistir = opciones.persistir === true;
|
|
48
|
+
// Con persistencia: la cuota es del ticket y del día, no del proceso, así
|
|
49
|
+
// que reiniciar el servidor no debe borrar la memoria de un 429.
|
|
50
|
+
this.rateLimiter = new RateLimiter(15, persistir ? RUTA_ESTADO_POR_DEFECTO : null);
|
|
51
|
+
this.cache = new ResponseCache({ rutaEstado: persistir ? RUTA_CACHE_POR_DEFECTO : null });
|
|
22
52
|
// El cliente se auto-protege: cualquier consumidor (servidor MCP, daemon,
|
|
23
53
|
// scripts, tests) queda cubierto sin tener que acordarse de registrarlo.
|
|
24
54
|
registrarSecreto(ticket);
|
|
@@ -27,6 +57,15 @@ export class CompraAgilClient {
|
|
|
27
57
|
* Realiza un GET autenticado a la API.
|
|
28
58
|
*/
|
|
29
59
|
async request(path, params) {
|
|
60
|
+
// Una respuesta vigente en caché ahorra la consulta entera: ni cuota, ni
|
|
61
|
+
// espera, ni riesgo de 429. Se comprueba antes que el rate limit, para que
|
|
62
|
+
// un ticket temporalmente limitado igual pueda servir lo ya conocido.
|
|
63
|
+
const claveCache = ResponseCache.clave(path, params);
|
|
64
|
+
const enCache = this.cache.obtener(claveCache);
|
|
65
|
+
if (enCache !== undefined) {
|
|
66
|
+
logger.debug(`Caché: acierto para ${claveCache}`);
|
|
67
|
+
return enCache;
|
|
68
|
+
}
|
|
30
69
|
// Verificar rate limit diario antes de enviar
|
|
31
70
|
const limitCheck = this.rateLimiter.checkLimit();
|
|
32
71
|
if (limitCheck.limited) {
|
|
@@ -63,14 +102,40 @@ export class CompraAgilClient {
|
|
|
63
102
|
},
|
|
64
103
|
});
|
|
65
104
|
if (response.status === 429) {
|
|
66
|
-
|
|
105
|
+
// La guía (§7) indica esperar lo que diga Retry-After; si no viene, el
|
|
106
|
+
// limitador aplica su propia espera progresiva.
|
|
107
|
+
const retryAfter = Number(response.headers?.get?.('retry-after'));
|
|
108
|
+
this.rateLimiter.markLimited(Number.isFinite(retryAfter) && retryAfter > 0 ? retryAfter : undefined);
|
|
67
109
|
}
|
|
68
110
|
else {
|
|
69
111
|
this.rateLimiter.recordRequest();
|
|
70
112
|
}
|
|
71
113
|
const payload = await handleApiResponse(response);
|
|
114
|
+
// Solo se guardan respuestas exitosas: un error no debe quedar congelado.
|
|
115
|
+
const ttl = path.includes('/compra-agil/') ? TTL_DETALLE_SEG : TTL_BUSQUEDA_SEG;
|
|
116
|
+
this.cache.guardar(claveCache, payload, ttl);
|
|
72
117
|
return payload;
|
|
73
118
|
}
|
|
119
|
+
/**
|
|
120
|
+
* Devuelve el detalle SOLO si ya está en caché; nunca sale a la red.
|
|
121
|
+
*
|
|
122
|
+
* Permite que una herramienta enriquezca su respuesta cuando el dato ya se
|
|
123
|
+
* pagó, sin gastar cuota si no lo está. Lo usa `verificar_orden_compra`,
|
|
124
|
+
* que de otro modo consumiría una consulta para responder algo que la API
|
|
125
|
+
* estructuralmente no publica.
|
|
126
|
+
*/
|
|
127
|
+
detalleEnCache(codigo) {
|
|
128
|
+
const clave = ResponseCache.clave(`/v2/compra-agil/${encodeURIComponent(codigo)}`);
|
|
129
|
+
return this.cache.obtener(clave);
|
|
130
|
+
}
|
|
131
|
+
/** Estadísticas de reutilización de respuestas (cuánta cuota se ahorró). */
|
|
132
|
+
getCacheStats() {
|
|
133
|
+
return this.cache.estadisticas();
|
|
134
|
+
}
|
|
135
|
+
/** Descarta las respuestas guardadas y fuerza consultas frescas. */
|
|
136
|
+
limpiarCache() {
|
|
137
|
+
this.cache.limpiar();
|
|
138
|
+
}
|
|
74
139
|
/**
|
|
75
140
|
* Buscar Compras Ágiles con filtros y paginación.
|
|
76
141
|
*/
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"compra-agil-client.js","sourceRoot":"","sources":["../../src/api/compra-agil-client.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAEH,OAAO,EAAE,MAAM,EAAE,MAAM,oBAAoB,CAAC;AAC5C,OAAO,EAAE,iBAAiB,EAAE,kBAAkB,EAAE,MAAM,2BAA2B,CAAC;AAClF,OAAO,EAAE,WAAW,EAAE,MAAM,0BAA0B,CAAC;
|
|
1
|
+
{"version":3,"file":"compra-agil-client.js","sourceRoot":"","sources":["../../src/api/compra-agil-client.ts"],"names":[],"mappings":"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"}
|
package/dist/index.js
CHANGED
|
@@ -60,7 +60,7 @@ const VALID_TICKET = TICKET;
|
|
|
60
60
|
async function main() {
|
|
61
61
|
logger.info('Iniciando servidor MCP Compra Ágil v2...');
|
|
62
62
|
// 1. Crear cliente HTTP para la API de Mercado Público
|
|
63
|
-
const client = new CompraAgilClient(VALID_TICKET, BASE_URL);
|
|
63
|
+
const client = new CompraAgilClient(VALID_TICKET, BASE_URL, { persistir: true });
|
|
64
64
|
logger.info(`Cliente API configurado → ${BASE_URL}`);
|
|
65
65
|
// 2. Crear servidor MCP
|
|
66
66
|
const server = new McpServer({
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";AAEA,OAAO,EAAE,aAAa,EAAE,MAAM,uBAAuB,CAAC;AACtD,oEAAoE;AACpE,aAAa,EAAE,CAAC;AAEhB;;;;;;;;GAQG;AAEH,OAAO,EAAE,SAAS,EAAE,MAAM,yCAAyC,CAAC;AACpE,OAAO,EAAE,oBAAoB,EAAE,MAAM,2CAA2C,CAAC;AACjF,OAAO,EAAE,aAAa,EAAE,MAAM,QAAQ,CAAC;AAEvC,MAAM,OAAO,GAAG,aAAa,CAAC,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;AAC/C,MAAM,EAAE,OAAO,EAAE,WAAW,EAAE,GAAG,OAAO,CAAC,iBAAiB,CAAwB,CAAC;AAEnF,OAAO,EAAE,gBAAgB,EAAE,MAAM,6BAA6B,CAAC;AAC/D,OAAO,EAAE,MAAM,EAAE,YAAY,EAAE,MAAM,mBAAmB,CAAC;AACzD,OAAO,EAAE,gBAAgB,EAAS,MAAM,mBAAmB,CAAC;AAE5D,QAAQ;AACR,OAAO,EAAE,qBAAqB,EAAE,MAAM,2BAA2B,CAAC;AAClE,OAAO,EAAE,qBAAqB,EAAE,MAAM,2BAA2B,CAAC;AAClE,OAAO,EAAE,yBAAyB,EAAE,MAAM,+BAA+B,CAAC;AAC1E,OAAO,EAAE,mBAAmB,EAAE,MAAM,yBAAyB,CAAC;AAC9D,OAAO,EAAE,uBAAuB,EAAE,MAAM,6BAA6B,CAAC;AACtE,OAAO,EAAE,iBAAiB,EAAE,MAAM,uBAAuB,CAAC;AAC1D,OAAO,EAAE,uBAAuB,EAAE,MAAM,uBAAuB,CAAC;AAChE,OAAO,EAAE,8BAA8B,EAAE,MAAM,qCAAqC,CAAC;AACrF,OAAO,EAAE,wBAAwB,EAAE,MAAM,8BAA8B,CAAC;AACxE,OAAO,EAAE,uBAAuB,EAAE,MAAM,6BAA6B,CAAC;AACtE,OAAO,EAAE,0BAA0B,EAAE,MAAM,gCAAgC,CAAC;AAC5E,OAAO,EAAE,sBAAsB,EAAE,MAAM,4BAA4B,CAAC;AACpE,OAAO,EAAE,uBAAuB,EAAE,MAAM,6BAA6B,CAAC;AAEtE,YAAY;AACZ,OAAO,EAAE,wBAAwB,EAAE,MAAM,yBAAyB,CAAC;AACnE,OAAO,EAAE,uBAAuB,EAAE,MAAM,wBAAwB,CAAC;AACjE,OAAO,EAAE,wBAAwB,EAAE,MAAM,yBAAyB,CAAC;AACnE,OAAO,EAAE,+BAA+B,EAAE,MAAM,iCAAiC,CAAC;AAClF,OAAO,EAAE,6BAA6B,EAAE,MAAM,8BAA8B,CAAC;AAE7E,UAAU;AACV,OAAO,EAAE,iCAAiC,EAAE,MAAM,mCAAmC,CAAC;AACtF,OAAO,EAAE,iCAAiC,EAAE,MAAM,mCAAmC,CAAC;AAEtF,uEAAuE;AAEvE,MAAM,MAAM,GAAG,OAAO,CAAC,GAAG,CAAC,kBAAkB,CAAC;AAC9C,MAAM,QAAQ,GAAG,OAAO,CAAC,GAAG,CAAC,oBAAoB,IAAI,gCAAgC,CAAC;AAEtF,iFAAiF;AACjF,gFAAgF;AAChF,iDAAiD;AACjD,gBAAgB,CAAC,MAAM,CAAC,CAAC;AAEzB,IAAI,CAAC,MAAM,EAAE,CAAC;IACZ,MAAM,CAAC,KAAK,CACV,yDAAyD;QACzD,gGAAgG,CACjG,CAAC;IACF,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;AAClB,CAAC;AAED,sEAAsE;AACtE,MAAM,YAAY,GAAW,MAAM,CAAC;AAEpC,uEAAuE;AAEvE,KAAK,UAAU,IAAI;IACjB,MAAM,CAAC,IAAI,CAAC,0CAA0C,CAAC,CAAC;IAExD,uDAAuD;IACvD,MAAM,MAAM,GAAG,IAAI,gBAAgB,CAAC,YAAY,EAAE,QAAQ,CAAC,CAAC;
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
|
package/dist/services/monitor.js
CHANGED
|
@@ -60,7 +60,7 @@ console.log(`Presupuesto mínimo : $${MIN_BUDGET.toLocaleString('es-CL')} C
|
|
|
60
60
|
console.log(`Palabras clave a buscar: ${KEYWORDS.join(', ')}`);
|
|
61
61
|
console.log(`Destino de alertas : ${ALERTS_LOG_PATH}`);
|
|
62
62
|
console.log('========================================================');
|
|
63
|
-
const client = new CompraAgilClient(TICKET, BASE_URL);
|
|
63
|
+
const client = new CompraAgilClient(TICKET, BASE_URL, { persistir: true });
|
|
64
64
|
async function runCheck() {
|
|
65
65
|
const timestamp = new Date().toISOString();
|
|
66
66
|
console.log(`[${timestamp}] Iniciando ciclo de búsqueda de cambios...`);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"monitor.js","sourceRoot":"","sources":["../../src/services/monitor.ts"],"names":[],"mappings":"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
|
|
1
|
+
{"version":3,"file":"monitor.js","sourceRoot":"","sources":["../../src/services/monitor.ts"],"names":[],"mappings":"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"}
|
|
@@ -33,7 +33,7 @@ const inputSchema = {
|
|
|
33
33
|
codigo_compra: z.string().optional().describe('Código de una Compra Ágil para extraer sus palabras clave automáticamente (ej: "1057539-228-COT26"). Opcional si se especifica "q".'),
|
|
34
34
|
q: z.string().optional().describe('Término de búsqueda del producto/servicio a cotizar (ej: "resmas papel", "reactivos"). Opcional si se especifica "codigo_compra".'),
|
|
35
35
|
region: z.string().optional().describe('Código de región para acotar el análisis (1-16). Ej: "13" para Metropolitana.'),
|
|
36
|
-
limite_analisis: z.number().min(1).max(15).default(
|
|
36
|
+
limite_analisis: z.number().min(1).max(15).default(5).optional().describe('Cuántos procesos históricos auditar (1-15, default 5). Cada uno consume una consulta de cuota y la API es lenta (~1-5s por consulta).'),
|
|
37
37
|
};
|
|
38
38
|
export function registerAnalizarPreciosMercado(server, client) {
|
|
39
39
|
server.registerTool(TOOL_NAME, { description: TOOL_DESCRIPTION, inputSchema }, async (args) => {
|
|
@@ -86,7 +86,7 @@ export function registerAnalizarPreciosMercado(server, client) {
|
|
|
86
86
|
};
|
|
87
87
|
}
|
|
88
88
|
// 3. Recolectar cotizaciones de los detalles
|
|
89
|
-
const limite = args.limite_analisis ||
|
|
89
|
+
const limite = args.limite_analisis || 5;
|
|
90
90
|
const preciosUnitarios = [];
|
|
91
91
|
const montosNetos = [];
|
|
92
92
|
const cotizaciones = [];
|
|
@@ -11,7 +11,7 @@ También reporta el motivo oficial de deserción y las cotizaciones declaradas i
|
|
|
11
11
|
const inputSchema = {
|
|
12
12
|
codigo_compra: z.string().optional().describe('Código de la Compra Ágil desierta para auditar (ej: "1057539-228-COT26"). Opcional si se especifica "q".'),
|
|
13
13
|
q: z.string().optional().describe('Término de búsqueda de producto/servicio para encontrar y auditar un proceso desierto reciente (ej: "resmas papel"). Opcional.'),
|
|
14
|
-
limite_analisis: z.number().min(1).max(8).default(
|
|
14
|
+
limite_analisis: z.number().min(1).max(8).default(3).optional().describe('Cantidad de procesos históricos exitosos con los que comparar (1-8, default 3) para no agotar la cuota de la API.'),
|
|
15
15
|
};
|
|
16
16
|
export function registerAuditarDesiertas(server, client) {
|
|
17
17
|
server.registerTool(TOOL_NAME, {
|
|
@@ -79,7 +79,7 @@ export function registerAuditarDesiertas(server, client) {
|
|
|
79
79
|
// expone (desierta 5/8 procesos con precios; cerrada 0/8).
|
|
80
80
|
// `proveedor_seleccionado` devuelve 0 resultados.
|
|
81
81
|
logger.info(`auditar_compras_desiertas: Buscando procesos comparables para "${keyword}"`);
|
|
82
|
-
const limit = args.limite_analisis ||
|
|
82
|
+
const limit = args.limite_analisis || 3;
|
|
83
83
|
const searchResponse = await client.buscar({
|
|
84
84
|
q: keyword,
|
|
85
85
|
estado: 'desierta',
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"detalle-oc.d.ts","sourceRoot":"","sources":["../../src/tools/detalle-oc.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAGH,OAAO,EAAE,SAAS,EAAE,MAAM,yCAAyC,CAAC;AACpE,OAAO,EAAE,gBAAgB,EAAE,MAAM,8BAA8B,CAAC;
|
|
1
|
+
{"version":3,"file":"detalle-oc.d.ts","sourceRoot":"","sources":["../../src/tools/detalle-oc.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAGH,OAAO,EAAE,SAAS,EAAE,MAAM,yCAAyC,CAAC;AACpE,OAAO,EAAE,gBAAgB,EAAE,MAAM,8BAA8B,CAAC;AAehE,wBAAgB,iBAAiB,CAAC,MAAM,EAAE,SAAS,EAAE,MAAM,EAAE,gBAAgB,GAAG,IAAI,CAuEnF"}
|
package/dist/tools/detalle-oc.js
CHANGED
|
@@ -8,9 +8,8 @@ import { z } from 'zod';
|
|
|
8
8
|
import { CompraAgilApiError } from '../utils/error-handler.js';
|
|
9
9
|
import { safeError } from '../utils/redact.js';
|
|
10
10
|
const TOOL_NAME = 'obtener_detalle_orden_compra';
|
|
11
|
-
const TOOL_DESCRIPTION = `Obtiene el detalle completo de una Orden de Compra (OC) emitida en Mercado Público de Chile.
|
|
12
|
-
|
|
13
|
-
Retorna información sobre montos (neto, impuestos, total), comprador, proveedor adjudicado y el listado de productos/servicios adquiridos.`;
|
|
11
|
+
const TOOL_DESCRIPTION = `Obtiene el detalle completo de una Orden de Compra (OC) emitida en Mercado Público de Chile: montos (neto, impuestos, total), comprador, proveedor adjudicado y listado de productos adquiridos. Admite el ID numérico o el código alfanumérico externo.
|
|
12
|
+
⚠ EL CÓDIGO DEBE VENIR DE OTRA FUENTE. Consulta la API legada de Órdenes de Compra, que es independiente de la de Compra Ágil — y esta última NO entrega códigos de OC (verificado: id_orden_compra viene null en el 100% de los procesos). Úsala cuando ya tengas el código por otra vía: la OC que te emitieron como proveedor, un correo de Mercado Público o la ficha pública del proceso. No esperes obtenerlo con las demás herramientas de este servidor.`;
|
|
14
13
|
const inputSchema = {
|
|
15
14
|
codigo_oc: z.string().describe('Código alfanumérico (ej: "1057532-156-AG26") o ID numérico (ej: "54909627") de la Orden de Compra.'),
|
|
16
15
|
};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"detalle-oc.js","sourceRoot":"","sources":["../../src/tools/detalle-oc.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAGxB,OAAO,EAAE,kBAAkB,EAAE,MAAM,2BAA2B,CAAC;AAC/D,OAAO,EAAE,SAAS,EAAE,MAAM,oBAAoB,CAAC;AAE/C,MAAM,SAAS,GAAG,8BAA8B,CAAC;AAEjD,MAAM,gBAAgB,GAAG
|
|
1
|
+
{"version":3,"file":"detalle-oc.js","sourceRoot":"","sources":["../../src/tools/detalle-oc.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAGxB,OAAO,EAAE,kBAAkB,EAAE,MAAM,2BAA2B,CAAC;AAC/D,OAAO,EAAE,SAAS,EAAE,MAAM,oBAAoB,CAAC;AAE/C,MAAM,SAAS,GAAG,8BAA8B,CAAC;AAEjD,MAAM,gBAAgB,GAAG;icACwa,CAAC;AAElc,MAAM,WAAW,GAAG;IAClB,SAAS,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,CAC5B,oGAAoG,CACrG;CACF,CAAC;AAEF,MAAM,UAAU,iBAAiB,CAAC,MAAiB,EAAE,MAAwB;IAC3E,MAAM,CAAC,YAAY,CACjB,SAAS,EACT;QACE,WAAW,EAAE,gBAAgB;QAC7B,WAAW,EAAE,WAAW;KACzB,EACD,KAAK,EAAE,IAAI,EAAE,EAAE;QACb,IAAI,CAAC;YACH,MAAM,QAAQ,GAAG,MAAM,MAAM,CAAC,gBAAgB,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC;YAE/D,IAAI,CAAC,QAAQ,CAAC,OAAO,IAAI,QAAQ,CAAC,OAAO,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;gBACvD,OAAO;oBACL,OAAO,EAAE,CAAC;4BACR,IAAI,EAAE,MAAe;4BACrB,IAAI,EAAE,qEAAqE,IAAI,CAAC,SAAS,IAAI;yBAC9F,CAAC;iBACH,CAAC;YACJ,CAAC;YAED,MAAM,EAAE,GAAG,QAAQ,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC;YAE/B,oDAAoD;YACpD,MAAM,MAAM,GAAG;gBACb,MAAM,EAAE,EAAE,CAAC,MAAM;gBACjB,MAAM,EAAE,EAAE,CAAC,MAAM;gBACjB,MAAM,EAAE,EAAE,CAAC,MAAM;gBACjB,aAAa,EAAE,EAAE,CAAC,YAAY;gBAC9B,mBAAmB,EAAE,EAAE,CAAC,gBAAgB;gBACxC,WAAW,EAAE,EAAE,CAAC,WAAW;gBAC3B,cAAc,EAAE,EAAE,CAAC,aAAa;gBAChC,gBAAgB,EAAE,EAAE,CAAC,eAAe;gBACpC,MAAM,EAAE;oBACN,IAAI,EAAE,EAAE,CAAC,SAAS;oBAClB,SAAS,EAAE,EAAE,CAAC,SAAS;oBACvB,KAAK,EAAE,EAAE,CAAC,KAAK;iBAChB;gBACD,SAAS,EAAE;oBACT,SAAS,EAAE,EAAE,CAAC,SAAS,CAAC,eAAe;oBACvC,MAAM,EAAE,EAAE,CAAC,SAAS,CAAC,YAAY;oBACjC,MAAM,EAAE,EAAE,CAAC,SAAS,CAAC,aAAa;iBACnC;gBACD,SAAS,EAAE;oBACT,MAAM,EAAE,EAAE,CAAC,SAAS,CAAC,MAAM;oBAC3B,GAAG,EAAE,EAAE,CAAC,SAAS,CAAC,GAAG;iBACtB;gBACD,KAAK,EAAE,CAAC,EAAE,CAAC,KAAK,EAAE,OAAO,IAAI,EAAE,CAAC,CAAC,GAAG,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,CAAC;oBAC9C,QAAQ,EAAE,IAAI,CAAC,QAAQ;oBACvB,QAAQ,EAAE,IAAI,CAAC,QAAQ;oBACvB,WAAW,EAAE,IAAI,CAAC,UAAU;oBAC5B,UAAU,EAAE,IAAI,CAAC,SAAS,IAAI,IAAI,CAAC,UAAU,IAAI,IAAI;iBACtD,CAAC,CAAC;aACJ,CAAC;YAEF,OAAO;gBACL,OAAO,EAAE,CAAC;wBACR,IAAI,EAAE,MAAe;wBACrB,IAAI,EAAE,IAAI,CAAC,SAAS,CAAC,MAAM,EAAE,IAAI,EAAE,CAAC,CAAC;qBACtC,CAAC;aACH,CAAC;QACJ,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACf,MAAM,OAAO,GAAG,KAAK,YAAY,kBAAkB;gBACjD,CAAC,CAAC,KAAK,CAAC,iBAAiB;gBACzB,CAAC,CAAC,qBAAqB,SAAS,CAAC,KAAK,CAAC,EAAE,CAAC;YAC5C,OAAO;gBACL,OAAO,EAAE,CAAC,EAAE,IAAI,EAAE,MAAe,EAAE,IAAI,EAAE,OAAO,EAAE,CAAC;gBACnD,OAAO,EAAE,IAAI;aACd,CAAC;QACJ,CAAC;IACH,CAAC,CACF,CAAC;AACJ,CAAC"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"documentos.d.ts","sourceRoot":"","sources":["../../src/tools/documentos.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,SAAS,EAAE,MAAM,yCAAyC,CAAC;
|
|
1
|
+
{"version":3,"file":"documentos.d.ts","sourceRoot":"","sources":["../../src/tools/documentos.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,SAAS,EAAE,MAAM,yCAAyC,CAAC;AAUpE;;GAEG;AACH,wBAAgB,uBAAuB,CAAC,MAAM,EAAE,SAAS,GAAG,IAAI,CA0S/D"}
|
package/dist/tools/documentos.js
CHANGED
|
@@ -3,6 +3,7 @@ import fs from 'fs';
|
|
|
3
3
|
import path from 'path';
|
|
4
4
|
import { PDFParse } from 'pdf-parse';
|
|
5
5
|
import { resolveDocsDir, listSupportedDocs } from '../utils/docs-locator.js';
|
|
6
|
+
import { buscarEnTexto } from '../utils/doc-search.js';
|
|
6
7
|
import { safeError } from '../utils/redact.js';
|
|
7
8
|
const DOCS_DIR = resolveDocsDir();
|
|
8
9
|
/**
|
|
@@ -28,18 +29,23 @@ export function registerDocumentosTools(server) {
|
|
|
28
29
|
};
|
|
29
30
|
}
|
|
30
31
|
else {
|
|
32
|
+
// Verificado en septiembre 2026: este endpoint heredado responde 404
|
|
33
|
+
// para los adjuntos de Compra Ágil, aun con IDs numéricos válidos
|
|
34
|
+
// entregados por la API. Se sigue ofreciendo por si el portal lo
|
|
35
|
+
// restablece, pero la ficha va primero y sin prometer que funcionará.
|
|
31
36
|
const directUrl = `https://www.mercadopublico.cl/FichaLicitacion/RetornaDocumento.aspx?id=${args.id_documento}`;
|
|
32
37
|
return {
|
|
33
38
|
content: [{
|
|
34
39
|
type: 'text',
|
|
35
|
-
text: `
|
|
40
|
+
text: `Para acceder al adjunto ${args.id_documento}, abre la ficha pública del proceso (no requiere iniciar sesión):\n${fichaUrl}\n\nExiste además un enlace heredado de descarga directa, pero se comprobó que hoy responde 404 para los adjuntos de Compra Ágil, así que probablemente no funcione:\n${directUrl}`,
|
|
36
41
|
}],
|
|
37
42
|
};
|
|
38
43
|
}
|
|
39
44
|
});
|
|
40
45
|
// ─── 2. DESCARGAR Y LEER DOCUMENTO DE PROCESO (REMOTO) ───────────────
|
|
41
46
|
server.registerTool('descargar_y_leer_documento', {
|
|
42
|
-
description:
|
|
47
|
+
description: `Intenta descargar un adjunto de Compra Ágil (bases técnicas/administrativas) y extraer su texto.
|
|
48
|
+
⚠ IMPORTANTE: para los IDs numéricos —que son los que entrega esta API— el portal ya NO sirve el archivo, así que la herramienta responde de inmediato con el enlace a la ficha pública en vez de intentar una descarga que se sabe fallida. Si necesitas las especificaciones para cotizar, tendrás que abrir esa ficha en un navegador: el enlace del adjunto lo genera JavaScript y no existe una URL que un programa pueda pedir.`,
|
|
43
49
|
inputSchema: {
|
|
44
50
|
id_documento: z.string().describe('ID único del documento. Ej: "123456" o un UUID.'),
|
|
45
51
|
codigo_compra: z.string().optional().describe('Código de la Compra Ágil asociada (Ej: "2494-141-COT26"). Permite guiar al usuario a la ficha pública en caso de fallar la descarga.'),
|
|
@@ -49,29 +55,58 @@ export function registerDocumentosTools(server) {
|
|
|
49
55
|
}, async (args) => {
|
|
50
56
|
try {
|
|
51
57
|
const isUuid = /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i.test(args.id_documento);
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
58
|
+
// ⚠ NO se intenta la descarga de IDs numéricos: se comprobó que el
|
|
59
|
+
// endpoint heredado responde 404 para todos los adjuntos de Compra
|
|
60
|
+
// Ágil (IDs 1855508 y 1854909, de procesos distintos), y la causa es
|
|
61
|
+
// estructural — en la ficha el enlace es un <a> con href vacío, la
|
|
62
|
+
// descarga la dispara JavaScript y no hay URL estática que pedir.
|
|
63
|
+
// Gastar una petición y esperar su timeout para confirmar un fallo
|
|
64
|
+
// conocido solo retrasa la única respuesta útil, que es el enlace.
|
|
65
|
+
//
|
|
66
|
+
// Los UUID SÍ se intentan: usan otro endpoint (adjunto.mercadopublico.cl)
|
|
67
|
+
// que nunca se pudo ejercitar, así que no se da por muerto sin prueba.
|
|
68
|
+
// Si algún día vuelven a servirse los numéricos, `scripts/debug-*.ts`
|
|
69
|
+
// y esta guarda son el punto por donde revertirlo.
|
|
70
|
+
if (!isUuid) {
|
|
71
|
+
const ficha = args.codigo_compra
|
|
72
|
+
? `\n\nÁbrelo desde la ficha pública del proceso (en un navegador, sin iniciar sesión):\nhttps://buscador.mercadopublico.cl/ficha?code=${args.codigo_compra}`
|
|
73
|
+
: '\n\nBusca el código de la compra en https://buscador.mercadopublico.cl y abre su ficha para ver el adjunto.';
|
|
74
|
+
return {
|
|
75
|
+
content: [{
|
|
76
|
+
type: 'text',
|
|
77
|
+
text: `El adjunto ${args.id_documento} no se puede descargar por programa: Mercado Público dejó de servir los adjuntos de Compra Ágil por enlace directo, y en la ficha el archivo se descarga mediante JavaScript, sin una URL que se pueda pedir.${ficha}\n\nSi necesitas las especificaciones técnicas para cotizar, suelen estar solo en ese adjunto, así que conviene abrirlo ahí.`,
|
|
78
|
+
}],
|
|
79
|
+
};
|
|
80
|
+
}
|
|
81
|
+
const url = `https://adjunto.mercadopublico.cl/adjunto-compra-agil/descargar/${args.id_documento}`;
|
|
55
82
|
// Descargar PDF
|
|
56
83
|
const response = await fetch(url, {
|
|
57
84
|
headers: {
|
|
58
85
|
'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36'
|
|
59
86
|
}
|
|
60
87
|
});
|
|
61
|
-
|
|
88
|
+
// ⚠ 404 se trata igual que 401/403 y no como un fallo inesperado:
|
|
89
|
+
// verificado contra el servicio real (septiembre 2026) que el endpoint
|
|
90
|
+
// heredado RetornaDocumento.aspx responde 404 para los adjuntos de
|
|
91
|
+
// Compra Ágil, incluso con IDs numéricos entregados por la propia API
|
|
92
|
+
// (probados 1855508 y 1854909, de procesos distintos). Para el usuario
|
|
93
|
+
// la situación práctica es la misma que un bloqueo: hay que ir a la
|
|
94
|
+
// ficha. Devolver un "Error HTTP 404" pelado hacía que el modelo
|
|
95
|
+
// informara una falla técnica en vez de la vía alternativa que sí sirve.
|
|
96
|
+
if (!response.ok) {
|
|
62
97
|
const fichaMsg = args.codigo_compra
|
|
63
|
-
? `\n\
|
|
64
|
-
: '\n\
|
|
98
|
+
? `\n\nDescarga el archivo desde la ficha pública del proceso (se abre en el navegador, sin iniciar sesión):\nhttps://buscador.mercadopublico.cl/ficha?code=${args.codigo_compra}`
|
|
99
|
+
: '\n\nBusca el código de la compra en https://buscador.mercadopublico.cl para descargar el archivo desde su ficha.';
|
|
100
|
+
const causa = response.status === 404
|
|
101
|
+
? `el portal ya no expone este adjunto por descarga directa (HTTP 404). Es el comportamiento observado para los adjuntos de Compra Ágil, no un error de tu consulta`
|
|
102
|
+
: `el servidor de Mercado Público requiere autenticación (Clave Única) o bloquea las solicitudes programáticas (HTTP ${response.status})`;
|
|
65
103
|
return {
|
|
66
104
|
content: [{
|
|
67
105
|
type: 'text',
|
|
68
|
-
text: `No
|
|
106
|
+
text: `No fue posible descargar el documento ${args.id_documento} automáticamente: ${causa}.${fichaMsg}\n\nSi necesitas las especificaciones técnicas para cotizar, ábrelo desde ese enlace: suelen estar solo en el adjunto.`,
|
|
69
107
|
}],
|
|
70
108
|
};
|
|
71
109
|
}
|
|
72
|
-
if (!response.ok) {
|
|
73
|
-
throw new Error(`Error HTTP al intentar descargar el documento: ${response.status} ${response.statusText}`);
|
|
74
|
-
}
|
|
75
110
|
const arrayBuffer = await response.arrayBuffer();
|
|
76
111
|
const buffer = Buffer.from(arrayBuffer);
|
|
77
112
|
// Parsear PDF
|
|
@@ -143,7 +178,7 @@ export function registerDocumentosTools(server) {
|
|
|
143
178
|
server.registerTool('consultar_documentos_locales', {
|
|
144
179
|
description: 'Busca y lee información dentro de los manuales, normativas o guías de Compra Ágil almacenados localmente en la carpeta docs/ (soporta formatos .pdf, .txt, .md).',
|
|
145
180
|
inputSchema: {
|
|
146
|
-
query: z.string().optional().describe('
|
|
181
|
+
query: z.string().optional().describe('Qué buscar. Admite tanto un término suelto ("multas", "garantía") como una pregunta en lenguaje natural ("¿qué multas me pueden aplicar?"): la consulta se descompone en términos y se ignoran acentos y palabras vacías. Si se omite, lista los documentos disponibles.'),
|
|
147
182
|
max_caracteres: z.number().min(500).max(15000).default(3000).optional().describe('Cantidad máxima de texto a retornar de cada coincidencia.'),
|
|
148
183
|
},
|
|
149
184
|
}, async (args) => {
|
|
@@ -173,8 +208,11 @@ export function registerDocumentosTools(server) {
|
|
|
173
208
|
}],
|
|
174
209
|
};
|
|
175
210
|
}
|
|
176
|
-
const searchTerm = args.query.toLowerCase();
|
|
177
211
|
const results = [];
|
|
212
|
+
// Términos que sí aparecieron en algún documento, para poder explicar
|
|
213
|
+
// un resultado vacío en vez de afirmar que no existe información.
|
|
214
|
+
const terminosEncontrados = new Set();
|
|
215
|
+
let terminosConsulta = [];
|
|
178
216
|
for (const file of files) {
|
|
179
217
|
const filePath = path.join(DOCS_DIR, file);
|
|
180
218
|
const ext = path.extname(file).toLowerCase();
|
|
@@ -189,28 +227,18 @@ export function registerDocumentosTools(server) {
|
|
|
189
227
|
else {
|
|
190
228
|
fileText = fs.readFileSync(filePath, 'utf8');
|
|
191
229
|
}
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
const
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
context.push(`[Siguiente] ${lines[i + 1]?.trim()}`);
|
|
205
|
-
fileMatches.push(context.join('\n'));
|
|
206
|
-
}
|
|
207
|
-
}
|
|
208
|
-
if (fileMatches.length > 0) {
|
|
209
|
-
const limit = args.max_caracteres || 3000;
|
|
210
|
-
const matchesText = fileMatches.join('\n\n---\n\n');
|
|
211
|
-
const truncated = matchesText.length > limit ? `${matchesText.substring(0, limit)}... [TRUNCADO]` : matchesText;
|
|
212
|
-
results.push(`### Archivo: ${file}\n\n${truncated}`);
|
|
213
|
-
}
|
|
230
|
+
const hallazgo = buscarEnTexto(fileText, args.query);
|
|
231
|
+
terminosConsulta = hallazgo.terminos;
|
|
232
|
+
for (const f of hallazgo.fragmentos) {
|
|
233
|
+
for (const t of f.terminos)
|
|
234
|
+
terminosEncontrados.add(t);
|
|
235
|
+
}
|
|
236
|
+
if (hallazgo.fragmentos.length > 0) {
|
|
237
|
+
const limit = args.max_caracteres || 3000;
|
|
238
|
+
const matchesText = hallazgo.fragmentos.map((f) => f.texto).join('\n\n---\n\n');
|
|
239
|
+
const truncated = matchesText.length > limit ? `${matchesText.substring(0, limit)}... [TRUNCADO]` : matchesText;
|
|
240
|
+
const cubiertos = [...new Set(hallazgo.fragmentos.flatMap((f) => f.terminos))];
|
|
241
|
+
results.push(`### Archivo: ${file}\n(términos encontrados aquí: ${cubiertos.join(', ')})\n\n${truncated}`);
|
|
214
242
|
}
|
|
215
243
|
}
|
|
216
244
|
catch (e) {
|
|
@@ -218,10 +246,13 @@ export function registerDocumentosTools(server) {
|
|
|
218
246
|
}
|
|
219
247
|
}
|
|
220
248
|
if (results.length === 0) {
|
|
249
|
+
const detalle = terminosConsulta.length > 0
|
|
250
|
+
? `\n\nLa consulta se buscó como los términos: ${terminosConsulta.join(', ')}. Ninguno aparece en los documentos. Prueba con sinónimos o con un término más general.`
|
|
251
|
+
: '';
|
|
221
252
|
return {
|
|
222
253
|
content: [{
|
|
223
254
|
type: 'text',
|
|
224
|
-
text: `No se encontraron coincidencias para "${args.query}" en ninguno de los ${files.length} documentos locales en "docs/"
|
|
255
|
+
text: `No se encontraron coincidencias para "${args.query}" en ninguno de los ${files.length} documentos locales en "docs/".${detalle}`,
|
|
225
256
|
}],
|
|
226
257
|
};
|
|
227
258
|
}
|