ModuHaus-MCP
Click on "Install Server".
Wait a few minutes for the server to deploy. Once ready, it will show a "Started" state.
In the chat, type
@followed by the MCP server name and your instructions, e.g., "@ModuHaus-MCPCompare granny flat rules in NSW and VIC"
That's it! The server will respond to your query, and you can continue using it as needed.
Here is a step-by-step guide with screenshots.
ModuHaus — Australian Modular House Knowledge Base
A PostgreSQL-backed knowledge base covering everything a buyer or builder needs to know about modular housing in Australia: planning regulation, finance, cost, suppliers, contracts and construction. It is built to be consumed by an MCP server and by interactive tools on the ModuHaus website (site feasibility lookup, budget estimator, and so on).
The knowledge base is deliberately built one module at a time. The schema and naming conventions below exist so that later modules drop into the same database without restructuring anything.
Design principles
One database, many modules. Everything lives in modular_house_kb. The name
describes the whole knowledge base, not any single feature — there is no
granny_flat_db. A single database keeps cross-module queries possible: a
feasibility check that combines a planning rule with a cost band and a supplier
lead time should be one SQL query, not three round trips.
The table name carries the module. Every table is prefixed with its module, so
\dt in psql groups the schema by domain and any reader can tell at a glance what
a table belongs to:
regulation_* planning rules, permit pathways, DA process
finance_* construction loan structures, lender policies, rates
cost_* build cost ranges by spec and region
supplier_* suppliers, product lines, specifications, reputation
contract_* standard clauses, common dispute points
construction_* timelines, transport and install, delay causesRows are jurisdiction-scoped and source-stamped. Australian modular housing
rules differ per state and change often. Every fact-bearing table carries the
jurisdiction it applies to plus source and last_verified, so stale content is
visible rather than silently wrong. Never store a regulatory number without the
instrument it came from.
Related MCP server: au-eli-mcp
Current status
Completed — Regulation module, granny flat subset
regulation_granny_flat_rules holds state-level approval standards for secondary
dwellings (granny flats, office pods).
Column | Type | Notes |
| SERIAL PK | |
| VARCHAR(10) |
|
| VARCHAR(50) |
|
| VARCHAR(100) | the specific rule being described |
| NUMERIC | |
| NUMERIC | |
| BOOLEAN | whether approval is needed by default |
| TEXT[] | overlays/hazards that void the pathway |
| VARCHAR(50) | e.g. |
| INTEGER | |
| VARCHAR(50) | e.g. |
| INTEGER | |
| TEXT | the planning instrument |
| DATE |
All eight jurisdictions are seeded. The headline numbers:
State | Max area | Min lot | Permit by default | Instrument |
NSW | 60 sqm | 450 sqm | yes (CDC) | SEPP (Housing) 2021 |
VIC | 60 sqm | 300 sqm | no | Amendment VC253 |
QLD | — | — | — | set by each council |
WA | 70 sqm | — | no | R-Codes Vol 1 |
SA | 70 sqm | — | yes | Planning and Design Code |
TAS | 60 sqm | — | no | State Planning Provisions |
ACT | 90 sqm | 500 sqm | yes | Territory Plan 2023 |
NT | 75 sqm | — | no | NT Planning Scheme 2020 |
Every row was checked against the responsible planning authority's own site on
its last_verified date. Where a jurisdiction publishes no single statewide
figure the column is NULL rather than a number borrowed from a builder's
website — see the NULL semantics gap below before reading those blanks.
Two rows deserve explanation:
QLD sets no statewide standard at all. The Planning Act 2016 leaves both size and assessment pathway to each local government's planning scheme, so every numeric column is
NULLanddata_statusisno_rule_at_this_level. The only statewide rule is the 2022 amendment removing occupancy restrictions. Queensland's real numbers live inregulation_lga_granny_flat_rules.default_permit_requiredmeasures whether approval is needed at all, not how fast it is. NSW istruebecause a complying development certificate is still issued; VIC, WA, TAS and NT arefalsebecause the requirement is removed outright when the conditions are met.
UNIQUE (state, category, rule_type) is the natural key. Note that
default_permit_required is not a measure of speed but of whether approval is
needed at all: NSW is true because a complying development certificate is still
issued, while VIC is false because the permit requirement is removed outright.
The VIC row was verified against Planning Victoria on 2026-08-11: Amendment VC253, gazetted 14 December 2023, is the correct instrument, and the 300 sqm minimum lot size is confirmed for the residential zones.
Completed — Regulation module, council-level subset
regulation_lga_granny_flat_rules mirrors the state table plus lga_name,
planning_scheme and varies_from_state. Queensland depends on it entirely;
elsewhere a row should exist only where a council departs from the state
position, so the absence of a row means the state rule applies.
Seeded with four Queensland councils. Only City of Moreton Bay is fully
verified — its limit steps with lot area (45 sqm on 450–800 sqm lots, 55 sqm
above 800 sqm, 100 sqm in rural zones), which is why it holds three rows.
Brisbane, Gold Coast and Logan have confirmed floor-area limits but unconfirmed
approval pathways, recorded in unresearched_fields.
Still to add: Sunshine Coast, Ipswich, Townsville, Cairns, Toowoomba, Redland, and the remaining Queensland councils.
Note that published builder and comparison sites disagree with the councils' own schemes on these numbers — Moreton Bay is widely quoted as 90 sqm when the scheme says 45/55/100. Seed only from the responsible authority's own document.
Planned modules
Finance — construction loan structures, per-lender policy, progress payment schedules, current rates.
Cost — build cost ranges by size and specification, regional differentials, site cost drivers.
Supplier — suppliers, product lines, specifications, certifications, reviews.
Contract — standard clauses, variation and delay provisions, common disputes.
Construction — lead times, transport and craneage, install sequence, typical causes of delay.
Setup
Requires PostgreSQL 14+ and uv.
uv syncCopy .env.example to .env and set DB_PASSWORD to your PostgreSQL password.
.env is gitignored and must never be committed; db.py is the only place
credentials are read, and every script imports from it.
uv run setup_db.py # create the database, tables, migrations, constraints
uv run insert_rules.py # seed the state-level granny flat rules
uv run insert_lga_rules.py # seed the council-level rules
uv run query_rules.py # read them backAll four are safe to re-run. setup_db.py creates only what is missing and
applies migrations that are no-ops once current; the seed scripts update
existing rows in place instead of duplicating them.
MCP server
mcp_server.py exposes the knowledge base over the Model Context Protocol
(stdio transport, built on the official mcp SDK):
uv run mcp_server.pyTool | Answers |
| "Can I build one in X, how big, and do I need approval?" — returns the state rule plus any council rules |
| "Which state is easiest?" — cross-jurisdiction comparison |
| "Is this still current?" — flags rules not re-verified recently |
The server's contract is that a null is never a fact. Every null comes back
with a why_missing entry naming one of the three reasons above, and any field
whose value is genuinely unknown is also listed in must_not_state. A model
relaying an answer has to work against the payload to invent a figure, rather
than merely failing to notice a blank. Day counts always travel with their
_basis, and every rule carries source and last_verified.
rules.py holds the read layer and the why_null logic. Both the CLI and the
MCP server go through it, so the two can never disagree about what a blank cell
means — this is the one piece of logic worth centralising, because the failure
it prevents is a fabricated regulatory answer.
To register it with an MCP client, point the client at
uv run mcp_server.py with this directory as the working directory. The server
reads credentials from .env like every other script.
Querying
uv run query_rules.py # every state
uv run query_rules.py NSW # one state
uv run query_rules.py nsw vic # severalConventions for adding a module
Name the table
<module>_<subject>. Use the module prefixes listed above; add a new prefix only for a genuinely new domain, and document it here. Table and column names aresnake_case, table names plural where the row is one of many (..._rules,..._lenders).Put units in the column name.
max_floor_area_sqm,fallback_max_days,deposit_pct. A bareareaordayscolumn will eventually be misread.Every fact-bearing table gets
sourceandlast_verified. Regulations, rates and prices all go stale. A row without provenance cannot be trusted by the MCP server and should not be inserted.Scope by jurisdiction where it varies. Add
state(andlgaif the rule operates at council level) rather than storing a national average that is wrong everywhere.Distinguish
NULLfrom zero and from false.NULLmeans not applicable or not yet researched; encode "no permit needed" asdefault_permit_required = false, not as a missing row.Add the DDL to
MODULE_TABLESinsetup_db.pyso a fresh clone builds the whole schema in one command. Keep the DDLCREATE TABLE IF NOT EXISTS.One seed script per module subset, named for what it loads (
insert_rules.py, laterinsert_lender_policies.py). Make it idempotent by keying on the table's natural key so re-running never duplicates data.Import connections from
db.py. Do not build a connection string or reados.environanywhere else.Give every table a natural-key
UNIQUEconstraint and register it inMODULE_CONSTRAINTSinsetup_db.py. Seed scripts then useON CONFLICT (...) DO UPDATE, which is atomic and safe to re-run. Enforcing the key in the database rather than in Python matters because the MCP server, bulk imports and manual SQL all write to these tables too, and none of them go through the seed scripts.
Reading a NULL
A blank cell is never self-explanatory, so two columns carry the reason:
meaning | how to read a | |
column named in | nobody has looked it up | unknown — never present as fact |
| the jurisdiction legislates elsewhere | look one level down (QLD → councils) |
otherwise, | researched, genuinely absent | not applicable |
data_status is one of verified, partial (some fields still in
unresearched_fields) or no_rule_at_this_level. The distinction matters most
to the MCP server: telling a Queensland user "no permit required" because a
column was NULL would be a fabricated answer, and this is what stops it.
Day counts
fast_track_days and fallback_max_days are meaningless without
*_days_basis, which is business or calendar. NSW, VIC, WA and TAS count
calendar days; SA, QLD and ACT count business days. 35 business days is roughly
49 calendar days, so mixing them silently breaks any duration arithmetic. A
CHECK constraint refuses a day count whose basis is missing.
Where a jurisdiction publishes two periods, the longer one is stored and the
shorter is noted in source — better to under-promise on a timeline. NT stores
no figure at all because the Development Consent Authority decides at monthly
meetings rather than within a set period.
Known schema gaps
Recorded rather than fixed, so the next person does not mistake them for oversights. Each needs a schema change, not just more rows:
No zone dimension. Victoria's exemption is written per zone (RGZ, GRZ, NRZ, plus rural zones), and the 300 sqm lot threshold applies to those residential zones specifically. WA, SA, TAS and NT all set minimum lot size and sometimes maximum floor area per zone too, which is why those cells are blank. Moreton Bay is currently modelled with one row per lot-size band, which works but would not survive a council that varies by zone and by band.
"Researched, but no published figure" has no encoding. NT's missing decision period is recorded as
verifiedwith an explanation insource, because it is neither unresearched nor truly inapplicable. If this case recurs it deserves its owndata_statusvalue.One row cannot express a threshold split. Victoria is really two rules: over 300 sqm the permit exemption applies; at or under 300 sqm a permit is always required and Clause 54 / VicSmart applies (Amendment VC282, in operation 8 September 2025). This should become a second row with its own
rule_typeonce the sub-300 sqm pathway is researched.Pending changes are recorded only as prose. Tasmania's SPP amendment 01/2026 would raise 60 sqm to 90 sqm but is not gazetted; that fact currently lives in a sentence inside
source. Anything that needs to answer "what is changing soon" needs real columns.Council coverage is partial, and absence is ambiguous. The convention is that a missing council row means the state rule applies — but for a council nobody has researched, it equally means "unknown". The MCP server says so in words on every response; the schema cannot yet distinguish the two.
Only negative conditions are modelled.
excluding_conditionscaptures what disqualifies a site. Victoria also imposes positive conditions — no more than one existing dwelling on the lot, only one small second dwelling, and no reticulated natural gas connection — which have nowhere to live yet.One row cannot express a threshold split. Victoria is really two rules: over 300 sqm the permit exemption applies; at or under 300 sqm a permit is always required and Clause 54 / VicSmart applies (Amendment VC282, in operation 8 September 2025). This should become a second row with its own
rule_typeonce the sub-300 sqm pathway is researched.
Maintenance
Resources
Unclaimed servers have limited discoverability.
Looking for Admin?
If you are the server author, to access and configure the admin panel.
Related MCP Servers
- Flicense-qualityBmaintenanceProvides comprehensive Australian planning property reports, including zoning, overlays, land size, and utility information for AI assistants. This high-performance MCP server is built for Cloudflare Workers and enables real-time property data retrieval through an HTTP-based interface.
- AlicenseAqualityAmaintenanceMCP server for Australia's Federal Register of Legislation. Enables searching and fetching Commonwealth Acts with verifiable citations.2Apache 2.0
- Flicense-qualityCmaintenanceThis MCP server integrates South Korea's national law information, building registers from MOLIT, and KOSIS statistics for housing development research. It enables searching laws, retrieving building details, and accessing statistical data through natural language.
- AlicenseAqualityBmaintenanceMCP server for HUD housing data, enabling Fair Market Rent lookups, Section 8 income limits, and ZIP-to-county crosswalk mapping for affordable housing assessments.6MIT
Related MCP Connectors
This MCP server provides seamless access to Malaysia's government open data, including datasets, w…
MCP server giving Claude AI access to 22+ NYC public-record databases for real estate due diligence
MCP server for generating rough-draft project plans from natural-language prompts.
Latest Blog Posts
- Who's Calling? MCP Hosts Are an Identity Blind Spot (And the Spec Knows It)By Om-Shree-0709 on .mcpAgent IdentityOAuth 2.1
- Your AI Chatbot Just Exposed Your CEO's Salary to an InternBy Om-Shree-0709 on .Agent IdentityMCP SecurityOAuth Delegation
- Why MCP Servers Need Execution Sandboxing (And Why Your Current Stack Isn't Enough)By Om-Shree-0709 on .Agentic AiPrompt InjectionWebAssembly
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/HMEI83/Moduhaus-MCP'
If you have feedback or need assistance with the MCP directory API, please join our Discord server