---
title: "Outils publics"
description: "Référence des outils MCP de Matchai search_listings, get_listing et get_professional. Entrées, sorties, exemples et widget de fiches d'inscription."
last_updated: "2026-10-21"
lang: "fr-CA"
canonical: "https://matchai.co/docs/fr/developers/mcp-server/public-tools"
---

# Outils publics

> Référence des outils MCP de Matchai search_listings, get_listing et get_professional. Entrées, sorties, exemples et widget de fiches d'inscription.

Source: https://matchai.co/docs/fr/developers/mcp-server/public-tools

Le [serveur MCP](https://matchai.co/docs/fr/developers/mcp-server) offre trois outils. Tous sont en lecture seule, ne demandent aucun compte et ne renvoient que des données publiées.

| Outil | Rôle |
|---|---|
| `search_listings` | Trouver des inscriptions disponibles selon le lieu, le prix, les chambres, les salles de bain, le type de propriété, et la vente ou la location. |
| `get_listing` | Obtenir tous les détails publics d'une inscription à partir de n'importe laquelle de ses adresses ou de son identifiant. |
| `get_professional` | Obtenir le profil public d'un courtier et ses inscriptions disponibles. |

## Comportement des outils [#how-the-tools-behave]

- **Lecture seule.** Chaque outil est annoté `readOnlyHint: true`, `destructiveHint: false`, `idempotentHint: true` et `openWorldHint: false`. Les outils ne font que lire le catalogue publié de Matchai.
- **Trois parties dans chaque résultat.** `content` est du texte brut qu'un modèle peut citer. `structuredContent` contient des données typées qui correspondent au `outputSchema` de l'outil. `_meta` sert au [widget de fiches d'inscription](#the-listing-card-widget) et peut être ignoré par les autres clients.
- **Inconnu signifie null.** Un fait que le courtier n'a pas indiqué vaut `null`, jamais `0`. Une inscription sans prix indiqué a `price: null`.
- **Des arguments tolérants.** Les valeurs `null` et les chaînes vides sont retirées, et les nombres envoyés sous forme de chaînes, comme `"600000"` ou `"$600,000"`, sont convertis avant la validation.
- **Les erreurs qu'un modèle peut corriger** reviennent sous forme de résultat avec `isError: true` et un message. Un appel qui nomme un outil inconnu, ou dont les `arguments` ne sont pas un objet, est une erreur JSON-RPC `-32602`. Voir les [erreurs](https://matchai.co/docs/fr/developers/mcp-server#errors).

## L'objet inscription [#the-listing-object]

`search_listings` et `get_professional` renvoient des objets inscription, et `get_listing` renvoie le même objet avec des champs de détail supplémentaires.

<TypeTable
  type={{
    id: { type: 'string', description: "L'identifiant de l'inscription, un UUID. Passez-le à get_listing." },
    title: { type: 'string', description: "Le titre de l'inscription." },
    url: { type: 'string', description: "La page de l'inscription. C'est le domaine propre du courtier une fois celui-ci actif, et c'est l'adresse à citer et vers laquelle faire un lien." },
    price: { type: 'number | null', description: "Le prix demandé, ou le loyer, dans la devise de l'inscription. null quand le courtier n'en a fixé aucun." },
    currency: { type: 'string', description: 'Le code de devise ISO 4217, généralement CAD.' },
    priceText: { type: 'string | null', description: "Le prix tel que les gens le lisent, par exemple $589,000. null quand il n'y a pas de prix." },
    transaction: { type: '"sale" | "rent" | null', description: 'Indique si la propriété est à vendre ou à louer.' },
    status: { type: '"available" | "sold" | "rented"', description: 'La disponibilité. La recherche ne renvoie que les inscriptions disponibles.' },
    propertyType: { type: '"house" | "condo" | "apartment" | "townhouse" | "plex" | "land" | "cottage" | "commercial" | null', description: "Le type de propriété. plex couvre les duplex jusqu'aux quintuplex." },
    bedrooms: { type: 'number | null', description: 'Le nombre de chambres.' },
    bathrooms: { type: 'number | null', description: "Le nombre de salles de bain. Une salle d'eau compte pour 0,5." },
    livingAreaSqft: { type: 'number | null', description: 'La superficie habitable en pieds carrés, convertie quand le courtier a entré des mètres carrés.' },
    neighbourhood: { type: 'string | null', description: "Le quartier ou l'arrondissement." },
    city: { type: 'string | null', description: 'La ville ou la municipalité.' },
    region: { type: 'string | null', description: 'La province ou la région.' },
    location: { type: 'string | null', description: "La ligne de localité qu'affiche la page de l'inscription, par exemple Plateau-Mont-Royal, Montréal." },
    image: { type: 'string | null', description: "L'URL de la photo de couverture." },
    broker: { type: '{ name: string, brokerage: string | null } | null', description: 'Le courtier inscripteur.' },
    site: { type: '{ name: string | null, url: string }', description: "Le site Matchai du courtier qui publie l'inscription." },
    updatedAt: { type: 'string', description: "Le moment du dernier changement de l'inscription, sous forme d'horodatage ISO 8601." },
  }}
/>

## search_listings [#search_listings]

Cherche parmi les inscriptions publiées qui sont disponibles en ce moment. Renvoie jusqu'à 10 inscriptions, la meilleure correspondance d'abord.

### Entrée [#input]

Tous les champs sont facultatifs. Sans argument, ce sont les inscriptions mises à jour le plus récemment qui sont renvoyées.

<TypeTable
  type={{
    query: { type: 'string', description: "Ce que la personne a demandé, dans ses propres mots et dans n'importe quelle langue, par exemple condo 3 chambres près d'un métro à Laval. Jusqu'à 300 caractères." },
    city: { type: 'string', description: "La ville ou la municipalité, par exemple Montréal ou Gatineau. Jusqu'à 80 caractères. Comparée comme un nom de lieu entier, sans tenir compte des accents." },
    neighbourhood: { type: 'string', description: "Le quartier ou l'arrondissement, par exemple Plateau-Mont-Royal. Jusqu'à 80 caractères." },
    transaction: { type: '"sale" | "rent"', description: 'sale pour acheter, rent pour louer.' },
    propertyType: { type: '"house" | "condo" | "apartment" | "townhouse" | "plex" | "land" | "cottage" | "commercial"', description: 'Le type de propriété.' },
    minPrice: { type: 'integer', description: 'Le prix le plus bas en dollars, ou le loyer mensuel pour les locations. De 0 à 1 000 000 000.' },
    maxPrice: { type: 'integer', description: 'Le prix le plus élevé en dollars, ou le loyer mensuel pour les locations. De 0 à 1 000 000 000.' },
    minBedrooms: { type: 'integer', description: 'Au moins ce nombre de chambres. De 0 à 20.' },
    minBathrooms: { type: 'number', description: "Au moins ce nombre de salles de bain. De 0 à 20. Une salle d'eau compte pour 0,5." },
    limit: { type: 'integer', default: '6', description: "Le nombre d'inscriptions à renvoyer. De 1 à 10." },
  }}
/>

`query` est lu avec le même analyseur que la [recherche d'inscriptions](https://matchai.co/docs/fr/developers/listing-search#what-the-query-understands) : les prix, les chambres, les salles de bain, la vente ou la location et le type de propriété sont extraits de la phrase, en anglais, en français ou en espagnol. Un argument explicite l'emporte toujours sur ce que dit la phrase, et la phrase complète ce que les arguments ne précisent pas. Si `minPrice` est plus élevé que `maxPrice`, les deux valeurs sont interverties.

### Sortie [#output]

<TypeTable
  type={{
    kind: { type: '"listings"', description: 'Indique le type de résultat.' },
    filters: { type: 'object', description: "Les filtres que la recherche a appliqués : keywords, city, neighbourhood, transaction, propertyType, minPrice, maxPrice, minBedrooms et minBathrooms. Chacun vaut null s'il n'a pas été appliqué. keywords contient jusqu'à 6 mots en minuscules, sans accents, qui ont été comparés aux titres, aux lieux, aux types de propriété et aux descriptions." },
    count: { type: 'integer', description: "Le nombre d'inscriptions renvoyées." },
    listings: { type: 'listing[]', description: "Les inscriptions correspondantes, la meilleure correspondance d'abord. Voir l'objet inscription ci-dessus." },
  }}
/>

Le texte de `content` commence par le nombre d'inscriptions et une phrase qui explique leur ordre. Il donne ensuite une entrée par inscription avec le titre, le prix et le type, les données clés, le lieu, le courtier inscripteur et l'URL.

Un résultat vide indique si Matchai a vérifié toutes les inscriptions ou seulement les plus récemment mises à jour. Il n'affirme jamais « il n'en existe aucune » pour une recherche qui n'est pas remontée plus loin. Une ville ou une fourchette de prix permet à la recherche de remonter plus loin.

### Exemple [#example]

Envoyez ceci comme requête `tools/call` :

```json
{
  "jsonrpc": "2.0",
  "id": 3,
  "method": "tools/call",
  "params": {
    "name": "search_listings",
    "arguments": { "query": "3 bedroom condo in Laval under 600k" }
  }
}
```

Un résultat abrégé. Cette recherche a trouvé une inscription, et l'objet `filters` montre comment la phrase a été lue :

```json
{
  "content": [
    {
      "type": "text",
      "text": "1 published listing on Matchai. Results are ordered by relevance to the request and by how recently the listing was updated. No broker can pay to change the order or to be included.\n\n1. Bright 3-bedroom condo near Montmorency metro — $585,000, condo for sale\n   3 bedrooms · 1.5 bathrooms · 1,120 sq ft · Montmorency, Laval, Québec\n   Listed by Alice Tremblay (Agence Exemple)\n   https://alice.matchai.co/bright-condo-montmorency"
    }
  ],
  "structuredContent": {
    "kind": "listings",
    "filters": {
      "keywords": ["laval"],
      "city": null,
      "neighbourhood": null,
      "transaction": null,
      "propertyType": "condo",
      "minPrice": null,
      "maxPrice": 600000,
      "minBedrooms": 3,
      "minBathrooms": null
    },
    "count": 1,
    "listings": [
      {
        "id": "7c9e6679-7425-40de-944b-e07fc1f90ae7",
        "title": "Bright 3-bedroom condo near Montmorency metro",
        "url": "https://alice.matchai.co/bright-condo-montmorency",
        "price": 585000,
        "currency": "CAD",
        "priceText": "$585,000",
        "transaction": "sale",
        "status": "available",
        "propertyType": "condo",
        "bedrooms": 3,
        "bathrooms": 1.5,
        "livingAreaSqft": 1120,
        "neighbourhood": "Montmorency",
        "city": "Laval",
        "region": "Québec",
        "location": "Montmorency, Laval, Québec",
        "image": "https://media.example.com/listings/bright-condo-montmorency/cover.jpg",
        "broker": { "name": "Alice Tremblay", "brokerage": "Agence Exemple" },
        "site": { "name": "Alice Tremblay Immobilier", "url": "https://alice.matchai.co" },
        "updatedAt": "2026-10-12T14:03:22.000Z"
      }
    ]
  },
  "_meta": {
    "ui": { "resourceUri": "ui://matchai/listing-cards.html?v=3f9a1c2b7d10" }
  }
}
```

Le véritable objet `_meta` contient quelques clés de plus pour le widget. Les noms, les adresses et l'hôte des photos de ces exemples sont fictifs.

## get_listing [#get_listing]

Renvoie tous les détails publics d'une inscription publiée.

### Entrée [#input-1]

Envoyez `url` ou `id`. Si vous envoyez les deux, c'est `id` qui est utilisé.

<TypeTable
  type={{
    url: { type: 'string', description: "N'importe quelle adresse de la page de l'inscription. Jusqu'à 2 048 caractères. Le schéma peut être omis." },
    id: { type: 'string', description: "L'identifiant de l'inscription, un UUID, tiré d'un résultat précédent." },
  }}
/>

Ces adresses désignent toutes la même inscription, avec ou sans barre oblique finale ou paramètres de suivi :

- le site Matchai du courtier, comme `https://alice.matchai.co/bright-condo-montmorency`;
- l'ancienne forme avec `/listing/` devant le slug, comme `https://alice.matchai.co/listing/bright-condo-montmorency`;
- le domaine propre du courtier, quand le site en a un;
- la forme avec chemin sur la plateforme, comme `https://matchai.co/site/alice/bright-condo-montmorency`;
- la copie Markdown de n'importe laquelle de ces adresses, qui se termine par `.md`;
- l'identifiant seul de l'inscription.

### Sortie [#output-1]

<TypeTable
  type={{
    kind: { type: '"listing"', description: 'Indique le type de résultat.' },
    listing: { type: 'listing object + details', description: "L'objet inscription ci-dessus, plus les champs ci-dessous." },
  }}
/>

Les champs supplémentaires de `listing` :

<TypeTable
  type={{
    description: { type: 'string | null', description: 'La description du courtier, raccourcie à 1 500 caractères.' },
    highlights: { type: 'string[]', description: "Jusqu'à 8 points forts choisis par le courtier." },
    yearBuilt: { type: 'number | null', description: "L'année de construction du bâtiment." },
    lotSizeSqft: { type: 'number | null', description: 'La superficie du terrain en pieds carrés.' },
    address: { type: 'string | null', description: "La ligne de l'adresse civique. Présente seulement si le courtier a publié l'adresse." },
    postalCode: { type: 'string | null', description: "Présent seulement si le courtier a publié l'adresse." },
    images: { type: 'string[]', description: "Jusqu'à 8 URL de photos, la photo de couverture en premier." },
    datePosted: { type: 'string | null', description: "La date de la première publication de l'inscription." },
  }}
/>

La recherche ne renvoie que des inscriptions disponibles. `get_listing` peut aussi renvoyer une inscription publiée qui a depuis été vendue ou louée, alors vérifiez `status`.

Si aucune inscription publiée ne correspond, le résultat a `isError: true` et indique que l'inscription n'est peut-être plus publiée ou que l'adresse est peut-être incomplète.

### Exemple [#example-1]

```json
{
  "name": "get_listing",
  "arguments": { "url": "https://alice.matchai.co/bright-condo-montmorency" }
}
```

Le `structuredContent` du résultat, abrégé :

```json
{
  "kind": "listing",
  "listing": {
    "id": "7c9e6679-7425-40de-944b-e07fc1f90ae7",
    "title": "Bright 3-bedroom condo near Montmorency metro",
    "url": "https://alice.matchai.co/bright-condo-montmorency",
    "price": 585000,
    "currency": "CAD",
    "priceText": "$585,000",
    "transaction": "sale",
    "status": "available",
    "propertyType": "condo",
    "bedrooms": 3,
    "bathrooms": 1.5,
    "livingAreaSqft": 1120,
    "neighbourhood": "Montmorency",
    "city": "Laval",
    "region": "Québec",
    "location": "Montmorency, Laval, Québec",
    "image": "https://media.example.com/listings/bright-condo-montmorency/cover.jpg",
    "broker": { "name": "Alice Tremblay", "brokerage": "Agence Exemple" },
    "site": { "name": "Alice Tremblay Immobilier", "url": "https://alice.matchai.co" },
    "updatedAt": "2026-10-12T14:03:22.000Z",
    "description": "A bright corner unit on the fourth floor, five minutes from the metro. …",
    "highlights": ["Two balconies", "Indoor parking", "Five minutes from the metro"],
    "yearBuilt": 2012,
    "lotSizeSqft": null,
    "address": null,
    "postalCode": null,
    "images": [
      "https://media.example.com/listings/bright-condo-montmorency/cover.jpg",
      "https://media.example.com/listings/bright-condo-montmorency/living-room.jpg"
    ],
    "datePosted": "2026-09-30"
  }
}
```

Ici, le courtier n'a pas publié l'adresse civique, alors `address` et `postalCode` valent `null`.

## get_professional [#get_professional]

Renvoie le profil public d'un courtier avec ses inscriptions disponibles, jusqu'à 10.

### Entrée [#input-2]

Envoyez `username` ou `url`. Si vous envoyez les deux, c'est `username` qui est utilisé.

<TypeTable
  type={{
    username: { type: 'string', description: "Le nom d'utilisateur Matchai du courtier, par exemple alice_tremblay. Un @ au début est ignoré. Jusqu'à 64 caractères." },
    url: { type: 'string', description: "Le site Matchai du courtier, comme https://alice.matchai.co, sa Page Matchai, comme https://alice.matchai.pro, sa carte professionnelle ou son profil, ou n'importe laquelle de ses pages d'inscription. Jusqu'à 2 048 caractères." },
  }}
/>

### Sortie [#output-2]

<TypeTable
  type={{
    kind: { type: '"professional"', description: 'Indique le type de résultat.' },
    professional: { type: 'object', description: 'Le courtier. Voir les champs ci-dessous.' },
    listings: { type: 'listing[]', description: "Les inscriptions publiées et disponibles du courtier, jusqu'à 10." },
  }}
/>

Les champs de `professional` :

<TypeTable
  type={{
    name: { type: 'string', description: 'Le nom du courtier.' },
    username: { type: 'string | null', description: "Son nom d'utilisateur Matchai." },
    jobTitle: { type: 'string | null', description: 'Son titre professionnel.' },
    brokerage: { type: 'string | null', description: 'Son agence immobilière.' },
    licence: { type: '{ number: string, body: string | null } | null', description: "Son numéro de permis et l'organisme de réglementation, par exemple OACIQ. null quand aucun permis n'est au dossier." },
    photo: { type: 'string | null', description: "L'URL de sa photo de profil." },
    siteUrl: { type: 'string | null', description: "Son site Matchai, lorsqu'il est publié." },
    pageUrl: { type: 'string | null', description: "Sa Page Matchai, lorsqu'elle est publiée." },
    contact: { type: '{ email: string | null, phone: string | null }', description: 'Son adresse courriel et son numéro de téléphone. Les deux valent null, sauf si le courtier les a publiés sur sa carte professionnelle.' },
  }}
/>

Un courtier n'est renvoyé que s'il a choisi d'être public quelque part : un site publié, une Page Matchai publiée ou une carte professionnelle activée. Sinon, le résultat a `isError: true` et indique qu'aucun courtier ayant un profil Matchai public ne correspond.

### Exemple [#example-2]

```json
{
  "name": "get_professional",
  "arguments": { "username": "alice_tremblay" }
}
```

La partie `professional` du `structuredContent` du résultat. Le tableau `listings` à côté contient des objets inscription comme ceux de `search_listings`.

```json
{
  "name": "Alice Tremblay",
  "username": "alice_tremblay",
  "jobTitle": "Real estate broker",
  "brokerage": "Agence Exemple",
  "licence": { "number": "123456", "body": "OACIQ" },
  "photo": "https://media.example.com/avatars/alice-tremblay.jpg",
  "siteUrl": "https://alice.matchai.co",
  "pageUrl": "https://alice.matchai.pro",
  "contact": { "email": null, "phone": null }
}
```

## Le widget de fiches d'inscription [#the-listing-card-widget]

Quand un outil renvoie des inscriptions, les assistants qui prennent en charge MCP Apps peuvent les afficher sous forme de fiches dans la conversation. Les fiches proviennent d'une seule ressource, vers laquelle pointent tous les outils.

| Détail | Valeur |
|---|---|
| URI | `ui://matchai/listing-cards.html?v=…`, où `v` est une version qui change chaque fois que le widget change |
| Type | `text/html;profile=mcp-app` |
| Nom | `listing-cards` (titre « Listing cards ») |
| Référencé dans | `_meta.ui.resourceUri` sur chaque outil de `tools/list` et sur chaque résultat. ChatGPT lit le même URI dans sa propre clé de `_meta`. |

Lisez l'URI actuel dans `tools/list` au lieu de le coder en dur. `resources/read` accepte aussi l'URI sans `v`, ou avec n'importe quel ancien `v`, et répond avec le widget actuel.

`resources/list` renvoie cette ressource unique, avec la politique de sécurité du contenu que l'assistant devrait appliquer :

```json
{
  "resources": [
    {
      "uri": "ui://matchai/listing-cards.html?v=3f9a1c2b7d10",
      "name": "listing-cards",
      "title": "Listing cards",
      "description": "Interactive cards for the listings a Matchai tool returned.",
      "mimeType": "text/html;profile=mcp-app",
      "_meta": {
        "ui": {
          "csp": {
            "connectDomains": ["https://matchai.co"],
            "resourceDomains": ["https://matchai.co", "https://media.example.com"]
          },
          "prefersBorder": true
        }
      }
    }
  ]
}
```

`resources/read` renvoie le widget sous forme d'un seul document HTML autonome dans `contents[0].text`. Il n'utilise aucun cadriciel, ni aucune police ou aucun script externe.

Ce que fait le widget :

- **Il affiche le résultat selon son type.** `kind: "listings"` devient une rangée défilante de fiches, `kind: "listing"` devient une fiche plus grande avec une courte description, et `kind: "professional"` devient le nom et le rôle du courtier, avec un lien **Visiter le site**, au-dessus d'une rangée de fiches.
- **Il suit l'assistant.** Il utilise le thème de couleurs et la langue de l'assistant (anglais, français ou espagnol) et ouvre les liens par l'intermédiaire de l'assistant.
- **Il gère les échecs.** Un résultat avec `isError: true`, ou sans `structuredContent`, affiche « Rien à afficher ».
- **Il signale qu'une fiche a été vue.** Quand une fiche est restée à l'écran assez longtemps pour être lue, le widget indique à Matchai quelles inscriptions étaient visibles, pendant combien de temps et dans quelle proportion, ainsi que le type approximatif de plateforme de l'assistant (Web, ordinateur ou mobile). Si le résultat ne porte aucun jeton pour ce signalement, rien n'est envoyé. Le widget n'envoie jamais le texte de la conversation ni un identifiant d'utilisateur.

Un assistant qui n'affiche pas les MCP Apps ignore le widget. Le texte de `content` et les données de `structuredContent` portent toute la réponse. Si vous créez vos propres fiches, reliez chacune à l'`url` de l'inscription.

<Cards>
  <Card title="Serveur MCP" href="https://matchai.co/docs/fr/developers/mcp-server">
    Points de terminaison, transport et connexion d'un assistant.
  </Card>
  <Card title="Recherche d'inscriptions" href="https://matchai.co/docs/fr/developers/listing-search">
    La même recherche, sous forme de point de terminaison HTTP simple.
  </Card>
</Cards>

## Sitemap

- [Toutes les pages de la documentation Matchai](https://matchai.co/docs/sitemap.md)
- [llms.txt](https://matchai.co/docs/fr/llms.txt)
