Skip to main content
Glama
iMark21

AEAT MCP Server

by iMark21

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
NameRequiredDescriptionDefault
ccaaYesAutonomous community name (e.g., 'baleares', 'madrid', 'cataluna', 'valencia', 'andalucia')
queryNoOptional keyword to filter deductions (e.g., 'alquiler', 'hijo', 'vivienda', 'donacion')

Implementation Reference

  • 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')"
        ),
    },
  • 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;
    }
Behavior3/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

With no annotations provided, the description carries the full burden of behavioral disclosure. It describes what the tool returns (deductions with specific fields) and mentions the data source (AEAT Manual Practico Renta 2025), which adds useful context. However, it doesn't disclose potential behavioral traits like rate limits, error conditions, or response format details that would be helpful for an agent.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is efficiently structured in three sentences: purpose statement, scope/details, and usage/source information. Every sentence adds value with no wasted words, and key information is front-loaded.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For a read-only data retrieval tool with 2 parameters and no output schema, the description provides good context about what data is returned and its source. However, without annotations or output schema, it could benefit from more detail about response structure or potential limitations to be fully complete.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is 100%, so the schema already documents both parameters thoroughly. The description adds marginal value by providing example CCAA names and mentioning the optional query parameter can filter by keywords like 'alquiler' or 'hijo', but doesn't significantly enhance the parameter understanding beyond what the schema provides.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description clearly states the verb ('Returns') and resource ('all tax deductions available in a specific Spanish autonomous community'), specifying the scope (17 CCAA + Ceuta + Melilla) and content details (amount/percentage, limits, income requirements, legal source). It distinguishes from siblings by focusing on autonomous community deductions rather than calendars, brackets, or other tax data.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The description provides clear context for when to use this tool (to get deductions for a specific CCAA) and includes usage guidance ('Use common names: ...'). However, it doesn't explicitly state when NOT to use it or name specific alternatives among the sibling tools, though the distinct purpose implies differentiation.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

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/iMark21/aeat-mcp'

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