Skip to main content
Glama
tresor4k

takeoffmetric-mcp

by tresor4k
README.md
# takeoffmetric-mcp

A Model Context Protocol server (stdio) that runs the construction calculators of TakeoffMetric
(https://takeoffmetric.com/) from an MCP client. It ships 15 calculators, a tool that lists them, and a search
over a table of estimating constants in which every row names its published source.

The calculators are not re-implemented here. The site's TypeScript engine is bundled unchanged into
`vendor/engine.mjs`, and the test suite checks that each tool returns what the engine source computes.

## Install

Requires Node.js 20 or later.

```bash
npx -y takeoffmetric-mcp
```

Claude Desktop (`claude_desktop_config.json`):

```json
{
  "mcpServers": {
    "takeoffmetric": {
      "command": "npx",
      "args": ["-y", "takeoffmetric-mcp"]
    }
  }
}
```

Claude Code:

```bash
claude mcp add takeoffmetric -- npx -y takeoffmetric-mcp
```

## Tools

| Tool | What it returns |
|---|---|
| `calc_concrete_slab` | Concrete volume, order quantity, bags, truck loads and weight for a slab, with extra sections and an optional thickened edge. |
| `calc_concrete_cost` | Concrete cost from your own delivered price, with short-load fee, delivery, and bags compared with ready-mix. |
| `calc_rebar` | Bar count each way, lap splices, stock bars, weight, intersections and supports for a slab grid or a continuous footing. |
| `calc_gravel` | Cubic yards, short tons and metric tonnes of gravel, stone or rock, with the compaction conversion and a truck count. |
| `calc_fill_dirt` | Cubic yards, tons and truck loads of fill dirt, loose or in place. |
| `calc_sand` | Cubic yards, short tons and a bag count for sand, by moisture condition. |
| `calc_topsoil` | Cubic yards, bags, weight and coverage of topsoil for a lawn, a top-dressing pass, a garden bed or a raised box. |
| `calc_cubic_yard` | Cubic yards, cubic feet and cubic meters over several areas, the area a volume covers, swell, bags and truck trips. |
| `calc_asphalt` | Short tons and metric tonnes of hot mix by course and by area, with the spread rate. |
| `calc_board_foot` | Board feet, lineal feet, pieces and cost for a lumber order of several sizes. |
| `calc_roofing` | Squares, shingle bundles, underlayment rolls, ridge cap and starter from the plan footprint and the pitch. |
| `calc_roof_pitch` | Rise in 12, angle, grade and slope factor from any one of them, plus ridge height and common rafter length from a span. |
| `calc_fence` | Posts, rails, pickets, gates and post-hole concrete for a fence line. |
| `calc_duct` | Round and rectangular duct size from airflow and a friction rate or velocity limit, what a duct carries, and a reducing trunk. |
| `calc_paver_base` | Crushed stone base, bedding sand and excavation depth under a paver patio, driveway or street. |

Two more tools complete the server:

- `list_calculators`: tool name, title, page URL, one-line description and input keys of each calculator.
- `search_constants`: rows of the constants table matched by a substring (`query`) and/or a `category`, 50 rows at most per call.

### Inputs

Each calculator's input schema is generated at start-up from the engine's own input list, so keys, bounds, options
and defaults are the ones of the matching form on the site.

- Every input is optional. A key you leave out takes the engine default, as an untouched form field does.
- `system` is `"imperial"` (default) or `"metric"`. It sets the unit the numbers are typed in and the defaults.
- A length is a number in the unit named in its description, or a string that carries its unit, such as `"20 ft 6 in"`.
- An unknown key or an out-of-range value returns `isError: true` with one message per field. Nothing is computed from a clamped value.

### Output

A JSON text block: `calculator`, `url`, `system`, `engine_version`, `revised`, `inputs_used`, `primary`, `secondary`,
`takeoff`, `warnings`, `assumptions`. `inputs_used` is the engine's normalized input (lengths in metres). `assumptions`
lists what the result rests on, and `warnings` carries the cautions the page would show.

## Worked example

Request (`tools/call`, tool `calc_concrete_slab`):

```json
{"length":24,"width":16,"thickness":"5 in","price":165}
```

Response, copied from a run of this server (whitespace condensed):

```json
{
  "calculator": "calc_concrete_slab",
  "url": "https://takeoffmetric.com/concrete/concrete-calculator/",
  "system": "imperial",
  "engine_version": "1.2.0",
  "revised": "2026-09-19",
  "inputs_used": {"system":"imperial","sections":[{"length":7.315200000000001,"width":4.8768},{"length":0,"width":0},{"length":0,"width":0}],"thickness":0.127,"wastePct":10,"bagSize":"60","pricePerCuYd":165,"thickenedEdge":false,"edgeDepth":0.30479999999999996,"edgeWidth":0.30479999999999996,"gravelDepth":0.1016,"unitWeight":150,"truckCuYd":10,"minLoadCuYd":null,"shortLoadFee":null},
  "primary": {"value":6.52,"unit":"cuyd","label":"Concrete volume","precision":2},
  "secondary": [
    {"value":6.75,"unit":"cuyd","label":"Order quantity","precision":2},
    {"value":176,"unit":"cuft","label":"Concrete volume","precision":1},
    {"value":384,"unit":"sqft","label":"Slab area","precision":0},
    {"value":26400,"unit":"lb","label":"Concrete weight","precision":0},
    {"value":392,"unit":"bag","label":"60 lb bags","precision":0},
    {"value":1,"unit":"load","label":"Truck loads","precision":0},
    {"value":10,"unit":"ft","label":"Control-joint spacing","display":"10'-0″ to 15'-0″"},
    {"value":1113.75,"unit":"usd","label":"Estimated concrete cost","precision":2}
  ],
  "takeoff": [
    {"key":"readymix","item":"Ready-mix concrete","qty":5.93,"unit":"cuyd","waste":10,"order":6.75,"orderUnit":"cuyd","note":"Rounded up to the nearest 0.25 cu yd."},
    {"key":"bags","item":"Bagged concrete mix, 60 lb","qty":176,"unit":"cuft","waste":10,"order":392,"orderUnit":"bag","note":"0.45 cu ft per bag."},
    {"key":"trucks","item":"Ready-mix truck loads","qty":6.52,"unit":"cuyd","order":1,"orderUnit":"load","note":"10 cu yd per load (your assumption)."},
    {"key":"gravel","item":"Compacted base, 4″","qty":4.74,"unit":"cuyd","order":6.5,"orderUnit":"cuyd","note":"Loose volume ordered = compacted volume x 1.31 (3,570 / 2,730 lb/cu yd, FHWA Exhibit 5.1 A, gravel dry, average gradation; 1.17 uniformly graded, 1.49 well graded). For estimating purposes, ±33%: a highway embankment, not a plate-compacted base."},
    {"key":"cost","item":"Concrete cost at your price","qty":6.75,"unit":"cuyd","order":1113.75,"orderUnit":"usd","note":"6.75 cu yd x $165.00 / cu yd."}
  ],
  "warnings": [
    {"level":"caution","code":"too-many-bags","message":"392 bags is a day of mixing. Price a ready-mix delivery instead."}
  ],
  "assumptions": [
    "Volume = length x width x thickness; 1 cubic yard = 27 cubic feet.",
    "Waste allowance 10% applied to the net volume.",
    "Ready-mix rounded up to 0.25 cu yd; truck capacity 10 cu yd (editable).",
    "Bag yield 0.45 cu ft per 60 lb bag of standard concrete mix.",
    "Unit weight 150 lb/cu ft (editable; normal-weight concrete runs about 140-155).",
    "Contraction joints at 24-36 times the slab thickness, capped at 15 ft (NRMCA CIP 6).",
    "Thickness, reinforcement and base depth come from your drawings or local code."
  ]
}
```

## How the numbers are sourced

- Formulas, constants and rounding rules come from the engine bundle. `vendor/ENGINE_COMMIT.txt` records the commit it
  was built from, and every response carries the calculator's `engine_version` and `revised` date.
- Each tool computes with the same engine as its page on the site. `calc_gravel`, for instance, runs the engine
  behind https://takeoffmetric.com/earthwork/gravel-calculator/.
- `search_constants` reads `vendor/constants.csv` (148 rows). Each row gives the value, its unit, the SI value, the
  condition it applies to, and the publisher, title and URL of the document it was read from.
- The site's methodology (tested formulas, assumptions shown on the page, sources as documents, versioned sheets) is
  at https://takeoffmetric.com/methodology/.

## Limits

- Results are estimates. Confirm quantities with your plans, your supplier and your local code before ordering or building.
- This release covers 15 calculators. Calculators that apply building-code provisions, or that rely on third-party
  tables the site links to without reproducing them, are not part of it.
- Responses carry numbers and notes only: no drawing and no CSV export.
- `unit` fields use the engine's unit codes. Several results that are not plain counts are coded `ea`; read `label`
  and `display` for their meaning.
- Prices are whatever you type in. The server holds no price data and makes no network request.
- Transport is stdio only.

## Development

```bash
npm install
npm test
```

The tests run with this repository alone. `npm run sync-engine` and `npm run make-fixtures` are maintainer scripts:
they rebuild `vendor/` and `test/fixtures.json` from the site's source repository, which users of the package never need.

## License

Server code: MIT. Calculation engine (`vendor/engine.mjs`): copyright TakeoffMetric, distributed with this package to run
as part of it, not licensed for modification or separate redistribution. Both are set out in `LICENSE`.
Constants table: CC BY 4.0, see `DATA_LICENSE.md`.