Skip to main content

MCP server wrapping the Universal EC (汎宇電商) Taiwan e-invoice POS Web Service into 27 AI Agent-callable tools

Project description

MCP Universal EC E-Invoice Server

PyPI version Python versions License: MIT

繁體中文

An open-source MCP (Model Context Protocol) server wrapping the Universal EC (汎宇電商) Taiwan E-Invoice POS Web Service (JSON format, MIG4.1). Exposes 27 AI-callable tools covering all available function codes via stdio JSON-RPC 2.0.

Built for Claude Code and any MCP-compatible AI client. Enables AI agents to issue invoices, void invoices, manage invoice numbers, query cancellation status, and handle allowances through natural language.

Features

  • 27 MCP tools — Full coverage of all Universal EC e-invoice API function codes
  • stdio JSON-RPC 2.0 — Standard MCP transport protocol
  • 3 wrapper formats — INDEX, Invoice, Allowance (auto-selected per function)
  • Credential injection — SELLERID/POSID/POSSN auto-injected by connector
  • TDD tested — 53 unit tests + 5 live regression tests

Quick Start

# Setup
uv venv && source .venv/bin/activate
uv pip install -e ".[dev]"

# Configure credentials
cp .env.example .env
# Edit .env with your Universal EC credentials

# Run server
python mcp_server.py

Configuration

Create a .env file with your Universal EC POS credentials:

EINVOICE_BASE_URL=https://epostw.einvoice.com.tw/GetInvoice.ashx
EINVOICE_SELLER_ID=your_seller_id
EINVOICE_POS_ID=your_pos_id
EINVOICE_POS_SN=your_pos_sn
Environment URL
Test (測試機) https://epostw.einvoice.com.tw/GetInvoice.ashx
Production (正式機) https://eposw.einvoice.com.tw/GetInvoice.ashx

Project Structure

mcp-universalec-e-invoice/
├── app.py                          # FastMCP singleton
├── mcp_server.py                   # Entry point (stdio transport)
├── config/
│   └── settings.py                 # URL + credentials from .env
├── connectors/
│   └── einvoice_client.py          # Single POST connector (3 wrappers)
├── tools/
│   ├── system_tools.py             # Y01
│   ├── invoice_number_tools.py     # A01, C01, Z21, Z22
│   ├── b2c_invoice_tools.py        # C0401, C0401N, C0501
│   ├── b2b_invoice_tools.py        # A0401, A0501, A0101, A0201
│   ├── allowance_tools.py          # D0401, D0401N, D0501, B0401, B0501, B0101
│   ├── cancel_tools.py             # C0701, B0701
│   ├── query_tools.py              # Z11, Z31, Z33, Z34
│   └── admin_tools.py              # Z32, E0401, E0402
└── tests/
    ├── conftest.py                 # Shared fixtures
    ├── test_einvoice_client.py     # Connector unit tests
    ├── test_system_tools.py        # Y01 tests
    ├── test_invoice_number_tools.py
    ├── test_b2c_invoice_tools.py
    ├── test_b2b_invoice_tools.py
    ├── test_allowance_tools.py
    ├── test_cancel_tools.py
    ├── test_query_tools.py
    ├── test_admin_tools.py
    └── test_regression.py          # Live API tests

Tools (27 total)

System

Tool Code Description
get_system_time Y01 Connection test / get server time

Invoice Number Management

Tool Code Description
get_invoice_numbers A01 Get invoice number allocation (current period)
get_next_period_numbers C01 Get invoice number allocation (next period)
get_invoice_numbers_expanded Z21 Get numbers expanded per-invoice with AESKEY
get_next_period_numbers_expanded Z22 Get next period numbers expanded with AESKEY

B2C Invoices

Tool Code Description
create_b2c_invoice C0401 Create B2C invoice (positional field format)
create_b2c_invoice_named C0401N Create B2C invoice (named field format)
void_b2c_invoice C0501 Void a B2C invoice

B2B Invoices

Tool Code Description
create_b2b_invoice A0401 Create B2B invoice (platform certified)
void_b2b_invoice A0501 Void a B2B invoice
create_b2b_exchange_invoice A0101 Create B2B exchange invoice
void_b2b_exchange_invoice A0201 Void a B2B exchange invoice

Allowances (折讓)

Tool Code Description
create_b2c_allowance D0401 Create B2C allowance
create_b2c_allowance_named D0401N Create B2C allowance (named format)
void_b2c_allowance D0501 Void a B2C allowance
create_b2b_allowance B0401 Create B2B allowance
void_b2b_allowance B0501 Void a B2B allowance
create_b2b_exchange_allowance B0101 Create B2B exchange allowance

Cancellation (註銷)

Tool Code Description
cancel_invoice C0701 Cancel an invoice
batch_cancel_invoice B0701 Batch cancel with full invoice data

Queries

Tool Code Description
get_cancel_status Z11 Get invoice cancel process status
get_downloaded_track_ranges Z31 Query downloaded track ranges
get_assignment_info Z33 Query tax ID number assignment
get_winning_list Z34 Download winning invoice list

Administration

Tool Code Description
upload_next_period_tracks Z32 Upload next period track numbers
assign_branch_tracks E0401 Branch office track assignment
report_unused_tracks E0402 Report unused track ranges

Usage Examples

Once the MCP server is running, an AI assistant (e.g. Claude) can call these tools on your behalf. Here are real-world scenarios showing what you say and how the AI responds.


"Help me check if the e-invoice system is connected"

You: 幫我測試一下電子發票系統有沒有連線成功

AI calls: get_system_time()

Result: The system returns REPLY: "1" with MESSAGE: "連線成功" and the server time 2026/04/01 22:29:03. Your connection is working.


"What invoice numbers do I have available right now?"

You: 我目前有哪些可用的發票號碼?

AI calls: get_invoice_numbers()

Result: Current period is 115 年 03-04 月, track GS, numbers 82775400 ~ 82775449 (50 invoices available). The AI can also explain the QRCode AES key returned for barcode generation.


"I need to get the detailed invoice numbers with AES keys for printing"

You: 我需要取得每張發票的 AESKEY 跟隨機碼,準備列印用

AI calls: get_invoice_numbers_expanded()

Result: Returns 50 individual invoices, each with its own number, AESKEY, and random number:

GS82775450 → AESKEY: Xymp9aqy..., RandomNumber: 7833
GS82775451 → AESKEY: XausdWBO..., RandomNumber: 4581
...

"Issue an invoice for a customer who bought 2 lattes and 1 cake"

You: 幫我開一張發票,客人買了 2 杯拿鐵 65 元、1 個巧克力蛋糕 85 元,總共 215 元含稅,紙本發票已列印

AI calls: get_invoice_numbers_expanded() to get an available number, then:

create_b2c_invoice(
  invoice_number = "GS82775402",     ← from the allocation
  invoice_date   = "2026-04-01",
  invoice_time   = "14:30:00",
  buyer_id       = "0000000000",     ← consumer, no tax ID
  buyer_name     = "0000",
  invoice_type   = "07",
  donate_mark    = "0",
  print_mark     = "Y",
  random_number  = "6136",           ← from the allocation
  tax_type = "1", tax_rate = "0.05", tax_amount = "10",
  sales_amount = "205", free_tax = "0", zero_tax = "0", total = "215",
  items = [
    {B1:"1", B2:"拿鐵咖啡", B3:"2", B5:"65", B6:"130", B7:"1", B13:"1"},
    {B1:"2", B2:"巧克力蛋糕", B3:"1", B5:"85", B6:"85", B7:"2", B13:"1"},
  ]
)

Result: REPLY: "1", MESSAGE: "成功", invoice GS82775402 created.


"Please void invoice GS82775401"

You: 請幫我作廢發票 GS82775401,原因是客戶取消訂單

AI calls:

void_b2c_invoice(
  invoice_number = "GS82775401",
  invoice_date   = "2026-04-01",
  buyer_id       = "0000000000",
  seller_id      = "23997652",
  cancel_date    = "2026-04-01",
  cancel_time    = "15:00:00",
  cancel_reason  = "客戶取消訂單",
)

Result: REPLY: "1", MESSAGE: "成功" — invoice voided successfully.


"Check the cancellation status of invoice GS82775400"

You: 幫我查一下 GS82775400 這張發票的註銷狀態

AI calls: get_cancel_status(invoice_number="GS82775400", invoice_date="2026-04-01")

Result: STATUSCODE: "1" = completed, "2" = pending, "3" = failed. The AI interprets and tells you the current status in plain language.


"Cancel invoice GS82775400 — it was issued by mistake"

You: 發票 GS82775400 開錯了,幫我註銷

AI calls:

cancel_invoice(
  invoice_number = "GS82775400",
  invoice_date   = "2026-04-01",
  buyer_id       = "0000000000",
  seller_id      = "23997652",
  cancel_date    = "2026-04-01",
  cancel_time    = "16:00:00",
  cancel_reason  = "誤開發票",
)

Result: If the invoice has been uploaded to the tax authority, REPLY: "1" confirms cancellation. If it hasn't been uploaded yet, the system returns REPLY: "-1" with a message explaining the invoice is still being processed — the AI will tell you to try again later.

Note: "作廢" (C0501 void) and "註銷" (C0701 cancel) are different. Void happens before upload to tax authority; cancel happens after. The AI picks the right tool based on context.


"I need to check what invoice number ranges have been downloaded"

You: 查一下統編 23997652 在 11504 期的 GS 字軌已下載的配號區間

AI calls:

get_downloaded_track_ranges(
  head_ban      = "23997652",
  branch_ban    = "23997652",
  invoice_type  = "07",
  year_month    = "11504",
  invoice_track = "GS",
)

Result: Returns the track ranges that have been successfully downloaded for this period.

Testing

# Unit tests (mocked HTTP, no credentials needed)
pytest tests/ --ignore=tests/test_regression.py -v

# Regression tests (requires .env with valid credentials)
pytest tests/test_regression.py -v -s

Architecture

All 27 functions communicate through a single POST endpoint (GetInvoice.ashx), differentiated by function code in the JSON body. The connector auto-injects credentials (SELLERID, POSID, POSSN) and system time.

Three JSON wrapper formats:

  • INDEX — System/number functions (Y01, A01, C01, Z21, Z22, Z11)
  • Invoice — Invoice/allowance/admin CRUD (C0401, A0401, D0401, C0701, E0401, Z31, etc.)
  • Allowance — B0501 only (void B2B allowance)

License

MIT License — see LICENSE for details.

Part of the Asgard Ecosystem

See the full Asgard AI Platform for more MCP servers.

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

mcp_universalec_e_invoice-0.1.0.tar.gz (24.6 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

mcp_universalec_e_invoice-0.1.0-py3-none-any.whl (21.5 kB view details)

Uploaded Python 3

File details

Details for the file mcp_universalec_e_invoice-0.1.0.tar.gz.

File metadata

File hashes

Hashes for mcp_universalec_e_invoice-0.1.0.tar.gz
Algorithm Hash digest
SHA256 f7cf52de4f1cce27d5ae88dd3173fc6999021ba43e3a0abb454e6b368ac9ec79
MD5 612f205bd8e21870db33f06b7b1560da
BLAKE2b-256 26c8776a9a1daa91163bc65f1bba3d27bff8189ac1ce3f1292abd685c663dfa8

See more details on using hashes here.

File details

Details for the file mcp_universalec_e_invoice-0.1.0-py3-none-any.whl.

File metadata

File hashes

Hashes for mcp_universalec_e_invoice-0.1.0-py3-none-any.whl
Algorithm Hash digest
SHA256 6edb145426e5f1b70d242e63469d46db37814aa1974a9d127abe5994ab97535f
MD5 02e38627e19cb2fed32eab23141dcc64
BLAKE2b-256 955208c44b5c53f5384c633075e014e57bca5c589b7748e12ab2851277c6e2d6

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page