# Special Assessment Calculator

> Turn a project cost into a clear funding gap and payment options per home.

Human page: https://tools.rodri.ai/tools/special-assessment
Skill: https://tools.rodri.ai/.well-known/skills/special-assessment/SKILL.md
Category: finance
Exports: text, csv, print

## Operations

| Operation | Engine | Cost |
| --- | --- | --- |
| `special_assessment.calculate` | deterministic | free, no key |

### `special_assessment.calculate`

Calculate assessment. No credential needed. Deterministic arithmetic, so it costs no allowance and is rate limited by address.

Input schema version 1, output schema version 1.
MCP tool name: `special_assessment_calculate`

Input JSON Schema:

```json
{
  "$schema": "https://json-schema.org/draft/2020-12/schema",
  "type": "object",
  "properties": {
    "projectLabel": {
      "type": "string",
      "minLength": 1,
      "maxLength": 120
    },
    "communityName": {
      "type": "string",
      "maxLength": 120
    },
    "currency": {
      "default": "USD",
      "type": "string",
      "enum": [
        "USD",
        "EUR",
        "GBP",
        "CAD",
        "MXN"
      ]
    },
    "costLines": {
      "minItems": 1,
      "maxItems": 50,
      "type": "array",
      "items": {
        "type": "object",
        "properties": {
          "label": {
            "type": "string",
            "minLength": 1,
            "maxLength": 80
          },
          "amount": {
            "type": "string",
            "pattern": "^\\d{1,12}(\\.\\d{1,4})?$"
          },
          "inContingencyBasis": {
            "default": true,
            "type": "boolean"
          }
        },
        "required": [
          "label",
          "amount"
        ]
      }
    },
    "contingencyPercent": {
      "anyOf": [
        {
          "type": "string",
          "pattern": "^\\d{1,3}(\\.\\d{1,4})?$"
        },
        {
          "type": "string",
          "const": ""
        }
      ]
    },
    "reserveDraw": {
      "anyOf": [
        {
          "type": "string",
          "pattern": "^\\d{1,12}(\\.\\d{1,4})?$"
        },
        {
          "type": "string",
          "const": ""
        }
      ]
    },
    "availableReserveBalance": {
      "anyOf": [
        {
          "type": "string",
          "pattern": "^\\d{1,12}(\\.\\d{1,4})?$"
        },
        {
          "type": "string",
          "const": ""
        }
      ]
    },
    "otherFunding": {
      "maxItems": 50,
      "type": "array",
      "items": {
        "type": "object",
        "properties": {
          "label": {
            "type": "string",
            "minLength": 1,
            "maxLength": 80
          },
          "amount": {
            "type": "string",
            "pattern": "^\\d{1,12}(\\.\\d{1,4})?$"
          }
        },
        "required": [
          "label",
          "amount"
        ]
      }
    },
    "unitCount": {
      "type": "integer",
      "exclusiveMinimum": 0,
      "maximum": 20000
    },
    "allocationMode": {
      "default": "equal",
      "type": "string",
      "enum": [
        "equal",
        "classes"
      ]
    },
    "unitClasses": {
      "maxItems": 100,
      "type": "array",
      "items": {
        "type": "object",
        "properties": {
          "name": {
            "type": "string",
            "minLength": 1,
            "maxLength": 60
          },
          "unitCount": {
            "type": "integer",
            "exclusiveMinimum": 0,
            "maximum": 20000
          },
          "weightPerUnit": {
            "type": "string",
            "pattern": "^\\d{1,7}(\\.\\d{1,6})?$"
          }
        },
        "required": [
          "name",
          "unitCount",
          "weightPerUnit"
        ]
      }
    },
    "allocationBasisNote": {
      "type": "string",
      "maxLength": 400
    },
    "paymentOptions": {
      "maxItems": 3,
      "type": "array",
      "items": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string",
            "minLength": 1,
            "maxLength": 40
          },
          "installmentCount": {
            "type": "integer",
            "minimum": 1,
            "maximum": 60
          },
          "spacing": {
            "default": "monthly",
            "type": "string",
            "enum": [
              "monthly",
              "quarterly"
            ]
          }
        },
        "required": [
          "id",
          "installmentCount"
        ]
      }
    },
    "firstPaymentDate": {
      "anyOf": [
        {
          "type": "string",
          "pattern": "^\\d{4}-\\d{2}-\\d{2}$"
        },
        {
          "type": "string",
          "const": ""
        }
      ]
    },
    "approvalStatus": {
      "default": "proposed",
      "type": "string",
      "enum": [
        "proposed",
        "approved_per_user",
        "unknown"
      ]
    },
    "locale": {
      "default": "en",
      "type": "string",
      "enum": [
        "en",
        "es"
      ]
    }
  },
  "required": [
    "projectLabel",
    "costLines",
    "unitCount"
  ]
}
```

### Running an operation

Two ways in, and the difference is what an operation costs.

**No credential.** The four calculators are pure arithmetic — no model, nothing
stored, no allowance spent. Rate limited to 30 requests a minute per address.

```http
POST https://tools.rodri.ai/api/agent/tools/{toolId}/runs
Content-Type: application/json

{"operation": "meeting_quorum.calculate", "input": { ... }}
```

**With an API key.** Everything else, including every AI operation. The key's
owner creates it at https://tools.rodri.ai/account. It carries exactly their entitlements: a
free account has 20 AI credits a month and unlimited use of the calculators.
A key grants nothing its owner does not already have.

```http
POST https://tools.rodri.ai/api/agent/tools/{toolId}/runs
Authorization: Bearer hpt_live_…
Content-Type: application/json

{"operation": "resident_notice.generate", "input": { ... }}
```

Errors come back as `{"error": {"code", "message", "retryable"}}`. Branch on
`code` — `QUOTA_EXHAUSTED`, `RATE_LIMITED`, `REGISTRATION_REQUIRED`,
`VALIDATION_ERROR` — not on the sentence, which is written for people and is
translated.

**MCP.** The same operations are exposed at `https://tools.rodri.ai/api/mcp` over Streamable
HTTP. It is stateless, so POST JSON-RPC and read the JSON reply; the same
`Authorization` header applies.
