Malaysia Invoices (LHDN MyInvois submit, query & cancel)
Official4 tools
by junter1989k-ai ยท JavaScript
Malaysia LHDN MyInvois: AI agents submit, query and cancel e-invoices, stateless BYO.
app.wishpool/malaysia-invoice-mcp (MCP Server)
This MCP server for Malaysia LHDN MyInvois enables AI agents to submit, query, and cancel e-invoices. It is described as stateless BYO (bring your own). The server is intended for invoice and tax workflows involving VAT in a MyInvois context.
๐ ๏ธ Key Features
Malaysia LHDN MyInvois e-invoice operations
AI-agent actions: submit, query, cancel
Stateless โBYOโ design
๐ Use Cases
Submitting e-invoices to MyInvois via AI agents
Looking up existing e-invoice records
Canceling e-invoices when required
โก Developer Benefits
MCP server interface for MyInvois e-invoice lifecycle tasks
Works with AI agents and associated tool workflows
โ ๏ธ Limitations
Scope is limited to MyInvois e-invoice submit/query/cancel operations
Submit an ALREADY-SIGNED Malaysian e-invoice (UBL 2.1) to LHDN MyInvois โ the POST /api/v1.0/documentsubmissions call. This server does NOT sign: you XAdES-sign the UBL document merchant-side, compute its SHA-256 hash, and pass { format, document(base64), documentHash, codeNumber }. MyInvois validates asynchronously, so a successful submit returns a submissionUid plus accepted_documents (each with the assigned uuid) and rejected_documents โ it does NOT yet mean the invoice is Valid; call query_submission with the submissionUid to poll the validation outcome. Result: accepted=true when at least one document was accepted for processing (HTTP 202); rejected_documents lists any structurally-rejected documents with their error. Required credential headers (set once in your MCP client, per-request, never stored): x-myinvois-client-id + x-myinvois-client-secret (your ERP OAuth2 credentials from the MyTax "Register ERP" self-service). Optional header x-myinvois-mode: sandbox (default = preprod, no fiscal effect) | prod (production, real fiscal effect). Optional owner-policy headers x-agentpay-max-amount / x-agentpay-approval-above / x-agentpay-allowed-tools.
Parameters4
document
string
required
The FULL signed UBL 2.1 document, base64-encoded. You XAdES-sign it merchant-side; this server forwards the bytes untouched.
documentHash
string
required
SHA-256 hash (hex) of the signed document bytes. Computed merchant-side; MyInvois re-checks it against the document.
codeNumber
string
required
Your internal invoice number / eInvoice code number (cbc:ID of the document), e.g. INV-2026-000123. Used to correlate accepted/rejected results.
format
string
optional
Document format: JSON (default) or XML โ must match how you built and signed the document.
Raw schema
{
"type": "object",
"properties": {
"document": {
"type": "string",
"description": "The FULL signed UBL 2.1 document, base64-encoded. You XAdES-sign it merchant-side; this server forwards the bytes untouched."
},
"documentHash": {
"type": "string",
"description": "SHA-256 hash (hex) of the signed document bytes. Computed merchant-side; MyInvois re-checks it against the document."
},
"codeNumber": {
"type": "string",
"description": "Your internal invoice number / eInvoice code number (cbc:ID of the document), e.g. INV-2026-000123. Used to correlate accepted/rejected results."
},
"format": {
"type": "string",
"enum": [
"JSON",
"XML"
],
"description": "Document format: JSON (default) or XML โ must match how you built and signed the document."
}
},
"required": [
"document",
"documentHash",
"codeNumber"
]
}
query_submission
Get the validation status of a MyInvois submission โ the GET /api/v1.0/documentsubmissions/{submissionUid} call. Use the submissionUid returned by submit_invoice to poll (MyInvois validates asynchronously; 3-5s polling is recommended). Result overall_status enum: "in progress" (still validating), "valid" (all documents valid), "partially valid" (some valid, some invalid), "invalid" (all invalid). document_summary lists each document with its own status (Submitted / Valid / Invalid / Cancelled), uuid and totals. Required credential headers (set once in your MCP client, per-request, never stored): x-myinvois-client-id + x-myinvois-client-secret (your ERP OAuth2 credentials from the MyTax "Register ERP" self-service). Optional header x-myinvois-mode: sandbox (default = preprod, no fiscal effect) | prod (production, real fiscal effect). Optional owner-policy headers x-agentpay-max-amount / x-agentpay-approval-above / x-agentpay-allowed-tools.
Parameters3
submissionUid
string
required
The submissionUid returned by submit_invoice (26 alphanumeric characters).
pageNo
number
optional
Optional page number when the submission has many documents.
pageSize
number
optional
Optional documents per page (max 100).
Raw schema
{
"type": "object",
"properties": {
"submissionUid": {
"type": "string",
"description": "The submissionUid returned by submit_invoice (26 alphanumeric characters)."
},
"pageNo": {
"type": "number",
"description": "Optional page number when the submission has many documents."
},
"pageSize": {
"type": "number",
"description": "Optional documents per page (max 100)."
}
},
"required": [
"submissionUid"
]
}
cancel_invoice
Cancel a previously-issued, VALID MyInvois document โ the PUT /api/v1.0/documents/state/{uuid}/state call (body status=cancelled). Only allowed within the 72-HOUR window from the moment the document became valid; after that you must issue a credit/debit note instead. In: uuid (the document uuid from query_submission, NOT the submissionUid) + reason (why, max 300 chars). Result status "Cancelled" on success. Common errors: OperationPeriodOver (72h passed), IncorrectState (not cancellable), ActiveReferencingDocuments (referenced by another doc), Forbidden (you did not issue it). Required credential headers (set once in your MCP client, per-request, never stored): x-myinvois-client-id + x-myinvois-client-secret (your ERP OAuth2 credentials from the MyTax "Register ERP" self-service). Optional header x-myinvois-mode: sandbox (default = preprod, no fiscal effect) | prod (production, real fiscal effect). Optional owner-policy headers x-agentpay-max-amount / x-agentpay-approval-above / x-agentpay-allowed-tools.
Parameters2
uuid
string
required
The MyInvois document uuid to cancel (26 alphanumeric characters, from query_submission โ NOT the submissionUid).
reason
string
required
Reason for cancellation (mandatory, max 300 characters).
Raw schema
{
"type": "object",
"properties": {
"uuid": {
"type": "string",
"description": "The MyInvois document uuid to cancel (26 alphanumeric characters, from query_submission โ NOT the submissionUid)."
},
"reason": {
"type": "string",
"description": "Reason for cancellation (mandatory, max 300 characters)."
}
},
"required": [
"uuid",
"reason"
]
}
build_invoice_draft
Local helper (NO network, NO credentials, NO signing): assemble an UNSIGNED UBL 2.1 invoice skeleton from line items and Malaysian SST tax, and compute the monetary totals (excl-tax, tax, incl-tax, payable). Use it to prepare a document you then complete (supplier/buyer TIN, MSIC code, etc.), XAdES-sign, hash, and pass to submit_invoice. It does NOT submit and has NO fiscal effect. In: lines [{ description, quantity, unitPrice, taxRate? (percent, e.g. 0/6/8/10) }], codeNumber, currency? (default MYR), issueDate? (default today). Out: computed totals + ubl_json skeleton. NOTE: it applies the taxRate you give per line (SST classification is your decision); it does not pick the rate for you.
Parameters4
lines
array
required
Line items. Each: { description, quantity, unitPrice, taxRate? }. taxRate is a percentage (0 = exempt/zero-rated; 6/8 = service tax; 5/10 = sales tax).
codeNumber
string
required
Your internal invoice number / eInvoice code number (becomes the document cbc:ID).