dns_list_records
List DNS records in a zone, optionally filter by a specific domain name.
Instructions
List DNS records in a zone. Optionally filter by a specific domain name within the zone. When no domain is specified, returns all records across all zones matching the zone name (including subzones like app.example.com when zone=example.com). When domain is specified, returns records for that exact domain only.
Input Schema
| Name | Required | Description | Default |
|---|---|---|---|
| zone | Yes | Zone domain name (e.g. example.com). Can be a parent domain to list all subzones. | |
| domain | No | Optional specific domain to filter (e.g. www.example.com). Defaults to the zone name if omitted. |
Implementation Reference
- src/tools/records.ts:61-122 (handler)Handler function for the dns_list_records tool. Takes zone (required) and optional domain parameters. If domain is specified, queries that exact domain. Otherwise finds all matching zones (parent + subzones), exports each via BIND format, and parses the results.
handler: async (args) => { const zone = validateDomain(args.zone as string); if (args.domain) { // Specific domain requested — query that domain directly const domain = validateDomain(args.domain as string); const data = await client.callOrThrow("/api/zones/records/get", { zone, domain, }); return JSON.stringify(data, null, 2); } // No domain specified — find all zones that match or are subzones of the requested name const zoneList = await client.callOrThrow("/api/zones/list"); const allZones = ( zoneList.zones as Array<{ name: string; internal: boolean }> ).filter( (z) => !z.internal && (z.name === zone || z.name.endsWith("." + zone)) ); if (allZones.length === 0) { // No matching zones — fall back to direct query (will surface API error if zone missing) const data = await client.callOrThrow("/api/zones/records/get", { zone, domain: zone, }); return JSON.stringify(data, null, 2); } if (allZones.length === 1 && allZones[0].name === zone) { // Exact single zone — export to get ALL records (apex + subdomains) const bindText = await client.callRawTextGet("/api/zones/export", { zone, }); return JSON.stringify( { zone, records: parseBind(zone, bindText) }, null, 2 ); } // Multiple zones or parent-level query — export each and combine const results: unknown[] = []; for (const z of allZones) { try { const bindText = await client.callRawTextGet("/api/zones/export", { zone: z.name, }); results.push({ zone: z.name, records: parseBind(z.name, bindText) }); } catch (e) { results.push({ zone: z.name, error: String(e) }); } } return JSON.stringify( { totalZones: results.length, zones: results }, null, 2 ); }, - src/tools/records.ts:43-58 (schema)Input schema for dns_list_records: requires 'zone' (string), optional 'domain' (string).
inputSchema: { type: "object", properties: { zone: { type: "string", description: "Zone domain name (e.g. example.com). Can be a parent domain to list all subzones.", }, domain: { type: "string", description: "Optional specific domain to filter (e.g. www.example.com). Defaults to the zone name if omitted.", }, }, required: ["zone"], }, - src/tools/records.ts:33-34 (registration)The dns_list_records tool is registered as part of the recordTools array export in src/tools/records.ts.
export function recordTools(client: TechnitiumClient): ToolEntry[] { return [ - src/tools/index.ts:14-27 (registration)recordTools is included in the global getAllTools aggregation, which registers all tools.
export function getAllTools(client: TechnitiumClient): ToolEntry[] { return [ ...dashboardTools(client), ...dnsClientTools(client), ...zoneTools(client), ...recordTools(client), ...blockingTools(client), ...cacheTools(client), ...settingsTools(client), ...logTools(client), ...appTools(client), ...dnssecTools(client), ]; } - src/tools/records.ts:6-31 (helper)Helper function that parses BIND-format zone export text into structured record objects used by the handler.
function parseBind( zone: string, bindText: string ): Array<{ name: string; ttl: number; type: string; value: string }> { const records: Array<{ name: string; ttl: number; type: string; value: string }> = []; const origin = zone.endsWith(".") ? zone : zone + "."; for (const raw of bindText.split("\n")) { const line = raw.trim(); if (!line || line.startsWith(";") || line.startsWith("$")) continue; // Format: <name> <ttl> IN <type> <rdata...> const parts = line.split(/\s+/); if (parts.length < 5) continue; const [name, ttlStr, , type, ...rdata] = parts; const ttl = parseInt(ttlStr, 10); if (isNaN(ttl)) continue; const fqdn = name === "@" ? zone : name.includes(".") ? name.replace(/\.$/, "") : `${name}.${zone}`; records.push({ name: fqdn, ttl, type, value: rdata.join(" ") }); } return records; }