mcp-marmiton 0.1.0
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.
- package/LICENSE +25 -0
- package/README.md +310 -0
- package/dist/index.d.ts +1 -0
- package/dist/index.js +1334 -0
- package/dist/index.js.map +1 -0
- package/dist/marmiton/client.d.ts +122 -0
- package/dist/marmiton/client.js +631 -0
- package/dist/marmiton/client.js.map +1 -0
- package/package.json +82 -0
- package/server.json +35 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 smeet666
|
|
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.
|
|
22
|
+
|
|
23
|
+
This license covers the source code of this project only. Song lyrics retrieved
|
|
24
|
+
through this software are the property of their respective copyright holders and
|
|
25
|
+
are not covered by this license.
|
package/README.md
ADDED
|
@@ -0,0 +1,310 @@
|
|
|
1
|
+
# mcp-marmiton
|
|
2
|
+
|
|
3
|
+
[](https://www.npmjs.com/package/mcp-marmiton)
|
|
4
|
+
[](https://github.com/smeet666/mcp-marmiton/actions/workflows/ci.yml)
|
|
5
|
+
[](./LICENSE)
|
|
6
|
+
|
|
7
|
+
An [MCP](https://modelcontextprotocol.io) server for [Marmiton](https://www.marmiton.org),
|
|
8
|
+
the French recipe site. Search recipes, read their ingredients and steps, and
|
|
9
|
+
**rescale the quantities to any number of servings**. **No API key, no account, no
|
|
10
|
+
configuration.**
|
|
11
|
+
|
|
12
|
+
_(Version française plus bas / [French version below](#mcp-marmiton-français))_
|
|
13
|
+
|
|
14
|
+
---
|
|
15
|
+
|
|
16
|
+
## Quickstart
|
|
17
|
+
|
|
18
|
+
**Claude Code**
|
|
19
|
+
|
|
20
|
+
```bash
|
|
21
|
+
claude mcp add marmiton -- npx -y mcp-marmiton
|
|
22
|
+
```
|
|
23
|
+
|
|
24
|
+
**Claude Desktop, Cursor, and any client using the standard config format**
|
|
25
|
+
|
|
26
|
+
```json
|
|
27
|
+
{
|
|
28
|
+
"mcpServers": {
|
|
29
|
+
"marmiton": {
|
|
30
|
+
"command": "npx",
|
|
31
|
+
"args": ["-y", "mcp-marmiton"]
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
```
|
|
36
|
+
|
|
37
|
+
## Tools
|
|
38
|
+
|
|
39
|
+
| Tool | What it does | Key parameters |
|
|
40
|
+
| ------------------- | -------------------------------------- | ------------------------------------------------------- |
|
|
41
|
+
| `search_recipes` | Finds recipes by dish or ingredient. | `query`, `limit` |
|
|
42
|
+
| `get_recipe` | Reads one recipe, optionally rescaled. | `id`, `url`, `servings` |
|
|
43
|
+
| `scale_ingredients` | Rescales any ingredient list, offline. | `ingredients`, `factor`, `from_servings`, `to_servings` |
|
|
44
|
+
|
|
45
|
+
Search returns a Marmiton `id` for every result; `get_recipe` takes that id. That
|
|
46
|
+
is the intended chain: search, then read.
|
|
47
|
+
|
|
48
|
+
The server is **read-only**. It never posts anything to Marmiton.
|
|
49
|
+
|
|
50
|
+
### Scaling is the point
|
|
51
|
+
|
|
52
|
+
Asking a language model to divide a recipe by 1.5 tends to produce "2.4 eggs" and
|
|
53
|
+
"0.67 pinches of salt", stated with the same confidence as a correct number. This
|
|
54
|
+
server does the arithmetic itself and, more importantly, **says what it could not
|
|
55
|
+
compute**. Every ingredient comes back with a `scaling` flag:
|
|
56
|
+
|
|
57
|
+
| Flag | Meaning | Example at factor 0.667 |
|
|
58
|
+
| ---------- | ------------------------------------------------ | --------------------------------- |
|
|
59
|
+
| `scaled` | Multiplied and rounded to a readable value. | `25 cl de lait` → `17 cl de lait` |
|
|
60
|
+
| `rounded` | Multiplied, then rounded to something countable. | `3 oeufs` → `2 oeufs` |
|
|
61
|
+
| `unscaled` | Left exactly as published. | `1 pincée de sel`, `coriandre` |
|
|
62
|
+
|
|
63
|
+
Two rules are enforced. Scaling a recipe **down never asks for more** than the
|
|
64
|
+
original: half a sachet at factor 0.667 becomes a third of a sachet, never a whole
|
|
65
|
+
one. And scaling never **silently drops** an ingredient by rounding it to zero,
|
|
66
|
+
which is why small amounts come back as fractions.
|
|
67
|
+
|
|
68
|
+
`scale_ingredients` exposes the same logic **without any network request**, so it
|
|
69
|
+
also works on a recipe pasted from somewhere else.
|
|
70
|
+
|
|
71
|
+
### Other things worth knowing
|
|
72
|
+
|
|
73
|
+
**Marmiton is French.** Queries work best in French: `tarte aux pommes`,
|
|
74
|
+
`poulet curry coco`.
|
|
75
|
+
|
|
76
|
+
**One page of results.** Marmiton's robots.txt disallows paginating search
|
|
77
|
+
results, so this server does not, and there is no page parameter. Narrow the query
|
|
78
|
+
instead.
|
|
79
|
+
|
|
80
|
+
**Nutrition is not rescaled.** The figures Marmiton publishes describe the recipe
|
|
81
|
+
as written, and they are returned as such.
|
|
82
|
+
|
|
83
|
+
**Structured data, not scraping.** Everything is read from the `schema.org`
|
|
84
|
+
JSON-LD that Marmiton publishes for machines, so there are no CSS selectors to
|
|
85
|
+
break when the site is redesigned.
|
|
86
|
+
|
|
87
|
+
## Configuration
|
|
88
|
+
|
|
89
|
+
Every variable is optional. Set them in the `env` block of your MCP client config.
|
|
90
|
+
|
|
91
|
+
| Variable | Default | Purpose |
|
|
92
|
+
| ---------------------------- | -------------------------------------- | -------------------------------------------------------------- |
|
|
93
|
+
| `MARMITON_USER_AGENT` | `mcp-marmiton v<version> (<repo url>)` | User-Agent sent to Marmiton. |
|
|
94
|
+
| `MARMITON_MIN_INTERVAL_MS` | `1000` | Minimum gap between requests. Values below 500 ms are ignored. |
|
|
95
|
+
| `MARMITON_TIMEOUT_MS` | `15000` | Per-request timeout. |
|
|
96
|
+
| `MARMITON_MAX_RETRIES` | `3` | Retries on rate limiting and transient errors. |
|
|
97
|
+
| `MARMITON_CACHE_TTL_MS` | `900000` | In-memory cache lifetime (15 minutes). |
|
|
98
|
+
| `MARMITON_CACHE_MAX_ENTRIES` | `200` | In-memory cache size. |
|
|
99
|
+
| `MARMITON_LOG_LEVEL` | `error` | `silent`, `error`, `info` or `debug`. Logs go to stderr. |
|
|
100
|
+
|
|
101
|
+
## Troubleshooting
|
|
102
|
+
|
|
103
|
+
**`rate_limited` errors.** Marmiton is throttling this client. The server already
|
|
104
|
+
retries with backoff and slows itself down. Wait a moment and try again, and raise
|
|
105
|
+
`MARMITON_MIN_INTERVAL_MS` if it persists. This never means the recipe is missing.
|
|
106
|
+
|
|
107
|
+
**`parse_failure` errors.** Marmiton changed how it publishes its structured data
|
|
108
|
+
and the server could not read the response. Please
|
|
109
|
+
[open an issue](https://github.com/smeet666/mcp-marmiton/issues) with the recipe
|
|
110
|
+
you asked for. The server reports this loudly rather than pretending it found
|
|
111
|
+
nothing.
|
|
112
|
+
|
|
113
|
+
## Development
|
|
114
|
+
|
|
115
|
+
```bash
|
|
116
|
+
npm install
|
|
117
|
+
npm run build:fixtures # regenerate the HTML test fixtures
|
|
118
|
+
npm test # unit tests, no network
|
|
119
|
+
npm run typecheck
|
|
120
|
+
npm run build
|
|
121
|
+
MARMITON_LIVE=1 npm run test:live # hits the real site, excluded from CI
|
|
122
|
+
npm run inspector # explore the tools in the MCP Inspector
|
|
123
|
+
```
|
|
124
|
+
|
|
125
|
+
Fixtures are generated, not captured: they reproduce Marmiton's JSON-LD shape with
|
|
126
|
+
invented recipes, so the tests are deterministic and no Marmiton content lives in
|
|
127
|
+
this repository.
|
|
128
|
+
|
|
129
|
+
The scraping layer (`src/marmiton`, `src/recipe`) does not import the MCP SDK and
|
|
130
|
+
is published separately as `mcp-marmiton/client`, so it can be used as a plain
|
|
131
|
+
library.
|
|
132
|
+
|
|
133
|
+
## Recipes, copyright and cooking
|
|
134
|
+
|
|
135
|
+
Ingredient lists and cooking steps are facts and procedures. The descriptive prose
|
|
136
|
+
an author writes around them is their work, and this server does not return it:
|
|
137
|
+
you get what you need to cook, plus a link to the original page.
|
|
138
|
+
|
|
139
|
+
This server is a client. It reads the structured data Marmiton publishes for
|
|
140
|
+
machines, on demand, one request at a time, in response to an explicit request
|
|
141
|
+
from you or your assistant. It does not crawl the site, does not build a recipe
|
|
142
|
+
database, and writes nothing to disk. It honours Marmiton's robots.txt, including
|
|
143
|
+
the rule against paginating search results.
|
|
144
|
+
|
|
145
|
+
Every result carries the recipe title and its source URL. If you display or reuse
|
|
146
|
+
anything this server returns, keep that attribution and link back to Marmiton.
|
|
147
|
+
|
|
148
|
+
Rescaled quantities are computed, and cooking is not arithmetic: baking in
|
|
149
|
+
particular does not always scale linearly. Read them as a helpful starting point
|
|
150
|
+
and use your judgement.
|
|
151
|
+
|
|
152
|
+
This is an unofficial project, with no affiliation to or endorsement by Marmiton.
|
|
153
|
+
|
|
154
|
+
## License
|
|
155
|
+
|
|
156
|
+
MIT. See [LICENSE](./LICENSE). The license covers this source code only, not the
|
|
157
|
+
recipes retrieved through it.
|
|
158
|
+
|
|
159
|
+
---
|
|
160
|
+
|
|
161
|
+
<a name="mcp-marmiton-français"></a>
|
|
162
|
+
|
|
163
|
+
# mcp-marmiton (français)
|
|
164
|
+
|
|
165
|
+
Un serveur [MCP](https://modelcontextprotocol.io) pour [Marmiton](https://www.marmiton.org).
|
|
166
|
+
Cherchez des recettes, lisez leurs ingrédients et leurs étapes, et **adaptez les
|
|
167
|
+
quantités au nombre de convives**. **Sans clé d'API, sans compte, sans configuration.**
|
|
168
|
+
|
|
169
|
+
## Démarrage rapide
|
|
170
|
+
|
|
171
|
+
**Claude Code**
|
|
172
|
+
|
|
173
|
+
```bash
|
|
174
|
+
claude mcp add marmiton -- npx -y mcp-marmiton
|
|
175
|
+
```
|
|
176
|
+
|
|
177
|
+
**Claude Desktop, Cursor, et tout client utilisant le format standard**
|
|
178
|
+
|
|
179
|
+
```json
|
|
180
|
+
{
|
|
181
|
+
"mcpServers": {
|
|
182
|
+
"marmiton": {
|
|
183
|
+
"command": "npx",
|
|
184
|
+
"args": ["-y", "mcp-marmiton"]
|
|
185
|
+
}
|
|
186
|
+
}
|
|
187
|
+
}
|
|
188
|
+
```
|
|
189
|
+
|
|
190
|
+
## Outils
|
|
191
|
+
|
|
192
|
+
| Outil | Rôle | Paramètres principaux |
|
|
193
|
+
| ------------------- | ------------------------------------------- | ------------------------------------------------------- |
|
|
194
|
+
| `search_recipes` | Trouve des recettes par plat ou ingrédient. | `query`, `limit` |
|
|
195
|
+
| `get_recipe` | Lit une recette, avec adaptation possible. | `id`, `url`, `servings` |
|
|
196
|
+
| `scale_ingredients` | Adapte n'importe quelle liste, hors ligne. | `ingredients`, `factor`, `from_servings`, `to_servings` |
|
|
197
|
+
|
|
198
|
+
La recherche renvoie un `id` Marmiton pour chaque résultat, et `get_recipe` prend
|
|
199
|
+
cet id. C'est l'enchaînement prévu : chercher, puis lire.
|
|
200
|
+
|
|
201
|
+
Le serveur est en **lecture seule**. Il ne publie jamais rien sur Marmiton.
|
|
202
|
+
|
|
203
|
+
### L'adaptation des quantités est le cœur du sujet
|
|
204
|
+
|
|
205
|
+
Demander à un modèle de diviser une recette par 1,5 produit volontiers « 2,4 œufs »
|
|
206
|
+
et « 0,67 pincée de sel », énoncés avec le même aplomb qu'un chiffre juste. Ce
|
|
207
|
+
serveur fait le calcul lui-même et, surtout, **signale ce qu'il n'a pas pu
|
|
208
|
+
calculer**. Chaque ingrédient porte un indicateur `scaling` :
|
|
209
|
+
|
|
210
|
+
| Indicateur | Sens | Exemple au facteur 0,667 |
|
|
211
|
+
| ---------- | ------------------------------------------------- | --------------------------------- |
|
|
212
|
+
| `scaled` | Multiplié et arrondi à une valeur lisible. | `25 cl de lait` → `17 cl de lait` |
|
|
213
|
+
| `rounded` | Multiplié, puis arrondi à une valeur dénombrable. | `3 oeufs` → `2 oeufs` |
|
|
214
|
+
| `unscaled` | Laissé exactement tel que publié. | `1 pincée de sel`, `coriandre` |
|
|
215
|
+
|
|
216
|
+
Deux règles sont garanties. Réduire une recette **ne demande jamais davantage** que
|
|
217
|
+
l'originale : un demi-sachet au facteur 0,667 devient un tiers de sachet, jamais un
|
|
218
|
+
sachet entier. Et l'adaptation ne **supprime jamais** un ingrédient en l'arrondissant
|
|
219
|
+
à zéro, d'où les fractions pour les petites quantités.
|
|
220
|
+
|
|
221
|
+
`scale_ingredients` expose la même logique **sans aucune requête réseau**, ce qui
|
|
222
|
+
permet aussi d'adapter une recette venue d'ailleurs.
|
|
223
|
+
|
|
224
|
+
### Autres points utiles
|
|
225
|
+
|
|
226
|
+
**Marmiton est un site français.** Les requêtes fonctionnent mieux en français :
|
|
227
|
+
`tarte aux pommes`, `poulet curry coco`.
|
|
228
|
+
|
|
229
|
+
**Une seule page de résultats.** Le robots.txt de Marmiton interdit de paginer les
|
|
230
|
+
résultats de recherche, donc ce serveur ne le fait pas et n'expose aucun paramètre
|
|
231
|
+
de page. Affinez plutôt la requête.
|
|
232
|
+
|
|
233
|
+
**La nutrition n'est pas recalculée.** Les valeurs publiées par Marmiton décrivent
|
|
234
|
+
la recette telle quelle, et sont restituées comme telles.
|
|
235
|
+
|
|
236
|
+
**Données structurées, pas de scraping.** Tout est lu dans le JSON-LD `schema.org`
|
|
237
|
+
que Marmiton publie à destination des machines, donc aucun sélecteur CSS ne peut
|
|
238
|
+
casser lors d'une refonte du site.
|
|
239
|
+
|
|
240
|
+
## Configuration
|
|
241
|
+
|
|
242
|
+
Toutes les variables sont optionnelles, à déclarer dans le bloc `env` de votre client.
|
|
243
|
+
|
|
244
|
+
| Variable | Défaut | Rôle |
|
|
245
|
+
| ---------------------------- | ------------------------------------------ | ----------------------------------------------------------------- |
|
|
246
|
+
| `MARMITON_USER_AGENT` | `mcp-marmiton v<version> (<url du dépôt>)` | User-Agent envoyé à Marmiton. |
|
|
247
|
+
| `MARMITON_MIN_INTERVAL_MS` | `1000` | Écart minimal entre requêtes. Sous 500 ms, la valeur est ignorée. |
|
|
248
|
+
| `MARMITON_TIMEOUT_MS` | `15000` | Délai d'attente par requête. |
|
|
249
|
+
| `MARMITON_MAX_RETRIES` | `3` | Tentatives en cas de limitation ou d'erreur passagère. |
|
|
250
|
+
| `MARMITON_CACHE_TTL_MS` | `900000` | Durée de vie du cache mémoire (15 minutes). |
|
|
251
|
+
| `MARMITON_CACHE_MAX_ENTRIES` | `200` | Taille du cache mémoire. |
|
|
252
|
+
| `MARMITON_LOG_LEVEL` | `error` | `silent`, `error`, `info` ou `debug`. Logs sur stderr. |
|
|
253
|
+
|
|
254
|
+
## Dépannage
|
|
255
|
+
|
|
256
|
+
**Erreurs `rate_limited`.** Marmiton limite ce client. Le serveur réessaie déjà avec
|
|
257
|
+
backoff et ralentit tout seul. Patientez un instant, et augmentez
|
|
258
|
+
`MARMITON_MIN_INTERVAL_MS` si cela persiste. Cela ne signifie jamais que la recette
|
|
259
|
+
est absente.
|
|
260
|
+
|
|
261
|
+
**Erreurs `parse_failure`.** Marmiton a changé la façon dont il publie ses données
|
|
262
|
+
structurées et le serveur n'a pas su lire la réponse. Merci d'[ouvrir une issue](https://github.com/smeet666/mcp-marmiton/issues)
|
|
263
|
+
en indiquant la recette demandée. Le serveur signale ce cas au lieu de faire comme
|
|
264
|
+
s'il n'avait rien trouvé.
|
|
265
|
+
|
|
266
|
+
## Développement
|
|
267
|
+
|
|
268
|
+
```bash
|
|
269
|
+
npm install
|
|
270
|
+
npm run build:fixtures # régénère les fixtures HTML de test
|
|
271
|
+
npm test # tests unitaires, sans réseau
|
|
272
|
+
npm run typecheck
|
|
273
|
+
npm run build
|
|
274
|
+
MARMITON_LIVE=1 npm run test:live # touche le vrai site, exclu de la CI
|
|
275
|
+
npm run inspector # explorer les outils dans le MCP Inspector
|
|
276
|
+
```
|
|
277
|
+
|
|
278
|
+
Les fixtures sont générées, pas capturées : elles reproduisent la forme du JSON-LD
|
|
279
|
+
de Marmiton avec des recettes inventées, ce qui rend les tests déterministes et
|
|
280
|
+
évite de stocker du contenu Marmiton dans ce dépôt.
|
|
281
|
+
|
|
282
|
+
La couche d'accès (`src/marmiton`, `src/recipe`) n'importe pas le SDK MCP et est
|
|
283
|
+
publiée séparément sous `mcp-marmiton/client`, utilisable comme simple bibliothèque.
|
|
284
|
+
|
|
285
|
+
## Recettes, droits d'auteur et cuisine
|
|
286
|
+
|
|
287
|
+
Les listes d'ingrédients et les étapes de préparation sont des faits et des procédés.
|
|
288
|
+
La prose descriptive qu'un auteur rédige autour relève de sa création, et ce serveur
|
|
289
|
+
ne la renvoie pas : vous obtenez de quoi cuisiner, plus un lien vers la page d'origine.
|
|
290
|
+
|
|
291
|
+
Ce serveur est un client. Il lit les données structurées que Marmiton publie pour
|
|
292
|
+
les machines, à la demande, une requête à la fois, en réponse à une demande explicite
|
|
293
|
+
de votre part ou de celle de votre assistant. Il ne parcourt pas le site, ne constitue
|
|
294
|
+
aucune base de recettes et n'écrit rien sur le disque. Il respecte le robots.txt de
|
|
295
|
+
Marmiton, y compris l'interdiction de paginer les résultats de recherche.
|
|
296
|
+
|
|
297
|
+
Chaque résultat porte le titre de la recette et son URL source. Si vous affichez ou
|
|
298
|
+
réutilisez ce que renvoie ce serveur, conservez cette attribution et le lien vers
|
|
299
|
+
Marmiton.
|
|
300
|
+
|
|
301
|
+
Les quantités adaptées sont calculées, et la cuisine n'est pas de l'arithmétique :
|
|
302
|
+
la pâtisserie en particulier ne se met pas toujours à l'échelle linéairement.
|
|
303
|
+
Prenez-les comme un point de départ commode et gardez votre jugement.
|
|
304
|
+
|
|
305
|
+
Projet non officiel, sans affiliation à Marmiton ni approbation de sa part.
|
|
306
|
+
|
|
307
|
+
## Licence
|
|
308
|
+
|
|
309
|
+
MIT, voir [LICENSE](./LICENSE). La licence couvre uniquement le code source, pas les
|
|
310
|
+
recettes récupérées par son intermédiaire.
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
#!/usr/bin/env node
|