{
  "markdown": "# joomil-mcp\n\n> MCP server for [Joomil.ch](https://www.joomil.ch) — Switzerland's leading French-speaking classifieds marketplace, active since 2007.\n\nBrowse and search 45,000+ active listings across 34 categories: real estate, vehicles, jobs, animals, electronics, fashion and more — all from Switzerland's French-speaking regions (Romandie).\n\n## Tools\n\n| Tool | Description |\n|------|-------------|\n| `suggest_filters` | Infer `search_classifieds` filters from a natural-language query |\n| `search_classifieds` | Search listings with filters: keyword, category, canton (strict enum), location, price range, sort, pagination |\n| `get_classified` | Get full details of a listing by ID: description, images, vendor, expiry date |\n| `get_categories` | List active categories with hierarchy via `parent_id` |\n| `get_cantons` | List the canton values supported by the `canton` filter (API-specific spellings) |\n\n## Quick Start\n\nThis is a **remote MCP server** — no local installation required.\n\n**Endpoint:** `https://joomil-mcp.snowy-surf-deec.workers.dev/mcp`\n\n### Claude Desktop\n\nAdd to `~/.claude/claude_desktop_config.json`:\n\n```json\n{\n  \"mcpServers\": {\n    \"joomil\": {\n      \"command\": \"npx\",\n      \"args\": [\"mcp-remote\", \"https://joomil-mcp.snowy-surf-deec.workers.dev/mcp\"]\n    }\n  }\n}\n```\n\n### Cursor\n\nAdd to your MCP settings:\n\n```json\n{\n  \"joomil\": {\n    \"url\": \"https://joomil-mcp.snowy-surf-deec.workers.dev/mcp\"\n  }\n}\n```\n\n## Example Prompts\n\n- *\"Trouve-moi une voiture automatique à moins de 10'000 CHF dans le canton de Vaud.\"*\n- *\"Cherche un appartement 3 pièces à Sion.\"*\n- *\"Quelles catégories d'électronique propose Joomil ?\"*\n- *\"Montre-moi les annonces de canapés vintage en Valais.\"*\n- *\"Cherche des offres d'emploi dans l'hôtellerie à Neuchâtel.\"*\n\n> **Tip for agents**: call `get_cantons` before filtering by canton — the API uses\n> non-obvious spellings (e.g. `Bern` not `Berne`, `Geneve` not `Genève`/`Geneva`).\n> For free-text user requests, call `suggest_filters` first, then pass the returned\n> `filters` object to `search_classifieds`.\n\n## API Reference\n\n### `suggest_filters`\n\n| Parameter | Type | Description |\n|-----------|------|-------------|\n| `query` | string | Natural-language search request, e.g. `appartement 3 pièces à Sion` |\n\nReturns a ready-to-use `filters` object for `search_classifieds`, plus a category confidence score and warnings when matching is uncertain. Category metadata is cached briefly by the MCP layer to avoid refetching the category tree for every suggestion.\n\nUseful examples:\n\n| User request | Typical suggested filters |\n|--------------|---------------------------|\n| `Tesla Model 3 moins de 25'000 CHF` | `q: \"Tesla Model 3\"`, `cat_id: 101`, `price_max: 25000`, `sort: \"price_asc\"` |\n| `vélo budget 1.5k CHF` | `q: null`, category in sport/leisure, `price_max: 1500`, `sort: \"price_asc\"` |\n| `appartement 3 pièces à Sion` | `q: \"3 pièces\"`, `cat_id: 10255`, `location: \"Sion\"` |\n| `voiture entre 10'000 et 20'000 CHF` | `cat_id: 101`, `price_min: 10000`, `price_max: 20000` |\n| `Golf GTI dans le canton de Vaud` | `q: \"Golf GTI\"`, `cat_id: 101`, `canton: \"Vaud\"` |\n| `canapé vintage à Lausanne` | `q: \"vintage\"`, `cat_id: 10022`, `location: \"Lausanne\"` |\n| `iPhone 14 à Genève` | `q: \"iPhone 14\"`, `cat_id: 10127`, `location: \"Genève\"` |\n\n```json\n{\n  \"query\": \"appartement 3 pièces à Sion\",\n  \"filters\": {\n    \"q\": \"3 pièces\",\n    \"cat_id\": 10255,\n    \"canton\": null,\n    \"location\": \"Sion\",\n    \"price_min\": null,\n    \"price_max\": null,\n    \"sort\": \"recent\",\n    \"limit\": 20\n  },\n  \"category\": {\n    \"id\": 10255,\n    \"name\": \"Appartements\",\n    \"url\": \"https://www.joomil.ch/annonces/immobilier/locations/appartements/10255\",\n    \"parent_id\": 339,\n    \"confidence\": 0.82,\n    \"reason\": \"requête immobilière appartement\"\n  },\n  \"confidence\": 0.74,\n  \"warnings\": [],\n  \"next_step\": \"Call search_classifieds with the filters object. Adjust q or cat_id if the result set is too broad.\"\n}\n```\n\n### `search_classifieds`\n\n| Parameter | Type | Description |\n|-----------|------|-------------|\n| `q` | string | Full-text search (title + description) |\n| `cat_id` | number | Category ID — includes subcategories |\n| `canton` | enum | Strict enum — see `get_cantons`. `Geneve`, `Vaud`, `Valais`, `Fribourg`, `Neuchatel`, `Jura`, `Bern`, `Argovie`, `Zurich`, `Lucerne`, `Bale-Ville`, `Etranger` |\n| `location` | string | City name or postal code (partial match) |\n| `price_min` | number | Minimum price in CHF |\n| `price_max` | number | Maximum price in CHF |\n| `sort` | enum | `recent` (default, newest first), `price_asc`, `price_desc`, `views` (most viewed) |\n| `limit` | number | Results per page (1–50, default 20) |\n| `offset` | number | Pagination offset — use `next_offset` from previous response |\n\nTool responses include a short human-readable summary followed by compact serialized JSON in `content` for MCP backward compatibility. Full data is also returned in `structuredContent` with `results`, `total`, `limit`, `offset`, `has_more`, `next_offset`, and `filtered_out` (items removed from the current page by MCP-side category restrictions).\n\n**Result shape** (each item):\n```json\n{\n  \"id\": 366872, \"title\": \"Maison avec étangs\",\n  \"price\": { \"amount\": 237977.5, \"currency\": \"CHF\" },\n  \"location\": { \"city\": \"Saint Eugène\", \"postal_code\": \"71320\", \"canton\": \"Geneve\", \"country\": \"FR\" },\n  \"category\": { \"id\": 10261, \"name\": \"Maisons & Villas\", \"url\": \"https://...\" },\n  \"url\": \"https://www.joomil.ch/annonce/.../366872\",\n  \"created_at\": \"2026-06-26T22:17:11+02:00\",\n  \"has_picture\": true,\n  \"seller\": { \"name\": \"jpclair\", \"certified\": false }\n}\n```\n\n### `get_classified`\n\n| Parameter | Type | Description |\n|-----------|------|-------------|\n| `id` | number | Listing ID (from search results or listing URL) |\n\nReturns full listing details, including complete description, images, category path, expiry date, boost level, and seller details.\n\n### `get_categories`\n\n| Parameter | Type | Description |\n|-----------|------|-------------|\n| `parent_id` | number | Optional — omit for all, `0` for root categories, or any category ID for its children |\n\n### `get_cantons`\n\nNo parameters. Returns the canton values accepted by `search_classifieds`' `canton` filter, with their French labels:\n\n```json\n{\n  \"cantons\": [\n    { \"name\": \"Geneve\", \"label_fr\": \"Genève\", \"code\": \"GE\", \"region\": \"Romandie\" },\n    { \"name\": \"Bern\", \"label_fr\": \"Berne\", \"code\": \"BE\", \"region\": \"Suisse alémanique\" }\n  ],\n  \"total\": 12\n}\n```\n\nAlways pass the `name` field (not `label_fr` nor `code`) to the `canton` filter.\n\n## Data\n\n- **Source**: Joomil.ch public REST API\n- **Coverage**: 45,000+ active listings, 34 top-level categories, 190,000+ registered users\n- **Location**: Switzerland (French-speaking regions — Romandie)\n- **Language**: French\n- **Update frequency**: Real-time\n- **Authentication**: None required\n\n## Limitations\n\nThis MCP server is **read-only** and uses **public data only**.\n\n- **No write operations**: cannot create, edit, or delete listings; cannot contact sellers.\n- **No authentication**: no user accounts, no messages, no favorites, no saved searches.\n- **No seller contact**: phone numbers and email addresses are not exposed — use the listing `url` to open Joomil.ch directly.\n- **No posting**: publishing an ad must be done on joomil.ch.\n- **Restricted categories**: Erotique (28), Rencontres & Amitié (14000), Voyance & Astrologie (651), and their descendants are filtered out by the MCP layer per content policy. The underlying PHP API remains available for direct use.\n- **Canton filter is strict**: only the values returned by `get_cantons` are accepted. Other spellings (`Berne`, `Genève`, `Geneva`, `GE`, `VD`...) are silently ignored by the upstream API and would return all listings instead of a filtered set — the strict enum here prevents that.\n- **Currency**: all prices are in CHF. Listings may have `price.amount: null` (price on request) or `0` (free).\n- **Upstream errors**: Joomil API failures are returned as MCP tool errors with `isError: true`.\n\n## Deploy Your Own\n\n```bash\ngit clone https://github.com/Valmo-Sarl/joomil-mcp\ncd joomil-mcp\nnpm install\nnpx wrangler login\nnpm run deploy\n```\n\n## License\n\nMIT\n",
  "bytes": 8198,
  "sha": "1c9da014e9d502ac9c08f8610d2e766defd3f5981d5326d343e9760c4e06ca00",
  "repo_slug": "valmo-sarl/joomil-mcp",
  "fonte": "repo",
  "truncated": false,
  "api": "https://agentalog.com/api/listings/mcp_io_github_valmodev_joomil_aa892e93/readme"
}