About pop-mcp
pop-mcp is an MCP server for using POP to create and manage Italian e-invoices and invoices in several international formats. It supports hosted HTTP access or local operation, with tools for validation, submission, and document lookup.
Key features
- 01Create FatturaPA, Peppol, and KSeF invoices
- 02Generate ZUGFeRD and PDF invoices
- 03Submit invoices and check status
- 04Validate SdI documents
- 05Archive documents for Italian legal preservation
Use cases
- 01Generate and submit FatturaPA invoices for Italian business
- 02Create Peppol or KSeF electronic invoices
- 03Produce branded PDF invoices and email them
MCP support
It exposes 11 tools for invoice creation, submission, lookup, validation, and preservation to MCP clients. Clients can connect to its hosted HTTP endpoint or run the local stdio server.
Configuration
Remote servers need no local install. Pick your client, then copy the config or install in one click.
https://mcp.popapi.io/mcpclaude mcp add --transport http popapidev-pop https://mcp.popapi.io/mcp{"mcpServers":{"popapidev-pop":{"type":"http","url":"https://mcp.popapi.io/mcp"}}}Open in Cursor{"servers":{"popapidev-pop":{"type":"http","url":"https://mcp.popapi.io/mcp"}}}Open in VS Code{"mcpServers":{"popapidev-pop":{"type":"http","url":"https://mcp.popapi.io/mcp"}}}{"mcpServers":{"popapidev-pop":{"serverUrl":"https://mcp.popapi.io/mcp"}}}Run commands in a terminal; paste JSON into the client’s MCP config and restart. Servers that need sign-in will prompt on first connect.
https://mcp.popapi.io/mcpAuth requiredTools
13| Parameter | Type | Required | Description |
|---|---|---|---|
| data | object | Yes | Full invoice data object |
| data.id | integer | Yes | Invoice/order ID (numeric) |
| data.pdf | object | No | PDF generation configuration (only for create-pdf endpoint) |
| data.pdf.head | object | Yes | |
| data.pdf.head.billing | array | Yes | Billing address details |
| data.pdf.head.shipping | array | No | Shipping address details (optional) |
| data.pdf.head.store_info_address | string | Yes | Full store/company address string |
| data.pdf.logo_url | string | No | URL of company logo to include in PDF |
| data.pdf.nature_rc | string | No | VAT exemption nature code for reverse charge |
| data.pdf.total_tax | string | Yes | Total tax amount as string |
| data.pdf.footer_text | string | No | Custom footer text for the PDF |
| data.pdf.ref_norm_rc | string | No | Legal reference for reverse charge |
| data.pdf.invoice_html | enum | Yes | Whether to generate HTML invoicetrue | false |
| data.pdf.email_invoice | object | No | Email delivery configuration |
| data.pdf.email_invoice.to | array | Yes | Recipient email addresses (max 3) |
| data.pdf.email_invoice.from | string | No | Reply-to email address |
| data.pdf.doc_type_title | string | Yes | Document title shown on PDF (e.g. 'Invoice', 'Receipt', 'Credit Note') |
| data.pdf.ref_n5_normative | string | No | Legal reference for N5 (reverse charge) exemption |
| data.type | enum | Yes | Document typeinvoice | credit_note |
| data.vies | boolean | No | Whether EU VIES validation was performed for this customer |
| data.nature | string | No | VAT exemption nature code (e.g. 'N2.1', 'N3.1', 'N6.1') — required when VAT rate is 0% |
| data.version | enum | Yes | FPR12 for private/companies, FPA12 for Public AdministrationFPR12 | FPA12 |
| data.filename | string | Yes | Output filename without extension (e.g. 'IT99900088876_00009') |
| data.sdi_type | string | Yes | SDI recipient code — 7 chars ('0000000' for private individuals without SDI code) |
| data.vat_kind | enum | No | Italian VAT kind: I=Imponibile, D=Deducibile, S=ScissioneI | D | S |
| data.overrides | object | No | Optional overrides for locale and stamp settings |
| data.overrides.language | string | No | Locale override (e.g. 'it', 'en', 'de', 'fr', 'es') |
| data.overrides.bollo_force_apply | boolean | No | Force apply virtual stamp (bollo virtuale) for Italian invoices |
| data.order_items | array | Yes | Line items (products, services, shipping) |
| data.invoice_body | object | Yes | |
| data.invoice_body.general_data | object | Yes | |
| data.invoice_body.general_data.date | string | Yes | Invoice date in YYYY-MM-DD format |
| data.invoice_body.general_data.currency | string | No | ISO 4217 currency code (default: 'EUR') |
| data.invoice_body.general_data.doc_type | enum | Yes | TD01 for invoice, TD04 for credit noteTD01 | TD04 |
| data.invoice_body.general_data.invoice_number | string | Yes | Full invoice number (e.g. 'WEB9/2025') |
| data.invoice_body.general_data.invoice_prefix | string | No | Invoice number prefix (e.g. 'WEB') |
| data.invoice_body.general_data.invoice_suffix | string | No | Invoice number suffix (e.g. '9/2025') |
| data.invoice_body.total_document_amount | string|number | Yes | Total invoice amount including taxes (e.g. '122.00') |
| data.payment_data | object | Yes | |
| data.payment_data.iban | string | No | IBAN — required for MP05 (bank transfer) |
| data.payment_data.beneficiary | string | No | Bank account beneficiary name — required for MP05 (bank transfer) |
| data.payment_data.terms_payment | enum | Yes | TP01=instalment, TP02=full payment, TP03=advance paymentTP01 | TP02 | TP03 |
| data.payment_data.payment_amount | string | Yes | Payment amount (e.g. '122.00') |
| data.payment_data.payment_details | enum | Yes | Payment method: MP01=Cash, MP02=Check, MP05=Bank Transfer, MP08=Credit Card, MP12=RIBA, MP16=Direct Debit, MP19=SEPA, MP21=SEPA Core, MP22=Withholding, MP23=PagoPAMP01 | MP02 | MP05 | MP08 | MP12 | MP15 | MP16 | MP19 | MP21 | MP22 | MP23 |
| data.payment_data.financial_institution | string | No | Bank name — required for MP05 (bank transfer) |
| data.customer_type | enum | Yes | Customer categoryprivate | company | freelance | pa |
| data.ref_normative | string | No | Legal reference for VAT exemption |
| data.transfer_lender | object | Yes | Supplier/seller details |
| data.transfer_lender.place | object | Yes | |
| data.transfer_lender.place.city | string | Yes | City |
| data.transfer_lender.place.address | string | Yes | Street address |
| data.transfer_lender.place.zip_code | string | Yes | Postal/ZIP code |
| data.transfer_lender.place.country_id | string | Yes | ISO country code (e.g. 'IT') |
| data.transfer_lender.place.province_id | string | No | Province/state code (e.g. 'MI' for Milan, 'CT' for Catania) |
| data.transfer_lender.contact | object | Yes | |
| data.transfer_lender.contact.email | string | Yes | Email address |
| data.transfer_lender.contact.phone | string | Yes | Phone number |
| data.transfer_lender.personal_data | object | Yes | |
| data.transfer_lender.personal_data.last_name | string | No | Last name (for individual/freelance) |
| data.transfer_lender.personal_data.first_name | string | No | First name (for individual/freelance) |
| data.transfer_lender.personal_data.tax_id_vat | object | Yes | |
| data.transfer_lender.personal_data.company_name | string | No | Company or business name (required if not individual) |
| data.transmitter_data | object | Yes | |
| data.transmitter_data.sdi_code | string | Yes | SDI destination code — 7 characters ('0000000' for private individuals) |
| data.transmitter_data.progressive | string | Yes | Progressive transmission ID (e.g. '00001') |
| data.transmitter_data.recipient_pec | string | No | PEC (certified email) for delivery — alternative to SDI code |
| data.transmitter_data.transmitter_id | object | Yes | Transmitter tax identification |
| data.transmitter_data.transmitter_id.id_code | string | Yes | VAT number or tax ID (e.g. '12345678901' for Italy) |
| data.transmitter_data.transmitter_id.country_id | string | Yes | ISO 3166-1 alpha-2 country code (e.g. 'IT', 'DE', 'FR') |
| data.transmitter_data.transmitter_format | enum | Yes | FPR12 for private/companies, FPA12 for Public AdministrationFPR12 | FPA12 |
| data.transmitter_data.transmitter_contact | object | Yes | |
| data.transmitter_data.transmitter_contact.email | string | Yes | Transmitter email address |
| data.transmitter_data.transmitter_contact.phone | string | Yes | Transmitter phone number |
| data.transferee_client | object | Yes | Customer/buyer details |
| data.transferee_client.place | object | Yes | |
| data.transferee_client.place.city | string | Yes | City |
| data.transferee_client.place.address | string | Yes | Street address |
| data.transferee_client.place.zip_code | string | Yes | Postal/ZIP code |
| data.transferee_client.place.country_id | string | Yes | ISO country code |
| data.transferee_client.place.province_id | string | No | Province code (optional for non-Italian addresses) |
| data.transferee_client.personal_data | object | Yes | |
| data.transferee_client.personal_data.email | string | No | Customer email |
| data.transferee_client.personal_data.last_name | string | No | Customer last name |
| data.transferee_client.personal_data.first_name | string | No | Customer first name |
| data.transferee_client.personal_data.tax_id_vat | object | Yes | |
| data.transferee_client.personal_data.tax_id_code | string | No | Italian fiscal code (codice fiscale) — required for Italian private individuals |
| data.transferee_client.personal_data.company_name | string | No | Company name |
| data.purchase_order_data | object | No | Purchase order reference |
| data.purchase_order_data.id | string | Yes | Purchase order ID/number |
| data.purchase_order_data.date | string | Yes | Purchase order date in YYYY-MM-DD format |
| data.connected_invoice_data | array | No | Referenced invoices (required for credit notes) |
| site_url | string | No | Site/shop URL |
| site_title | string | No | Site/shop title |
| environment | string | No | Target environment (e.g. 'sandbox') |
| integration | any | No | Integration configuration — use this to override the default behaviour or deliver via webhook/Fatture in Cloud. Overrides submit_to_sdi if set. |
| submit_to_sdi | boolean | No | If true, automatically submits the invoice to the Italian SdI (Sistema di Interscambio). Requires active SdI via POP integration (Growth+ plan). |
| plugin_version | string | No | Caller application version |
Details
From the project READMEpop-mcp
MCP (Model Context Protocol) server for POP — enabling LLMs to generate, submit, and manage Italian e-invoices (FatturaPA/SdI), Peppol, KSeF, ZUGFeRD/Factur-X, and PDF invoices directly from AI assistants.
npm:
@getpopapi/pop-mcp· Remote:https://mcp.popapi.io/mcp
Remote MCP (HTTP) — fastest way to get started
Don't want to install anything? pop-mcp runs as a hosted, multi-tenant MCP server at:
https://mcp.popapi.io/mcp
Head to popapi.io to grab a license key, then point any MCP-speaking client at
that URL with your key as a Bearer token. No local install, no POP_API_KEY env var, no build step
— this is the recommended way to try pop-mcp for most people. Use the local stdio setup below only
if you specifically need a Claude Desktop config running a process on your own machine.
How it works
This endpoint speaks MCP 2026-07-28, which is fully stateless: there is no initialize
handshake and no session to open or track. Every request is self-contained — it names its own
protocol version and capabilities — and the server answers it independently. Because of that,
this is a multi-tenant endpoint: it never reads a fixed POP_API_KEY from its own environment.
Every request must carry your own POP license key as a Bearer token:
Authorization: Bearer <your_license_key>
A missing or malformed Authorization header returns a 401 with error_code: "unauthorized_user"
before any POP API call is made. An invalid-but-well-formed key is passed straight through to POP's
API and surfaces whatever error POP returns (unauthorized_user, insufficient_level, etc.) — the
server does not re-validate keys itself.
Any modern MCP HTTP client can connect: Claude (remote connector), the OpenAI Responses API, n8n,
MCP Inspector, or a custom integration — not
just Claude Desktop. All invoice, status, advanced, and onboarding tools are available; onboarding
tools use their own onboarding_token per call and don't require the Bearer key.
Example with curl
Discover the server's supported protocol versions and capabilities (optional — clients can also
just call tools/list or tools/call directly and handle a version-negotiation error inline):
curl -X POST https://mcp.popapi.io/mcp \
-H "Content-Type: application/json" \
-H "Authorization: Bearer your_license_key_here" \
-H "MCP-Protocol-Version: 2026-07-28" \
-H "Mcp-Method: server/discover" \
-d '{
"jsonrpc": "2.0",
"id": 1,
"method": "server/discover",
"params": { "_meta": { "io.modelcontextprotocol/protocolVersion": "2026-07-28", "io.modelcontextprotocol/clientCapabilities": {} } }
}'
List the available tools — every request is self-contained, so _meta (protocol version + client
capabilities) travels on every call, not just the first one:
curl -X POST https://mcp.popapi.io/mcp \
-H "Content-Type: application/json" \
-H "Authorization: Bearer your_license_key_here" \
-H "MCP-Protocol-Version: 2026-07-28" \
-H "Mcp-Method: tools/list" \
-d '{
"jsonrpc": "2.0",
"id": 2,
"method": "tools/list",
"params": { "_meta": { "io.modelcontextprotocol/protocolVersion": "2026-07-28", "io.modelcontextprotocol/clientCapabilities": {} } }
}'
The tool catalog is identical for every license key, so tools/list and server/discover
responses carry a one-hour public cache hint (ttlMs: 3600000, cacheScope: "public") — clients and
gateways may cache them across tenants.
MCP-Protocol-VersionandMcp-Methodare required on every request (per SEP-2243), and must match the body's_meta.protocolVersionandmethodexactly, or the server rejects the request with a400and JSON-RPC error-32020(HeaderMismatch).tools/callrequests additionally require anMcp-Nameheader matchingparams.name.
Example with MCP Inspector
npx @modelcontextprotocol/inspector
Configure it to connect to https://mcp.popapi.io/mcp with header
Authorization: Bearer <your_license_key>.
This endpoint runs as a Vercel serverless function (api/mcp.ts → src/mcpHandler.ts). To run it
locally: npx vercel dev (requires vercel link to the project first).
What is POP?
POP is a cloud service for electronic invoice generation and delivery, supporting:
- 🇮🇹 Italian e-invoicing (FatturaPA/SdI) — compliant with D.Lgs. 127/2015
- 🇪🇺 Peppol — pan-European cross-border B2B invoicing (UBL 2.1)
- 📄 PDF invoices — branded, with email delivery
- ✅ Validation — fiscal codes, VAT numbers, document pre-submission checks
- 🗄️ Preservation — Italian legal archival (conservazione sostitutiva)
Tools Available (11 total)
Invoice Creation
| Tool | Endpoint | Plan |
|---|---|---|
pop_create_sdi_invoice | POST /create-xml | Any |
pop_create_peppol_invoice | POST /create-ubl | Any (Basic+ to submit) |
pop_create_pdf_invoice | POST /create-pdf | Any (Basic+ for email) |
pop_create_ksef_invoice | POST /create-ksef-xml | Any (KSeF setup for provider submission) |
pop_create_zugferd_invoice | POST /create-zugferd | Any |
pop_sync_zoho_document | POST /integration/zoho/sync | Zoho connector required |
Status & Retrieval
| Tool | Endpoint | Plan |
|---|---|---|
pop_get_invoice_status | POST /sdi/document-notifications | Any |
pop_get_peppol_document | POST /peppol/document-get | Basic+ |
pop_get_sdi_document | POST /sdi/document-get | Basic+ |
Validation & Advanced SdI
| Tool | Endpoint | Plan |
|---|---|---|
pop_verify_sdi_document | POST /sdi/document-verify | Basic+ |
pop_preserve_document | POST /sdi/document-preserve | Basic+ |
Prerequisites
- Node.js >= 20
- A POP license key
- For SdI/Peppol submission: active integration on your POP account (Basic/Growth plan)
Authentication
Get Your License Key
New to POP? Visit popapi.io to create your account and get your license key.
API-only users can activate their account and obtain a license_key with this flow:
- Open https://popapi.io/otp-login/
- Enter your email address
- Receive a one-time password (OTP) by email and enter it
- Complete the configuration wizard
- Open https://popapi.io/ → Account > API
- Copy the default generated
license_key
Key Management
- Your account includes one default
license_key, visible under Account > API - You can generate additional keys linked to the same account from that same page
- Every
license_keymust be treated as a secret credential — do not commit it to source control
Recommended First Steps
- Get your
license_key - Test it with
GET /account-profile - Send one document-generation request with a real payload
- Add optional delivery integrations only after local generation works
Installation
From npm (recommended)
npm install -g @getpopapi/pop-mcp
From Source
git clone https://github.com/getpopapi/pop-mcp
cd pop-mcp
npm install
npm run build
Configuration
Set your POP license key as an environment variable:
export POP_API_KEY=your_license_key_here
Optional — use the staging environment:
export POP_ENVIRONMENT=staging
Claude Desktop Setup
Add to your claude_desktop_config.json:
If installed from npm:
{
"mcpServers": {
"pop": {
"command": "pop-mcp",
"env": {
"POP_API_KEY": "your_license_key_here"
}
}
}
}
If running from source:
{
"mcpServers": {
"pop": {
"command": "node",
"args": ["/path/to/pop-mcp/dist/cli.js"],
"env": {
"POP_API_KEY": "your_license_key_here"
}
}
}
}
Config file locations:
- macOS:
~/Library/Application Support/Claude/claude_desktop_config.json - Windows:
%APPDATA%\Claude\claude_desktop_config.json - Linux:
~/.config/Claude/claude_desktop_config.json
Tool Reference
The license_key is always injected automatically from POP_API_KEY — never pass it manually.
pop_create_sdi_invoice
Generate an Italian FatturaPA XML document. Optionally submit it to the SdI (Sistema di Interscambio).
MCP inputs:
| Parameter | Type | Required | Description |
|---|---|---|---|
data | object | ✅ | Full invoice data (see Invoice Data Structure) |
submit_to_sdi | boolean | — | Set true to submit to SdI. Requires Basic+ plan with active SdI integration. Default: false |
integration | object | — | Override integration config. Overrides submit_to_sdi if set. |
environment | string | — | Target environment (e.g. "sandbox") |
Integration options for integration.use:
"sdi-via-pop"or"sdi"— Submit via POP SdI"pop-to-webhook"— Deliver to a webhook (requiresid)"fatture-in-cloud"— Deliver to Fatture in Cloud
API payload sent:
{
"license_key": "YOUR_LICENSE_KEY",
"user_agent": "pop-mcp",
"user_agent_version": "1.0.0",
"data": { "...invoice fields..." },
"integration": { "use": "sdi-via-pop", "action": "create" }
}
integrationis omitted whensubmit_to_sdiisfalseand no override is provided (XML-only generation).
pop_create_peppol_invoice
Generate a Peppol UBL 2.1 document. Optionally submit it to the Peppol network.
MCP inputs:
| Parameter | Type | Required | Description |
|---|---|---|---|
data | object | ✅ | Full invoice data. customer_type must be "company" or "freelance" |
submit_to_peppol | boolean | — | Set true to submit to the Peppol network. Requires Basic+ plan. Default: false |
integration | object | — | Override integration config |
environment | string | — | Target environment |
Integration options for integration.use:
"peppol-via-pop"or"peppol"— Submit via POP Peppol"pop-to-webhook"— Deliver to a webhook (requiresid)
VAT exemption rules specific to Peppol:
data.natureis the VAT exemption code (a VATEX code such asVATEX-EU-G,VATEX-EU-IC,VATEX-EU-AEorVATEX-EU-O; these are examples, not a complete list). It stays a free string: the POP API verifies it and answers with a plain-language error.- The exemption code comes from the user. The model never chooses, infers (countries,
vies, VAT rate) or changes it, and asks when it is missing. An API error is shown to the user and the call is not retried with another code. - The API requires
data.delivery_data.country(ISO 3166-1 alpha-2, country only, never the address) when the code isVATEX-EU-IC.delivery_data.date(YYYY-MM-DD) is optional and defaults to the document date. A credit note carries the samedelivery_dataas the invoice it reverses.
API payload sent:
{
"license_key": "YOUR_LICENSE_KEY",
"user_agent": "pop-mcp",
"user_agent_version": "1.0.0",
"data": { "...invoice fields...", "nature": "VATEX-EU-IC", "delivery_data": { "country": "FR" } },
"integration": { "use": "peppol-via-pop", "action": "create" }
}
pop_create_pdf_invoice
Generate a branded PDF invoice. Optionally email it to up to 3 recipients.
MCP inputs:
| Parameter | Type | Required | Description |
|---|---|---|---|
data | object | ✅ | Invoice data. Must include data.pdf for PDF-specific settings |
send_email | boolean | — | Set true to email the PDF (requires data.pdf.email_invoice, Basic+ plan). Default: false |
environment | string | — | Target environment |
data.pdf fields:
| Field | Description |
|---|---|
doc_type_title | Title shown on document (e.g. "Invoice", "Receipt") |
logo_url | Company logo URL (HTTPS) |
head.store_info_address | Supplier address string in header |
head.billing[] | Customer billing address array |
head.shipping[] | Shipping address array (optional) |
email_invoice.to | Up to 3 recipient email addresses |
email_invoice.from | Reply-to address |
footer_text | Custom footer message |
total_tax | Total tax amount as string |
API payload sent:
{
"license_key": "YOUR_LICENSE_KEY",
"user_agent": "pop-mcp",
"user_agent_version": "1.0.0",
"data": {
"...invoice fields...",
"pdf": {
"doc_type_title": "Invoice",
"logo_url": "https://example.com/logo.png",
"head": { "store_info_address": "Via Roma 1, 00100 Roma IT", "billing": [] },
"total_tax": "22.00",
"email_invoice": { "to": ["[email protected]"] }
}
}
}
pop_create_ksef_invoice
Generate a Polish KSeF FA(3) XML invoice or credit note. Optionally submit it through a configured KSeF provider integration.
MCP inputs:
| Parameter | Type | Required | Description |
|---|---|---|---|
data | object | ✅ | Full invoice data for KSeF FA(3) generation |
integration | object | — | Optional KSeF provider submission config: { use: "ksef" | "ksef-via-pop", action } |
environment | string | — | Target environment (e.g. "sandbox") |
Domain rules specific to KSeF:
- Poland only —
transfer_lender.personal_data.tax_id_vat.country_idmust be"PL"with a 10-digit NIP asid_code customer_typemust be"company"or"freelance"(no private individuals)natureis always required at the top level for KSeF (unlike SdI/Peppol, where it's only required at 0% VAT) — reuses the same SdI nature codes (N1,N2.1,N2.2,N3.1,N3.2,N4, ...) to derive KSeF's internal fiscal varianttransmitter_datais not used (SdI-only concept)payment_data.payment_detailsonly acceptsMP01,MP02/MP03,MP05,MP08— other payment method codes are rejected at generation time- Base XML generation is available on any plan; provider submission via
integration.use: "ksef"requires a Basic+ plan and the supplier already enrolled as a KSeF legal entity in the POP dashboard
API payload sent:
{
"license_key": "YOUR_LICENSE_KEY",
"user_agent": "pop-mcp",
"user_agent_version": "1.0.0",
"data": { "...invoice fields...", "nature": "N1" },
"integration": { "use": "ksef", "action": "create" }
}
integrationis omitted entirely for local XML-only generation (no provider submission).
Returns: raw FA(3) XML (application/xml) for local generation, or JSON (with a UUID) when submitted through a provider integration.
pop_create_zugferd_invoice
Generate a ZUGFeRD/Factur-X document package: a visual PDF, an EN16931 CII XML, and a hybrid PDF/A-3 with the XML embedded.
MCP inputs:
| Parameter | Type | Required | Description |
|---|---|---|---|
data | object | ✅ | Full invoice data for ZUGFeRD/Factur-X generation |
environment | string | — | Target environment (e.g. "sandbox") |
This tool has no integration parameter — ZUGFeRD generation is local only, with no submit/delivery step.
API payload sent:
{
"license_key": "YOUR_LICENSE_KEY",
"user_agent": "pop-mcp",
"user_agent_version": "1.0.0",
"data": { "...invoice fields..." }
}
Returns: JSON with generation metadata and three Base64-encoded attachments:
{
"success": true,
"data": {
"valid": true,
"profile": "EN16931",
"attachments": {
"pdf": { "filename": "...", "mime": "application/pdf", "content_base64": "..." },
"xml": { "filename": "...", "mime": "application/xml", "content_base64": "..." },
"hybrid_pdf": { "filename": "...", "mime": "application/pdf", "content_base64": "..." }
},
"validation": { "...": "..." },
"errors": [],
"warnings": []
}
}
pop_get_invoice_status
Retrieve the SdI processing status and notifications for a submitted invoice.
MCP inputs:
| Parameter | Type | Required | Description |
|---|---|---|---|
uuid | string (UUID) | ✅ | Invoice UUID returned by pop_create_sdi_invoice when submit_to_sdi=true |
response_format | "markdown" | "json" | — | Output format. Default: "markdown" |
environment | string | — | Target environment |
API payload sent:
{
"license_key": "YOUR_LICENSE_KEY",
"integration": { "uuid": "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx" }
}
SdI notification statuses: pending · accepted · rejected · delivery
SdI processing is asynchronous and can take minutes to hours. Retry if no notifications are returned yet.
pop_get_peppol_document
Retrieve a Peppol document from the network by UUID.
MCP inputs:
| Parameter | Type | Required | Description |
|---|---|---|---|
uuid | string (UUID) | ✅ | Peppol document UUID from pop_create_peppol_invoice |
zone | string (2 chars) | — | Country code of the Peppol access point (e.g. "BE" for Belgium). Required for some regions. |
response_format | "markdown" | "json" | — | Output format. Default: "markdown" |
environment | string | — | Target environment |
API payload sent:
{
"license_key": "YOUR_LICENSE_KEY",
"integration": { "uuid": "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx", "zone": "IT" }
}
zoneis omitted from the payload if not provided.
pop_get_sdi_document
Retrieve an archived SdI (FatturaPA) document from POP storage by UUID.
MCP inputs:
| Parameter | Type | Required | Description |
|---|---|---|---|
uuid | string (UUID) | ✅ | SdI document UUID |
response_format | "markdown" | "json" | — | Output format. Default: "markdown" |
environment | string | — | Target environment |
API payload sent:
{
"license_key": "YOUR_LICENSE_KEY",
"integration": { "uuid": "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx" }
}
Requires: Basic+ plan with active SdI integration.
pop_verify_sdi_document
Validate an SdI XML document for compliance before submission. Does not submit the document.
MCP inputs:
| Parameter | Type | Required | Description |
|---|---|---|---|
xml_base64 | string | ✅ | The SdI XML document encoded as a Base64 string |
environment | string | — | Target environment |
API payload sent:
{
"license_key": "YOUR_LICENSE_KEY",
"skip_business_check": true,
"integration": { "xml": "<base64-encoded-xml-string>" }
}
Validation checks performed: XML schema conformance · fiscal code format · VAT number validity · required field presence · amount consistency
Requires: Basic+ plan with active SdI integration and registered business.
pop_preserve_document
Archive an SdI document in certified long-term digital storage (conservazione sostitutiva). Italian law requires invoices to be preserved for 10 years.
MCP inputs:
| Parameter | Type | Required | Description |
|---|---|---|---|
uuid | string (UUID) | ✅ | UUID of the SdI document to archive |
environment | string | — | Target environment |
API payload sent:
{
"license_key": "YOUR_LICENSE_KEY",
"integration": { "uuid": "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx" }
}
Important: Only call this tool when
pop_get_invoice_statusreturns statusRC(Ricevuta di Consegna) orMC(Mancata Consegna). Do not call for statusesNS,EC,SE, orDT.
Requires: Basic+ plan with active SdI integration.
Usage Examples
Generate a Simple Italian Invoice (XML Only)
Ask your AI assistant:
"Create a FatturaPA invoice for 1000€ + 22% VAT to Rossi SRL (VAT IT12345678901, Milan). My company is Bianchi SRL (VAT IT98765432109, Rome), using payment method bank transfer to IBAN IT60X0542811101000000123456."
Submit Invoice to SdI
"Create and submit to SdI an invoice #45 for consulting services, 500€ + 22% VAT to customer Mario Rossi (fiscal code RSSMRA80A01H501U) in Rome."
Check Invoice Status After Submission
"What's the status of SdI invoice with UUID abc123-def456-...?"
Generate PDF with Email Delivery
"Create a PDF invoice for order #123 and email it to [email protected]."
Verify SdI Document Before Sending
"Verify SdI document with UUID abc123-... for compliance before submission."
Plan Requirements
| Feature | Free | Basic/Growth | Pro |
|---|---|---|---|
| XML generation (local) | ✅ | ✅ | ✅ |
| PDF generation | ✅ | ✅ | ✅ |
| SdI submission | ❌ | ✅ | ✅ |
| Peppol submission | ❌ | ✅ | ✅ |
| PDF email delivery | ❌ | ✅ | ✅ |
| SdI document verification | ❌ | ✅ | ✅ |
| Document preservation | ❌ | ✅ | ✅ |
Testing
MCP Inspector (Interactive)
npm run inspector
# or
npx @modelcontextprotocol/inspector dist/cli.js
Quick Smoke Test
POP_API_KEY=your_key node -e "
import('./dist/cli.js').catch(e => {
if (e.message.includes('stdin')) process.exit(0);
console.error(e); process.exit(1);
});
"
Test Tool Schema Listing
echo '{"jsonrpc":"2.0","id":1,"method":"tools/list","params":{}}' | POP_API_KEY=test node dist/cli.js
Development
# Run with auto-reload
npm run dev
# Build
npm run build
# Clean build artifacts
npm run clean
Invoice Data Structure
The data parameter for invoice creation follows the FatturaPA structure:
data
├── id Invoice/order ID (numeric)
├── filename Output filename without extension (e.g. 'IT99900088876_00009')
├── type "invoice" | "credit_note"
├── version "FPR12" | "FPA12"
├── sdi_type 7-char SDI code ('0000000' for private individuals)
├── customer_type "private" | "company" | "freelance" | "pa"
├── nature VAT exemption code (required when rate is 0%, e.g. 'N2.1', 'N6.1')
├── transmitter_data
│ ├── transmitter_id { country_id, id_code }
│ ├── progressive Transmission progressive ID (e.g. '00001')
│ ├── transmitter_format "FPR12" | "FPA12"
│ ├── sdi_code 7-char code
│ ├── transmitter_contact { phone, email }
│ └── recipient_pec PEC email (alternative to sdi_code)
├── transfer_lender Supplier/seller
│ ├── personal_data { tax_id_vat: { country_id, id_code, tax_regime }, company_name }
│ ├── place { address, zip_code, city, province_id, country_id }
│ └── contact { phone, email }
├── transferee_client Customer/buyer
│ ├── personal_data { tax_id_vat, tax_id_code (fiscal code for IT private), company_name }
│ └── place { address, zip_code, city, province_id, country_id }
├── invoice_body
│ ├── general_data { doc_type (TD01|TD04), date (YYYY-MM-DD), invoice_number, currency }
│ └── total_document_amount
├── order_items[]
│ ├── description, quantity, unit
│ ├── unit_price, total_price
│ ├── rate VAT rate as string (e.g. '22.00')
│ ├── total_tax VAT amount (number)
│ └── item_type "product" | "shipping" | "fee"
├── payment_data
│ ├── terms_payment TP01 (instalment) | TP02 (full) | TP03 (advance)
│ ├── payment_details MP01 (Cash) | MP02 (Check) | MP05 (Bank Transfer) | MP08 (Credit Card) | ...
│ ├── payment_amount
│ ├── beneficiary Required for MP05 (bank transfer)
│ ├── financial_institution Required for MP05
│ └── iban Required for MP05
├── purchase_order_data (optional) { id, date }
├── delivery_data (optional, Peppol) { country, date? } — country required for VATEX-EU-IC
├── connected_invoice_data[] (required for credit notes) { id, date }
├── overrides (optional) { language, bollo_force_apply }
└── pdf (only for pop_create_pdf_invoice)
├── doc_type_title
├── logo_url
├── head { store_info_address, billing[], shipping[] }
├── total_tax
├── email_invoice { to[] (max 3), from }
└── footer_text
Error Reference
| Error Code | Meaning | Solution |
|---|---|---|
unauthorized_user | Invalid license key | Check POP_API_KEY |
insufficient_level | Plan too low | Upgrade POP plan |
business_not_registered | No business profile | Register on popapi.io |
integration_inactive | SdI/Peppol not enabled | Activate on popapi.io |
pop_api_email_limit | >3 email recipients | Reduce to max 3 |
pop_api_email_not_allowed | Plan doesn't allow email | Upgrade to Basic+ |
Related Projects
- n8n-nodes-pop — n8n community nodes for POP
- POP — Official website
- API Documentation — Postman docs
License
MIT © getpopapi
Comments
New to MCP?
From what the protocol is to installing your first server, these answers cover most first questions.
An open protocol that defines how AI applications connect to external tools and data in a uniform way. Clients talk to the model; MCP servers provide tools, resources and prompt templates. They exchange standard messages, so one server can be reused by many clients.