This commit is contained in:
Your Name committed 2026-06-27 23:59:16 -04:00
1 parent 1c0313495f
commit ac387185e0
15 files changed
+1855 -12

No files matched your search

+190
View File
@@ -486,6 +486,148 @@ server.setRequestHandler(ListToolsRequestSchema, async () => {
required: ["id", "lang"]
}
},
{
name: "list_attribute_definitions",
description: "List attribute definitions, optionally filtered by category. Returns localized labels unless lang=all.",
inputSchema: {
type: "object",
properties: {
categoryId: { type: "number" },
lang: { type: "string", description: "Language code (e.g. th, en, all)" }
}
}
},
{
name: "get_attribute_definition_detail",
description: "Get full detail for one attribute definition, including translations and localized option labels.",
inputSchema: {
type: "object",
properties: {
id: { type: "number" },
lang: { type: "string", description: "Language code (e.g. th, en, all)" }
},
required: ["id"]
}
},
{
name: "create_attribute_definition",
description: "Create a reusable product attribute definition. For SELECT, provide localized options as arrays of language maps.",
inputSchema: {
type: "object",
properties: {
code: { type: "string" },
type: { type: "string", enum: ["TEXT", "NUMBER", "BOOLEAN", "SELECT", "JSON"] },
label: { type: "string", description: "Base Thai or fallback label" },
description: { type: "string" },
unit: { type: "string" },
isRequired: { type: "boolean" },
isFilterable: { type: "boolean" },
sortOrder: { type: "number" },
categoryId: { type: "number" },
translations: {
type: "object",
additionalProperties: {
type: "object",
properties: {
label: { type: "string" },
description: { type: "string" }
}
}
},
options: {
type: "array",
items: {
type: "object",
additionalProperties: { type: "string" }
}
}
},
required: ["code", "type", "label"]
}
},
{
name: "update_attribute_definition",
description: "Update base metadata for an attribute definition.",
inputSchema: {
type: "object",
properties: {
id: { type: "number" },
code: { type: "string" },
type: { type: "string", enum: ["TEXT", "NUMBER", "BOOLEAN", "SELECT", "JSON"] },
label: { type: "string" },
description: { type: "string" },
unit: { type: "string" },
isRequired: { type: "boolean" },
isFilterable: { type: "boolean" },
sortOrder: { type: "number" },
categoryId: { type: "number" },
options: {
type: "array",
items: {
type: "object",
additionalProperties: { type: "string" }
}
}
},
required: ["id", "code", "type", "label"]
}
},
{
name: "update_attribute_definition_translation",
description: "Upsert translated label/description for an attribute definition.",
inputSchema: {
type: "object",
properties: {
id: { type: "number" },
lang: { type: "string" },
label: { type: "string" },
description: { type: "string" }
},
required: ["id", "lang", "label"]
}
},
{
name: "list_product_attributes",
description: "List localized product attributes for a product.",
inputSchema: {
type: "object",
properties: {
productId: { type: "number" },
lang: { type: "string", description: "Language code (e.g. th, en, all)" }
},
required: ["productId"]
}
},
{
name: "set_product_attribute",
description: "Create or update a product attribute base value. Only TEXT attributes support translations separately. SELECT values must match the base Thai option value.",
inputSchema: {
type: "object",
properties: {
productId: { type: "number" },
attributeDefinitionId: { type: "number" },
valueText: { type: "string" },
valueNumber: { type: "number" },
valueBoolean: { type: "boolean" },
valueJson: { type: "object" }
},
required: ["productId", "attributeDefinitionId"]
}
},
{
name: "update_product_attribute_translation",
description: "Upsert translated valueText for a TEXT product attribute only. Fallback is requested lang -> th -> base valueText.",
inputSchema: {
type: "object",
properties: {
productId: { type: "number" },
productAttributeId: { type: "number" },
lang: { type: "string" },
valueText: { type: "string" }
},
required: ["productId", "productAttributeId", "lang", "valueText"]
}
},
{
name: "upload_product_image_from_url",
description: "Download image from URL, upload to backend, and append to product images",
@@ -883,6 +1025,54 @@ server.setRequestHandler(CallToolRequestSchema, async (request) => {
content: [{ type: "text", text: JSON.stringify({ success: true, message: `Translation for language '${params.lang}' updated successfully on product ${params.id}.` }, null, 2) }]
};
}
case "list_attribute_definitions": {
const categoryId = params.categoryId ? `categoryId=${params.categoryId}&` : "";
const lang = params.lang ? `lang=${params.lang}` : "lang=th";
const res = await api.get(`/product-attributes/definitions?${categoryId}${lang}`);
return { content: [{ type: "text", text: JSON.stringify(res.data, null, 2) }] };
}
case "get_attribute_definition_detail": {
const lang = params.lang ? `?lang=${params.lang}` : "";
const res = await api.get(`/product-attributes/definitions/${params.id}${lang}`);
return { content: [{ type: "text", text: JSON.stringify(res.data, null, 2) }] };
}
case "create_attribute_definition": {
const res = await api.post(`/product-attributes/definitions`, params);
return { content: [{ type: "text", text: JSON.stringify(res.data, null, 2) }] };
}
case "update_attribute_definition": {
const { id, ...payload } = params as any;
const res = await api.put(`/product-attributes/definitions/${id}`, payload);
return { content: [{ type: "text", text: JSON.stringify(res.data, null, 2) }] };
}
case "update_attribute_definition_translation": {
const { id, lang, label, description } = params as any;
const res = await api.patch(`/product-attributes/definitions/${id}/translations`, {
translations: {
[lang]: { label, description }
}
});
return { content: [{ type: "text", text: JSON.stringify(res.data, null, 2) }] };
}
case "list_product_attributes": {
const lang = params.lang ? `?lang=${params.lang}` : "";
const res = await api.get(`/products/${params.productId}/attributes${lang}`);
return { content: [{ type: "text", text: JSON.stringify(res.data, null, 2) }] };
}
case "set_product_attribute": {
const { productId, ...payload } = params as any;
const res = await api.post(`/products/${productId}/attributes`, payload);
return { content: [{ type: "text", text: JSON.stringify(res.data, null, 2) }] };
}
case "update_product_attribute_translation": {
const { productId, productAttributeId, lang, valueText } = params as any;
const res = await api.patch(`/products/${productId}/attributes/${productAttributeId}/translations`, {
translations: {
[lang]: valueText
}
});
return { content: [{ type: "text", text: JSON.stringify(res.data, null, 2) }] };
}
case "upload_product_image_from_url": {
// 1. Download image
const imgRes = await axios.get(params.imageUrl, { responseType: 'arraybuffer' });