AlegraAPI
Interact with Alegra's accounting API to perform CRUD operations on resources like invoices, contacts, items, and purchase orders via the Alegra MCP Server.
Instructions
Una herramienta para interactuar con la API de contabilidad de Alegra. Permite realizar operaciones CRUD en una amplia gama de recursos como Facturas, Contactos, Items, Notas de Crédito, Órdenes de Compra y muchos más.
Input Schema
TableJSON Schema
| Name | Required | Description | Default |
|---|---|---|---|
| endpoint | Yes | El tipo de recurso de la API de Alegra a consultar o modificar. Ej: 'invoices', 'contacts', 'items', 'credit-notes', 'purchase-orders', etc. | |
| id | No | El ID específico de un recurso (ej: el ID de una factura para get, put, delete). | |
| method | No | El método HTTP a utilizar (get, post, put, delete). | get |
| queryParams | No | Parámetros de consulta adicionales (ej: 'start', 'limit', 'query' para GET) o cuerpo de la solicitud para POST/PUT. |
Implementation Reference
- src/main.ts:93-147 (handler)The handler function that constructs and executes HTTP requests to the Alegra API using the provided endpoint, method, ID, and parameters. Handles GET, POST, PUT, DELETE operations, logging, error handling, and returns JSON response.async ({ endpoint, method, id, queryParams }) => { const BASE_URL = 'https://api.alegra.com/api/v1/'; let url = `${BASE_URL}${endpoint}`; if (id) { url += `/${id}`; } // Definimos RequestInit aquí para poder modificarlo antes de fetch const fetchOptions: RequestInit = { method: method.toUpperCase(), headers: getAlegraAuthHeaders() // Content-Type application/json ya está en getAlegraAuthHeaders }; if (method.toUpperCase() === 'GET' || method.toUpperCase() === 'DELETE') { if (queryParams && Object.keys(queryParams).length > 0) { const params = new URLSearchParams(queryParams as any); url += `?${params.toString()}`; } } else if (method.toUpperCase() === 'POST' || method.toUpperCase() === 'PUT') { if (queryParams && Object.keys(queryParams).length > 0) { fetchOptions.body = JSON.stringify(queryParams); } else { // Para POST/PUT, si no se proporcionan queryParams (cuerpo), enviar un cuerpo JSON vacío. fetchOptions.body = JSON.stringify({}); } } logger.info(`Realizando petición: ${method.toUpperCase()} ${url}`); if (fetchOptions.body) { logger.info(`Con cuerpo: ${fetchOptions.body}`); } try { const response = await fetch(url, fetchOptions); if (!response.ok) { const errorBody = await response.text(); throw new Error(`Error de la API de Alegra: ${response.status} ${response.statusText} - ${errorBody}`); } const data = await response.json(); return { content: [{ type: "text", text: JSON.stringify(data, null, 2) }], }; } catch (error: any) { logger.error("Error al llamar a la API de Alegra:", error); return { content: [{ type: "text", text: `Error: ${error.message}` }], isError: true }; } }
- src/main.ts:47-92 (schema)Zod schema defining the input parameters: endpoint (enum of Alegra resources), method (HTTP method), id (optional resource ID), queryParams (optional query or body params).{ // Esquema de argumentos usando Zod endpoint: z.enum([ 'invoices', 'contacts', 'items', 'credit-notes', 'remissions', 'purchase-orders', 'estimates', 'income-debit-notes', 'global-invoices', 'transportation-receipts', 'recurring-invoices', 'payments', 'bills', 'debit-notes', // Este es para notas débito de proveedor 'recurring-payments', 'warehouses', 'warehouse-transfers', 'inventory-adjustments', 'price-lists', 'custom-fields', 'variant-attributes', 'item-categories', 'sellers', 'categories', // Para Cuentas Contables 'cost-centers', 'journals', 'bank-accounts', 'reconciliations', 'taxes', 'retentions', 'currencies', 'terms', 'company', 'users', 'number-templates', 'webhooks-subscriptions', 'additional-charges' ]).describe("El tipo de recurso de la API de Alegra a consultar o modificar. Ej: 'invoices', 'contacts', 'items', 'credit-notes', 'purchase-orders', etc."), method: z.enum(['get', 'post', 'put', 'delete']).default('get').describe("El método HTTP a utilizar (get, post, put, delete)."), id: z.string().optional().describe("El ID específico de un recurso (ej: el ID de una factura para get, put, delete)."), queryParams: z.record(z.union([z.string(), z.any()])).optional().describe("Parámetros de consulta adicionales (ej: 'start', 'limit', 'query' para GET) o cuerpo de la solicitud para POST/PUT.") },
- src/main.ts:44-148 (registration)Registration of the 'AlegraAPI' tool using server.tool(), including name, description, input schema, and handler function.server.tool( "AlegraAPI", // Nombre de la herramienta "Una herramienta para interactuar con la API de contabilidad de Alegra. Permite realizar operaciones CRUD en una amplia gama de recursos como Facturas, Contactos, Items, Notas de Crédito, Órdenes de Compra y muchos más.", // Descripción para la IA { // Esquema de argumentos usando Zod endpoint: z.enum([ 'invoices', 'contacts', 'items', 'credit-notes', 'remissions', 'purchase-orders', 'estimates', 'income-debit-notes', 'global-invoices', 'transportation-receipts', 'recurring-invoices', 'payments', 'bills', 'debit-notes', // Este es para notas débito de proveedor 'recurring-payments', 'warehouses', 'warehouse-transfers', 'inventory-adjustments', 'price-lists', 'custom-fields', 'variant-attributes', 'item-categories', 'sellers', 'categories', // Para Cuentas Contables 'cost-centers', 'journals', 'bank-accounts', 'reconciliations', 'taxes', 'retentions', 'currencies', 'terms', 'company', 'users', 'number-templates', 'webhooks-subscriptions', 'additional-charges' ]).describe("El tipo de recurso de la API de Alegra a consultar o modificar. Ej: 'invoices', 'contacts', 'items', 'credit-notes', 'purchase-orders', etc."), method: z.enum(['get', 'post', 'put', 'delete']).default('get').describe("El método HTTP a utilizar (get, post, put, delete)."), id: z.string().optional().describe("El ID específico de un recurso (ej: el ID de una factura para get, put, delete)."), queryParams: z.record(z.union([z.string(), z.any()])).optional().describe("Parámetros de consulta adicionales (ej: 'start', 'limit', 'query' para GET) o cuerpo de la solicitud para POST/PUT.") }, async ({ endpoint, method, id, queryParams }) => { const BASE_URL = 'https://api.alegra.com/api/v1/'; let url = `${BASE_URL}${endpoint}`; if (id) { url += `/${id}`; } // Definimos RequestInit aquí para poder modificarlo antes de fetch const fetchOptions: RequestInit = { method: method.toUpperCase(), headers: getAlegraAuthHeaders() // Content-Type application/json ya está en getAlegraAuthHeaders }; if (method.toUpperCase() === 'GET' || method.toUpperCase() === 'DELETE') { if (queryParams && Object.keys(queryParams).length > 0) { const params = new URLSearchParams(queryParams as any); url += `?${params.toString()}`; } } else if (method.toUpperCase() === 'POST' || method.toUpperCase() === 'PUT') { if (queryParams && Object.keys(queryParams).length > 0) { fetchOptions.body = JSON.stringify(queryParams); } else { // Para POST/PUT, si no se proporcionan queryParams (cuerpo), enviar un cuerpo JSON vacío. fetchOptions.body = JSON.stringify({}); } } logger.info(`Realizando petición: ${method.toUpperCase()} ${url}`); if (fetchOptions.body) { logger.info(`Con cuerpo: ${fetchOptions.body}`); } try { const response = await fetch(url, fetchOptions); if (!response.ok) { const errorBody = await response.text(); throw new Error(`Error de la API de Alegra: ${response.status} ${response.statusText} - ${errorBody}`); } const data = await response.json(); return { content: [{ type: "text", text: JSON.stringify(data, null, 2) }], }; } catch (error: any) { logger.error("Error al llamar a la API de Alegra:", error); return { content: [{ type: "text", text: `Error: ${error.message}` }], isError: true }; } } );
- src/auth.ts:1-16 (helper)Helper function to generate authentication headers for Alegra API using environment variables ALEGRIA_USER and ALEGRIA_TOKEN.export function getAlegraAuthHeaders(): Headers { const user = process.env.ALEGRA_USER; const token = process.env.ALEGRA_TOKEN; if (!user || !token) { throw new Error('ALEGRA_USER y ALEGRA_TOKEN deben estar definidos en el archivo .env'); } const base64Credentials = Buffer.from(`${user}:${token}`).toString('base64'); const headers = new Headers(); headers.append('Authorization', `Basic ${base64Credentials}`); headers.append('Content-Type', 'application/json'); return headers; }
- src/logger.ts:15-22 (helper)Logger utility with info and error methods that append to a log file, used in the handler for request logging and errors.export const logger = { info(message: string, data?: unknown) { appendFileSync(LOG_FILE, formatMessage("INFO", message, data)); }, error(message: string, error?: unknown) { appendFileSync(LOG_FILE, formatMessage("ERROR", message, error)); }, };