InvoiceXML

Cumplimiento global de facturación electrónica: Factur-X, Peppol UBL, CII y más

Documentación

InvoiceXML MCP Server

Un servidor de Model Context Protocol que expone la API de InvoiceXML a agentes de IA. Cubre Factur-X, ZUGFeRD, XRechnung, UBL / CII y Peppol BIS Billing 3.0.

El mismo código base se ejecuta en dos formas de despliegue, seleccionadas al inicio mediante una variable de entorno:

ModoQuién lo ejecutaAutenticación
AutohospedadoTú, en tu propia máquina o servidorUna única clave de API en env o appsettings.json
HospedadoInvoiceXML, en su propia infraestructuraOAuth 2.1 + Registro dinámico de clientes contra invoicexml.com

Ambos ejecutan el mismo binario; solo difiere la configuración. El repositorio es independiente de la plataforma: no sabe nada sobre dónde ni cómo lo alojas.

Arquitectura

+----------------------+   ProjectReference   +----------------------+
|  InvoiceXml.Mcp.Core | -------------------> |  InvoiceXml.Mcp.Host |
|  (SDK: client+tools) |                      |  (the deployable)    |
+----------------------+                      +----------------------+

InvoiceXml.Mcp.Core es un SDK pequeño e independiente del transporte:

  • IInvoiceXmlClient — cliente tipado sobre la API REST pública
  • HttpInvoiceXmlClient — la única implementación; consume un HttpClient de IHttpClientFactory
  • InvoiceXmlClientOptions — URL base, tiempo de espera (sin autenticación)
  • AddInvoiceXmlMcpCore(IServiceCollection, IConfiguration) — punto de entrada de DI; devuelve el IHttpClientBuilder para que el host adjunte la autenticación como DelegatingHandler

El SDK nunca ve credenciales. El host las aplica a través de la canalización HTTP. Esa costura es lo que permite que un solo código base sirva para ambos modos de despliegue.

InvoiceXml.Mcp.Host es una aplicación ASP.NET Core 10:

  • Lee Mcp:AuthMode (ApiKey o OAuth) al inicio
  • Conecta el DelegatingHandler correspondiente al cliente HTTP de Core mediante AddHostAuth(...)
  • Sirve el endpoint MCP en POST /, una página de bienvenida amigable en GET / y /health

Añadir un nuevo modo de autenticación = una rama en AuthExtensions.cs más una pequeña carpeta en Auth/<Mode>/. Añadir una nueva herramienta = una clase [McpServerTool]. Nada más cambia.

Estructura del repositorio

invoicexml-mcp/
├── src/
│   ├── InvoiceXml.Mcp.Core/              # the SDK: client, models, tools
│   │   ├── Enums/  Interfaces/  Models/  Options/  Services/  Tools/  Extensions/
│   └── InvoiceXml.Mcp.Host/              # the deployable host
│       ├── Auth/{ApiKey,OAuth}/          # the two auth modes
│       ├── Configuration/
│       ├── Program.cs
│       └── appsettings.json              # safe defaults, no secrets
├── tests/
│   ├── InvoiceXml.Mcp.Core.Tests/
│   └── InvoiceXml.Mcp.Host.Tests/
├── Directory.Build.props                 # repo-wide MSBuild defaults
├── Directory.Packages.props              # Central Package Management
├── global.json                           # pins the .NET SDK
└── InvoiceXml.Mcp.slnx

Ejecución local

Necesitas un SDK de .NET 10 y una clave de API de InvoiceXML.

# 1. Provide your API key (pick one):

# A. dotnet user-secrets (recommended — kept outside the repo)
dotnet user-secrets --project src/InvoiceXml.Mcp.Host set "Mcp:ApiKey:Value" "your-key"

# B. environment variable
$env:INVOICEXML_API_KEY = "your-key"

# 2. Run
dotnet run --project src/InvoiceXml.Mcp.Host

GET http://localhost:5004/ muestra una página de bienvenida en el navegador; el endpoint MCP es POST http://localhost:5004/; GET /health devuelve { "status": "ok" }.

Configuración

{
  // Required in OAuth mode. The public origin where this MCP server is reachable.
  // Used in the protected-resource metadata response.
  "McpUri": "https://mcp.example.com",

  "InvoiceXml": {
    "BaseUrl": "https://api.invoicexml.com",   // override for staging / local
    "Timeout": "00:01:40"
  },

  "Mcp": {
    "AuthMode": "ApiKey",                       // "ApiKey" | "OAuth"
    "ApiKey": {
      "Value": ""                               // ApiKey mode: NEVER commit a real key
    },
    "OAuth": {
      "AuthorizationServer": "https://invoicexml.com",
      "ScopesSupported": [ "api_token.read" ]
    },
    "FileInput": {                              // limits for the URL-fetch input mode
      "MaxFileSizeBytes": 5242880,
      "FetchTimeout": "00:00:30"
    }
  }
}

Equivalentes de variables de entorno (doble guion bajo = anidación):

VariableSe asigna a
INVOICEXML_API_KEYMcp:ApiKey:Value (alias amigable)
Mcp__ApiKey__ValueMcp:ApiKey:Value
Mcp__AuthModeMcp:AuthMode (ApiKey o OAuth)
Mcp__OAuth__AuthorizationServerMcp:OAuth:AuthorizationServer
McpUriMcpUri (nivel raíz)
InvoiceXml__BaseUrlInvoiceXml:BaseUrl

Modo OAuth

Cuando Mcp:AuthMode=OAuth, el host deja de aceptar una clave de API estática y en su lugar:

  1. Devuelve 401 con WWW-Authenticate: Bearer resource_metadata="…" para cualquier POST / que no tenga token Bearer.
  2. Sirve GET /.well-known/oauth-protected-resource apuntando a los clientes MCP hacia invoicexml.com como servidor de autorización.
  3. Reenvía el token Bearer entrante tal cual en cada llamada saliente a la API de InvoiceXML (la API es la fuente de verdad para la validez del token; el servidor MCP no valida tokens localmente).

La secuencia que realiza un cliente MCP:

client → MCP  POST /                           → 401 + resource_metadata
client → /.well-known/oauth-protected-resource → { authorization_servers: [invoicexml.com] }
client → invoicexml.com/.well-known/oauth-authorization-server
                                               → { authorize, token, register endpoints }
client → invoicexml.com/oauth/register         → client_id + client_secret  (DCR)
client → invoicexml.com/oauth/authorize        → user consents, gets code
client → invoicexml.com/oauth/token            → access_token  (= user's API key)
client → MCP  POST /  + Authorization: Bearer  → 200, tool call flows through

Despliegue

El host es una aplicación ASP.NET Core estándar: ejecútala como ejecutes servicios .NET (systemd, un contenedor, un PaaS, etc.; el repositorio no prescribe uno):

dotnet publish src/InvoiceXml.Mcp.Host -c Release -o ./publish
# then run ./publish/InvoiceXml.Mcp.Host on your host

Configura mediante variables de entorno en el host (nunca confirmes secretos):

  • ASPNETCORE_ENVIRONMENT=Production
  • Mcp__AuthMode=ApiKey (o OAuth)
  • Mcp__ApiKey__Value=… / INVOICEXML_API_KEY=… (modo ApiKey)
  • McpUri=https://your-public-url y Mcp__OAuth__AuthorizationServer=https://invoicexml.com (modo OAuth)

Termina TLS en tu proxy inverso / balanceador de carga y reenvía al puerto HTTP del host. El servidor no tiene estado, por lo que puedes ejecutar varias instancias detrás de un balanceador de carga.

Licencia

MIT — consulta LICENSE.