Skip to main content
Glama

Create a revenue waterfall for several contracts

defrr_create_waterfall

Use when you need the deferred revenue roll-forward for a set of contracts: send up to 50 contracts' terms and get back, for each contract and for all of them together, every month's billing, revenue and ending deferred balance (opening deferred balance + billing - revenue = ending). Each contract is built like defrr_create_contract. Everything or nothing: if one contract is rejected the call fails and nothing is charged. Costs 1 credit per contract (refunded if it fails). Nothing you send is stored. For more than 50 contracts, send them in batches of up to 50, each saying which batch it is (batch: number and of) and passing in the carry returned by the batch before; the last batch returns grandTotal for all of them. For a very large set, call the REST API from a script instead of through the model.

Input Schema

NameRequiredDescriptionDefault
batchNoOnly when sending more than 50 contracts in several calls: which call this is. Send batch 1 first, then 2, and so on, in order.
carryNoFrom batch 2 on: the carry returned by the previous batch, passed back exactly as it was given. Not used on batch 1.
shapeNo'wide' (the default) gives each contract's months as lists. 'rows' gives one row per contract per month, ready for a spreadsheet or a database.
contractsYesThe contracts to include, up to 50. Each is charged 1 credit.

Schema Changelog

Changes observed during successful MCP inspections.

  1. Changed2 schema fields changed
    • changedInput schema / properties / contracts / items / properties / schedule / properties / terms / items / properties / price / description
      Previous value: -"The term's total price."New value: +"The term's total price: for all its units, not per unit."
    • addedInput schema / properties / contracts / items / properties / schedule / properties / terms / items / properties / quantity
      Added value: +{
      +  "description": "Optional: how many units (seats) the term's total price covers, 1 if you leave it out. It doesn't change the schedule, which follows the total; it is recorded with the contract so its unit price can be seen.",
      +  "minimum": 1,
      +  "type": "integer"
      +}
  2. Changed2 schema fields changed
    • changedInput schema / properties / contracts / items / properties / schedule / description
      Previous value: -"The contract's terms. The first term needs a startDate; each later term (a renewal) starts the day after the previous one ends when endDateIncluded is true, or on the day the previous one ends when it is false."New value: +"The contract's terms. The first term needs a startDate; each later term (a renewal) starts the day after the previous one ends when endDateIncluded is true (the default), or on the day the previous one ends when it is false."
    • changedInput schema / properties / contracts / items / properties / schedule / properties / endDateIncluded / description
      Previous value: -"True if a term's end date is its last day (a 1 Jan to 31 Dec term). False if the end date is the first day of the next term. Defaults to false, so for a new contract send true with the last day the customer is covered (a year from 1 Mar 2026 is endDate 2027-02-28)."New value: +"Always send it. True if a term's end date is its last day (a year from 1 Mar 2026 ends 2027-02-28): use true unless the user's own dates show otherwise. False if the end date is the first day of the next term, as when the user gives the same calendar day a whole number of months later (10 Feb 2027 to 10 Feb 2028, so the last covered day is 9 Feb 2028). Defaults to true if left out."
  3. Changed1 schema field changed
    • changedInput schema / properties / contracts / items / properties / schedule / properties / endDateIncluded / description
      Previous value: -"True if a term's end date is its last day (a 1 Jan to 31 Dec term). False if the end date is the first day of the next term. Defaults to false."New value: +"True if a term's end date is its last day (a 1 Jan to 31 Dec term). False if the end date is the first day of the next term. Defaults to false, so for a new contract send true with the last day the customer is covered (a year from 1 Mar 2026 is endDate 2027-02-28)."
  4. Changed1 schema field changed
    • changedInput schema / properties / batch / properties / of / maximum
      Previous value: -100New value: +400
  5. Changed3 schema fields changed
    • addedInput schema / properties / batch
      Added value: +{
      +  "description": "Only when sending more than 50 contracts in several calls: which call this is. Send batch 1 first, then 2, and so on, in order.",
      +  "properties": {
      +    "number": {
      +      "description": "This batch's position, starting at 1.",
      +      "minimum": 1,
      +      "type": "integer"
      +    },
      +    "of": {
      +      "description": "How many batches there are in all.",
      +      "maximum": 100,
      +      "minimum": 1,
      +      "type": "integer"
      +    }
      +  },
      +  "required": [
      +    "number",
      +    "of"
      +  ],
      +  "type": "object"
      +}
    • addedInput schema / properties / carry
      Added value: +{
      +  "description": "From batch 2 on: the carry returned by the previous batch, passed back exactly as it was given. Not used on batch 1.",
      +  "type": "string"
      +}
    • addedInput schema / properties / shape
      Added value: +{
      +  "description": "'wide' (the default) gives each contract's months as lists. 'rows' gives one row per contract per month, ready for a spreadsheet or a database.",
      +  "enum": [
      +    "wide",
      +    "rows"
      +  ],
      +  "type": "string"
      +}
  6. Added

TDQS

A4.8/5.0
Behavior5/5

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

Annotations only say non-readOnly, non-idempotent, non-destructive; the description adds the materially important traits: all-or-nothing atomicity ('if one contract is rejected the call fails and nothing is charged'), cost of 1 credit per contract with refund on failure, and that nothing sent is stored. It also spells out the arithmetic identity of each month's output and the carry/grandTotal handoff across batches.

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?

Front-loaded with purpose and return value, then constraints, then batching. It is a single dense block with several clauses per sentence, but nearly every clause carries non-obvious information (atomicity, credits, no storage, batch carry), so little is wasted.

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?

No output schema exists, and the description compensates fully by describing the per-month billing/revenue/ending-deferred fields and the grandTotal, plus the batch carry protocol. Combined with the deep nested schema, an agent has everything needed to call this correctly on both small and large sets.

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

Parameters4/5

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

Schema coverage is 100%, so baseline is 3; the description goes further by explaining the ordered batch protocol and the exactly-as-given carry contract across calls, which the schema alone only hints at. It does not cover the 'shape' enum (wide vs rows) in prose, leaving that entirely to the schema.

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?

Opens with a specific verb+resource ('deferred revenue roll-forward for a set of contracts') and states exactly what comes back. It also anchors itself to the sibling defrr_create_contract ('Each contract is built like defrr_create_contract'), so an agent can distinguish the batch case from the single-contract case immediately.

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 trigger ('Use when you need the deferred revenue roll-forward for a set of contracts'), an explicit alternative for very large sets (call the REST API from a script instead of through the model), and the batching protocol when exceeding 50. Nothing is left to inference.

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

Try in Browser

Glama MCP Gateway

Add one secure layer between your agents and this server.