InvoiceXML
Conformidade global de faturamento eletrônico: Factur-X, Peppol UBL, CII e mais
Documentação
Servidor MCP InvoiceXML
Um servidor Model Context Protocol que expõe a API InvoiceXML para agentes de IA. Cobre Factur-X, ZUGFeRD, XRechnung, UBL / CII e Peppol BIS Billing 3.0.
O mesmo código-fonte roda em duas formas de implantação, selecionadas na inicialização por uma variável de ambiente:
| Modo | Quem executa | Autenticação |
|---|---|---|
| Auto-hospedado | Você, na sua própria máquina ou servidor | Uma única chave de API no ambiente ou appsettings.json |
| Hospedado | InvoiceXML, na sua própria infraestrutura | OAuth 2.1 + Registro Dinâmico de Cliente contra invoicexml.com |
Ambos executam o mesmo binário; apenas a configuração difere. O repositório é independente de plataforma — ele não sabe nada sobre onde ou como você o hospeda.
Arquitetura
+----------------------+ ProjectReference +----------------------+
| InvoiceXml.Mcp.Core | -------------------> | InvoiceXml.Mcp.Host |
| (SDK: client+tools) | | (the deployable) |
+----------------------+ +----------------------+
InvoiceXml.Mcp.Core é um SDK pequeno e agnóstico de transporte:
IInvoiceXmlClient— cliente tipado sobre a API REST públicaHttpInvoiceXmlClient— a única implementação; consome umHttpClientdeIHttpClientFactoryInvoiceXmlClientOptions— URL base, tempo limite (sem autenticação)AddInvoiceXmlMcpCore(IServiceCollection, IConfiguration)— ponto de entrada de injeção de dependência; retorna oIHttpClientBuilderpara que o host anexe autenticação como umDelegatingHandler
O SDK nunca vê credenciais. O host as aplica através do pipeline HTTP. Essa costura é o que permite que um único código-fonte atenda a ambos os modos de implantação.
InvoiceXml.Mcp.Host é um aplicativo ASP.NET Core 10:
- Lê
Mcp:AuthMode(ApiKeyouOAuth) na inicialização - Conecta o
DelegatingHandlercorrespondente ao cliente HTTP Core viaAddHostAuth(...) - Serve o endpoint MCP em
POST /, uma página de boas-vindas amigável emGET /e/health
Adicionar um novo modo de autenticação = um braço em AuthExtensions.cs mais uma pequena pasta em
Auth/<Mode>/. Adicionar uma nova ferramenta = uma classe [McpServerTool]. Nada mais muda.
Estrutura do repositório
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
Executando localmente
Você precisa de um SDK .NET 10 e uma chave de API 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/ mostra uma página de boas-vindas no navegador; o endpoint MCP é
POST http://localhost:5004/; GET /health retorna { "status": "ok" }.
Configuração
{
// 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 variáveis de ambiente (sublinhado duplo = aninhamento):
| Variável | Mapeia para |
|---|---|
INVOICEXML_API_KEY | Mcp:ApiKey:Value (alias amigável) |
Mcp__ApiKey__Value | Mcp:ApiKey:Value |
Mcp__AuthMode | Mcp:AuthMode (ApiKey ou OAuth) |
Mcp__OAuth__AuthorizationServer | Mcp:OAuth:AuthorizationServer |
McpUri | McpUri (nível raiz) |
InvoiceXml__BaseUrl | InvoiceXml:BaseUrl |
Modo OAuth
Quando Mcp:AuthMode=OAuth o host para de aceitar uma chave de API estática e em vez disso:
- Retorna 401 com
WWW-Authenticate: Bearer resource_metadata="…"para qualquerPOST /que não tenha um token Bearer. - Serve
GET /.well-known/oauth-protected-resourceapontando clientes MCP parainvoicexml.comcomo o servidor de autorização. - Encaminha o token Bearer recebido literalmente em cada chamada de saída para a API InvoiceXML (a API é a fonte da verdade para validade do token; o servidor MCP não valida tokens localmente).
A dança que um cliente MCP executa:
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
Implantação
O host é um aplicativo ASP.NET Core padrão — execute-o da maneira que você executa serviços .NET (systemd, um contêiner, um PaaS, etc.; o repositório não prescreve um):
dotnet publish src/InvoiceXml.Mcp.Host -c Release -o ./publish
# then run ./publish/InvoiceXml.Mcp.Host on your host
Defina a configuração via variáveis de ambiente no host (nunca confirme segredos):
ASPNETCORE_ENVIRONMENT=ProductionMcp__AuthMode=ApiKey(ouOAuth)Mcp__ApiKey__Value=…/INVOICEXML_API_KEY=…(modo ApiKey)McpUri=https://your-public-urleMcp__OAuth__AuthorizationServer=https://invoicexml.com(modo OAuth)
Encerre o TLS no seu proxy reverso / balanceador de carga e encaminhe para a porta HTTP do host. O servidor não tem estado, então você pode executar várias instâncias atrás de um balanceador de carga.
Licença
MIT — veja LICENSE.