PEAK Account MCP Server
MCP server for PEAK Account, a Thai cloud accounting platform, enabling AI assistants to manage accounting data through natural language via the official REST API.
README
PEAK Account MCP Server
MCP (Model Context Protocol) server for PEAK Account — a Thai cloud accounting platform. It lets AI assistants like Claude manage your PEAK data through natural language, using the official PEAK Open API.
Unlike a browser-scraping approach, this server talks to PEAK's documented REST API and authenticates with HMAC-SHA1 request signing — no headless browser required. 136 tools cover the full API surface.
Features
- Master data — Contacts, Products, Services, Payment Methods
- Sales / Income — Quotations, Invoices, Receipts, Credit Notes, Billing Notes (create/get/list/edit/void/approve, payments, e-Tax Invoice / e-Receipt, file attachments, async queue)
- Purchases / Expense — Purchase Orders, Expenses, Credit Note Expenses, Billing Note Expenses (create/get/list/edit/void/approve, payments, received tax invoice, attachments)
- Accounting & misc — Daily Journals, Account Codes, Tags, Classifications, Invitations, File Vault
Note on "delete": PEAK is an accounting system — posted documents are voided (
void_*), never hard-deleted, to preserve the audit trail.
How authentication works
Every PEAK API request carries four headers:
| Header | Value |
|---|---|
Time-Stamp |
Current UTC time, yyyyMMddHHmmss |
Time-Signature |
HMAC-SHA1(Time-Stamp), secret = your Connect ID (default; switchable to Connect Key) |
User-Token |
Issued by PEAK for your business |
Client-Token |
Fetched from POST /clienttoken (valid 24h, cached in memory) |
The client token is obtained by POST /api/v1/clienttoken with body { "peakClientToken": { "connectId": "...", "connectKey": "..." } }, signed with Time-Stamp + Time-Signature. The success response is { "PeakClientToken": { "token": "…", "resCode": "200", "resDesc": "Token Authorized" } }.
The server generates Time-Stamp/Time-Signature fresh per request, caches the client token, and refreshes it automatically on a 401.
Rate limits (enforced by PEAK)
| Policy | Scope | Limit |
|---|---|---|
| Client token | POST /clienttoken |
10 requests / minute |
| File upload | *-insertfile, FileVault |
2 requests / minute |
| GET concurrency | per User-Token | 10 concurrent |
| POST concurrency | per User-Token | 5 concurrent |
Exceeding a limit returns HTTP 429. The client automatically backs off (honoring retryAfterSeconds) and retries.
Setup
Prerequisites
- Node.js 18+
- A PEAK Developer account with Connect ID, Connect Key, and User Token — see peakaccount.com/developers. API access requires the PEAK PRO Plus package (฿12,000/year) or higher; UAT/sandbox is free for 3 months.
Install & build
npm install
npm run build
Configure
Copy .env.example to .env and fill in your credentials:
PEAK_ENV=uat # "uat" (sandbox) or "production"
PEAK_CONNECT_ID=... # sent in /clienttoken body
PEAK_CONNECT_KEY=... # sent in /clienttoken body
PEAK_USER_TOKEN=... # per-business token, sent as header
# PEAK_SIGNATURE_ENCODING=base64 # switch to "hex" if auth fails
# PEAK_SIGNATURE_SECRET=connectId # switch to "connectKey" if auth fails
Verify auth (recommended first step)
export $(grep -v '^#' .env | xargs) # load .env into the shell
npm run auth-check
This acquires a client token and prints masked headers. If it fails:
TimeSignature Unauthorized→ tryPEAK_SIGNATURE_ENCODING=hex, thenPEAK_SIGNATURE_SECRET=connectKey.Validate User Failed→ checkPEAK_CONNECT_ID/PEAK_CONNECT_KEY.
Claude Desktop / Claude Code integration
{
"mcpServers": {
"peakaccount": {
"command": "node",
"args": ["/path/to/PeakAccountMcp/dist/index.js"],
"env": {
"PEAK_ENV": "uat",
"PEAK_CONNECT_ID": "your-connect-id",
"PEAK_CONNECT_KEY": "your-connect-key",
"PEAK_USER_TOKEN": "your-user-token"
}
}
}
}
Environments
PEAK_ENV selects the base URL (confirmed from the PEAK OpenAPI servers block):
PEAK_ENV |
Default base URL | Override env var |
|---|---|---|
uat |
https://peakengineapidev.azurewebsites.net/api/v1 |
PEAK_BASE_URL_UAT |
production |
https://api.peakaccount.com/api/v1 |
PEAK_BASE_URL_PROD |
Tool design
- Read tools (
get_*,list_*) take an optionalparamsobject mapped to the endpoint's query string (e.g.{ "id": "…" }or{ "currentPage": 1, "pageSize": 20 }). - Write tools (
create_*,update_*,void_*,approve_*,record_*_payment, …) take adataobject sent as the JSON request body. Field names must match the PEAK API schema for that endpoint. - File tools (
attach_file_to_*,upload_file_vault) take afilePathplus optionalfields.
📋 Payload cheat sheet
Field names below are taken from the PEAK OpenAPI definitions. Numeric enums (type, taxStatus, vatType, isCheque, bankId, …) must be looked up in the numeric reference. Always confirm against the API reference for your account.
Create a contact — create_contact
Documents are wrapped in PeakContacts.contacts[]:
{
"data": {
"PeakContacts": {
"contacts": [
{
"name": "บริษัท ตัวอย่าง จำกัด",
"type": 2,
"taxNumber": "0105557000000",
"branchCode": "00000",
"address": "123 ถนนตัวอย่าง",
"subDistrict": "ท่าแร้ง",
"district": "บางเขน",
"province": "กรุงเทพมหานคร",
"country": "Thailand",
"postCode": "10220",
"email": "contact@example.com",
"callCenterNumber": "021234567",
"contactFirstName": "สมชาย",
"contactLastName": "ใจดี"
}
]
}
}
}
Key fields: name* (name only, no legal prefix), type* (2 = juristic, 5 = individual — see numeric ref), prefixNameType (for individuals), taxNumber, branchCode (5 digits), address parts, contactFirstName/LastName/Email, purchaseAccount/sellAccount (chart-of-accounts codes), bankAccount (bankId, bankBranch, bankAccountNo, bankAccountName).
Issue an invoice (income) — create_invoice
Wrapped in peakInvoices.invoices[]; getResult trims the response:
{
"data": {
"peakInvoices": {
"invoices": [
{
"issuedDate": "2026-07-19",
"dueDate": "2026-08-18",
"contactId": "917c3e8f-b315-4968-b8cc-08e2220d8682",
"reference": "SO-2026-001",
"remark": "ค่าบริการที่ปรึกษา",
"taxStatus": 1,
"isTaxInvoice": 1,
"products": [
{
"productCode": "SV001",
"description": "ค่าบริการที่ปรึกษา เดือน ก.ค.",
"quantity": 1,
"price": 10000,
"discount": "0",
"vatType": 1
}
]
}
],
"getResult": 1
}
}
}
Header fields: code (auto if omitted), issuedDate*, dueDate, contactId or contactCode, reference, remark, taxStatus (VAT status — numeric), isTaxInvoice, discountTotal, tags[]. preTaxAmount/vatAmount/netAmount auto-calc if null.
Line item (products[]): productId/productCode, description, accountCode, quantity, price, discount, vatType, withHoldingTaxAmount.
create_invoice_allinoneuses the same body but also approves the document in one call. To bill from a quotation, usecreate_invoice_by_quotation.
Record a payment on an invoice — inline or record_invoice_payment
Payments can be embedded in the document via paidPayments, or recorded later against an approved invoice:
{
"data": {
"paidPayments": {
"paymentDate": "20260720",
"withHoldingTaxAmount": "0",
"payments": [
{
"amount": 10700,
"isCheque": 0,
"paymentMethodCode": "PM-CASH",
"note": "รับโอนพร้อมเพย์"
}
]
}
}
}
Payment fields: amount*, paymentMethodId/paymentMethodCode, isCheque (0/1), cheque (object when isCheque=1), accountCode/accountSubCode, note. paymentDate is yyyyMMdd.
Record an expense (รายจ่าย) — create_expense
Same document shape as invoices, wrapped in peakExpenses.expenses[]:
{
"data": {
"peakExpenses": {
"expenses": [
{
"issuedDate": "2026-07-19",
"dueDate": "2026-07-19",
"contactId": "917c3e8f-b315-4968-b8cc-08e2220d8682",
"reference": "BILL-8842",
"remark": "ค่าอินเทอร์เน็ตสำนักงาน",
"taxStatus": 1,
"isTaxInvoice": 1,
"products": [
{
"description": "ค่าบริการอินเทอร์เน็ต 1 เดือน",
"accountCode": "540104",
"quantity": 1,
"price": 800,
"vatType": 1
}
],
"paidPayments": {
"paymentDate": "20260719",
"payments": [
{ "amount": 856, "isCheque": 0, "paymentMethodCode": "PM-CASH" }
]
}
}
],
"getResult": 1
}
}
}
For input-VAT (ภาษีซื้อ), use create_expense_received_tax_invoice. create_expense_allinone creates + approves.
VAT / Tax
VAT is embedded in each line item (vatType) and document (taxStatus), not a separate resource. To issue electronic tax documents:
- Output VAT (ภาษีขาย):
create_invoice_etax,create_receipt_etax,create_credit_note_etax - Input VAT (ภาษีซื้อ):
create_expense_received_tax_invoice
VAT return reports (ภ.พ.30) are not exposed by the API.
Reads
// get_contact
{ "params": { "id": "917c3e8f-b315-4968-b8cc-08e2220d8682" } }
// list_invoices
{ "params": { "currentPage": 1, "pageSize": 20 } }
Async queue
Some documents process asynchronously. Submit with enqueue_* and poll with get_*_queue (e.g. enqueue_invoice → get_invoice_queue).
🧰 All 136 tools
Legend: 🔍 read (GET, takes params) · ✏️ write (POST, takes data) · 📎 file (multipart, takes filePath)
Master Data — Contacts, Products, Services, Payment Methods (19)
| # | Tool | Type | Description |
|---|---|---|---|
| 1 | create_contact |
✏️ write | Create a contact (customer/supplier) in PEAK. |
| 2 | get_contact |
🔍 read | Get a single contact by id (pass { id }). |
| 3 | list_contacts |
🔍 read | List contacts with optional paging/search params. |
| 4 | update_contact |
✏️ write | Edit an existing contact. |
| 5 | list_contact_groups |
🔍 read | List contact groups. |
| 6 | create_product |
✏️ write | Create a product. |
| 7 | get_product |
🔍 read | Get a single product by id. |
| 8 | list_products |
🔍 read | List products with optional paging/search params. |
| 9 | update_product |
✏️ write | Edit an existing product. |
| 10 | adjust_product |
✏️ write | Adjust product stock quantity. |
| 11 | list_product_units |
🔍 read | List product units. |
| 12 | create_service |
✏️ write | Create a service. |
| 13 | get_service |
🔍 read | Get a single service by id. |
| 14 | list_services |
🔍 read | List services with optional paging/search params. |
| 15 | update_service |
✏️ write | Edit an existing service. |
| 16 | list_service_units |
🔍 read | List service units. |
| 17 | create_payment_method |
✏️ write | Create a payment method. |
| 18 | list_payment_methods |
🔍 read | Get/list payment methods. |
| 19 | transfer_payment_method |
✏️ write | Transfer funds between payment methods. |
Sales / Income — Quotations, Invoices, Receipts, Credit Notes, Billing Notes (61)
| # | Tool | Type | Description |
|---|---|---|---|
| 1 | create_quotation |
✏️ write | Create a quotation (draft). |
| 2 | create_quotation_allinone |
✏️ write | Create + approve a quotation in one call. |
| 3 | get_quotation |
🔍 read | Get a single quotation by id. |
| 4 | list_quotations |
🔍 read | List quotations with optional paging/filter params. |
| 5 | update_quotation |
✏️ write | Edit an existing quotation. |
| 6 | void_quotation |
✏️ write | Void a quotation. |
| 7 | approve_quotation |
✏️ write | Approve a quotation. |
| 8 | enqueue_quotation |
✏️ write | Submit a quotation to the async processing queue. |
| 9 | get_quotation_queue |
🔍 read | Poll the status of a queued quotation. |
| 10 | set_quotation_queue_priority |
✏️ write | Set queue priority for a quotation. |
| 11 | attach_file_to_quotation |
📎 file | Attach a file to a quotation. |
| 12 | create_invoice |
✏️ write | Create an invoice (draft). |
| 13 | create_invoice_allinone |
✏️ write | Create + approve an invoice in one call. |
| 14 | create_invoice_by_quotation |
✏️ write | Create an invoice from a quotation. |
| 15 | get_invoice |
🔍 read | Get a single invoice by id. |
| 16 | list_invoices |
🔍 read | List invoices with optional paging/filter params. |
| 17 | list_invoices_by_contact |
🔍 read | List invoices for a specific contact. |
| 18 | update_invoice |
✏️ write | Edit an existing invoice. |
| 19 | void_invoice |
✏️ write | Void an invoice. |
| 20 | approve_invoice |
✏️ write | Approve an invoice. |
| 21 | record_invoice_payment |
✏️ write | Record a payment against an invoice. |
| 22 | void_invoice_payment |
✏️ write | Void a recorded invoice payment. |
| 23 | create_invoice_etax |
✏️ write | Issue an e-Tax Invoice for an invoice. |
| 24 | enqueue_invoice |
✏️ write | Submit an invoice to the async processing queue. |
| 25 | get_invoice_queue |
🔍 read | Poll the status of a queued invoice. |
| 26 | set_invoice_queue_priority |
✏️ write | Set queue priority for an invoice. |
| 27 | attach_file_to_invoice |
📎 file | Attach a file to an invoice. |
| 28 | create_receipt |
✏️ write | Create a receipt (draft). |
| 29 | create_receipt_allinone |
✏️ write | Create + approve a receipt in one call. |
| 30 | create_receipt_by_invoice |
✏️ write | Create a receipt from an invoice. |
| 31 | create_receipt_by_quotation |
✏️ write | Create a receipt from a quotation. |
| 32 | create_receipt_by_billing_note |
✏️ write | Create a receipt from a billing note. |
| 33 | get_receipt |
🔍 read | Get a single receipt by id. |
| 34 | list_receipts |
🔍 read | List receipts with optional paging/filter params. |
| 35 | update_receipt |
✏️ write | Edit an existing receipt. |
| 36 | void_receipt |
✏️ write | Void a receipt. |
| 37 | approve_receipt |
✏️ write | Approve a receipt. |
| 38 | create_receipt_ereceipt |
✏️ write | Issue an e-Receipt for a receipt. |
| 39 | create_receipt_etax |
✏️ write | Issue an e-Tax Invoice for a receipt. |
| 40 | enqueue_receipt |
✏️ write | Submit a receipt to the async processing queue. |
| 41 | get_receipt_queue |
🔍 read | Poll the status of a queued receipt. |
| 42 | set_receipt_queue_priority |
✏️ write | Set queue priority for a receipt. |
| 43 | attach_file_to_receipt |
📎 file | Attach a file to a receipt. |
| 44 | create_credit_note |
✏️ write | Create a credit note. |
| 45 | get_credit_note |
🔍 read | Get a single credit note by id. |
| 46 | list_credit_notes |
🔍 read | List credit notes with optional paging/filter params. |
| 47 | void_credit_note |
✏️ write | Void a credit note. |
| 48 | create_credit_note_ereceipt |
✏️ write | Issue an e-Receipt for a credit note. |
| 49 | create_credit_note_etax |
✏️ write | Issue an e-Tax Invoice for a credit note. |
| 50 | enqueue_credit_note |
✏️ write | Submit a credit note to the async processing queue. |
| 51 | get_credit_note_queue |
🔍 read | Poll the status of a queued credit note. |
| 52 | attach_file_to_credit_note |
📎 file | Attach a file to a credit note. |
| 53 | create_billing_note |
✏️ write | Create a billing note. |
| 54 | get_billing_note |
🔍 read | Get a single billing note by id. |
| 55 | list_billing_notes |
🔍 read | List billing notes with optional paging/filter params. |
| 56 | record_billing_note_payment |
✏️ write | Record a payment against a billing note. |
| 57 | void_billing_note_payment |
✏️ write | Void a recorded billing note payment. |
| 58 | void_billing_note |
✏️ write | Void a billing note. |
| 59 | enqueue_billing_note |
✏️ write | Submit a billing note to the async processing queue. |
| 60 | get_billing_note_queue |
🔍 read | Poll the status of a queued billing note. |
| 61 | attach_file_to_billing_note |
📎 file | Attach a file to a billing note. |
Purchases / Expense — Purchase Orders, Expenses, Credit/Billing Note Expenses (43)
| # | Tool | Type | Description |
|---|---|---|---|
| 1 | create_purchase_order |
✏️ write | Create a purchase order (draft). |
| 2 | create_purchase_order_allinone |
✏️ write | Create + approve a purchase order in one call. |
| 3 | get_purchase_order |
🔍 read | Get a single purchase order by id. |
| 4 | list_purchase_orders |
🔍 read | List purchase orders with optional paging/filter params. |
| 5 | update_purchase_order |
✏️ write | Edit an existing purchase order. |
| 6 | void_purchase_order |
✏️ write | Void a purchase order. |
| 7 | approve_purchase_order |
✏️ write | Approve a purchase order. |
| 8 | enqueue_purchase_order |
✏️ write | Submit a purchase order to the async processing queue. |
| 9 | get_purchase_order_queue |
🔍 read | Poll the status of a queued purchase order. |
| 10 | set_purchase_order_queue_priority |
✏️ write | Set queue priority for a purchase order. |
| 11 | attach_file_to_purchase_order |
📎 file | Attach a file to a purchase order. |
| 12 | create_expense |
✏️ write | Create an expense (draft). |
| 13 | create_expense_allinone |
✏️ write | Create + approve an expense in one call. |
| 14 | create_expense_by_purchase_order |
✏️ write | Create an expense from a purchase order. |
| 15 | get_expense |
🔍 read | Get a single expense by id. |
| 16 | list_expenses |
🔍 read | List expenses with optional paging/filter params. |
| 17 | list_expenses_by_contact |
🔍 read | List expenses for a specific contact. |
| 18 | update_expense |
✏️ write | Edit an existing expense. |
| 19 | void_expense |
✏️ write | Void an expense. |
| 20 | approve_expense |
✏️ write | Approve an expense. |
| 21 | record_expense_payment |
✏️ write | Record a payment against an expense. |
| 22 | void_expense_payment |
✏️ write | Void a recorded expense payment. |
| 23 | create_expense_received_tax_invoice |
✏️ write | Create a received tax invoice for an expense. |
| 24 | enqueue_expense |
✏️ write | Submit an expense to the async processing queue. |
| 25 | get_expense_queue |
🔍 read | Poll the status of a queued expense. |
| 26 | set_expense_queue_priority |
✏️ write | Set queue priority for an expense. |
| 27 | attach_file_to_expense |
📎 file | Attach a file to an expense. |
| 28 | create_credit_note_expense |
✏️ write | Create a credit note expense. |
| 29 | get_credit_note_expense |
🔍 read | Get a single credit note expense by id. |
| 30 | list_credit_note_expenses |
🔍 read | List credit note expenses. |
| 31 | void_credit_note_expense |
✏️ write | Void a credit note expense. |
| 32 | enqueue_credit_note_expense |
✏️ write | Submit a credit note expense to the queue. |
| 33 | get_credit_note_expense_queue |
🔍 read | Poll the status of a queued credit note expense. |
| 34 | attach_file_to_credit_note_expense |
📎 file | Attach a file to a credit note expense. |
| 35 | create_billing_note_expense |
✏️ write | Create a billing note expense. |
| 36 | get_billing_note_expense |
🔍 read | Get a single billing note expense by id. |
| 37 | list_billing_note_expenses |
🔍 read | List billing note expenses. |
| 38 | record_billing_note_expense_payment |
✏️ write | Record a payment against a billing note expense. |
| 39 | void_billing_note_expense_payment |
✏️ write | Void a recorded billing note expense payment. |
| 40 | void_billing_note_expense |
✏️ write | Void a billing note expense. |
| 41 | enqueue_billing_note_expense |
✏️ write | Submit a billing note expense to the queue. |
| 42 | get_billing_note_expense_queue |
🔍 read | Poll the status of a queued billing note expense. |
| 43 | attach_file_to_billing_note_expense |
📎 file | Attach a file to a billing note expense. |
Accounting & Misc — Daily Journals, Tags, Classifications, File Vault (13)
| # | Tool | Type | Description |
|---|---|---|---|
| 1 | create_daily_journal |
✏️ write | Create a daily journal entry. |
| 2 | get_daily_journal |
🔍 read | Get a single daily journal by id. |
| 3 | void_daily_journal |
✏️ write | Void a daily journal entry. |
| 4 | get_account_codes |
🔍 read | Get the chart of account codes. |
| 5 | enqueue_daily_journal |
✏️ write | Submit a daily journal to the async processing queue. |
| 6 | insert_tag |
✏️ write | Attach a tag to a record. |
| 7 | remove_tag |
✏️ write | Remove a tag from a record. |
| 8 | list_classification_groups |
🔍 read | Get classification groups. |
| 9 | get_transaction_classification |
🔍 read | Get classifications for a transaction. |
| 10 | create_transaction_classification |
✏️ write | Create a transaction classification. |
| 11 | remove_transaction_classification |
✏️ write | Void/remove a transaction classification. |
| 12 | create_invitation |
✏️ write | Create an invitation. |
| 13 | upload_file_vault |
📎 file | Upload a file to the PEAK File Vault. |
Notes / open items
- The passthrough
data/paramsdesign keeps the server correct across all endpoints. As per-endpoint schemas are confirmed against UAT, individual tools can be given stricter typed inputs. Time-Signatureencoding (base64 vs hex) and secret source (connectId vs connectKey) are configurable — confirm the working combination on your account vianpm run auth-check.- Numeric enums (
type,taxStatus,vatType,bankId,prefixNameType, …) — see the numeric reference.
License
MIT
推荐服务器
Baidu Map
百度地图核心API现已全面兼容MCP协议,是国内首家兼容MCP协议的地图服务商。
Playwright MCP Server
一个模型上下文协议服务器,它使大型语言模型能够通过结构化的可访问性快照与网页进行交互,而无需视觉模型或屏幕截图。
Magic Component Platform (MCP)
一个由人工智能驱动的工具,可以从自然语言描述生成现代化的用户界面组件,并与流行的集成开发环境(IDE)集成,从而简化用户界面开发流程。
Audiense Insights MCP Server
通过模型上下文协议启用与 Audiense Insights 账户的交互,从而促进营销洞察和受众数据的提取和分析,包括人口统计信息、行为和影响者互动。
VeyraX
一个单一的 MCP 工具,连接你所有喜爱的工具:Gmail、日历以及其他 40 多个工具。
graphlit-mcp-server
模型上下文协议 (MCP) 服务器实现了 MCP 客户端与 Graphlit 服务之间的集成。 除了网络爬取之外,还可以将任何内容(从 Slack 到 Gmail 再到播客订阅源)导入到 Graphlit 项目中,然后从 MCP 客户端检索相关内容。
Kagi MCP Server
一个 MCP 服务器,集成了 Kagi 搜索功能和 Claude AI,使 Claude 能够在回答需要最新信息的问题时执行实时网络搜索。
e2b-mcp-server
使用 MCP 通过 e2b 运行代码。
Neon MCP Server
用于与 Neon 管理 API 和数据库交互的 MCP 服务器
Exa MCP Server
模型上下文协议(MCP)服务器允许像 Claude 这样的 AI 助手使用 Exa AI 搜索 API 进行网络搜索。这种设置允许 AI 模型以安全和受控的方式获取实时的网络信息。