@nubiia/mcp-freematica 0.6.1

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.
Files changed (138) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +485 -0
  3. package/dist/clients/base-client.d.ts +31 -0
  4. package/dist/clients/base-client.js +102 -0
  5. package/dist/clients/base-client.js.map +1 -0
  6. package/dist/clients/fiql-builder.d.ts +118 -0
  7. package/dist/clients/fiql-builder.js +257 -0
  8. package/dist/clients/fiql-builder.js.map +1 -0
  9. package/dist/clients/freematica-client.d.ts +659 -0
  10. package/dist/clients/freematica-client.js +1327 -0
  11. package/dist/clients/freematica-client.js.map +1 -0
  12. package/dist/clients/hardened-base-client.d.ts +143 -0
  13. package/dist/clients/hardened-base-client.js +366 -0
  14. package/dist/clients/hardened-base-client.js.map +1 -0
  15. package/dist/config.d.ts +104 -0
  16. package/dist/config.js +105 -0
  17. package/dist/config.js.map +1 -0
  18. package/dist/index.d.ts +2 -0
  19. package/dist/index.js +55 -0
  20. package/dist/index.js.map +1 -0
  21. package/dist/logger.d.ts +71 -0
  22. package/dist/logger.js +114 -0
  23. package/dist/logger.js.map +1 -0
  24. package/dist/schemas/albaranes.d.ts +124 -0
  25. package/dist/schemas/albaranes.js +250 -0
  26. package/dist/schemas/albaranes.js.map +1 -0
  27. package/dist/schemas/cartera.d.ts +70 -0
  28. package/dist/schemas/cartera.js +104 -0
  29. package/dist/schemas/cartera.js.map +1 -0
  30. package/dist/schemas/contratos.d.ts +7 -0
  31. package/dist/schemas/contratos.js +2 -0
  32. package/dist/schemas/contratos.js.map +1 -0
  33. package/dist/schemas/facturas-electronicas.d.ts +60 -0
  34. package/dist/schemas/facturas-electronicas.js +79 -0
  35. package/dist/schemas/facturas-electronicas.js.map +1 -0
  36. package/dist/schemas/facturas-ventas.d.ts +118 -0
  37. package/dist/schemas/facturas-ventas.js +153 -0
  38. package/dist/schemas/facturas-ventas.js.map +1 -0
  39. package/dist/schemas/filters.d.ts +92 -0
  40. package/dist/schemas/filters.js +76 -0
  41. package/dist/schemas/filters.js.map +1 -0
  42. package/dist/schemas/master-data.d.ts +26 -0
  43. package/dist/schemas/master-data.js +86 -0
  44. package/dist/schemas/master-data.js.map +1 -0
  45. package/dist/schemas/pagination.d.ts +14 -0
  46. package/dist/schemas/pagination.js +27 -0
  47. package/dist/schemas/pagination.js.map +1 -0
  48. package/dist/schemas/pedidos-compras.d.ts +92 -0
  49. package/dist/schemas/pedidos-compras.js +189 -0
  50. package/dist/schemas/pedidos-compras.js.map +1 -0
  51. package/dist/server-instructions.d.ts +1 -0
  52. package/dist/server-instructions.js +83 -0
  53. package/dist/server-instructions.js.map +1 -0
  54. package/dist/server.d.ts +6 -0
  55. package/dist/server.js +41 -0
  56. package/dist/server.js.map +1 -0
  57. package/dist/tools/albaranes.d.ts +16 -0
  58. package/dist/tools/albaranes.js +202 -0
  59. package/dist/tools/albaranes.js.map +1 -0
  60. package/dist/tools/calendarios.d.ts +13 -0
  61. package/dist/tools/calendarios.js +82 -0
  62. package/dist/tools/calendarios.js.map +1 -0
  63. package/dist/tools/cartera.d.ts +13 -0
  64. package/dist/tools/cartera.js +78 -0
  65. package/dist/tools/cartera.js.map +1 -0
  66. package/dist/tools/clientes.d.ts +3 -0
  67. package/dist/tools/clientes.js +48 -0
  68. package/dist/tools/clientes.js.map +1 -0
  69. package/dist/tools/contabilidad.d.ts +14 -0
  70. package/dist/tools/contabilidad.js +259 -0
  71. package/dist/tools/contabilidad.js.map +1 -0
  72. package/dist/tools/contactos-clientes.d.ts +3 -0
  73. package/dist/tools/contactos-clientes.js +25 -0
  74. package/dist/tools/contactos-clientes.js.map +1 -0
  75. package/dist/tools/contratos.d.ts +10 -0
  76. package/dist/tools/contratos.js +35 -0
  77. package/dist/tools/contratos.js.map +1 -0
  78. package/dist/tools/facturas-compras.d.ts +13 -0
  79. package/dist/tools/facturas-compras.js +131 -0
  80. package/dist/tools/facturas-compras.js.map +1 -0
  81. package/dist/tools/facturas-electronicas.d.ts +17 -0
  82. package/dist/tools/facturas-electronicas.js +268 -0
  83. package/dist/tools/facturas-electronicas.js.map +1 -0
  84. package/dist/tools/facturas-ventas.d.ts +16 -0
  85. package/dist/tools/facturas-ventas.js +181 -0
  86. package/dist/tools/facturas-ventas.js.map +1 -0
  87. package/dist/tools/helpers.d.ts +17 -0
  88. package/dist/tools/helpers.js +36 -0
  89. package/dist/tools/helpers.js.map +1 -0
  90. package/dist/tools/localizaciones.d.ts +17 -0
  91. package/dist/tools/localizaciones.js +192 -0
  92. package/dist/tools/localizaciones.js.map +1 -0
  93. package/dist/tools/master-data.d.ts +10 -0
  94. package/dist/tools/master-data.js +70 -0
  95. package/dist/tools/master-data.js.map +1 -0
  96. package/dist/tools/oportunidades-negocio.d.ts +3 -0
  97. package/dist/tools/oportunidades-negocio.js +68 -0
  98. package/dist/tools/oportunidades-negocio.js.map +1 -0
  99. package/dist/tools/pedidos-compras.d.ts +14 -0
  100. package/dist/tools/pedidos-compras.js +105 -0
  101. package/dist/tools/pedidos-compras.js.map +1 -0
  102. package/dist/tools/personal.d.ts +13 -0
  103. package/dist/tools/personal.js +154 -0
  104. package/dist/tools/personal.js.map +1 -0
  105. package/dist/tools/prl.d.ts +47 -0
  106. package/dist/tools/prl.js +242 -0
  107. package/dist/tools/prl.js.map +1 -0
  108. package/dist/tools/proveedores.d.ts +14 -0
  109. package/dist/tools/proveedores.js +122 -0
  110. package/dist/tools/proveedores.js.map +1 -0
  111. package/dist/transports/http.d.ts +12 -0
  112. package/dist/transports/http.js +110 -0
  113. package/dist/transports/http.js.map +1 -0
  114. package/dist/transports/stdio.d.ts +12 -0
  115. package/dist/transports/stdio.js +15 -0
  116. package/dist/transports/stdio.js.map +1 -0
  117. package/dist/types/api-envelope.d.ts +27 -0
  118. package/dist/types/api-envelope.js +2 -0
  119. package/dist/types/api-envelope.js.map +1 -0
  120. package/dist/types/clientes.d.ts +9 -0
  121. package/dist/types/clientes.js +2 -0
  122. package/dist/types/clientes.js.map +1 -0
  123. package/dist/types/contactos-clientes.d.ts +7 -0
  124. package/dist/types/contactos-clientes.js +2 -0
  125. package/dist/types/contactos-clientes.js.map +1 -0
  126. package/dist/types/contratos.d.ts +8 -0
  127. package/dist/types/contratos.js +2 -0
  128. package/dist/types/contratos.js.map +1 -0
  129. package/dist/types/master-data.d.ts +9 -0
  130. package/dist/types/master-data.js +2 -0
  131. package/dist/types/master-data.js.map +1 -0
  132. package/dist/types/oportunidades-negocio.d.ts +8 -0
  133. package/dist/types/oportunidades-negocio.js +2 -0
  134. package/dist/types/oportunidades-negocio.js.map +1 -0
  135. package/dist/utils/size-guardrail.d.ts +22 -0
  136. package/dist/utils/size-guardrail.js +31 -0
  137. package/dist/utils/size-guardrail.js.map +1 -0
  138. package/package.json +90 -0
@@ -0,0 +1,122 @@
1
+ import { z } from 'zod';
2
+ import { FreematicaError } from '../clients/base-client.js';
3
+ import { PaginationSchema } from '../schemas/pagination.js';
4
+ import { error, ok, okList } from './helpers.js';
5
+ const LIST_TOOL_NAME = 'freematica_list_proveedores';
6
+ const GET_TOOL_NAME = 'freematica_get_proveedor';
7
+ const LIST_DESCRIPTION = [
8
+ 'Devuelve la lista paginada de proveedores de Freemática.',
9
+ '',
10
+ 'Cada item contiene campos como COD_PRO (código), COD_GRUPO_PRO (grupo), NIF, NOMBRE_PRO (nombre),',
11
+ 'FECHA_BAJA (baja del proveedor), CMP_TIPO_IDENT (tipo identificador), COD_PROVINCIA, COD_PAIS,',
12
+ 'más `idReg` opaco para el endpoint singular.',
13
+ '',
14
+ 'Paginación 1-indexed.',
15
+ '',
16
+ 'El filtro `activo` es un booleano: true = FECHA_BAJA nula (proveedores activos);',
17
+ 'false = FECHA_BAJA informada (dados de baja).',
18
+ '',
19
+ 'El filtro `nombre` realiza búsqueda parcial mediante operador FIQL =lk= (LIKE).',
20
+ ].join('\n');
21
+ const GET_DESCRIPTION = [
22
+ 'Devuelve el detalle completo de un proveedor.',
23
+ '',
24
+ 'El parámetro `id` DEBE ser el campo `idReg` (string opaco base64) que aparece en los items de',
25
+ 'freematica_list_proveedores. NO usar COD_PRO ni otro código natural.',
26
+ ].join('\n');
27
+ const LIST_SCHEMA = {
28
+ ...PaginationSchema,
29
+ codProveedor: z
30
+ .string()
31
+ .min(1)
32
+ .optional()
33
+ .describe('Código natural del proveedor (COD_PRO en Freemática).'),
34
+ grupoProveedor: z
35
+ .string()
36
+ .min(1)
37
+ .optional()
38
+ .describe('Código de grupo de proveedores (COD_GRUPO_PRO en Freemática).'),
39
+ nif: z
40
+ .string()
41
+ .min(1)
42
+ .optional()
43
+ .describe('NIF / CIF del proveedor (NIF en Freemática). Búsqueda exacta.'),
44
+ nombre: z
45
+ .string()
46
+ .min(1)
47
+ .optional()
48
+ .describe('Nombre del proveedor (NOMBRE_PRO). Búsqueda parcial — se usa operador FIQL =lk= (LIKE). ' +
49
+ 'Ejemplo: "García" devuelve todos los proveedores cuyo nombre contenga "García".'),
50
+ activo: z
51
+ .boolean()
52
+ .optional()
53
+ .describe('Filtra por estado del proveedor. true = sin fecha de baja (activos); ' +
54
+ 'false = con fecha de baja (dados de baja). FECHA_BAJA en Freemática.'),
55
+ tipoIdent: z
56
+ .string()
57
+ .min(1)
58
+ .optional()
59
+ .describe('Tipo de identificador fiscal (CMP_TIPO_IDENT en Freemática). Enum del API.'),
60
+ codProvincia: z
61
+ .string()
62
+ .min(1)
63
+ .optional()
64
+ .describe('Código de provincia (COD_PROVINCIA en Freemática).'),
65
+ codPais: z
66
+ .string()
67
+ .min(1)
68
+ .optional()
69
+ .describe('Código de país (COD_PAIS en Freemática).'),
70
+ };
71
+ /**
72
+ * Registra las tools de proveedores en el servidor MCP.
73
+ *
74
+ * Tools registradas:
75
+ * - `freematica_list_proveedores`: lista paginada con filtros FIQL (incluye búsqueda parcial por nombre
76
+ * con =lk= y filtro activo/inactivo vía FECHA_BAJA).
77
+ * - `freematica_get_proveedor`: detalle por idReg opaco.
78
+ *
79
+ * @param server - Instancia del servidor MCP.
80
+ * @param client - Cliente Freemática autenticado.
81
+ */
82
+ export function registerProveedoresTools(server, client) {
83
+ server.tool(LIST_TOOL_NAME, LIST_DESCRIPTION, LIST_SCHEMA, { readOnlyHint: true, destructiveHint: false, openWorldHint: true }, async ({ page, items, codProveedor, grupoProveedor, nif, nombre, activo, tipoIdent, codProvincia, codPais, }) => {
84
+ try {
85
+ const result = await client.listProveedores({
86
+ page,
87
+ items,
88
+ codProveedor,
89
+ grupoProveedor,
90
+ nif,
91
+ nombre,
92
+ activo,
93
+ tipoIdent,
94
+ codProvincia,
95
+ codPais,
96
+ });
97
+ return okList({ items: result.items, total: result.total, page, itemsPerPage: items });
98
+ }
99
+ catch (err) {
100
+ if (err instanceof FreematicaError)
101
+ return error(err);
102
+ return error(err instanceof Error ? err : new Error(String(err)));
103
+ }
104
+ });
105
+ server.tool(GET_TOOL_NAME, GET_DESCRIPTION, {
106
+ id: z
107
+ .string()
108
+ .min(1)
109
+ .describe('idReg opaco del proveedor (campo "idReg" en los items de freematica_list_proveedores).'),
110
+ }, { readOnlyHint: true, destructiveHint: false, openWorldHint: true }, async ({ id }) => {
111
+ try {
112
+ const proveedor = await client.getProveedor(id);
113
+ return ok(proveedor);
114
+ }
115
+ catch (err) {
116
+ if (err instanceof FreematicaError)
117
+ return error(err);
118
+ return error(err instanceof Error ? err : new Error(String(err)));
119
+ }
120
+ });
121
+ }
122
+ //# sourceMappingURL=proveedores.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"proveedores.js","sourceRoot":"","sources":["../../src/tools/proveedores.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,12 @@
1
+ import express from 'express';
2
+ import type { FreematicaClient } from '../clients/freematica-client.js';
3
+ export interface HttpTransportConfig {
4
+ port: number;
5
+ client: FreematicaClient;
6
+ allowedOrigins: string;
7
+ }
8
+ export interface HttpAppResult {
9
+ app: express.Application;
10
+ shutdown: () => Promise<void>;
11
+ }
12
+ export declare function createHttpApp(config: HttpTransportConfig): Promise<HttpAppResult>;
@@ -0,0 +1,110 @@
1
+ import express from 'express';
2
+ import cors from 'cors';
3
+ import rateLimit from 'express-rate-limit';
4
+ import { randomUUID } from 'node:crypto';
5
+ import { StreamableHTTPServerTransport } from '@modelcontextprotocol/sdk/server/streamableHttp.js';
6
+ import { isInitializeRequest } from '@modelcontextprotocol/sdk/types.js';
7
+ import { createFreematicaServer } from '../server.js';
8
+ const SESSION_TTL_MS = 30 * 60 * 1000; // 30 min
9
+ export async function createHttpApp(config) {
10
+ const app = express();
11
+ const sessions = new Map();
12
+ const origins = config.allowedOrigins === '*'
13
+ ? true
14
+ : config.allowedOrigins.split(',').map((s) => s.trim());
15
+ app.use(cors({
16
+ origin: origins,
17
+ exposedHeaders: ['Mcp-Session-Id'],
18
+ allowedHeaders: ['Content-Type', 'Mcp-Session-Id', 'Authorization'],
19
+ }));
20
+ app.use(express.json({ limit: '1mb' }));
21
+ const mcpRateLimit = rateLimit({
22
+ windowMs: 60_000,
23
+ limit: 120,
24
+ standardHeaders: true,
25
+ legacyHeaders: false,
26
+ });
27
+ app.get('/health', (_req, res) => {
28
+ res.json({ status: 'ok', version: '0.4.1', sessions: sessions.size });
29
+ });
30
+ // POST /mcp — JSON-RPC handler
31
+ app.post('/mcp', mcpRateLimit, async (req, res) => {
32
+ const sessionId = req.headers['mcp-session-id'];
33
+ let entry = sessionId ? sessions.get(sessionId) : undefined;
34
+ if (!entry) {
35
+ if (!isInitializeRequest(req.body)) {
36
+ res.status(400).json({
37
+ jsonrpc: '2.0',
38
+ error: { code: -32000, message: 'No session: send initialize first' },
39
+ id: null,
40
+ });
41
+ return;
42
+ }
43
+ const transport = new StreamableHTTPServerTransport({
44
+ sessionIdGenerator: () => randomUUID(),
45
+ onsessioninitialized: (sid) => {
46
+ sessions.set(sid, { transport, createdAt: Date.now() });
47
+ },
48
+ });
49
+ transport.onclose = () => {
50
+ if (transport.sessionId)
51
+ sessions.delete(transport.sessionId);
52
+ };
53
+ const server = createFreematicaServer({ client: config.client });
54
+ await server.connect(transport);
55
+ await transport.handleRequest(req, res, req.body);
56
+ return;
57
+ }
58
+ await entry.transport.handleRequest(req, res, req.body);
59
+ });
60
+ // GET /mcp — SSE stream
61
+ app.get('/mcp', mcpRateLimit, async (req, res) => {
62
+ const sessionId = req.headers['mcp-session-id'];
63
+ const entry = sessionId ? sessions.get(sessionId) : undefined;
64
+ if (!entry) {
65
+ res.status(400).send('Invalid or missing Mcp-Session-Id');
66
+ return;
67
+ }
68
+ await entry.transport.handleRequest(req, res);
69
+ });
70
+ // DELETE /mcp — terminate session
71
+ app.delete('/mcp', mcpRateLimit, async (req, res) => {
72
+ const sessionId = req.headers['mcp-session-id'];
73
+ const entry = sessionId ? sessions.get(sessionId) : undefined;
74
+ if (!entry) {
75
+ res.status(404).send('Session not found');
76
+ return;
77
+ }
78
+ await entry.transport.handleRequest(req, res);
79
+ sessions.delete(sessionId);
80
+ });
81
+ // Background pruning of orphaned sessions
82
+ const pruneInterval = setInterval(() => {
83
+ const now = Date.now();
84
+ for (const [sid, entry] of sessions.entries()) {
85
+ if (now - entry.createdAt > SESSION_TTL_MS) {
86
+ try {
87
+ void entry.transport.close();
88
+ }
89
+ catch {
90
+ /* ignore */
91
+ }
92
+ sessions.delete(sid);
93
+ }
94
+ }
95
+ }, 5 * 60 * 1000);
96
+ const shutdown = async () => {
97
+ clearInterval(pruneInterval);
98
+ for (const entry of sessions.values()) {
99
+ try {
100
+ await entry.transport.close();
101
+ }
102
+ catch {
103
+ /* ignore */
104
+ }
105
+ }
106
+ sessions.clear();
107
+ };
108
+ return { app, shutdown };
109
+ }
110
+ //# sourceMappingURL=http.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"http.js","sourceRoot":"","sources":["../../src/transports/http.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,12 @@
1
+ import type { FreematicaClient } from '../clients/freematica-client.js';
2
+ export interface StartStdioOptions {
3
+ client: FreematicaClient;
4
+ }
5
+ /**
6
+ * Arranca el MCP server sobre el transport stdio.
7
+ *
8
+ * Mantiene el proceso vivo mientras el transport esté abierto (Claude
9
+ * Desktop / Claude Code cierran stdin cuando terminan, lo que dispara
10
+ * el `onclose` del transport y libera el proceso).
11
+ */
12
+ export declare function startStdio(opts: StartStdioOptions): Promise<void>;
@@ -0,0 +1,15 @@
1
+ import { StdioServerTransport } from '@modelcontextprotocol/sdk/server/stdio.js';
2
+ import { createFreematicaServer } from '../server.js';
3
+ /**
4
+ * Arranca el MCP server sobre el transport stdio.
5
+ *
6
+ * Mantiene el proceso vivo mientras el transport esté abierto (Claude
7
+ * Desktop / Claude Code cierran stdin cuando terminan, lo que dispara
8
+ * el `onclose` del transport y libera el proceso).
9
+ */
10
+ export async function startStdio(opts) {
11
+ const server = createFreematicaServer({ client: opts.client });
12
+ const transport = new StdioServerTransport();
13
+ await server.connect(transport);
14
+ }
15
+ //# sourceMappingURL=stdio.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"stdio.js","sourceRoot":"","sources":["../../src/transports/stdio.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,oBAAoB,EAAE,MAAM,2CAA2C,CAAC;AAEjF,OAAO,EAAE,sBAAsB,EAAE,MAAM,cAAc,CAAC;AAMtD;;;;;;GAMG;AACH,MAAM,CAAC,KAAK,UAAU,UAAU,CAAC,IAAuB;IACtD,MAAM,MAAM,GAAG,sBAAsB,CAAC,EAAE,MAAM,EAAE,IAAI,CAAC,MAAM,EAAE,CAAC,CAAC;IAC/D,MAAM,SAAS,GAAG,IAAI,oBAAoB,EAAE,CAAC;IAC7C,MAAM,MAAM,CAAC,OAAO,CAAC,SAAS,CAAC,CAAC;AAClC,CAAC"}
@@ -0,0 +1,27 @@
1
+ /**
2
+ * Wrapper universal que devuelve el API REST de Freemática en TODAS las
3
+ * respuestas. El `BaseClient` desempaqueta automáticamente este envelope
4
+ * y propaga `data` al método caller.
5
+ *
6
+ * `errorCode` viene como string (p.ej. "200", "404", "500"). Si es distinto
7
+ * de "200" el `BaseClient` lanza `FreematicaError` con un código mapeado.
8
+ */
9
+ export interface FreematicaEnvelope<T> {
10
+ errorCode: string;
11
+ errorMessage: string;
12
+ data: T;
13
+ }
14
+ /**
15
+ * Shape del campo `data` en endpoints de listado.
16
+ *
17
+ * `total` viene como string del API (típicamente "2007"). El método cliente
18
+ * lo convierte a `number` antes de exponerlo.
19
+ *
20
+ * `rowHeight` es metadata interno del API (parece UI-related); el cliente
21
+ * lo descarta.
22
+ */
23
+ export interface FreematicaListData<T> {
24
+ total: string;
25
+ items: T[];
26
+ rowHeight: number;
27
+ }
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=api-envelope.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"api-envelope.js","sourceRoot":"","sources":["../../src/types/api-envelope.ts"],"names":[],"mappings":""}
@@ -0,0 +1,9 @@
1
+ /**
2
+ * Cliente devuelto por Freemática.
3
+ *
4
+ * El shape exacto tiene ~87 campos en mayúsculas (`COD_CLI`, `NOMBRE_CLI`,
5
+ * `NIF`, `FECHA_ALTA`, etc.) más un campo `idReg` opaco (base64) que es la
6
+ * clave para los endpoints singulares. Se mantiene como `Record<string, unknown>`
7
+ * hasta que tengamos un caso de uso que justifique tipar campos concretos.
8
+ */
9
+ export type Cliente = Record<string, unknown>;
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=clientes.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"clientes.js","sourceRoot":"","sources":["../../src/types/clientes.ts"],"names":[],"mappings":""}
@@ -0,0 +1,7 @@
1
+ /**
2
+ * Contacto de cliente devuelto por Freemática.
3
+ *
4
+ * Mismo patrón que `Cliente`: campos en mayúsculas + `idReg` opaco. Sin
5
+ * tipado fuerte por ahora.
6
+ */
7
+ export type ContactoCliente = Record<string, unknown>;
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=contactos-clientes.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"contactos-clientes.js","sourceRoot":"","sources":["../../src/types/contactos-clientes.ts"],"names":[],"mappings":""}
@@ -0,0 +1,8 @@
1
+ /**
2
+ * Response object for GET /pvss/v2/contratos-servicios-material.
3
+ *
4
+ * The exact shape is not documented in the Postman collection. The type is
5
+ * declared as a loose record until we have access to real API responses;
6
+ * tighten it then.
7
+ */
8
+ export type VoContratosServMatAsignado = Record<string, unknown>;
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=contratos.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"contratos.js","sourceRoot":"","sources":["../../src/types/contratos.ts"],"names":[],"mappings":""}
@@ -0,0 +1,9 @@
1
+ /**
2
+ * Item de un catálogo de datos maestros de Freemática.
3
+ *
4
+ * El shape exacto varía por catálogo (algunos exponen `{ idreg, codigo, nombre }`,
5
+ * otros tienen campos específicos). Se mantiene como `Record<string, unknown>`
6
+ * hasta que se vean respuestas reales y se decida si tiparlos por catálogo o
7
+ * con un shape común mínimo.
8
+ */
9
+ export type MasterDataItem = Record<string, unknown>;
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=master-data.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"master-data.js","sourceRoot":"","sources":["../../src/types/master-data.ts"],"names":[],"mappings":""}
@@ -0,0 +1,8 @@
1
+ /**
2
+ * Oportunidad de negocio devuelta por Freemática (módulo pcrm).
3
+ *
4
+ * ~33 campos: `COD_CLI`, `COD_ESTADO_OPOR`, `COD_ETAPA_OPOR`, `NOMBRE`,
5
+ * `VALOR`, `ID_OPORTUNIDAD`, etc. Más un `idReg` opaco para el endpoint
6
+ * singular.
7
+ */
8
+ export type OportunidadNegocio = Record<string, unknown>;
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=oportunidades-negocio.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"oportunidades-negocio.js","sourceRoot":"","sources":["../../src/types/oportunidades-negocio.ts"],"names":[],"mappings":""}
@@ -0,0 +1,22 @@
1
+ /**
2
+ * Utilidades de guardrail de tamaño para respuestas del API de Freemática.
3
+ *
4
+ * Centraliza la lógica de lectura del límite de tamaño de respuesta para
5
+ * evitar duplicación entre el cliente HTTP y las tools MCP.
6
+ *
7
+ * @module size-guardrail
8
+ */
9
+ /**
10
+ * Lee el límite de respuesta en MB desde la variable de entorno
11
+ * `FREEMATICA_MAX_RESPONSE_SIZE_MB`. Si no está definida o es inválida,
12
+ * devuelve el default de 10 MB.
13
+ *
14
+ * Reglas de validación:
15
+ * - Debe ser un número.
16
+ * - Debe ser un número entero.
17
+ * - Debe estar en el rango [1, 500].
18
+ * Si cualquiera de esas condiciones falla, se devuelve el default de 10 MB.
19
+ *
20
+ * @returns Límite en megabytes (entero en [1, 500]).
21
+ */
22
+ export declare function loadMaxResponseSizeMb(): number;
@@ -0,0 +1,31 @@
1
+ /**
2
+ * Utilidades de guardrail de tamaño para respuestas del API de Freemática.
3
+ *
4
+ * Centraliza la lógica de lectura del límite de tamaño de respuesta para
5
+ * evitar duplicación entre el cliente HTTP y las tools MCP.
6
+ *
7
+ * @module size-guardrail
8
+ */
9
+ /**
10
+ * Lee el límite de respuesta en MB desde la variable de entorno
11
+ * `FREEMATICA_MAX_RESPONSE_SIZE_MB`. Si no está definida o es inválida,
12
+ * devuelve el default de 10 MB.
13
+ *
14
+ * Reglas de validación:
15
+ * - Debe ser un número.
16
+ * - Debe ser un número entero.
17
+ * - Debe estar en el rango [1, 500].
18
+ * Si cualquiera de esas condiciones falla, se devuelve el default de 10 MB.
19
+ *
20
+ * @returns Límite en megabytes (entero en [1, 500]).
21
+ */
22
+ export function loadMaxResponseSizeMb() {
23
+ const raw = process.env['FREEMATICA_MAX_RESPONSE_SIZE_MB'];
24
+ if (raw === undefined || raw === '')
25
+ return 10;
26
+ const parsed = Number(raw);
27
+ if (isNaN(parsed) || !Number.isInteger(parsed) || parsed < 1 || parsed > 500)
28
+ return 10;
29
+ return parsed;
30
+ }
31
+ //# sourceMappingURL=size-guardrail.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"size-guardrail.js","sourceRoot":"","sources":["../../src/utils/size-guardrail.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAEH;;;;;;;;;;;;GAYG;AACH,MAAM,UAAU,qBAAqB;IACnC,MAAM,GAAG,GAAG,OAAO,CAAC,GAAG,CAAC,iCAAiC,CAAC,CAAC;IAC3D,IAAI,GAAG,KAAK,SAAS,IAAI,GAAG,KAAK,EAAE;QAAE,OAAO,EAAE,CAAC;IAC/C,MAAM,MAAM,GAAG,MAAM,CAAC,GAAG,CAAC,CAAC;IAC3B,IAAI,KAAK,CAAC,MAAM,CAAC,IAAI,CAAC,MAAM,CAAC,SAAS,CAAC,MAAM,CAAC,IAAI,MAAM,GAAG,CAAC,IAAI,MAAM,GAAG,GAAG;QAAE,OAAO,EAAE,CAAC;IACxF,OAAO,MAAM,CAAC;AAChB,CAAC"}
package/package.json ADDED
@@ -0,0 +1,90 @@
1
+ {
2
+ "name": "@nubiia/mcp-freematica",
3
+ "version": "0.6.1",
4
+ "description": "MCP server for Freemática REST API (consumed by Claude via Nubiia)",
5
+ "type": "module",
6
+ "main": "dist/index.js",
7
+ "bin": {
8
+ "mcp-freematica": "dist/index.js"
9
+ },
10
+ "files": [
11
+ "dist",
12
+ "README.md",
13
+ "LICENSE"
14
+ ],
15
+ "scripts": {
16
+ "build": "tsc",
17
+ "start": "node dist/index.js",
18
+ "dev": "tsx src/index.ts",
19
+ "lint": "eslint src tests",
20
+ "lint:fix": "eslint src tests --fix",
21
+ "format": "prettier --write src tests",
22
+ "typecheck": "tsc --noEmit -p tsconfig.test.json",
23
+ "test": "vitest run",
24
+ "test:watch": "vitest",
25
+ "test:coverage": "vitest run --coverage",
26
+ "prepack": "npm run build",
27
+ "prepare": "husky"
28
+ },
29
+ "repository": {
30
+ "type": "git",
31
+ "url": "git+https://github.com/nubiia-dev/mcp-freematica.git"
32
+ },
33
+ "bugs": {
34
+ "url": "https://github.com/nubiia-dev/mcp-freematica/issues"
35
+ },
36
+ "homepage": "https://github.com/nubiia-dev/mcp-freematica#readme",
37
+ "publishConfig": {
38
+ "access": "public"
39
+ },
40
+ "engines": {
41
+ "node": ">=20"
42
+ },
43
+ "keywords": [
44
+ "mcp",
45
+ "model-context-protocol",
46
+ "freematica",
47
+ "nubiia"
48
+ ],
49
+ "author": "Nubiia",
50
+ "license": "MIT",
51
+ "dependencies": {
52
+ "@modelcontextprotocol/sdk": "^1.27.1",
53
+ "axios": "^1.7.0",
54
+ "cors": "^2.8.5",
55
+ "express": "^4.21.0",
56
+ "express-rate-limit": "^8.3.1",
57
+ "pino": "^10.3.1",
58
+ "uuid": "^14.0.0",
59
+ "zod": "^3.23.8"
60
+ },
61
+ "lint-staged": {
62
+ "*.{ts,js}": [
63
+ "eslint --fix"
64
+ ],
65
+ "*.{json,md}": [
66
+ "prettier --write"
67
+ ]
68
+ },
69
+ "devDependencies": {
70
+ "@types/cors": "^2.8.19",
71
+ "@types/express": "^4.17.21",
72
+ "@types/node": "^20.10.0",
73
+ "@types/uuid": "^10.0.0",
74
+ "@typescript-eslint/eslint-plugin": "^8.0.0",
75
+ "@typescript-eslint/parser": "^8.0.0",
76
+ "@vitest/coverage-v8": "^3.2.6",
77
+ "@vitest/ui": "^3.2.6",
78
+ "dotenv": "^16.0.0",
79
+ "eslint": "^9.0.0",
80
+ "fast-check": "^4.8.0",
81
+ "husky": "^9.1.7",
82
+ "lint-staged": "^16.4.0",
83
+ "nock": "^13.5.0",
84
+ "pino-pretty": "^13.1.3",
85
+ "prettier": "^3.3.0",
86
+ "tsx": "^4.6.0",
87
+ "typescript": "^5.3.0",
88
+ "vitest": "^3.2.6"
89
+ }
90
+ }