Skip to main content
Glama
dragosh29

Dezrez Rezi MCP server

by dragosh29

Dezrez Rezi MCP server

An MCP server that lets Claude, ChatGPT and other MCP clients read an estate agency's Dezrez Rezi CRM: properties and their marketing roles, property and group timelines (viewings, offers, notes, appointments), people, groups (households and companies) and offers. It is built from Dezrez's public documentation: the Rezi API Swagger 2.0 document at api.dezrez.com/swagger/docs/v1 and the developer guides in the public DezrezCoreAPI repository (OAuth2 flows, the Rezi-Api-Version header, the agencyId rule).

Once it's connected, someone at the agency can ask things like:

  • "What happened at 12 High Street this month? Any feedback from the viewings?"

  • "Which of our sales are under offer, and at what price?"

  • "Find the Evans family. What are they buying and renting, and how many viewings have they had?"

  • "List the open offers and who made them."

  • "Who is in the Patel group, and what did they answer about their mortgage?"

This version is read-only. There are no write tools at all: creating leads, booking viewings and recording offers need scopes and a test agency that were not available when it was built, and a write that cannot be tested against a real account should not be shipped (see Status).

Tools

Tool

What it does

API calls

get_property

One property: address, status, marketing roles (sale or letting, with status), certificates, special arrangements, keys (holder and check-out status), the number of alarms, custom fields, default picture link. Key and alarm codes are never returned.

GET /api/property/{id}

search_properties

Search property marketing roles by free text, on-market flag, role type and role status, with the property address, prices, summary line and owning group. Pages by page/max_results.

GET /api/role/suggest

get_property_events

A property's timeline: viewings, offers, notes, appointments and other events, with the documented filters from, to, type (repeated), excludedTypes (repeated), eventCategoryType, branchId, showCancelled and includeOnlyOriginalNotes.

GET /api/property/{id}/events

get_person

One person: name, gender, group memberships, marketing preferences, custom fields, dates. Contact items, addresses, the note and identity details only on request.

GET /api/people/{id}

find_people

Search by surname, postcode, email, telephone and/or mobile, exactly the parameters the endpoint documents. No paging on the API side.

GET /api/people/findbydetails

get_person_roles

The properties a person is selling, letting, buying or renting, with price, offer and viewing counts. The address is reduced to town, county and country by default (a buyer's or tenant's property is their home); the full address on request.

GET /api/people/{id}/roles

get_group

One group (household or company): members by name, type, status, applicant qualification answers, preferred companies, custom fields.

GET /api/group/{id}

get_group_events

A group's timeline, with the property-event filters plus activeRolesOnly, propertyId, roleId and includeDrafts.

GET /api/group/{id}/events

list_offers

Offers across the agency, paged: value, status, property, applicant and vendor groups, marketed price, response, negotiators.

GET /api/Offer

get_offer

One offer in full, including the vendor's response and communication, notes and documents (name, type, link).

GET /api/Offer/{id}

Not covered on purpose: everything else in a 1,400-operation API, including documents and their downloads, diary and appointments, valuations, progression, tenancies, accounting, and every write. GET /api/people/{id}/accounts and GET /api/people/{id}/bankReferences (bank details) are never called; the test suite asserts it.

Related MCP server: Qobrix CRM MCP Server

Setup

Requires Node 18 or later.

npm install
npm run build

You need an OAuth2 client registered with Dezrez. Registration is by request (developer.dezrez.com/api-request or developer.registration@dezrez.com, per HowToRegister.md); Dezrez decides the flow (code, implicit, resource owner, client credentials) and the scopes. Two environments exist: LIVE (https://api.dezrez.com, token endpoint https://auth.dezrez.com/Dezrez.Core.Api/oauth/token/) and UAT (https://core-api-uat.dezrez.com, https://dezrez-core-auth-uat.dezrez.com/Dezrez.Core.Api/oauth/token/).

The server authenticates in one of two ways:

  • An access token you already have (DEZREZ_ACCESS_TOKEN), obtained through whichever flow your client is registered for. Access tokens last about two hours according to the overview, so this is for testing and for hosts that refresh the token themselves. A value pasted with its Bearer prefix is accepted. With a user token (code, implicit or resource-owner flow) no agencyId is needed; if DEZREZ_AGENCY_ID is set it is sent anyway.

  • Client credentials (DEZREZ_CLIENT_ID and DEZREZ_CLIENT_SECRET): the server posts to the token endpoint as DezrezCoreAPIOverview.md documents (Authorization: Basic base64(clientId:clientSecret), JSON body {"grant_type":"client_credentials","scope":"..."}), caches the token until a minute before its expires_in (or halfway through its life, for a token shorter than two minutes; an hour when expires_in is absent), shares one token request between tool calls that start at the same time, and fetches a new one if the API answers 401. Dezrez documents that a client token "must" carry the agencyId parameter on every request, so DEZREZ_AGENCY_ID is required and the server refuses to start without it.

Claude Desktop: add this to claude_desktop_config.json:

{
  "mcpServers": {
    "dezrez": {
      "command": "node",
      "args": ["/absolute/path/to/dezrez-mcp/dist/index.js"],
      "env": { "DEZREZ_CLIENT_ID": "your-client-id", "DEZREZ_CLIENT_SECRET": "your-client-secret", "DEZREZ_AGENCY_ID": "1234" }
    }
  }
}

Claude Code:

claude mcp add dezrez -e DEZREZ_CLIENT_ID=your-client-id -e DEZREZ_CLIENT_SECRET=your-client-secret -e DEZREZ_AGENCY_ID=1234 -- node /absolute/path/to/dezrez-mcp/dist/index.js

Variable

Required

Meaning

DEZREZ_ACCESS_TOKEN

one of the two

An OAuth2 access token for the Rezi API, sent as Authorization: Bearer …. When set, the token endpoint is never called.

DEZREZ_CLIENT_ID, DEZREZ_CLIENT_SECRET

one of the two

The client ID and secret Dezrez issued, used for the client-credentials flow.

DEZREZ_AGENCY_ID

with client credentials

The agency to act for, sent as the agencyId query parameter on every request. Optional with an access token.

DEZREZ_SCOPE

no

The scope asked for in the client-credentials request. Defaults to impersonate_web_user, the value in the documented example; set it to whatever Dezrez granted your client.

DEZREZ_BASE_URL

no

Defaults to https://api.dezrez.com. Set to https://core-api-uat.dezrez.com for UAT. Used by the tests. Must not contain a username or password; the server refuses to start if it does.

DEZREZ_TOKEN_URL

no

Defaults to https://auth.dezrez.com/Dezrez.Core.Api/oauth/token/. Set to the UAT token endpoint for UAT. Used by the tests. Same rule about credentials in the URL.

DEZREZ_ALLOW_WRITES

no

Has no effect: this version has no write tools. A set value (whatever it is) is only mentioned in the start-up log.

Every request carries Rezi-Api-Version: 1.0, which the overview says is mandatory.

Safety defaults

  • Read-only. Every tool carries the MCP readOnlyHint annotation and only GETs the API; the one POST the server makes is the OAuth2 token request.

  • People are heavily personal in a CRM, so by default a person, group member, attendee, negotiator or applicant is identified by ID and name only. Email addresses, phone numbers, postal addresses, the free-text note on a person, identity, right-to-rent, NRL and housing-benefit details (the spec's AdditionalInformationDataContract, including its documents), attendees' contact items on events and negotiators' emails and phones are only returned when a tool is called with include_contact_details=true. Custom field values whose name looks like contact data (email, phone, address, date of birth, passport, bank and the like) are withheld by default too.

  • In free text (notes, descriptions, special arrangements, summary lines, names, group names, custom field values) email addresses are replaced with [email redacted] and phone-number-like sequences with [phone redacted] by default. The phone match is a heuristic: it covers international numbers written with + or 00 (including the +44 (0)7700 … form), UK numbers with a bracketed area code such as (020) 7946 0958, and UK-style 0… numbers of 9 to 11 digits with spaces, dots or hyphens between groups. Other digit strings starting with 0 are redacted too, while numeric IDs, timestamps and hyphenated references are left alone; the raw text is available with include_contact_details. The same redaction is applied to Dezrez's error messages before they are passed on.

  • Error messages never quote a response body. From an error response only a JSON message field (Message, ExceptionMessage, message, error, error_description) is passed on, redacted as above; a non-JSON body (a gateway page, a login page) is described by content type and size only. Every message is also scrubbed of the server's own secrets (the configured access token, each token the token endpoint issued, the client secret and the Basic credential), so an error body that echoes the request's Authorization header shows Bearer [redacted] or Basic [redacted]. A token endpoint answer without access_token is described by its content type, size and JSON key names, never its content. An unreachable endpoint is named by origin and path, without the query string.

  • Never returned, even on request: bank details (HasBankAccounts is dropped from person records and the /accounts and /bankReferences endpoints are never called), property key codes (PropertyKeyDataContract.Code, KeySignedOutDataContract.Code) and alarm codes (PropertyAlarmDataContract, reduced to a count).

  • Property addresses are the agency's stock and are returned by default on properties, searches, events and offers. The one exception is get_person_roles, where a role ties a named person to a property that, for someone renting or buying, is their home: there the address is reduced to town, county and country by default (the role type is a free string in the spec, so no type is treated as exempt), and the full address comes with include_contact_details or from get_property by ID. Document links (certificates, offer documents, pictures) are returned as stored, with the spec's RequiresAuthentication flag; the files are never fetched.

  • IDs are checked before any call: every ID on the endpoints this server calls is an int64 path parameter (a few elsewhere in the spec are strings) and each get-by-id says "Pass 0 to be returned an empty data contract", so only positive whole numbers are accepted. Type, status and category filters must be single tokens (letters, digits, _, -). from/to must be ISO 8601 and real calendar dates (2026-02-30 is refused, not rolled over); a date-time is sent as given and a date alone is completed to the start of that day for from (T00:00:00Z) and the end of it for to (T23:59:59Z), since the parameters are typed date-time. Search fields are trimmed and a blank value counts as not given.

  • Dezrez documents no rate limit. Requests are spaced 250 ms apart (about four per second). A 429 is retried at most twice, waiting for Retry-After (whole or fractional seconds, or an HTTP-date; 2 s then 4 s when the header is absent or unreadable). Each wait is capped at 10 seconds so a tool call stays under the MCP client's default 60-second request timeout: if Dezrez asks for a longer wait the call gives up at once and the message says how long to wait.

  • 502, 503 and 504 are retried the same way for GET only; when all three attempts fail the error says the service may be unavailable and to try again in a few minutes, without the gateway's HTML. The token POST is never retried after a gateway error.

  • A 200 whose body is not JSON (a proxy or a login page in the way) is reported as an error naming DEZREZ_BASE_URL, never as an empty record. A 200 with a null body is reported as not found where the spec documents it that way: every get-by-id ("null if it does not exist") and the two events endpoints ("null if the property/group does not exist"); on GET /api/Offer the spec says "null if none exist", so there it is an empty list.

  • A rejected token or rejected client credentials produce messages that say which variables to check; a 403 names the documented read scopes and the agency in use.

Tests

npm test

The test suite:

  1. Validates every fixture record against the definitions in Dezrez's published Swagger 2.0 document (PropertyDataContract, EventListDataContract, PersonDataContract, BasicPersonRoleDataContract, GroupDataContract, OfferDataContract, PropertyRoleSuggestResultDataContract and everything they embed) with ajv-draft-04, the JSON Schema dialect Swagger 2.0 uses, plus ajv-formats for date-time, int64 and double. The document is downloaded from api.dezrez.com/swagger/docs/v1 to spec.json on the first run. Because the definitions set no additionalProperties: false, Ajv alone would accept a fixture field the spec never declares, so every fixture is also walked key by key against its definition (following $ref and items; the Dates and Descriptions maps take any key) and an undeclared key fails the check. One deliberate loosening: the spec types custom field values as its Object definition, which it describes as "an unspecified legacy API value", so that definition is validated as "any value", left opaque by the key walk, and the fixtures use plain strings there. Negative controls check that the schemas still reject wrong types and that the key walk reports undeclared keys at any depth.

  2. Starts a local mock of the API and of the OAuth2 token endpoint that serves those fixtures with the documented pageSize/pageNumber paging (PagedCollectionDataContract, pages capped at 10 to exercise paging), the documented auth (Bearer token plus Rezi-Api-Version: 1.0; Basic client:secret and a JSON grant_type/scope body at the token endpoint; agencyId required with a client token), 401 on a bad token or bad client secret, 404 for unknown IDs, the documented 200 with null for one reserved ID, and a one-off 429 with Retry-After on GET /api/Offer. The mock's list, detail and paged-collection responses are validated against the response schemas the spec names for each operation.

  3. Starts the built server and drives it over stdio with the official MCP client: 22 checks covering tools/list and annotations (10 read tools, none writable, DEZREZ_ALLOW_WRITES adding nothing), the client-credentials token request in its documented form with the token cached across calls, one token request shared by two concurrent first calls, and agencyId on every request, every read tool, paging to TotalCount across pages 1, 2, 3 and whole-page continuation with next_page covering every event exactly once, the bare-array paging of person roles with the address reduced to the area by default and complete on request, each documented filter passed through exactly (from, to, type and excludedTypes as repeated keys, eventCategoryType, branchId, showCancelled, includeOnlyOriginalNotes, activeRolesOnly, propertyId, roleId, includeDrafts, the five findbydetails fields, the dataContract.* search parameters), a date-only from/to completed to a date-time and impossible calendar dates refused, blank search fields treated as absent, redaction of contact details by default and their return on request, key and alarm codes never returned, bank fields never returned and bank endpoints never called, ID validation before any call, the 404 message, a null body reported as not found on get-by-id and on the events endpoints and as an empty list on GET /api/Offer, the 429 retry waiting for Retry-After in the seconds, fractional-seconds and HTTP-date forms, giving up after three attempts on a persistent 429 and at once on a Retry-After above the cap, a 502 retried for GET, a GET failing three times with 503 reported with advice and without the gateway HTML, a non-JSON 200 reported as an error described by content type and size with nothing of the body (its email, phone number and token) quoted, a non-JSON 400 body not passed on at all, error bodies that echo the Authorization header (a Bearer token on a 400 and a 401, the Basic credential at the token endpoint) scrubbed to [redacted], a token endpoint 200 without access_token described by its JSON keys or content type without the token, a revoked token fetched again once, a token response without expires_in still cached, a token with expires_in of 30 seconds reused across three calls, a 502 from the token endpoint not retried, a 400 whose message contains an email and a phone number passed on redacted, the 401 messages for a wrong access token and wrong client credentials, a token pasted with its Bearer prefix sent once, the 403 message, start-up refused without credentials, without DEZREZ_AGENCY_ID in the client flow, or with a username and password inside DEZREZ_BASE_URL or DEZREZ_TOKEN_URL (without repeating them), an unreachable endpoint named without its query string, and that every request used the documented headers and a documented method and path.

The spec marks no property as required on any of these definitions, so schema validation proves the types of fields that are present, not that any field is present; the checks in step 3 assert the fields the tools rely on explicitly.

Status

This is a working prototype. It has not yet been run against the live API, because it was built without a registered client, a token or an agency to test on. Everything below is taken from the published documentation and should be confirmed on a real account (UAT first):

  • Authentication end to end: that a client registered for the client-credentials flow gets a token with the documented request (the overview's example scope is impersonate_web_user; the read scopes it lists are property_read, property_basic_read, people_read, people_basic_read, event_read and document_read, and which of them a reading client is actually granted is decided by Dezrez), that expires_in is present in the token response (the server keeps a token for an hour when it is not) and how long the tokens really last, what the API answers when agencyId is missing or wrong (the mock answers 400 and 403), and the body of a 401 (undocumented; the server reads Message, ExceptionMessage, message, error and error_description when present).

  • Paging: that pageNumber is 1-based (the server assumes it), that TotalCount and PageSize are filled on every PagedCollectionDataContract, what the maximum pageSize is (the server sends at most 100, its own cap; the spec says "Can be null" and gives no limit) and what a page past the end returns (the mock answers an empty Collection). GET /api/people/{id}/roles answers a bare array with no total, so the only end condition is a page shorter than the requested size; if the live API capped pages below the requested size, that walk would stop early.

  • The sort order of every list. The spec documents none; the mock serves timelines newest first and the server returns whatever order the API uses.

  • Filter semantics: whether from/to compare against DateTime, StartDate or CreatedDate and are inclusive; whether type, excludedTypes, eventCategoryType, roleType and roleStatus take the enum system names (the swagger types them as plain strings and lists no values; the documented examples are role types Sales and Letting, role statuses OfferAccepted and Exchanged, and suggest types AgencyOnly and ViewableOnly); whether the findbydetails matches are exact or partial; and whether GET /api/role/suggest needs a query at all.

  • The EnumDataContract values that come back (SystemName is what the server shows, falling back to Name) and the event types that represent viewings, offers and notes in a live agency.

  • Date formats: the spec says date-time; the fixtures use RFC 3339 with a Z and ajv-formats requires a zone designator, so a live API emitting 2026-09-01T10:00:00 without one would still be passed through by the server but would fail the suite's schema check. A from/to date-time is sent exactly as given; a date alone is completed to T00:00:00Z (from) or T23:59:59Z (to), and whether the live API reads the Z as UTC or ignores the zone is unconfirmed.

  • Which fields the live API fills: Keys, Alarms, SpecialArrangements and Certificates on a property, AttendingGroups, Notes, KeySignedOut and Dates on events, AdditionalInformation and CustomFields on people, Owner and Prices on suggest results, Response, VendorCommunication and Documents on offers. The team-level security described in Breaking_Change_Log.md can reduce a record to Id, OwningTeamId, BranchId, Name and TeamAccessType; the server passes such records through as they are.

  • Whether the documented "null if it does not exist" is what the API really answers for an unknown ID (on get-by-id and on the events endpoints), or a 404; both are handled.

  • The wording of Dezrez's error messages and whether any of them echo request data; the server passes on only JSON message fields, redacts contact details from them and scrubs its own secrets regardless.

  • How many requests per second the API tolerates; nothing is documented, so the 250 ms spacing is a guess on the polite side.

Going to production

This version runs locally over stdio with the agency's own client credentials or token. For agencies to connect from claude.ai or ChatGPT without handling credentials, the next step is a remote server (Streamable HTTP) behind OAuth, hosted by Dezrez, that uses the code flow Dezrez already offers so each user's own token and branch context apply, and then a listing in the Claude and ChatGPT connector directories. Write tools (leads, viewings, offers) can follow once they can be tested on a UAT agency.

Licence

MIT. Built by Alexandru Dragoș (alexandru.dragos96@gmail.com) with an AI agent (Claude) working under his direction.

Available Tools

10 tools
find_peopleFind peopleA
Read-onlyIdempotent

Search people by surname, postcode, email address, telephone and/or mobile number, exactly the fields GET /api/people/findbydetails accepts; at least one is required. Results are returned as get_person returns them: names by default, contact details only with include_contact_details. Note that searching by an email or number and getting a match confirms that detail exists on the account even when it is not returned.

ParametersJSON Schema
NameRequiredDescriptionDefault
emailNoEmail address (API parameter `email`)
mobileNoMobile number (API parameter `mobile`)
surnameNoSurname (API parameter `surname`)
postcodeNoPostcode (API parameter `postcode`)
telephoneNoMain telephone number (API parameter `telephone`)
max_resultsNoMost people to return; the API has no paging on this endpoint, so the rest are dropped and reported
include_contact_detailsNoInclude email addresses, phone numbers, postal addresses, notes and identity details. Off by default.

TDQS

A4.3/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already cover the safe-read profile (readOnly, idempotent, non-destructive), and the description still adds real behavioral content: the at-least-one-input rule, that results mirror get_person's shape, and the non-obvious fact that a match on an email/number confirms that detail exists on the account even when not returned. Missing are auth requirements and any rate-limit expectations for an openWorld endpoint.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Three sentences, front-loaded with the searchable fields and the required-input rule, then result behavior, then the caveat. Slightly dense in the final sentence but every clause carries information an agent needs.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

With no output schema, the description steps in to describe return contents ('names by default, contact details only with include_contact_details') and the reporting behavior when max_results truncates. Coverage is solid for a 7-parameter read tool, though the practical note about what to do with a confirmed-but-not-returned detail is left implicit.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters4/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema coverage is 100%, so the baseline is 3, but the description earns more by supplying the cross-field constraint that at least one search field is required — a rule the schema does not encode (required is empty). It also restates the contact-detail gating behavior of include_contact_details in plain terms.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

States a specific verb and resource ('search people by surname, postcode, email...') and pins it to the exact API endpoint GET /api/people/findbydetails. Clearly distinguishable from the sibling get_person, which it references as a comparison point for result shape.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

Gives a hard precondition ('at least one is required') and implicitly frames this as the lookup-by-detail path versus get_person. It does not, however, explicitly state when to prefer get_person or how to follow up once a match is found, so no exclusions are spelled out.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

get_groupGet groupA
Read-onlyIdempotent

One group by ID: a household or company (vendors, applicants, landlords, tenants, suppliers) with its members (names by default), type, status, applicant qualification answers, preferred companies and custom fields. Members' emails, phones and addresses only with include_contact_details. Uses GET /api/group/{id}.

ParametersJSON Schema
NameRequiredDescriptionDefault
group_idYesGroup ID (a positive whole number)
include_contact_detailsNoInclude members' email addresses, phone numbers and postal addresses, and stop redacting emails and phone numbers from names, notes and descriptions. Off by default.

TDQS

A4/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already declare readOnly, idempotent and non-destructive, so safety is covered. The description adds real value beyond that: members' emails, phones and addresses are omitted and redacted by default, and only revealed via include_contact_details, plus a disclosure of default member representation (names only). No permission or rate-limit notes, but the redaction behavior is the key trait.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Two dense sentences with the core identification and the returned fields front-loaded, and the conditional flag explained last. Slightly list-heavy but every clause carries information; no filler.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

With no output schema, the description compensates by enumerating the returned payload (members, type, status, qualification answers, preferred companies, custom fields) and explaining the default redaction state — exactly what an agent needs to interpret results.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is 100%, so both parameters are fully documented in the schema and the baseline is 3. The description reinforces that contact details are opt-in and that names are returned by default, but adds no syntax or format detail beyond the schema.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

States a specific verb+resource ('One group by ID') and goes further to define what a group is (household or company with roles like vendors/applicants/landlords), so an agent can distinguish it from get_person and get_property. The returned field inventory makes the scope unambiguous.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines3/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The description implies usage (fetch a single group when you have its ID) and gives a conditional for include_contact_details, but never states when to prefer this over a sibling such as get_group_events or find_people, nor any exclusions or prerequisites. The endpoint reference is useful but not routing guidance.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

get_group_eventsGroup eventsB
Read-onlyIdempotent

The timeline of one group (household or company): viewings, offers, notes, appointments and other events, with the same filters as get_property_events plus the group-only ones: only active roles, one property, one role, and drafts. Uses GET /api/group/{id}/events.

ParametersJSON Schema
NameRequiredDescriptionDefault
toNoOnly events up to this date/time (API parameter `to`, ISO 8601). A date alone means the end of that day, UTC (2026-09-30 is sent as 2026-09-30T23:59:59Z).
fromNoOnly events from this date/time (API parameter `from`, ISO 8601). A date alone means the start of that day, UTC (2026-09-01 is sent as 2026-09-01T00:00:00Z).
pageNoAPI page number to start from (1-based, as this server assumes; use next_page from a previous call)
typesNoOnly these event types, as Rezi system names (API parameter `type`, repeated). The swagger does not list the values.
role_idNoOnly events on this role (API parameter `roleId`)
group_idYesGroup ID (a positive whole number)
branch_idNoOnly events in this branch (API parameter `branchId`)
max_resultsNoMost records to return in this call; whole API pages only, so fewer may come back with a next_page to continue from
property_idNoOnly events relating to this property (API parameter `propertyId`)
excluded_typesNoEvery type except these (API parameter `excludedTypes`, repeated)
include_draftsNoInclude draft events (API parameter `includeDrafts`)
show_cancelledNoInclude cancelled events (API parameter `showCancelled`; the API's default is false)
active_roles_onlyNoOnly events on the group's active roles (API parameter `activeRolesOnly`)
event_category_typeNoOnly this event category (API parameter `eventCategoryType`)
include_contact_detailsNoInclude attendees' and negotiators' email addresses and phone numbers, and stop redacting emails and phone numbers from notes, names and descriptions. Off by default.
include_only_original_notesNoSkip note editions and return only original notes (API parameter `includeOnlyOriginalNotes`; the API's default is true)

TDQS

B3.4/5.0
Behavior3/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already declare readOnlyHint=true, destructiveHint=false, idempotentHint=true, and openWorldHint=true, so the safety profile is covered. The description adds the endpoint (GET /api/group/{id}/events) and the filter scope but does not disclose pagination behavior, rate limits, authentication needs, or result shape beyond what the schema already implies. It meets the minimum for an annotated read-only tool but adds only moderate behavioral context.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is a single dense sentence that front-loads the purpose and then lists filters, with no redundant phrasing. It is efficient, though the clause 'with the same filters as get_property_events plus the group-only ones' is somewhat compressed and could be clearer if split.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness3/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

Given 16 parameters, no output schema, and rich annotations, the description is adequate but thin. It does not explain pagination behavior (e.g., next_page usage), does not describe the response structure, and does not clarify how the group-only filters (only active roles, one property, one role, drafts) map to the parameter names. The schema covers many of these details, but the description itself leaves gaps for an agent trying to understand the tool's full behavior.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters2/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema coverage is 100%, so the schema already documents all 16 parameters in detail, including date semantics, pagination, and filter meanings. The description only mentions filters abstractly and does not explain any parameter syntax, defaults, or interactions beyond what the schema provides. With full schema coverage, the description contributes nothing new to parameter understanding; a baseline of 3 would be too generous given the lack of added meaning.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose4/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description clearly states the tool returns a timeline of events for a single group (household or company), listing concrete event types (viewings, offers, notes, appointments). It distinguishes itself from get_property_events by explicitly noting group-only filters. It falls short of a 5 only because the relationship between group_id and the returned data is not elaborated beyond 'timeline of one group.'

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The description explicitly references get_property_events as the parallel tool and delineates the group-only filters (active roles, one property, one role, drafts), which helps an agent choose between the two. It does not state when NOT to use this tool or cover other alternatives like get_group, but the sibling routing is clear.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

get_offerGet offerA
Read-onlyIdempotent

One offer by ID, in full: value, validity, status, the property, applicant and vendor groups with their primary members (names by default), the marketed price, the vendor's response and communication, notes, documents (name, type and link) and negotiators. Uses GET /api/Offer/{id}.

ParametersJSON Schema
NameRequiredDescriptionDefault
offer_idYesOffer ID (a positive whole number)
include_contact_detailsNoInclude applicants', vendors' and negotiators' email addresses, phone numbers and postal addresses, and stop redacting emails and phone numbers from names and notes. Off by default.

TDQS

A3.7/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already cover the read-only, idempotent, non-destructive safety profile. The description adds real behavioral context beyond that: member names are returned by default, emails/phones are redacted unless include_contact_details is set, and it names the backing endpoint GET /api/Offer/{id}.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

A single dense sentence front-loads the core intent and then enumerates the returned fields, followed by a short endpoint note. Every clause carries information, though the field list is long.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

With no output schema, the description commendably enumerates the returned fields (value, validity, status, property, groups, price, vendor response, notes, documents, negotiators), which an agent needs to interpret results. Missing only explicit routing guidance against sibling search tools.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema coverage is 100%, so both parameters are fully documented in the schema, including the default=false for include_contact_details and its redaction semantics. The description's 'names by default' echoes that without adding format or syntax beyond the schema, so baseline 3 applies.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose4/5

Does the description clearly state what the tool does and how it differs from similar tools?

States a specific verb (get) and resource (one offer by ID) and enumerates the payload's contents in detail, making the scope unmistakable. It does not explicitly name siblings like list_offers to contrast, so it stops short of a 5.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines3/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The phrase 'One offer by ID' implies retrieval of a single known offer, which is adequate context, but the description never states when to use this versus list_offers or search tools, and gives no prerequisites.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

get_personGet personA
Read-onlyIdempotent

One person by ID: name, gender, group memberships (the households or companies they belong to), marketing preferences, custom fields and dates. Contact items (emails, phones), postal addresses, the free-text note and the identity, right-to-rent and NRL details are only returned with include_contact_details. Bank details are never returned. Uses GET /api/people/{id}.

ParametersJSON Schema
NameRequiredDescriptionDefault
person_idYesPerson ID (a positive whole number)
include_contact_detailsNoInclude email addresses, phone numbers, postal addresses, the note, and identity/right-to-rent/NRL details. Off by default.

TDQS

A3.7/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already cover safety (readOnly, idempotent, non-destructive). The description adds valuable conditional behavior: contact items and identity details are only returned with include_contact_details, and bank details are never returned. This is genuine behavioral disclosure beyond the annotations.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Front-loaded with the core purpose, then field inventory, then the critical include_contact_details caveat. Efficient single paragraph without waste, though the field enumeration is slightly list-like.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

Covers what is returned, the conditional fields, hard exclusions (bank details), and the endpoint. No output schema exists, so return details in the description are necessary and present. Missing pagination/error context but complete for a GET-by-ID tool.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema coverage is 100%, so baseline is 3. The description adds meaning about what include_contact_details gates (contact items, note, identity/right-to-rent/NRL), but the schema already lists these. Marginal added value.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose4/5

Does the description clearly state what the tool does and how it differs from similar tools?

States a specific verb+resource: retrieve one person by ID, and details what is returned. Distinguishes itself from find_people implicitly by being singular-with-ID, but doesn't name the sibling alternative explicitly. Clear but no explicit sibling differentiation.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines3/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

Implied usage: you call this when you have a person_id. No explicit 'use X when Y' guidance, no exclusions, and find_people isn't named as the search alternative. Contextual inference is required.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

get_person_rolesPerson's rolesA
Read-onlyIdempotent

The properties a person is selling, letting, buying or renting: each role with its type, the property ID, headline price, offer and viewing counts and the accepted offer price. A role ties a named person to a property, and for someone renting or buying that property is their home, so by default the address is reduced to town, county and country; the full address (number, street, postcode, coordinates) is returned with include_contact_details, or from get_property by ID. Uses GET /api/people/{id}/roles, which answers a plain list without a total, so paging ends at a short page.

ParametersJSON Schema
NameRequiredDescriptionDefault
pageNoAPI page number to start from (1-based, as this server assumes; use next_page from a previous call)
person_idYesPerson ID (a positive whole number)
max_resultsNoMost records to return in this call; whole API pages only, so fewer may come back with a next_page to continue from
include_contact_detailsNoInclude the full property address of each role (number, street, building, postcode, coordinates). Off by default.

TDQS

A4.4/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already declare readOnly/idempotent/non-destructive, so safety is covered; the description goes beyond them by disclosing that addresses are reduced to town/county/country by default and that the endpoint returns a plain list without a total, so paging terminates at a short page. That paging quirk is real behavioral context an agent could not derive from structured fields.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Purpose and role contents are front-loaded, followed by the address and paging caveats. The sentences are dense and slightly overpacked, but every clause carries information rather than filler.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

With no output schema, the description carries the return-shape burden and does so: it names the role fields, the default vs full address, and the paging termination behavior. An agent has everything needed to call it and interpret the response.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters4/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is 100%, so the baseline is 3. The description still adds meaning by explaining the default address-reduction behavior tied to include_contact_details and the pagination semantics (no total; short page ends paging) that contextualize page/max_results.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

States a specific verb and resource ('the properties a person is selling, letting, buying or renting') and enumerates the returned role fields: type, property ID, headline price, offer/viewing counts, accepted offer price. It also distinguishes itself from the get_property sibling for full-address lookups, so an agent can route without opening either schema.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

Gives a clear condition for include_contact_details (full number/street/postcode/coordinates) and names get_property by ID as the alternative source for the full address. It does not state when to prefer this tool over get_offer/list_offers for offer data, but the primary selection context is covered.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

get_propertyGet propertyA
Read-onlyIdempotent

One property by ID: address, status, its marketing roles (sale or letting, with status), certificates (EPC and the like), special arrangements, keys (holder and check-out status; key codes are never returned), the number of alarms (codes never returned), custom fields and the default picture link. Note that prices and bedrooms live on events and role searches, not on the property record.

ParametersJSON Schema
NameRequiredDescriptionDefault
property_idYesProperty ID (a positive whole number)
include_contact_detailsNoInclude email addresses and phone numbers typed into names, notes and special arrangements, and custom field values that look like contact data. Off by default.

TDQS

A4.4/5.0
Behavior5/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

The annotations already declare this as a safe, read-only, idempotent operation, but the description adds important behavioral detail: key codes and alarm codes are never returned. It also discloses that keys include holder and check-out status, and that custom fields and a default picture link are returned. This goes meaningfully beyond the structured annotations.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is front-loaded with the core action and then lists returned fields in a compact, information-dense style. It is longer than a minimal sentence, but with no output schema the field enumeration earns its place and is organized around the property record rather than padding.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

Given that no output schema exists, the description carries the burden of explaining what comes back, and it does so thoroughly by listing address, status, roles, certificates, arrangements, keys, alarms, custom fields, and picture link. It also clarifies excluded data, so an agent has enough context to invoke it correctly alongside annotations and a fully documented input schema.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is 100%, so both the required property_id and optional include_contact_details are already documented in the input schema. The description confirms retrieval by ID but does not add parameter meaning beyond what the schema provides, which matches the baseline for full schema coverage.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description states a clear verb and resource: retrieving one property by ID. It enumerates the returned property record contents and explicitly distinguishes this tool from event and role-search data by noting that prices and bedrooms live elsewhere. This gives an agent enough information to identify the tool's unique scope among siblings.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

It establishes context by saying this returns one property by ID and notes where prices and bedrooms actually live, which helps route the agent away from inappropriate use. However, it does not explicitly name sibling tools such as search_properties or get_property_events, nor does it state when not to use this tool.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

get_property_eventsProperty eventsA
Read-onlyIdempotent

The timeline of one property: viewings, offers, notes, appointments and other events, newest to oldest as the API returns them, with dates, status, prices, the groups and people attending (names only by default), notes and negotiators. Filter by date range, event type(s), category, branch, and whether cancelled events are included. Uses GET /api/property/{id}/events.

ParametersJSON Schema
NameRequiredDescriptionDefault
toNoOnly events up to this date/time (API parameter `to`, ISO 8601). A date alone means the end of that day, UTC (2026-09-30 is sent as 2026-09-30T23:59:59Z).
fromNoOnly events from this date/time (API parameter `from`, ISO 8601). A date alone means the start of that day, UTC (2026-09-01 is sent as 2026-09-01T00:00:00Z).
pageNoAPI page number to start from (1-based, as this server assumes; use next_page from a previous call)
typesNoOnly these event types, as Rezi system names (API parameter `type`, repeated). The swagger does not list the values.
branch_idNoOnly events in this branch (API parameter `branchId`)
max_resultsNoMost records to return in this call; whole API pages only, so fewer may come back with a next_page to continue from
property_idYesProperty ID (a positive whole number)
excluded_typesNoEvery type except these (API parameter `excludedTypes`, repeated)
show_cancelledNoInclude cancelled events (API parameter `showCancelled`; the API's default is false)
event_category_typeNoOnly this event category (API parameter `eventCategoryType`)
include_contact_detailsNoInclude attendees' and negotiators' email addresses and phone numbers, and stop redacting emails and phone numbers from notes, names and descriptions. Off by default.
include_only_original_notesNoSkip note editions and return only original notes (API parameter `includeOnlyOriginalNotes`; the API's default is true)

TDQS

A3.9/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already declare readOnly/idempotent/non-destructive/openWorld, so the safety profile is covered. The description adds real behavioral context beyond that: newest-to-oldest ordering, page-based pagination with whole-page returns and next_page continuation, contact details redacted by default, and the API's showCancelled=false default. It does not mention rate limits or auth, keeping it short of a 5.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

A single dense but front-loaded paragraph: returned content first, then filtering, then the backing endpoint. No filler, though the enumeration of returned fields is long enough to be slightly heavy for a one-paragraph description.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For a 12-parameter read tool with no output schema, the description usefully describes what comes back (fields, ordering) and how pagination works, complementing the annotations. It could say more about redaction/auth prerequisites, but nothing an agent needs to call it correctly is missing.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema coverage is 100%, so the schema already documents all 12 parameters in detail (including defaults and the 'names only / redaction' semantics). The description's 'filter by date range, event type(s), category, branch, and cancelled' summary adds marginal value but no syntax or meaning beyond the schema, warranting the baseline 3.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

States a specific verb (get/retrieve the timeline) and resource (events for one property), enumerating the event kinds (viewings, offers, notes, appointments). An agent can distinguish it from get_group_events and list_offers without inspecting the schema.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines3/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The description implies when this tool is relevant (fetching one property's event history) and lists the filter conditions, but it never names an alternative sibling or states when NOT to use it (e.g., vs get_group_events or get_property). Usage is implied rather than explicit.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

list_offersList offersA
Read-onlyIdempotent

Offers on the agency's properties, in the order the API returns them, each with its value, status, the property and address, the applicant and vendor groups (names by default), the marketed price, the vendor's response and the negotiators. The endpoint has no filters; page through with page/max_results. Uses GET /api/Offer.

ParametersJSON Schema
NameRequiredDescriptionDefault
pageNoAPI page number to start from (1-based, as this server assumes; use next_page from a previous call)
max_resultsNoMost records to return in this call; whole API pages only, so fewer may come back with a next_page to continue from
include_contact_detailsNoInclude applicants', vendors' and negotiators' email addresses, phone numbers and postal addresses, and stop redacting emails and phone numbers from names and notes. Off by default.

TDQS

A4.4/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already declare read-only, idempotent, open-world, non-destructive, so the safety profile is covered. The description adds real value beyond that: the endpoint returns records unordered ('in the order the API returns them'), supports no filtering, and redacts contact details by default. It does not discuss rate limits or response size limits, but the disclosed behavior is substantive.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Three sentences with no filler; the resource description, the no-filter/pagination constraint, and the API path are each stated once. The first sentence is a long field enumeration, but every listed field earns its place given there is no output schema.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

With no output schema, the description carries the return-shape burden and does so by enumerating fields and noting default redaction. Pagination, absence of filters, and the underlying endpoint are all covered, so an agent has everything needed to call it correctly.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters4/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema coverage is 100%, so the baseline is 3. The description adds meaning: pagination is the only way to traverse since there are no filters, and 'names by default' signals that contact data is withheld unless include_contact_details is enabled, reinforcing that parameter's purpose beyond its schema text.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

Starts with a precise noun phrase ('Offers on the agency's properties') and enumerates the returned fields, so the agent knows exactly what this resource is. The explicit 'no filters' note distinguishes it from filtering siblings like search_properties, and the contrast with the single-record get_offer is implicit in the plural/list framing.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

States plainly that 'The endpoint has no filters' and instructs to 'page through with page/max_results', which tells the agent when this is the right call versus a filtered search. It stops short of naming an alternative tool or an explicit 'use X instead when filtering' rule, so it is clear context without exclusions.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

search_propertiesSearch propertiesA
Read-onlyIdempotent

Search the agency's property marketing roles (a property being sold or let) by free text such as an address fragment or postcode, optionally only those on the market, of one role type (documented examples: Sales, Letting) or in one role status (documented examples: OfferAccepted, Exchanged). Each result carries the property ID, address, the role with its status, prices, a summary line and the owning group. Uses GET /api/role/suggest; the role type and status values are system names the swagger does not enumerate.

ParametersJSON Schema
NameRequiredDescriptionDefault
pageNoAPI page number to start from (1-based, as this server assumes; use next_page from a previous call)
queryNoFree-text search (API parameter `dataContract.query`)
role_typeNoRole type system name, e.g. Sales or Letting (`dataContract.roleType`)
max_resultsNoMost records to return in this call; whole API pages only, so fewer may come back with a next_page to continue from
role_statusNoRole status system name, e.g. OfferAccepted (`dataContract.roleStatus`)
is_on_marketNoOnly roles currently on the market (`dataContract.isOnMarket`)
suggest_typeNoThe two values the spec documents for `dataContract.suggestType`
include_contact_detailsNoInclude the owning group's members' email addresses, phone numbers and postal addresses, and stop redacting emails and phone numbers from names and summary text. Off by default.

TDQS

A4/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already declare this as a read-only, idempotent, non-destructive operation. The description adds useful behavioral context beyond annotations: the backing endpoint, the result shape, the redaction behavior of include_contact_details, and the caveat that role type/status values are system names not enumerated in swagger.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is appropriately sized and front-loaded: it begins with the core search behavior, then describes results and implementation caveats. Every sentence adds useful information without repetition.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

Given eight optional parameters, no output schema, and rich annotations, the description is complete enough. It explains the searchable filters, the return fields, the pagination-related schema context, and the important enumeration caveat for role type/status.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters4/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is 100%, so baseline is 3. The description adds meaningful parameter semantics by giving examples for role_type and role_status and warning that their system names are not enumerated by swagger, which goes beyond the schema text.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose4/5

Does the description clearly state what the tool does and how it differs from similar tools?

States a specific verb and resource: searching the agency's property marketing roles by free text, with optional filters. The role-oriented scope clearly separates it from property-entity siblings like get_property, but it does not explicitly name or contrast those alternatives.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines3/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

Provides clear usage context, such as searching by address fragment or postcode and optionally filtering by on-market status, role type, or role status. However, it does not explicitly state when to use this instead of get_property or other sibling tools, leaving routing guidance implied.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

Tool Schema Changelog

Recent tool additions, removals, and schema changes observed during successful MCP inspections.

  1. 10 tool updatesv0.1.0
    • First observedfind_people
    • First observedget_group
    • First observedget_group_events
    • First observedget_offer
    • First observedget_person
    • First observedget_person_roles
    • First observedget_property
    • First observedget_property_events
    • First observedlist_offers
    • First observedsearch_properties

TDQS

A4.1/5.0

Scored across 10 tools

Disambiguation5/5

Each tool targets a distinct entity and action: get-by-ID vs search/list for properties, people, groups, and offers, plus separate property/group event timelines. The apparent overlap between get_property_events and get_group_events is explicitly scoped to different parent entities, so an agent can select correctly.

Naming Consistency5/5

All names use snake_case with a consistent verb_noun pattern: get_*, search_*, find_*, list_*. Plural/singular forms follow the operation type predictably, and there is no mixed casing or vague verb usage.

Tool Count5/5

10 tools is well within the ideal range and maps cleanly to the core read entities: properties, people, groups, offers, and events. Each tool covers a distinct resource or operation without redundancy.

Completeness4/5

The read-only query surface covers the main entities and their timelines, but there is no direct way to search or list groups (only get_group by ID), and no write operations if mutation is in scope. These are workable gaps via related tools, but not full lifecycle coverage.

Maintenance

ActivityMaintained
ResponsivenessNo issues

Related MCP Connectors

Related MCP Servers

  • A
    license
    A
    quality
    A
    maintenance
    A read-only MCP server providing 56 tools to query Qobrix real-estate CRM data, covering listings, leads, viewings, offers, contracts, analytics, and more, with RESO Data Dictionary alignment and caching support.
    64
    3
    Apache 2.0