@timbrix/mcp
Click on "Deploy Server".
Wait a few minutes for the server to deploy. Once ready, it will show a "Started" state.
In the chat, type
@followed by the MCP server name and your instructions, e.g., "@@timbrix/mcpStamp a CFDI 4.0 invoice for 5,000 MXN"
That's it! The server will respond to your query, and you can continue using it as needed.
Here is a step-by-step guide with screenshots.
@timbrix/mcp
MCP (Model Context Protocol) server for Timbrix — lets AI agents (Claude, Cursor, ChatGPT, etc.) stamp, cancel, and query CFDI 4.0 invoices directly, through the same REST API @timbrix/sdk uses.
Full guide: see docs.timbrix.mx/ai-agents for setup, the complete tool reference, LangChain (TS/Python) examples, error handling, and authentication best practices for agents.
This is the official public repository for
@timbrix/mcp— open issues and PRs here.Listed in the Official MCP Registry as
mx.timbrix/mcp.
v1 tools
Tool | Description |
| Stamp a CFDI 4.0 Ingreso invoice |
| Cancel a stamped CFDI by UUID and motivo |
| Get CFDI usage/quota for the current billing month |
| List invoices with page/type/status filters |
timbrix_crear_emisor(registering a new RFC issuer + CSD) is not available in v1 — organization creation and CSD upload require an authenticated owner session today, not an API key. See the Timbrix dashboard or@timbrix/clito onboard a new organization.
Related MCP server: brazil-invoice-mcp
Installation
No install step is required to try it — npx @timbrix/mcp always runs the
latest published version. To install it globally instead:
npm install -g @timbrix/mcp
TIMBRIX_API_KEY=sk_... timbrix-mcpClaude Desktop (local, npx)
Add to your claude_desktop_config.json:
{
"mcpServers": {
"timbrix": {
"command": "npx",
"args": ["@timbrix/mcp"],
"env": {
"TIMBRIX_API_KEY": "sk_..."
}
}
}
}Claude Desktop (hosted, no install)
Point at https://mcp.timbrix.mx/mcp instead — same config file, no local process:
{
"mcpServers": {
"timbrix": {
"url": "https://mcp.timbrix.mx/mcp",
"headers": {
"Authorization": "Bearer sk_..."
}
}
}
}Any MCP client that supports a url + custom headers remote server config (Cursor included) works the same way.
Environment variables
Variable | Required | Description |
| only for | API key created in the Timbrix dashboard, scoped to one organization |
| no | Overrides the API base URL (default |
| no |
|
| no | HTTP transport port when |
| no | HTTP transport bind address (default |
| only when | Comma-separated hostnames this server is publicly reachable as (Host-header allowlist) |
Running the HTTP transport
MCP_TRANSPORT=http PORT=8787 npx @timbrix/mcpEndpoints:
Endpoint | Purpose |
| Streamable HTTP — |
| SSE stream for server-to-client messages on an established session |
| Explicitly terminate a session |
| Health check ( |
Sessions
The endpoint is stateful, as the MCP spec requires. A client's first
POST /mcp carries an initialize request and no session header; the server
creates one MCP server instance for it and returns an Mcp-Session-Id. Every
later request (starting with notifications/initialized) must send that header
back and is routed to the same instance — an unknown or missing session ID is
rejected rather than silently given a fresh, uninitialized server.
A session lives until one of:
the client sends
DELETE /mcpwith itsMcp-Session-Id, orit goes 30 minutes without a request, at which point the idle sweep evicts it (clients that crash, close, or lose the network never send
DELETE, so without this they would leak).
After eviction, requests on that session ID get 404 Session not found; a client
recovers by re-running initialize.
Security: bind address, Host validation, and authentication
In http mode, each session authenticates independently via the
Authorization: Bearer <api-key> or X-API-Key header sent with the
client's initialize request — there is no single, process-wide API key.
The key is never validated by this package itself; it's forwarded to the
Timbrix API on every call, exactly as stdio mode already does, so the
Timbrix API's own key validation is the source of truth. An initialize
request with neither header is rejected with 401 before any session is
created.
The server binds to
127.0.0.1by default — reachable only from the same machine. Host-header (DNS-rebinding) validation is applied on this default, so a malicious web page cannot point a hostname it controls at your loopback server and drive it through the victim's browser.Set
MCP_HTTP_HOST(e.g.MCP_HTTP_HOST=0.0.0.0) to expose it further — this also requiresMCP_ALLOWED_HOSTS, since Host-header validation still applies on a non-loopback bind (the server refuses to start without it, rather than skipping validation altogether).New-session creation is rate-limited per IP (30/minute by default) to protect the process from unbounded session creation; requests on an already-established session are never affected by this limit.
GET /healthis exempt from Host validation, so infrastructure health probes (which send their own Host header, e.g. Railway'shealthcheck.railway.app) don't need to be added toMCP_ALLOWED_HOSTS.Once a session is established, its
Mcp-Session-Idheader alone authorizes further requests on it — the API key isn't re-checked per request — so treat a session ID as sensitive as the credential that created it for the rest of that session's life.
For local, single-user agents, stdio (the default) still needs no port
at all and is the simplest option.
Development
pnpm install
pnpm dev # watch build
pnpm test # vitest
pnpm build # tsupLicense
MIT © Timbrix — see LICENSE.
Available Tools
4 toolstimbrix_cancelar_cfdiCancelar CFDIADestructiveIdempotent
Solicita la cancelación de un CFDI ya timbrado ante el SAT. Si el receptor debe aprobar la cancelación, el resultado queda en estatus 'pendiente'.
| Name | Required | Description | Default |
|---|---|---|---|
| uuid | Yes | UUID fiscal (folio fiscal) del CFDI a cancelar | |
| motivo | Yes | 01 = con relación (requiere folioSustitucion), 02 = sin relación, 03 = no se llevó a cabo la operación, 04 = operación nominativa de factura global | |
| folioSustitucion | No | UUID del CFDI que sustituye a este; requerido cuando motivo=01 |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare readOnlyHint=false, idempotentHint=true, and destructiveHint=true, so the safety profile is clear. The description adds valuable behavioral context: the cancellation is a request ('Solicita'), the result may be 'pendiente' if receiver approval is needed, and it operates on an already-timbrado CFDI. This goes beyond the annotations by explaining the asynchronous/pending nature.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is a single, concise sentence that front-loads the core action and includes the most important behavioral nuance (pending status). No wasted words.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a cancellation tool with full schema coverage and annotations covering safety, the description is nearly complete. It explains the pending status and the SAT context. It could mention that motivo=01 requires folioSustitucion, but the schema already covers that. No output schema exists, so return values are not specified, but the description's mention of 'pendiente' status partially compensates.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 100%, so the schema already documents all three parameters. The description adds no additional parameter-level meaning beyond what the schema provides. Baseline 3 is appropriate since the schema does the heavy lifting.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description clearly states the action ('Solicita la cancelación de un CFDI ya timbrado ante el SAT') and the specific resource (CFDI). It also distinguishes itself from siblings by focusing on cancellation, while siblings handle creation, listing, and balance queries. The verb 'cancelar' is specific and unambiguous.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description implies when to use this tool: when a CFDI is already stamped and needs cancellation. It also mentions the pending status when receiver approval is required, which is a key usage context. However, it doesn't explicitly state when NOT to use it or name alternatives (e.g., use timbrix_listar_cfdi to find the UUID first).
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
timbrix_consultar_saldoConsultar saldo de CFDIARead-onlyIdempotent
Devuelve cuántos CFDI ha timbrado la organización configurada en el mes calendario actual (hora Ciudad de México) contra el límite incluido en su plan, y cuándo se reinicia el periodo. Importante: cfdiIncluded y cfdiRemaining son null cuando el plan es enterprise (timbrado ilimitado), no cero — nunca reportes que al cliente le quedan 0 timbres en ese caso.
| Name | Required | Description | Default |
|---|---|---|---|
No parameters | |||
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already cover read-only, idempotent, and non-destructive behavior. The description adds valuable context beyond that: the scope is the current calendar month in Mexico City time, the response includes a reset period, and the critical enterprise caveat that cfdiIncluded/cfdiRemaining are null, not zero, with explicit instructions not to report 0 timbres.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Two sentences with zero filler: the first front-loads the core functionality and timeframe, the second is a tightly-scoped edge-case warning. Every sentence earns its place.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Even without an output schema, the description gives the essential return semantics: usage vs limit, reset timing, and the null-values caveat that prevents misreporting. An agent has everything needed to call the tool and interpret the result correctly.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
The input schema has zero parameters, so the description has no parameter behavior to document. Per the rubric, a tool with 0 params gets a baseline of 4; no further param info is needed.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description states the exact verb ('Devuelve') and resource (CFDI timbrados in the current calendar month against the plan limit, plus the reset period). It clearly distinguishes from sibling tools like timbrix_crear_cfdi_ingreso and timbrix_cancelar_cfdi by being a read-only status query.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The full purpose makes the usage scenario obvious: an agent should call this when it needs current CFDI stamping usage against the plan limit or the period reset time. It does not explicitly name alternatives or state when not to use it, but confusion with the mutation/list siblings is unlikely.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
timbrix_crear_cfdi_ingresoTimbrar CFDI de ingresoA
Timbra (sella ante el SAT vía PAC) un CFDI 4.0 de tipo Ingreso para la organización configurada. Devuelve el UUID fiscal, el XML timbrado y el estatus.
| Name | Required | Description | Default |
|---|---|---|---|
| use | Yes | Clave SAT de uso de CFDI (catálogo c_UsoCFDI), ej. 'G01' | |
| date | Yes | Obligatorio. Fecha y hora de emisión del CFDI en ISO 8601 sin zona horaria, en hora local de Ciudad de México (America/Mexico_City, UTC-6) — NUNCA en UTC. El PAC compara este valor directamente contra su propio reloj de servidor, que está en hora de México sin ninguna conversión; una fecha en UTC se ve ~6 horas en el futuro y el timbrado falla (a veces reportado como el confuso 'CFDI40102 - digestión no coincide con el sello' en vez de un error de fecha claro). El SAT exige que esté dentro de las 72 horas previas al timbrado, por lo que debe indicarla explícitamente el llamador; el servidor no la asigna por su cuenta. | |
| items | Yes | Conceptos del CFDI | |
| series | Yes | Serie del folio (ej. 'A') | |
| currency | No | ||
| customer | No | Datos del receptor (excluyente con customerId) | |
| exchange | No | ||
| confirmado | No | Envíalo como true en una segunda llamada, después de que un humano confirme explícitamente, para timbrar a pesar de que el subtotal supere `umbral_confirmacion_mxn`. Default: false. | |
| customerId | No | ID de un cliente ya registrado (excluyente con customer) | |
| folioNumber | Yes | Número de folio | |
| paymentForm | Yes | Clave SAT de forma de pago (catálogo c_FormaPago), ej. '01' = Efectivo | |
| paymentMethod | No | ||
| idempotencyKey | No | ||
| requiere_confirmacion | No | Si es true, valida el subtotal estimado del CFDI (suma de items[].amount) contra `umbral_confirmacion_mxn` antes de timbrar. Si lo supera y `confirmado` no es true, el tool NO timbra: retorna un mensaje estructurado pidiendo confirmación explícita en vez de proceder. Default: false (no bloquea el flujo estándar). | |
| umbral_confirmacion_mxn | No | Monto en MXN a partir del cual se requiere confirmación explícita antes de timbrar. Obligatorio cuando `requiere_confirmacion` es true. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already indicate it is not read-only (mutating), not idempotent, and not destructive. The description adds the return format (UUID, XML, status) but does not disclose side effects, permission requirements, or irreversible consequences. It does not contradict annotations; the added value is modest, so a 3 is appropriate.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is two sentences with no filler, front-loading the core action and return values. Every sentence contributes meaning, and it is appropriately sized for the tool's purpose.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Despite the tool's complexity (15 parameters, nested objects, a confirmation threshold flow, timezone-sensitive date handling), the description provides only a minimal overview. It does not mention the `requiere_confirmacion`/`confirmado` workflow or the date timezone pitfall, which are critical for correct invocation. With no output schema, the description should summarize these to guide the agent; it falls short.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is high (73%), and many parameters have explicit descriptions (e.g., date timezone warning, confirmation flow fields). The description itself adds no parameter-level detail beyond what the schema already provides. Baseline 3 is correct when the schema carries the documentation burden.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description states a clear, specific verb ('Timbra' = stamps) and resource ('CFDI 4.0 de tipo Ingreso') and explicitly lists what it returns (UUID, XML, status). This distinguishes it from sibling tools that cancel, list, or check balance, so an agent can identify it unambiguously.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description implies it is for creating/stamping income CFDI but offers no explicit guidance on when to use it versus alternatives, nor any prerequisites (e.g., configured organization) or conditions for use. Since siblings perform different actions, the lack of exclusions is acceptable, but the description does not add usage context beyond the action itself.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
timbrix_listar_cfdiListar CFDIARead-onlyIdempotent
Lista los CFDI timbrados de la organización configurada, más recientes primero, con filtros opcionales de tipo y estatus.
| Name | Required | Description | Default |
|---|---|---|---|
| page | No | ||
| type | No | ||
| limit | No | ||
| status | No |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already communicate read-only, idempotent, and non-destructive behavior. The description adds meaningful behavioral context beyond those annotations: results are restricted to the configured organization and are sorted most recent first. No additional side effects, rate limits, or response details are disclosed, but the safety profile is well covered.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is a single, front-loaded sentence with no filler. It packs the resource, scope, ordering, and filters into a concise statement that earns its place.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a simple list operation with annotations covering safety, the description is mostly sufficient. However, with no output schema and no mention of pagination semantics, the documentation is not fully complete for an agent needing to use paginated results correctly. The core purpose is clear, but the page/limit handling is left to inference.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 0%, so the description must compensate. It clarifies that 'type' and 'status' are optional filters, but it does not explain the pagination parameters 'page' and 'limit', nor the meaning of the enum values ('I', 'E', 'T'; 'vigente', 'cancelado'). This leaves half the parameters semantically underdocumented.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description uses a specific verb ('Lista') and a clear resource ('CFDI timbrados'), plus the organizational scope and ordering ('más recientes primero'). It also names the optional filters, making its purpose distinct from the sibling mutation and balance tools.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description implies usage: it is a read-only listing tool for the configured organization's stamped CFDI. However, it does not explicitly state when to use this tool over alternatives or when not to use it, leaving selection to inference from the tool name and siblings.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
Tool Schema Changelog
Recent tool additions, removals, and schema changes observed during successful MCP inspections.
4 tool updates
v0.5.0- First observed
timbrix_cancelar_cfdi - First observed
timbrix_consultar_saldo - First observed
timbrix_crear_cfdi_ingreso - First observed
timbrix_listar_cfdi
TDQS
Scored across 4 tools
Cada herramienta cubre una acción distinta: timbrar, cancelar, listar y consultar saldo. No hay solapamiento real entre ellas; incluso listar y consultar saldo se diferencian claramente porque uno devuelve documentos y el otro uso mensual del plan.
Las cuatro herramientas siguen el patrón consistente timbrix_ + verbo en infinitivo + objeto: crear_cfdi_ingreso, cancelar_cfdi, listar_cfdi, consultar_saldo. La variante con subtipo en crear_cfdi_ingreso es descriptiva y no rompe la convención.
Cuatro herramientas es una cantidad adecuada para un servicio especializado de timbrado fiscal: cubre las operaciones esenciales sin inflar la superficie. No hay herramientas redundantes ni faltan piezas obvias dentro del alcance declarado.
El ciclo principal queda cubierto: crear/timbrar, cancelar, listar y monitorear saldo. Faltan detalles menores como consultar un CFDI específico por UUID o descargar el XML de uno ya timbrado, pero no son huecos que impidan el flujo de trabajo central.
Maintenance
Related MCP Connectors
Official Timbrix MCP server: stamp, cancel, and query Mexican CFDI 4.0 invoices from AI agents.
Mexico CFDI 4.0 invoices for AI agents - issue, query, cancel facturas via Facturapi.
Chile DTE for AI agents - boleta/factura electronica via OpenFactura or LibreDTE. Stateless BYO.
Brazilian fiscal MCP server - issue NF-e, NFC-e, NFS-e, CT-e, MDF-e and DC-e via SEFAZ.
Related MCP Servers
- AlicenseNot gradedqualityBmaintenanceEnables AI agents to issue Mexico CFDI 4.0 electronic invoices (factura electrónica) via Facturapi, with tools for creating, querying, canceling, and sending invoices.MIT
- AlicenseNot gradedqualityBmaintenanceMCP server that lets AI agents issue Brazilian NFS-e service invoices via Focus NFe, with tools for creating, querying, and canceling invoices.MIT

brasilnfe-mcpofficial
FlicenseNot gradedqualityDmaintenanceMCP server that exposes Brazilian tax infrastructure as tools, resources, and prompts, enabling AI agents to emit and manage fiscal documents (NF-e, NFC-e, NFS-e, CT-e, MDF-e, DC-e) through natural language.-- AlicenseAqualityAmaintenanceEnables AI assistants to access the Billingo v3 invoicing API through MCP, providing 49 read/write tools for managing invoices, partners, and related data over stdio or HTTP transports.2248 npmMIT