Building an AI agent
If you are giving a model the ability to read and act on an MTRO PRO portfolio, you have two starting points. Pick the MCP server unless you have a reason not to.
Option 1 — the MCP server
MTRO PRO ships an MCP server that wraps the
API in 172 tools, each with a description and typed arguments the model can use
directly: properties_list, bookings_create, leads_update_stage,
conversations_send_message, and so on.
It handles authentication, path building, and the error envelope for you, and it is tested against the live route table, so a tool cannot silently point at an endpoint that no longer exists.
The server is open source and MIT licensed, at github.com/mtropro/mcp. Run it pinned to a release tag:
npx -y github:mtropro/mcp#v1.0.0
Configure it with your API key:
{
"mcpServers": {
"mtropro": {
"command": "npx",
"args": ["-y", "github:mtropro/mcp#v1.0.0"],
"env": {
"MTROPRO_API_KEY": "mtro_your_api_key",
"MTROPRO_API_URL": "https://core.mtro.app"
}
}
}
}
Every operation in the API reference names the MCP tool that calls it, so you can move between the two views freely.
Option 2 — the OpenAPI document
If you are building tools yourself, generate them from the contract rather than by hand:
https://core.mtro.app/openapi.json
It is public, needs no key, and carries everything a generator needs: operation
ids, parameters, request schemas, and the scope each operation requires under
x-mtro-scopes. There is a browsable console at
https://core.mtro.app/api-docs.
Rules your agent has to respect
Check error in the body, not just the status. Some failures come back as
HTTP 200 with error: true. An agent that reads the status alone will report a
refused write as a success and carry on. See
Errors and conventions.
Give the key the narrowest scopes that work. A key with no scopes inherits
everything its creator can do. A read-only agent should hold only the .read
scopes it needs. See Authentication and scopes.
Put a human in front of anything that leaves the building. Sending a message reaches a real guest. Creating a payment or a checkout link moves real money. Signing a lease is a legal act. These should require explicit confirmation, not model judgement.
Read before you write. Stage ids, vendor ids, and property ids are per-organization. Fetch the list, then act on an id from it, rather than assuming.
Poll, do not wait. There are no outbound webhooks. Nothing will notify your agent that a message arrived; it has to look.
Watch the shape of list responses. Almost nothing is paginated. A portfolio with hundreds of properties returns all of them in one response, which is a large amount of context to hand a model. Filter before you put it in a prompt. Conversations, logs, and notifications are the exceptions and do take page parameters — use them.
A sensible first agent
A read-only assistant is a good place to start and carries almost no risk:
- Create a key with
properties.read,bookings.read,guests.read,leads.read,conversations.read,tasks.read,vendors.read. - Point it at the development environment first.
- Let it answer questions: which properties are free next month, which leads have gone quiet, which tasks are overdue.
- Add write scopes one at a time, each behind a confirmation step, once you trust what it does with reads.