Fiscalapi MCP

Fiscalapi MCP connects your tenant (the space in Fiscalapi that holds your issuers, recipients, credits, and data) to an AI client such as Claude Code, Cursor, or Codex, or to your own app or agent. Issue, look up, and cancel CFDI 4.0 invoices (CFDI: Mexico's electronic invoice) with the same permissions and credits as the API, at no extra cost.

How it works

Fiscalapi MCP is a remote Model Context Protocol server with the streamable HTTP transport. Your client or your app connects with an API key and your tenant, and each tool calls the Fiscalapi API with that credential:

  • The agent can do what the person (any individual or legal entity registered in your tenant) who owns the API key can do, with that person's permissions.
  • Each CFDI the agent issues uses one stamp (one credit, used each time you stamp a CFDI), as in the API.
  • The API applies the tax rules and validations. A rejection reaches the agent with its details and, if it carries a SAT (Mexico's tax authority, Servicio de Administración Tributaria) or PAC (Proveedor Autorizado de Certificación, a SAT-authorized provider that stamps CFDIs) code, with the errors page that explains it.

You can connect it in two ways, with the same server and the same tools:

WayWhat it's for
From your app or agentYour product's backend or your own agent connects with an MCP SDK and gives the tools to its model.
From an AI clientYou add the server to an assistant, such as Claude Code or Cursor, and ask for what you need in the chat.

It authenticates the same way as the API: with your API key and your tenant (see Credentials). It doesn't use OAuth, so you can't connect from ChatGPT or from claude.ai connectors.

Environments

Each connection works in a single environment, the one in its URL:

EnvironmentURLWhat it does
Testhttps://test.mcp.fiscalapi.com/mcpStamping (the certification by a SAT-authorized provider that makes a CFDI valid) runs on the test PAC. The invoices have no tax validity.
Productionhttps://live.mcp.fiscalapi.com/mcpStamps real CFDIs with the SAT and uses stamps.

The API key must belong to the same environment as the URL: a test API key doesn't work in production. Start in test, and switch the URL and the API key when your flow is ready.

Credentials

The server requires two headers on every request, the same ones as the API:

HeaderValue
X-API-KEYAn API key dedicated to the MCP.
X-TENANT-KEYYour tenant.

Create an API key only for the MCP in Get credentials and assign it to the person whose permissions you want to give the agent. You can revoke it at any time without affecting your other integrations.

Store both credentials in environment variables. The examples in this guide read them from FISCALAPI_API_KEY and FISCALAPI_TENANT_KEY, and none of them writes their values to a configuration file, so they don't end up in a repository. Don't paste the API key into the agent's chat.

Environment variables

# Add them to your ~/.zshrc or ~/.bashrc and open a new terminal.
export FISCALAPI_API_KEY='<tu-api-key>'
export FISCALAPI_TENANT_KEY='<tu-tenant>'

An AI client reads the variables when it starts: after you set them, quit it completely and open it again. On macOS, an editor you open from the Dock might not see your terminal's variables; open it from the terminal.

In your app, the credentials live on its server: in environment variables or in your platform's secrets manager. Never send them to the browser or include them in your frontend code: anyone can see them there, and the MCP rejects requests that come from a web page.

CSDs (Certificado de Sello Digital, the digital seal certificate used to sign CFDIs) and the e.firma (the SAT advanced electronic signature that identifies a taxpayer, formerly FIEL) never travel through the MCP. Upload them in the dashboard or with Upload tax files. To issue, the agent uses a person whose CSD is already uploaded as the issuer, and no tool accepts certificates, private keys, or passwords.

Connection details

These details work for any client or app that connects to a remote MCP server:

DetailValue
Test URLhttps://test.mcp.fiscalapi.com/mcp
Production URLhttps://live.mcp.fiscalapi.com/mcp
Read-only test URLhttps://test.mcp.fiscalapi.com/mcp/readonly
Read-only production URLhttps://live.mcp.fiscalapi.com/mcp/readonly
TransportStreamable HTTP.
HeadersX-API-KEY and X-TENANT-KEY on every request, the same as the API.
SessionStateless: the server doesn't keep a session between requests.
Where to call it fromFrom a server, a desktop app, or a terminal. The server rejects any request that carries an Origin header, like one from a web page.

Because the server doesn't keep a session, your app can open one connection per task or reuse the same one, and it can connect from serverless functions.

From your app or agent

Your backend connects with the MCP SDK for its language. The examples connect to the test environment, list the tools, and call fiscalapi_get_tenant_overview:

Connect from your app

// npm install @modelcontextprotocol/client
import { Client, StreamableHTTPClientTransport } from '@modelcontextprotocol/client';

const transport = new StreamableHTTPClientTransport(new URL('https://test.mcp.fiscalapi.com/mcp'), {
  requestInit: {
    headers: {
      'X-API-KEY': process.env.FISCALAPI_API_KEY!,
      'X-TENANT-KEY': process.env.FISCALAPI_TENANT_KEY!
    }
  }
});
const client = new Client({ name: 'mi-app', version: '1.0.0' });
await client.connect(transport);

const { tools } = await client.listTools();
// An issuance can take longer than 60 seconds: wait up to 120.
const result = await client.callTool(
  { name: 'fiscalapi_get_tenant_overview', arguments: {} },
  { timeout: 120_000 }
);

await client.close();

In your own agent, your app lists the tools and gives them to its model with their name, description, and input schema, through your provider's tool use or function calling. When the model picks a tool, your app runs it with callTool and returns the result to the model.

If you build your agent with a framework that accepts a remote MCP server over streamable HTTP with custom headers, configure it with the URL and the two headers in Connection details.

Timeouts and retries

  • An issuance can take longer than 60 seconds. Set a timeout of at least 120 seconds per call.
  • Each issuance tool requires an idempotencyKey. Generate a new key for each issuance; if a call is cut off, repeat it with the same key: if it was already stamped, you get the same invoice.
  • Each credential has its own request limit. If you get a 429, wait the number of seconds in the Retry-After header.

Confirmation to issue and cancel in your app

The 7 issuance tools and fiscalapi_cancel_invoice ask for confirmation from the server only if your client declares the form elicitation capability and negotiates the 2026-07-28 version of the protocol, the one that adds input requests across several round trips. In that case, the call responds with an input request that carries a summary of the operation: show it to the person and repeat the call with their answer.

If your client doesn't declare elicitation, the tool runs as soon as you call it. Your app is responsible for asking the person for confirmation before it calls those tools, or for connecting to the read-only path.

Prompts in your app

You list the 3 prompts with prompts/list and get each one with prompts/get.

From an AI client

These are the steps for the most common clients. Any other client that accepts a remote MCP server with headers connects with the Connection details.

The examples use the test environment. For production, change test to live in the URL and use a production API key.

Claude Code

Add the server with a command. The single quotes store a reference to the variable, not its value, and Claude Code resolves it each time it connects:

Claude Code

claude mcp add --transport http fiscalapi https://test.mcp.fiscalapi.com/mcp \
  --header 'X-API-KEY: ${FISCALAPI_API_KEY}' \
  --header 'X-TENANT-KEY: ${FISCALAPI_TENANT_KEY}'

The command adds the server for the current project only; with --scope user, it's available in all your projects. To share it with your team, use the .mcp.json file at the project root: Claude Code asks you to approve it the first time.

Check the connection with claude mcp list, which should show fiscalapi as connected. Inside Claude Code, /mcp shows its tools.

Cursor

Add the server to ~/.cursor/mcp.json, or to .cursor/mcp.json for a single project. Cursor resolves ${env:...} in the headers:

~/.cursor/mcp.json

{
  "mcpServers": {
    "fiscalapi": {
      "url": "https://test.mcp.fiscalapi.com/mcp",
      "headers": {
        "X-API-KEY": "${env:FISCALAPI_API_KEY}",
        "X-TENANT-KEY": "${env:FISCALAPI_TENANT_KEY}"
      }
    }
  }
}

The fiscalapi tools appear in Cursor's MCP settings. If it doesn't connect, check the Output panel, in the MCP Logs channel.

VS Code

With the GitHub Copilot agent, add the server to .vscode/mcp.json. Each credential goes in an input with password, and VS Code prompts you for it the first time the server starts.

VS Code

{
  "inputs": [
    {
      "type": "promptString",
      "id": "fiscalapi-api-key",
      "description": "API key de Fiscalapi",
      "password": true
    },
    {
      "type": "promptString",
      "id": "fiscalapi-tenant-key",
      "description": "Tenant de Fiscalapi",
      "password": true
    }
  ],
  "servers": {
    "fiscalapi": {
      "type": "http",
      "url": "https://test.mcp.fiscalapi.com/mcp",
      "headers": {
        "X-API-KEY": "${input:fiscalapi-api-key}",
        "X-TENANT-KEY": "${input:fiscalapi-tenant-key}"
      }
    }
  }
}

The VS Code Local harness reads that file. If your chat sessions use the Copilot harness, configure the server in ~/.copilot/mcp-config.json, which reads the environment variables. Check the connection with the MCP: List Servers command.

Codex

Add the server to ~/.codex/config.toml. env_http_headers maps each header to the name of its environment variable, and tool_timeout_sec gives issuances enough time, since they can take longer than the 60 seconds Codex waits by default:

~/.codex/config.toml

[mcp_servers.fiscalapi]
url = "https://test.mcp.fiscalapi.com/mcp"
env_http_headers = { "X-API-KEY" = "FISCALAPI_API_KEY", "X-TENANT-KEY" = "FISCALAPI_TENANT_KEY" }
tool_timeout_sec = 120

codex mcp add doesn't accept headers, so you add the server in the file. Check the configuration with codex mcp list; inside Codex, /mcp shows its tools. If a variable isn't set, Codex doesn't send its header and the server responds with a 401.

Windsurf

In Cascade, open the MCP menu and choose Open MCP config file. Add the server; Windsurf resolves ${env:...} in the headers:

mcp_config.json

{
  "mcpServers": {
    "fiscalapi": {
      "serverUrl": "https://test.mcp.fiscalapi.com/mcp",
      "headers": {
        "X-API-KEY": "${env:FISCALAPI_API_KEY}",
        "X-TENANT-KEY": "${env:FISCALAPI_TENANT_KEY}"
      }
    }
  }
}

Save the file and press the refresh button in the MCP panel to load the tools.

Read-only

For an agent that only looks things up, connect it to the read-only path of its environment instead of /mcp. That path publishes only the 10 read tools and no prompts.

EnvironmentRead-only URL
Testhttps://test.mcp.fiscalapi.com/mcp/readonly
Productionhttps://live.mcp.fiscalapi.com/mcp/readonly

The path limits what the agent sees, not the API key: with the same key, another connection to /mcp can still issue and cancel. Use it to analyze received CFDIs or webhook events (see Third-party content).

Tools

ToolWhat it doesRead
fiscalapi_get_tenant_overviewThe environment, the person who owns the API key, their credit balance, their CSDs and e.firma with their validity periods, and their recent credit movements.Yes
fiscalapi_search_peopleSearches people by legal name (as registered with the SAT), RFC (Mexico's taxpayer ID, Registro Federal de Contribuyentes), or email, or gets one by ID with the details of their tax files (the CSD and e.firma .cer and .key files you upload for a person).Yes
fiscalapi_create_personRegisters a person with their tax details.No
fiscalapi_update_personUpdates a person's tax details.No
fiscalapi_search_productsSearches CFDI products by description or SAT key, or gets one by ID.Yes
fiscalapi_create_productRegisters a CFDI product.No
fiscalapi_update_productReplaces a CFDI product's details.No
fiscalapi_search_sat_catalogSearches keys in the SAT catalogs.Yes
fiscalapi_list_invoicesLists the issued invoices, most recent first, with optional filters.Yes
fiscalapi_get_invoiceGets an invoice by ID.Yes
fiscalapi_get_invoice_sat_statusChecks the status of an invoice and its cancellation with the SAT.Yes
fiscalapi_issue_income_invoiceIssues an income invoice.No
fiscalapi_issue_credit_noteIssues a credit note (an Egreso CFDI, type E).No
fiscalapi_issue_payment_invoiceIssues a Payments 2.0 payment complement (the complement that records each payment received against a PPD invoice; the type P CFDI that carries it is also called REP).No
fiscalapi_issue_global_invoiceIssues a global invoice (factura global, one CFDI that groups a period's sales to the general public).No
fiscalapi_issue_payroll_invoiceIssues a payroll CFDI (the CFDI issued for each salary payment, type N).No
fiscalapi_issue_bill_of_lading_invoiceIssues a CFDI with the Carta Porte (the CFDI complement that documents the transport of goods in Mexico) complement (complemento, an XML extension the SAT defines for specific operations).No
fiscalapi_issue_foreign_trade_invoiceIssues a CFDI with the Comercio Exterior (the CFDI foreign trade complement for exports) complement.No
fiscalapi_cancel_invoiceCancels an invoice with the SAT, giving its cancellation reason (one of the SAT keys 01 to 04).No
fiscalapi_send_invoice_emailEmails an invoice's XML and PDF.No
fiscalapi_check_tin_sat_listsChecks whether an RFC appears in the SAT's Lista 69-B (the SAT list of taxpayers presumed to issue invoices for nonexistent transactions, under Article 69-B of the Federal Tax Code) and Lista 69-B Bis (the SAT list of taxpayers involved in a presumed improper transfer of the right to offset tax losses, under Article 69-B Bis of the Federal Tax Code).No
fiscalapi_list_sat_download_rulesLists the download rules for bulk download (the SAT service that delivers the CFDIs a taxpayer issued and received).Yes
fiscalapi_create_sat_download_ruleCreates a bulk download rule.No
fiscalapi_request_sat_downloadRequests a bulk download for a period from the SAT.No
fiscalapi_get_sat_downloadGets the status of a bulk download request and, once it finishes, a summary of its documents.Yes
fiscalapi_list_webhook_eventsLists the events of the last 30 days and their deliveries to your webhooks.Yes
fiscalapi_resend_webhook_eventResends an event to a webhook or to your CLI listener.No

The tools don't manage API keys, tax files, or webhooks, and they don't delete records. For that, use the dashboard or the API.

Prompts

The prompts guide the agent through a complete flow and ask for your confirmation before they issue or cancel. Depending on the client, they appear as chat commands.

PromptWhat it does
fiscalapi_guided_invoiceIssues an income invoice step by step: issuer, recipient, line items, and payment method.
fiscalapi_guided_paymentIssues the payment complement for a payment received against PPD (paid in installments or later, Pago en parcialidades o diferido) invoices.
fiscalapi_guided_cancellationCancels an invoice with its reason and checks its status with the SAT.

Credits and recurring effects

The MCP uses the same credits as the API. Check your balance with fiscalapi_get_tenant_overview or in the dashboard.

ToolUsage or effect
The 7 issuance tools1 stamp per CFDI issued.
fiscalapi_check_tin_sat_lists1 validation credit per list checked, even if the RFC doesn't appear.
fiscalapi_create_sat_download_ruleThe rule is approved when it's created: Fiscalapi downloads the previous day's documents from the SAT every day, and the rule takes up a seat (one RFC and one download type in bulk download) while it exists.

The other tools don't use credits. The test environment has no connection to the SAT: creating a download rule responds with a 403, and fiscalapi_request_sat_download creates a test request with up to 3 recent CFDIs from your tenant.

People and dashboard access

A person the agent creates has no password and no dashboard access: they can't sign in to the dashboard. If they need to, the owner (the person who created the tenant) gives them access from the dashboard or with loginEnabled in the Issuers API. The MCP tools never change a person's email, password, or dashboard access.

Security

Data the model provider receives

What you write in the chat or what your app sends to the model, and what the tools return (RFCs, legal names, payroll, line items), reaches the provider of the model that your client or your app uses. Review its terms before you work with real data.

Confirmation to issue and cancel

The 7 issuance tools and fiscalapi_cancel_invoice ask for your confirmation from the server, with a summary of what they'll do, in clients that support the MCP confirmation (elicitation). If you decline, nothing is issued or canceled.

In other clients, the confirmation is your client's tool approval. If you turn on its automatic approval, the agent issues and cancels without asking you. In your own app, asking for the confirmation is your app's job (see From your app or agent).

If your client declares the confirmation but no one is there to answer it (a non-interactive mode or a script), issuance and cancellation don't run. To automate without a person present, use the API or the SDKs.

XML and PDF files

No tool returns the XML or the PDF in the chat. fiscalapi_send_invoice_email emails them to the invoice's recipient or to the address you specify.

Third-party content

Received CFDIs and webhook events carry text that someone else writes, such as legal names and line item descriptions. The server tells the agent that this text is data, not an instruction, but an agent with write tools can be steered by it. To analyze that content, connect to the read-only path.

Troubleshooting

SymptomCauseWhat to do
401 with Missing required http X-API-KEY. or Missing required http X-TENANT-KEY.The client didn't send the header: the variable isn't set where the client runs.Set the variables and restart the client or your app completely.
401 with Invalid API KEYThe API key doesn't exist, is revoked, or belongs to another environment.Use an active API key from the same environment as the URL.
The client says the server requires authentication, or opens a sign-in flowThe server responded with a 401 and the client tries OAuth, which this version doesn't support.Don't complete that sign-in. Check the variables and the API key as in the two rows above.
403 with Origin no permitido. (origin not allowed)The request carries an Origin header, like one from a web page.Call the MCP from your app's backend or from a desktop or terminal client, never from the browser.
429 with Se superó el límite de solicitudes de esta credencial; intenta de nuevo en unos segundos. (the credential exceeded its request limit)The agent made too many requests with that credential.Wait the number of seconds in the Retry-After header.
503 with La API de Fiscalapi no está disponible; intenta de nuevo en unos segundos. (the Fiscalapi API isn't available)The API didn't respond.Try again in a few seconds.
An issuance responds with a 403 for an insufficient stamp balanceYou're out of stamps, or the person who owns the API key isn't allowed to issue.Check the balance with fiscalapi_get_tenant_overview, buy stamps, and issue with a new idempotencyKey.
An issuance responds with a 409An issuance with the same idempotencyKey is still in progress.Retry with the same key in a few seconds: if it was already stamped, it returns the same invoice.
An issuance responds with a 422An idempotencyKey was reused with different content.Use a new key for each different issuance. Details in Idempotent requests.
Codex stops an issuance because it timed outIts default wait is 60 seconds.Raise tool_timeout_sec. To retry, use the same idempotencyKey or look for the invoice with fiscalapi_list_invoices.
Your app stops an issuance because it timed outThe timeout of your MCP client or your HTTP client is shorter than the time the issuance took.Raise the timeout to 120 seconds or more. To retry, use the same idempotencyKey or look for the invoice with fiscalapi_list_invoices.

Fiscalapi MCP and docs-mcp

They're two different servers that complement each other. Connect both if your agent also writes code that integrates the API.

Fiscalapi MCPdocs-mcp
PurposeWork in your tenant: issue, look up, and cancel.Write your integration: look up the OpenAPI spec and the documentation.
Where it runsA remote Fiscalapi server.On your computer, with npx.
CredentialsAPI key and tenant.None; it doesn't call the API.

You install docs-mcp separately, as @fiscalapi/docs-mcp; the instructions for each client are in its repository.

Was this page helpful?