Skip to main content
Glama
apetta

Vibe Math MCP

by apetta

Perpetuity Calculations

perpetuity
Read-onlyIdempotent

Calculate present value of infinite payment streams for financial analysis of preferred stocks, endowments, and perpetual assets using level, growing, or due formulas.

Instructions

Calculate present value of a perpetuity (infinite series of payments).

A perpetuity is an annuity that continues forever. Common in: - Preferred stock dividends - Endowment funds - Real estate with infinite rental income - UK Consol bonds (historically)

Formulas: Level Ordinary: PV = C / r Level Due: PV = C / r × (1 + r) Growing: PV = C / (r - g), where r > g

Examples:

LEVEL PERPETUITY: £1000 annual payment at 5% payment=1000, rate=0.05 Result: PV = £20,000

GROWING PERPETUITY: £1000 payment growing 3% annually at 8% discount payment=1000, rate=0.08, growth_rate=0.03 Result: PV = £20,000

PERPETUITY DUE: £1000 at period start at 5% payment=1000, rate=0.05, when='begin' Result: PV = £21,000

Input Schema

TableJSON Schema
NameRequiredDescriptionDefault
contextNoOptional annotation to label this calculation (e.g., 'Bond A PV', 'Q2 revenue'). Appears in results for easy identification.
output_modeNoOutput format: full (default), compact, minimal, value, or final. See batch_execute tool for details.full
paymentYesPeriodic payment amount (e.g., 1000)
rateYesDiscount rate per period (e.g., 0.05)
growth_rateNoPayment growth rate (None or 0 for level, e.g., 0.03 for growing)
whenNoPayment timing: 'end' or 'begin'end

Output Schema

TableJSON Schema
NameRequiredDescriptionDefault
resultYes

Implementation Reference

  • MCP tool registration decorator defining the perpetuity tool's name, description, examples, and metadata annotations.
    @mcp.tool(
        name="perpetuity",
        description="""Calculate present value of a perpetuity (infinite series of payments).
    
    A perpetuity is an annuity that continues forever. Common in:
        - Preferred stock dividends
        - Endowment funds
        - Real estate with infinite rental income
        - UK Consol bonds (historically)
    
    Formulas:
        Level Ordinary: PV = C / r
        Level Due: PV = C / r × (1 + r)
        Growing: PV = C / (r - g), where r > g
    
    Examples:
    
    LEVEL PERPETUITY: £1000 annual payment at 5%
        payment=1000, rate=0.05
        Result: PV = £20,000
    
    GROWING PERPETUITY: £1000 payment growing 3% annually at 8% discount
        payment=1000, rate=0.08, growth_rate=0.03
        Result: PV = £20,000
    
    PERPETUITY DUE: £1000 at period start at 5%
        payment=1000, rate=0.05, when='begin'
        Result: PV = £21,000""",
        annotations=ToolAnnotations(
            title="Perpetuity Calculations",
            readOnlyHint=True,
            idempotentHint=True,
        ),
    )
  • Handler function implementing present value calculation for level perpetuity (PV=C/r), growing perpetuity (PV=C/(r-g)), and perpetuity due (PV=C/r * (1+r)), with input validation and metadata generation.
    async def perpetuity(
        payment: Annotated[float, Field(description="Periodic payment amount (e.g., 1000)")],
        rate: Annotated[float, Field(description="Discount rate per period (e.g., 0.05)", gt=0)],
        growth_rate: Annotated[
            float | None,
            Field(
                description="Payment growth rate (None or 0 for level, e.g., 0.03 for growing)", ge=0
            ),
        ] = None,
        when: Annotated[
            Literal["end", "begin"], Field(description="Payment timing: 'end' or 'begin'")
        ] = "end",
    ) -> str:
        """Calculate present value of perpetuity."""
        try:
            # Validate inputs
            if rate <= 0:
                raise ValueError("Discount rate must be positive")
    
            if growth_rate is not None:
                if growth_rate < 0:
                    raise ValueError("Growth rate cannot be negative")
                if growth_rate >= rate:
                    raise ValueError(
                        f"Growth rate ({growth_rate}) must be less than discount rate ({rate}) "
                        "for perpetuity to have finite value"
                    )
    
            # Calculate present value based on type
            if growth_rate is not None and growth_rate > 0:
                # Growing perpetuity: PV = C / (r - g)
                pv = payment / (rate - growth_rate)
                perpetuity_type = "growing"
            elif when == "begin":
                # Perpetuity due (payments at beginning): PV = C/r × (1+r)
                pv = (payment / rate) * (1 + rate)
                perpetuity_type = "level_due"
            else:
                # Ordinary perpetuity (payments at end): PV = C / r
                pv = payment / rate
                perpetuity_type = "level_ordinary"
    
            # Build metadata
            metadata: Dict[str, Any] = {
                "type": perpetuity_type,
                "payment": payment,
                "rate": rate,
            }
            if growth_rate is not None:
                metadata["growth_rate"] = growth_rate
            if when != "end":
                metadata["when"] = when
    
            return format_result(float(pv), metadata)
    
        except Exception as e:
            raise ValueError(f"Perpetuity calculation failed: {str(e)}")
  • TOOL_CATEGORIES dictionary listing 'perpetuity' under Financial category for batch execution tool registry.
    "Financial": ["financial_calcs", "compound_interest", "perpetuity"],

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/apetta/vibe-math-mcp'

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