Back to MCP Servers (sign in required)

Cin7 Core (Dear) Operations MCP Server

This MCP server is fast and powerful because it uses the GrowthPath App Server's cached Cin7 Core (Dear) data to let AI assistants search orders, products, customers and stock in ways that are not practically possible through the Dear API alone.

It provides read-only searches, selected summary reports and integration-job diagnostics. Results reflect the cached data, not necessarily the current state in Cin7 Core. A cached stock check is not a live availability guarantee. This release does not expose tools for changing Cin7 Core records. Broader historical analytics are available through GrowthPath's separate analytics reporting module.

New to MCP? Model Context Protocol (MCP) is a standard way for AI assistants to connect to business systems. An MCP server makes selected data and tools available to a connected assistant, so you can ask questions in ordinary language instead of looking up each record yourself. Read Cloudflare's introduction to MCP and MCP servers for an overview of how it works and the security considerations.

Connect this server

MCP endpoint
https://statusanxiety.growthpath.com.au/mcp-dear
Transport
Streamable HTTP
OAuth scope
mcp_dear.read
Resource metadata
https://statusanxiety.growthpath.com.au/.well-known/oauth-protected-resource/mcp-dear
Authorization server
https://statusanxiety.growthpath.com.au
Authorized user
Active Django user in the mcp group, or a superuser; staff status alone is insufficient.
Plain-text setup instructions for an AI or MCP client
Configure the Cin7 Core (Dear) Operations MCP server.
Server URL: https://statusanxiety.growthpath.com.au/mcp-dear
Transport: Streamable HTTP
Preferred authentication: MCP OAuth (authorization code with PKCE S256).
Requested scope: mcp_dear.read
Protected-resource metadata URL: https://statusanxiety.growthpath.com.au/.well-known/oauth-protected-resource/mcp-dear
Authorization server: https://statusanxiety.growthpath.com.au
Sign in as an active Django user in the mcp group or a superuser.
Review the client, callback origin, resource and scope before approving access.
Manual fallback: Authorization: Token <token key> (a Django REST Framework token, not a Dear API key).
Store credentials only in the client's approved secret or credential store, never in chat, logs or source control.
This server exposes read-only cached data, not live stock guarantees or record mutations.
Use the MCP endpoint, not the documentation page. A local documentation preview does not verify a local MCP transport.

Select and copy the text manually if clipboard access is unavailable.

Prefer OAuth. For clients without OAuth, use a Django REST Framework token through an approved credential store; see Manual API Token Setup. Never paste credentials into an AI conversation.

Current release: this MCP server is read-only. It can help clients discover, search, and understand configured Cin7/Dear data through read-only tools.
Current safety model: OAuth bearer authentication for desktop agents; DRF token authentication using Authorization: Token <token key>, or a bare token value for clients such as Microsoft Copilot Studio; runtime namespace scoping; pre-authentication throttling; per-token rate limiting; read-only cache and product-availability tools; summarized job-log queries; and allowlisted read-only or dry-run harness execution. Only read-only and dry-run paths are documented here.

Authentication

Public documentation: this page does not require a Django login so an LLM can read it and configure the MCP server. The MCP endpoint still requires an authenticated token.
Documentation URL vs MCP endpoint: /mcp_dear_documentation/ is this human-readable documentation page. Do not enter the documentation URL in an MCP client. Configure MCP clients with https://statusanxiety.growthpath.com.au/mcp-dear, which uses /mcp-dear. A 401 response from /mcp-dear with a WWW-Authenticate header is expected before OAuth authentication.

Preferred OAuth Setup For Desktop Agents

Recommended for ChatGPT, Claude Desktop, and similar desktop agents: use the built-in MCP OAuth flow instead of manually handling a DRF token.

Desktop agents that support MCP OAuth should be configured with the MCP server URL below and allowed to complete the browser-based OAuth login. The client should discover this server's protected-resource metadata from the WWW-Authenticate challenge or from the well-known metadata path on the same host as the MCP endpoint.

  • Server URL: https://statusanxiety.growthpath.com.au/mcp-dear
  • Protected-resource metadata URL: https://statusanxiety.growthpath.com.au/.well-known/oauth-protected-resource/mcp-dear
  • Authorization server: https://statusanxiety.growthpath.com.au
  • OAuth flow: authorization code with PKCE S256 and dynamic public-client registration.
  • OAuth refresh: refresh tokens are supported for OAuth clients and are rotated after successful use.
  • Requested scope: mcp_dear.read

The user who signs in through OAuth must be an active Django user authorized for MCP access: either a superuser or a member of the Django auth group named mcp. Do not paste OAuth access tokens, refresh tokens, authorization codes, or DRF token keys into normal chat messages.

After signing in, review the client name, callback origin, requested resource and scopes, then choose Allow access or Cancel. Only approve a connection you started and recognise. Opening the authorization link alone does not grant access. Each authorization requires a new review; the review expires after 10 minutes and a newer review in the same browser replaces the previous one.

OAuth access tokens are intentionally time-limited. Clients that support OAuth refresh should keep refresh tokens only in their approved credential store, use them to get fresh access tokens, and replace the stored refresh token whenever the token endpoint returns a rotated value. If a client cannot refresh automatically, re-run the browser-based OAuth authorization flow rather than copying tokens through chat or logs.

Refresh tokens are stored server-side only as hashes. Administrators can revoke stored refresh tokens in Django admin without seeing the plaintext token value.

Manual API Token Setup

Use this path for MCP clients that cannot complete the OAuth flow. The preferred complete header is Authorization: Token <token>. A bare token header, Authorization: <token>, is also accepted for clients such as Microsoft Copilot Studio that configure the header name and secret value separately but cannot prepend the Token scheme. The token is the key from Django REST Framework's Token model, stored in the Django database and managed in Django admin. It is not a Dear API key.

  1. In Django admin, create or select an active Django user account for the MCP client.
  2. Authorize that user by adding it to the Django auth group named mcp, or by making it a superuser. Staff status alone does not authorize MCP access.
  3. In Django admin, create or find the token for that same user in the Tokens table under Auth Token. The token row's key value is the token used by the MCP client. Modifying this table requires the appropriate Django admin permission and is normally restricted to superusers.
  4. Configure the MCP client to send Authorization: Token <token key> on every MCP request. If the client cannot prepend an authentication scheme, configure the same header as Authorization: <token key>.

MCP_DEAR_ALLOWED_ACTOR_EMAIL is not required for read-only MCP access. Access is based on the Django user linked to the supplied DRF token: the user must be active and either in the mcp group or a superuser.

Authorization is also scoped by namespace and Dear instance configuration. Tools can only read the object types and run the read-only or dry-run harnesses explicitly allowed for the runtime namespace.

These object-type permissions also apply to dedicated lookups, stock availability, recent sales, transaction reads and operation planning, not just generic cache searches.

Most tools accept an optional entity argument. If this deployment exposes only one Dear instance, omit entity and the MCP server will use that instance automatically. If multiple instances are exposed, the server will reject ambiguous requests and list the allowed entity values. Use list_queryable_object_types to discover the enabled cached object types and accepted filter keys before calling search_cached_objects.

MCP Client Setup

MCP client setup differs between tools such as Claude Desktop, Codex-style coding tools, and other MCP-enabled assistants, so this page documents the stable protocol values rather than tool-specific click paths. Prefer OAuth when the client supports it. You can give an MCP-enabled assistant this documentation URL and ask it to read the page and configure the server, but do not paste the DRF token into an ordinary chat prompt. If your client asks for a server name, choose a local label such as cin7-mcp; that label is not a server-side identifier and does not prove the connection is installed. Verify the client lists the MCP server, then complete the client's OAuth authentication flow. For Claude Desktop, a restart may be required after changing MCP configuration. For Claude Code, see Claude MCP Quickstart.

  • Server URL: https://statusanxiety.growthpath.com.au/mcp-dear
  • Transport: streamable HTTP MCP endpoint.
  • Preferred authentication: MCP OAuth using the protected-resource metadata and scope mcp_dear.read.
  • OAuth status endpoint: /mcp_oauth/status/ reports issuer, resource metadata, and token lifetimes.
  • Manual fallback header: Authorization: Token <token key>
  • Microsoft Copilot Studio fallback: header name Authorization, value <token key>.
  • Manual fallback token source: Django REST Framework's Token model in Django admin.

Enter the token only through the client's approved secret, environment-variable, credential, or HTTP-header configuration mechanism. If a client cannot store the token outside normal chat history, shared configuration, logs, or source control, do not connect that client until a safer setup path is available.

Codex Web App Setup

In the Codex web app, create a new app using this deployment's MCP server URL, https://statusanxiety.growthpath.com.au/mcp-dear, and OAuth.

  • Name: use a clear label such as Equipped Dear MCP or Cin7 Dear MCP.
  • Connection: choose Server URL and enter https://statusanxiety.growthpath.com.au/mcp-dear.
  • Authentication: choose OAuth.
  • Advanced OAuth settings: normally leave discovery enabled unless an administrator gives explicit values.
  • Risk warning: continue only for approved GrowthPath MCP deployments.

Configured Dear Scope

Namespace Dear Instances Read Object Types Allowed Harnesses
statusanxiety statusanxiety_2023 orders, sale_credits, sale_credits_stand_alone, account_metadata, accounts, payment_terms, tax_rules, purchase_orders, products, product_families, product_movements, customers, suppliers, locations, carriers, finished_goods, disassemblies, stock_transfers, stock_adjustments None

Knowledge Resources

  • dear://meta/server
  • dear://instance/{entity}
  • dear://catalog/object-types
  • dear://catalog/object-type/{object_type}
  • dear://catalog/jsonb-search
  • dear://typed-dict/{typed_dict_name}
  • dear://typed-dict/{typed_dict_name}/json-schema
  • dear://harness/{harness_name}
  • dear://job-log-guide

MCP Tools

The tools below are the callable API surface exposed by the Cin7/Dear MCP server. Use discovery tools first to resolve the namespace, entity, object type, accepted filters, and safety limits before calling data or diagnostic tools.

Safety summary: cached-data, report, schema, and job-log tools are read-only. Harness execution is allowlisted and should remain read-only or dry-run only. Operation tools validate and plan future operational workflows, but this release does not expose an execution tool.
Tool selection: use get_recent_sales for prompts like "most recent sales" or "latest orders." Use get_sale_transactions only when the user asks for accounting transaction lines from sales; it expands nested transaction JSON and is intentionally heavier. Use get_sale_order_lines for order lines across multiple sales. Use get_additional_attribute_sets to discover custom-field labels before selecting numbered fields.

Discovery And Schema

whoami

Confirm which Django/OAuth actor the MCP request is running as.

Arguments
None.
Returns
Actor email and authentication context.
Side effects and notes
None.

list_dear_instances

List the Dear/Cin7 Core instances exposed to the current namespace.

Arguments
None.
Returns
Configured entity names, account IDs, and company summary fields.
Side effects and notes
None.

describe_namespace

Describe the runtime namespace and its configured Dear scope.

Arguments
None.
Returns
Namespace, deployment_version, allowed entities, readable object types, and allowed harnesses.
Side effects and notes
None.
deployment_version is the running application build, also reported as serverInfo.version at initialization and in the server instructions. Use it to identify outdated client metadata; reading it does not force the client to refresh instructions or tool definitions.

list_entities

List Dear entity values that may be passed to scoped tools.

Arguments
None.
Returns
Entity records for the current namespace.
Side effects and notes
None.

get_object_type_schema

Fetch schema, selectable scalar fields, and search metadata for one cached object type.

Arguments
object_type.
Returns
Object-type schema, payload type, lifecycle, supported search metadata, and field_projection capabilities.
Side effects and notes
None.
Call list_queryable_object_types first when choosing object_type values for cache search. Call this tool before supplying fields to get_recent_sales or search_cached_objects. For bulk sale lines, object_type='orders' also publishes sale_order_lines.selectable_fields. Use object_type='accounts' to discover account fields without fetching account records.

list_queryable_object_types

List cached object types that can be searched in this namespace.

Arguments
None.
Returns
Queryable object types plus accepted standard and JSONB filter keys.
Side effects and notes
None.

get_additional_attribute_sets

Discover cached additional-attribute set labels, types and numbered field paths.

Arguments
object_type=products|customers, optional set_name (exact), label_contains (literal), limit=20 (maximum 100 sets/1000 labels), cursor and entity.
Returns
Current cached definitions, freshness, unresolved-definition counts and signed continuation.
Side effects and notes
None; no provider call, cache refresh or master values.
Use this when a user's business term is not a standard field. Labels are account- and set-specific. Consider synonyms as candidates; ask when product/customer/header meaning is ambiguous. A catalog entry does not prove record assignment. Inspect invalid/ambiguous counts before concluding a label is absent. Missing cache is not evidence that no sets exist. Use include_attribute_metadata=true on master or sale-line reads for actual assignments. Current definitions are not historical label snapshots. Metadata does not make master values bulk-selectable. Use next_cursor to read remaining definitions.

describe_workflow

Explain a curated Dear operational workflow.

Arguments
workflow_name.
Returns
Workflow description, guidance, and source-file references.
Side effects and notes
None.

Cached Dear Data

get_cached_sale

Look up one cached sale/order by order number.

Arguments
order_number, optional entity.
Returns
The matching cached sale payload and scope metadata.
Side effects and notes
None; reads the GrowthPath cache, not the live Dear API.
Use these tools for questions about configured Cin7 Core data, not general product how-to documentation.

get_cached_sale_collection

Return one sale sub-collection without returning the full sale payload.

Arguments
order_number, collection, optional limit (maximum 500), page=1, optional entity.
Returns
One page of rows from the selected sale collection with exact page metadata.
Side effects and notes
None.
Legacy collections are transactions, order_lines, payments, and fulfilments. Omitting limit preserves their complete collection; provide limit to use page numbers. Additional collections are invoices, credit_notes, invoice_lines, and credit_note_lines. These return reviewed fields only, default to 100 rows and allow at most 100 rows per page. Line collections include both product Lines and AdditionalCharges, with original document and line positions. Follow has_more and page metadata for complete detail. The maximum offset is 10000: at limit=100, capacity is 101 pages and 10100 rows per collection. Check pagination_truncated; get_cached_sale remains available for full single-order payloads. Embedded credits can also exist in sale_credits; do not add both representations to revenue. Use these tools for questions about configured Cin7 Core data, not general product how-to documentation.

get_cached_product

Look up one cached product by SKU.

Arguments
sku, optional entity and include_attribute_metadata=false.
Returns
The matching cached product payload and scope metadata.
Side effects and notes
None; reads the GrowthPath cache, not the live Dear API.
Set include_attribute_metadata=true to attach the product's current cached set and labels. Raw payload fields remain unchanged. Use these tools for questions about configured Cin7 Core data, not general product how-to documentation.

get_cached_customer

Look up one cached customer by name or GUID.

Arguments
customer_name_or_guid, optional entity and include_attribute_metadata=false.
Returns
The matching cached customer payload and scope metadata.
Side effects and notes
None; reads the GrowthPath cache, not the live Dear API.
Set include_attribute_metadata=true to attach the customer's current cached set and labels. Customer attributes are separate from product sale-line custom fields. Use these tools for questions about configured Cin7 Core data, not general product how-to documentation.

get_product_availability

Check cached product availability and stock by SKU, product, location, bin, or batch.

Arguments
Optional sku, product_id, location, bin_name, batch, consolidate_bins=true, limit=25 (maximum 1000), optional entity, cursor, or page, include_totals=true.
Returns
Availability rows and totals for the scoped product availability cache, with matched_row_count, has_more, total_pages, and next_cursor when another page is available.
Side effects and notes
None.
Use next_cursor for sequential traversal or a 1-based page for random access; never provide both. Pages are not a stable cross-call snapshot. Set include_totals=false for traversal without counting and summing all matching stock rows. Use these tools for questions about configured Cin7 Core data, not general product how-to documentation.

get_product_movements

Return cached product movement rows for one SKU.

Arguments
sku, optional movement_type, optional location, sort_by=DateDesc, limit=20 (maximum 500), page=1, optional entity.
Returns
Bounded product movement rows and search metadata.
Side effects and notes
None.
Use these tools for questions about configured Cin7 Core data, not general product how-to documentation.

get_recent_sales

Return recent cached sale/order summaries newest-first by SaleOrderDate.

Arguments
Optional statuses, sale_order_date_from, sale_order_date_to, sort_by=SaleOrderDateDesc, limit=25 (maximum 1000), page=1, optional entity, and up to 20 schema-discovered scalar fields.
Returns
Sale summary rows by default, or identity metadata plus only requested scalar DearSale values.
Side effects and notes
None.
Use this for prompts like 'most recent sales' or 'latest orders'. For stuck/status exception queues, use search_cached_objects. Before supplying fields, call get_object_type_schema with object_type='orders'. Use these tools for questions about configured Cin7 Core data, not general product how-to documentation.

get_sale_order_lines

Read projected cached sale order lines across sales, with optional numbered custom fields.

Arguments
Optional statuses, sale_order_date_from, sale_order_date_to, fields, limit=100 (maximum 500), cursor, include_total_count=false, include_attribute_metadata=false, and entity.
Returns
Line identity, original zero-based line_index, selected scalar values, and next_cursor.
Side effects and notes
None; reads cached Order.Lines, not live Dear or current product attributes.
Default fields are ProductID, SKU and Quantity. ProductCustomField1 through ProductCustomField10 require explicit selection. Their labels depend on the product's attribute set; do not infer labels from slot numbers. Set include_attribute_metadata=true to resolve each line's current product set and return each used definition once per page. The response has no historical label snapshot. Call get_object_type_schema with object_type='orders' for approved sale_order_lines fields. This is not accounting Transactions or a complete sales-revenue report. Date bounds are inclusive sale-calendar dates. Date-filtered calls examine at most 100 parents plus one parent-ID lookahead. Continue with next_cursor even when row_count is zero. A sale with more than 500 lines continues at its original line position; duplicate SKUs remain. Exact counts are off by default. Pages are not a stable cross-call snapshot. Use these tools for questions about configured Cin7 Core data, not general product how-to documentation.

get_sale_invoices

Read cached invoice headers by invoice calendar date, including invoices on older orders.

Arguments
invoice_date_from, invoice_date_to (inclusive YYYY-MM-DD, at most 31 days), optional statuses, limit=100 (maximum 500), cursor and entity.
Returns
Original reviewed invoice values, sale context, distinct revenue accounts, line counts and a signed next_cursor. No full-period count is calculated.
Side effects and notes
None; reads cached orders.Invoices, without provider calls or cache refreshes.
Convert a named month and year to inclusive YYYY-MM-DD calendar dates before calling date-filtered tools. For example, 'October 2026' means from='2026-10-01' and to='2026-10-31'. Use the actual last day of the month, including leap years. Do not substitute month-to-date unless requested. If the year or reference date cannot be resolved from the conversation, ask the user instead of guessing. Do not shift calendar dates between time zones or send month names or date prefixes as date bounds. Supply these bounds as invoice_date_from and invoice_date_to. Default invoice statuses are AUTHORISED, PAID and PARTIALLY PAID. Parent status is returned as sale.Status, not used to exclude invoice records. The date filter uses InvoiceDate, not SaleOrderDate or cache modification time. Missing or invalid invoice calendar dates do not match. Calls examine 100 date-matched parents plus one parent-ID lookahead. Continue after an empty page while next_cursor exists; original invoice positions are retained. Pages are not a stable cross-call snapshot. Split longer periods into non-overlapping windows of at most 31 inclusive days, with no gaps. Amounts remain in document currency; a header total is not a per-account revenue amount. For net sales, read both sale_credits and sale_credits_stand_alone using credit_note_date_from/to and subtract each authorised credit once. For lines and additional charges, use get_cached_sale_collection with invoice_lines or credit_note_lines. Prefer Analytics MCP for recurring aggregate revenue, channel grouping and currency conversion. Use these tools for questions about configured Cin7 Core data, not general product how-to documentation.

get_sale_transactions

Return flattened accounting transaction lines for cached sales in a bounded date range.

Arguments
sale_order_date_from, sale_order_date_to, optional statuses, sort_by=SaleOrderDate, limit=100 (maximum 500), page=1, optional entity.
Returns
Bounded transaction-line rows for cached sales.
Side effects and notes
None.
Do not use this for recent sale/order lists; use get_recent_sales instead. The maximum row offset is 10000: at limit=500, at most 21 pages (10500 rows) are accessible. Check pagination_truncated before treating the result as complete. Use these tools for questions about configured Cin7 Core data, not general product how-to documentation.

search_cached_objects

Search allowlisted cached Dear object summaries with standard filters, bounded JSONB filters, and deterministic cursor or page-number pagination.

Arguments
object_type, filters, limit=25 (maximum 1000), optional entity, cursor or page, sort_by=last_modified|object_uniqueID (also sale_order_date for orders, order_date for purchase_orders, credit_note_date for both sale credit types), sort_direction=asc|desc, optional fields (1 to 20 schema-discovered scalar paths), optional include_total_count=true, include_credit_header_amounts=false, include_nested_collections, nested_collection_limit=100 (maximum 100), and nested_collection_offset=0 (maximum 10000). Expanded searches support at most 25 documents per page.
Returns
Matching cached object summaries by default, or identity metadata plus requested scalar values; also exact cached-row counts, cache semantics, and next_cursor when another page is available. Requested nested collections include per-document counts and truncation metadata.
Side effects and notes
None.
Unsupported filters are rejected rather than ignored. Use this for exact status queues, stuck orders, object cleanup, and filtered cached object searches. Summaries are the default; request selected scalar fields only after calling get_object_type_schema for the object type, and request only the nested collections needed for line-level analysis. Repeat the same query arguments with next_cursor to continue, or use a 1-based page for random access; never provide both. Pages are not a stable cross-call snapshot and rows are summaries. For a known customer reference or Shopify order name with known spelling and case, use object_type="orders" and filters={"jsonb_filters":[{"path":"CustomerReference","operator":"equals","value":"#1001"}]}. This exact-match expression supports the existing customer-reference index. The standard customer_reference filter and JSONB iexact operator are case-insensitive; use them when case-insensitive matching is required. Set include_total_count=false whenever an exact total is unnecessary, including single-reference lookups and cursor traversal, to avoid counting every matching row. For sale-calendar windows, use sale_order_date_from/to filters and sort_by='sale_order_date'; for purchase orders, use order_date_from/to and sort_by='order_date'. For both sale_credits types, use credit_note_date_from/to and sort_by='credit_note_date'. Set include_credit_header_amounts=true to resolve native TotalBeforeTax, Tax and Total for either credit type, with limit at most 100. Raw fields stay unchanged. Each row reports credit_header_amounts with status, values, original currency, field sources and any reason. Use its values only when status='resolved', instead of adding them to raw totals. Missing, ambiguous, invalid or conflicting parent headers remain unresolved. The lookup uses the same account, exact order number, TaskID and credit number. It reads at most two matching parent headers per credit in the same search statement. Follow all cursors and check unresolved_count before reporting a complete total. For net sales, select AUTHORISED credits from both credit types and subtract each once. Do not also subtract their embedded sale representation or sum different currencies. Convert a named month and year to inclusive YYYY-MM-DD calendar dates before calling date-filtered tools. For example, 'October 2026' means from='2026-10-01' and to='2026-10-31'. Use the actual last day of the month, including leap years. Do not substitute month-to-date unless requested. If the year or reference date cannot be resolved from the conversation, ask the user instead of guessing. Do not shift calendar dates between time zones or send month names or date prefixes as date bounds. For either credit type, October 2026 uses filters={"credit_note_date_from":"2026-10-01","credit_note_date_to":"2026-10-31"}. JSONB contains does not match date prefixes; '2026-10' does not match a full CreditNoteDate. For invoice-date selection, use get_sale_invoices. Existing defaults remain last_modified descending with exact counts. Prefer cursors over deep page offsets. Use customer_contains on orders, supplier_contains on purchase_orders, and name_contains on customers for literal case-insensitive substrings; percent and underscore are not wildcards. Existing customer, supplier, name and ID filters keep their exact-match meaning. For bulk Order.Lines, use get_sale_order_lines instead of fetching each sale. For purchase receipt lines, request StockReceived.Lines and PutAway.Lines on purchase_orders. PutAway can contain receipts when StockReceived is empty; do not sum both collections. Representation depends on purchase type and Use Put Away configuration. Advanced Purchases with that mode enabled separate receiving from put-away; inspect both stages and Received flags. An empty stage does not prove no receipt. Line Date is not the invoice date. For products, request Suppliers, Suppliers.ProductSupplierOptions and ReorderLevels. These collections return reviewed scalars in values with source positions and optional parent context, not full native items. Supplier options are paged separately from supplier headers. At most 25 parents and 100 source slots per requested collection are read into the response per call. Check source_state, source_complete, unavailable_branch_counts, invalid counts and source_non_scalar_field_counts; unavailable data is not zero. source_complete checks structure, not domain validity or freshness. Follow next_offset for one parent/collection before moving past its outer cursor. At limit=100, at most 101 nested pages and 10100 source slots are accessible per parent collection. Check pagination_truncated and matches_remain. Receipt task Status alone does not prove receipt: Received=true identifies received lines, and a task can remain DRAFT while PutAway is pending. No PutAway fallback is applied. Receipt Date is raw; its meaning is not verified for every workflow. Order-date filters select PO OrderDate, not receipt dates. Lead and Safety are configured values with units and schedule rules not verified here, not measured lead times. Null supplier-option locations represent defaults. Keep location reorder levels, supplier options and product-wide settings separate. No lead-time calculation or reorder recommendation is performed. Use these tools for questions about configured Cin7 Core data, not general product how-to documentation.

Aggregate Reports

list_aggregate_reports

List allowlisted grouped or ranked reports.

Arguments
None.
Returns
Report names, filters, execution_mode and execution_tool; use the declared tool.
Side effects and notes
None.

run_aggregate_report

Run an allowlisted grouped or ranked read-only summary report.

Arguments
report_name, optional filters, limit=10 (maximum 100), page=1, optional entity.
Returns
One page of capped aggregate rows and page metadata.
Side effects and notes
None; successful results may be briefly cached server-side.
Reports do not return individual order rows. Source-batch reports use run_aggregate_report_batch preferentially. If a complete query times out, follow the JSON error's advertised fallback only. Discard prior complete pages before restarting as batches. No fallback means batching is not registered; do not invent one or repeatedly retry. Use these tools for questions about configured Cin7 Core data, not general product how-to documentation.

run_aggregate_report_batch

Read partial counts for a report with registered batch support, including products_by_status.

Arguments
report_name, optional filters, cursor from the previous accepted response, optional entity.
Returns
Batch-local rows, batch_id, scanned_count, has_more and next_cursor. Not complete totals.
Side effects and notes
None; selects at most 501 source records per call, counts at most 500.
Sum product_count by status across batches. NEVER stop on empty rows: continue until has_more=false. Count each batch_id once; replace retries, not add them. Use unchanged filters and entity throughout. Cache changes between calls are accepted; no consistent snapshot is promised. Retry the current batch only; restarting earlier requires discarding it and all following batches. Sort final totals only after all batches. A failed call contributes nothing and advances no cursor. For query_timeout, follow the error's retry arguments once; stop and seek support if it repeats.

Job Logs And Diagnostics

query_job_logs

Search summarized GrowthPath JobLog records for support diagnostics.

Arguments
Optional entity, job_id, title_pattern, statuses, limit=50 (maximum 1000), page=1.
Returns
Matching job-log summaries and count metadata.
Side effects and notes
None.
Use these tools for questions about configured Cin7 Core data, not general product how-to documentation.

Harnesses

list_harnesses

List diagnostic harnesses allowed for the current namespace.

Arguments
Optional entity.
Returns
Harness names, safety classes, execution targets, and argument specs.
Side effects and notes
None.

get_harness_spec

Fetch the full specification for one diagnostic harness.

Arguments
harness_name.
Returns
Harness description, safety class, target, allowed scope, and arguments.
Side effects and notes
None.

run_harness

Start a controlled, allowlisted diagnostic harness run.

Arguments
harness_name, args, dry_run=true, optional entity.
Returns
Run ID, validation result, job metadata, and launch status.
Side effects and notes
Creates JobLog audit records and executes the allowlisted harness target.
Harnesses documented for this server should remain read-only or dry-run only. run_harness itself is not read-only or idempotent: each call creates audit records and starts work. For the transaction validator, month is 1-12, year is 1-9999 (excluding December 9999), and sample_limit is 1-100. Output retains at most 8 KiB per line and the first 1 MiB of source bytes per run, with additional truncation markers.

get_harness_run_status

Check completion state for a previous harness run.

Arguments
run_id, optional entity.
Returns
Run status, timestamps, and job metadata.
Side effects and notes
None.

get_harness_run_logs

Fetch logs emitted by a previous harness run.

Arguments
run_id, limit=100 (maximum 250), page=1, optional entity.
Returns
One page of bounded log messages with exact page metadata.
Side effects and notes
None.

Planning-Only Operations

list_operations

List known operational workflows that can be inspected or planned.

Arguments
Optional entity.
Returns
Operation specs, safety classes, arguments, checks, and execution flags.
Side effects and notes
None.
The current MCP server exposes planning and validation only, not execution.

describe_operation

Fetch the full specification for one operation.

Arguments
operation_name.
Returns
Operation title, safety class, allowed fields, side effects, and required checks.
Side effects and notes
None.

validate_operation

Validate operation arguments and entity scope before planning.

Arguments
operation_name, args, entity.
Returns
Validation result, blockers, normalized args, and execution flags.
Side effects and notes
None.

plan_operation

Build a dry-run plan for an allowlisted operation.

Arguments
operation_name, args, entity.
Returns
Dry-run plan, blockers, warnings, plan hash, required checks, and source files.
Side effects and notes
Reads cached data to build the plan; does not execute the operation.
No execute_operation tool is exposed in this release.

Agentic Workflow Examples

These examples are intended for n8n-style agents and other MCP clients that need a safe first tool choice before chaining additional steps. Treat them as guidance for read-only investigation and dry-run planning, not permission to perform arbitrary ERP mutations.

Workflow Best first tool Likely follow-up Safety class
Investigate one delayed order. get_cached_sale query_job_logs for related sync or fulfilment activity. Read-only investigation.
Find stuck orders or status queues. search_cached_objects get_cached_sale for one selected order. Read-only filtered search.
Check cached stock availability for a SKU. get_product_availability get_cached_product for product master data. Read-only stock check.
Investigate unusual stock movements. get_product_movements get_product_availability for cached stock state. Read-only movement review.
Support lookup for a customer. get_cached_customer search_cached_objects for related cached orders. Read-only customer context.
Find a product or customer custom field by its business label. get_additional_attribute_sets for products or customers. get_cached_product or get_cached_customer with include_attribute_metadata=true to check the record's assigned set. Read-only current cached definitions and assignments; not historical labels.
Read sale-order lines across a sale-date range. get_object_type_schema for orders. get_sale_order_lines with approved fields; follow next_cursor even after an empty page. Read-only cached order lines; not an invoiced-revenue report.
Find sales or purchase orders by business date and part of a customer or supplier name. list_queryable_object_types for accepted filters. search_cached_objects with date filters, customer_contains or supplier_contains, and the matching business-date sort. Read-only filtered search; not a cache-modification date search.
Check failed sync jobs or daily exception digests. query_job_logs describe_workflow when an operator needs workflow context. Read-only diagnostics.
Prepare reconciliation evidence. get_sale_transactions get_cached_sale_collection for payments or fulfilments on one sale. Read-only, heavier accounting query.
Run sales or stock summary reporting. list_aggregate_reports Use the report's execution_tool: run_aggregate_report or run_aggregate_report_batch. Follow its continuation and merge rules. Read-only aggregate summary.
Find received quantities and dates for a purchase order. get_object_type_schema for purchase_orders. search_cached_objects by order_number, requesting both StockReceived.Lines and PutAway.Lines. See receipt interpretation and limits. Read-only receipt detail; do not count both stages as separate deliveries.
Read invoices or credits for a calendar month. get_sale_invoices for invoice dates. search_cached_objects for both credit types with credit-date filters. Follow all cursors. For net sales, subtract each authorised credit once. Read-only document detail; do not sum different currencies.
Find product data cleanup candidates. search_cached_objects get_cached_product for a selected SKU. Read-only filtered search.
Enumerate all matching cached object summaries. search_cached_objects with a bounded limit. Repeat the same query with each returned next_cursor until has_more=false. Read-only paged cache search; not a stable snapshot.
Find purchase orders needing follow-up. get_object_type_schema for purchase-order filter fields. search_cached_objects with supported filters. Read-only purchasing support.
Plan a safe operational change. plan_operation validate_operation and human approval before any future execution path. Dry-run/planning only.
Support a 3PL fulfilment question for one sale. get_cached_sale_collection Use collection=fulfilments, then query_job_logs if sync context is needed. Read-only fulfilment context.

Object Types

Object Type Lifecycle Queryable By Default Payload Type
orders active True DearSale
sale_credits active True SaleCreditNoteModelEnhanced
sale_credits_stand_alone active True SaleCreditNoteStandAloneModel
account_metadata active True Dear_Me
accounts active True Account
stock deprecated False UNSPECIFIED
payment_terms active True PaymentTerm
tax_rules active True TaxModel
purchase_orders active True AdvancedPurchase
products active True Product
product_families active True ProductFamily
product_availability deprecated False ProductAvailability
hard_allocations deprecated False UNSPECIFIED
hard_allocation_details deprecated False UNSPECIFIED
transactions active True UNSPECIFIED_TRANSACTION_ROW
product_movements active True Product
customers active True DearCustomer
suppliers active True SupplierModel
locations active True Location
carriers active True Carrier
finished_goods active True FinishedGoods
disassemblies active True Disassembly
stock_transfers active True StockTransfer
stock_adjustments active True StockAdjustment

Paginated Data Tools

Collection tools return has_more. Tools that support page numbers accept a 1-based page. Page-number traversal supports random access, but deep pages are less efficient and pages are not a stable snapshot while cache refreshes run. Page-size ceilings reflect row cost: 1,000 for narrow summaries and stock rows, 500 for sale lines and invoice headers, 250 for full harness log messages, and 100 for complete-aggregate report rows. Nested cache collections have separate limits below. Source-batch reports consume source records, not pages of complete aggregate results.

search_cached_objects returns at most 1,000 summary rows per call and defaults to 25. Set sort_by to last_modified or object_uniqueID, and set sort_direction to asc or desc. For orders, you can also sort by sale_order_date; for purchase_orders, use order_date. For sale_credits and sale_credits_stand_alone, use credit_note_date. These business-date sorts use the document's calendar date, not its cache modification time. The default remains last_modified desc; object_uniqueID is always used as the deterministic tie-breaker.

When has_more is true, call the tool again with next_cursor as the cursor argument. Repeat the same object type, filters, entity, and any explicit sorting arguments. Cursors are opaque, signed, and bound to that query and Dear account; clients must not inspect or modify them. Alternatively, provide page for random access. Never provide cursor and page together. get_product_availability supports the same two continuation modes.

get_sale_order_lines and get_additional_attribute_sets use cursors only, not page numbers. Repeat the same query with next_cursor as cursor until has_more=false. Sale-line reads default to 100 lines and allow at most 500 per call. Date-filtered calls examine at most 100 parent sales plus one parent-ID lookahead. Continue even when row_count=0 if a cursor is returned. A sale with more than 500 lines continues from its original line position; duplicate SKUs remain separate lines. Exact line counts are off by default. Attribute discovery defaults to 20 sets and allows at most 100 sets (1,000 labels) per call. If its cached definitions change during traversal, restart discovery without a cursor.

total_count is the exact number of matching rows in the local Dear cache at the time of that call. returned_count is the number in the current page. These counts are not live Cin7 Core totals, and pages are not a stable snapshot while cache refreshes run. Without fields, returned rows are summaries; with fields, they contain identity metadata plus the requested scalar values. Neither response contains a complete cached Dear payload. Fetch dear://catalog/cached-object-search for the machine-readable contract.

For sequential traversal without an exact count, set include_total_count=false on search_cached_objects. Counts and total pages are then null rather than estimates; use has_more and next_cursor to continue. On get_product_availability, set include_totals=false to omit both the matching count and stock totals. These options avoid repeating whole-result calculations on every page. Defaults still include exact metadata.

Sale-transaction page-number traversal has a maximum row offset of 10,000. At 500 rows per page this permits 21 pages (10,500 rows); at the default 100 rows per page it permits 101 pages (10,100 rows). Check pagination_truncated before treating a result as complete: remaining matches beyond the accessible pages are not an empty result. Narrow the filters or use analytics reporting when this limit is reached.

Source-batch reports

Call list_aggregate_reports and use each report's execution_tool and execution_mode. For products_by_status, the preferred tool is run_aggregate_report_batch. Each call selects at most 501 source product records: it consumes at most 500 and uses one for lookahead. Filters apply within that source batch, so a call can scan records but return rows=[]. Batching limits work per call; it does not guarantee that a call cannot time out.

  1. Start without a cursor. Keep the report name, filters and entity unchanged throughout the traversal.
  2. Save each accepted response by batch_id. Count each ID once. If the current batch is retried, replace its saved response instead of adding it again.
  3. Pass next_cursor as cursor while has_more=true, even if rows is empty. An empty batch is not the end of the report.
  4. Merge accepted batches using batch_group_by and batch_sum_fields from discovery. For products_by_status, sum product_count by status. Sort the combined totals only after has_more=false.

Each response contains batch-local counts, not cumulative or complete totals. If traversal stops early, report partial coverage, not a complete total. Retrying an earlier batch requires discarding that batch and all later batches first. Cache changes between calls are accepted; the traversal is not a consistent snapshot.

Report timeout recovery

A database statement timeout returns a structured error with error.code=query_timeout. The failed call contributes no counts and advances no cursor. Follow only the recovery that the error advertises; batching is registered per report, not automatically available for every slow query.

  • If a complete-report error supplies error.fallback, call its tool with its arguments. Discard all previous complete-report pages and start the batch traversal without a cursor. Do not combine complete-report rows with batch counts or retry the unchanged complete query.
  • If a complete-report error supplies no fallback, narrow the supported filters or seek support. Do not invent a paging method or repeatedly retry the same request. State when narrower filters change the requested report scope.
  • If a batch times out, use error.retry.tool and error.retry.arguments to retry that input cursor once. Keep earlier accepted batches. If the retry also times out, stop and seek support; do not advance the cursor or count either failed call.

Purchase receipts and dates

Discover purchase_orders with get_object_type_schema, then request both StockReceived.Lines and PutAway.Lines through include_nested_collections. Receipt representation depends on purchase type and Cin7 Core's Use put away setting. Advanced Purchases can separate receiving from put-away. PutAway.Lines can contain receipt data when StockReceived.Lines is empty, including for Simple Purchases. Do not infer the configuration or absence of receipts from one empty collection, and do not add both stages as independent deliveries.

Inspect line Received, parent task Status, and PO status. A task status alone does not prove receipt: Received=true identifies received lines, and a task can remain DRAFT while put-away is pending. Line Date is the raw recorded receipt date, not an invoice date or proof of when put-away was authorised. Report the source stage and missing dates. Verify the stage's meaning for the workflow before calculating lead time. PO order_date_from/to filters select OrderDate, not receipt dates. A partial receipt does not prove on-time-in-full delivery.

Expanded searches allow at most 25 parent documents and return at most 100 source slots per requested collection per parent per call. Check source_state, source_complete, invalid counts and unavailable_branch_counts; missing or invalid data is not zero. Source completeness describes structure, not freshness or complete pagination. Before advancing the outer cursor, finish each parent's nested pages: select that parent by object_uniqueID, request only the unfinished collection, and pass its next_offset as nested_collection_offset. The maximum offset is 10,000; at a limit of 100, capacity is 101 pages and 10,100 source slots per parent collection. Check pagination_truncated and matches_remain before reporting complete coverage.

Schema Discovery

The GrowthPath App Server stores cached Dear JSON documents in PostgreSQL. These tools support searching nested JSON fields without requiring the assistant to retrieve every complete document.

TypedDict resources are split into compact human-readable field lists and full JSON Schema resources. Use the compact dear://typed-dict/{typed_dict_name} resource first, then fetch dear://typed-dict/{typed_dict_name}/json-schema when a client needs required fields, nested object definitions, literals, unions, array item schemas, or descriptions. TypedDict class docstrings become object descriptions. Field descriptions are published when the annotation uses structured Annotated string metadata; ordinary source comments are not parsed.

Before supplying fields to get_recent_sales or search_cached_objects, call get_object_type_schema and use the exact, case-sensitive paths from field_projection.selectable_fields. A request may select 1 to 20 scalar paths. Whole objects, paths through arrays, and fields outside the MCP disclosure allowlist remain unavailable through field projection; use a registered nested collection or dedicated collection tool instead.

For get_sale_order_lines, call get_object_type_schema with object_type=orders and select from sale_order_lines.selectable_fields. Default line fields are ProductID, SKU and Quantity. Select ProductCustomField1 through ProductCustomField10 explicitly when needed. Their labels depend on each product's attribute set; a slot number alone does not identify its business meaning. Use include_attribute_metadata=true to resolve current cached product assignments. These definitions are not historical label snapshots, and attribute metadata does not make product or customer master attributes bulk-selectable.

The search_cached_objects tool also accepts bounded PostgreSQL JSONB filters through the reserved jsonb_filters key. Fetch dear://catalog/jsonb-search for the supported operators and examples, then use the object-type and JSON Schema resources to choose valid nested payload paths.

Allowlisted Harnesses

A harness is a pre-approved diagnostic script exposed through the MCP server as a controlled job. Harnesses are used for narrow evidence collection workflows that are too specific for a generic read-only tool but still need guardrails, audit logs, and namespace scoping.

Only harnesses listed for the current namespace can be invoked. Each run is validated against the registry, records JobLog output, and executes on the configured target rather than giving the MCP client arbitrary shell access. Harnesses documented here should remain read-only or dry-run only.

The transaction validator accepts a month from 1 to 12, a year from 1 to 9999 (excluding December 9999), and a sample_limit from 1 to 100. Logs retain at most 8 KiB of source bytes per line and the first 1 MiB per run; truncation markers are additional. Raw-payload differences are represented by hashes, not payload contents. Output limits do not change the underlying comparison results.

Harness Safety Class Execution Target Description
cached_transactions_validator read_only local_app_process Validate cached transactions against the live Dear transactions API for a date window.

Example MCP Usage

The User prompt column shows text a user might type into an MCP-enabled assistant. The Expected MCP server behavior column explains which MCP tool the assistant should call and the structured arguments it should send to this server.

Quick Investigation, Not Full Reporting

This MCP server is designed for safe, read-only investigation of cached Cin7/Dear data. It is useful for recent sales, targeted order/product/customer lookups, stock checks, and support diagnostics.

For broad ranking questions such as "top ten selling SKUs" or "most important products by stock value", use an allowlisted aggregate report when one is available. Aggregate reports run fixed, read-only server-side queries over the configured cache scope. Complete-aggregate reports return capped result pages and cache successful results briefly. Source-batch reports return partial aggregates that clients must merge. Both use a short database statement timeout and the configured read-only cache database connection when available. Use the execution tool returned by discovery. These reports avoid fetching individual full records to answer summary questions.

Generic cache-search answers should still state their scope, for example "based on the 50 most recent cached sales" or "based on all 1,767 matching cached product summaries across 18 pages." Pagination can enumerate all matching cached summaries, but it does not provide a stable cache snapshot or complete Dear payloads. For complete reporting workflows, trend analysis, or cross-object analytics beyond the allowlisted aggregate reports, use GrowthPath's analytics reporting module, which is backed by a reporting-optimized database and supports natural-language analytics queries.

Aggregate Reports

Use list_aggregate_reports to discover the enabled sale, customer, and product aggregate reports for the current namespace. Use the returned execution_tool. For run_aggregate_report, supply a report name, optional filters and entity, and limit from 1 to 100. For run_aggregate_report_batch, supply the report name, optional filters and entity, then follow next_cursor; there is no client-selected batch limit or page number. Follow the batch merge rules and timeout recovery instructions.

The examples below use <entity> as a placeholder. Replace it with a Dear instance/entity configured for this deployment. If an example elsewhere uses orbitkey, treat it as the same kind of placeholder rather than a value for every deployment. Omit entity when only one Dear instance is exposed. Names, SKUs, labels and dates below are examples; replace them with the requested values. Discover accepted object types and filters before searching.

Current deployment reference values:

  • Namespace statusanxiety; Dear instance/entity values: statusanxiety_2023
User prompt Expected MCP server behavior
What Dear instances are available? Call list_dear_instances with no arguments.
Which cached object types can I search? Call list_queryable_object_types with no arguments. Use the returned standard_filter_keys and jsonb_filter_key; unsupported filter or sort keys are rejected rather than ignored.
List every cached product summary in a deterministic order. Call search_cached_objects with object_type=products, empty filters, sort_by=object_uniqueID, and sort_direction=asc. Continue with each next_cursor until has_more=false; do not combine all pages into model context when a server-side report would answer the question.
Show me the ten most recent sales. Call get_recent_sales with sort_by=SaleOrderDateDesc and limit=10. Include entity=<entity> only when this deployment exposes multiple Dear instances. Do not call get_sale_transactions unless the user specifically asks for accounting transaction lines.
Find September 2026 sales for customers whose names contain "Acme", newest first. Call search_cached_objects with object_type=orders, filters={"customer_contains":"Acme","sale_order_date_from":"2026-09-01","sale_order_date_to":"2026-09-30"}, sort_by=sale_order_date, sort_direction=desc, limit=25, and include_total_count=false. Dates are inclusive sale-calendar dates, not invoice dates. Continue with next_cursor. Name matching is a literal, case-insensitive substring; % and _ are not wildcards. The existing customer filter remains an exact match.
Find September 2026 purchase orders for suppliers whose names contain "Acme", oldest first. Call search_cached_objects with object_type=purchase_orders, filters={"supplier_contains":"Acme","order_date_from":"2026-09-01","order_date_to":"2026-09-30"}, sort_by=order_date, sort_direction=asc, limit=25, and include_total_count=false. These are inclusive purchase-order calendar dates. Continue with next_cursor; supplier remains an exact-match filter.
Find customers whose names contain "Acme". Call search_cached_objects with object_type=customers, filters={"name_contains":"Acme"}, limit=25, and include_total_count=false. Continue with next_cursor. This is a literal, case-insensitive substring search; name remains an exact-match filter.
Which product custom field describes "material"? Call get_additional_attribute_sets with object_type=products, label_contains=material, and limit=20. Follow next_cursor while has_more=true. Inspect cache status, freshness, and invalid or ambiguous definition counts before claiming a label is absent. A missing cache does not prove that no sets exist. A matching definition does not prove that a product uses that set. If the business term or product/customer meaning is unclear, ask before selecting a field.
Show the custom-field labels and values for product SKU-001 or customer Acme. For the product, call get_cached_product with sku=SKU-001 and include_attribute_metadata=true. For the customer, call get_cached_customer with customer_name_or_guid=Acme and include_attribute_metadata=true. Use the record's resolved set definition to interpret its AdditionalAttribute1 through AdditionalAttribute10 values. Report unresolved assignments instead of guessing labels. Metadata uses current cached definitions, not historical labels; raw payload values stay unchanged.
Show SKUs and quantities on all September 2026 sale-order lines. First call get_object_type_schema with object_type=orders and check sale_order_lines.selectable_fields. Then call get_sale_order_lines with sale_order_date_from=2026-09-01, sale_order_date_to=2026-09-30, fields=["SKU","Quantity"], and limit=100. Repeat with each next_cursor, even after an empty page, until has_more=false. Preserve sale_id and line_index; repeated SKUs are separate order lines. These are cached order lines, not accounting transactions or invoiced revenue.
Include the product "material" custom field on September 2026 sale-order lines. Discover labels with get_additional_attribute_sets and approved line fields with get_object_type_schema for orders. If a definition maps "material" to ProductCustomField3, call get_sale_order_lines with sale_order_date_from=2026-09-01, sale_order_date_to=2026-09-30, fields=["ProductID","SKU","Quantity","ProductCustomField3"], limit=100, and include_attribute_metadata=true. Interpret each line only with its resolved product set; the same slot can mean something else in another set. Select other approved slots if needed. Follow next_cursor even after an empty page. Values come from cached sale lines, not current product master values; labels come from current cached definitions, not historical snapshots.
What quantities were received for PO-001, and on which dates? First discover purchase_orders with get_object_type_schema. Then call search_cached_objects with these example arguments:
{
  "object_type": "purchase_orders",
  "filters": {"order_number": "PO-001"},
  "fields": ["OrderNumber", "Supplier", "Type", "Status"],
  "include_nested_collections": ["StockReceived.Lines", "PutAway.Lines"],
  "limit": 1,
  "nested_collection_limit": 100,
  "include_total_count": false
}
Read each line's values for SKU, Quantity, Received and Date, and its parent for task context. Keep source positions and separate receipts for repeated SKUs. Follow outer and nested continuation before claiming complete coverage. Apply the receipt interpretation rules; do not add both stages together.
How many products have each status? Call list_aggregate_reports. For products_by_status, use its declared execution_tool=run_aggregate_report_batch. Start with {"report_name":"products_by_status","filters":{}} and omit the cursor. Repeat with each returned next_cursor as cursor, keeping the same filters and entity. Save one response per batch_id and sum product_count by status across those responses. Continue after rows=[] while has_more=true. Only after has_more=false are the combined counts complete for this traversal. Cache refreshes can change records between calls; this is not a consistent snapshot.
The complete products-by-status report timed out. Can you still obtain the counts? Inspect the structured query_timeout error. When error.fallback advertises run_aggregate_report_batch, discard any previous complete-report pages and call the supplied tool and arguments without a cursor. Complete and merge the batches as above. If a batch times out, retry using error.retry once without advancing. If that retry times out, stop and report partial coverage. Other reports may have no registered fallback; follow the advertised recovery only.
Show invoices dated October 2026, including invoices on older orders. Call get_sale_invoices with {"invoice_date_from":"2026-10-01","invoice_date_to":"2026-10-31","limit":100}. Follow next_cursor with the same arguments, even after an empty page, until no cursor remains. These dates select InvoiceDate, not SaleOrderDate. Default invoice statuses are AUTHORISED, PAID and PARTIALLY PAID. Split longer periods into non-overlapping windows of at most 31 inclusive days, with no gaps. For line detail, use get_cached_sale_collection with collection=invoice_lines and follow its pagination. Amounts stay in document currency; header totals are not per-account revenue amounts.
Show authorised credits dated October 2026 with their header amounts. Discover the fields and filters for sale_credits and sale_credits_stand_alone. Call search_cached_objects for each type, starting with these arguments for sale_credits:
{
  "object_type": "sale_credits",
  "filters": {
    "status": "AUTHORISED",
    "credit_note_date_from": "2026-10-01",
    "credit_note_date_to": "2026-10-31"
  },
  "sort_by": "credit_note_date",
  "sort_direction": "asc",
  "include_credit_header_amounts": true,
  "include_total_count": false,
  "limit": 100
}
Follow all cursors for both types. Use credit_header_amounts.values only when its status=resolved, instead of adding them to raw totals. Check unresolved_count before reporting a complete amount. Do not also count embedded sale credits. For net sales, subtract each authorised credit once from invoices in the same currency. Do not sum different currencies. Use Analytics for recurring revenue aggregates and currency conversion. Date bounds are inclusive calendar dates; do not shift them between time zones or use JSONB contains to match date prefixes.
What are the ten most important active products by stock on hand value? Call run_aggregate_report with entity=<entity>, report_name=top_active_products_by_stock_value, filters={}, and limit=10.
What are the top ten selling SKUs? Call run_aggregate_report with entity=<entity>, report_name=top_selling_skus, filters={}, and limit=10. This ranks quantities on cached sales-order lines, not invoiced revenue. cache_modified_since and cache_modified_until filter cache modification timestamps, not order or invoice dates. For sales within a particular reporting period, use GrowthPath's analytics reporting module.