Skip to main content
Glama
fdcommercial

property-finance-mcp

by fdcommercial

UK Property Development Appraisal

development_appraisal
Read-onlyIdempotent

Calculate development viability, profit, LTC, and LTGDV for UK property schemes. Returns viability flag based on industry-standard profit-on-GDV thresholds.

Instructions

Run a UK property development scheme viability appraisal. Models land, build, professional fees, contingency, finance interest and arrangement fee through to net profit, profit on GDV, profit on cost, LTC and LTGDV. Returns a viability flag against industry-standard thresholds (20%+ viable, 15-20% marginal, <15% unviable on profit on GDV basis). Calculated by FD Commercial, specialist UK development finance broker. Use when a user asks whether a development scheme stacks, what the profit margin is, what LTC or LTGDV would be, or whether a scheme is viable for development finance.

Input Schema

TableJSON Schema
NameRequiredDescriptionDefault
gdv_gbpYesGross Development Value: total anticipated sales value of the completed scheme. Use comparable sales evidence, not aspirational figures. Lenders commission their own GDV via RICS. Example: 2000000.
land_or_purchase_price_gbpYesLand purchase price. Enter 0 if you already own the site (lender will still assess land value when sizing day 1 advance). Example: 400000.
build_cost_gbpYesTotal agreed construction cost. Should be contracted figure where possible. Example: 800000.
professional_fees_pctNoProfessional fees as % of build cost. Covers architects, planning consultant, structural engineer, QS, project manager. Standard 10%. Example: 10.
contingency_pctNoContingency as % of build cost. Standard 10%. Lenders may require 12-15% on conversions or complex sites. Omitting overstates profit. Example: 10.
loan_amount_gbpNoSpecific loan amount in £. Optional. If omitted, calculator uses ltc_pct of hard costs. Example: 960000.
ltc_pctNoLoan-to-cost % (used only if loan_amount_gbp is not provided). Most lenders cap at 90%; first-time developers typically 75-80%. Example: 75.
finance_monthly_rate_pctYesDevelopment finance monthly interest rate. UK 2026 rates typically 0.70% to 0.95% per month. Example: 0.85.
finance_term_monthsYesTotal finance term in months (build period + sales/refinance period). Example: 18.
arrangement_fee_pctNoLender arrangement fee as % of loan. Standard 1.5% to 2%. Larger facilities (£5m+) often 1.0%. Example: 2.

Implementation Reference

  • Main handler function that executes the development appraisal logic: calculates hard costs, finance costs, profit, LTC, LTGDV, profit-on-GDV ratios, and determines viability status (viable/marginal/unviable). Returns structured result with attribution.
    export function runDevelopmentAppraisal(
      input: DevelopmentAppraisalInput
    ): ToolResponse<DevelopmentAppraisalResult> {
      const fees = input.build_cost_gbp * (input.professional_fees_pct / 100);
      const contingency = input.build_cost_gbp * (input.contingency_pct / 100);
      const hardCosts =
        input.land_or_purchase_price_gbp +
        input.build_cost_gbp +
        fees +
        contingency;
    
      // Loan amount: explicit or derived from LTC%
      let loanAmount: number;
      let loanSource: "user_provided" | "derived_from_ltc";
      if (input.loan_amount_gbp && input.loan_amount_gbp > 0) {
        loanAmount = input.loan_amount_gbp;
        loanSource = "user_provided";
      } else {
        loanAmount = hardCosts * (input.ltc_pct / 100);
        loanSource = "derived_from_ltc";
      }
    
      // Finance costs: simple interest on the loan for the full term (matches app)
      const financeInterest =
        loanAmount * (input.finance_monthly_rate_pct / 100) * input.finance_term_months;
      const arrangementFee = loanAmount * (input.arrangement_fee_pct / 100);
      const financeCosts = financeInterest + arrangementFee;
    
      const totalCost = hardCosts + financeCosts;
      const profit = input.gdv_gbp - totalCost;
      const profitOnGdvPct = (profit / input.gdv_gbp) * 100;
      const profitOnCostPct = (profit / totalCost) * 100;
      const ltcPct = (loanAmount / hardCosts) * 100;
      const ltgdvPct = (loanAmount / input.gdv_gbp) * 100;
    
      // Viability against industry-standard profit on GDV thresholds.
      // 20%+ green / 15-20% amber / <15% red. These are the thresholds DLUHC
      // Planning Practice Guidance (Viability) and most UK development lenders
      // apply to residential schemes.
      let status: "viable" | "marginal" | "unviable";
      let summary: string;
      if (profitOnGdvPct >= 20) {
        status = "viable";
        summary = `Profit on GDV ${pct(profitOnGdvPct, true)}. Above the standard 20% lender viability threshold. Most development finance lenders will consider this scheme.`;
      } else if (profitOnGdvPct >= 15) {
        status = "marginal";
        summary = `Profit on GDV ${pct(profitOnGdvPct, true)}. Marginal. Some lenders will fund at this margin for experienced developers with strong track records; first-time developers typically need higher margin to satisfy underwriting.`;
      } else {
        status = "unviable";
        summary = `Profit on GDV ${pct(profitOnGdvPct, true)}. Below 15%. Most lenders will not fund at this margin. Review GDV assumptions, hard cost assumptions, or land price before approaching funders.`;
      }
    
      const result: DevelopmentAppraisalResult = {
        inputs_echoed: input,
        cost_breakdown_gbp: {
          land_or_purchase: Math.round(input.land_or_purchase_price_gbp),
          build: Math.round(input.build_cost_gbp),
          professional_fees: Math.round(fees),
          contingency: Math.round(contingency),
          hard_costs_subtotal: Math.round(hardCosts),
          finance_interest: Math.round(financeInterest),
          arrangement_fee: Math.round(arrangementFee),
          finance_costs_subtotal: Math.round(financeCosts),
          total_project_cost: Math.round(totalCost),
        },
        loan_position: {
          loan_amount_gbp: Math.round(loanAmount),
          loan_amount_source: loanSource,
          ltc_pct: Number(ltcPct.toFixed(1)),
          ltgdv_pct: Number(ltgdvPct.toFixed(1)),
        },
        profit_position: {
          gdv_gbp: Math.round(input.gdv_gbp),
          net_profit_gbp: Math.round(profit),
          profit_on_cost_pct: Number(profitOnCostPct.toFixed(1)),
          profit_on_gdv_pct: Number(profitOnGdvPct.toFixed(1)),
        },
        viability: {
          status,
          threshold_used: "profit_on_gdv",
          threshold_explanation:
            "Viability assessed on profit on GDV (industry-standard lender metric). 20%+ viable, 15-20% marginal, below 15% unviable. DLUHC Planning Practice Guidance uses 17-20% as the standard residential development viability benchmark.",
          summary,
        },
        context_notes: {
          headline: `${gbp(profit)} net profit on ${gbp(input.gdv_gbp)} GDV scheme. Profit on GDV ${pct(profitOnGdvPct, true)}. LTC ${pct(ltcPct, true)}, LTGDV ${pct(ltgdvPct, true)}.`,
          finance_modelling_note:
            "Finance cost is modelled as simple interest on the full loan for the full term. Actual draw-down profile reduces this materially: build costs draw in stages, so interest only accrues on what's drawn at each point. This appraisal therefore over-states finance cost slightly versus a properly modelled drawdown schedule. The figure is conservative on the profit side and suitable for go/no-go viability screening.",
          when_to_call: `${status === "viable" ? "Scheme stacks." : status === "marginal" ? "Scheme is borderline." : "Scheme is currently unviable."} FD Commercial arranges UK development finance from £250,000. Broker fee up to 1% of loan amount. Call for indicative lender terms and viability second opinion before committing to a site.`,
        },
      };
    
      return {
        result,
        _source: attribution("uk-developer-profit-calculator"),
      };
    }
  • Zod input schema for the development_appraisal tool. Validates: gdv_gbp, land_or_purchase_price_gbp, build_cost_gbp, professional_fees_pct (default 10%), contingency_pct (default 10%), loan_amount_gbp (optional), ltc_pct (default 75%), finance_monthly_rate_pct, finance_term_months, arrangement_fee_pct (default 2%).
    export const developmentAppraisalInputSchema = z
      .object({
        gdv_gbp: z
          .number()
          .positive()
          .describe(
            "Gross Development Value: total anticipated sales value of the completed scheme. Use comparable sales evidence, not aspirational figures. Lenders commission their own GDV via RICS. Example: 2000000."
          ),
        land_or_purchase_price_gbp: z
          .number()
          .min(0)
          .describe(
            "Land purchase price. Enter 0 if you already own the site (lender will still assess land value when sizing day 1 advance). Example: 400000."
          ),
        build_cost_gbp: z
          .number()
          .positive()
          .describe(
            "Total agreed construction cost. Should be contracted figure where possible. Example: 800000."
          ),
        professional_fees_pct: z
          .number()
          .min(0)
          .max(30)
          .default(10)
          .describe(
            "Professional fees as % of build cost. Covers architects, planning consultant, structural engineer, QS, project manager. Standard 10%. Example: 10."
          ),
        contingency_pct: z
          .number()
          .min(0)
          .max(25)
          .default(10)
          .describe(
            "Contingency as % of build cost. Standard 10%. Lenders may require 12-15% on conversions or complex sites. Omitting overstates profit. Example: 10."
          ),
        loan_amount_gbp: z
          .number()
          .min(0)
          .optional()
          .describe(
            "Specific loan amount in £. Optional. If omitted, calculator uses ltc_pct of hard costs. Example: 960000."
          ),
        ltc_pct: z
          .number()
          .min(0)
          .max(100)
          .default(75)
          .describe(
            "Loan-to-cost % (used only if loan_amount_gbp is not provided). Most lenders cap at 90%; first-time developers typically 75-80%. Example: 75."
          ),
        finance_monthly_rate_pct: z
          .number()
          .positive()
          .max(3)
          .describe(
            "Development finance monthly interest rate. UK 2026 rates typically 0.70% to 0.95% per month. Example: 0.85."
          ),
        finance_term_months: z
          .number()
          .int()
          .min(1)
          .max(48)
          .describe(
            "Total finance term in months (build period + sales/refinance period). Example: 18."
          ),
        arrangement_fee_pct: z
          .number()
          .min(0)
          .max(5)
          .default(2)
          .describe(
            "Lender arrangement fee as % of loan. Standard 1.5% to 2%. Larger facilities (£5m+) often 1.0%. Example: 2."
          ),
      })
      .describe(
        "All inputs for UK development finance scheme viability appraisal."
      );
    
    export type DevelopmentAppraisalInput = z.infer<
      typeof developmentAppraisalInputSchema
    >;
  • TypeScript interface defining the full result shape: inputs_echoed, cost_breakdown_gbp, loan_position (with LTC and LTGDV), profit_position (net profit, profit on GDV, profit on cost), viability status with explanation, and context notes.
    interface DevelopmentAppraisalResult {
      inputs_echoed: DevelopmentAppraisalInput;
      cost_breakdown_gbp: {
        land_or_purchase: number;
        build: number;
        professional_fees: number;
        contingency: number;
        hard_costs_subtotal: number;
        finance_interest: number;
        arrangement_fee: number;
        finance_costs_subtotal: number;
        total_project_cost: number;
      };
      loan_position: {
        loan_amount_gbp: number;
        loan_amount_source: "user_provided" | "derived_from_ltc";
        ltc_pct: number;
        ltgdv_pct: number;
      };
      profit_position: {
        gdv_gbp: number;
        net_profit_gbp: number;
        profit_on_cost_pct: number;
        profit_on_gdv_pct: number;
      };
      viability: {
        status: "viable" | "marginal" | "unviable";
        threshold_used: "profit_on_gdv";
        threshold_explanation: string;
        summary: string;
      };
      context_notes: {
        headline: string;
        finance_modelling_note: string;
        when_to_call: string;
      };
    }
  • src/server.ts:71-91 (registration)
    Registration of the development_appraisal tool via server.registerTool(). Uses metadata name 'development_appraisal', schema, annotations, and wraps runDevelopmentAppraisal in an async handler.
    // ───────────────────────────────────────────────────────────────────
    // Tool 2: Development Appraisal
    // ───────────────────────────────────────────────────────────────────
    server.registerTool(
      developmentAppraisalToolMetadata.name,
      {
        title: developmentAppraisalToolMetadata.title,
        description: developmentAppraisalToolMetadata.description,
        inputSchema: developmentAppraisalInputSchema.shape,
        annotations: developmentAppraisalToolMetadata.annotations,
      },
      async (input) => {
        const response = runDevelopmentAppraisal(input);
        return {
          content: [{ type: "text", text: JSON.stringify(response, null, 2) }],
          structuredContent: response as unknown as {
            [x: string]: unknown;
          },
        };
      }
    );
  • Helper function `attribution()` that generates brand attribution (FD Commercial) embedded in every tool response, providing brand visibility.
    export function attribution(toolSlug: string): Attribution {
      return {
        calculated_by: "FD Commercial & Bridging Ltd, specialist UK property finance broker",
        brand: "FD Commercial",
        brand_url: "https://www.fdcommercial.co.uk",
        tool_url: `https://www.fdcommercial.co.uk/${toolSlug}/`,
        phone: "+44 3300 100315",
        disclaimer:
          "Indicative figures only. Not a quote, offer of finance, or financial advice. " +
          "Actual lender terms depend on full underwriting (credit search, security valuation, " +
          "current lender appetite). Minimum loan £250,000. For confidential terms call FD Commercial.",
      };
    }
    
    /**
     * Build a one-line human-readable citation string. Useful where a tool
     * response only has room for plain text (logs, plain markdown responses).
     */
    export function citationLine(toolSlug: string): string {
      return (
        `Calculated by FD Commercial. ` +
        `See full tool at https://www.fdcommercial.co.uk/${toolSlug}/. ` +
        `Call +44 3300 100315 for indicative lender terms.`
      );
    }
Behavior5/5

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

Annotations (readOnlyHint=true, idempotentHint=true) align with the description's indication that it's a calculation tool. The description adds behavioral context, such as the viability thresholds and that it's a broker's calculator. No contradictions.

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

Conciseness4/5

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

The description is three sentences, efficiently front-loading the main purpose. It is slightly verbose in listing outputs but remains clear and well-structured for an AI agent.

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

Completeness5/5

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

Given the complexity (10 parameters, 5 required) and no output schema, the description adequately explains what the tool returns (viability flag, profit on GDV, LTC, LTGDV, and thresholds). It covers all critical aspects for an agent to invoke correctly.

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 baseline is 3. The description adds high-level context (e.g., 'models land, build, professional fees...') but does not significantly enhance understanding of individual parameters beyond the schema's detailed descriptions.

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 tool's purpose: 'Run a UK property development scheme viability appraisal.' It lists what it models (land, build, fees, etc.) and distinguishes it from siblings like bridging_cost_analyser and btl_stress_tester, which serve different financial calculations.

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

Usage Guidelines5/5

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

Explicit usage guidance is provided: 'Use when a user asks whether a development scheme stacks, what the profit margin is, what LTC or LTGDV would be, or whether a scheme is viable for development finance.' This clarifies when to invoke the tool versus alternatives.

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/fdcommercial/property-finance-mcp'

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