We provide all the information about MCP servers via our MCP API.
curl -X GET 'https://glama.ai/api/mcp/v1/servers/jrszilard/diy-helper-mcp-servers'
If you have feedback or need assistance with the MCP directory API, please join our Discord server
"""
Material Quantity Calculators
Calculate how much material is needed for various projects
"""
import math
from typing import Dict, Optional
class MaterialCalculator:
"""Calculate material quantities for various projects"""
@staticmethod
def calculate_wire_length(
circuit_length_feet: float,
num_circuits: int = 1,
waste_factor: float = 0.15
) -> Dict:
"""
Calculate electrical wire needed
Args:
circuit_length_feet: One-way distance in feet
num_circuits: Number of circuits
waste_factor: Percentage extra for waste/mistakes (default 15%)
"""
# Wire needs to go and return, plus waste
total_feet = circuit_length_feet * 2 * num_circuits
with_waste = total_feet * (1 + waste_factor)
# Round up to nearest 25 feet (common spool sizes)
recommended_feet = math.ceil(with_waste / 25) * 25
return {
"base_feet": total_feet,
"with_waste": with_waste,
"recommended_feet": recommended_feet,
"waste_factor": waste_factor,
"note": f"Buying {recommended_feet}ft gives you buffer for mistakes and future repairs"
}
@staticmethod
def calculate_outlets_needed(
room_perimeter_feet: float,
room_type: str = "living"
) -> Dict:
"""
Calculate number of outlets needed per NEC
Args:
room_perimeter_feet: Total wall perimeter
room_type: 'living', 'kitchen', 'bathroom', 'garage'
"""
if room_type == "kitchen":
# Kitchen countertop: outlet every 4 feet (24 inches from any point)
# Assuming countertop is 50% of perimeter
countertop_length = room_perimeter_feet * 0.5
outlets = math.ceil(countertop_length / 4)
code_ref = "NEC 210.52(C)(1)"
note = "Kitchen countertops require outlets every 4 feet maximum"
elif room_type == "bathroom":
# Bathroom: at least 1 GFCI outlet
outlets = max(1, math.ceil(room_perimeter_feet / 12))
code_ref = "NEC 210.52(D)"
note = "Bathroom requires at least one GFCI outlet, all must be GFCI protected"
else: # living, bedroom, etc.
# General rule: outlet every 12 feet (no point more than 6 feet from outlet)
outlets = math.ceil(room_perimeter_feet / 12)
code_ref = "NEC 210.52(A)(1)"
note = "Living spaces require outlets every 12 feet of wall space"
return {
"outlets_needed": outlets,
"room_type": room_type,
"perimeter_feet": room_perimeter_feet,
"code_reference": code_ref,
"note": note
}
@staticmethod
def calculate_tile_needed(
area_sq_ft: float,
tile_size_inches: tuple = (12, 12),
waste_factor: float = 0.10
) -> Dict:
"""
Calculate tile needed for floor/wall
Args:
area_sq_ft: Total area to tile
tile_size_inches: (width, height) in inches
waste_factor: Extra for cuts/breakage (default 10%)
"""
# Convert tile size to sq ft
tile_width_ft = tile_size_inches[0] / 12
tile_height_ft = tile_size_inches[1] / 12
tile_area_sq_ft = tile_width_ft * tile_height_ft
# Calculate base tiles needed
base_tiles = math.ceil(area_sq_ft / tile_area_sq_ft)
# Add waste factor
total_tiles = math.ceil(base_tiles * (1 + waste_factor))
# Calculate cases (assume 10 tiles per case typically)
tiles_per_case = 10
cases_needed = math.ceil(total_tiles / tiles_per_case)
total_coverage = cases_needed * tiles_per_case * tile_area_sq_ft
return {
"area_sq_ft": area_sq_ft,
"tile_size": f"{tile_size_inches[0]}x{tile_size_inches[1]} inches",
"tiles_needed": total_tiles,
"cases_needed": cases_needed,
"total_tiles": cases_needed * tiles_per_case,
"total_coverage_sq_ft": round(total_coverage, 1),
"waste_factor": waste_factor,
"note": f"Ordering {cases_needed} cases gives you {total_tiles - base_tiles} extra tiles for cuts and repairs"
}
@staticmethod
def calculate_paint_needed(
area_sq_ft: float,
coats: int = 2,
coverage_per_gallon: int = 350
) -> Dict:
"""
Calculate paint needed
Args:
area_sq_ft: Total wall/ceiling area
coats: Number of coats (default 2)
coverage_per_gallon: Sq ft per gallon (default 350)
"""
total_area = area_sq_ft * coats
gallons_needed = total_area / coverage_per_gallon
# Round up to nearest gallon
gallons_to_buy = math.ceil(gallons_needed)
return {
"area_sq_ft": area_sq_ft,
"coats": coats,
"total_area_to_cover": total_area,
"gallons_needed": round(gallons_needed, 2),
"gallons_to_buy": gallons_to_buy,
"coverage_per_gallon": coverage_per_gallon,
"note": f"Buy {gallons_to_buy} gallon(s) for {coats} coats"
}
@staticmethod
def calculate_lumber_for_deck(
deck_length_ft: float,
deck_width_ft: float,
joist_spacing_inches: int = 16,
board_width_inches: float = 5.5
) -> Dict:
"""
Calculate lumber needed for deck framing and decking
Args:
deck_length_ft: Deck length
deck_width_ft: Deck width
joist_spacing_inches: Joist spacing (typically 16")
board_width_inches: Deck board width (typically 5.5" for 2x6)
"""
area_sq_ft = deck_length_ft * deck_width_ft
# Calculate joists needed
num_joists = math.ceil((deck_width_ft * 12) / joist_spacing_inches) + 1
# Calculate deck boards needed
board_width_ft = board_width_inches / 12
num_boards = math.ceil(deck_length_ft / board_width_ft)
# Calculate posts (assume one every 6-8 feet)
posts_length = math.ceil(deck_length_ft / 6)
posts_width = math.ceil(deck_width_ft / 6)
total_posts = posts_length * posts_width
return {
"deck_size": f"{deck_length_ft}x{deck_width_ft} feet",
"area_sq_ft": area_sq_ft,
"joists": {
"quantity": num_joists,
"size": f"2x8x{math.ceil(deck_width_ft)} (or 2x10 for larger spans)",
"spacing": f"{joist_spacing_inches} inches on center"
},
"decking_boards": {
"quantity": num_boards,
"size": f"2x6x{math.ceil(deck_width_ft)} or 5/4x6 composite",
"note": "Add 10% for cuts and waste"
},
"posts": {
"quantity": total_posts,
"size": "4x4x10 or 4x4x12 depending on height",
"note": "Actual quantity depends on height and local code"
},
"note": "This is a basic estimate. Consult building codes for beam sizes and post spacing based on deck height."
}
@staticmethod
def calculate_pex_pipe(
num_fixtures: int,
avg_distance_per_fixture: float = 30,
manifold_system: bool = True
) -> Dict:
"""
Calculate PEX piping needed for plumbing
Args:
num_fixtures: Number of fixtures (sinks, toilets, etc.)
avg_distance_per_fixture: Average run length in feet
manifold_system: True for home-run, False for trunk-and-branch
"""
if manifold_system:
# Home-run: each fixture gets dedicated line from manifold
hot_water_fixtures = math.ceil(num_fixtures * 0.6) # ~60% need hot
cold_water_fixtures = num_fixtures
hot_pipe_feet = hot_water_fixtures * avg_distance_per_fixture
cold_pipe_feet = cold_water_fixtures * avg_distance_per_fixture
else:
# Trunk-and-branch: more efficient but more complex
hot_pipe_feet = (num_fixtures * 0.6) * avg_distance_per_fixture * 0.7
cold_pipe_feet = num_fixtures * avg_distance_per_fixture * 0.7
# Add 20% waste
hot_total = math.ceil(hot_pipe_feet * 1.2)
cold_total = math.ceil(cold_pipe_feet * 1.2)
# Round to coil sizes (100ft or 300ft)
def round_to_coil(feet):
if feet <= 100:
return 100
elif feet <= 300:
return 300
else:
return math.ceil(feet / 300) * 300
hot_to_buy = round_to_coil(hot_total)
cold_to_buy = round_to_coil(cold_total)
return {
"system_type": "Manifold (home-run)" if manifold_system else "Trunk-and-branch",
"fixtures": num_fixtures,
"hot_water_pipe": {
"feet_needed": hot_total,
"feet_to_buy": hot_to_buy,
"size": "1/2 inch PEX",
"color": "Red"
},
"cold_water_pipe": {
"feet_needed": cold_total,
"feet_to_buy": cold_to_buy,
"size": "1/2 inch PEX",
"color": "Blue"
},
"note": "Also budget for manifold, fittings, and crimp rings. Consider 3/4 inch for main lines."
}