verychic-mcp 0.1.0__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- verychic_mcp-0.1.0/.dockerignore +13 -0
- verychic_mcp-0.1.0/.github/workflows/release.yml +90 -0
- verychic_mcp-0.1.0/.gitignore +29 -0
- verychic_mcp-0.1.0/CLAUDE.md +93 -0
- verychic_mcp-0.1.0/DEPLOY.md +31 -0
- verychic_mcp-0.1.0/Dockerfile +12 -0
- verychic_mcp-0.1.0/LICENSE +21 -0
- verychic_mcp-0.1.0/PKG-INFO +109 -0
- verychic_mcp-0.1.0/README.md +85 -0
- verychic_mcp-0.1.0/pyproject.toml +38 -0
- verychic_mcp-0.1.0/render.yaml +9 -0
- verychic_mcp-0.1.0/tests/__init__.py +0 -0
- verychic_mcp-0.1.0/tests/fixtures/checkin_availabilities_sample.json +42 -0
- verychic_mcp-0.1.0/tests/fixtures/hotel_sample.json +1508 -0
- verychic_mcp-0.1.0/tests/fixtures/preview_sample.json +29 -0
- verychic_mcp-0.1.0/tests/fixtures/products_sample.json +329 -0
- verychic_mcp-0.1.0/tests/test_api.py +94 -0
- verychic_mcp-0.1.0/tests/test_discovery.py +34 -0
- verychic_mcp-0.1.0/tests/test_errors.py +18 -0
- verychic_mcp-0.1.0/tests/test_http_client.py +73 -0
- verychic_mcp-0.1.0/tests/test_network_smoke.py +30 -0
- verychic_mcp-0.1.0/tests/test_parsers.py +63 -0
- verychic_mcp-0.1.0/tests/test_server.py +40 -0
- verychic_mcp-0.1.0/verychic_mcp/__init__.py +1 -0
- verychic_mcp-0.1.0/verychic_mcp/api.py +72 -0
- verychic_mcp-0.1.0/verychic_mcp/config.py +23 -0
- verychic_mcp-0.1.0/verychic_mcp/discovery.py +22 -0
- verychic_mcp-0.1.0/verychic_mcp/errors.py +22 -0
- verychic_mcp-0.1.0/verychic_mcp/http_client.py +59 -0
- verychic_mcp-0.1.0/verychic_mcp/models.py +57 -0
- verychic_mcp-0.1.0/verychic_mcp/parsers.py +55 -0
- verychic_mcp-0.1.0/verychic_mcp/server.py +72 -0
|
@@ -0,0 +1,90 @@
|
|
|
1
|
+
name: Release & Publish to PyPI
|
|
2
|
+
|
|
3
|
+
on:
|
|
4
|
+
push:
|
|
5
|
+
tags:
|
|
6
|
+
- "v*"
|
|
7
|
+
|
|
8
|
+
jobs:
|
|
9
|
+
test:
|
|
10
|
+
name: Run Tests
|
|
11
|
+
runs-on: ubuntu-latest
|
|
12
|
+
steps:
|
|
13
|
+
- name: Checkout code
|
|
14
|
+
uses: actions/checkout@v5
|
|
15
|
+
|
|
16
|
+
- name: Set up Python
|
|
17
|
+
uses: actions/setup-python@v6
|
|
18
|
+
with:
|
|
19
|
+
python-version: "3.12"
|
|
20
|
+
|
|
21
|
+
- name: Install dependencies
|
|
22
|
+
run: pip install -e ".[dev]"
|
|
23
|
+
|
|
24
|
+
- name: Run unit tests (offline) + lint
|
|
25
|
+
run: |
|
|
26
|
+
pytest
|
|
27
|
+
ruff check verychic_mcp tests
|
|
28
|
+
|
|
29
|
+
build:
|
|
30
|
+
name: Build Package
|
|
31
|
+
needs: test
|
|
32
|
+
runs-on: ubuntu-latest
|
|
33
|
+
steps:
|
|
34
|
+
- name: Checkout code
|
|
35
|
+
uses: actions/checkout@v5
|
|
36
|
+
|
|
37
|
+
- name: Set up Python
|
|
38
|
+
uses: actions/setup-python@v6
|
|
39
|
+
with:
|
|
40
|
+
python-version: "3.12"
|
|
41
|
+
|
|
42
|
+
- name: Build package
|
|
43
|
+
run: |
|
|
44
|
+
pip install build
|
|
45
|
+
python -m build
|
|
46
|
+
|
|
47
|
+
- name: Upload dist artifacts
|
|
48
|
+
uses: actions/upload-artifact@v5
|
|
49
|
+
with:
|
|
50
|
+
name: dist
|
|
51
|
+
path: dist/
|
|
52
|
+
|
|
53
|
+
publish-pypi:
|
|
54
|
+
name: Publish to PyPI
|
|
55
|
+
needs: build
|
|
56
|
+
runs-on: ubuntu-latest
|
|
57
|
+
environment: pypi
|
|
58
|
+
permissions:
|
|
59
|
+
id-token: write # OIDC trusted publishing — no token stored
|
|
60
|
+
steps:
|
|
61
|
+
- name: Download dist artifacts
|
|
62
|
+
uses: actions/download-artifact@v5
|
|
63
|
+
with:
|
|
64
|
+
name: dist
|
|
65
|
+
path: dist/
|
|
66
|
+
|
|
67
|
+
- name: Publish to PyPI
|
|
68
|
+
uses: pypa/gh-action-pypi-publish@release/v1
|
|
69
|
+
|
|
70
|
+
github-release:
|
|
71
|
+
name: Create GitHub Release
|
|
72
|
+
needs: publish-pypi
|
|
73
|
+
runs-on: ubuntu-latest
|
|
74
|
+
permissions:
|
|
75
|
+
contents: write
|
|
76
|
+
steps:
|
|
77
|
+
- name: Checkout code
|
|
78
|
+
uses: actions/checkout@v5
|
|
79
|
+
|
|
80
|
+
- name: Download dist artifacts
|
|
81
|
+
uses: actions/download-artifact@v5
|
|
82
|
+
with:
|
|
83
|
+
name: dist
|
|
84
|
+
path: dist/
|
|
85
|
+
|
|
86
|
+
- name: Create GitHub Release
|
|
87
|
+
uses: softprops/action-gh-release@v3
|
|
88
|
+
with:
|
|
89
|
+
files: dist/*
|
|
90
|
+
generate_release_notes: true
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
# Secrets / credentials — never commit
|
|
2
|
+
.env
|
|
3
|
+
.env.*
|
|
4
|
+
*.har
|
|
5
|
+
secrets.*
|
|
6
|
+
|
|
7
|
+
# Python
|
|
8
|
+
__pycache__/
|
|
9
|
+
*.py[cod]
|
|
10
|
+
.venv/
|
|
11
|
+
venv/
|
|
12
|
+
*.egg-info/
|
|
13
|
+
dist/
|
|
14
|
+
build/
|
|
15
|
+
.pytest_cache/
|
|
16
|
+
.ruff_cache/
|
|
17
|
+
.mypy_cache/
|
|
18
|
+
|
|
19
|
+
# Node (si la Phase 0 tranche pour Node/TS)
|
|
20
|
+
node_modules/
|
|
21
|
+
*.tsbuildinfo
|
|
22
|
+
|
|
23
|
+
# OS / editor
|
|
24
|
+
.DS_Store
|
|
25
|
+
.idea/
|
|
26
|
+
.vscode/
|
|
27
|
+
|
|
28
|
+
# Scratch de pilotage (subagent-driven-development)
|
|
29
|
+
.superpowers/
|
|
@@ -0,0 +1,93 @@
|
|
|
1
|
+
# CLAUDE.md — verychic-mcp
|
|
2
|
+
|
|
3
|
+
Serveur MCP **non officiel, read-only, anonyme** pour les offres d'hôtels VeryChic.
|
|
4
|
+
3 outils : `verychic_list_deals`, `verychic_search_offers`, `verychic_offer_details`
|
|
5
|
+
(détail + disponibilité/prix par dates). HTTP pur (curl_cffi), double transport
|
|
6
|
+
(stdio + streamable-http). Non affilié à VeryChic — voir le disclaimer du `README.md`.
|
|
7
|
+
|
|
8
|
+
## Les 4 principes à intégrer
|
|
9
|
+
|
|
10
|
+
1. **Think Before Coding** — expliciter les hypothèses ; si plusieurs interprétations, les présenter (ne pas trancher en silence) ; si plus simple existe, le dire ; si flou, s'arrêter et demander.
|
|
11
|
+
2. **Simplicity First** — code minimal qui résout le problème ; rien de spéculatif ; pas d'abstraction pour usage unique ; si 200 lignes pour 50, réécrire.
|
|
12
|
+
3. **Surgical Changes** — ne toucher que le nécessaire ; ne pas « améliorer » le code adjacent ; matcher le style existant ; signaler le dead code, ne pas le supprimer ; nettoyer seulement les orphelins créés par ses propres changements.
|
|
13
|
+
4. **Goal-Driven Execution** — transformer la tâche en critères vérifiables (« fix the bug » → « écrire un test qui le reproduit puis le faire passer ») ; plan bref multi-étapes avec vérification par étape.
|
|
14
|
+
|
|
15
|
+
## Commandes
|
|
16
|
+
|
|
17
|
+
```bash
|
|
18
|
+
pip install -e ".[dev]" # installer (deps : curl_cffi, mcp[cli])
|
|
19
|
+
pytest # tests hors-ligne (fixtures) — exclut @network
|
|
20
|
+
pytest -m network # smoke-test réseau réel (touche l'API live, faible volume)
|
|
21
|
+
ruff check verychic_mcp tests # lint
|
|
22
|
+
verychic-mcp --help # CLI (transports stdio / streamable-http)
|
|
23
|
+
verychic-mcp # lance en stdio (défaut)
|
|
24
|
+
python -m build # construit le wheel (publication)
|
|
25
|
+
```
|
|
26
|
+
|
|
27
|
+
Tests **hors-ligne** : ils tournent sur des fixtures JSON réelles dans `tests/fixtures/`
|
|
28
|
+
(capturées en Phase 0), aucune dépendance réseau. Le smoke `@network` est opt-in et
|
|
29
|
+
exclu de la CI par défaut (`addopts = "-m 'not network'"`).
|
|
30
|
+
|
|
31
|
+
## Architecture (une responsabilité par module, testable isolément)
|
|
32
|
+
|
|
33
|
+
```
|
|
34
|
+
config.py → constantes : routes, PRODUCT_PARAMS, rate-limit, fallback channelVersion
|
|
35
|
+
errors.py → VeryChicError + CloudflareBlocked / NotFound / UpstreamError (messages actionnables)
|
|
36
|
+
http_client.py → VeryChicClient : session curl_cffi (empreinte Chrome), rate-limit injectable,
|
|
37
|
+
classify_block() mappe les réponses HTTP en exceptions. get_json / get_text.
|
|
38
|
+
discovery.py → get_channel_version() : lit channelVersion sur le site live, fallback en dur
|
|
39
|
+
models.py → dataclasses Offer / Availability / OfferDetails (+ offer_url, cheapest_price)
|
|
40
|
+
parsers.py → JSON brut → modèles (tolérant aux champs manquants via .get)
|
|
41
|
+
api.py → list_deals / search_offers / offer_details : compose client + routes + parsers
|
|
42
|
+
server.py → FastMCP : enregistre les 3 outils, resolve_transport(), main()
|
|
43
|
+
```
|
|
44
|
+
|
|
45
|
+
Flux d'un appel : `server` (outil) → `api` (route + params) → `http_client.get_json` → `parsers` → modèle sérialisé en dict.
|
|
46
|
+
|
|
47
|
+
## Spécificités de l'API VeryChic
|
|
48
|
+
|
|
49
|
+
- Base unifiée : `https://api.verychic.com/verychic-endpoints/v1` (+ `search.verychic.com`).
|
|
50
|
+
Tout est **public/anonyme** (200 sans login), **pas de challenge Cloudflare** (confirmé en Phase 0).
|
|
51
|
+
- **`memberStatus=PROSPECT`** = visiteur anonyme (valeur d'enum valide ; `P` est rejeté en 422).
|
|
52
|
+
Centralisé dans `config.PRODUCT_PARAMS` — un seul endroit à changer.
|
|
53
|
+
- Deux types de `source` dans le catalogue, à router différemment dans `offer_details` :
|
|
54
|
+
- `ORCHESTRA` (hôtel) → base `/hotel/{source}/{id}.json` ; dispo via `/product/.../checkin-availabilities.json` (200).
|
|
55
|
+
- `ORCHESTRA_TO` (package tour-op) → base `/vacation-package/{source}/{id}.json` ; `checkin-availabilities` répond **400** → la dispo est **best-effort** (catch `NotFound`/`UpstreamError` → `[]`, mais on laisse remonter `CloudflareBlocked`).
|
|
56
|
+
- Page d'offre côté site : `https://www.verychic.fr/p/{externalId}/{urlName}` (→ `Offer.offer_url`).
|
|
57
|
+
- `channelVersion` (paramètre volatil de `preview.json`) est auto-découvert, avec fallback en dur dans `config.py`.
|
|
58
|
+
|
|
59
|
+
## Conventions
|
|
60
|
+
|
|
61
|
+
- **Read-only, anonyme, faible volume** : aucun credential, aucune écriture/réservation, rate-limit ≥ 1 s entre requêtes (dans `http_client`). Posture défensive : pas d'extraction massive, pas de contournement Cloudflare.
|
|
62
|
+
- **Erreurs actionnables** : toujours via les exceptions de `errors.py`, jamais un stacktrace brut.
|
|
63
|
+
- **TDD + fixtures réelles** : pour toute évolution des parsers/API, ajouter/étendre un test hors-ligne sur une fixture. Un changement de comportement face à l'API live se valide via le smoke `@network`.
|
|
64
|
+
- Messages de commit / docs en français ; README en anglais (convention OSS).
|
|
65
|
+
|
|
66
|
+
## Publication / Release
|
|
67
|
+
|
|
68
|
+
Repo public : **https://github.com/jordantete/verychic-mcp**.
|
|
69
|
+
|
|
70
|
+
La publication PyPI est **automatisée par `.github/workflows/release.yml`** au push d'un
|
|
71
|
+
tag `v*` : `test → build → publish-pypi → github-release`. L'auth PyPI se fait par
|
|
72
|
+
**Trusted Publishing (OIDC)** — **aucun token stocké**. Setup PyPI une fois : un *trusted
|
|
73
|
+
publisher* (projet `verychic-mcp`, owner `jordantete`, repo `verychic-mcp`, workflow
|
|
74
|
+
`release.yml`, environnement `pypi`).
|
|
75
|
+
|
|
76
|
+
Publier une version (SemVer) :
|
|
77
|
+
```bash
|
|
78
|
+
git switch main && git pull
|
|
79
|
+
pytest && ruff check verychic_mcp tests # doit passer avant de tagger
|
|
80
|
+
# bumper "version" dans pyproject.toml (X.Y.Z), puis :
|
|
81
|
+
git add pyproject.toml && git commit -m "chore: release vX.Y.Z"
|
|
82
|
+
git tag vX.Y.Z
|
|
83
|
+
git push origin main --tags
|
|
84
|
+
```
|
|
85
|
+
Le workflow fait le reste (build + upload PyPI + GitHub Release). Une fois publié,
|
|
86
|
+
`uvx verychic-mcp` fonctionne sans cloner. Ne jamais committer de token PyPI.
|
|
87
|
+
|
|
88
|
+
## État & suivi
|
|
89
|
+
|
|
90
|
+
MCP **fonctionnel et validé contre l'API live**, repo GitHub public, CI de release en place
|
|
91
|
+
(sur `main`). Reste : 1ère publication PyPI (config trusted publisher + tag) et déploiement
|
|
92
|
+
remote pour Cowork. Améliorations notées et suivi : projet Notion `verychic-mcp` et
|
|
93
|
+
`docs/superpowers/` (spec, verdict Phase 0, plans).
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
# Deploying VeryChic MCP for Claude.ai / Cowork
|
|
2
|
+
|
|
3
|
+
Cloud Claude clients only talk to **remote** MCP servers over HTTPS. To use VeryChic MCP from
|
|
4
|
+
claude.ai or Cowork, self-host it in `streamable-http` mode and add it as a custom connector.
|
|
5
|
+
|
|
6
|
+
## Option A — Docker (anywhere)
|
|
7
|
+
|
|
8
|
+
```bash
|
|
9
|
+
docker build -t verychic-mcp .
|
|
10
|
+
docker run -p 8000:8000 verychic-mcp
|
|
11
|
+
# serves streamable-http on http://localhost:8000 (put it behind HTTPS for real use)
|
|
12
|
+
```
|
|
13
|
+
|
|
14
|
+
## Option B — Render (1-click-ish)
|
|
15
|
+
|
|
16
|
+
This repo ships a `render.yaml`. On [Render](https://render.com): New → Blueprint → point it at your
|
|
17
|
+
fork. It builds the `Dockerfile` and exposes the server over HTTPS. Render injects `$PORT`
|
|
18
|
+
automatically; the container's start command already honors it.
|
|
19
|
+
|
|
20
|
+
## Add it to Claude.ai / Cowork
|
|
21
|
+
|
|
22
|
+
1. Copy your deployment's HTTPS URL (e.g. `https://verychic-mcp.onrender.com`).
|
|
23
|
+
2. Claude settings → Connectors → **Add custom connector** → paste the URL.
|
|
24
|
+
3. The three `verychic_*` tools become available in your chats.
|
|
25
|
+
|
|
26
|
+
## Notes
|
|
27
|
+
|
|
28
|
+
- The server is **anonymous and read-only**; no secrets or environment variables are required.
|
|
29
|
+
- Keep it private to you / low-traffic — see the disclaimer in the README.
|
|
30
|
+
- Default bind host is `127.0.0.1` for local stdio use; the Docker image binds `0.0.0.0` so the
|
|
31
|
+
platform can route to it.
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
FROM python:3.12-slim
|
|
2
|
+
|
|
3
|
+
WORKDIR /app
|
|
4
|
+
COPY pyproject.toml README.md LICENSE ./
|
|
5
|
+
COPY verychic_mcp ./verychic_mcp
|
|
6
|
+
RUN pip install --no-cache-dir .
|
|
7
|
+
|
|
8
|
+
ENV PORT=8000
|
|
9
|
+
EXPOSE 8000
|
|
10
|
+
|
|
11
|
+
# Transport HTTP distant ; l'hébergeur fournit $PORT.
|
|
12
|
+
CMD ["sh", "-c", "verychic-mcp --transport streamable-http --host 0.0.0.0 --port ${PORT:-8000}"]
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 VeryChic MCP contributors
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
|
@@ -0,0 +1,109 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: verychic-mcp
|
|
3
|
+
Version: 0.1.0
|
|
4
|
+
Summary: Unofficial read-only MCP server for VeryChic hotel offers
|
|
5
|
+
Project-URL: Homepage, https://github.com/jordantete/verychic-mcp
|
|
6
|
+
Project-URL: Repository, https://github.com/jordantete/verychic-mcp
|
|
7
|
+
Project-URL: Issues, https://github.com/jordantete/verychic-mcp/issues
|
|
8
|
+
Author: VeryChic MCP contributors
|
|
9
|
+
License-Expression: MIT
|
|
10
|
+
License-File: LICENSE
|
|
11
|
+
Keywords: hotels,mcp,model-context-protocol,travel,verychic
|
|
12
|
+
Classifier: License :: OSI Approved :: MIT License
|
|
13
|
+
Classifier: Operating System :: OS Independent
|
|
14
|
+
Classifier: Programming Language :: Python :: 3
|
|
15
|
+
Classifier: Topic :: Internet :: WWW/HTTP
|
|
16
|
+
Requires-Python: >=3.11
|
|
17
|
+
Requires-Dist: curl-cffi>=0.7
|
|
18
|
+
Requires-Dist: mcp[cli]>=1.2
|
|
19
|
+
Provides-Extra: dev
|
|
20
|
+
Requires-Dist: build>=1.2; extra == 'dev'
|
|
21
|
+
Requires-Dist: pytest>=8; extra == 'dev'
|
|
22
|
+
Requires-Dist: ruff>=0.6; extra == 'dev'
|
|
23
|
+
Description-Content-Type: text/markdown
|
|
24
|
+
|
|
25
|
+
# VeryChic MCP
|
|
26
|
+
|
|
27
|
+
An **unofficial, read-only** [Model Context Protocol](https://modelcontextprotocol.io) server for
|
|
28
|
+
[VeryChic](https://www.verychic.fr) hotel flash-sale offers. Search current deals, filter them, and
|
|
29
|
+
get an offer's details with availability and prices by date — straight from your MCP client.
|
|
30
|
+
|
|
31
|
+
> ⚠️ **Disclaimer.** This project is **not affiliated with, endorsed by, or connected to VeryChic /
|
|
32
|
+
> VeryChic SAS** in any way. It is an independent, community tool for **personal use**. It accesses
|
|
33
|
+
> VeryChic's public web API the same way a browser does. You are responsible for complying with
|
|
34
|
+
> VeryChic's Terms (Conditions Générales de Vente — notably Art. 9 on intellectual property and the
|
|
35
|
+
> *sui generis* database right). Use it at your own risk, for personal, low-volume browsing only.
|
|
36
|
+
> Do not use it for bulk extraction or redistribution of VeryChic's data.
|
|
37
|
+
|
|
38
|
+
## What it does
|
|
39
|
+
|
|
40
|
+
Three tools:
|
|
41
|
+
|
|
42
|
+
| Tool | Description |
|
|
43
|
+
|---|---|
|
|
44
|
+
| `verychic_list_deals` | The current VeryChic offers (limit configurable). |
|
|
45
|
+
| `verychic_search_offers` | Filter offers by `destination` (substring), `country` (exact), and/or `max_price`. |
|
|
46
|
+
| `verychic_offer_details` | An offer's content (advantages, gallery) **plus availability and prices by date**. |
|
|
47
|
+
|
|
48
|
+
All read-only, anonymous (no login), with a built-in conservative rate limit.
|
|
49
|
+
|
|
50
|
+
## Install & use (local — Claude Desktop / Claude Code)
|
|
51
|
+
|
|
52
|
+
Zero-install with [`uv`](https://docs.astral.sh/uv/). Add this to your MCP client config:
|
|
53
|
+
|
|
54
|
+
```json
|
|
55
|
+
{
|
|
56
|
+
"mcpServers": {
|
|
57
|
+
"verychic": {
|
|
58
|
+
"command": "uvx",
|
|
59
|
+
"args": ["verychic-mcp"]
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
```
|
|
64
|
+
|
|
65
|
+
That runs the server over **stdio**. No clone, no manual install.
|
|
66
|
+
|
|
67
|
+
To run it yourself:
|
|
68
|
+
|
|
69
|
+
```bash
|
|
70
|
+
uvx verychic-mcp # stdio (default)
|
|
71
|
+
uvx verychic-mcp --help # see options
|
|
72
|
+
```
|
|
73
|
+
|
|
74
|
+
## Use from Claude.ai / Cowork (remote)
|
|
75
|
+
|
|
76
|
+
Cloud clients (claude.ai web, Cowork) can only talk to **remote** MCP servers over HTTPS, so you must
|
|
77
|
+
**self-host** the server in `streamable-http` mode and add it as a *custom connector* by URL. See
|
|
78
|
+
[DEPLOY.md](DEPLOY.md) for a 1-click template. Then, in Claude settings → Connectors → Add custom
|
|
79
|
+
connector, paste your deployment URL.
|
|
80
|
+
|
|
81
|
+
> Listing in Anthropic's official connector directory (next to Booking/Tripadvisor) is **out of
|
|
82
|
+
> scope**: it requires a partner review this kind of tool would not pass.
|
|
83
|
+
|
|
84
|
+
## Tool examples
|
|
85
|
+
|
|
86
|
+
- "List the current VeryChic deals."
|
|
87
|
+
- "Search VeryChic offers in Spain under 600 €."
|
|
88
|
+
- "Get the details and dated prices for VeryChic offer ORCHESTRA 44983."
|
|
89
|
+
|
|
90
|
+
## Development
|
|
91
|
+
|
|
92
|
+
```bash
|
|
93
|
+
git clone https://github.com/jordantete/verychic-mcp.git && cd verychic-mcp
|
|
94
|
+
pip install -e ".[dev]"
|
|
95
|
+
pytest # offline tests (fixtures); excludes the @network smoke test
|
|
96
|
+
pytest -m network # optional: hits the live VeryChic API (low volume)
|
|
97
|
+
ruff check verychic_mcp tests
|
|
98
|
+
```
|
|
99
|
+
|
|
100
|
+
## How it works
|
|
101
|
+
|
|
102
|
+
VeryChic's web front-end calls a public JSON API under `https://api.verychic.com/verychic-endpoints/v1`
|
|
103
|
+
(plus `search.verychic.com`). This server replays those calls with a browser-like TLS fingerprint
|
|
104
|
+
(`curl_cffi`), parses the responses, and exposes them as MCP tools. The volatile `channelVersion`
|
|
105
|
+
parameter is auto-discovered from the live site, with a hardcoded fallback.
|
|
106
|
+
|
|
107
|
+
## License
|
|
108
|
+
|
|
109
|
+
MIT — see [LICENSE](LICENSE).
|
|
@@ -0,0 +1,85 @@
|
|
|
1
|
+
# VeryChic MCP
|
|
2
|
+
|
|
3
|
+
An **unofficial, read-only** [Model Context Protocol](https://modelcontextprotocol.io) server for
|
|
4
|
+
[VeryChic](https://www.verychic.fr) hotel flash-sale offers. Search current deals, filter them, and
|
|
5
|
+
get an offer's details with availability and prices by date — straight from your MCP client.
|
|
6
|
+
|
|
7
|
+
> ⚠️ **Disclaimer.** This project is **not affiliated with, endorsed by, or connected to VeryChic /
|
|
8
|
+
> VeryChic SAS** in any way. It is an independent, community tool for **personal use**. It accesses
|
|
9
|
+
> VeryChic's public web API the same way a browser does. You are responsible for complying with
|
|
10
|
+
> VeryChic's Terms (Conditions Générales de Vente — notably Art. 9 on intellectual property and the
|
|
11
|
+
> *sui generis* database right). Use it at your own risk, for personal, low-volume browsing only.
|
|
12
|
+
> Do not use it for bulk extraction or redistribution of VeryChic's data.
|
|
13
|
+
|
|
14
|
+
## What it does
|
|
15
|
+
|
|
16
|
+
Three tools:
|
|
17
|
+
|
|
18
|
+
| Tool | Description |
|
|
19
|
+
|---|---|
|
|
20
|
+
| `verychic_list_deals` | The current VeryChic offers (limit configurable). |
|
|
21
|
+
| `verychic_search_offers` | Filter offers by `destination` (substring), `country` (exact), and/or `max_price`. |
|
|
22
|
+
| `verychic_offer_details` | An offer's content (advantages, gallery) **plus availability and prices by date**. |
|
|
23
|
+
|
|
24
|
+
All read-only, anonymous (no login), with a built-in conservative rate limit.
|
|
25
|
+
|
|
26
|
+
## Install & use (local — Claude Desktop / Claude Code)
|
|
27
|
+
|
|
28
|
+
Zero-install with [`uv`](https://docs.astral.sh/uv/). Add this to your MCP client config:
|
|
29
|
+
|
|
30
|
+
```json
|
|
31
|
+
{
|
|
32
|
+
"mcpServers": {
|
|
33
|
+
"verychic": {
|
|
34
|
+
"command": "uvx",
|
|
35
|
+
"args": ["verychic-mcp"]
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
```
|
|
40
|
+
|
|
41
|
+
That runs the server over **stdio**. No clone, no manual install.
|
|
42
|
+
|
|
43
|
+
To run it yourself:
|
|
44
|
+
|
|
45
|
+
```bash
|
|
46
|
+
uvx verychic-mcp # stdio (default)
|
|
47
|
+
uvx verychic-mcp --help # see options
|
|
48
|
+
```
|
|
49
|
+
|
|
50
|
+
## Use from Claude.ai / Cowork (remote)
|
|
51
|
+
|
|
52
|
+
Cloud clients (claude.ai web, Cowork) can only talk to **remote** MCP servers over HTTPS, so you must
|
|
53
|
+
**self-host** the server in `streamable-http` mode and add it as a *custom connector* by URL. See
|
|
54
|
+
[DEPLOY.md](DEPLOY.md) for a 1-click template. Then, in Claude settings → Connectors → Add custom
|
|
55
|
+
connector, paste your deployment URL.
|
|
56
|
+
|
|
57
|
+
> Listing in Anthropic's official connector directory (next to Booking/Tripadvisor) is **out of
|
|
58
|
+
> scope**: it requires a partner review this kind of tool would not pass.
|
|
59
|
+
|
|
60
|
+
## Tool examples
|
|
61
|
+
|
|
62
|
+
- "List the current VeryChic deals."
|
|
63
|
+
- "Search VeryChic offers in Spain under 600 €."
|
|
64
|
+
- "Get the details and dated prices for VeryChic offer ORCHESTRA 44983."
|
|
65
|
+
|
|
66
|
+
## Development
|
|
67
|
+
|
|
68
|
+
```bash
|
|
69
|
+
git clone https://github.com/jordantete/verychic-mcp.git && cd verychic-mcp
|
|
70
|
+
pip install -e ".[dev]"
|
|
71
|
+
pytest # offline tests (fixtures); excludes the @network smoke test
|
|
72
|
+
pytest -m network # optional: hits the live VeryChic API (low volume)
|
|
73
|
+
ruff check verychic_mcp tests
|
|
74
|
+
```
|
|
75
|
+
|
|
76
|
+
## How it works
|
|
77
|
+
|
|
78
|
+
VeryChic's web front-end calls a public JSON API under `https://api.verychic.com/verychic-endpoints/v1`
|
|
79
|
+
(plus `search.verychic.com`). This server replays those calls with a browser-like TLS fingerprint
|
|
80
|
+
(`curl_cffi`), parses the responses, and exposes them as MCP tools. The volatile `channelVersion`
|
|
81
|
+
parameter is auto-discovered from the live site, with a hardcoded fallback.
|
|
82
|
+
|
|
83
|
+
## License
|
|
84
|
+
|
|
85
|
+
MIT — see [LICENSE](LICENSE).
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
[project]
|
|
2
|
+
name = "verychic-mcp"
|
|
3
|
+
version = "0.1.0"
|
|
4
|
+
description = "Unofficial read-only MCP server for VeryChic hotel offers"
|
|
5
|
+
readme = "README.md"
|
|
6
|
+
license = "MIT"
|
|
7
|
+
requires-python = ">=3.11"
|
|
8
|
+
authors = [{ name = "VeryChic MCP contributors" }]
|
|
9
|
+
keywords = ["mcp", "model-context-protocol", "verychic", "hotels", "travel"]
|
|
10
|
+
classifiers = [
|
|
11
|
+
"Programming Language :: Python :: 3",
|
|
12
|
+
"License :: OSI Approved :: MIT License",
|
|
13
|
+
"Operating System :: OS Independent",
|
|
14
|
+
"Topic :: Internet :: WWW/HTTP",
|
|
15
|
+
]
|
|
16
|
+
dependencies = ["curl_cffi>=0.7", "mcp[cli]>=1.2"]
|
|
17
|
+
|
|
18
|
+
[project.urls]
|
|
19
|
+
Homepage = "https://github.com/jordantete/verychic-mcp"
|
|
20
|
+
Repository = "https://github.com/jordantete/verychic-mcp"
|
|
21
|
+
Issues = "https://github.com/jordantete/verychic-mcp/issues"
|
|
22
|
+
|
|
23
|
+
[project.optional-dependencies]
|
|
24
|
+
dev = ["pytest>=8", "ruff>=0.6", "build>=1.2"]
|
|
25
|
+
|
|
26
|
+
[project.scripts]
|
|
27
|
+
verychic-mcp = "verychic_mcp.server:main"
|
|
28
|
+
|
|
29
|
+
[tool.pytest.ini_options]
|
|
30
|
+
markers = ["network: test nécessitant un accès réseau réel (hors CI)"]
|
|
31
|
+
addopts = "-m 'not network'"
|
|
32
|
+
|
|
33
|
+
[build-system]
|
|
34
|
+
requires = ["hatchling"]
|
|
35
|
+
build-backend = "hatchling.build"
|
|
36
|
+
|
|
37
|
+
[tool.hatch.build.targets.wheel]
|
|
38
|
+
packages = ["verychic_mcp"]
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
services:
|
|
2
|
+
- type: web
|
|
3
|
+
name: verychic-mcp
|
|
4
|
+
runtime: docker
|
|
5
|
+
plan: free
|
|
6
|
+
dockerfilePath: ./Dockerfile
|
|
7
|
+
# Pas de healthCheckPath : le serveur streamable-http sert MCP sur un sous-chemin,
|
|
8
|
+
# "/" renverrait 404. Render retombe sur un check d'ouverture du port.
|
|
9
|
+
autoDeploy: false
|
|
File without changes
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
[
|
|
2
|
+
{
|
|
3
|
+
"date": "20/06/2026",
|
|
4
|
+
"price": 169,
|
|
5
|
+
"currency": "EUR",
|
|
6
|
+
"departureCityCode": "XXX",
|
|
7
|
+
"nights": 1,
|
|
8
|
+
"days": 2
|
|
9
|
+
},
|
|
10
|
+
{
|
|
11
|
+
"date": "21/06/2026",
|
|
12
|
+
"price": 169,
|
|
13
|
+
"currency": "EUR",
|
|
14
|
+
"departureCityCode": "XXX",
|
|
15
|
+
"nights": 1,
|
|
16
|
+
"days": 2
|
|
17
|
+
},
|
|
18
|
+
{
|
|
19
|
+
"date": "22/06/2026",
|
|
20
|
+
"price": 169,
|
|
21
|
+
"currency": "EUR",
|
|
22
|
+
"departureCityCode": "XXX",
|
|
23
|
+
"nights": 1,
|
|
24
|
+
"days": 2
|
|
25
|
+
},
|
|
26
|
+
{
|
|
27
|
+
"date": "23/06/2026",
|
|
28
|
+
"price": 169,
|
|
29
|
+
"currency": "EUR",
|
|
30
|
+
"departureCityCode": "XXX",
|
|
31
|
+
"nights": 1,
|
|
32
|
+
"days": 2
|
|
33
|
+
},
|
|
34
|
+
{
|
|
35
|
+
"date": "24/06/2026",
|
|
36
|
+
"price": 169,
|
|
37
|
+
"currency": "EUR",
|
|
38
|
+
"departureCityCode": "XXX",
|
|
39
|
+
"nights": 1,
|
|
40
|
+
"days": 2
|
|
41
|
+
}
|
|
42
|
+
]
|