Skip to main content
Glama
junter1989k-ai

Vietnam Invoice MCP

README.md
# 🇻🇳 Vietnam Invoice MCP — MISA meInvoice (hóa đơn điện tử)

<!-- install-cta -->
## Use it in 60 seconds

Paste this into your MCP client config (Claude Desktop, Cursor, Windsurf, or any MCP-capable agent):

```json
{
  "mcpServers": {
    "vietnam-invoice": {
      "type": "http",
      "url": "https://inv-vn.wishpool.app/mcp"
    }
  }
}
```

Nothing to install. Credentials, when you need them, travel as HTTP headers on each request and are never stored — see the [threat model](https://mcp.wishpool.app/trust).

### Or run it yourself

Would you rather not send production credentials to a server you do not control? Deploy this identical code to your own account and point your agent at your own URL:

[![Deploy with Vercel](https://vercel.com/button)](https://vercel.com/new/clone?repository-url=https://github.com/junter1989k-ai/vietnam-invoice-mcp)

```bash
git clone https://github.com/junter1989k-ai/vietnam-invoice-mcp && cd vietnam-invoice-mcp && npx vercel --prod
```

MIT-licensed. Self-hosting removes us from the picture entirely, at no cost and with no loss of function.

---

A remote **MCP server** that lets any AI agent **create, publish and query Vietnamese e-invoices** (hóa đơn điện tử) through **MISA meInvoice**, a Tax-Department-connected e-invoicing provider. Electronic invoices have been **mandatory nationwide since 1 July 2022** (connected to the General Department of Taxation / Tổng cục Thuế).

- **Endpoint:** `https://inv-vn.wishpool.app/mcp`
- **Stateless · bring-your-own MISA token · stores nothing**
- **We only wrap the API calls — the digital signature stays merchant-side**

## What this server is (and is not)

Vietnamese e-invoices are signed with the merchant's own **digital signature (chữ ký số)** on a **USB Token** (or HSM), applied by the **MISA local signing service**. This server **never signs and never holds a certificate/USB Token**. It is a thin, stateless translation layer that:

1. `create_invoice` — builds the invoice, computes the **VAT (thuế GTGT) in VND** locally, and POSTs to MISA's `createinvoice` endpoint. MISA returns an **unsigned** invoice XML (`invoice_data`) + a `transaction_id`.
2. **You sign `invoice_data` merchant-side** with your USB Token (MISA local signing service) — this step never touches this server.
3. `publish_invoice` — forwards the signed XML to MISA's `invoicepublishing` endpoint; MISA issues the official `inv_no` / `inv_code`.
4. `query_invoice` — read-only tax-authority + publish status.

This mirrors the "we only wrap the submission" honesty of the sister servers (Saudi ZATCA, Malaysia MyInvois): the cryptographic signing never leaves the merchant.

## Connect

```json
{
  "mcpServers": {
    "vietnam-invoice": {
      "type": "http",
      "url": "https://inv-vn.wishpool.app/mcp",
      "headers": {
        "x-meinvoice-token": "your-misa-meinvoice-token",
        "x-meinvoice-taxcode": "your-company-tax-code",
        "x-meinvoice-env": "prod"
      }
    }
  }
}
```

| Header | Required | Notes |
|--------|----------|-------|
| `x-meinvoice-token` | ✅ | MISA meInvoice access token → forwarded as `Authorization: Bearer` |
| `x-meinvoice-taxcode` | ✅ | Company tax code / MST → forwarded as the `CompanyTaxCode` header |
| `x-meinvoice-env` | optional | `test` (default, sandbox `testapi.meinvoice.vn`, no fiscal effect) · `prod` (`api.meinvoice.vn`, real fiscal effect) |

Owner policy guardrails (set by the human owner in the client config; the agent cannot relax them): `x-agentpay-max-amount`, `x-agentpay-approval-above`, `x-agentpay-allowed-tools`. The cap applies to the invoice grand total (`TotalAmount`, VND) computed at create time.

## Tools

### `create_invoice` (step 1)
Build + compute VAT, POST `createinvoice`. Input: `seller{legalName,taxCode,address,…}`, `buyer{legalName|fullName,taxCode?,address,email?}`, `lines:[{name,unit?,quantity,unitPrice,taxRate?}]`, `invSeries`, optional `refId/invDate/currencyCode/withCode`. Output: `transaction_id`, `ref_id`, `invoice_data` (**unsigned XML — sign it merchant-side**), `inv_no`.

- **VAT rates:** `10` standard · `8` temporary reduced · `5` essentials · `0` exports. You choose the rate per line (tax classification is the merchant's decision).
- **Currency:** VND (đồng) — a **0-decimal integer** currency; every amount is a whole number.

### `publish_invoice` (step 3)
Forward the merchant-signed XML, POST `invoicepublishing`. Input: `transactionId`, `refId?`, `invoiceData` (the **signed** XML), `isSendEmail?`, `receiverEmail?`, `withCode?`. Output: `inv_no`, `inv_code`, `inv_series`. Common errors surfaced verbatim: `SignatureEmpty`, `InvalidSignature`, `InvoiceNumberNotContinuous`, `InvoiceDuplicated`.

### `query_invoice` (read-only)
POST `invoicepublished/invoicestatus`. Input: `transactionIds:[…]` (or single `transactionId`), `withCode?`. Output per invoice: `publish_status`, `send_tax_status` + label.

**`send_tax_status` (không mã / no code):** `0` not sent · `1` sent · `2` accepted · `3` rejected · `4` send error.
**`send_tax_status` (có mã / with code):** `0` awaiting code · `1` send error · `2` code issued · `3` code rejected.

## Path convention

MISA v3 splits by invoice type: **no-code (không mã)** = `/itg/…`, **with-code (có mã)** = `/code/itg/…`. Set `withCode` per invoice (default `false`). Base: `https://{testapi|api}.meinvoice.vn/api/v3`.

## Development

```bash
npm run dev    # local server on http://localhost:3240
npm test       # e2e: protocol + validation + VAT math + LIVE MISA InvalidTokenCode probe
```

The e2e suite makes a **real** call to `testapi.meinvoice.vn` with a fake token and asserts MISA's native `InvalidTokenCode` fingerprint — proof the integration line is wired correctly (we never sign, so a real published invoice needs a real merchant token + USB Token).

## Honest gaps

- The **prod host** `api.meinvoice.vn/api/v3` is taken from MISA's official developer intro (`doc.meinvoice.vn/api/`); only the **test** host `testapi.meinvoice.vn/api/v3` is live-verified here.
- End-to-end **publish** cannot be verified without a real MISA token **and** a merchant USB Token to sign the XML — by design, signing is merchant-side. The create/publish/query request shapes follow MISA's `InvoicePublishing` and `GetStatusInvoice` docs.

## Sister servers

Invoices: [Malaysia MyInvois](https://inv-my.wishpool.app) · [Saudi ZATCA](https://inv-sa.wishpool.app) · [Mexico CFDI](https://inv-mx.wishpool.app) · [Poland KSeF](https://inv-pl.wishpool.app) · [Chile DTE](https://inv-cl.wishpool.app) · [Brazil NF-e](https://inv-br.wishpool.app) · [Peru CPE](https://inv-pe.wishpool.app) · [India GST](https://inv-in.wishpool.app). Local payments in 81 countries: [mcp.wishpool.app](https://mcp.wishpool.app) · Logistics: [logi.wishpool.app](https://logi.wishpool.app).

MIT © 2026 WishPool

Maintenance

ActivityMaintained
ResponsivenessSyncing