Every change Wellknown observed on this MCP server, newest first, with what it was before and what it became. Tool-surface changes carry the definition diff. Nothing here is edited after the fact.
Recently observed → Unavailable
Certificate changed, valid to 2027-01-07
Live → Recently observed
Changed the definition of "submit_enquiry"
⟨88 unchanged words⟩ linked to a PropertyList account; an API keyremovesraisesthatit toallowance.40 enquiries per key in any 24 hours. Provide the property `reference` (from search results) ⟨24 unchanged words⟩
Changed the definition of "find_properties_by_description" and "search_properties"
⟨71 unchanged words⟩ was interpreted (and what couldn't be resolved). Features in the brief are filters too: a private pool, a communal pool, a sea view, a garden, a garage and the like. Works without an API key up to a ⟨44 unchanged words⟩
⟨123 unchanged words⟩ pool (any pool, communal included), private_pool, communal_pool, sea_view,garden, parking (a garage or parking space)
Changed the definition of "find_properties_by_description", "get_property" and "search_properties"
⟨72 unchanged words⟩ ,"oracle_verified":{"type":"boolean"},"photo":{"description":"Absolute https URL of the main photo.","type":["string","null"]},"price":{"type":["integer","null"]},"reference":{"type":"string"},"title":{"type":["string","null"]},"url":{"description":"Absolute https URL of the listing on PropertyList.","type":["string","null"]}}, ⟨15 unchanged words⟩
⟨128 unchanged words⟩ cannot resolve it. `location.latitude` / `location.longitude` are presentonly whenwhenever
Authorization not required, issuer https://mcp.propertylist.es
Added "assign_listing", "cancel_action", "confirm_action" and 5 more (21 tools before, 29 now)
Assign listing — Stage assigning one of YOUR agency's listings to a colleague. Returns a preview and an action_id; NOTHING changes until you call confirm_action with that id, after the agent has said yes. Only an agency admin (or someone allowed to edit every listing), or the agent the listing is assigned to now, may move it; an unassigned listing can be taken by anyone who may edit listings. Name the colleague as they appear in the CRM; if several match, the answer lists them. Requires a linked PropertyList account: the change is made in the agent's own name, with their CRM permissions, so an agency API ke…
Cancel action — Drop a change you staged and the agent does not want. Nothing in the CRM changes; the action_id can no longer be confirmed. An unconfirmed preview also lapses by itself after 30 minutes. Requires a linked PropertyList account: the change is made in the agent's own name, with their CRM permissions, so an agency API key alone cannot make it.
Confirm action — Make a change you staged with move_pipeline_stage, qualify_lead, assign_listing, set_listing_status, send_listings_to_contact or schedule_viewing. Call it ONLY after showing the agent the preview and hearing them say yes. It can charge credits and send email, exactly as the preview said. Everything is checked again first; if the client, listing or stage has changed so the action no longer applies, nothing happens and the answer says why. A preview is valid for 30 minutes, and each one can be confirmed once. Requires a linked PropertyList account: the change is made in the agent's own name, …
Added "find_price_reductions", "find_similar_properties", "get_contact" and 3 more; changed the definition of "area_market_summary", "autocomplete_location", "create_contact" and 12 more (15 tools before, 21 now)
⟨78 unchanged words⟩ "type":["string","null"]},"price_per_sqm":{"description":"EUR per m². Verified only when `verified` is true; otherwise an estimate from the source in source_label.","type":["integer","null"]},"requested_area":{"type":["string","null" ⟨19 unchanged words⟩ :{"type":"boolean"},"verified_price_per_sqm":{"description":"Deprecated: the same figure as price_per_sqm, under its old name. Despite the name it is verified only when `verified` is true.","type":["integer","null"]}}, ⟨28 unchanged words⟩
Certificate recorded, valid to 2026-11-09
Authorization not required
First tool surface recorded: 15 tools (server version 1.0.0)
Showing the latest 12 events. The API returns up to 500 and filters by kind: ?kind=tool_surface_changed
⟨33 unchanged words⟩ private_pool (tagged private or heated pool), communal_pool (tagged communal pool), sea_view, garden (private, landscaped or communal), ⟨14 unchanged words⟩ "items":{"enum":["pool","private_pool","communal_pool","sea_view","garden","parking","terrace ⟨164 unchanged words⟩
⟨240 unchanged words⟩ cannot resolve it. `location.latitude` / `location.longitude` are presentonly whenwhenever we hold a real,publishablecoordinate; the fields are absentotherwise, andare never 0,0. `location.coordinates_precision`says what thepoint is: exact or street is the property itself, approximate is a pin the agent keeps private, rounded to about 1 km, locality oradministrative_area is an area centroid (accurate tothe town,not the building), unknown is a pin we hold noprecision recordfor.
Move pipeline stage — Stage a move of a client's card to another step on a pipeline board they are already on (buyer, seller, lead or tenant), as dragging the card on the CRM board does. Returns a preview and an action_id; NOTHING changes until you call confirm_action with that id, after the agent has said yes. Use the stage name as it reads on the board (my_pipeline lists them). Putting a client on a board they are not on yet, or qualifying a lead, is qualify_lead. Won and Lost need details the CRM asks for, so they are done in the CRM. For an offer stage, pass offer_amount (and property_reference if the card ha…
Qualify lead — Stage qualifying a client, as the CRM's Qualified popup does: tags them as a buyer, seller or tenant, puts them on that pipeline board and takes them off the Lead board. Returns a preview, including what it will COST (a place on the Buyer board uses a free place or one credit), and an action_id; NOTHING changes or is charged until you call confirm_action with that id, after the agent has said yes. Without `board`, the type comes from what the CRM already knows (the client's saved search, or a Vendor/Landlord tag); with neither, it asks for their details instead of guessing. With `board`, the…
Schedule viewing — Stage a viewing in the agent's own CRM diary, with the client and the listing on it. Returns a preview and an action_id; NOTHING is saved until you call confirm_action with that id, after the agent has said yes. The listing can be the agency's own or a shared MLS listing. This only books the agent's diary: for an MLS listing, the listing agency is not contacted, so the agent arranges access with them. Times are read in Spanish time (Europe/Madrid) unless they carry an offset. Requires a linked PropertyList account: the change is made in the agent's own name, with their CRM permissions, so a…
Send listings to a client — Stage an email from the agent to one of their clients with listings attached, as the CRM sends listings (it appears on the client's timeline). You write the subject and message, in the client's language. Returns a preview with the address, subject, message and listings, and an action_id; NOTHING is sent until you call confirm_action with that id, after the agent has read it and said yes. Listings can be the agency's own or shared MLS listings it can sell (match_buyer_to_inventory finds them). Up to 10 per email. Requires a linked PropertyList account: the change is made in the agent's own n…
Set listing status — Stage putting one of YOUR agency's listings online (it goes into approval, as the CRM's Publish button does), taking it offline, or marking it sold. Returns a preview, including any credit cost (a private, unshared listing costs credits to publish), and an action_id; NOTHING changes until you call confirm_action with that id, after the agent has said yes. Publishing checks what the CRM checks (photos, required details, your agency's listing limit) and the preview says what is missing. Sold is for a sale listing that is online or offline; sale_price is recorded for market statistics unless hi…
⟨17 unchanged words⟩ name. 2+ characters.","type":"string"},"search_type":{"description":"Market the listing counts and the ranking are for. Defaults to 'for-sale'.","enum":["for-sale","for-rent","holiday-rentals"],"type":"string"}},"required":["query"],"type":"object"}
before
—after
{"properties":{"matches":{"items":{"properties":{"areas_in_group":{"description":"For a group: how many areas it is made of.","type":"integer"},"id":{"description":"Area id: pass it to search_properties as location_id.","type":"integer"},"kind":{"description":"The raw area level, kept for existing callers; read type instead.","type":["string","integer"]},"listings":{"description":"Live listings in it for the search_type asked for.","type":"integer"},"name":{"type":"string"},"parent":{"description":"The area this one sits in.","type":"string"},"province":{"type":"string"},"type":{"description":"What kind of place it is; a group is a region or a coast made of other areas.","enum":["city","suburb","urbanisation","group","area"],"type":"string"}},"required":["id","name","type","listings"],"type":"object"},"type":"array"}},"required":["matches"],"type":"object"}⟨45 unchanged words⟩ attention so it surfaces in the CRM. Requires a linked PropertyList account (or an agency APIkey.key).
before
—after
{"properties":{"contact_id":{"description":"For log_note.","type":"integer"},"status":{"description":"exists: a contact with this email was already in the CRM, and nothing was added.","enum":["created","exists"],"type":"string"}},"required":["status","contact_id"],"type":"object"}⟨80 unchanged words⟩ , suburb or urbanisation name is enough. Requires a linked PropertyList account (or an agency APIkey.key).
before
—after
{"properties":{"location":{"description":"Where the draft was filed; null when the place name matched no area.","type":["string","null"]},"next_steps":{"items":{"type":"string"},"type":"array"},"property_id":{"type":"integer"},"reference":{"type":"string"},"status":{"enum":["draft_created"],"type":"string"},"url":{"description":"The draft in the CRM, where the agent finishes and publishes it.","type":"string"},"warning":{"description":"Advice to pass on to the agent before they publish.","type":"string"}},"required":["status","property_id","reference","url","next_steps"],"type":"object"}⟨23 unchanged words⟩ check if they're already in the CRM. Requiresana linked PropertyList account (or an agency APIkey;key); only ever searches thecalling agency's owncontacts.
before
—after
{"properties":{"contacts":{"items":{"properties":{"company_name":{"type":"string"},"created_at":{"description":"ISO 8601, UTC.","type":"string"},"emails":{"items":{"type":"string"},"type":"array"},"id":{"description":"contact_id, for log_note.","type":"integer"},"name":{"type":"string"},"phones":{"items":{"type":"string"},"type":"array"},"pipelines":{"description":"Board name to the stage this contact is in, in the agency's own stage names.","type":"object"},"surname":{"type":"string"}},"required":["id"],"type":"object"},"type":"array"},"count":{"type":"integer"}},"required":["count","contacts"],"type":"object"}⟨71 unchanged words⟩ was interpreted (and what couldn't be resolved). Works without an API key up to a daily allowance per user (allowance.daily_answers in the result; briefs that find nothing do not count). An API key has its own, larger allowance. When the allowance is used up the call returns an error naming the limit; search_properties stays available for structured queries.
{"properties":{"allowance":{"properties":{"answers_left_today":{"type":["integer","null"]},"counted_per":{"type":"string"},"daily_answers":{"type":"integer"},"resets":{"type":"string"}},"type":["object","null"]},"billed":{"type":["boolean","null" ⟨2 unchanged words⟩ "string","null"]},"interpretation":{"description":"How the brief was read, one pill per constraint.","type":["objectarray","null"]},"properties":{"items" ⟨10 unchanged words⟩ {"type":"integer"},"location":{"description":"\"Suburb, City\".","type":["objectstring","null"]},"match_reason":{"type":["string", ⟨14 unchanged words⟩ ":"string"},"title":{"type":["string","null"]}},"type":"object"},"type": ⟨12 unchanged words⟩
⟨57 unchanged words⟩ without an API key up to a dailyper-IPallowance ofdistinct listings,listings;counted per IP address, or per account for an app linked to a PropertyList account; an API key raises that allowance. `location.city` is ⟨99 unchanged words⟩
before
—after
{"properties":{"agencies":{"items":{"properties":{"city":{"type":"string"},"id":{"type":"integer"},"listing_count":{"description":"Active listings it carries in the area.","type":"integer"},"name":{"type":"string"},"province":{"type":"string"},"url":{"description":"The agency's public page.","type":"string"}},"required":["id","listing_count"],"type":"object"},"type":"array"}},"required":["agencies"],"type":"object"}⟨35 unchanged words⟩ The note appears on the contact/property timeline. Requires a linked PropertyList account (or an agency APIkey.key).
before
—after
{"properties":{"activity_id":{"type":"integer"},"status":{"enum":["logged"],"type":"string"}},"required":["status","activity_id"],"type":"object"}⟨83 unchanged words⟩ not the same as having no leads. Requires a linked PropertyList account (or an agency APIkey;key); onlyever returns the calling agency'sown leads.
before
—after
{"properties":{"count":{"type":"integer"},"leads":{"items":{"properties":{"contact_id":{"type":"integer"},"created_at":{"description":"ISO 8601, UTC.","type":"string"},"email":{"type":"string"},"id":{"type":"integer"},"lead_type":{"type":"string"},"message":{"type":"string"},"name":{"type":"string"},"phone":{"type":"string"},"property_reference":{"type":"string"},"status":{"description":"new, active, closed_converted or closed_not_converted.","type":["string","integer"]}},"required":["id"],"type":"object"},"type":"array"}},"required":["count","leads"],"type":"object"}⟨22 unchanged words⟩ "is reference X still online?". Requires a linked PropertyList account (or an agency APIkey;key); only everreturns the callingagency's own properties.
before
—after
{"properties":{"count":{"type":"integer"},"listings":{"items":{"properties":{"bathrooms":{"type":"integer"},"bedrooms":{"type":"integer"},"build_sqm":{"type":"integer"},"id":{"type":"integer"},"location":{"type":"object"},"monthly_price":{"type":"integer"},"photo":{"type":"string"},"price":{"description":"Headline price for the listing's transaction type; read with price_period.","type":"integer"},"price_period":{"enum":["total","per_month","per_week"],"type":"string"},"reference":{"type":"string"},"sale_price":{"type":"integer"},"status":{"description":"online, offline, sold, new, inreview...","type":"string"},"updated_at":{"description":"ISO 8601, UTC.","type":"string"},"weekly_price_from":{"type":"integer"}},"required":["id","reference"],"type":"object"},"type":"array"}},"required":["count","listings"],"type":"object"}⟨115 unchanged words⟩ the WHOLE agency's boards, not one agent's cards-:anCRMAPIaccesskeybelongs to the agency, not to a person. Requires a linked PropertyList account (or an agency APIkey;key); only ever returns thecalling agency's own data.
before
—after
{"properties":{"boards":{"description":"The summary of every board, when no pipeline was asked for.","items":{"properties":{"pipeline":{"enum":["lead","buyer","seller","tenant","nurture","property"],"type":"string"},"stages":{"items":{"properties":{"count":{"type":"integer"},"stage":{"type":"string"}},"required":["stage","count"],"type":"object"},"type":"array"},"total":{"type":"integer"}},"required":["pipeline","total","stages"],"type":"object"},"type":"array"},"pipeline":{"description":"The board asked for.","enum":["lead","buyer","seller","tenant","nurture","property"],"type":"string"},"stages":{"description":"That board's stages, each with its full count and up to `limit` cards, most recently updated first.","items":{"properties":{"cards":{"items":{"type":"object"},"type":"array"},"closed":{"type":"boolean"},"count":{"type":"integer"},"stage":{"description":"The agency's own name for the stage.","type":"string"},"value_of_shown_cards":{"description":"EUR, buyer, seller and tenant boards only.","type":"integer"}},"required":["stage","count","cards"],"type":"object"},"type":"array"},"total_cards":{"type":"integer"}},"required":["total_cards"],"type":"object"}⟨76 unchanged words⟩ false. It never substitutes listings from other areas. `location_id` takes an area id from autocomplete_location instead of a name; a group id (type group, e.g. a region or a coast) searches every area in the group. `features` keeps only listings that have ALL the features asked for: pool (any pool, communal included), private_pool, sea_view, garden, parking (a garage or parking space) and terrace. Each result then carries matched_features, saying which tags (and, for parking and terrace, which space count or terrace size) the listing matched on. private_pool means the listing is tagged with a private or heated pool; many agency feeds tag every pool that way, communal ones included, so use pool for "with a pool" and check the listing when a pool must be private. `location.city` is whatever tier the listing was filed ⟨93 unchanged words⟩
⟨18 unchanged words⟩ "minimum":0,"type":"integer"},"features":{"description":"Only listings with ALL of these: pool (any pool), private_pool (tagged private or heated pool), sea_view, garden (private, landscaped or communal), parking (garage or parking space), terrace. Results say what each matched on in matched_features.","items":{"enum":["pool","private_pool","sea_view","garden","parking","terrace"],"type":"string"},"type":"array"},"language":{"default":"en","description": ⟨46 unchanged words⟩ need to confirm match.","type":"string"},"location_id":{"description":"Area id from autocomplete_location. Takes precedence over location. A group id (a region or coast, type group) searches every area in the group.","minimum":1,"type":"integer"},"page":{"default":1,"minimum ⟨71 unchanged words⟩
⟨65 unchanged words⟩ ,"location":{"type":"object"},"matched_features":{"items":{"properties":{"feature":{"type":"string"},"parking_spaces":{"type":"integer"},"tags":{"items":{"type":"string"},"type":"array"},"terrace_sqm":{"type":"integer"}},"type":"object"},"type":"array"},"monthly_price":{"type":["integer","null" ⟨88 unchanged words⟩
⟨69 unchanged words⟩ an API key up to a small dailyper-IPallowance,allowance;counted per IP address, or per account for an app linked to a PropertyList account; an API key removes thatallowance. Provide the property `reference` (from search results ⟨24 unchanged words⟩
before
—after
{"properties":{"agency":{"description":"The agency that received the enquiry.","type":["string","null"]},"lead_id":{"type":"integer"},"reference":{"type":"string"},"status":{"enum":["submitted"],"type":"string"}},"required":["status","lead_id","reference"],"type":"object"}Get a valuation for a property or area in Spain, Portugal or Cyprus from recorded market data, notasking prices. Returns the €/m² (`price_per_sqm`) for the municipality and segment, anindicativeindicative valuation when you give a size (build_sqm) or a listingreference, anda content-hashed attestation URL the figure can be citedfrom. Check `verified` before citing. It is true ⟨13 unchanged words⟩ with at least 10 recorded transactions behind them.ElsewherePortuguese-figuresPortugalcomeandfromCyprustheespeciallyINE-house-pricetheindexfigureandcomesCypriot ones froma national house-pricetheindexCyprusandStatisticalisServiceanhouse-priceestimateindex: they are estimates, `transaction_backed` isfalse, `source_label` names therealsource, anditthey must not bedescribed as notary-verified. Other countries have no figure yet. `indicative_band_pct` widens as the evidence thins. Transactions are ⟨122 unchanged words⟩
{"properties":{"build":{"description":"Alias of build_sqm.","minimum":1,"type":"integer"},"build_size":{"description":"Alias of build_sqm.","minimum":1,"type":"integer"},"build_sqm":{"description":"Built size in m² ⟨63 unchanged words⟩
⟨36 unchanged words⟩ "type":["string","null"]},"price_per_sqm":{"description":"EUR per m². Verified only when `verified` is true; otherwise an estimate from the source in source_label.","type":["integer","null"]},"property_type":{"type":["string","null" ⟨35 unchanged words⟩ :{"type":"boolean"},"verified_price_per_sqm":{"description":"Deprecated: the same figure as price_per_sqm, under its old name. Despite the name it is verified only when `verified` is true.","type":["integer","null"]}}, ⟨5 unchanged words⟩
Find price reductions — Live listings whose asking price has been reduced recently, biggest reduction first. Each listing carries the price before the cut, the price now, the reduction in euros and percent, and when it was cut. Use for "what has dropped in price in Estepona this month?" or to spot motivated sellers. Filters work as in search_properties (location, type, bedrooms, price). A location we do not hold returns zero results with error: location_not_found. Listings shown as price on application are never included.
Find similar properties — Listings similar to one property: same market (sale or rent), same town, same kind of home, a similar number of bedrooms and a price within about 25%. Closest in price first. Use it for "show me alternatives to PL12345" or "anything like this but cheaper?". Every property carries `oracle_verified` and `oracle_attestation_url`, as in search_properties.
Get contact — The full picture of one client in YOUR agency's CRM: contact details, where they sit on the pipeline boards, the agents they belong to, their saved searches, their enquiries, recent notes and history, viewings with outcomes, listings already sent to them, when they were last in touch and what is booked next. Get the contact_id from find_contacts or my_pipeline first. Use this before advising an agent on a client, and before match_buyer_to_inventory, so you know what has already been sent. Requires a linked PropertyList account (or an agency API key); only ever reads the calling agency's own…
Listing health — Checks YOUR agency's own listings for what is holding them back, and lists the ones with problems, most problems first: - stale: online for 90 days or more, no enquiry in the last 60 days and no price change in the last 90 - too_few_photos: fewer than the 5 photos a listing needs to publish - no_energy_rating - missing_description: no Spanish or no English description - no_price: no asking price and not marked price on application Defaults to online listings; status 'draft' checks what is not published yet (what stops it publishing), 'all' checks both. Requires a linked Pro…
Match buyer to inventory — The listings that fit one client's search in YOUR agency's CRM: your own listings first, then shared MLS listings your agency can sell, newest first. Each listing says whether it is your own. Uses the client's saved search (or, if none is saved, the search their latest debrief described), the same search the CRM runs for that client. A client with no search returns an explanation rather than a guess; set one up in the CRM or ask the agent for the brief and use search_properties instead. Get the contact_id from find_contacts. Call get_contact first if you need to know what has already been s…
Match inventory to buyers — The clients in YOUR agency's CRM whose saved search fits one listing: who to call about it. Works for your own listings and for shared MLS listings your agency can sell. Only online listings can be matched (a saved search only ever shows online stock); a draft returns an explanation. Clients are listed with their assigned agent, pipeline stage and the search they matched on. Use get_contact on any of them for the full picture. Requires a linked PropertyList account (or an agency API key); only the calling agency's clients that the caller may see in the CRM.