Skip to main content
Glama

Taokeh MCP server

Stock movements

stock_movements
Read-only

Read the STOCK MOVEMENT LEDGER in bulk — every recorded change to on-hand quantity, across products, in one call. stock_level says how many you have RIGHT NOW for one product; this says WHAT MOVED, WHEN, WHY and WHAT IT LEFT BEHIND. Use it for stock-turn analysis, shrinkage hunting, reorder timing, or reconstructing how a balance got where it is. Every filter is optional and a bare call is a legitimate "what moved lately" pull: narrow with product (case-insensitive contains against the product name OR SKU), from/to (the movement date window, in Malaysian time) and sourceType (exactly one cause — see the list). Each row: ts, product {sku, name}, qtyDelta (signed — negative took stock out), balanceAfter (on-hand immediately after that move, as the posting path recorded it), unitCost, reason (free text the person typed, where there was one), sourceType and sourceId (the id of the document that moved it — pair it with search_documents to see which one). ⚠ WHICH MOVEMENTS EXIST AT ALL DEPENDS ON THIS COMPANY'S STOCK MODE, and the answer says which mode it is in (stockMode) with a note. In modified_periodic — the DEFAULT — selling does NOT move stock: invoices, delivery orders and credit notes write no movement row, and stock is trued up at stock take. Seeing no 'sale' rows there means the company is periodic; it does NOT mean nothing was sold, and it is NOT shrinkage. Only a perpetual company has sale / sale_void / credit_note rows. Read the mode before you interpret the rows. balanceAfter is the total across the whole company, not per location; on a multi-location company each row also carries location. Rows come back newest first, capped at 200 with total, shown and more — when more is true, narrow by date and pull the periods in turn rather than treating a partial page as the whole. Values are verbatim as recorded at the time, never re-derived. ⛔ WHAT IT WILL NOT DO: it does not value your inventory (balance_sheet does), does not compute COGS or margin (income_statement, profit_drivers), and does not tell you what to reorder (low_stock). Nothing is written, and no draft is created.

Input Schema

TableJSON Schema
NameRequiredDescriptionDefault
toNoLatest movement date (YYYY-MM-DD, Malaysian time).
skuNoNOT a filter on this tool. Pass it as `product` — one case-insensitive contains matched against BOTH the product name and the SKU.
dateNoNOT a filter on this tool. Pass a date WINDOW as `from` and/or `to` (YYYY-MM-DD). A single date is `from` and `to` set to the same day.
fromNoEarliest movement date (YYYY-MM-DD, Malaysian time). The main way to break a >200-row pull into honest slices.
itemNoNOT a filter on this tool. Pass it as `product` — one case-insensitive contains matched against BOTH the product name and the SKU.
nameNoNOT a filter on this tool. Pass it as `product` — one case-insensitive contains matched against BOTH the product name and the SKU.
typeNoNOT a filter on this tool. Pass the movement cause as `sourceType`.
limitNoNOT a filter on this tool. The page size is fixed at 200 movements. Narrow with from/to, product or sourceType and pull the periods in turn.
queryNoNOT a filter on this tool. Pass it as `product` — one case-insensitive contains matched against BOTH the product name and the SKU.
dateToNoNOT a filter on this tool. Pass the end of the window as `to`.
reasonNoNOT a filter on this tool. `reason` is free text the person typed and is RETURNED on each row, not a filter. To narrow by cause use `sourceType` (e.g. 'adjustment').
sourceNoNOT a filter on this tool. Pass the movement cause as `sourceType`.
productNoCase-insensitive contains matched against the product NAME or SKU. Omit for every product.
dateFromNoNOT a filter on this tool. Pass the start of the window as `from`.
productIdNoNOT a filter on this tool. This search matches product TEXT, not ids — pass the name or SKU as `product`.
sourceTypeNoExactly one movement cause. One of: purchase, purchase_void, debit_note, debit_note_void, adjustment, stock_take, import_opening, assembly_out, assembly_in, disassembly_out, disassembly_in, sale, sale_void, credit_note, transfer_out, transfer_in. Note that sale, sale_void, credit_note only ever exist in a perpetual company.
productNameNoNOT a filter on this tool. Pass it as `product` — one case-insensitive contains matched against BOTH the product name and the SKU.

Schema Changelog

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

  1. Changed1 schema field changed
    • changedInput schema / properties / sourceType / description
      Previous value: -"Exactly one movement cause. One of: purchase, purchase_void, debit_note, debit_note_void, adjustment, stock_take, import_opening, assembly_out, assembly_in, disassembly_out, disassembly_in, sale, sale_void, credit_note, transfer_out, transfer_in. Note that sale, sale_void, credit_note only ever exist in a perpetual workspace."New value: +"Exactly one movement cause. One of: purchase, purchase_void, debit_note, debit_note_void, adjustment, stock_take, import_opening, assembly_out, assembly_in, disassembly_out, disassembly_in, sale, sale_void, credit_note, transfer_out, transfer_in. Note that sale, sale_void, credit_note only ever exist in a perpetual company."
  2. Added

TDQS

A4.9/5.0
Behavior5/5

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

Beyond the readOnlyHint=true annotation, the description discloses crucial behavioral traits: row cap at 200 with total/shown/more, newest-first ordering, stock-mode dependence, balanceAfter being company-wide, and values being verbatim as recorded. It also states 'Nothing is written, and no draft is created,' reinforcing the read-only safety profile. This is rich, non-obvious context that annotations alone cannot convey.

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

Conciseness5/5

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

The description is long but every sentence earns its place: purpose, use cases, filter semantics, row format, the critical stock-mode caveat, pagination behavior, and explicit exclusions. It is front-loaded with the core purpose, uses structured warnings and a clear 'WHAT IT WILL NOT DO' section, and avoids repetition or filler.

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?

For a tool with no output schema and many subtle behavioral traps, the description is exceptionally complete. It covers return fields, signed quantity semantics, balanceAfter scope, location presence, pagination handling, stock mode interpretation, and how to follow sourceId to search_documents. An agent has everything needed to call this correctly and interpret results properly.

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

Parameters4/5

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

Schema coverage is 100%, so the schema already documents each parameter. The description adds genuinely useful parameter semantics beyond that: every filter is optional, product matches case-insensitively against name OR SKU, from/to define a Malaysian-time window, and from is 'the main way to break a >200-row pull into honest slices.' This is more than the schema-only baseline, though the schema still carries most of the parameter documentation load.

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?

The description opens with a specific verb and resource: 'Read the STOCK MOVEMENT LEDGER in bulk — every recorded change to on-hand quantity, across products, in one call.' It clearly differentiates itself from stock_level by contrasting 'how many RIGHT NOW' with 'WHAT MOVED, WHEN, WHY and WHAT IT LEFT BEHIND.' This makes the tool's identity unambiguous even among many sibling tools.

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?

The description gives concrete use cases (stock-turn analysis, shrinkage hunting, reorder timing, reconstructing a balance) and explicitly states what it will NOT do, naming the correct sibling tools for those jobs (balance_sheet, income_statement, profit_drivers, low_stock). It also explains when a bare call is legitimate and how to narrow it, giving clear operational guidance.

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