Property Ops MCP Server
A Model Context Protocol server that gives AI assistants scoped, policy-checked, audited access to a property manager's work orders, with every change approved by a person.
- Agent Lab · sample data for Keystone Property Management
- Design & Engineering
- Agent Lab · 2026
Overview
Businesses want to connect Claude or ChatGPT to their own systems, but not with unlimited access. This MCP server exposes a property manager's maintenance system through eight tools: five that read and three that write. Writes need the write scope, pass the maintenance policy in code (right trade, 24/7 vendors for emergencies, insurance current, spend limits), and are logged whether they succeed or not. The demo console connects a model over stdio, exactly as Claude Desktop does, and pauses every write for a person to approve.
The Problem
Giving an AI assistant access to operational data is easy; giving it safe access is not. The assistant must not see more than it needs, must not change anything it isn't allowed to, and every action must be traceable.
- ▸Most quick integrations hand the model broad API keys and hope for the best.
- ▸Business rules like approval limits and insurance checks live in people's heads, not in the integration.
- ▸When something goes wrong, there's no record of what the assistant tried to do.
The Solution
A least-privilege MCP server where a single gate checks every call in order: the tool exists, the connection holds the scope, the input validates, and the policy allows it. Then it writes an audit entry.
- ✓Read and write scopes per connection; a read-only server refuses writes before reading the arguments.
- ✓Policy in code: trade match, 24/7 vendors for emergencies, current insurance, spend over $500 to the owner, legal status changes.
- ✓No tool returns tenant phone numbers, emails or rent; message recipients are resolved by the server.
- ✓Works with Claude Desktop over stdio, and with any MCP client.
Architecture
An MCP server on the official SDK, a policy module that also generates the policy document, and a console that turns MCP tools into model function specs.
MCP server
tools/list and tools/call handled on the SDK's Server so refused calls are still audited; resources for the policy and the live work-order board.
Policy & store
Maintenance rules as tested code, and an in-memory property system seeded with 3 buildings, 24 units, 8 vendors and 10 open work orders.
Console client
Launches the server as a child process over stdio, converts MCP JSON Schemas to function specs, and pauses writes for approval.
Audit
Every call, allowed or denied, logged with arguments and outcome, and sent to the client as MCP log messages.
Key Features
Scoped access
Grant read, or read and write. A read-only connection is refused by the server, whatever the model tries.
Policy enforced in code
Vendors must match the trade, be available 24/7 for emergencies and be insured on the day.
Approval for every write
Each change appears as a card, for example assign a plumber not to exceed $560, before it reaches the server.
Claude Desktop ready
The README ships the exact config to connect Claude Desktop to the server.
Technology Stack
Design & Engineering
Designed the tool contracts, scopes and policy on the shared Agent Lab runtime, and directed the build.
- ▪Defined the eight tools, their scopes and what data each is allowed to return.
- ▪Wrote the maintenance policy and a realistic Saturday-morning work-order queue with traps: a duplicate leak, lapsed insurance, a gas fitter who only works weekdays.
- ▪Specified the approval and audit behaviour for every write.
- ▪Reviewed the console so scopes, approvals and denials are obvious on screen.
Product UI



Technical Challenges
Auditing refused calls
Challenge: The SDK validates arguments before a registered handler runs, so rejected calls never reach application code.
Solution: tools/list and tools/call are handled on the SDK's underlying Server, so one gate validates, enforces policy and audits every call.
Money the model can't miscalculate
Challenge: In early runs the model got not-to-exceed amounts wrong.
Solution: The server computes the policy amount and returns it with the qualified vendors, and refuses any amount more than 10% off.
Triage the model can't get backwards
Challenge: On a small, fast model, one run filed the gas smell as urgent and raised the elderly tenant's AC to an emergency.
Solution: Priority rules moved into the server: gas is always an emergency, a vulnerable occupant at 87°F is urgent, and no vendor is assigned until the work order is at its policy priority.
Secrets stay out of the server
Challenge: A child process launched from the web app could inherit API keys.
Solution: The server starts with the SDK's minimal environment, so it never sees the model provider's keys.
Outcomes & Highlights
In the demo the assistant triages the whole queue: the leak and gas smell handled as emergencies, the elderly tenant's AC raised to urgent, a duplicate closed, and tenants messaged, with every change approved and logged.
- ✓Eight tools, five read and three write, each validated and audited.
- ✓Policy rules tested one by one, including scope denial and insurance expiry.
- ✓One test launches the stdio entry exactly as Claude Desktop does.
- ✓A read-only connection is refused by the server even when a person approves.
- 8
- MCP tools
- 100%
- Calls audited
- 0
- Writes without approval
5 read, 3 write
Allowed or denied
Each change is a card
