uk_duty_calculator
Estimate UK import duty and VAT for any HS commodity code. Uses live Trade Tariff data to calculate CIF value, applies duty rate, then adds 20% VAT.
Instructions
Estimate UK import duty and VAT for any commodity code.
Uses live GOV.UK Trade Tariff data. Calculates CIF value from goods value + freight + insurance, applies the appropriate duty rate, then calculates VAT (standard 20%) on the duty-inclusive value.
Use this tool when you need to:
Estimate import costs for UK-bound shipments
Check duty rates for specific HS/commodity codes
Compare landed costs for different origin countries
Determine if preferential rates apply
Input Schema
| Name | Required | Description | Default |
|---|---|---|---|
| commodity_code | Yes | HS/tariff code (6–10 digits, e.g., "847989") | |
| origin_country | Yes | ISO 2-letter origin country code (e.g., "CN", "DE") | |
| customs_value | Yes | Goods value in GBP | |
| freight_cost | No | Freight cost in GBP (added to CIF value) | |
| insurance_cost | No | Insurance cost in GBP (added to CIF value) | |
| incoterm | No | Incoterm (e.g., "FOB", "CIF", "EXW") |
Implementation Reference
- src/tools.ts:519-519 (handler)The handler function for uk_duty_calculator. It calls apiPost('duty', args) which POSTs to the FreightUtils API endpoint '/duty' with the validated arguments.
handler: async (args) => apiPost('duty', args), - src/tools.ts:506-513 (schema)Zod schema defining input validation: commodity_code (6-10 digits), origin_country (2-letter ISO), customs_value (positive GBP), optional freight_cost, insurance_cost, and incoterm. Strict mode rejects unknown keys.
schema: z.object({ commodity_code: z.string().regex(/^\d{6,10}$/, 'Commodity code must be 6–10 digits').describe('HS/tariff code (6–10 digits, e.g., "847989")'), origin_country: z.string().length(2, 'Origin country must be a 2-letter ISO code').regex(/^[A-Z]{2}$/i, 'Origin country must be a 2-letter ISO code (e.g., "CN", "DE")').describe('ISO 2-letter origin country code (e.g., "CN", "DE")'), customs_value: z.number().positive().describe('Goods value in GBP'), freight_cost: z.number().optional().describe('Freight cost in GBP (added to CIF value)'), insurance_cost: z.number().optional().describe('Insurance cost in GBP (added to CIF value)'), incoterm: z.string().optional().describe('Incoterm (e.g., "FOB", "CIF", "EXW")'), }).strict(), - src/tools.ts:728-728 (registration)The tool is registered in the ALL_TOOLS array at line 728, which is iterated over in server.ts to register each tool with the MCP server.
ukDutyCalculator, - src/server.ts:20-41 (registration)Server registration loop in createServer(): iterates ALL_TOOLS and calls server.tool() with name, description, schema, annotations, and a wrapper handler that catches errors.
server.tool( tool.name, tool.description, tool.schema.shape, tool.annotations, async (args: Record<string, unknown>) => { try { const result = await tool.handler(args); return { content: [ { type: 'text' as const, text: JSON.stringify(result, null, 2) }, ], }; } catch (err: unknown) { const message = err instanceof Error ? err.message : String(err); return { content: [{ type: 'text' as const, text: `Error: ${message}` }], isError: true, }; } }, ); - src/api.ts:26-39 (helper)The apiPost helper function used by the handler to POST to the FreightUtils API. It constructs the URL from BASE_URL + endpoint, sends JSON body, and returns parsed JSON response.
export async function apiPost(endpoint: string, body: unknown): Promise<unknown> { const res = await fetch(`${BASE_URL}/${endpoint}`, { method: 'POST', headers: { 'Content-Type': 'application/json', 'Accept': 'application/json' }, body: JSON.stringify(body), }); if (!res.ok) { const text = await res.text(); throw new Error(`FreightUtils API error ${res.status}: ${text}`); } return res.json(); }