Skip to main content
Glama
OrtaMarco

mx-fiscal-mcp-server

by OrtaMarco

CFDI Status at the SAT

cfdi_status
Read-onlyIdempotent

Query the SAT directly to confirm whether a Mexican CFDI invoice is still valid, cancelled or not found, using no credentials. Also returns EFOS blacklist and cancellation state.

Instructions

Ask the SAT whether an invoice actually exists and is still live. This queries the public ConsultaCFDIService SOAP endpoint — the same service the QR code printed on every Mexican invoice points at — so it needs no credentials, no CSD and no PAC contract.

Pass either the four values the SAT keys on (issuer RFC, receiver RFC, total, UUID) or the whole xml, in which case they are derived from it with the same reader parse_cfdi uses. Deriving them from the XML is the more reliable route: the total must be formatted exactly the way the printed-representation spec demands (six decimals, trailing zeros trimmed), and a hand-typed total is the single most common cause of a spurious 'No Encontrado'.

What comes back, each with its meaning spelled out:

  • Estado — Vigente / Cancelado / No Encontrado.

  • EsCancelable — whether the issuer can cancel it unilaterally, needs the receiver's approval, or cannot cancel it at all.

  • EstatusCancelacion — whether a cancellation is in progress, was accepted, was rejected, or lapsed.

  • ValidacionEFOS — whether the issuer appears on the SAT's definitive 69-B list of companies that invoice simulated operations.

  • CodigoEstatus — the service's own result code.

Fail-soft by design. The SAT publishes no rate limit, no SLA and no status page, and the endpoint does go down. On timeout, refusal or a malformed answer this returns available: false with the reason instead of raising — a failed lookup is a statement about the SAT, never about the invoice. Never report a document as invalid on the strength of an unreachable service. One retry, 10-second timeout.

Args (either shape):

  • xml (string), OR rfc_emisor + rfc_receptor + total + uuid (all strings).

  • response_format ('markdown' | 'json'): output format (default 'markdown').

Returns: { available, unavailable_reason, endpoint, expression, attempts, elapsed_ms, source, status{codigo_estatus, query_outcome, estado, document_state, document_meaning, es_cancelable, cancellable_state, cancellable_meaning, estatus_cancelacion, cancellation_state, cancellation_meaning, validacion_efos, efos_state, efos_meaning, raw} | null, findings[] }.

Example: "Is this invoice still valid?" -> cfdi_status(xml="<cfdi:Comprobante …>").

Input Schema

TableJSON Schema
NameRequiredDescriptionDefault
xmlNoThe complete CFDI XML. When given, the four query fields are derived from it and any values passed alongside are ignored.
uuidNoThe fiscal folio (UUID) from the Timbre Fiscal Digital. Required unless `xml` is given.
totalNoInvoice total exactly as written in the XML, e.g. '1160.00'. Required unless `xml` is given.
rfc_emisorNoIssuer's RFC. Required unless `xml` is given.
rfc_receptorNoReceiver's RFC. Required unless `xml` is given.
response_formatNoOutput format: 'markdown' for a human-readable summary (default) or 'json' for the full structured payload.markdown

Output Schema

TableJSON Schema
NameRequiredDescriptionDefault
sourceYes
statusYes
attemptsYes
endpointYes
findingsYes
availableYes
elapsed_msYes
expressionYes
unavailable_reasonYes

Schema Changelog

Changes observed during successful MCP inspections.

  1. First observedv1.0.0

TDQS

A4.2/5.0
Behavior3/5

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

Annotations already declare readOnlyHint, idempotentHint, openWorldHint and destructiveHint=false, so the safety profile is covered by structured data. The description nonetheless adds real behavioral context beyond annotations: no credentials/CSD/PAC required, fail-soft contract returning available:false, one retry with a 10-second timeout, and the cross-tool output schema already carries return fields. Strong additive context, but the effort is largely replicated in the output schema it also enumerates.

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?

Well front-loaded (purpose first, then argument shapes, then return semantics, then failure behavior) and the bulleted status meanings are dense but useful. It is on the long side and the 'Returns: {...}' block restates the output schema, which is minor waste.

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

Completeness5/5

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

For a read-only external-service lookup with full annotations and an output schema, the description covers everything an agent needs: input shapes, preferred path, output field meanings, and the fail-soft edge case ('a failed lookup is a statement about the SAT, never about the invoice'). Nothing material is missing.

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?

Schema coverage is 100%, so every parameter is already documented, and required-unless-xml relationships are stated in the schema itself. The description adds a genuinely useful formatting constraint ('six decimals, trailing zeros trimmed') and flags hand-typed totals as the common cause of a spurious 'No Encontrado', which is marginal added value over a fully documented schema. Baseline 3 is correct.

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

Purpose5/5

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

Specific verb+resource: 'Ask the SAT whether an invoice actually exists and is still live' via the public ConsultaCFDIService SOAP endpoint. It distinguishes itself from parse_cfdi by noting the derivation uses 'the same reader parse_cfdi uses', so an agent can tell the two apart without opening either schema.

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

Usage Guidelines5/5

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

Explicitly lays out both invocation shapes (four key fields OR the whole xml) and states which is preferred ('Deriving them from the XML is the more reliable route') with the reason. Gives a concrete example mapping a natural-language intent to the call.

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