Skip to main content
Glama
Dattics

Alegra MCP Server

by Dattics

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
NameRequiredDescriptionDefault
endpointYesEl tipo de recurso de la API de Alegra a consultar o modificar. Ej: 'invoices', 'contacts', 'items', 'credit-notes', 'purchase-orders', etc.
idNoEl ID específico de un recurso (ej: el ID de una factura para get, put, delete).
methodNoEl método HTTP a utilizar (get, post, put, delete).get
queryParamsNoParámetros de consulta adicionales (ej: 'start', 'limit', 'query' para GET) o cuerpo de la solicitud para POST/PUT.

Implementation Reference

  • 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
          };
      }
    }
  • 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
            };
        }
      }
    );
  • 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;
    }
  • 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));
        },
    };
Behavior2/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

With no annotations provided, the description carries the full burden of behavioral disclosure. It states the tool allows CRUD operations but doesn't mention authentication requirements, rate limits, error handling, or what happens during mutations (e.g., are deletions permanent?). For a generic API tool with multiple endpoints and methods, this is a significant gap in behavioral context.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is concise and front-loaded, stating the core purpose in the first sentence and listing example resources. It avoids unnecessary fluff, though it could be slightly more structured (e.g., explicitly noting it's a generic wrapper). Every sentence contributes to understanding the tool's scope.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness2/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

Given the tool's complexity (generic API wrapper with 4 parameters, multiple endpoints/methods, no output schema, and no annotations), the description is inadequate. It doesn't explain how to construct requests, handle responses, or manage errors. For a flexible but potentially error-prone tool, more guidance is needed to ensure correct usage.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

The description mentions 'recursos' like Facturas and Contactos, which aligns with the 'endpoint' parameter, but doesn't add meaningful semantics beyond what the 100% schema coverage already provides. The schema descriptions thoroughly document each parameter, so the description adds minimal value here. Baseline 3 is appropriate given high schema coverage.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose4/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description clearly states the tool's purpose: 'interactuar con la API de contabilidad de Alegra' and 'realizar operaciones CRUD en una amplia gama de recursos'. It specifies the action (CRUD operations) and resources (Facturas, Contactos, Items, etc.), though it doesn't need to differentiate from siblings since none exist. The description is specific but could be more precise about being a generic API wrapper rather than dedicated CRUD tools.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines2/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The description provides no guidance on when to use this tool versus alternatives. It mentions CRUD operations on various resources but doesn't explain prerequisites, constraints, or appropriate contexts for use. Without sibling tools, this is less critical, but the description still lacks any usage context or limitations.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

Install Server

Other Tools

Related Tools

Latest Blog Posts

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/Dattics/Alegra-MCP'

If you have feedback or need assistance with the MCP directory API, please join our Discord server