Read Safefood 360 documents, complaints, suppliers, materials; create complaints, update documents.
Maintain this server? Claim it
Call this server's tools from your browser. Nothing to install.
Requests go through mcptry because browsers can't call most MCP servers directly. Header values are sent to the server for that request only and are never stored or logged.
Tool list from our last check. Connect live to refresh it.
WRITE: record a NEW complaint in Safefood 360 (it may trigger the site's complaint workflow and notifications). Not idempotent: calling it twice creates two complaints. Safefood 360 validates the fields (ids such as source, company and recorded_by are GUIDs from your site's lists) and rejects a request that lacks required ones. POST /complaints/sites/{siteId}/v1/complaints/.
What the complaint is about.
When the complaint was received, ISO 8601, e.g. 2026-10-20T09:30:00Z.
Risk level as named in Safefood 360, e.g. None, Low, Medium, High.
Complaint source id (GUID) from the site's list of sources.
Quantity affected.
Batch / trace number of the product.
The complainant's own reference.
Customer/company id (GUID) the complaint is about.
Id (GUID) of the product, material or service complained about.
User id (GUID) of the person recording the complaint.
The complainant.
Sample request and collection details.
Free-text details of the source.
This tool isn't marked read-only, so it may change something on the server or in an account you connected.
WRITE: record a NEW complaint in Safefood 360 (it may trigger the site's complaint workflow and notifications). Not idempotent: calling it twice creates two complaints. Safefood 360 validates the fields (ids such as source, company and recorded_by are GUIDs from your site's lists) and rejects a request that lacks required ones. POST /complaints/sites/{siteId}/v1/complaints/.
| Argument | Type | Description |
|---|---|---|
| date | string | When the complaint was received, ISO 8601, e.g. 2026-10-20T09:30:00Z. |
| risk | string | Risk level as named in Safefood 360, e.g. None, Low, Medium, High. |
| source | string | Complaint source id (GUID) from the site's list of sources. |
| quantity | integer | Quantity affected. |
| trace_no | string | Batch / trace number of the product. |
| reference | string | The complainant's own reference. |
| company_id | string | Customer/company id (GUID) the complaint is about. |
| product_id | string | Id (GUID) of the product, material or service complained about. |
| description* | string | What the complaint is about. |
| recorded_by | string | User id (GUID) of the person recording the complaint. |
| contact_person | object | The complainant. |
| sample_details | string | Sample request and collection details. |
| source_details | string | Free-text details of the source. |
{
"type": "object",
"$schema": "https://json-schema.org/draft/2020-12/schema",
"required": [
"description"
],
"properties": {
"date": {
"type": "string",
"maxLength": 40,
"description": "When the complaint was received, ISO 8601, e.g. 2026-10-20T09:30:00Z."
},
"risk": {
"type": "string",
"maxLength": 50,
"description": "Risk level as named in Safefood 360, e.g. None, Low, Medium, High."
},
"source": {
"type": "string",
"pattern": "^[0-9a-fA-F-]{36}$",
"description": "Complaint source id (GUID) from the site's list of sources."
},
"quantity": {
"type": "integer",
"maximum": 1000000,
"minimum": 0,
"description": "Quantity affected."
},
"trace_no": {
"type": "string",
"maxLength": 200,
"description": "Batch / trace number of the product."
},
"reference": {
"type": "string",
"maxLength": 200,
"description": "The complainant's own reference."
},
"company_id": {
"type": "string",
"pattern": "^[0-9a-fA-F-]{36}$",
"description": "Customer/company id (GUID) the complaint is about."
},
"product_id": {
"type": "string",
"pattern": "^[0-9a-fA-F-]{36}$",
"description": "Id (GUID) of the product, material or service complained about."
},
"description": {
"type": "string",
"maxLength": 5000,
"minLength": 1,
"description": "What the complaint is about."
},
"recorded_by": {
"type": "string",
"pattern": "^[0-9a-fA-F-]{36}$",
"description": "User id (GUID) of the person recording the complaint."
},
"contact_person": {
"type": "object",
"properties": {
"email": {
"type": "string",
"maxLength": 254
},
"phone": {
"type": "string",
"maxLength": 60
},
"title": {
"type": "string",
"maxLength": 50
},
"mobile": {
"type": "string",
"maxLength": 60
},
"address": {
"type": "string",
"maxLength": 500
},
"last_name": {
"type": "string",
"maxLength": 100
},
"purchased": {
"type": "string",
"maxLength": 200,
"description": "Where the product was purchased."
},
"first_name": {
"type": "string",
"maxLength": 100
}
},
"description": "The complainant."
},
"sample_details": {
"type": "string",
"maxLength": 2000,
"description": "Sample request and collection details."
},
"source_details": {
"type": "string",
"maxLength": 1000,
"description": "Free-text details of the source."
}
}
}One batching (traceability) record by its id (GUID). GET /batching/sites/{siteId}/v1/batching/records/{recordId}.
| Argument | Type | Description |
|---|---|---|
| record_id* | string | Batching record id (GUID). |
{
"type": "object",
"$schema": "https://json-schema.org/draft/2020-12/schema",
"required": [
"record_id"
],
"properties": {
"record_id": {
"type": "string",
"pattern": "^[0-9a-fA-F-]{36}$",
"description": "Batching record id (GUID)."
}
}
}One complaint by its id (GUID). GET /complaints/sites/{siteId}/v1/complaints/{id}.
| Argument | Type | Description |
|---|---|---|
| complaint_id* | string | Complaint id (GUID), e.g. from safefood360_list_complaints. |
{
"type": "object",
"$schema": "https://json-schema.org/draft/2020-12/schema",
"required": [
"complaint_id"
],
"properties": {
"complaint_id": {
"type": "string",
"pattern": "^[0-9a-fA-F-]{36}$",
"description": "Complaint id (GUID), e.g. from safefood360_list_complaints."
}
}
}One customer by its identifier (name, addresses, phone, notes). The vendor offers no customer list. GET /customers/sites/{siteId}/v1/customers/{identifier}.
| Argument | Type | Description |
|---|---|---|
| identifier* | string | Customer identifier. |
{
"type": "object",
"$schema": "https://json-schema.org/draft/2020-12/schema",
"required": [
"identifier"
],
"properties": {
"identifier": {
"type": "string",
"maxLength": 200,
"minLength": 1,
"description": "Customer identifier."
}
}
}One controlled document by its identifier: title, description, version, folder, responsible person and workflow. GET /documents/sites/{siteId}/v1/documents/{identifier}.
| Argument | Type | Description |
|---|---|---|
| identifier* | string | Document identifier (as shown in Safefood 360). |
{
"type": "object",
"$schema": "https://json-schema.org/draft/2020-12/schema",
"required": [
"identifier"
],
"properties": {
"identifier": {
"type": "string",
"maxLength": 200,
"minLength": 1,
"description": "Document identifier (as shown in Safefood 360)."
}
}
}One document review by its review number. GET /documents/sites/{siteId}/v1/documentreviews/{no}.
| Argument | Type | Description |
|---|---|---|
| review_no* | string | Document review number. |
{
"type": "object",
"$schema": "https://json-schema.org/draft/2020-12/schema",
"required": [
"review_no"
],
"properties": {
"review_no": {
"type": "string",
"maxLength": 200,
"minLength": 1,
"description": "Document review number."
}
}
}One employee record by its identifier (training/HR master data of the site). Contains personal data: use it only for the question asked. The vendor offers no employee list. GET /employees/sites/{siteId}/v1/employees/{identifier}.
| Argument | Type | Description |
|---|---|---|
| identifier* | string | Employee identifier. |
{
"type": "object",
"$schema": "https://json-schema.org/draft/2020-12/schema",
"required": [
"identifier"
],
"properties": {
"identifier": {
"type": "string",
"maxLength": 200,
"minLength": 1,
"description": "Employee identifier."
}
}
}One final (finished) product by its identifier: name, folder, categories, barcode, specifications and the materials it is made of. The vendor offers no final-product list. GET /finalproducts/sites/{siteId}/v1/finalproducts/{identifier}.
| Argument | Type | Description |
|---|---|---|
| identifier* | string | Final product identifier. |
{
"type": "object",
"$schema": "https://json-schema.org/draft/2020-12/schema",
"required": [
"identifier"
],
"properties": {
"identifier": {
"type": "string",
"maxLength": 200,
"minLength": 1,
"description": "Final product identifier."
}
}
}One material by its external id. GET /v1/materials/{externalId}?siteId=.
| Argument | Type | Description |
|---|---|---|
| external_id* | string | Material external id. |
{
"type": "object",
"$schema": "https://json-schema.org/draft/2020-12/schema",
"required": [
"external_id"
],
"properties": {
"external_id": {
"type": "string",
"maxLength": 200,
"minLength": 1,
"description": "Material external id."
}
}
}One supplier by its external id. GET /v1/suppliers/{externalId}?siteId=.
| Argument | Type | Description |
|---|---|---|
| external_id* | string | Supplier external id. |
{
"type": "object",
"$schema": "https://json-schema.org/draft/2020-12/schema",
"required": [
"external_id"
],
"properties": {
"external_id": {
"type": "string",
"maxLength": 200,
"minLength": 1,
"description": "Supplier external id."
}
}
}List customer complaints (number, name, risk, date, company, source, contact person, product/material, description, created/modified). Supports OData $filter, $orderby, $top, $skip and $count. GET /complaints/sites/{siteId}/v1/complaints.
| Argument | Type | Description |
|---|---|---|
| top | integer | Records per page, 1-1000 (the vendor default is 100). |
| skip | integer | Records to skip (offset). Pass the previous reply's next_skip. |
| count | boolean | Include the total count of matching records in the reply. |
| filter | string | OData $filter, e.g. "date ge 2026-01-01T00:00:00Z" (comparison, logical and string operators). |
| orderby | string | OData $orderby, e.g. "date desc,name asc". |
{
"type": "object",
"$schema": "https://json-schema.org/draft/2020-12/schema",
"properties": {
"top": {
"type": "integer",
"maximum": 1000,
"minimum": 1,
"description": "Records per page, 1-1000 (the vendor default is 100)."
},
"skip": {
"type": "integer",
"maximum": 1000000,
"minimum": 0,
"description": "Records to skip (offset). Pass the previous reply's next_skip."
},
"count": {
"type": "boolean",
"description": "Include the total count of matching records in the reply."
},
"filter": {
"type": "string",
"maxLength": 1000,
"description": "OData $filter, e.g. \"date ge 2026-01-01T00:00:00Z\" (comparison, logical and string operators)."
},
"orderby": {
"type": "string",
"maxLength": 300,
"description": "OData $orderby, e.g. \"date desc,name asc\"."
}
}
}List document reviews (the periodic review records of controlled documents). Supports OData $filter, $orderby, $top, $skip and $count; use it to find reviews that are due or overdue. GET /documents/sites/{siteId}/v1/documentreviews/.
| Argument | Type | Description |
|---|---|---|
| top | integer | Records per page, 1-1000 (the vendor default is 100). |
| skip | integer | Records to skip (offset). Pass the previous reply's next_skip. |
| count | boolean | Include the total count of matching records in the reply. |
| filter | string | OData $filter, e.g. "date ge 2026-01-01T00:00:00Z" (comparison, logical and string operators). |
| orderby | string | OData $orderby, e.g. "date desc,name asc". |
{
"type": "object",
"$schema": "https://json-schema.org/draft/2020-12/schema",
"properties": {
"top": {
"type": "integer",
"maximum": 1000,
"minimum": 1,
"description": "Records per page, 1-1000 (the vendor default is 100)."
},
"skip": {
"type": "integer",
"maximum": 1000000,
"minimum": 0,
"description": "Records to skip (offset). Pass the previous reply's next_skip."
},
"count": {
"type": "boolean",
"description": "Include the total count of matching records in the reply."
},
"filter": {
"type": "string",
"maxLength": 1000,
"description": "OData $filter, e.g. \"date ge 2026-01-01T00:00:00Z\" (comparison, logical and string operators)."
},
"orderby": {
"type": "string",
"maxLength": 300,
"description": "OData $orderby, e.g. \"date desc,name asc\"."
}
}
}List controlled documents of the Safefood 360 site (title, description, version, folder, responsible person, review/approval workflow, created/modified). Supports OData $filter, $orderby, $top, $skip and $count. GET /documents/sites/{siteId}/v1/documents/.
| Argument | Type | Description |
|---|---|---|
| top | integer | Records per page, 1-1000 (the vendor default is 100). |
| skip | integer | Records to skip (offset). Pass the previous reply's next_skip. |
| count | boolean | Include the total count of matching records in the reply. |
| filter | string | OData $filter, e.g. "date ge 2026-01-01T00:00:00Z" (comparison, logical and string operators). |
| orderby | string | OData $orderby, e.g. "date desc,name asc". |
{
"type": "object",
"$schema": "https://json-schema.org/draft/2020-12/schema",
"properties": {
"top": {
"type": "integer",
"maximum": 1000,
"minimum": 1,
"description": "Records per page, 1-1000 (the vendor default is 100)."
},
"skip": {
"type": "integer",
"maximum": 1000000,
"minimum": 0,
"description": "Records to skip (offset). Pass the previous reply's next_skip."
},
"count": {
"type": "boolean",
"description": "Include the total count of matching records in the reply."
},
"filter": {
"type": "string",
"maxLength": 1000,
"description": "OData $filter, e.g. \"date ge 2026-01-01T00:00:00Z\" (comparison, logical and string operators)."
},
"orderby": {
"type": "string",
"maxLength": 300,
"description": "OData $orderby, e.g. \"date desc,name asc\"."
}
}
}List materials/ingredients (name, our code, supplier code, description, category, countries of origin, risk, archived flag). Paged with start_index and limit; the reply carries recordCount and next_start_index. GET /v1/materials/?siteId=.
| Argument | Type | Description |
|---|---|---|
| sort | string | Field to sort by. |
| limit | integer | Records per page, 1-100 (default 30). |
| order | string | Sort direction. |
| is_archived | boolean | true = archived records, false = active records (default: the vendor's default). |
| start_index | integer | Index of the first record (default 0). Pass the previous reply's next_start_index. |
{
"type": "object",
"$schema": "https://json-schema.org/draft/2020-12/schema",
"properties": {
"sort": {
"type": "string",
"maxLength": 100,
"description": "Field to sort by."
},
"limit": {
"type": "integer",
"maximum": 100,
"minimum": 1,
"description": "Records per page, 1-100 (default 30)."
},
"order": {
"enum": [
"asc",
"desc"
],
"type": "string",
"description": "Sort direction."
},
"is_archived": {
"type": "boolean",
"description": "true = archived records, false = active records (default: the vendor's default)."
},
"start_index": {
"type": "integer",
"maximum": 1000000,
"minimum": 0,
"description": "Index of the first record (default 0). Pass the previous reply's next_start_index."
}
}
}List suppliers (name, code, addresses, contacts, approval status, risk, establishment numbers). Paged with start_index and limit; the reply carries recordCount and next_start_index. GET /v1/suppliers/?siteId=.
| Argument | Type | Description |
|---|---|---|
| sort | string | Field to sort by. |
| limit | integer | Records per page, 1-100 (default 30). |
| order | string | Sort direction. |
| is_archived | boolean | true = archived records, false = active records (default: the vendor's default). |
| start_index | integer | Index of the first record (default 0). Pass the previous reply's next_start_index. |
{
"type": "object",
"$schema": "https://json-schema.org/draft/2020-12/schema",
"properties": {
"sort": {
"type": "string",
"maxLength": 100,
"description": "Field to sort by."
},
"limit": {
"type": "integer",
"maximum": 100,
"minimum": 1,
"description": "Records per page, 1-100 (default 30)."
},
"order": {
"enum": [
"asc",
"desc"
],
"type": "string",
"description": "Sort direction."
},
"is_archived": {
"type": "boolean",
"description": "true = archived records, false = active records (default: the vendor's default)."
},
"start_index": {
"type": "integer",
"maximum": 1000000,
"minimum": 0,
"description": "Index of the first record (default 0). Pass the previous reply's next_start_index."
}
}
}WRITE: change the name, phone, mobile and/or notes of a customer in Safefood 360 (JSON patch of those fields; others stay as they are). notes REPLACES the existing notes. PATCH /customers/sites/{siteId}/v1/customers/{identifier}.
| Argument | Type | Description |
|---|---|---|
| name | string | New customer name. |
| notes | string | New notes (replaces the existing notes). |
| phone | string | New phone number. |
| mobile | string | New mobile number. |
| identifier* | string | Customer identifier. |
{
"type": "object",
"$schema": "https://json-schema.org/draft/2020-12/schema",
"required": [
"identifier"
],
"properties": {
"name": {
"type": "string",
"maxLength": 300,
"minLength": 1,
"description": "New customer name."
},
"notes": {
"type": "string",
"maxLength": 5000,
"description": "New notes (replaces the existing notes)."
},
"phone": {
"type": "string",
"maxLength": 60,
"description": "New phone number."
},
"mobile": {
"type": "string",
"maxLength": 60,
"description": "New mobile number."
},
"identifier": {
"type": "string",
"maxLength": 200,
"minLength": 1,
"description": "Customer identifier."
}
}
}WRITE: change the title, description and/or folder of a controlled document in Safefood 360 (JSON patch; fields you leave out stay as they are). It does not publish a new version or change the review workflow. Returns the updated document. PATCH /documents/sites/{siteId}/v1/documents/{identifier}.
| Argument | Type | Description |
|---|---|---|
| title | string | New title. |
| folder | string | Folder to move the document to. |
| identifier* | string | Document identifier. |
| description | string | New description. |
{
"type": "object",
"$schema": "https://json-schema.org/draft/2020-12/schema",
"required": [
"identifier"
],
"properties": {
"title": {
"type": "string",
"maxLength": 500,
"minLength": 1,
"description": "New title."
},
"folder": {
"type": "string",
"maxLength": 500,
"minLength": 1,
"description": "Folder to move the document to."
},
"identifier": {
"type": "string",
"maxLength": 200,
"minLength": 1,
"description": "Document identifier."
},
"description": {
"type": "string",
"maxLength": 5000,
"description": "New description."
}
}
}