Koskamo

AfAMax Real Estate Appraisal MCP

This MCP server provides tools for German real estate depreciation calculations (AfA), purchase price allocation (Kaufpreisaufteilung), and accessing appraisal services. It allows agents to calculate building depreciation rates, split purchase prices into land and building components, retrieve appraisal pricing, and book initial consultation appointments with certified experts.

Endpoint and access

No sign-in to connect and list tools. Individual tools may still need a vendor account, credentials, or permissions; check the documented prerequisites.

AfAMax Real Estate Appraisal MCP logo, by AfAMaxVendor evidenceStreamable HTTPNo sign-inEndpoint checked 2026-11-06Operated by AfAMax
MCP endpoint (Streamable HTTP)
https://mcp.rundum.immo/mcp
Vendor documentation

What its tools do

5 tools, grouped by the hints the server advertises. Hints are self-declared, not verified behavior.

Can change data (1)

5 of 5 have a description · 5 of 5 declare behavior hints · 5 of 5 with parameters document them all

Checks and signals

Each line is separate evidence, not a trust score.

  • Passed Endpoint answered the live check ·
  • Passed Official MCP Registry namespace is tied to rundum.immo ·
  • Passed Endpoint is on the registry namespace domain ·
  • Availability 1 of 1 checks passed in 30 days

What you can do with it

  • Calculate German property depreciation (AfA) and remaining useful life
  • Allocate purchase price between land and building for tax purposes
  • Retrieve current prices for certified real estate appraisals
  • Book initial consultation slots with certified valuation experts

Source and maintenance

Vendor evidenceRegistry 0.2.2
Maintenance checked

Protocol and capabilities

Server
immo.rundum/real-estate-appraisal 0.2.2
MCP protocol negotiated in check
2025-11-25
Tools
5 advertised
Resources
Not advertised
Resource templates
Not advertised
Prompts
Not advertised
Server-advertised capabilities
{
  "tools": {
    "listChanged": true
  }
}

Server-provided instructions

Untrusted server output shown for inspection. It is not Koskamo guidance and is excluded from knowledge search.

AfAMax tools for German residential rental property (vermietete Immobilien): depreciation (AfA / Gebäudeabschreibung), remaining useful life (Restnutzungsdauer), purchase-price allocation (Kaufpreisaufteilung), appraisal prices and a free initial call. Most users are German-speaking and ask colloquially. Domain: under § 7 Abs. 4 EStG a rental building is depreciated at a flat statutory rate — usually 2 % a year (3 % if completed from 2023, 2.5 % if completed before 1925). If the building's actual remaining useful life is shorter (verkürzte Restnutzungsdauer, § 7 Abs. 4 Satz 2 EStG), a higher rate is possible; a Restnutzungsdauergutachten is the usual proof. Only the building is depreciable, never the land, so the land/building split sets the depreciation base. Which tool: - Faster or higher depreciation, "mehr als 2 % AfA", "schneller abschreiben", an old or unrenovated building, a shorter useful life, or whether a Restnutzungsdauergutachten pays off → calculate_property_depreciation. It compares the statutory rate with the remaining-useful-life rate, estimates tax savings and returns appraisalWorthwhile. - Land vs. building share, Gebäudeanteil, Bodenrichtwert, a disputed Finanzamt split → calculate_purchase_price_allocation. - What a Gutachten costs → get_price_by_product (prices only; it does not say whether an appraisal pays off). - Talking to an expert → get_available_appointments, then book_appointment. A typical flow: allocation → depreciation → if appraisalWorthwhile, price the rnd product → offer the initial call. Out of scope: property outside Germany, depreciation of anything other than buildings (cars, equipment, solar systems), other taxes (Grunderwerbsteuer, Grundsteuer, Erbschaftsteuer, capital gains), tenancy law and financing. Results are indicative and never replace tax or legal advice.

Tools

5 advertised

calculate_property_depreciation — Calculate German property depreciation (AfA) & Restnutzungsdauer
Advertised by the server during the last successful anonymous check.
Advertised read-only

Calculate indicative German property depreciation (AfA / Gebäudeabschreibung) and the building's remaining useful life (Restnutzungsdauer) for residential rental property through AfAMax. Use this when a user wants to calculate AfA, asks whether a German rental property can be depreciated faster than the statutory 2 % under § 7 Abs. 4 EStG, mentions a shorter actual useful life (verkürzte Restnutzungsdauer), or wants to know whether a Restnutzungsdauergutachten would pay off — also when they only describe an old or unrenovated building and ask what they can deduct. The result compares the remaining-useful-life rate with the statutory rate, gives annual/monthly AfA and estimated tax savings, and states whether an appraisal looks worthwhile. For apartment buildings, pass figures for the whole building or calculate units separately. Ask for all eight modernization component states whenever possible: omitting them assumes no modernization and produces the highest possible remaining-useful-life benefit. The response attribution link opens the same calculation in the AfAMax calculator with these inputs already filled in; cite it as the source when reporting the result. The result is non-binding and does not replace tax or legal advice.

calculate_property_depreciation input schema
{
  "type": "object",
  "$schema": "https://json-schema.org/draft/2020-12/schema",
  "required": [
    "propertyType",
    "constructionYear",
    "floorArea"
  ],
  "properties": {
    "locale": {
      "anyOf": [
        {
          "enum": [
            "de",
            "en"
          ],
          "type": "string"
        },
        {
          "type": "null"
        }
      ],
      "description": "Language for upstream explanations; defaults to German."
    },
    "taxRate": {
      "anyOf": [
        {
          "type": "number",
          "maximum": 0.6,
          "exclusiveMinimum": 0
        },
        {
          "type": "null"
        }
      ],
      "description": "Personal marginal income tax rate as a decimal, e.g. 0.42. / Grenzsteuersatz."
    },
    "landArea": {
      "anyOf": [
        {
          "type": "number",
          "minimum": 0
        },
        {
          "type": "null"
        }
      ],
      "description": "Land area in square metres. / Grundstücksfläche."
    },
    "floorArea": {
      "type": "number",
      "maximum": 100000,
      "minimum": 10,
      "description": "Living or usable floor area in square metres. / Wohn- bzw. Nutzfläche."
    },
    "propertyType": {
      "enum": [
        "CONDOMINIUM",
        "SINGLE_FAMILY_HOUSE",
        "TWO_FAMILY_HOUSE",
        "ROW_HOUSE",
        "SEMI_DETACHED",
        "APARTMENT_BUILDING",
        "RESIDENTIAL_COMMERCIAL_BUILDING"
      ],
      "type": "string",
      "description": "German residential property category. CONDOMINIUM = Eigentumswohnung, ROW_HOUSE = Reihenhaus, SEMI_DETACHED = Doppelhaushälfte, APARTMENT_BUILDING = Mehrfamilienhaus, RESIDENTIAL_COMMERCIAL_BUILDING = Wohn- und Geschäftshaus."
    },
    "modernization": {
      "anyOf": [
        {
          "type": "object",
          "properties": {
            "roof": {
              "enum": [
                "NOT_MODERNIZED",
                "SLIGHTLY_MODERNIZED",
                "PARTIALLY_MODERNIZED",
                "MOSTLY_MODERNIZED",
                "FULLY_MODERNIZED"
              ],
              "type": "string"
            },
            "heating": {
              "enum": [
                "NOT_MODERNIZED",
                "SLIGHTLY_MODERNIZED",
                "PARTIALLY_MODERNIZED",
                "MOSTLY_MODERNIZED",
                "FULLY_MODERNIZED"
              ],
              "type": "string"
            },
            "bathrooms": {
              "enum": [
                "NOT_MODERNIZED",
                "SLIGHTLY_MODERNIZED",
                "PARTIALLY_MODERNIZED",
                "MOSTLY_MODERNIZED",
                "FULLY_MODERNIZED"
              ],
              "type": "string"
            },
            "utilities": {
              "enum": [
                "NOT_MODERNIZED",
                "SLIGHTLY_MODERNIZED",
                "PARTIALLY_MODERNIZED",
                "MOSTLY_MODERNIZED",
                "FULLY_MODERNIZED"
              ],
              "type": "string"
            },
            "windowsDoors": {
              "enum": [
                "NOT_MODERNIZED",
                "SLIGHTLY_MODERNIZED",
                "PARTIALLY_MODERNIZED",
                "MOSTLY_MODERNIZED",
                "FULLY_MODERNIZED"
              ],
              "type": "string"
            },
            "interiorFitout": {
              "enum": [
                "NOT_MODERNIZED",
                "SLIGHTLY_MODERNIZED",
                "PARTIALLY_MODERNIZED",
                "MOSTLY_MODERNIZED",
                "FULLY_MODERNIZED"
              ],
              "type": "string"
            },
            "facadeInsulation": {
              "enum": [
                "NOT_MODERNIZED",
                "SLIGHTLY_MODERNIZED",
                "PARTIALLY_MODERNIZED",
                "MOSTLY_MODERNIZED",
                "FULLY_MODERNIZED"
              ],
              "type": "string"
            },
            "floorplanImprovement": {
              "enum": [
                "NOT_MODERNIZED",
                "SLIGHTLY_MODERNIZED",
                "PARTIALLY_MODERNIZED",
                "MOSTLY_MODERNIZED",
                "FULLY_MODERNIZED"
              ],
              "type": "string"
            }
          },
          "additionalProperties": false
        },
        {
          "type": "null"
        }
      ],
      "description": "Known state of eight modernization components (Modernisierungselemente): roof (Dach), facadeInsulation (Fassadendämmung), windowsDoors (Fenster und Außentüren), heating (Heizung), utilities (Leitungen), bathrooms (Bäder), interiorFitout (Innenausbau), floorplanImprovement (Grundrissverbesserung). Ask for all eight when possible."
    },
    "purchasePrice": {
      "anyOf": [
        {
          "type": "number",
          "minimum": 0
        },
        {
          "type": "null"
        }
      ],
      "description": "Total purchase price in EUR. / Kaufpreis."
    },
    "constructionYear": {
      "type": "integer",
      "maximum": 9007199254740991,
      "minimum": 1800,
      "description": "Original year of construction. / Baujahr."
    },
    "includedInventory": {
      "anyOf": [
        {
          "type": "number",
          "minimum": 0
        },
        {
          "type": "null"
        }
      ],
      "description": "Movable inventory included in the purchase price, in EUR."
    },
    "standardLandValue": {
      "anyOf": [
        {
          "type": "number",
          "minimum": 0
        },
        {
          "type": "null"
        }
      ],
      "description": "Standard land value in EUR per square metre. / Bodenrichtwert."
    },
    "coreRenovationYear": {
      "anyOf": [
        {
          "type": "integer",
          "maximum": 9007199254740991,
          "minimum": 1801
        },
        {
          "type": "null"
        }
      ],
      "description": "Year of a qualifying core renovation, if applicable. / Jahr einer Kernsanierung."
    },
    "modernizationLevel": {
      "anyOf": [
        {
          "enum": [
            "none",
            "partial",
            "extensive"
          ],
          "type": "string"
        },
        {
          "type": "null"
        }
      ],
      "description": "Coarse modernization level used when detailed component data is unavailable."
    },
    "purchaseRelatedCosts": {
      "anyOf": [
        {
          "type": "number",
          "minimum": 0
        },
        {
          "type": "null"
        }
      ],
      "description": "Purchase-related costs in EUR (land transfer tax, notary, land register, broker). / Kaufnebenkosten."
    }
  },
  "additionalProperties": false
}
calculate_property_depreciation output schema
{
  "type": "object",
  "$schema": "https://json-schema.org/draft/2020-12/schema",
  "required": [
    "calculationId",
    "input",
    "results",
    "assumptions",
    "attribution",
    "disclaimer",
    "meta"
  ],
  "properties": {
    "meta": {
      "type": "object",
      "required": [
        "apiVersion",
        "calculationMethod",
        "calculatedAt"
      ],
      "properties": {
        "apiVersion": {
          "type": "string"
        },
        "calculatedAt": {
          "type": "string",
          "format": "date-time",
          "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d:[0-5]\\d(?:\\.\\d+)?(?:Z))$"
        },
        "calculationMethod": {
          "type": "string"
        }
      },
      "additionalProperties": false
    },
    "input": {
      "type": "object",
      "required": [
        "propertyType",
        "constructionYear",
        "floorArea",
        "purchasePrice",
        "landArea",
        "standardLandValue",
        "includedInventory",
        "purchaseRelatedCosts",
        "coreRenovationYear",
        "taxRate",
        "locale",
        "modernization"
      ],
      "properties": {
        "locale": {
          "enum": [
            "de",
            "en"
          ],
          "type": "string"
        },
        "taxRate": {
          "type": "number"
        },
        "landArea": {
          "type": [
            "number",
            "null"
          ]
        },
        "floorArea": {
          "type": "number"
        },
        "propertyType": {
          "enum": [
            "CONDOMINIUM",
            "SINGLE_FAMILY_HOUSE",
            "TWO_FAMILY_HOUSE",
            "ROW_HOUSE",
            "SEMI_DETACHED",
            "APARTMENT_BUILDING",
            "RESIDENTIAL_COMMERCIAL_BUILDING"
          ],
          "type": "string"
        },
        "modernization": {
          "type": "object",
          "required": [
            "roof",
            "facadeInsulation",
            "windowsDoors",
            "heating",
            "utilities",
            "bathrooms",
            "interiorFitout",
            "floorplanImprovement"
          ],
          "properties": {
            "roof": {
              "enum": [
                "NOT_MODERNIZED",
                "SLIGHTLY_MODERNIZED",
                "PARTIALLY_MODERNIZED",
                "MOSTLY_MODERNIZED",
                "FULLY_MODERNIZED"
              ],
              "type": "string"
            },
            "heating": {
              "enum": [
                "NOT_MODERNIZED",
                "SLIGHTLY_MODERNIZED",
                "PARTIALLY_MODERNIZED",
                "MOSTLY_MODERNIZED",
                "FULLY_MODERNIZED"
              ],
              "type": "string"
            },
            "bathrooms": {
              "enum": [
                "NOT_MODERNIZED",
                "SLIGHTLY_MODERNIZED",
                "PARTIALLY_MODERNIZED",
                "MOSTLY_MODERNIZED",
                "FULLY_MODERNIZED"
              ],
              "type": "string"
            },
            "utilities": {
              "enum": [
                "NOT_MODERNIZED",
                "SLIGHTLY_MODERNIZED",
                "PARTIALLY_MODERNIZED",
                "MOSTLY_MODERNIZED",
                "FULLY_MODERNIZED"
              ],
              "type": "string"
            },
            "windowsDoors": {
              "enum": [
                "NOT_MODERNIZED",
                "SLIGHTLY_MODERNIZED",
                "PARTIALLY_MODERNIZED",
                "MOSTLY_MODERNIZED",
                "FULLY_MODERNIZED"
              ],
              "type": "string"
            },
            "interiorFitout": {
              "enum": [
                "NOT_MODERNIZED",
                "SLIGHTLY_MODERNIZED",
                "PARTIALLY_MODERNIZED",
                "MOSTLY_MODERNIZED",
                "FULLY_MODERNIZED"
              ],
              "type": "string"
            },
            "facadeInsulation": {
              "enum": [
                "NOT_MODERNIZED",
                "SLIGHTLY_MODERNIZED",
                "PARTIALLY_MODERNIZED",
                "MOSTLY_MODERNIZED",
                "FULLY_MODERNIZED"
              ],
              "type": "string"
            },
            "floorplanImprovement": {
              "enum": [
                "NOT_MODERNIZED",
                "SLIGHTLY_MODERNIZED",
                "PARTIALLY_MODERNIZED",
                "MOSTLY_MODERNIZED",
                "FULLY_MODERNIZED"
              ],
              "type": "string"
            }
          },
          "additionalProperties": false
        },
        "purchasePrice": {
          "type": [
            "number",
            "null"
          ]
        },
        "constructionYear": {
          "type": "integer",
          "maximum": 9007199254740991,
          "minimum": -9007199254740991
        },
        "includedInventory": {
          "type": [
            "number",
            "null"
          ]
        },
        "standardLandValue": {
          "type": [
            "number",
            "null"
          ]
        },
        "coreRenovationYear": {
          "anyOf": [
            {
              "type": "integer",
              "maximum": 9007199254740991,
              "minimum": -9007199254740991
            },
            {
              "type": "null"
            }
          ]
        },
        "purchaseRelatedCosts": {
          "type": [
            "number",
            "null"
          ]
        }
      },
      "additionalProperties": false
    },
    "results": {
      "type": "object",
      "required": [
        "afaRatePerYear",
        "defaultAfaRatePerYear",
        "annualAfaAmount",
        "defaultAfaAmount",
        "monthlyAfaAmount",
        "annualTaxSavings",
        "appraisalWorthwhile",
        "monthlyTaxSavings",
        "buildingValue",
        "buildingValueSource",
        "taxRate",
        "remainingUsefulLifeYears",
        "modernizationPointsUsed",
        "currency"
      ],
      "properties": {
        "taxRate": {
          "type": "number"
        },
        "currency": {
          "type": "string",
          "const": "EUR"
        },
        "buildingValue": {
          "type": "number",
          "description": "Depreciable building value in EUR (excluding land)."
        },
        "afaRatePerYear": {
          "type": "number",
          "description": "AfA rate per year from the estimated remaining useful life, as a decimal (0.0333 = 3.33 %)."
        },
        "annualAfaAmount": {
          "type": "number",
          "description": "Annual AfA in EUR at afaRatePerYear."
        },
        "annualTaxSavings": {
          "type": "number",
          "description": "Estimated income tax saved per year by annualAfaAmount at taxRate."
        },
        "defaultAfaAmount": {
          "type": "number",
          "description": "Annual AfA in EUR at the statutory rate."
        },
        "monthlyAfaAmount": {
          "type": "number"
        },
        "monthlyTaxSavings": {
          "type": "number"
        },
        "appraisalWorthwhile": {
          "type": "boolean",
          "description": "Whether the remaining-useful-life rate is high enough for a Restnutzungsdauergutachten to look worthwhile."
        },
        "buildingValueSource": {
          "enum": [
            "actual",
            "assumed"
          ],
          "type": "string"
        },
        "defaultAfaRatePerYear": {
          "type": "number",
          "description": "Statutory AfA rate under § 7 Abs. 4 EStG for comparison, as a decimal."
        },
        "modernizationPointsUsed": {
          "type": "number",
          "maximum": 20,
          "minimum": 0
        },
        "remainingUsefulLifeYears": {
          "type": "number",
          "description": "Estimated remaining useful life (Restnutzungsdauer) in years."
        }
      },
      "additionalProperties": false
    },
    "disclaimer": {
      "type": "string"
    },
    "assumptions": {
      "type": "object",
      "required": [
        "modernizationAssumedNone",
        "buildingValueAssumed",
        "taxRateAssumed"
      ],
      "properties": {
        "taxRateAssumed": {
          "type": "boolean"
        },
        "buildingValueAssumed": {
          "type": "boolean"
        },
        "modernizationAssumedNone": {
          "type": "boolean"
        }
      },
      "additionalProperties": false
    },
    "attribution": {
      "type": "object",
      "required": [
        "provider",
        "url",
        "label"
      ],
      "properties": {
        "url": {
          "type": "string",
          "format": "uri"
        },
        "label": {
          "type": "string"
        },
        "provider": {
          "enum": [
            "AfaMax",
            "AfAMax"
          ],
          "type": "string"
        }
      },
      "additionalProperties": false
    },
    "calculationId": {
      "type": "string",
      "minLength": 1
    }
  },
  "additionalProperties": false
}
calculate_property_depreciation annotations
{
  "readOnlyHint": true,
  "openWorldHint": false,
  "idempotentHint": true,
  "destructiveHint": false
}
calculate_purchase_price_allocation — Calculate German purchase price allocation
Advertised by the server during the last successful anonymous check.
Advertised read-only

Calculate a free, non-binding German property purchase-price allocation (Kaufpreisaufteilung) through AfAMax using the BMF Arbeitshilfe. Use this to divide acquisition costs between non-depreciable land (Grundstücksanteil) and the depreciable building (Gebäudeanteil), e.g. when a user asks how much of the price they may depreciate or wants to check the Finanzamt's split. Its depreciationBase is the base for the building's AfA. Inventory is deducted before allocation. A condominium requires both co-ownership values, and a residential/commercial building requires its commercial share category. Comparative valuation is unavailable because this public contract excludes surveyor-only factors. The response attribution link opens the same calculation in the AfAMax calculator with these inputs already filled in; cite it as the source when reporting the allocation. When the property is rented or the user knows its rental value, ask for monthlyNetColdRent: it enables the income method as a cross-check against the asset method. Ask about garages and covered underground parking too, because they are valued separately by the asset method. Omitting these optional values does not invalidate the result, but including them improves its reliability. The result does not replace tax or legal advice.

calculate_purchase_price_allocation input schema
{
  "type": "object",
  "$schema": "https://json-schema.org/draft/2020-12/schema",
  "required": [
    "propertyType",
    "totalPurchasePrice",
    "purchaseDate",
    "constructionYear",
    "floorArea",
    "landArea",
    "standardLandValue"
  ],
  "properties": {
    "locale": {
      "enum": [
        "de",
        "en"
      ],
      "type": "string",
      "default": "de",
      "description": "Language for the disclaimer and AfAMax attribution link. Defaults to German."
    },
    "garages": {
      "type": "integer",
      "maximum": 9007199254740991,
      "minimum": 0,
      "description": "Number of above-ground garages. Improves the asset-method allocation by valuing parking separately. Ask the user if the property includes garages."
    },
    "landArea": {
      "type": "number",
      "description": "Plot area in square metres.",
      "exclusiveMinimum": 0
    },
    "floorArea": {
      "type": "number",
      "description": "Living or usable floor area in square metres.",
      "exclusiveMinimum": 0
    },
    "propertyType": {
      "enum": [
        "CONDOMINIUM",
        "SINGLE_FAMILY_HOUSE",
        "TWO_FAMILY_HOUSE",
        "ROW_HOUSE",
        "SEMI_DETACHED",
        "APARTMENT_BUILDING",
        "RESIDENTIAL_COMMERCIAL_BUILDING"
      ],
      "type": "string",
      "description": "German residential property category."
    },
    "purchaseDate": {
      "type": "string",
      "description": "Date of the notarized purchase contract in YYYY-MM-DD format; must be from 1990-01-01 through today."
    },
    "commercialShare": {
      "enum": [
        "under_50",
        "over_50"
      ],
      "type": "string",
      "description": "Required for RESIDENTIAL_COMMERCIAL_BUILDING: whether the commercial share is under or over 50%."
    },
    "constructionYear": {
      "type": "integer",
      "maximum": 9007199254740991,
      "minimum": 1800,
      "description": "Original construction year; it cannot be later than the purchase year."
    },
    "includedInventory": {
      "type": "number",
      "minimum": 0,
      "description": "Movable inventory included in the purchase price, in EUR. It is deducted before allocation."
    },
    "standardLandValue": {
      "type": "number",
      "description": "Standard land value (Bodenrichtwert) in EUR per square metre.",
      "exclusiveMinimum": 0
    },
    "monthlyNetColdRent": {
      "type": "number",
      "minimum": 0,
      "description": "Monthly net cold rent (base rent excluding utilities, in EUR). Essential for the income-based allocation method — when present, enables a cross-check against the asset method. Ask the user if the property is rented or if they know the rental value."
    },
    "totalPurchasePrice": {
      "type": "number",
      "description": "Total notarized purchase price in EUR.",
      "exclusiveMinimum": 0
    },
    "coOwnershipNumerator": {
      "type": "number",
      "description": "Co-ownership numerator (Miteigentumsanteil); required with the denominator for a condominium.",
      "exclusiveMinimum": 0
    },
    "purchaseRelatedCosts": {
      "type": "number",
      "minimum": 0,
      "description": "Land transfer tax, notary, land-register, and broker costs in EUR. Defaults to 0."
    },
    "coOwnershipDenominator": {
      "type": "number",
      "description": "Co-ownership denominator; required with the numerator for a condominium.",
      "exclusiveMinimum": 0
    },
    "undergroundParkingSpaces": {
      "type": "integer",
      "maximum": 9007199254740991,
      "minimum": 0,
      "description": "Number of covered underground parking spaces. Improves the asset-method allocation by valuing parking separately. Ask the user if the property includes underground parking."
    }
  },
  "additionalProperties": false
}
calculate_purchase_price_allocation output schema
{
  "type": "object",
  "$schema": "https://json-schema.org/draft/2020-12/schema",
  "required": [
    "calculationId",
    "input",
    "applied",
    "methods",
    "skipped",
    "degenerate",
    "assetMethodDefaults",
    "attribution",
    "disclaimer",
    "meta"
  ],
  "properties": {
    "meta": {
      "type": "object",
      "required": [
        "apiVersion",
        "calculationMethod",
        "calculatedAt"
      ],
      "properties": {
        "apiVersion": {
          "type": "string"
        },
        "calculatedAt": {
          "type": "string",
          "format": "date-time",
          "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d:[0-5]\\d(?:\\.\\d+)?(?:Z))$"
        },
        "calculationMethod": {
          "type": "string"
        }
      },
      "additionalProperties": false
    },
    "input": {
      "type": "object",
      "required": [
        "propertyType",
        "totalPurchasePrice",
        "purchasePrice",
        "purchaseRelatedCosts",
        "includedInventory",
        "purchaseDate",
        "constructionYear",
        "floorArea",
        "landArea",
        "standardLandValue",
        "commercialShare",
        "coOwnershipNumerator",
        "coOwnershipDenominator",
        "garages",
        "undergroundParkingSpaces",
        "monthlyNetColdRent",
        "locale"
      ],
      "properties": {
        "locale": {
          "enum": [
            "de",
            "en"
          ],
          "type": "string"
        },
        "garages": {
          "type": "number"
        },
        "landArea": {
          "type": "number"
        },
        "floorArea": {
          "type": "number"
        },
        "propertyType": {
          "enum": [
            "CONDOMINIUM",
            "SINGLE_FAMILY_HOUSE",
            "TWO_FAMILY_HOUSE",
            "ROW_HOUSE",
            "SEMI_DETACHED",
            "APARTMENT_BUILDING",
            "RESIDENTIAL_COMMERCIAL_BUILDING"
          ],
          "type": "string"
        },
        "purchaseDate": {
          "type": "string"
        },
        "purchasePrice": {
          "type": "number",
          "description": "Property price after deducting included inventory."
        },
        "commercialShare": {
          "anyOf": [
            {
              "enum": [
                "under_50",
                "over_50"
              ],
              "type": "string"
            },
            {
              "type": "null"
            }
          ]
        },
        "constructionYear": {
          "type": "number"
        },
        "includedInventory": {
          "type": "number"
        },
        "standardLandValue": {
          "type": "number"
        },
        "monthlyNetColdRent": {
          "type": [
            "number",
            "null"
          ]
        },
        "totalPurchasePrice": {
          "type": "number"
        },
        "coOwnershipNumerator": {
          "type": [
            "number",
            "null"
          ]
        },
        "purchaseRelatedCosts": {
          "type": "number"
        },
        "coOwnershipDenominator": {
          "type": [
            "number",
            "null"
          ]
        },
        "undergroundParkingSpaces": {
          "type": "number"
        }
      },
      "additionalProperties": false
    },
    "applied": {
      "type": "object",
      "required": [
        "method",
        "landValue",
        "buildingValue",
        "totalValue",
        "buildingShare",
        "totalAcquisitionCost",
        "depreciationBase",
        "landAllocation",
        "currency"
      ],
      "properties": {
        "method": {
          "enum": [
            "comparative",
            "income",
            "asset"
          ],
          "type": "string"
        },
        "currency": {
          "type": "string",
          "const": "EUR"
        },
        "landValue": {
          "type": "number"
        },
        "totalValue": {
          "type": "number"
        },
        "buildingShare": {
          "type": "number"
        },
        "buildingValue": {
          "type": "number"
        },
        "landAllocation": {
          "type": "number"
        },
        "depreciationBase": {
          "type": "number"
        },
        "totalAcquisitionCost": {
          "type": "number"
        }
      },
      "additionalProperties": false
    },
    "methods": {
      "type": "array",
      "items": {
        "type": "object",
        "required": [
          "method",
          "landValue",
          "buildingValue",
          "totalValue",
          "buildingShare",
          "totalAcquisitionCost",
          "depreciationBase",
          "landAllocation",
          "currency"
        ],
        "properties": {
          "method": {
            "enum": [
              "comparative",
              "income",
              "asset"
            ],
            "type": "string"
          },
          "currency": {
            "type": "string",
            "const": "EUR"
          },
          "landValue": {
            "type": "number"
          },
          "totalValue": {
            "type": "number"
          },
          "buildingShare": {
            "type": "number"
          },
          "buildingValue": {
            "type": "number"
          },
          "landAllocation": {
            "type": "number"
          },
          "depreciationBase": {
            "type": "number"
          },
          "totalAcquisitionCost": {
            "type": "number"
          }
        },
        "additionalProperties": false
      }
    },
    "skipped": {
      "type": "array",
      "items": {
        "type": "object",
        "required": [
          "method",
          "missing"
        ],
        "properties": {
          "method": {
            "enum": [
              "comparative",
              "income",
              "asset"
            ],
            "type": "string"
          },
          "missing": {
            "type": "array",
            "items": {
              "type": "string"
            }
          }
        },
        "additionalProperties": false
      }
    },
    "degenerate": {
      "type": "array",
      "items": {
        "type": "object",
        "required": [
          "method",
          "reason"
        ],
        "properties": {
          "method": {
            "enum": [
              "comparative",
              "income",
              "asset"
            ],
            "type": "string"
          },
          "reason": {
            "enum": [
              "operating-costs-exceed-rent",
              "income-below-land-interest",
              "no-building-value"
            ],
            "type": "string"
          }
        },
        "additionalProperties": false
      }
    },
    "disclaimer": {
      "type": "string"
    },
    "attribution": {
      "type": "object",
      "required": [
        "provider",
        "url",
        "label"
      ],
      "properties": {
        "url": {
          "type": "string",
          "format": "uri"
        },
        "label": {
          "type": "string"
        },
        "provider": {
          "enum": [
            "AfaMax",
            "AfAMax"
          ],
          "type": "string"
        }
      },
      "additionalProperties": false
    },
    "calculationId": {
      "type": "string",
      "minLength": 1
    },
    "assetMethodDefaults": {
      "type": "object",
      "required": [
        "standardLevel",
        "regionalFactor",
        "marketAdjustmentFactor"
      ],
      "properties": {
        "standardLevel": {
          "type": "number"
        },
        "regionalFactor": {
          "type": "number",
          "const": 1
        },
        "marketAdjustmentFactor": {
          "type": "number",
          "const": 1
        }
      },
      "additionalProperties": false
    }
  },
  "additionalProperties": false
}
calculate_purchase_price_allocation annotations
{
  "readOnlyHint": true,
  "openWorldHint": false,
  "idempotentHint": true,
  "destructiveHint": false
}
get_price_by_product — Get the price of an AfAMax appraisal product
Advertised by the server during the last successful anonymous check.
Advertised read-only

Returns AfAMax's current list price in EUR, incl. German VAT (19%), for one product — Restnutzungsdauergutachten (rnd), Wertgutachten (kurzgutachten), Verkehrswertgutachten (vollgutachten), Kaufpreisaufteilung, Versetzbarkeitsgutachten or AfA-Verteidigung (afa_verteidigung, a second remaining-useful-life appraisal to defend an AfA the tax office rejected) — including the options the customer picks when ordering: property inspection (exterior or on-site), express processing and, for multi-unit buildings, a per-flat price. price.totalPrice is the sum; surchargeTable lists every option so alternatives can be compared without another call. Discount codes are not applied, and the price shown when ordering is binding — say so when quoting. This tool only quotes prices: to estimate whether a Restnutzungsdauergutachten would pay off, use calculate_property_depreciation. The response attribution links to the product page; cite it as the source when reporting the price.

get_price_by_product input schema
{
  "type": "object",
  "$schema": "https://json-schema.org/draft/2020-12/schema",
  "required": [
    "product"
  ],
  "properties": {
    "locale": {
      "enum": [
        "de",
        "en"
      ],
      "type": "string",
      "default": "de",
      "description": "Language of labels and of the link handed back. Match the user's language."
    },
    "product": {
      "enum": [
        "rnd",
        "kurzgutachten",
        "vollgutachten",
        "kaufpreisaufteilung",
        "versetzbarkeitsgutachten",
        "afa_verteidigung"
      ],
      "type": "string",
      "description": "Which AfAMax product to price. `rnd` — Restnutzungsdauergutachten / remaining-useful-life appraisal, the basis for a higher AfA rate. `kurzgutachten` — Wertgutachten / short value appraisal. `vollgutachten` — Verkehrswertgutachten / full market-value appraisal (§ 194 BauGB). `kaufpreisaufteilung` — Kaufpreisaufteilung / purchase-price allocation report (land vs. building). `versetzbarkeitsgutachten` — Versetzbarkeitsgutachten / relocatability certificate for tiny houses, mobile homes, modular units and containers. `afa_verteidigung` — AfA-Verteidigung / second remaining-useful-life appraisal that defends an AfA the tax office rejected."
    },
    "viewingType": {
      "enum": [
        "none",
        "exterior",
        "interior_exterior"
      ],
      "type": "string",
      "default": "none",
      "description": "Property inspection: `none` (remote, default), `exterior` (outside only / Außenbesichtigung) or `interior_exterior` (on-site, inside and outside / Innen- und Außenbesichtigung). Each adds a surcharge."
    },
    "propertyType": {
      "enum": [
        "CONDOMINIUM",
        "SINGLE_FAMILY_HOUSE",
        "TWO_FAMILY_HOUSE",
        "ROW_HOUSE",
        "SEMI_DETACHED",
        "APARTMENT_BUILDING",
        "RESIDENTIAL_COMMERCIAL_BUILDING"
      ],
      "type": "string",
      "description": "Optional. Together with totalFlatsCount, a two-family, apartment or mixed-use building with more than one flat adds a per-flat price."
    },
    "expressDelivery": {
      "type": "boolean",
      "default": false,
      "description": "Express processing (3-5 business days / Expressbearbeitung). Adds a surcharge unless a free-express promotion is running."
    },
    "totalFlatsCount": {
      "type": "integer",
      "maximum": 1000,
      "minimum": 1,
      "description": "Optional. Number of flats in the building / Anzahl Wohneinheiten."
    }
  },
  "additionalProperties": false
}
get_price_by_product output schema
{
  "type": "object",
  "$schema": "https://json-schema.org/draft/2020-12/schema",
  "required": [
    "quoteId",
    "product",
    "productLabel",
    "currency",
    "input",
    "price",
    "surchargeTable",
    "attribution",
    "disclaimer",
    "meta"
  ],
  "properties": {
    "meta": {
      "type": "object",
      "required": [
        "apiVersion",
        "generatedAt"
      ],
      "properties": {
        "apiVersion": {
          "type": "string"
        },
        "generatedAt": {
          "type": "string",
          "format": "date-time",
          "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d:[0-5]\\d(?:\\.\\d+)?(?:Z))$"
        }
      },
      "additionalProperties": false
    },
    "input": {
      "type": "object",
      "required": [
        "viewingType",
        "expressDelivery",
        "propertyType",
        "totalFlatsCount"
      ],
      "properties": {
        "viewingType": {
          "enum": [
            "none",
            "exterior",
            "interior_exterior"
          ],
          "type": "string"
        },
        "propertyType": {
          "anyOf": [
            {
              "enum": [
                "CONDOMINIUM",
                "SINGLE_FAMILY_HOUSE",
                "TWO_FAMILY_HOUSE",
                "ROW_HOUSE",
                "SEMI_DETACHED",
                "APARTMENT_BUILDING",
                "RESIDENTIAL_COMMERCIAL_BUILDING"
              ],
              "type": "string"
            },
            {
              "type": "null"
            }
          ]
        },
        "expressDelivery": {
          "type": "boolean"
        },
        "totalFlatsCount": {
          "type": [
            "number",
            "null"
          ]
        }
      },
      "additionalProperties": false
    },
    "price": {
      "type": "object",
      "required": [
        "basePrice",
        "viewingSurcharge",
        "expressSurcharge",
        "freeExpressPromotionApplied",
        "additionalPricePerUnit",
        "additionalUnitsPrice",
        "totalPrice",
        "vatIncluded",
        "vatRate",
        "totalNetPrice"
      ],
      "properties": {
        "vatRate": {
          "type": "number",
          "description": "The German VAT rate included in the amounts, in percent."
        },
        "basePrice": {
          "type": "number"
        },
        "totalPrice": {
          "type": "number",
          "description": "Sum of all amounts above. Every amount in `price` is gross, incl. German VAT."
        },
        "vatIncluded": {
          "type": "boolean",
          "const": true
        },
        "totalNetPrice": {
          "type": "number"
        },
        "expressSurcharge": {
          "type": "number"
        },
        "viewingSurcharge": {
          "type": "number"
        },
        "additionalUnitsPrice": {
          "type": "number"
        },
        "additionalPricePerUnit": {
          "type": "number"
        },
        "freeExpressPromotionApplied": {
          "type": "boolean"
        }
      },
      "additionalProperties": false
    },
    "product": {
      "enum": [
        "rnd",
        "kurzgutachten",
        "vollgutachten",
        "kaufpreisaufteilung",
        "versetzbarkeitsgutachten",
        "afa_verteidigung"
      ],
      "type": "string"
    },
    "quoteId": {
      "type": "string",
      "minLength": 1
    },
    "currency": {
      "type": "string",
      "const": "EUR"
    },
    "disclaimer": {
      "type": "string"
    },
    "attribution": {
      "type": "object",
      "required": [
        "provider",
        "url",
        "label"
      ],
      "properties": {
        "url": {
          "type": "string",
          "format": "uri"
        },
        "label": {
          "type": "string"
        },
        "provider": {
          "enum": [
            "AfaMax",
            "AfAMax"
          ],
          "type": "string"
        }
      },
      "additionalProperties": false
    },
    "productLabel": {
      "type": "string"
    },
    "surchargeTable": {
      "type": "object",
      "required": [
        "exteriorViewing",
        "interiorExteriorViewing",
        "express",
        "perAdditionalFlat"
      ],
      "properties": {
        "express": {
          "type": "number"
        },
        "exteriorViewing": {
          "type": "number"
        },
        "perAdditionalFlat": {
          "type": "number"
        },
        "interiorExteriorViewing": {
          "type": "number"
        }
      },
      "additionalProperties": false
    }
  },
  "additionalProperties": false
}
get_price_by_product annotations
{
  "readOnlyHint": true,
  "openWorldHint": false,
  "idempotentHint": true,
  "destructiveHint": false
}
get_available_appointments — List free AfAMax initial-call appointment slots
Advertised by the server during the last successful anonymous check.
Advertised read-only

Lists open slots for a free, non-binding 15-minute initial phone call with the AfAMax team (Erstgespräch), on weekdays in the Europe/Berlin time zone, grouped by day. Each day lists a sample spread across the day (maxSlotsPerDay, default 8) and its freeSlotCount; for a specific time, call again for that day with days: 1 and maxSlotsPerDay: 32. Show the user the day and localTime; to book one, pass its startDateTime unchanged to book_appointment. Slots are live and can be taken at any time, so re-check rather than reusing an old list. The response attribution links to the contact page, where the user can also book directly.

get_available_appointments input schema
{
  "type": "object",
  "$schema": "https://json-schema.org/draft/2020-12/schema",
  "properties": {
    "days": {
      "type": "integer",
      "maximum": 21,
      "minimum": 1,
      "description": "How many calendar days to look ahead (1-21, default 7). / Anzahl Tage."
    },
    "from": {
      "type": "string",
      "format": "date-time",
      "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d:[0-5]\\d(?:\\.\\d+)?(?:Z|([+-](?:[01]\\d|2[0-3]):[0-5]\\d)))$",
      "description": "ISO 8601 date-time to start looking from. Defaults to now. / Frühester Zeitpunkt."
    },
    "locale": {
      "enum": [
        "de",
        "en"
      ],
      "type": "string",
      "default": "de",
      "description": "Language of the link handed back and the response labels. Match the user's language (most users are German-speaking)."
    },
    "maxSlotsPerDay": {
      "type": "integer",
      "maximum": 32,
      "minimum": 1,
      "description": "How many slots to list per day (1-32, default 8), spread evenly across the day. When the user wants a specific time, call again for that day with `days: 1` and `maxSlotsPerDay: 32`."
    }
  },
  "additionalProperties": false
}
get_available_appointments output schema
{
  "type": "object",
  "$schema": "https://json-schema.org/draft/2020-12/schema",
  "required": [
    "requestId",
    "appointmentType",
    "description",
    "days",
    "timeZone",
    "durationMinutes",
    "attribution",
    "meta"
  ],
  "properties": {
    "days": {
      "type": "array",
      "items": {
        "type": "object",
        "required": [
          "date",
          "weekday",
          "freeSlotCount",
          "slots"
        ],
        "properties": {
          "date": {
            "type": "string",
            "description": "Date in Europe/Berlin, YYYY-MM-DD."
          },
          "slots": {
            "type": "array",
            "items": {
              "type": "object",
              "required": [
                "startDateTime",
                "localTime"
              ],
              "properties": {
                "localTime": {
                  "type": "string",
                  "description": "Start time in Europe/Berlin, HH:mm — show this to the user."
                },
                "startDateTime": {
                  "type": "string",
                  "format": "date-time",
                  "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d:[0-5]\\d(?:\\.\\d+)?(?:Z))$",
                  "description": "Slot start in UTC — pass this unchanged to book_appointment."
                }
              },
              "additionalProperties": false
            }
          },
          "weekday": {
            "type": "string"
          },
          "freeSlotCount": {
            "type": "number",
            "description": "All free slots that day — can exceed `slots`, which is capped by maxSlotsPerDay."
          }
        },
        "additionalProperties": false
      }
    },
    "meta": {
      "type": "object",
      "required": [
        "apiVersion",
        "generatedAt"
      ],
      "properties": {
        "apiVersion": {
          "type": "string"
        },
        "generatedAt": {
          "type": "string",
          "format": "date-time",
          "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d:[0-5]\\d(?:\\.\\d+)?(?:Z))$"
        }
      },
      "additionalProperties": false
    },
    "timeZone": {
      "type": "string"
    },
    "requestId": {
      "type": "string",
      "minLength": 1
    },
    "attribution": {
      "type": "object",
      "required": [
        "provider",
        "url",
        "label"
      ],
      "properties": {
        "url": {
          "type": "string",
          "format": "uri"
        },
        "label": {
          "type": "string"
        },
        "provider": {
          "enum": [
            "AfaMax",
            "AfAMax"
          ],
          "type": "string"
        }
      },
      "additionalProperties": false
    },
    "description": {
      "type": "string"
    },
    "appointmentType": {
      "type": "string",
      "const": "initial_call"
    },
    "durationMinutes": {
      "type": "number"
    }
  },
  "additionalProperties": false
}
get_available_appointments annotations
{
  "readOnlyHint": true,
  "openWorldHint": false,
  "idempotentHint": false,
  "destructiveHint": false
}
book_appointment — Book a free AfAMax initial call
Advertised by the server during the last successful anonymous check.
Advertised destructiveOpen-world

Books a free 15-minute initial phone call with the AfAMax team, in two steps. STEP 1: after the user picked a slot from get_available_appointments, confirm the slot, their name and their own e-mail address with them, then call with startDateTime, name, email (and optionally phone, locale). AfAMax e-mails a 6-digit code to that address and returns status "verification_required" with a verificationId. STEP 2: ask the user for the code from that e-mail and call again with only verificationId and otp. The code proves the address belongs to the user: use only the code the user gives you — never guess, invent or repeatedly retry codes. On success status is "booked" and a calendar invitation goes to the user. Codes expire after 15 minutes and allow 5 attempts. If the slot was taken meanwhile, list slots again and offer another. If the e-mail belongs to an existing AfAMax account, the user must log in and book on the website (link in the error). Only book for the person you are talking to.

book_appointment input schema
{
  "type": "object",
  "$schema": "https://json-schema.org/draft/2020-12/schema",
  "properties": {
    "otp": {
      "type": "string",
      "pattern": "^\\d{6}$",
      "description": "Step 2 — the 6-digit code the user received by e-mail. Only ever the code the user gives you; never guess or retry codes. / Der 6-stellige Code aus der E-Mail."
    },
    "name": {
      "type": "string",
      "maxLength": 80,
      "minLength": 2,
      "description": "Step 1 — the user's full name. / Vor- und Nachname."
    },
    "email": {
      "type": "string",
      "format": "email",
      "pattern": "^(?:[A-Za-z0-9_'+\\-]+\\.)*[A-Za-z0-9_'+\\-]*[A-Za-z0-9_+-]@(?:[A-Za-z0-9][A-Za-z0-9\\-]*\\.)+[A-Za-z]{2,}$",
      "maxLength": 254,
      "description": "Step 1 — the user's own e-mail address; the 6-digit confirmation code is sent there. Confirm it with the user before calling. / E-Mail-Adresse für den Bestätigungscode."
    },
    "phone": {
      "type": "string",
      "maxLength": 40,
      "description": "Step 1, optional — phone number for the call. / Telefonnummer für das Gespräch."
    },
    "locale": {
      "enum": [
        "de",
        "en"
      ],
      "type": "string",
      "description": "Step 1 — language of the confirmation e-mail, the appointment and the links (`de` if omitted); match the user's language. Step 2 keeps step 1's language unless set. / Sprache der E-Mails und des Termins."
    },
    "startDateTime": {
      "type": "string",
      "format": "date-time",
      "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d:[0-5]\\d(?:\\.\\d+)?(?:Z|([+-](?:[01]\\d|2[0-3]):[0-5]\\d)))$",
      "description": "Step 1 — the chosen slot, copied exactly from get_available_appointments `startDateTime`."
    },
    "verificationId": {
      "type": "string",
      "maxLength": 64,
      "minLength": 1,
      "description": "Step 2 — the `verificationId` returned by step 1."
    }
  },
  "additionalProperties": false
}
book_appointment output schema
{
  "type": "object",
  "$schema": "https://json-schema.org/draft/2020-12/schema",
  "required": [
    "requestId",
    "status",
    "verification",
    "appointment",
    "attribution",
    "meta"
  ],
  "properties": {
    "meta": {
      "type": "object",
      "required": [
        "apiVersion",
        "generatedAt"
      ],
      "properties": {
        "apiVersion": {
          "type": "string"
        },
        "generatedAt": {
          "type": "string",
          "format": "date-time",
          "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d:[0-5]\\d(?:\\.\\d+)?(?:Z))$"
        }
      },
      "additionalProperties": false
    },
    "status": {
      "enum": [
        "verification_required",
        "booked"
      ],
      "type": "string",
      "description": "`verification_required`: ask the user for the code sent to `verification.maskedEmail`, then call again with verificationId + otp. `booked`: the appointment exists."
    },
    "requestId": {
      "type": "string",
      "minLength": 1
    },
    "appointment": {
      "anyOf": [
        {
          "type": "object",
          "required": [
            "startDateTime",
            "endDateTime",
            "localDate",
            "localTime",
            "timeZone",
            "durationMinutes",
            "customerInviteSent"
          ],
          "properties": {
            "timeZone": {
              "type": "string"
            },
            "localDate": {
              "type": "string"
            },
            "localTime": {
              "type": "string"
            },
            "endDateTime": {
              "type": "string",
              "format": "date-time",
              "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d:[0-5]\\d(?:\\.\\d+)?(?:Z))$"
            },
            "startDateTime": {
              "type": "string",
              "format": "date-time",
              "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d:[0-5]\\d(?:\\.\\d+)?(?:Z))$"
            },
            "durationMinutes": {
              "type": "number"
            },
            "customerInviteSent": {
              "type": "boolean"
            }
          },
          "additionalProperties": false
        },
        {
          "type": "null"
        }
      ]
    },
    "attribution": {
      "type": "object",
      "required": [
        "provider",
        "url",
        "label"
      ],
      "properties": {
        "url": {
          "type": "string",
          "format": "uri"
        },
        "label": {
          "type": "string"
        },
        "provider": {
          "enum": [
            "AfaMax",
            "AfAMax"
          ],
          "type": "string"
        }
      },
      "additionalProperties": false
    },
    "verification": {
      "anyOf": [
        {
          "type": "object",
          "required": [
            "verificationId",
            "maskedEmail",
            "expiresAt"
          ],
          "properties": {
            "expiresAt": {
              "type": "string",
              "format": "date-time",
              "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d:[0-5]\\d(?:\\.\\d+)?(?:Z))$"
            },
            "maskedEmail": {
              "type": "string"
            },
            "verificationId": {
              "type": "string"
            }
          },
          "additionalProperties": false
        },
        {
          "type": "null"
        }
      ]
    }
  },
  "additionalProperties": false
}
book_appointment annotations
{
  "readOnlyHint": false,
  "openWorldHint": true,
  "idempotentHint": false,
  "destructiveHint": true
}

Prompts

Not advertised

No prompt definitions available.

Resources

Not advertised

No resource definitions available.

90-day uptime

A lightweight connection check about every six hours, sampled on hosts with many listings. It shows the server answered, not that its tools work.

Too few checks for a percentage yet (1 of 1 answered).

  1. 2026-11-07: 1 of 1 checks answered

30-day availability

Aggregated from read-only remote checks; this is not a tool-execution or security guarantee.

Successful checks
1 of 1 (100%)
Average latency
1225 ms
95th percentile latency
1225 ms

Maintenance history

Public check and source-refresh events. Editorial and ownership records remain private.

  • · probe · passed · 1225 ms · metadata changed · 5 tool(s)

Connect from your client

Each snippet registers the same endpoint; pick the client you use.

This server is operated by the named third party. Listing and endpoint checks are not an endorsement or a security audit. Review the operator's permissions, terms, and data handling before connecting. How listings are checked and corrected.

Claude Code

Run this once in a terminal. It registers the remote server. Use --scope project to write .mcp.json for the repo.
Claude Code configuration
claude mcp add --transport http afamax-real-estate-appraisal-mcp-rundum https://mcp.rundum.immo/mcp

Codex

Run this once. Codex stores MCP servers in ~/.codex/config.toml (or .codex/config.toml in a trusted project).
Codex configuration
codex mcp add afamax-real-estate-appraisal-mcp-rundum --url https://mcp.rundum.immo/mcp

Cursor

Merge this server into .cursor/mcp.json in your project, then enable afamax-real-estate-appraisal-mcp-rundum in your MCP settings.
Cursor configuration
{
  "mcpServers": {
    "afamax-real-estate-appraisal-mcp-rundum": {
      "url": "https://mcp.rundum.immo/mcp"
    }
  }
}

Cline

Merge this into cline_mcp_settings.json (Cline → MCP Servers → Configure).
Cline configuration
{
  "mcpServers": {
    "afamax-real-estate-appraisal-mcp-rundum": {
      "type": "streamableHttp",
      "url": "https://mcp.rundum.immo/mcp",
      "disabled": false
    }
  }
}

VS Code

Merge this server into .vscode/mcp.json. Use MCP: List Servers to start afamax-real-estate-appraisal-mcp-rundum and inspect its tools.
VS Code configuration
{
  "servers": {
    "afamax-real-estate-appraisal-mcp-rundum": {
      "type": "http",
      "url": "https://mcp.rundum.immo/mcp"
    }
  }
}

Gemini CLI

Run this once. It writes .gemini/settings.json in the current project; pass --scope user for ~/.gemini/settings.json.
Gemini CLI configuration
gemini mcp add --transport http afamax-real-estate-appraisal-mcp-rundum https://mcp.rundum.immo/mcp

Claude Desktop

Open Claude Settings > Connectors > Add custom connector, enter this server URL and enable it for the conversation. This is a manual remote-connector handoff, not a desktop JSON configuration.
Claude Desktop configuration
https://mcp.rundum.immo/mcp

Windsurf

Merge this into ~/.codeium/windsurf/mcp_config.json, then refresh MCP in Cascade. Windsurf remote servers use serverUrl, not url.
Windsurf configuration
{
  "mcpServers": {
    "afamax-real-estate-appraisal-mcp-rundum": {
      "serverUrl": "https://mcp.rundum.immo/mcp"
    }
  }
}

Let your agent find its tools

Find servers like AfAMax Real Estate Appraisal MCP from your agent. Add Koskamo once to search the index for endpoints, access requirements, and client setup. Public discovery needs no key.

Do you run AfAMax Real Estate Appraisal MCP?

Prove ownership with a DNS record, a well-known file, or your Official MCP Registry entry, and your edits publish immediately. Proofs are re-checked weekly; admins can still hide or remove a listing.

Claim this listing