bereken_hypotheek_doorstromer
Calculate maximum mortgage for home movers to determine new loan amount, monthly payments, and equity indication based on income, property value, and existing mortgage details.
Instructions
Berekent de maximale hypotheek voor doorstromers. Output: nieuw leenbedrag, maandlast en overwaarde-indicatie.
Input Schema
TableJSON Schema
| Name | Required | Description | Default |
|---|---|---|---|
| inkomen_aanvrager | Yes | Bruto jaarinkomen hoofdaanvrager in euro's. | |
| geboortedatum_aanvrager | Yes | Geboortedatum hoofdaanvrager (YYYY-MM-DD). | |
| heeft_partner | Yes | Geeft aan of een partner mee leent. | |
| inkomen_partner | No | Optioneel partnerinkomen in euro's. | |
| geboortedatum_partner | No | Optionele geboortedatum partner (YYYY-MM-DD). | |
| verplichtingen_pm | No | Optionele maandelijkse verplichtingen in euro's. | |
| waarde_huidige_woning | Yes | Huidige marktwaarde van de bestaande woning. | |
| bestaande_hypotheek | Yes | Bestaande leningdelen voor doorstromer (detailuitleg: hypotheek://v4/guide/opzet-intake). | |
| session_id | No | Optioneel sessie-ID vanuit n8n (voor logging). |
Implementation Reference
- src/index.ts:550-580 (handler)Main handler function: normalizes and validates input, constructs API payload, calls Replit backend API for doorstromer hypotheek calculation, formats doorstromer-specific output.async function handleBerekenDoorstromer(request: any): Promise<ToolResponse> { const rawArgs = requireArguments<DoorstromerArguments>(request); const normalizedArgs = normalizeDoorstromerArgs(rawArgs) as DoorstromerArguments; const logger = createLogger(normalizedArgs.session_id); validateDoorstromerArguments(normalizedArgs); enforceRateLimit(normalizedArgs.session_id); const payload: any = { aanvragers: mapAanvragers(normalizedArgs), bestaande_hypotheek: { waarde_huidige_woning: normalizedArgs.waarde_huidige_woning, leningdelen: normalizedArgs.bestaande_hypotheek.leningdelen, }, }; if (normalizedArgs.session_id) { payload.session_id = normalizedArgs.session_id; } const apiClient = getApiClient(); const { data } = await apiClient.post( REPLIT_API_URL_BEREKENEN, payload, { correlationId: normalizedArgs.session_id } ); logger.info('Toolcall succesvol', { tool: 'bereken_hypotheek_doorstromer' }); return successResponse(formatResponse(data, "bereken_hypotheek_doorstromer")); }
- src/index.ts:800-826 (schema)Input schema definition and tool description provided in MCP listTools response.name: "bereken_hypotheek_doorstromer", description: `Maximale hypotheek voor doorstromers ZONDER concrete woning. Gebruik dit wanneer de gebruiker wil weten hoeveel ruimte er is om straks te verhuizen maar er nog geen koopsom of specifieke woning op tafel ligt. Zodra een concreet huis ter sprake komt schakelt u over op de opzet-hypotheek tools. Alle regels uit het doorstromerbeleid gelden ook voor de uitgebreide tool: ${DOORSTROMER_OUTPUT_GUIDANCE}`, inputSchema: { type: "object", description: `Gebruik basisintakevelden plus huidige woninginformatie; zie ${OPZET_GUIDE_URI} voor detaildefinities.`, properties: { ...baseIntakeProperties, waarde_huidige_woning: { type: "number", description: "Huidige marktwaarde van de bestaande woning.", }, bestaande_hypotheek: { ...bestaandeHypotheekSchema, }, session_id: { type: "string", description: "Optioneel sessie-ID vanuit n8n (voor logging).", }, }, required: [ ...baseIntakeRequired, "waarde_huidige_woning", "bestaande_hypotheek", ], }, },
- src/index.ts:766-774 (registration)Maps tool name to handler function in TOOL_HANDLERS object used by CallToolRequestHandler.const TOOL_HANDLERS: Record<string, ToolHandler> = { bereken_hypotheek_starter: handleBerekenStarter, bereken_hypotheek_doorstromer: handleBerekenDoorstromer, bereken_hypotheek_uitgebreid: handleBerekenUitgebreid, haal_actuele_rentes_op: handleActueleRentes, opzet_hypotheek_starter: handleOpzetStarter, opzet_hypotheek_doorstromer: handleOpzetDoorstromer, opzet_hypotheek_uitgebreid: handleOpzetUitgebreid, };
- Normalizes doorstromer input arguments, mapping variant field names (e.g. 'restschuld' -> 'huidige_schuld') and restructuring leningdelen array.export function normalizeDoorstromerArgs(args: any): any { if (!args || typeof args !== 'object') { logger.warn('Invalid doorstromer args input', { args }); return args; } const normalized: any = { ...args }; for (const key of Object.keys(normalized)) { const lowerKey = key.toLowerCase().trim(); const isBestaandeHypotheek = (lowerKey.includes('bestaande') || lowerKey.includes('existing') || lowerKey.includes('current')) && (lowerKey.includes('hypotheek') || lowerKey.includes('lening') || lowerKey.includes('mortgage') || lowerKey.includes('loan')); if (isBestaandeHypotheek) { logger.debug('Normalizing bestaande_hypotheek', { original_key: key }); normalized.bestaande_hypotheek = normalizeBestaandeHypotheek(normalized[key]); if (key !== 'bestaande_hypotheek') { delete normalized[key]; } } const isWoningwaarde = (lowerKey.includes('waarde') && lowerKey.includes('woning')) || (lowerKey.includes('home') && lowerKey.includes('value')); if (isWoningwaarde && typeof normalized[key] === 'number') { logger.debug('Normalizing waarde_huidige_woning', { original_key: key }); normalized.waarde_huidige_woning = normalized[key]; if (key !== 'waarde_huidige_woning') { delete normalized[key]; } } } logger.info('Normalization complete', { has_bestaande_hypotheek: !!normalized.bestaande_hypotheek, has_leningdelen: !!normalized.bestaande_hypotheek?.leningdelen, leningdelen_count: normalized.bestaande_hypotheek?.leningdelen?.length || 0 }); return normalized; }
- src/validation/schemas.ts:331-366 (helper)Validates doorstromer-specific inputs: woningwaarde range, leningdelen structure, counts, rentevast <= looptijd, etc.export function validateDoorstromerArguments(args: unknown): void { // Eerst base arguments valideren validateBaseArguments(args); const input = args as Record<string, unknown>; // Valideer woningwaarde if (typeof input.waarde_huidige_woning !== 'number') { throw new ValidationError( ErrorCode.INVALID_INPUT, 'waarde_huidige_woning moet een getal zijn', 'waarde_huidige_woning' ); } if (input.waarde_huidige_woning < ValidationConstraints.WONING_WAARDE.MIN || input.waarde_huidige_woning > ValidationConstraints.WONING_WAARDE.MAX) { throw new ValidationError( ErrorCode.WONING_VALUE_OUT_OF_RANGE, `Woningwaarde moet tussen €${ValidationConstraints.WONING_WAARDE.MIN.toLocaleString('nl-NL')} en €${ValidationConstraints.WONING_WAARDE.MAX.toLocaleString('nl-NL')} liggen`, 'waarde_huidige_woning', input.waarde_huidige_woning ); } // Valideer bestaande hypotheek if (!input.bestaande_hypotheek) { throw new ValidationError( ErrorCode.INVALID_INPUT, 'bestaande_hypotheek is verplicht voor doorstromers', 'bestaande_hypotheek' ); } validateBestaandeHypotheek(input.bestaande_hypotheek); }