Cin7 MCP Server

This MCP server exposes curated Cin7 Core/Dear knowledge plus read-only diagnostic tools for configured Dear instances.

In plain terms, this lets approved AI assistants understand how our Cin7/Dear data is structured, answer safer questions about orders, products, stock, and background jobs, and guide support work without giving broad access to the live system. It is intended to make investigations faster, reduce repeated manual lookup work, and keep access behind clear authentication, scoping, and audit controls. All exposed data access is read-only.

This MCP server prioritizes searching the GrowthPath App Server's cache of JSON documents. That makes it similar to the JSON-centric approach used with the Dear API, but the cache is served by PostgreSQL, and this MCP server understands PostgreSQL's support for searching and working with nested JSON documents. For many investigation tasks, that makes it more powerful than querying the raw Dear API directly. GrowthPath also has a separate analytics reporting module, which is outside the scope of this MCP server and is supported by a state-of-the-art natural language query tool.

MCP Endpoint: https://statusanxiety.growthpath.com.au/mcp-dear
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> for clients that need manual headers; 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/ is this human-readable documentation page. It is not the MCP transport endpoint. 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 path: /.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.

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. MCP requests must send Authorization: Token <token>. 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.

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.

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>
  • 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 the MCP server URL and OAuth. The example screenshot uses the Equipped deployment URL, but for this deployment use https://statusanxiety.growthpath.com.au/mcp-dear.

  • 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.

The example screenshot should show https://equipped.growthpath.com.au/mcp-dear as the server URL, Server URL connection mode, and OAuth authentication.

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, 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.
Documentation questions: if the user is asking how Cin7/Odoo works, how to configure a feature, what a field/status means, or where to find a setting, do not query Dear live/cache data. Route the request to recommended_server="Cin7/Odoo Help Documentation MCP" and recommended_tool="search_cin7_odoo_help_docs" with reason="documentation_question_not_live_data".

Discovery And Schema

Tool Purpose Arguments Returns Side effects and notes
whoami Confirm which Django/OAuth actor the MCP request is running as. None. Actor email and authentication context. None.
list_dear_instances List the Dear/Cin7 Core instances exposed to the current namespace. None. Configured entity names, account IDs, and company summary fields. None.
describe_namespace Describe the runtime namespace and its configured Dear scope. None. Namespace, allowed entities, readable object types, and allowed harnesses. None.
list_entities List Dear entity values that may be passed to scoped tools. None. Entity records for the current namespace. None.
get_object_type_schema Fetch schema and search metadata for one cached object type. object_type. Object-type schema, payload type, lifecycle, and supported search metadata. None.
Call list_queryable_object_types first when choosing object_type values for cache search.
list_queryable_object_types List cached object types that can be searched in this namespace. None. Queryable object types plus accepted standard and JSONB filter keys. None.
describe_workflow Explain a curated Dear operational workflow. workflow_name. Workflow description, guidance, and source-file references. None.

Cached Dear Data

Tool Purpose Arguments Returns Side effects and notes
get_cached_sale Look up one cached sale/order by order number. order_number, optional entity. The matching cached sale payload and scope metadata. None; reads the GrowthPath cache, not the live Dear API.
If the request is a Cin7/Odoo how-to, help, or documentation question rather than a live/cache data question, use search_cin7_odoo_help_docs on the Cin7/Odoo Help Documentation MCP server instead.
get_cached_sale_collection Return one sale sub-collection without returning the full sale payload. order_number, collection, optional entity. Rows from the selected sale collection. None.
Supported collections are transactions, order_lines, payments, and fulfilments. If the request is a Cin7/Odoo how-to, help, or documentation question rather than a live/cache data question, use search_cin7_odoo_help_docs on the Cin7/Odoo Help Documentation MCP server instead.
get_cached_product Look up one cached product by SKU. sku, optional entity. The matching cached product payload and scope metadata. None; reads the GrowthPath cache, not the live Dear API.
If the request is a Cin7/Odoo how-to, help, or documentation question rather than a live/cache data question, use search_cin7_odoo_help_docs on the Cin7/Odoo Help Documentation MCP server instead.
get_cached_customer Look up one cached customer by name or GUID. customer_name_or_guid, optional entity. The matching cached customer payload and scope metadata. None; reads the GrowthPath cache, not the live Dear API.
If the request is a Cin7/Odoo how-to, help, or documentation question rather than a live/cache data question, use search_cin7_odoo_help_docs on the Cin7/Odoo Help Documentation MCP server instead.
get_product_availability Check cached product availability and stock by SKU, product, location, bin, or batch. Optional sku, product_id, location, bin_name, batch, consolidate_bins=true, limit=25, optional entity. Availability rows and totals for the scoped product availability cache. None.
If the request is a Cin7/Odoo how-to, help, or documentation question rather than a live/cache data question, use search_cin7_odoo_help_docs on the Cin7/Odoo Help Documentation MCP server instead.
get_product_movements Return cached product movement rows for one SKU. sku, optional movement_type, optional location, sort_by=DateDesc, limit=20, optional entity. Bounded product movement rows and search metadata. None.
If the request is a Cin7/Odoo how-to, help, or documentation question rather than a live/cache data question, use search_cin7_odoo_help_docs on the Cin7/Odoo Help Documentation MCP server instead.
get_recent_sales Return recent cached sale/order summaries newest-first by SaleOrderDate. Optional statuses, sale_order_date_from, sale_order_date_to, sort_by=SaleOrderDateDesc, limit=25, optional entity. Bounded sale summary rows with order number, sale date, customer, status, and cache timestamp. None.
Use this for prompts like 'most recent sales' or 'latest orders'. For stuck/status exception queues, use search_cached_objects. If the request is a Cin7/Odoo how-to, help, or documentation question rather than a live/cache data question, use search_cin7_odoo_help_docs on the Cin7/Odoo Help Documentation MCP server instead.
get_sale_transactions Return flattened accounting transaction lines for cached sales in a bounded date range. sale_order_date_from, sale_order_date_to, optional statuses, sort_by=SaleOrderDate, limit=100, optional entity. Bounded transaction-line rows for cached sales. None.
Do not use this for recent sale/order lists; use get_recent_sales instead. If the request is a Cin7/Odoo how-to, help, or documentation question rather than a live/cache data question, use search_cin7_odoo_help_docs on the Cin7/Odoo Help Documentation MCP server instead.
search_cached_objects Search allowlisted cached Dear objects with standard filters and bounded JSONB filters. object_type, filters, limit=25, optional entity. Matching cached object rows and search metadata. None.
Unsupported filters are rejected rather than ignored. Use this for exact status queues, stuck orders, object cleanup, and filtered cached object searches. If the request is a Cin7/Odoo how-to, help, or documentation question rather than a live/cache data question, use search_cin7_odoo_help_docs on the Cin7/Odoo Help Documentation MCP server instead.

Aggregate Reports

Tool Purpose Arguments Returns Side effects and notes
list_aggregate_reports List allowlisted grouped or ranked reports. None. Report names, domains, descriptions, required object types, and supported filters. None.
run_aggregate_report Run an allowlisted grouped or ranked read-only summary report. report_name, optional filters, limit=10, optional entity. Capped aggregate rows and report metadata. None; successful results may be briefly cached server-side.
Reports do not return individual order rows. If the request is a Cin7/Odoo how-to, help, or documentation question rather than a live/cache data question, use search_cin7_odoo_help_docs on the Cin7/Odoo Help Documentation MCP server instead.

Job Logs And Diagnostics

Tool Purpose Arguments Returns Side effects and notes
query_job_logs Search summarized GrowthPath JobLog records for support diagnostics. Optional entity, job_id, title_pattern, statuses, limit=50. Matching job-log summaries and count metadata. None.
If the request is a Cin7/Odoo how-to, help, or documentation question rather than a live/cache data question, use search_cin7_odoo_help_docs on the Cin7/Odoo Help Documentation MCP server instead.

Harnesses

Tool Purpose Arguments Returns Side effects and notes
list_harnesses List diagnostic harnesses allowed for the current namespace. Optional entity. Harness names, safety classes, execution targets, and argument specs. None.
get_harness_spec Fetch the full specification for one diagnostic harness. harness_name. Harness description, safety class, target, allowed scope, and arguments. None.
run_harness Start a controlled, allowlisted diagnostic harness run. harness_name, args, dry_run=true, optional entity. Run ID, validation result, job metadata, and launch status. Creates JobLog audit records and executes the allowlisted harness target.
Harnesses documented for this server should remain read-only or dry-run only.
get_harness_run_status Check completion state for a previous harness run. run_id, optional entity. Run status, timestamps, and job metadata. None.
get_harness_run_logs Fetch logs emitted by a previous harness run. run_id, limit=100, optional entity. Bounded log messages for the harness JobLog. None.

Planning-Only Operations

Tool Purpose Arguments Returns Side effects and notes
list_operations List known operational workflows that can be inspected or planned. Optional entity. Operation specs, safety classes, arguments, checks, and execution flags. None.
The current MCP server exposes planning and validation only, not execution.
describe_operation Fetch the full specification for one operation. operation_name. Operation title, safety class, allowed fields, side effects, and required checks. None.
validate_operation Validate operation arguments and entity scope before planning. operation_name, args, entity. Validation result, blockers, normalized args, and execution flags. None.
plan_operation Build a dry-run plan for an allowlisted operation. operation_name, args, entity. Dry-run plan, blockers, warnings, plan hash, required checks, and source files. 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 whether a SKU can be fulfilled. 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 current 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.
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. run_aggregate_report list_aggregate_reports to discover available report names first. Read-only aggregate summary.
Find product data cleanup candidates. search_cached_objects get_cached_product for a selected SKU. Read-only filtered search.
Find purchase orders needing follow-up. search_cached_objects get_object_type_schema for purchase-order filter fields. 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
stock_transfers active True StockTransfer
stock_adjustments active True StockAdjustment

Schema Discovery

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, or array item schemas.

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.

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 and return capped result sets. They also run with a short database statement timeout, use the configured read-only cache database connection when available, and cache successful results briefly so repeated questions cannot monopolize the web pod. They are better for rankings than asking an MCP client to fetch many individual records and aggregate them itself.

Generic cache-search answers should still state their scope, for example "based on the 50 most recent cached sales" or "based on 100 active cached products." 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 run_aggregate_report with entity=<entity>, a report name, optional filters, and a bounded limit to run one of those reports.

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.

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.
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.
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. If the user needs a date-limited answer, include cache_modified_since or cache_modified_until in the filters.