get_ccaa_deductions
Retrieve tax deductions for a specific Spanish autonomous community, including amounts, limits, requirements, and legal sources. Filter results by keywords like 'alquiler' or 'vivienda' to find relevant deductions.
Instructions
Returns all tax deductions available in a specific Spanish autonomous community (CCAA). Covers all 17 CCAA + Ceuta + Melilla. Each deduction includes amount/percentage, limits, income requirements, and legal source. Use common names: 'baleares', 'madrid', 'cataluna', 'valencia', etc. Source: AEAT Manual Practico Renta 2025, Parte 2 — Deducciones Autonomicas.
Input Schema
TableJSON Schema
| Name | Required | Description | Default |
|---|---|---|---|
| ccaa | Yes | Autonomous community name (e.g., 'baleares', 'madrid', 'cataluna', 'valencia', 'andalucia') | |
| query | No | Optional keyword to filter deductions (e.g., 'alquiler', 'hijo', 'vivienda', 'donacion') |
Implementation Reference
- src/tools/get_ccaa_deductions.ts:85-151 (handler)The handler logic for the 'get_ccaa_deductions' tool, which processes input parameters, loads regional data, filters it, and returns the result.
async ({ ccaa, query }) => { const data = loadAllCcaa(); if (Object.keys(data).length === 0) { return { content: [ { type: "text" as const, text: JSON.stringify({ error: "no_data", message: "CCAA deductions data not available.", }), }, ], }; } const key = CCAA_ALIASES[ccaa.toLowerCase().replace(/[\s-]/g, "_")] ?? ccaa.toLowerCase().replace(/[\s-]/g, "_"); const ccaaData = data[key]; if (!ccaaData) { const available = Object.keys(data).join(", "); return { content: [ { type: "text" as const, text: JSON.stringify({ error: "not_found", message: `CCAA '${ccaa}' not found. Available: ${available}`, suggestion: "Try common names: baleares, madrid, cataluna, valencia, andalucia", }), }, ], }; } let deductions = ccaaData.deductions || []; if (query) { const keywords = query.toLowerCase().split(/\s+/).filter((k: string) => k.length >= 2); deductions = deductions.filter((d: any) => { const text = JSON.stringify(d).toLowerCase(); return keywords.every((kw: string) => text.includes(kw)); }); } return { content: [ { type: "text" as const, text: JSON.stringify( { ccaa: ccaaData.name || key, year: 2025, total_deductions: deductions.length, query: query ?? null, deductions, disclaimer: "Informational only. Does not constitute tax advice.", }, null, 2 ), }, ], }; } ); - The Zod schema validation for the 'get_ccaa_deductions' tool input.
{ ccaa: z .string() .min(2) .describe( "Autonomous community name (e.g., 'baleares', 'madrid', 'cataluna', 'valencia', 'andalucia')" ), query: z .string() .optional() .describe( "Optional keyword to filter deductions (e.g., 'alquiler', 'hijo', 'vivienda', 'donacion')" ), }, - src/tools/get_ccaa_deductions.ts:63-152 (registration)The registration of the 'get_ccaa_deductions' tool on the McpServer.
export function registerCcaaDeductionsTool(server: McpServer) { server.tool( "get_ccaa_deductions", "Returns all tax deductions available in a specific Spanish autonomous community (CCAA). " + "Covers all 17 CCAA + Ceuta + Melilla. Each deduction includes amount/percentage, " + "limits, income requirements, and legal source. " + "Use common names: 'baleares', 'madrid', 'cataluna', 'valencia', etc. " + "Source: AEAT Manual Practico Renta 2025, Parte 2 — Deducciones Autonomicas.", { ccaa: z .string() .min(2) .describe( "Autonomous community name (e.g., 'baleares', 'madrid', 'cataluna', 'valencia', 'andalucia')" ), query: z .string() .optional() .describe( "Optional keyword to filter deductions (e.g., 'alquiler', 'hijo', 'vivienda', 'donacion')" ), }, async ({ ccaa, query }) => { const data = loadAllCcaa(); if (Object.keys(data).length === 0) { return { content: [ { type: "text" as const, text: JSON.stringify({ error: "no_data", message: "CCAA deductions data not available.", }), }, ], }; } const key = CCAA_ALIASES[ccaa.toLowerCase().replace(/[\s-]/g, "_")] ?? ccaa.toLowerCase().replace(/[\s-]/g, "_"); const ccaaData = data[key]; if (!ccaaData) { const available = Object.keys(data).join(", "); return { content: [ { type: "text" as const, text: JSON.stringify({ error: "not_found", message: `CCAA '${ccaa}' not found. Available: ${available}`, suggestion: "Try common names: baleares, madrid, cataluna, valencia, andalucia", }), }, ], }; } let deductions = ccaaData.deductions || []; if (query) { const keywords = query.toLowerCase().split(/\s+/).filter((k: string) => k.length >= 2); deductions = deductions.filter((d: any) => { const text = JSON.stringify(d).toLowerCase(); return keywords.every((kw: string) => text.includes(kw)); }); } return { content: [ { type: "text" as const, text: JSON.stringify( { ccaa: ccaaData.name || key, year: 2025, total_deductions: deductions.length, query: query ?? null, deductions, disclaimer: "Informational only. Does not constitute tax advice.", }, null, 2 ), }, ], }; } ); } - Helper function to load and cache CCAA (autonomous community) data from JSON files.
function loadAllCcaa(): Record<string, any> { if (allCcaaData) return allCcaaData; allCcaaData = {}; const ccaaDir = join(__dirname, "..", "data", "irpf", "ccaa"); try { for (const f of readdirSync(ccaaDir)) { if (f.endsWith(".json")) { const content = JSON.parse(readFileSync(join(ccaaDir, f), "utf-8")); if (content.ccaa) { Object.assign(allCcaaData, content.ccaa); } } } } catch { // Directory might not exist } return allCcaaData; }