Skip to main content
Glama

Taokeh MCP server

Search documents

search_documents
Read-only

Find invoices, credit notes, sell-side debit notes, quotes, delivery orders, bills, buy-side debit notes and purchase orders by any combination of: doc number (partial), party (customer/vendor) name (partial), date range, amount range, due-date window (invoices and bills), and doc type. Returns compact rows (docId, type, number, date, party, total, status), newest first, capped — with a more flag when there are further matches to narrow down. INVOICE rows carry two more fields: refNo, the CUSTOMER's own reference for that job — their delivery-order or purchase-order number, the one they quote back at you on the phone — and dueDate, the date that invoice falls due. refNo is NOT the invoice number; the invoice's own number is number. refNo is null when the invoice was raised without one. dueDate is null on a CASH sale — paid at the counter, so it is not money anyone is waiting on and it deliberately sits outside every due-date window and aging bucket; a null there means CASH, not a missing date. Only CREDIT invoices report one. BILL rows carry dueDate too — the date a supplier bill falls due, from the payment term printed on it, and null on a CASH bill for the same reason. Only invoices carry refNo (a bill's own number IS the supplier's number, so it needs no second field), and only invoices and bills carry dueDate — every other type omits them rather than reporting null about a column its document has no such thing as. number searches BOTH, so "find INV-0031" and "find the invoice for their DO 1074" are the same call. Invoices, credit notes, bills and quotes also report whether their ORIGINAL document (a scan or upload) is on file: hasAttachment plus an attachments list you can fetch with get_attachment. Delivery orders and purchase orders omit that field because they cannot carry an original. INVOICES, CREDIT NOTES and SELL-SIDE DEBIT NOTES (sales_debit_note — additional charges this business added to an invoice it issued; not to be confused with debit_note, the buy-side one raised against a supplier bill) also carry an einvoice field — this business's MyInvois posture for that document AS RECORDED IN TAOKEH: validated (a MyInvois validation is recorded here, with uuid + validatedAt), consolidated (covered by a consolidated e-invoice, which holds the uuid — the individual document has none by design), platform (a marketplace sale: Shopee/TikTok Shop/Lazada issues the e-invoice, nothing for this business to submit), exported (put into a MyInvois batch export from Taokeh, nothing recorded back yet) or none. Taokeh CANNOT see the MyInvois portal, so say "no validation recorded in Taokeh" — never "never submitted to LHDN". Bills and buy-side debit notes omit the field. Use the docId with get_attachment (the SOURCE document someone filed) or get_document_pdf (the PDF Taokeh generates). PAYMENTS — docType:'payment' — are an OPT-IN type you must ask for BY NAME: they are never included when you omit docType, because a payment is not a document. It is a BANK LINE that invoices or bills point at, so the grain is the movement of money: one receipt that settles three invoices is ONE row carrying three allocations ({docId, docType, docNumber, party, amount, amountForeign, notes}). An allocation's docType is the real kind of the document settled — 'invoice', 'credit_note' (a refund walks a credit note back), 'sales_debit_note', 'bill' or 'debit_note' — not an assumption from which side of the books it sits on, and notes is that allocation's own note rather than one note borrowed for the whole transfer. That makes "which payment covered INV-0031" a single call — number and party here match the ALLOCATED documents, not the bank line, and on the invoice side number also matches the customer's own Ref No (their DO/PO number, or a marketplace order key), exactly as it does for invoices in the ordinary search. Each row: docId (⚠ a BANK TRANSACTION id, NOT a document id — do not hand it to get_document_pdf or get_attachment), date, direction ('in'/'out'), total (the bank line's own magnitude), status (the bank row's status), bankAccount, party (the single customer or supplier when every allocation is to the same one, else null — read the per-allocation party then), source and description (the bank line as stored). source is DERIVED from where the line came from, not stored: 'statement' (it arrived on an imported bank statement and a human matched it in Banking), 'receipt_draft' or 'payment_draft' (an AI-filed draft the owner approved), or 'manual' — recorded by hand in the app, which is EVERYTHING ELSE rather than one door: the receipt door, the /go command bar, the supplier-payment door, a refund against a hand-recorded line. Taokeh does not distinguish them, so do not tell the owner which screen was used. A NEGATIVE allocation amount is a REFUND walking that document back down, not a settlement. CONTRAS ARE NOT PAYMENTS and never appear here: a set-off moves no bank money, and Taokeh books it as two internal clearing lines which are excluded from this read on purpose. To see one, use search_journal or the contra note on the documents themselves.

Input Schema

TableJSON Schema
NameRequiredDescriptionDefault
toNo
refNoNOT a filter on this tool. Pass the customer's own Ref No (their DO / PO number) as `number` — that one parameter searches BOTH the invoice's own number and the customer's Ref No, and the row it returns reports each separately as `number` and `refNo`.
fromNo
textNoNOT a filter on this tool. This search matches document numbers and party names only — use `number` or `party`. To search memo/line text, use search_journal (`text`) or search_expenses (`text`).
dueToNoLatest DUE date (YYYY-MM-DD). Same docType rule as dueFrom — 'invoice' or 'bill'. Pair the two for a window: dueFrom + dueTo across this week with docType:'bill' answers "what do I owe before Friday"; dueTo alone with a past date is everything already due.
partyNoPartial customer or vendor name (case-insensitive contains).
refNoNoNOT a filter on this tool. Pass the customer's own Ref No (their DO / PO number) as `number` — that one parameter searches BOTH the invoice's own number and the customer's Ref No, and the row it returns reports each separately as `number` and `refNo`.
numberNoPartial doc number / reference (case-insensitive). On INVOICES this also matches the customer's own Ref No — their DO or PO number, whatever they printed on the paperwork. So a customer chasing "our PO 4471" is one call: pass 4471 here. That Ref No is NOT the invoice number; the invoice's own number matches here too, and you cannot tell from a hit which of the two it was — read `number` and `refNo` on the row it comes back with. On MARKETPLACE-IMPORTED invoices the Ref No is the platform's order key (SHOPEE-<order_sn>, TIKTOK-<order id>, SHOPIFY-<order id>), not a customer's number — so a marketplace order id pasted here finds its invoice too.
vendorNoNOT a filter on this tool. Pass a customer or vendor name as `party`.
docTypeNoRestrict to one type: 'invoice','credit_note','sales_debit_note','quote','delivery_order','bill','debit_note','purchase_order','payment'. Omit for all — EXCEPT 'payment', which is opt-in only and is never returned unless you name it. NOTE the two debit notes: 'sales_debit_note' is one this business ISSUED to a customer (additional charges on an invoice — money owed TO this business); 'debit_note' is the BUY side, issued to a supplier against a bill.
dueFromNoEarliest DUE date (YYYY-MM-DD) — this is the "what's due this week" filter, and it asks about when the money falls due, not when the document was raised (that's `from`/`to`). INVOICES OR BILLS, one at a time: pass docType:'invoice' (money coming in) or docType:'bill' (money going out) with it, or the call is refused. Nothing else in this search has a due date, and quietly dropping every quote and delivery order would be a wrong answer wearing a right one's clothes; netting receivables and payables into one list would be another.
customerNoNOT a filter on this tool. Pass a customer or vendor name as `party`.
supplierNoNOT a filter on this tool. Pass a customer or vendor name as `party`.
docNumberNoNOT a filter on this tool. Pass the document number as `number` (partial matches are fine).
maxAmountNo
minAmountNo
referenceNoNOT a filter on this tool. Pass the customer's own Ref No (their DO / PO number) as `number` — that one parameter searches BOTH the invoice's own number and the customer's Ref No, and the row it returns reports each separately as `number` and `refNo`.

Schema Changelog

Changes observed during successful MCP inspections. Dates show when Glama detected each change.

  1. Changed2 schema fields changed
    • changedInput schema / properties / dueFrom / description
      Previous value: -"Earliest DUE date (YYYY-MM-DD) — this is the \"what's due this week\" filter, and it asks about when the money falls due, not when the invoice was raised (that's `from`/`to`). INVOICES ONLY: pass docType:'invoice' with it, or the call is refused, because nothing else in this search has a due date and quietly dropping every quote and bill would be a wrong answer wearing a right one's clothes."New value: +"Earliest DUE date (YYYY-MM-DD) — this is the \"what's due this week\" filter, and it asks about when the money falls due, not when the document was raised (that's `from`/`to`). INVOICES OR BILLS, one at a time: pass docType:'invoice' (money coming in) or docType:'bill' (money going out) with it, or the call is refused. Nothing else in this search has a due date, and quietly dropping every quote and delivery order would be a wrong answer wearing a right one's clothes; netting receivables and payables into one list would be another."
    • changedInput schema / properties / dueTo / description
      Previous value: -"Latest DUE date (YYYY-MM-DD). Same invoices-only rule as dueFrom. Pair the two for a window — dueFrom + dueTo across this week answers \"what's landing on me before Friday\"; dueTo alone with a past date is everything already due."New value: +"Latest DUE date (YYYY-MM-DD). Same docType rule as dueFrom — 'invoice' or 'bill'. Pair the two for a window: dueFrom + dueTo across this week with docType:'bill' answers \"what do I owe before Friday\"; dueTo alone with a past date is everything already due."
  2. Changed1 schema field changed
    • changedInput schema / properties / docType / description
      Previous value: -"Restrict to one type: 'invoice','credit_note','sales_debit_note','quote','delivery_order','bill','debit_note','purchase_order'. Omit for all. NOTE the two debit notes: 'sales_debit_note' is one this business ISSUED to a customer (additional charges on an invoice — money owed TO this business); 'debit_note' is the BUY side, issued to a supplier against a bill."New value: +"Restrict to one type: 'invoice','credit_note','sales_debit_note','quote','delivery_order','bill','debit_note','purchase_order','payment'. Omit for all — EXCEPT 'payment', which is opt-in only and is never returned unless you name it. NOTE the two debit notes: 'sales_debit_note' is one this business ISSUED to a customer (additional charges on an invoice — money owed TO this business); 'debit_note' is the BUY side, issued to a supplier against a bill."
  3. Changed8 schema fields changed
    • addedInput schema / properties / customer
      Added value: +{
      +  "description": "NOT a filter on this tool. Pass a customer or vendor name as `party`."
      +}
    • addedInput schema / properties / docNumber
      Added value: +{
      +  "description": "NOT a filter on this tool. Pass the document number as `number` (partial matches are fine)."
      +}
    • addedInput schema / properties / ref
      Added value: +{
      +  "description": "NOT a filter on this tool. Pass the customer's own Ref No (their DO / PO number) as `number` — that one parameter searches BOTH the invoice's own number and the customer's Ref No, and the row it returns reports each separately as `number` and `refNo`."
      +}
    • addedInput schema / properties / refNo
      Added value: +{
      +  "description": "NOT a filter on this tool. Pass the customer's own Ref No (their DO / PO number) as `number` — that one parameter searches BOTH the invoice's own number and the customer's Ref No, and the row it returns reports each separately as `number` and `refNo`."
      +}
    • addedInput schema / properties / reference
      Added value: +{
      +  "description": "NOT a filter on this tool. Pass the customer's own Ref No (their DO / PO number) as `number` — that one parameter searches BOTH the invoice's own number and the customer's Ref No, and the row it returns reports each separately as `number` and `refNo`."
      +}
    • addedInput schema / properties / supplier
      Added value: +{
      +  "description": "NOT a filter on this tool. Pass a customer or vendor name as `party`."
      +}
    • addedInput schema / properties / text
      Added value: +{
      +  "description": "NOT a filter on this tool. This search matches document numbers and party names only — use `number` or `party`. To search memo/line text, use search_journal (`text`) or search_expenses (`text`)."
      +}
    • addedInput schema / properties / vendor
      Added value: +{
      +  "description": "NOT a filter on this tool. Pass a customer or vendor name as `party`."
      +}
  4. Changed3 schema fields changed
    • addedInput schema / properties / dueFrom
      Added value: +{
      +  "description": "Earliest DUE date (YYYY-MM-DD) — this is the \"what's due this week\" filter, and it asks about when the money falls due, not when the invoice was raised (that's `from`/`to`). INVOICES ONLY: pass docType:'invoice' with it, or the call is refused, because nothing else in this search has a due date and quietly dropping every quote and bill would be a wrong answer wearing a right one's clothes.",
      +  "pattern": "^\\d{4}-\\d{2}-\\d{2}$",
      +  "type": "string"
      +}
    • addedInput schema / properties / dueTo
      Added value: +{
      +  "description": "Latest DUE date (YYYY-MM-DD). Same invoices-only rule as dueFrom. Pair the two for a window — dueFrom + dueTo across this week answers \"what's landing on me before Friday\"; dueTo alone with a past date is everything already due.",
      +  "pattern": "^\\d{4}-\\d{2}-\\d{2}$",
      +  "type": "string"
      +}
    • changedInput schema / properties / number / description
      Previous value: -"Partial doc number / reference (case-insensitive)."New value: +"Partial doc number / reference (case-insensitive). On INVOICES this also matches the customer's own Ref No — their DO or PO number, whatever they printed on the paperwork. So a customer chasing \"our PO 4471\" is one call: pass 4471 here. That Ref No is NOT the invoice number; the invoice's own number matches here too, and you cannot tell from a hit which of the two it was — read `number` and `refNo` on the row it comes back with. On MARKETPLACE-IMPORTED invoices the Ref No is the platform's order key (SHOPEE-<order_sn>, TIKTOK-<order id>, SHOPIFY-<order id>), not a customer's number — so a marketplace order id pasted here finds its invoice too."
  5. Changed1 schema field changed
    • changedInput schema / properties / docType / description
      Previous value: -"Restrict to one type: 'invoice','credit_note','quote','delivery_order','bill','debit_note','purchase_order'. Omit for all."New value: +"Restrict to one type: 'invoice','credit_note','sales_debit_note','quote','delivery_order','bill','debit_note','purchase_order'. Omit for all. NOTE the two debit notes: 'sales_debit_note' is one this business ISSUED to a customer (additional charges on an invoice — money owed TO this business); 'debit_note' is the BUY side, issued to a supplier against a bill."
  6. First observed

TDQS

A4.9/5.0
Behavior5/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Despite readOnlyHint=true already covering safety, the description adds extensive behavioral context: payment docId is a bank transaction id (not a document id), refNo is not the invoice number, null dueDate means cash not missing data, einvoice status is 'as recorded in Taokeh' (not portal truth), source is derived not stored, and contras are intentionally absent. This goes far beyond what annotations could convey.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is front-loaded with the core purpose and results, and every sentence carries real semantic weight. However, it is a very long single block with some repetition (the customer Ref No / DO-PO concept is restated multiple times in the description and schema), so it sacrifices scanability for completeness.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

With no output schema, the description fully specifies return-row semantics: which fields appear on which doc types, field omissions vs nulls, payment allocations grain, capped results with more flag, and special id warnings. An agent has everything needed to call correctly and interpret results without guessing.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters5/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema coverage is 76%, but the description substantially enriches parameter meaning: number searches both document number and customer Ref No, dueFrom/dueTo are due-date (not document-date) filters restricted to invoice/bill, docType disambiguates sales_debit_note vs debit_note, and multiple 'NOT a filter' params are correctly routed to canonical parameters. It more than compensates for the remaining undocumented params.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

Opens with a specific verb ('Find') and enumerates exact document types and filter combinations, immediately distinguishing it from line-level, journal, and expense searches. The return row description clarifies what a search_documents hit looks like, and the payments section further scopes the tool to document-grain and bank-line search.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines5/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

Explicitly names alternatives: search_journal for contras/text, search_expenses for text, get_attachment/get_document_pdf for fetching artifacts, and states payments are opt-in by name. It also gives when-not-to-use cases (dueDate filters only with invoice/bill; contras excluded) and reasons for the exclusions.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

Try in Browser

Glama MCP Gateway

Add one secure layer between your agents and this server.

Resources