Safefood 360 MCP by usefulapi
Read Safefood 360 documents, complaints, suppliers, materials; create complaints, update documents.
사용해야 할까요
품질 및 안전성
발견 사항 (3)
- LOWsafefood360_list_document_reviews에서
- LOWsafefood360_get_document_review에서
- LOWsafefood360_get_batching_record에서
도구 정의와 프로토콜 준수에 대한 자동 분석을 기반으로 합니다.
컨텍스트 비용
이는 서버의 도구가 모델의 컨텍스트에 로드될 때마다 소비되는 대략적인 토큰 수입니다. 수치가 높을수록 다른 작업에 사용할 수 있는 주의가 줄어듭니다.
설치
원클릭 설치
`claude_desktop_config.json` 파일에 다음을 추가하세요:
{
"mcpServers": {
"safefood-360": {
"url": "https://safefood-360.usefulapi.io/mcp"
}
}
}원격 엔드포인트
https://safefood-360.usefulapi.io/mcpstreamable-http할 수 있는 일
도구 목록
도구 (17)
🟢safefood360_list_documents(filter, orderby, top, skip, count)
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/.
입력 스키마
{
"type": "object",
"properties": {
"filter": {
"description": "OData $filter, e.g. \"date ge 2026-01-01T00:00:00Z\" (comparison, logical and string operators).",
"type": "string",
"maxLength": 1000
},
"orderby": {
"description": "OData $orderby, e.g. \"date desc,name asc\".",
"type": "string",
"maxLength": 300
},
"top": {
"description": "Records per page, 1-1000 (the vendor default is 100).",
"type": "integer",
"minimum": 1,
"maximum": 1000
},
"skip": {
"description": "Records to skip (offset). Pass the previous reply's next_skip.",
"type": "integer",
"minimum": 0,
"maximum": 1000000
},
"count": {
"description": "Include the total count of matching records in the reply.",
"type": "boolean"
}
},
"$schema": "https://json-schema.org/draft/2020-12/schema"
}🟢safefood360_get_document(identifier)
One controlled document by its identifier: title, description, version, folder, responsible person and workflow. GET /documents/sites/{siteId}/v1/documents/{identifier}.
입력 스키마
{
"type": "object",
"properties": {
"identifier": {
"type": "string",
"minLength": 1,
"maxLength": 200,
"description": "Document identifier (as shown in Safefood 360)."
}
},
"required": [
"identifier"
],
"$schema": "https://json-schema.org/draft/2020-12/schema"
}🟢safefood360_list_document_reviews(filter, orderby, top, skip, count)
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/.
입력 스키마
{
"type": "object",
"properties": {
"filter": {
"description": "OData $filter, e.g. \"date ge 2026-01-01T00:00:00Z\" (comparison, logical and string operators).",
"type": "string",
"maxLength": 1000
},
"orderby": {
"description": "OData $orderby, e.g. \"date desc,name asc\".",
"type": "string",
"maxLength": 300
},
"top": {
"description": "Records per page, 1-1000 (the vendor default is 100).",
"type": "integer",
"minimum": 1,
"maximum": 1000
},
"skip": {
"description": "Records to skip (offset). Pass the previous reply's next_skip.",
"type": "integer",
"minimum": 0,
"maximum": 1000000
},
"count": {
"description": "Include the total count of matching records in the reply.",
"type": "boolean"
}
},
"$schema": "https://json-schema.org/draft/2020-12/schema"
}🟢safefood360_get_document_review(review_no)
One document review by its review number. GET /documents/sites/{siteId}/v1/documentreviews/{no}.
입력 스키마
{
"type": "object",
"properties": {
"review_no": {
"type": "string",
"minLength": 1,
"maxLength": 200,
"description": "Document review number."
}
},
"required": [
"review_no"
],
"$schema": "https://json-schema.org/draft/2020-12/schema"
}🟢safefood360_list_complaints(filter, orderby, top, skip, count)
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.
입력 스키마
{
"type": "object",
"properties": {
"filter": {
"description": "OData $filter, e.g. \"date ge 2026-01-01T00:00:00Z\" (comparison, logical and string operators).",
"type": "string",
"maxLength": 1000
},
"orderby": {
"description": "OData $orderby, e.g. \"date desc,name asc\".",
"type": "string",
"maxLength": 300
},
"top": {
"description": "Records per page, 1-1000 (the vendor default is 100).",
"type": "integer",
"minimum": 1,
"maximum": 1000
},
"skip": {
"description": "Records to skip (offset). Pass the previous reply's next_skip.",
"type": "integer",
"minimum": 0,
"maximum": 1000000
},
"count": {
"description": "Include the total count of matching records in the reply.",
"type": "boolean"
}
},
"$schema": "https://json-schema.org/draft/2020-12/schema"
}🟢safefood360_get_complaint(complaint_id)
One complaint by its id (GUID). GET /complaints/sites/{siteId}/v1/complaints/{id}.
입력 스키마
{
"type": "object",
"properties": {
"complaint_id": {
"type": "string",
"pattern": "^[0-9a-fA-F-]{36}$",
"description": "Complaint id (GUID), e.g. from safefood360_list_complaints."
}
},
"required": [
"complaint_id"
],
"$schema": "https://json-schema.org/draft/2020-12/schema"
}🟢safefood360_list_suppliers(start_index, limit, is_archived, sort, order)
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=.
입력 스키마
{
"type": "object",
"properties": {
"start_index": {
"description": "Index of the first record (default 0). Pass the previous reply's next_start_index.",
"type": "integer",
"minimum": 0,
"maximum": 1000000
},
"limit": {
"description": "Records per page, 1-100 (default 30).",
"type": "integer",
"minimum": 1,
"maximum": 100
},
"is_archived": {
"description": "true = archived records, false = active records (default: the vendor's default).",
"type": "boolean"
},
"sort": {
"description": "Field to sort by.",
"type": "string",
"maxLength": 100
},
"order": {
"description": "Sort direction.",
"type": "string",
"enum": [
"asc",
"desc"
]
}
},
"$schema": "https://json-schema.org/draft/2020-12/schema"
}🟢safefood360_get_supplier(external_id)
One supplier by its external id. GET /v1/suppliers/{externalId}?siteId=.
입력 스키마
{
"type": "object",
"properties": {
"external_id": {
"type": "string",
"minLength": 1,
"maxLength": 200,
"description": "Supplier external id."
}
},
"required": [
"external_id"
],
"$schema": "https://json-schema.org/draft/2020-12/schema"
}🟢safefood360_list_materials(start_index, limit, is_archived, sort, order)
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=.
입력 스키마
{
"type": "object",
"properties": {
"start_index": {
"description": "Index of the first record (default 0). Pass the previous reply's next_start_index.",
"type": "integer",
"minimum": 0,
"maximum": 1000000
},
"limit": {
"description": "Records per page, 1-100 (default 30).",
"type": "integer",
"minimum": 1,
"maximum": 100
},
"is_archived": {
"description": "true = archived records, false = active records (default: the vendor's default).",
"type": "boolean"
},
"sort": {
"description": "Field to sort by.",
"type": "string",
"maxLength": 100
},
"order": {
"description": "Sort direction.",
"type": "string",
"enum": [
"asc",
"desc"
]
}
},
"$schema": "https://json-schema.org/draft/2020-12/schema"
}🟢safefood360_get_material(external_id)
One material by its external id. GET /v1/materials/{externalId}?siteId=.
입력 스키마
{
"type": "object",
"properties": {
"external_id": {
"type": "string",
"minLength": 1,
"maxLength": 200,
"description": "Material external id."
}
},
"required": [
"external_id"
],
"$schema": "https://json-schema.org/draft/2020-12/schema"
}🟢safefood360_get_customer(identifier)
One customer by its identifier (name, addresses, phone, notes). The vendor offers no customer list. GET /customers/sites/{siteId}/v1/customers/{identifier}.
입력 스키마
{
"type": "object",
"properties": {
"identifier": {
"type": "string",
"minLength": 1,
"maxLength": 200,
"description": "Customer identifier."
}
},
"required": [
"identifier"
],
"$schema": "https://json-schema.org/draft/2020-12/schema"
}🟢safefood360_get_employee(identifier)
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}.
입력 스키마
{
"type": "object",
"properties": {
"identifier": {
"type": "string",
"minLength": 1,
"maxLength": 200,
"description": "Employee identifier."
}
},
"required": [
"identifier"
],
"$schema": "https://json-schema.org/draft/2020-12/schema"
}🟢safefood360_get_final_product(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}.
입력 스키마
{
"type": "object",
"properties": {
"identifier": {
"type": "string",
"minLength": 1,
"maxLength": 200,
"description": "Final product identifier."
}
},
"required": [
"identifier"
],
"$schema": "https://json-schema.org/draft/2020-12/schema"
}🟢safefood360_get_batching_record(record_id)
One batching (traceability) record by its id (GUID). GET /batching/sites/{siteId}/v1/batching/records/{recordId}.
입력 스키마
{
"type": "object",
"properties": {
"record_id": {
"type": "string",
"pattern": "^[0-9a-fA-F-]{36}$",
"description": "Batching record id (GUID)."
}
},
"required": [
"record_id"
],
"$schema": "https://json-schema.org/draft/2020-12/schema"
}🔴safefood360_update_document(identifier, title, description, folder)
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}.
입력 스키마
{
"type": "object",
"properties": {
"identifier": {
"type": "string",
"minLength": 1,
"maxLength": 200,
"description": "Document identifier."
},
"title": {
"description": "New title.",
"type": "string",
"minLength": 1,
"maxLength": 500
},
"description": {
"description": "New description.",
"type": "string",
"maxLength": 5000
},
"folder": {
"description": "Folder to move the document to.",
"type": "string",
"minLength": 1,
"maxLength": 500
}
},
"required": [
"identifier"
],
"$schema": "https://json-schema.org/draft/2020-12/schema"
}🔴safefood360_update_customer(identifier, name, phone, mobile, notes)
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}.
입력 스키마
{
"type": "object",
"properties": {
"identifier": {
"type": "string",
"minLength": 1,
"maxLength": 200,
"description": "Customer identifier."
},
"name": {
"description": "New customer name.",
"type": "string",
"minLength": 1,
"maxLength": 300
},
"phone": {
"description": "New phone number.",
"type": "string",
"maxLength": 60
},
"mobile": {
"description": "New mobile number.",
"type": "string",
"maxLength": 60
},
"notes": {
"description": "New notes (replaces the existing notes).",
"type": "string",
"maxLength": 5000
}
},
"required": [
"identifier"
],
"$schema": "https://json-schema.org/draft/2020-12/schema"
}🟡safefood360_create_complaint(description, date, risk, recorded_by, company_id, ...)
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/.
입력 스키마
{
"type": "object",
"properties": {
"description": {
"type": "string",
"minLength": 1,
"maxLength": 5000,
"description": "What the complaint is about."
},
"date": {
"description": "When the complaint was received, ISO 8601, e.g. 2026-10-20T09:30:00Z.",
"type": "string",
"maxLength": 40
},
"risk": {
"description": "Risk level as named in Safefood 360, e.g. None, Low, Medium, High.",
"type": "string",
"maxLength": 50
},
"recorded_by": {
"type": "string",
"pattern": "^[0-9a-fA-F-]{36}$",
"description": "User id (GUID) of the person recording the complaint."
},
"company_id": {
"type": "string",
"pattern": "^[0-9a-fA-F-]{36}$",
"description": "Customer/company id (GUID) the complaint is about."
},
"source": {
"type": "string",
"pattern": "^[0-9a-fA-F-]{36}$",
"description": "Complaint source id (GUID) from the site's list of sources."
},
"source_details": {
"description": "Free-text details of the source.",
"type": "string",
"maxLength": 1000
},
"reference": {
"description": "The complainant's own reference.",
"type": "string",
"maxLength": 200
},
"sample_details": {
"description": "Sample request and collection details.",
"type": "string",
"maxLength": 2000
},
"contact_person": {
"description": "The complainant.",
"type": "object",
"properties": {
"title": {
"type": "string",
"maxLength": 50
},
"first_name": {
"type": "string",
"maxLength": 100
},
"last_name": {
"type": "string",
"maxLength": 100
},
"address": {
"type": "string",
"maxLength": 500
},
"purchased": {
"description": "Where the product was purchased.",
"type": "string",
"maxLength": 200
},
"phone": {
"type": "string",
"maxLength": 60
},
"mobile": {
"type": "string",
"maxLength": 60
},
"email": {
"type": "string",
"maxLength": 254
}
}
},
"product_id": {
"type": "string",
"pattern": "^[0-9a-fA-F-]{36}$",
"description": "Id (GUID) of the product, material or service complained about."
},
"quantity": {
"description": "Quantity affected.",
"type": "integer",
"minimum": 0,
"maximum": 1000000
},
"trace_no": {
"description": "Batch / trace number of the product.",
"type": "string",
"maxLength": 200
}
},
"required": [
"description"
],
"$schema": "https://json-schema.org/draft/2020-12/schema"
}커뮤니티
증거