# MCP tools

> Every tool on the TradeCatalog MCP server, its inputs, who can use it and what it returns.

The server has six tools. All are read-only (`readOnlyHint: true`) and only touch TradeCatalog (`openWorldHint: false`). Results come back as JSON text, with prices already formatted as money, like `£15.73`.

Most tools take a `workspace`: the workspace address from `list_workspaces`, like `northgate`. The AI app normally calls `list_workspaces` first on its own.

When a tool can’t do something, for example you aren’t staff at that workspace or the customer doesn’t exist, it returns an error message the AI app can read and act on, like “No customer "OAK99". Use list_customers for account codes.”

## list_workspaces

Supplier workspaces you work in, and trade portals where you buy. Start here.

**Who:** anyone signed in. **Inputs:** none.

```json
{
  "supplierWorkspaces": [
    { "workspace": "northgate", "name": "Northgate Fixings", "role": "owner" }
  ],
  "tradePortals": [
    {
      "workspace": "hartley-timber",
      "supplier": "Hartley Timber",
      "yourAccount": "Northgate Fixings"
    }
  ]
}
```

## search_products

Search a catalogue by SKU, manufacturer reference, name, brand or category. Returns up to **25** products.

**Who:** staff and buyers.

| Input       | Type   | Required | Description                                                                                                        |
| ----------- | ------ | -------- | ------------------------------------------------------------------------------------------------------------------ |
| `workspace` | string | yes      | Workspace address.                                                                                                 |
| `query`     | string | yes      | What to search for. Empty lists products by name.                                                                  |
| `customer`  | string | no       | Staff only: a customer’s account code or name, to see their prices and only what they can see. Ignored for buyers. |

- **Buyers** always see their own account’s prices and only active products they can see.
- **Staff** see list prices and every product, or a named customer’s view.

```json
{
  "supplier": "Northgate Fixings",
  "pricesFor": "Oakfield Joinery",
  "taxNote": "ex VAT",
  "products": [
    {
      "sku": "HX-8510",
      "name": "Hex bolt M10 x 50 zinc",
      "unit": "Box of 100",
      "availability": "in_stock",
      "price": "£15.73",
      "listPrice": "£18.50",
      "why": "Brand discount −15%"
    }
  ]
}
```

Try: “Search Northgate for M10 hex bolts at Oakfield’s prices.”

## check_price

What a customer pays for a SKU at a quantity, and which rule set the price.

**Who:** staff only.

| Input       | Type    | Required | Description                |
| ----------- | ------- | -------- | -------------------------- |
| `workspace` | string  | yes      | Workspace address.         |
| `customer`  | string  | yes      | Account code or name.      |
| `sku`       | string  | yes      | The SKU.                   |
| `qty`       | integer | no       | 1 to 1,000,000. Default 1. |

```json
{
  "customer": "Oakfield Joinery",
  "sku": "HX-8510",
  "name": "Hex bolt M10 x 50 zinc",
  "qty": 20,
  "unitPrice": "£15.73",
  "lineTotal": "£314.60",
  "listPrice": "£18.50",
  "why": "Brand discount −15%",
  "taxNote": "ex VAT"
}
```

Try: “What does OAK01 pay for 20 of HX-8510, and why?”

## list_customers

Trade customers with account codes, contact emails, active status and account discount.

**Who:** staff only. **Inputs:** `workspace`.

```json
[
  {
    "accountCode": "OAK01",
    "name": "Oakfield Joinery",
    "email": "accounts@oakfieldjoinery.co.uk",
    "active": true,
    "discount": "5%"
  }
]
```

Try: “Which customers have no discount set?”

## list_orders

Recent orders, newest first, up to **50**.

**Who:** staff see every customer’s orders; buyers see their own account’s.

| Input       | Type   | Required | Description                                                      |
| ----------- | ------ | -------- | ---------------------------------------------------------------- |
| `workspace` | string | yes      | Workspace address.                                               |
| `status`    | string | no       | `new`, `acknowledged`, `dispatched`, `completed` or `cancelled`. |

```json
[
  {
    "reference": "SO-000142",
    "customer": "Oakfield Joinery",
    "status": "new",
    "total": "£314.60",
    "poNumber": "PO-88231",
    "placed": "2026-09-27T07:48:12.000Z"
  }
]
```

Try: “Any new orders since yesterday? Total them up by customer.”

## recent_activity

The activity log of changes to customers, discounts and prices, newest first, up to **50** entries. Optionally one customer’s history.

**Who:** staff only.

| Input       | Type   | Required | Description           |
| ----------- | ------ | -------- | --------------------- |
| `workspace` | string | yes      | Workspace address.    |
| `customer`  | string | no       | Account code or name. |

```json
[
  {
    "when": "2026-09-26T14:21:03.000Z",
    "who": "Jo Hartley",
    "customer": "Oakfield Joinery",
    "what": "Set Northgate brand discount to 15% (was 12.5%)"
  }
]
```

Try: “Who changed Oakfield’s prices this month?”

## Notes

- Customer names and account codes are matched without regard to case. An exact account code is safest.
- A buyer with several accounts at one supplier sees the first account by name. To check another account, use the trade portal.
- For more than 25 products or 50 orders, or to change anything, use the [REST API](/docs/api).
