Skip to main content
Glama
jodur

RDW MCP Server

by jodur

rdw-license-plate-lookup

Retrieve comprehensive Dutch vehicle data including specifications, emissions, inspection history, recalls, and ownership details using a license plate number.

Instructions

Look up ALL available Dutch vehicle information from RDW databases including vehicle specs, fuel/emissions, APK history, recalls, ownership history, technical defects, and more

Input Schema

TableJSON Schema
NameRequiredDescriptionDefault
kentekenYesDutch license plate (kenteken) to look up

Implementation Reference

  • The main handler function for the 'rdw-license-plate-lookup' tool. Cleans the license plate input, fetches comprehensive vehicle data from multiple RDW API endpoints in parallel using makeRDWRequest, overrides power data if available from fuel info, formats the data using formatVehicleInfo, and returns a structured markdown-like text response or error.
    async ({ kenteken }) => { // Clean up the license plate (remove spaces and hyphens, convert to uppercase) const cleanKenteken = kenteken.replace(/[\s-]+/g, "").toUpperCase(); try { // Get basic vehicle information const vehicleData = await makeRDWRequest<VehicleBaseInfo[]>("m9d7-ebf2", { kenteken: cleanKenteken, }); if (!vehicleData || vehicleData.length === 0) { return { content: [ { type: "text", text: `No vehicle found for license plate: ${cleanKenteken}`, }, ], }; } const vehicle = vehicleData[0]; // Fetch all available RDW data in parallel for better performance const [ fuelData, axesData, bodyData ] = await Promise.all([ // Fuel and emissions data makeRDWRequest<VehicleFuelInfo[]>("8ys7-d773", { kenteken: cleanKenteken }), // Axle data makeRDWRequest<VehicleAxesInfo[]>("3huj-srit", { kenteken: cleanKenteken }), // Body/carrosserie data makeRDWRequest<VehicleBodyInfo[]>("vezc-m2t6", { kenteken: cleanKenteken }) ]); // If fuel data is available, use the power from there for consistency if (fuelData && fuelData.length > 0 && fuelData[0].nettomaximumvermogen) { vehicle.nettomaximumvermogen = fuelData[0].nettomaximumvermogen; } const formattedInfo = formatVehicleInfo( vehicle, fuelData || undefined, undefined, // apkData - endpoint doesn't exist undefined, // recallData - endpoint doesn't exist undefined, // ownershipData - same as main dataset axesData || undefined, bodyData || undefined, undefined, // colorData - endpoint doesn't exist undefined // defectData - endpoint doesn't exist ); return { content: [ { type: "text", text: `COMPLETE RDW Database Information for ${cleanKenteken}:\n\n${formattedInfo}`, }, ], }; } catch (error) { return { content: [ { type: "text", text: `Error retrieving vehicle information: ${error instanceof Error ? error.message : "Unknown error"}`, }, ], }; } },
  • Zod input schema defining the required 'kenteken' string parameter for the license plate lookup tool.
    inputSchema: { kenteken: z.string().min(1).describe("Dutch license plate (kenteken) to look up"), }
  • src/index.ts:475-559 (registration)
    The MCP server tool registration call that associates the tool name 'rdw-license-plate-lookup' with its metadata (title, description, inputSchema) and handler function.
    server.registerTool( "rdw-license-plate-lookup", { title: "RDW License Plate Lookup", description: "Look up ALL available Dutch vehicle information from RDW databases including vehicle specs, fuel/emissions, APK history, recalls, ownership history, technical defects, and more", inputSchema: { kenteken: z.string().min(1).describe("Dutch license plate (kenteken) to look up"), } }, async ({ kenteken }) => { // Clean up the license plate (remove spaces and hyphens, convert to uppercase) const cleanKenteken = kenteken.replace(/[\s-]+/g, "").toUpperCase(); try { // Get basic vehicle information const vehicleData = await makeRDWRequest<VehicleBaseInfo[]>("m9d7-ebf2", { kenteken: cleanKenteken, }); if (!vehicleData || vehicleData.length === 0) { return { content: [ { type: "text", text: `No vehicle found for license plate: ${cleanKenteken}`, }, ], }; } const vehicle = vehicleData[0]; // Fetch all available RDW data in parallel for better performance const [ fuelData, axesData, bodyData ] = await Promise.all([ // Fuel and emissions data makeRDWRequest<VehicleFuelInfo[]>("8ys7-d773", { kenteken: cleanKenteken }), // Axle data makeRDWRequest<VehicleAxesInfo[]>("3huj-srit", { kenteken: cleanKenteken }), // Body/carrosserie data makeRDWRequest<VehicleBodyInfo[]>("vezc-m2t6", { kenteken: cleanKenteken }) ]); // If fuel data is available, use the power from there for consistency if (fuelData && fuelData.length > 0 && fuelData[0].nettomaximumvermogen) { vehicle.nettomaximumvermogen = fuelData[0].nettomaximumvermogen; } const formattedInfo = formatVehicleInfo( vehicle, fuelData || undefined, undefined, // apkData - endpoint doesn't exist undefined, // recallData - endpoint doesn't exist undefined, // ownershipData - same as main dataset axesData || undefined, bodyData || undefined, undefined, // colorData - endpoint doesn't exist undefined // defectData - endpoint doesn't exist ); return { content: [ { type: "text", text: `COMPLETE RDW Database Information for ${cleanKenteken}:\n\n${formattedInfo}`, }, ], }; } catch (error) { return { content: [ { type: "text", text: `Error retrieving vehicle information: ${error instanceof Error ? error.message : "Unknown error"}`, }, ], }; } }, );
  • Utility function to make HTTP requests to RDW Open Data API endpoints, handling URL construction, parameters, headers, fetch, and error handling. Used by the tool handler for all API calls.
    async function makeRDWRequest<T>(endpoint: string, params?: Record<string, string>): Promise<T | null> { const url = new URL(`${RDW_API_BASE}/${endpoint}.json`); if (params) { Object.entries(params).forEach(([key, value]) => { url.searchParams.append(key, value); }); } const headers = { "User-Agent": USER_AGENT, "Accept": "application/json", }; try { const response = await fetch(url.toString(), { headers }); if (!response.ok) { throw new Error(`HTTP error! status: ${response.status}`); } return (await response.json()) as T; } catch (error) { console.error("Error making RDW request:", error); return null; } }
  • Comprehensive formatting utility that takes raw RDW vehicle data from multiple API responses and structures it into a human-readable, multi-section text report covering all aspects of the vehicle (basic info, specs, weights, fuel, axles, etc.). Called by the tool handler.
    function formatVehicleInfo( vehicle: VehicleBaseInfo, fuelData?: VehicleFuelInfo[], apkData?: VehicleAPKInfo[], recallData?: VehicleRecallInfo[], ownershipData?: VehicleOwnershipInfo[], axesData?: VehicleAxesInfo[], bodyData?: VehicleBodyInfo[], colorData?: VehicleColorInfo[], defectData?: VehicleDefectInfo[] ): string { const basicInfo = [ `License Plate: ${vehicle.kenteken || "Unknown"}`, `Vehicle Type: ${vehicle.voertuigsoort || "Unknown"}`, `Brand: ${vehicle.merk || "Unknown"}`, `Model: ${vehicle.handelsbenaming || "Unknown"}`, `Variant: ${vehicle.variant || "Unknown"}`, `Version: ${vehicle.uitvoering || "Unknown"}`, `European Category: ${vehicle.europese_voertuigcategorie || "Unknown"}`, `Vehicle Type Code: ${vehicle.type || "Unknown"}`, ]; const appearance = [ `Primary Color: ${vehicle.eerste_kleur || "Unknown"}`, ...(vehicle.tweede_kleur && vehicle.tweede_kleur !== "Niet geregistreerd" ? [`Secondary Color: ${vehicle.tweede_kleur}`] : []), `Body Type: ${vehicle.inrichting || "Unknown"}`, `Number of Doors: ${vehicle.aantal_deuren || "Unknown"}`, `Number of Wheels: ${vehicle.aantal_wielen || "Unknown"}`, `Length: ${vehicle.lengte ? `${vehicle.lengte} cm` : "Unknown"}`, `Width: ${vehicle.breedte ? `${vehicle.breedte} cm` : "Unknown"}`, `Height: ${vehicle.hoogte_voertuig ? `${vehicle.hoogte_voertuig} cm` : "Unknown"}`, `Wheelbase: ${vehicle.wielbasis ? `${vehicle.wielbasis} cm` : "Unknown"}`, ]; const capacity = [ `Seats: ${vehicle.aantal_zitplaatsen || "Unknown"}`, ...(vehicle.aantal_staanplaatsen ? [`Standing Places: ${vehicle.aantal_staanplaatsen}`] : []), ]; const technical = [ `Engine Cylinders: ${vehicle.aantal_cilinders || "Unknown"}`, `Engine Displacement: ${vehicle.cilinderinhoud ? `${vehicle.cilinderinhoud} cc` : "Unknown"}`, `Net Max Power: ${vehicle.nettomaximumvermogen ? `${vehicle.nettomaximumvermogen} kW` : "Unknown"}`, `Power/Mass Ratio: ${vehicle.vermogen_massarijklaar ? `${vehicle.vermogen_massarijklaar} kW/kg` : "Unknown"}`, `Max Construction Speed: ${vehicle.maximale_constructiesnelheid ? `${vehicle.maximale_constructiesnelheid} km/h` : "Unknown"}`, ...(vehicle.nominaal_continu_maximumvermogen ? [`Nominal Continuous Max Power: ${vehicle.nominaal_continu_maximumvermogen} kW`] : []), ]; const masses = [ `Empty Weight (Massa ledig): ${vehicle.massa_ledig_voertuig ? `${vehicle.massa_ledig_voertuig} kg` : "Unknown"}`, `Curb Weight (Massa rijklaar): ${vehicle.massa_rijklaar ? `${vehicle.massa_rijklaar} kg` : "Unknown"}`, `Maximum Vehicle Mass: ${vehicle.toegestane_maximum_massa_voertuig || vehicle.maximum_massa_voertuig ? `${vehicle.toegestane_maximum_massa_voertuig || vehicle.maximum_massa_voertuig} kg` : "Unknown"}`, `Technical Max Mass: ${vehicle.technische_max_massa_voertuig ? `${vehicle.technische_max_massa_voertuig} kg` : "Unknown"}`, `Max Towing Unbraked (Ongeremd): ${vehicle.maximum_massa_trekken_ongeremd ? `${vehicle.maximum_massa_trekken_ongeremd} kg` : "Unknown"}`, `Max Towing Braked (Geremd): ${vehicle.maximum_trekken_massa_geremd || vehicle.maximum_massa_trekken_geremd ? `${vehicle.maximum_trekken_massa_geremd || vehicle.maximum_massa_trekken_geremd} kg` : "Unknown"}`, ...(vehicle.maximum_massa_samenstelling ? [`Max Combination Mass: ${vehicle.maximum_massa_samenstelling} kg`] : []), ...(vehicle.massa_alt_aandr ? [`Alternative Drive Mass: ${vehicle.massa_alt_aandr} kg`] : []), ]; const registration = [ `First Registration: ${vehicle.datum_eerste_toelating || "Unknown"}`, `First NL Registration: ${vehicle.datum_eerste_tenaamstelling_in_nederland || "Unknown"}`, ...(vehicle.datum_tenaamstelling ? [`Current Registration: ${vehicle.datum_tenaamstelling}`] : []), `Type Approval: ${vehicle.typegoedkeuringsnummer || vehicle.type_goedkeuring_nummer || "Unknown"}`, `EU Type Approval Change Number: ${vehicle.volgnummer_wijziging_eu_typegoedkeuring || "Unknown"}`, `Registration Possible: ${vehicle.tenaamstellen_mogelijk || "Unknown"}`, `Pending Inspection: ${vehicle.wacht_op_keuren || "Unknown"}`, ...(vehicle.registratie_datum_goedkeuring_afschrijvingsmoment_bpm ? [`BPM Approval Date: ${vehicle.registratie_datum_goedkeuring_afschrijvingsmoment_bpm}`] : []), ]; const inspection = [ `APK Expiry: ${vehicle.vervaldatum_apk || "Unknown"}`, ...(vehicle.vervaldatum_tachograaf ? [`Tachograph Expiry: ${vehicle.vervaldatum_tachograaf}`] : []), ]; const financial = [ ...(vehicle.catalogusprijs ? [`Catalog Price: €${vehicle.catalogusprijs}`] : []), ...(vehicle.bruto_bpm ? [`Gross BPM: €${vehicle.bruto_bpm}`] : []), ]; const indicators = [ `Fuel Efficiency Class: ${vehicle.zuinigheidsclassificatie || vehicle.zuinigheidslabel || "Unknown"}`, `Export Status: ${vehicle.export_indicator || vehicle.exportindicator || "Unknown"}`, `Taxi: ${vehicle.taxi_indicator || "Unknown"}`, `WAM Insured: ${vehicle.wam_verzekerd || "Unknown"}`, `Open Recall: ${vehicle.openstaande_terugroepactie_indicator || "Unknown"}`, `Odometer Status: ${vehicle.tellerstandoordeel || "Unknown"}`, ...(vehicle.code_toelichting_tellerstandoordeel ? [`Odometer Code: ${vehicle.code_toelichting_tellerstandoordeel}`] : []), `Aerodynamic Equipment: ${vehicle.aerodyn_voorz || "Unknown"}`, `Extended Cab: ${vehicle.verl_cab_ind || "Unknown"}`, ]; // Format fuel and emissions data if available const fuelEmissions: string[] = []; if (fuelData && fuelData.length > 0) { fuelData.forEach((fuel, index) => { const fuelInfo = [ `Fuel Type ${index + 1}: ${fuel.brandstof_omschrijving || "Unknown"}`, `Emission Code: ${fuel.emissiecode_omschrijving || "Unknown"}`, `Emission Level: ${fuel.uitlaatemissieniveau || "Unknown"}`, `Environmental Class: ${fuel.milieuklasse_eg_goedkeuring_licht || "Unknown"}`, `CO2 Emission Class: ${fuel.co2_emissieklasse || "Unknown"}`, `Max Power: ${fuel.nettomaximumvermogen || "Unknown"} kW`, `Sound Level (Driving): ${fuel.geluidsniveau_rijdend || "Unknown"} dB`, `Sound Level (Idle): ${fuel.geluidsniveau_stationair || "Unknown"} dB`, `Sound Test RPM: ${fuel.toerental_geluidsniveau || "Unknown"}`, `CO2 Combined (WLTP): ${fuel.emissie_co2_gecombineerd_wltp || "Unknown"} g/km`, `Fuel Consumption Combined (WLTP): ${fuel.brandstof_verbruik_gecombineerd_wltp || "Unknown"} l/100km`, `Particle Emissions Type 1 (WLTP): ${fuel.emis_deeltjes_type1_wltp || "Unknown"} mg/km`, `Soot Emission: ${fuel.roetuitstoot || "Unknown"}`, ]; fuelEmissions.push(fuelInfo.join("\n")); }); } // Format APK (MOT) inspection data const apkInfo: string[] = []; if (apkData && apkData.length > 0) { apkData.forEach((apk, index) => { const info = [ `APK Record ${index + 1}:`, `Expiry Date: ${apk.vervaldatum_apk || "Unknown"}`, `Last Updated: ${apk.dt_laatste_update_in_rdw || "Unknown"}`, `Number of APK Dates: ${apk.aantal_datums_apk || "Unknown"}`, ]; apkInfo.push(info.join("\n")); }); } // Format recall/defect data const recallInfo: string[] = []; if (recallData && recallData.length > 0) { recallData.forEach((recall, index) => { const info = [ `Recall ${index + 1}:`, `Reference Code: ${recall.referentiecode_rdw || "Unknown"}`, `Recall Date: ${recall.datum_terugroepactie || "Unknown"}`, `Defect Code: ${recall.code_gebrek || "Unknown"}`, `Defect Description: ${recall.omschrijving_gebrek || "Unknown"}`, `Valid From: ${recall.datum_vanaf_eerste_toepassing_terugroepactie || "Unknown"}`, `Valid Until: ${recall.datum_tot_eerste_toepassing_terugroepactie || "Unknown"}`, ]; recallInfo.push(info.join("\n")); }); } // Format ownership/registration history const ownershipInfo: string[] = []; if (ownershipData && ownershipData.length > 0) { ownershipData.forEach((ownership, index) => { const info = [ `Registration ${index + 1}:`, `Registration Date: ${ownership.datum_tenaamstelling || "Unknown"}`, `First Registration Date: ${ownership.datum_eerste_tenaamstelling || "Unknown"}`, `Last Updated: ${ownership.dt_laatste_update_in_rdw || "Unknown"}`, ]; ownershipInfo.push(info.join("\n")); }); } // Format axle data const axleInfo: string[] = []; if (axesData && axesData.length > 0) { const totalAxles = axesData[0].aantal_assen || "Unknown"; axleInfo.push(`Total Number of Axles: ${totalAxles}`); axesData.forEach((axle, index) => { const info = [ `Axle ${axle.as_nummer || index + 1}:`, `Driven Axle: ${axle.aangedreven_as === "J" ? "Yes" : axle.aangedreven_as === "N" ? "No" : "Unknown"}`, `Position Code: ${axle.plaatscode_as || "Unknown"}`, `Track Width: ${axle.spoorbreedte || "Unknown"} cm`, `Technical Max Load: ${axle.technisch_toegestane_maximum_aslast || "Unknown"} kg`, `Legal Max Load: ${axle.wettelijk_toegestane_maximum_aslast || "Unknown"} kg`, `Distance to Next Axle: ${axle.afstand_tot_volgende_as_voertuig || "Unknown"} cm`, ]; axleInfo.push(info.join("\n")); }); } // Format body/carrosserie data const bodyInfo: string[] = []; if (bodyData && bodyData.length > 0) { bodyData.forEach((body, index) => { const info = [ `Body Configuration ${index + 1}:`, `Carrosserie Type: ${body.carrosserietype || "Unknown"}`, `European Description: ${body.type_carrosserie_europese_omschrijving || "Unknown"}`, // Note: Body Type is already shown in Appearance section from main vehicle data ]; bodyInfo.push(info.join("\n")); }); } // Format additional color data const additionalColorInfo: string[] = []; if (colorData && colorData.length > 0) { colorData.forEach((color, index) => { additionalColorInfo.push(`Color ${index + 1}: ${color.kleur || "Unknown"}`); }); } // Format defect data const defectInfo: string[] = []; if (defectData && defectData.length > 0) { defectData.forEach((defect, index) => { const info = [ `Defect ${index + 1}:`, `ID: ${defect.gebrek_identificatie || "Unknown"}`, `Date Found: ${defect.datum_constatering_gebrek || "Unknown"}`, `Location: ${defect.locatie_gebrek || "Unknown"}`, `Code: ${defect.code_gebrek || "Unknown"}`, `Description: ${defect.omschrijving_gebrek || "Unknown"}`, ]; defectInfo.push(info.join("\n")); }); } const sections = [ `BASIC INFORMATION:\n${basicInfo.join("\n")}`, `APPEARANCE:\n${appearance.join("\n")}`, `CAPACITY:\n${capacity.join("\n")}`, `TECHNICAL SPECIFICATIONS:\n${technical.join("\n")}`, `WEIGHTS & TOWING CAPACITY:\n${masses.join("\n")}`, `REGISTRATION:\n${registration.join("\n")}`, `INSPECTION:\n${inspection.join("\n")}`, ...(financial.length > 0 ? [`FINANCIAL:\n${financial.join("\n")}`] : []), ...(indicators.length > 0 ? [`STATUS INDICATORS:\n${indicators.join("\n")}`] : []), ...(fuelEmissions.length > 0 ? [`FUEL & EMISSIONS:\n${fuelEmissions.join("\n---\n")}`] : []), ...(apkInfo.length > 0 ? [`APK INSPECTION HISTORY:\n${apkInfo.join("\n---\n")}`] : []), ...(recallInfo.length > 0 ? [`RECALLS & SAFETY ACTIONS:\n${recallInfo.join("\n---\n")}`] : []), ...(ownershipInfo.length > 0 ? [`REGISTRATION HISTORY:\n${ownershipInfo.join("\n---\n")}`] : []), ...(axleInfo.length > 0 ? [`AXLE SPECIFICATIONS:\n${axleInfo.join("\n---\n")}`] : []), ...(bodyInfo.length > 0 ? [`BODY SPECIFICATIONS:\n${bodyInfo.join("\n---\n")}`] : []), ...(additionalColorInfo.length > 0 ? [`ADDITIONAL COLORS:\n${additionalColorInfo.join("\n")}`] : []), ...(defectInfo.length > 0 ? [`TECHNICAL DEFECTS:\n${defectInfo.join("\n---\n")}`] : []), `Last Odometer Reading: ${vehicle.jaar_laatste_registratie_tellerstand || "Unknown"}`, ]; return sections.join("\n\n"); }
Install Server

Other Tools

Latest Blog Posts

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/jodur/RDW-MCP'

If you have feedback or need assistance with the MCP directory API, please join our Discord server