Klassio — EU customs tariff (CN/HS) classification + EUDR
Server Details
EU customs tariff classification: CN/HS code + GIR rule, MFN duty and EUDR scope. Sourced.
- Status
- Healthy
- Uptime
- 100.0% over 22 days
- Last Tested
- Transport
- Streamable HTTP · MCP 2025-11-25
- URL
TDQS
Scored across 2 tools
The two tools have clearly distinct purposes: classify_article handles free-text product classification, while lookup_cn_code serves fast retrieval for an already-known CN code. There is no overlap or ambiguity in when to use each.
Both names follow the same snake_case pattern with a consistent klassio_ prefix and verb_noun structure (classify_article, lookup_cn_code). The convention is predictable and easy to parse.
Two tools is thin for a server covering both classification and EUDR; common needs like batch classification or EUDR-specific actions have no entry point. The surface is focused but arguably under-scoped.
Core operations for single-item classification and code lookup are covered, and EUDR scope is returned as a side output. However, obvious gaps exist: no batch/bulk classification, no EUDR due-diligence or statement tools, and no tariff-calculation or landed-cost operation.
Available Tools
2 toolsklassio_classify_articleARead-onlyIdempotentInspect
Single-product classification. Accepts a free-text description plus optional structured hints (materials, intended_use, category, origin/destination country). POPULATE EVERY HINT YOU HAVE — materials/intended_use/category materially improve retrieval and candidate quality vs a description-only call (e.g. description:"Funko POP Vinyl", category:"Figurines", materials:["PVC plastic"], intended_use:"decorative collectible figure" reliably surfaces ch. 95). Returns top-3 CN candidates, EUDR scope, MFN duty, a bilingual reasoning_md narrative, a gap_analysis flagging missing inputs, and a tri-state status (confident / review_recommended / manual_review_required). Trust status for review-routing — do not re-derive your own confidence threshold. PAT-authed callers also receive prior_decisions[] from the org dictionary history.
| Name | Required | Description | Default |
|---|---|---|---|
| lang | No | Return reasoning in a single language: drops the redundant rationale_* field for the other and (with compact_rules) collapses the shared rule pool to this language. Absent = bilingual (default). | |
| dry_run | No | First half of the BYOM eval loop: with dry_run:true retrieval + prompt-build run but the judge is NOT called — returns candidates_top10 + request_token only, no judge spend. Judge with your own model (e.g. fan out across subagents to parallelise), then call klassio_submit_classification_verdict. Prefer this over the inline judge for bulk eval/scoring. | |
| include | No | L3 opt-ins. 'compact_rules' hoists per-candidate rule bodies into a shared top-level classification_rules pool (candidates carry rule_ids[] instead). 'truncate_rules' truncates the pool bodies to ~240 chars (use with compact_rules). Default = master shape (per-candidate bilingual classification_rules, no pool). | |
| category | No | Your internal product-taxonomy label, e.g. "Figurines", "Vacuum Cleaner Accessories". Folded into the retrieval query to anchor the right chapter (e.g. "Figurines" pulls ch. 95 toys instead of ch. 39 raw polymer). Populate whenever you have one. | |
| materials | No | Constituent materials, e.g. ["PVC plastic","vinyl"] or ["wood","MDF"]. Strongly improves retrieval — a material-poor description retrieves weaker candidates. Populate whenever known. | |
| current_cn | No | ||
| description | Yes | ||
| origin_iso2 | No | Country of origin (ISO 3166-1 alpha-2, e.g. "CN"). Improves duty/FTA and EUDR country-risk context and disambiguates origin-sensitive headings. | |
| intended_use | No | Function / end use, e.g. "decorative collectible figure" or "kitchen cabinet door panel". Disambiguates products whose bare name misleads (a "Funko POP Vinyl" reads as raw vinyl without it). Populate whenever known. | |
| destination_iso2 | No | Import destination country (ISO 3166-1 alpha-2, e.g. "SE"). Adds destination-specific measure/declaration context. | |
| omit_system_prompt | No | Dry-run only: omit the re-sent judge system prompt from dry_run_prompt.system (set null) to save ~3k tokens per call. prompt_version is still returned so a caller can validate a system cached via klassio_get_judge_system_prompt. Does NOT change request_token. Default false (system included). | |
| omit_raw_candidates | No | Dry-run only: omit the diagnostic dry_run_prompt.raw_candidates pool. Default false (raw_candidates included). The BYOM submit path re-runs retrieval, so omitting this does not affect request_token. |
Output Schema
| Name | Required | Description |
|---|---|---|
| status | Yes | |
| taric_gap | No | |
| candidates | Yes | |
| confidence | Yes | |
| query_used | Yes | |
| result_ref | Yes | |
| taric_code | No | |
| gri_applied | Yes | |
| judge_debug | Yes | |
| taric_basis | No | |
| gap_analysis | Yes | |
| judge_winner | Yes | |
| rationale_en | Yes | |
| rationale_sv | Yes | |
| reasoning_md | Yes | |
| dry_run_prompt | No | |
| taric_measures | No | |
| judge_runner_up | Yes | |
| prior_decisions | No | |
| taric_candidates | No | |
| mfn_across_leaves | No | |
| retrieval_quality | No | |
| recommended_action | No | |
| classification_rules | No | |
| judge_quota_remaining | No |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare read-only/idempotent safety, so the description rightly spends its budget on behavior the schema can't convey: the tri-state status contract ('Trust status for review-routing — do not re-derive your own confidence threshold'), PAT-auth prior_decisions behavior, and dry_run's judge-spend avoidance. This is rich, non-redundant disclosure.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Front-loaded with purpose, then inputs, then outputs, then the status caveat. Dense but nearly every sentence earns its place; the hint-emphasis slightly overlaps the schema descriptions but is defensible given retrieval stakes.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
An output schema exists so return values needn't be explained in depth, yet the description still summarizes the key return fields and the review-routing rule. For a 12-parameter tool with a sibling lookup tool, an agent has everything needed to call it correctly.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is already 83%, so the baseline is 3, but the description adds genuine meaning: it explains why materials/intended_use/category matter (retrieval quality) and reinforces the description-only vs hinted comparison, supplementing the schema's own field docs.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
Opens with a specific verb+resource phrase ('Single-product classification') and immediately states the accepted inputs and the concrete outputs (top-3 CN candidates, EUDR scope, MFN duty, status). The sibling klassio_lookup_cn_code is a code lookup, so this classification tool is clearly distinguished without opening either schema.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Gives strong when-to-use guidance: 'POPULATE EVERY HINT YOU HAVE' with a worked example showing how hints change chapter retrieval, and routes bulk eval to dry_run. It does not explicitly state when to prefer klassio_lookup_cn_code over this tool, so it stops short of full alternative routing.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
klassio_lookup_cn_codeARead-onlyIdempotentInspect
Fast lookup for a known CN code. Returns the canonical description (SV + EN), chapter heading, applicable classification rules, EUDR Annex I scope (in_scope + is_ex), and the MFN duty headline. Pass include=["reasoning"] to also receive the bilingual reasoning_md narrative.
| Name | Required | Description | Default |
|---|---|---|---|
| cn_code | Yes | ||
| include | No |
Output Schema
| Name | Required | Description |
|---|---|---|
| duty | No | |
| eudr | No | |
| found | Yes | |
| cn_code | Yes | |
| message | No | |
| reasoning_md | No | |
| description_en | No | |
| description_sv | No | |
| cn_code_display | No | |
| classification_rules | No | |
| chapter_description_en | No | |
| chapter_description_sv | No |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
With readOnlyHint, idempotentHint, and destructiveHint=false already provided, there is no contradiction and no need for side-effect warnings. The description adds behavioral value by revealing that include=['reasoning'] changes the response to append a bilingual reasoning narrative, and by characterizing the operation as a fast deterministic lookup.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Two compact sentences carry purpose, output summary, and the single optional parameter behavior. No filler, redundancy, or tautology.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a read-only, idempotent two-parameter lookup with an output schema present, the description is complete: it names the required input, the returned fields, and the optional include flag. Nothing needed to call the tool correctly is missing.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 0%, so the description must supply parameter meaning; it explains include=['reasoning'] precisely, and identifies cn_code as the known CN code being looked up. The valid digit-length alternatives are left to the schema pattern, which is an acceptable structured constraint.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description states a specific operation ('lookup') on a concrete resource ('a known CN code') and enumerates what is returned. The word 'known' signals that this is a direct code lookup rather than a classification task, helping distinguish it from klassio_classify_article.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
'Fast lookup for a known CN code' clearly tells the agent when to call this tool: when the code is already known. It does not explicitly say 'use klassio_classify_article when the code is unknown,' so it lacks a full when-not/alternative statement, but the context is strongly implied.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
Tool Schema Changelog
Recent tool additions, removals, and schema changes observed during successful MCP inspections.
1 tool update
- Changed
klassio_classify_article1 field changed- added
Output schema / properties / judge_debug / properties / deciding_notesAdded value: +{ + "additionalProperties": false, + "properties": { + "chapters": { + "items": { + "type": "string" + }, + "type": "array" + }, + "chars": { + "maximum": 9007199254740991, + "minimum": -9007199254740991, + "type": "integer" + }, + "clause_keys": { + "items": { + "type": "string" + }, + "type": "array" + }, + "status": { + "enum": [ + "rendered", + "not_triggered", + "no_clauses", + "loader_error" + ], + "type": "string" + } + }, + "required": [ + "status", + "clause_keys", + "chars", + "chapters" + ], + "type": "object" +}
1 tool update
- Changed
klassio_classify_article11 fields changed- added
Output schema / properties / judge_debug / properties / heading_proposal_injectedAdded value: +{ + "maximum": 9007199254740991, + "minimum": -9007199254740991, + "type": "integer" +} - added
Output schema / properties / judge_debug / properties / normalize_msAdded value: +{ + "anyOf": [ + { + "maximum": 9007199254740991, + "minimum": -9007199254740991, + "type": "integer" + }, + { + "type": "null" + } + ] +} - added
Output schema / properties / judge_debug / properties / normalize_outcomeAdded value: +{ + "enum": [ + "off", + "cache_hit", + "ok", + "timeout", + "parse_fail", + "refused", + "error" + ], + "type": "string" +} - added
Output schema / properties / judge_debug / properties / normalize_prompt_versionAdded value: +{ + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ] +} - added
Output schema / properties / judge_debug / properties / proposed_headingsAdded value: +{ + "items": { + "type": "string" + }, + "type": "array" +} - added
Output schema / properties / judge_debug / properties / proposed_headings_validAdded value: +{ + "items": { + "type": "string" + }, + "type": "array" +} - added
Output schema / properties / judge_debug / properties / retrieval_msAdded value: +{ + "anyOf": [ + { + "maximum": 9007199254740991, + "minimum": -9007199254740991, + "type": "integer" + }, + { + "type": "null" + } + ] +} - added
Output schema / properties / judge_debug / properties / rewrite_dense_nAdded value: +{ + "maximum": 9007199254740991, + "minimum": -9007199254740991, + "type": "integer" +} - added
Output schema / properties / judge_debug / properties / rewrite_only_codesAdded value: +{ + "items": { + "type": "string" + }, + "type": "array" +} - added
Output schema / properties / judge_debug / properties / rewrite_only_in_poolAdded value: +{ + "maximum": 9007199254740991, + "minimum": -9007199254740991, + "type": "integer" +} - added
Output schema / properties / judge_debug / properties / tariff_rewriteAdded value: +{ + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ] +}
1 tool update
- Changed
klassio_classify_article7 fields changed- added
Output schema / properties / judge_debug / properties / chapter_hint_sourceAdded value: +{ + "enum": [ + "normalised", + "raw", + "bti" + ], + "type": "string" +} - added
Output schema / properties / judge_debug / properties / judge_flagged_missingAdded value: +{ + "type": "boolean" +} - added
Output schema / properties / judge_debug / properties / off_list_cn_codeAdded value: +{ + "type": "string" +} - added
Output schema / properties / judge_debug / properties / off_list_reasonAdded value: +{ + "type": "string" +} - added
Output schema / properties / judge_debug / properties / off_list_rejectedAdded value: +{ + "type": "string" +} - added
Output schema / properties / judge_debug / properties / rationale_winner_mismatchAdded value: +{ + "type": "boolean" +} - added
Output schema / properties / judge_debug / properties / rerank_errorAdded value: +{ + "type": "string" +}
2 tool updates
- First observed
klassio_classify_article - First observed
klassio_lookup_cn_code
Related MCP Connectors
Practitioner-verified EU customs facts: classification, duty, origin, procedures. x402.
EU customs-trade & industrial-production statistics (Eurostat Comext/PRODCOM)
Classify, validate & verify HS codes and access tariff compliance data for cross-border trade
Classify products to official HS codes and validate supplier codes before customs submissions
Related MCP Servers
- AlicenseAqualityCmaintenanceEnables checking whether a CN code is an EU Deforestation Regulation relevant product, when the obligations apply by operator type, and the risk level of a country, with answers citing the article, act and consolidated version used. It serves the current Annex I, application dates and country classifications as an MCP server and command line, applying amendments not yet consolidated.5MIT
- AlicenseAqualityCmaintenanceEnables users to query EU Carbon Border Adjustment Mechanism data offline: whether a Combined Nomenclature code is in scope, which default emission values apply for a given country of origin, and what the code describes. Every answer cites the legally binding act, the dated data version, and flags that the data itself is not legally binding.5MIT
- AlicenseBqualityBmaintenanceAutonomous AI Agent compliance engine for EU Deforestation Regulation (EU 2023/1115). Verifies farm plot GIS polygons, Sentinel-2 satellite deforestation past 2020, VIES VAT, and generates official TRACES-NT DDS XML.41MIT
- AlicenseNot gradedqualityCmaintenanceEnables US import compliance by providing CBP customs ruling letter searches and antidumping/countervailing duty order lookups, answering how Customs has classified products and whether trade-remedy duties apply.227 npmMIT
Glama MCP Gateway
Add one secure layer between your agents and this server.