Catalog Attribute Normalizer
Catalog attribute normalizer, taxonomy-grounded — no fabricated Google/Shopify category IDs.
Should I use this
Quality & Safety
Based on automated analysis of tool definitions and protocol compliance.
Context Cost
This is the approximate number of tokens consumed each time the server's tools are loaded into a model's context. Higher counts reduce the attention available for other tasks.
Install
One-Click Install
Add this to your `claude_desktop_config.json` file:
{
"mcpServers": {
"catalog-normalizer": {
"url": "https://acjlabs-catalog-normalizer.acjlabs.workers.dev/mcp"
}
}
}Remote endpoints
https://acjlabs-catalog-normalizer.acjlabs.workers.dev/mcpstreamable-httphttps://catalog-normalizer.acjlabs.com/mcpstreamable-httpWhat it can do
Tool inventory
Tools (1)
🟢normalize_catalog(products, target_taxonomies)
Normalizes a batch of catalog products (attribute canonicalization/extraction + category-path mapping into the requested target taxonomies: google, shopify, amazon). Returns one result per input product, same order: a NormalizedProduct on success, or { error, source_title } if that specific product's classification failed — one product's failure never voids the rest of the batch. attributes is keyed by a controlled vocabulary (size, color, material, gender, sleeve_length — unrecognized keys are dropped, not passed through under a model-chosen name) and each value carries provenance: "canonicalized" means it came from your own raw_attributes input for that product (deterministic cleanup only, no recall); "extracted" means the model inferred it from the title/description and it wasn't in your input — treat extracted values as a suggestion, not a confirmed fact about the product, the same way you'd treat a low-confidence category_paths entry. category_paths for google and shopify is retrieval-grounded against the real, current taxonomy files (not recalled from memory) — measured at 22/24 (91.7%) exact path+leaf_id matches on a 12-product evaluation set; amazon has no comparable public reference file, so it stays best-effort. Each entry's confidence (0-1) and leaf_id (null when not confident it matches a real node) are the honest signal regardless of taxonomy — treat a low-confidence or null-leaf_id result as a suggestion worth a quick human check, not a confirmed classification.
Input Schema
{
"type": "object",
"properties": {
"products": {
"maxItems": 200,
"type": "array",
"items": {
"type": "object",
"properties": {
"title": {
"type": "string",
"maxLength": 500
},
"description": {
"type": "string",
"maxLength": 5000
},
"raw_attributes": {
"type": "object",
"propertyNames": {
"type": "string"
},
"additionalProperties": {
"type": "string",
"maxLength": 1000
}
}
},
"required": [
"title",
"description",
"raw_attributes"
]
}
},
"target_taxonomies": {
"minItems": 1,
"type": "array",
"items": {
"type": "string",
"enum": [
"google",
"shopify",
"amazon"
]
}
}
},
"required": [
"products",
"target_taxonomies"
],
"$schema": "http://json-schema.org/draft-07/schema#"
}Output Schema
{
"type": "object",
"properties": {
"results": {
"type": "array",
"items": {
"anyOf": [
{
"type": "object",
"properties": {
"schema_version": {
"type": "string",
"const": "2.0"
},
"source_title": {
"type": "string"
},
"category_paths": {
"type": "object",
"properties": {
"google": {
"type": "object",
"properties": {
"path": {
"type": "array",
"items": {
"type": "string"
}
},
"leaf_id": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
]
},
"confidence": {
"type": "number"
}
},
"required": [
"path",
"leaf_id",
"confidence"
],
"additionalProperties": false
},
"shopify": {
"type": "object",
"properties": {
"path": {
"type": "array",
"items": {
"type": "string"
}
},
"leaf_id": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
]
},
"confidence": {
"type": "number"
}
},
"required": [
"path",
"leaf_id",
"confidence"
],
"additionalProperties": false
},
"amazon": {
"type": "object",
"properties": {
"path": {
"type": "array",
"items": {
"type": "string"
}
},
"leaf_id": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
]
},
"confidence": {
"type": "number"
}
},
"required": [
"path",
"leaf_id",
"confidence"
],
"additionalProperties": false
}
},
"additionalProperties": false
},
"attributes": {
"type": "object",
"properties": {
"size": {
"type": "object",
"properties": {
"value": {
"type": "string"
},
"provenance": {
"type": "string",
"enum": [
"canonicalized",
"extracted"
]
}
},
"required": [
"value",
"provenance"
],
"additionalProperties": false
},
"color": {
"type": "object",
"properties": {
"value": {
"type": "string"
},
"provenance": {
"type": "string",
"enum": [
"canonicalized",
"extracted"
]
}
},
"required": [
"value",
"provenance"
],
"additionalProperties": false
},
"material": {
"type": "object",
"properties": {
"value": {
"type": "string"
},
"provenance": {
"type": "string",
"enum": [
"canonicalized",
"extracted"
]
}
},
"required": [
"value",
"provenance"
],
"additionalProperties": false
},
"gender": {
"type": "object",
"properties": {
"value": {
"type": "string"
},
"provenance": {
"type": "string",
"enum": [
"canonicalized",
"extracted"
]
}
},
"required": [
"value",
"provenance"
],
"additionalProperties": false
},
"sleeve_length": {
"type": "object",
"properties": {
"value": {
"type": "string"
},
"provenance": {
"type": "string",
"enum": [
"canonicalized",
"extracted"
]
}
},
"required": [
"value",
"provenance"
],
"additionalProperties": false
}
},
"additionalProperties": false
}
},
"required": [
"schema_version",
"source_title",
"category_paths",
"attributes"
],
"additionalProperties": false
},
{
"type": "object",
"properties": {
"error": {
"type": "string"
},
"source_title": {
"type": "string"
}
},
"required": [
"error",
"source_title"
],
"additionalProperties": false
}
]
}
}
},
"required": [
"results"
],
"$schema": "http://json-schema.org/draft-07/schema#",
"additionalProperties": false
}Community
Evidence