Recipes
Pesquise cinco sites de receitas de uma vez, em francês e inglês, e ajuste as quantidades. Sem chave de API.
Documentação
mcp-recipes
As receitas vivem em muitos sites, e cada um as escreve do seu jeito: um site de culinária francês publica em francês, com suas próprias medidas e sua própria ideia do que é uma porção, e um livro de receitas wiki em inglês, com listas de equipamentos e prosa para a qual o primeiro não tem campo. Fazer uma pergunta a um deles responde sobre um deles.
Este servidor lê seis. Três publicam em francês, Marmiton, Ptitchef e Supertoinette; dois em inglês, o Wikibooks Cookbook e o BBC Good Food; e um em espanhol, Pequerecetas. Você pode pesquisar em todos eles com uma única pergunta, ler uma receita de qualquer um deles em um único formato, colocar várias versões do mesmo prato lado a lado e redimensionar qualquer lista de ingredientes. Não precisa de chave de API nem de conta.
Instalação
Instalação com um clique
Claude Code
claude mcp add recipes -- npx -y mcp-recipes
Claude Desktop, Cursor e qualquer cliente que use o formato de configuração padrão
{
"mcpServers": {
"recipes": {
"command": "npx",
"args": ["-y", "mcp-recipes"]
}
}
}
Node 24 ou posterior é necessário, e nenhuma variável de ambiente precisa ser definida.
Com Docker
{
"mcpServers": {
"recipes": {
"command": "docker",
"args": ["run", "-i", "--rm", "ghcr.io/smeet666/mcp-recipes:4.0.0"]
}
}
}
-i mantém o stdin aberto, que é por onde o protocolo trafega, e -t é omitido
porque um TTY reescreve o fluxo. O contêiner precisa de HTTPS de saída para
www.marmiton.org, api.wikimedia.org, www.ptitchef.com,
www.bbcgoodfood.com, www.supertoinette.com e www.pequerecetas.com, e
nada mais: sem volume, sem porta, sem credencial.
Pacote, sem npm
Baixe mcp-recipes-4.0.0.mcpb de
a versão mais recente e
abra-o. Um cliente que suporta pacotes MCP o instala por conta própria, sem npm
e sem arquivo de configuração para editar. O pacote carrega suas dependências,
então nada é baixado no momento da instalação.
O que você pode perguntar
- "Encontre receitas de carbonara, de onde você puder."
- "Compare as versões francesa e inglesa desse prato."
- "Leia a segunda para oito pessoas."
- "Qual delas usa creme?"
- "Redimensione esta lista do meu caderno por 1,5."
O caminho comum vai de uma busca a uma leitura: uma linha carrega um id nomeando
sua fonte, e get_recipe a recebe.
As fontes
| Fonte | Site | Idioma |
|---|---|---|
marmiton | www.marmiton.org | Francês |
cookbook | Wikibooks Cookbook | Inglês |
ptitchef | www.ptitchef.com | Francês |
goodfood | www.bbcgoodfood.com | Inglês |
supertoinette | www.supertoinette.com | Francês |
pequerecetas | www.pequerecetas.com | Espanhol |
O id de uma linha nomeia sua fonte, então um identificador lido de uma resposta
volta para o site certo. Contagens nunca são somadas entre fontes, e uma fonte
que falhou é relatada como tendo falhado, em vez de como não tendo encontrado nada.
Cada site é lido no seu próprio ritmo: dois deles pedem três segundos entre requisições, e uma configuração publicada para todos eles só pode tornar este servidor mais paciente do que o mais lento pede.
Dois desses sites arquivam algo que não é uma receita no endereço onde uma
receita vive. O Wikibooks Cookbook mantém páginas sobre um ingrediente ao lado
das receitas que o usam, e o Pequerecetas publica artigos que reúnem receitas.
Uma busca diz isso, e get_recipe diz o que leu da página.
Ferramentas
| Ferramenta | O que faz |
|---|---|
search_recipes | Pesquisa em todas as fontes com uma única pergunta. |
get_recipe | Lê uma receita de qualquer fonte, em um único formato. |
compare_recipes | Coloca várias versões do mesmo prato lado a lado. |
scale_ingredients | Redimensiona qualquer lista de ingredientes, sem requisição a nenhum site. |
search_recipes
Pesquisa em todas as fontes com uma única pergunta.
| Argumento | Tipo | Obrigatório | O que faz |
|---|---|---|---|
query | string, 1 a 200 caracteres | sim | O prato ou o ingrediente a procurar. |
limit_per_source | inteiro, 1 a 25, padrão 5 | não | Linhas a manter de cada fonte. |
sources | array de ids de fonte | não | Perguntar apenas a estas fontes. |
fan_out | booleano, padrão true | não | Perguntar a todas as fontes em vez de parar na primeira que responder. |
Em retorno: results, linhas carregando id, que get_recipe recebe;
source e source_name dizendo qual site publicou a linha; title; url;
image_url; e um excerpt onde a fonte oferece um. per_source dá um
relatório por site com seu status, lendo answered ou failed, o count que
contribuiu, e seu reported_total junto com reported_total_means, que
diz o que esse número conta naquele site. names_the_dish diz quantas das
linhas daquele site carregam o prato no título, de count: um índice de busca responde
às palavras que recebe, então um site pode oferecer linhas e nenhuma delas ser o prato.
order diz em palavras como a lista foi construída.
get_recipe
Lê uma receita de qualquer fonte, em um único formato.
| Argumento | Tipo | Obrigatório | O que faz |
|---|---|---|---|
id | string, 1 a 500 caracteres | sim | O identificador que uma linha carrega, como marmiton:44078. Duas fontes endereçam uma receita por um número puro, então soletre um id com sua fonte. |
servings | inteiro, 1 a 500 | não | Redimensionar os ingredientes para este número de porções. |
sections | array de ingredients, steps, times, nutrition, tips, equipment, padrão ["ingredients", "steps"] | não | Quais partes retornar. |
max_steps | inteiro, 1 a 100, padrão 20 | não | Passos a servir. |
max_gathered | inteiro, 1 a 500, padrão 30 | não | Receitas e títulos a retornar de um endereço que reúne receitas. |
max_step_chars | inteiro, 80 a 4000, padrão 600 | não | Caracteres mantidos por passo. |
Em retorno: kind diz o que o endereço continha. Uma resposta recipe carrega
recipe e nenhum collection; uma resposta collection carrega collection e nenhum
recipe, e é um artigo que reúne outras receitas, com o headings do qual é
construído e o recipes para o qual aponta, cada um legível com
get_recipe.
Uma receita vem no formato no qual toda fonte é renderizada, seja qual for a que
a publicou: seu título, seu endereço, seus ingredientes com o scaling e o is_equipment de cada linha,
seus passos e as seções pedidas. Um campo que uma fonte publica e outra
não tem noção dele volta ausente, em vez de inventado. rest_minutes carrega um
tempo de descanso de uma fonte que o imprime separado, e não está em nenhum outro
tempo aqui. steps_as_one_block diz quando uma fonte publicou seu método como um bloco de
prosa em vez de passos. withheld nomeia uma parte que uma fonte mantém para seus
assinantes, que é uma parte que a página tem, em vez de uma parte que não pôde ser
lida. scaling_summary conta as linhas de quatro maneiras, e as quatro somam a
lista. Aumente max_step_chars quando um passo foi cortado no meio de uma frase.
compare_recipes
Coloca várias versões do mesmo prato lado a lado.
| Argumento | Tipo | Obrigatório | O que faz |
|---|---|---|---|
dish | string, 1 a 200 caracteres | sim | O prato a comparar. |
servings | inteiro, 1 a 500 | não | Redimensionar cada versão para este número de porções. |
sections | array de ingredients, steps, times, nutrition, tips, equipment, padrão ["ingredients"] | não | Quais partes retornar por versão. |
max_steps | inteiro, 1 a 100, padrão 10 | não | Passos a servir por versão. |
max_step_chars | inteiro, 80 a 4000, padrão 600 | não | Caracteres mantidos por passo. |
sources | array de ids de fonte | não | Comparar apenas estas fontes. |
Em retorno: versions, uma receita por fonte que respondeu, todas redimensionadas para
o mesmo número de porções para que suas quantidades possam ser lidas umas contra as outras,
e differences, o que as separa. per_source relata cada site como uma
busca faz.
scale_ingredients
Redimensiona qualquer lista de ingredientes, sem requisição a nenhum site.
| Argumento | Tipo | Obrigatório | O que faz |
|---|---|---|---|
ingredients | array de 1 a 200 linhas | sim | As linhas a serem redimensionadas. |
factor | número, até 1000 | um de dois | O multiplicador a ser aplicado. |
from_servings | inteiro, de 1 a 500 | um de dois | Para quantas porções a lista foi escrita. |
to_servings | inteiro, de 1 a 500 | um de dois | Quantas porções são desejadas. |
language | auto, fr, en ou es, padrão auto | não | Como cada linha é lida. |
Passe factor, ou o par from_servings e to_servings. auto lê cada
linha individualmente, que é o que uma lista com mais de um idioma precisa; nomear um
idioma lê cada linha dessa forma.
Em retorno: as linhas redimensionadas no formato que get_recipe retorna, cada uma com
seu scaling.
Redimensionando as quantidades
Uma quantidade é expressa na unidade que melhor se adequa, então uma linha pode voltar em uma
unidade diferente daquela usada na receita: 200 g multiplicado por vinte lê-se
4 kg.
O quão finamente um ingrediente pode ser dividido depende do que ele é. Uma baguete pode ser
cortada em dois, em três ou em quatro; um ovo não pode ser compartilhado. Uma quantidade que cai
entre os dois é arredondada, e a receita redimensionada então se afasta um pouco das
proporções do original. A linha carrega rounded, e sua nota diz o que
foi feito.
As fontes escrevem suas quantidades em seus próprios idiomas, e uma linha é lida no idioma em que foi escrita. Os números são aritmética deste servidor, então diga que foram recalculados quando você os exibir.
O que uma resposta afirma sobre as fontes
Cada resposta considera cada fonte separadamente. Um site que falhou, um que ninguém consultou e um que respondeu com nada são três coisas diferentes, e são relatados como três. Um total permanece ao lado da fonte que o publicou, com o que essa fonte conta quando o diz: um site conta uma categoria inteira, outro conta as linhas que serviu, e um terceiro não publica total algum.
Configuração
Todas as variáveis são opcionais. Defina-as no bloco env da configuração do seu cliente.
| Variável | Padrão | O que faz |
|---|---|---|
RECIPES_USER_AGENT | a identidade do projeto | Nomeia seu aplicativo para os sites, com um endereço onde uma pessoa pode ser contatada. |
RECIPES_MIN_INTERVAL_MS | 1000 | Intervalo entre duas solicitações a um site, de 500 a 60000. |
RECIPES_TIMEOUT_MS | 20000 | Prazo para uma solicitação, de 1000 a 120000. |
RECIPES_MAX_RETRIES | 3 | Tentativas após uma falha transitória, de 0 a 8. |
RECIPES_CACHE_TTL_MS | 900000 | Por quanto tempo uma resposta permanece na memória, de 0 a 86400000. |
RECIPES_CACHE_MAX_ENTRIES | 200 | Respostas mantidas na memória de uma vez, de 1 a 5000. |
RECIPES_LOG_LEVEL | error | silent, error, info ou debug, escritos em stderr. |
Um valor fora do intervalo cai para o padrão, e o motivo é escrito em stderr.
Erros
Cada falha carrega um de seis códigos, uma mensagem e, onde ajuda, uma dica nomeando o próximo passo.
| Código | O que aconteceu | O que fazer |
|---|---|---|
not_found | Uma fonte respondeu e não contém tal receita. | Verifique o identificador com search_recipes. |
invalid_input | Os argumentos foram recusados antes de qualquer solicitação sair. | Leia a mensagem, que nomeia o argumento. |
rate_limited | Uma fonte pediu que este cliente desacelerasse. | Espere, então chame novamente com os mesmos argumentos. A receita ainda está lá. |
parse_failure | Uma página carregou e o conteúdo esperado estava ausente. | Reporte em o rastreador de problemas. |
network_error | A solicitação não foi concluída. | Tente novamente em breve. |
timeout | A solicitação passou do prazo. | Aumente RECIPES_TIMEOUT_MS, ou peça menos linhas. |
Uma fonte que falhou é relatada por fonte, em vez de falhar toda a resposta, então um site silencioso nunca esconde o outro.
Como biblioteca
A camada que lê os sites é publicada separadamente, com seu ritmo, seu cache e seus erros, e sem protocolo anexado.
import { RecipesClient } from "mcp-recipes/client";
const client = new RecipesClient();
const { rows, reports } = await client.searchRecipes("carbonara", 3);
console.log(
rows.length,
reports.map((report) => report.status),
);
const { recipe } = await client.getRecipe(rows[0].id);
searchRecipes(query, limitPerSource, sources?, options?) respostas
{ rows, reports }: um relatório por fonte, dizendo se respondeu e o que
sua própria contagem mediu, para que uma fonte que falhou nunca seja lida como uma fonte que
não contém nada. getRecipe(id) responde { recipe, cached, read }, e lança um
erro carregando um dos seis códigos. client.profiles lista as fontes que a
construção registra.
O escalador é publicado separadamente em mcp-recipes/scale, e funciona offline em
qualquer lista:
import { scaleIngredients } from "mcp-recipes/scale";
scaleIngredients(["200 g de harina", "4 oeufs", "1 cup milk"], { factor: 2 });
Cada site mantém seu próprio ritmo, e os mínimos valem aqui também.
Ritmo e atribuição
Cada site é ritmado individualmente, uma solicitação por vez, com pelo menos um segundo
entre duas, e o mínimo de meio segundo vale independentemente de como o
servidor está configurado. Dois dos sites pedem mais, três segundos entre duas solicitações,
e eles conseguem: uma configuração publicada para cada fonte pode aumentar o espaçamento de um site
e nunca diminuí-lo. Perguntar a todos os sites de uma vez custa, portanto, a cada um deles uma solicitação,
nunca duas. O User-Agent sempre termina com a identidade do projeto e um endereço
onde uma pessoa pode ser contatada.
Cada linha carrega o endereço da página da própria receita e o nome do site que a publicou. As páginas do Cookbook são publicadas sob CC BY-SA 4.0, que pede que o que for construído sobre elas seja compartilhado sob a mesma licença. Marmiton, Ptitchef, BBC Good Food, Supertoinette e Pequerecetas não declaram termos em uma página de receita, e suas receitas pertencem a esses sites e aos cozinheiros que as escreveram. Silêncio não é uma concessão, então credite o site e link a página de onde você tirou uma receita.
Uma receita que a BBC Good Food mantém para seus assinantes volta sem seus ingredientes e seu método, nomeada como uma receita retida, com o endereço de sua página. Este servidor não reconstrói o que esse site escolheu vender.
Dois números que os sites publicam não são repetidos aqui. Uma dificuldade é uma palavra que cada site escreve à sua maneira, sem escala que qualquer um deles publique, então ela não se situa em nenhum eixo ao longo do qual duas versões poderiam ser comparadas. Um custo é um preço em euros em um site e uma classificação dentro de sua própria lista em outro, e um único campo que contivesse ambos os convidaria a serem comparados.
Este servidor MCP é um projeto não oficial, sem afiliação a nenhum dos sites que lê.
Privacidade
Este servidor não coleta nada sobre você e não envia nada ao seu autor. Ele roda
na sua máquina, contata www.marmiton.org, api.wikimedia.org,
www.ptitchef.com, www.bbcgoodfood.com, www.supertoinette.com e
www.pequerecetas.com e nada
mais, mantém suas respostas na memória enquanto roda,
e não grava nada em disco. PRIVACY.md declara o que uma solicitação
carrega e quais configurações alteram qualquer parte disso.
Desenvolvimento
npm install
npm run build:fixtures
npm test
npm run check
Os testes rodam contra fixtures geradas e não fazem nenhuma solicitação de rede. A suíte ao vivo,
npm run test:live, faz uma solicitação por rota e roda todas as noites contra os
próprios sites.
Contribuindo
Bugs, perguntas e ideias pertencem a o rastreador de problemas. Pull requests são bem-vindos; abrir uma issue primeiro ajuda a concordar sobre a forma da mudança. Veja CONTRIBUTING.md.
Licença
MIT, veja LICENSE. As receitas pertencem aos sites que as publicaram e aos seus autores.
mcp-recipes (francês)
As receitas vivem em muitos sites, e cada um as escreve à sua maneira: um site de culinária francês publica em francês, com suas medidas e sua ideia do que é uma porção, e um wiki de culinária em inglês, com listas de equipamentos e uma prosa para a qual o primeiro não tem nenhum campo. Fazer uma pergunta a um deles responde sobre o assunto de um deles.
Este servidor lê seis. Três publicam em francês, Marmiton, Ptitchef e Supertoinette; dois em inglês, o Cookbook dos Wikibooks e BBC Good Food; um em espanhol, Pequerecetas. Pode-se pesquisar nos seis com uma única pergunta, ler uma receita de qualquer um deles sob uma única forma, colocar várias versões do mesmo prato lado a lado, e adaptar qualquer lista de ingredientes. Nenhuma chave de API, nenhuma conta.
Instalação
Instalação em um clique
Claude Code
claude mcp add recipes -- npx -y mcp-recipes
Claude Desktop, Cursor, e qualquer cliente no formato de configuração padrão
{
"mcpServers": {
"recipes": {
"command": "npx",
"args": ["-y", "mcp-recipes"]
}
}
}
Node 24 ou mais recente é necessário, e nenhuma variável de ambiente precisa ser preenchida.
Com Docker
{
"mcpServers": {
"recipes": {
"command": "docker",
"args": ["run", "-i", "--rm", "ghcr.io/smeet666/mcp-recipes:4.0.0"]
}
}
}
-i mantém a entrada padrão aberta, que é o canal do protocolo, e -t é
omitido porque um TTY reescreve o fluxo. O contêiner precisa de acesso HTTPS
de saída para www.marmiton.org, api.wikimedia.org, www.ptitchef.com,
www.bbcgoodfood.com, www.supertoinette.com e www.pequerecetas.com, e de
nada mais: nenhum volume, nenhuma porta, nenhum identificador.
Bundle, sem npm
Baixe mcp-recipes-4.0.0.mcpb de
a última publicação
e abra-o. Um cliente que gerencia bundles MCP o instala sozinho, sem npm e
sem arquivo de configuração para modificar. O bundle carrega suas dependências, então
nada é baixado na instalação.
O que se pode pedir
- « Encontre-me receitas de carbonara, de onde você puder. »
- « Compare as versões francesa e inglesa deste prato. »
- « Leia-me a segunda para oito pessoas. »
- « Qual delas usa creme? »
- « Multiplique por 1,5 esta lista do meu caderno. »
O caminho comum vai de uma pesquisa a uma leitura: uma linha carrega um id
que nomeia sua fonte, e get_recipe o retoma.
As fontes
| Fonte | Site | Idioma |
|---|---|---|
marmiton | www.marmiton.org | francês |
cookbook | Cookbook Wikibooks | inglês |
ptitchef | www.ptitchef.com | francês |
goodfood | www.bbcgoodfood.com | inglês |
supertoinette | www.supertoinette.com | francês |
pequerecetas | www.pequerecetas.com | espanhol |
A linha id de uma busca nomeia sua fonte, portanto um identificador lido em uma resposta | ||
| retorna ao site correto. **As contagens nunca são somadas entre | ||
| fontes**, e uma fonte que falhou é relatada como tendo falhado, em vez de | ||
| como não tendo encontrado nada. |
Cada site é lido no seu próprio ritmo: dois deles exigem três segundos entre duas requisições, e uma configuração definida para todos só pode tornar este servidor mais paciente do que o mais lento exige.
Dois desses sites guardam outra coisa além de uma receita no endereço onde vive uma
receita. O Cookbook dos Wikibooks mantém páginas sobre um ingrediente ao lado das
receitas que o utilizam, e o Pequerecetas publica artigos que reúnem
receitas. Uma busca informa isso, e get_recipe informa o que leu na
página.
As ferramentas
| Ferramenta | O que faz |
|---|---|
search_recipes | Busca em todas as fontes com uma única pergunta. |
get_recipe | Lê uma receita de qualquer fonte, em um único formato. |
compare_recipes | Coloca várias versões do mesmo prato lado a lado. |
scale_ingredients | Adapta qualquer lista de ingredientes, sem requisição. |
search_recipes
Busca em todas as fontes com uma única pergunta.
| Argumento | Tipo | Obrigatório | O que faz |
|---|---|---|---|
query | texto, 1 a 200 caracteres | sim | O prato ou ingrediente procurado. |
limit_per_source | inteiro, 1 a 25, padrão 5 | não | Linhas a manter de cada fonte. |
sources | lista de identificadores de fonte | não | Consultar apenas essas fontes. |
fan_out | booleano, padrão true | não | Consultar cada fonte em vez de parar na primeira que responder. |
Em retorno: results, linhas com id, que get_recipe retoma;
source e source_name que indicam qual site publicou a linha; title;
url; image_url; e um excerpt onde a fonte oferecer um.
per_source fornece um relatório por site com seu status, valendo answered ou
failed, o count que forneceu, e seu reported_total acompanhado de
reported_total_means, que indica o que esse número conta naquele site.
names_the_dish indica quantas das linhas daquele site trazem o prato no
título, em count: um índice de busca responde às palavras que lhe são dadas, portanto
um site pode retornar linhas das quais nenhuma é o prato. order descreve em palavras
como a lista foi construída.
get_recipe
Lê uma receita de qualquer fonte, em um único formato.
| Argumento | Tipo | Obrigatório | O que faz |
|---|---|---|---|
id | texto, 1 a 500 caracteres | sim | O identificador de uma linha, como marmiton:44078. Duas fontes endereçam uma receita por um número puro: escreva o id com sua fonte. |
servings | inteiro, 1 a 500 | não | Adapta os ingredientes a esse número de porções. |
sections | lista de ingredients, steps, times, nutrition, tips, equipment, padrão ["ingredients", "steps"] | não | As partes a retornar. |
max_gathered | inteiro, 1 a 500, padrão 30 | não | Receitas e subtítulos retornados para um endereço que reúne receitas. |
max_steps | inteiro, 1 a 100, padrão 20 | não | Etapas a servir. |
max_step_chars | inteiro, 80 a 4000, padrão 600 | não | Caracteres mantidos por etapa. |
Em retorno: kind indica o que o endereço continha. Uma resposta recipe traz
recipe e não collection; uma resposta collection traz collection e
não recipe, e é um artigo que reúne outras receitas, com os
headings dos quais é composto e os recipes para os quais aponta, cada um
legível por get_recipe.
Uma receita vem no formato em que todas as fontes são retornadas, independentemente
de qual a publicou: seu título, seu endereço, seus ingredientes com o
scaling e a is_equipment de cada linha, suas etapas, e as partes
solicitadas. Um campo que uma
fonte publica e do qual outra não tem a noção retorna ausente, em vez de
inventado. rest_minutes traz o tempo de descanso de uma fonte que o imprime à
parte, e ele não entra em nenhum outro tempo retornado aqui. steps_as_one_block indica
quando uma fonte publicou seu método em um único bloco de prosa, em vez de em etapas.
scaling_summary conta as linhas de quatro maneiras, e as quatro totalizam a
lista. withheld nomeia a parte que uma fonte reserva aos seus assinantes, que é uma
parte que a página contém e não uma parte ilegível. Aumente max_step_chars
quando uma etapa foi cortada no meio de uma frase.
compare_recipes
Coloca várias versões do mesmo prato lado a lado.
| Argumento | Tipo | Obrigatório | O que faz |
|---|---|---|---|
dish | texto, 1 a 200 caracteres | sim | O prato a comparar. |
servings | inteiro, 1 a 500 | não | Adapta cada versão a esse número de porções. |
sections | lista de ingredients, steps, times, nutrition, tips, equipment, padrão ["ingredients"] | não | As partes a retornar por versão. |
max_steps | inteiro, 1 a 100, padrão 10 | não | Etapas a servir por versão. |
max_step_chars | inteiro, 80 a 4000, padrão 600 | não | Caracteres mantidos por etapa. |
sources | lista de ids de fonte | não | Comparar apenas essas fontes. |
Em retorno: versions, uma receita por fonte que respondeu, todas adaptadas
ao mesmo número de porções para que suas quantidades se leiam uma contra a outra,
e differences, o que as separa. per_source relata cada site como o
faz uma busca.
scale_ingredients
Adapta qualquer lista de ingredientes, sem requisição a nenhum site.
| Argumento | Tipo | Obrigatório | O que faz |
|---|---|---|---|
ingredients | lista de 1 a 200 linhas | sim | As linhas a adaptar. |
factor | número, até 1000 | um dos dois | O multiplicador a aplicar. |
from_servings | inteiro, 1 a 500 | um dos dois | O número de porções da lista original. |
to_servings | inteiro, 1 a 500 | um dos dois | O número de porções desejado. |
language | auto, fr, en ou es, padrão auto | não | Como cada linha é lida. |
Passe factor, ou o par from_servings e to_servings. auto lê cada
linha por si mesma, o que é necessário para uma lista com vários idiomas;
nomear um idioma lê todas as linhas dessa forma.
Em retorno: as linhas adaptadas no formato que get_recipe retorna, cada uma
com seu scaling e seu is_equipment, verdadeiro para uma linha que nomeia uma ferramenta
e que é deixada como está. scaled_count, rounded_count, unscaled_count
e equipment_count totalizam as linhas enviadas.
A adaptação das quantidades
Uma quantidade é expressa na unidade que lhe convém. Após a adaptação, uma
linha pode, portanto, aparecer em outra unidade que não a da receita: 200 g
multiplicados por vinte resultam em 4 kg.
A fineza com que um ingrediente se corta depende de sua natureza. Uma baguete se
corta em dois, em três ou em quatro; um ovo não se divide. Uma quantidade
que cai entre os dois é, portanto, arredondada, e a receita adaptada se desvia então
um pouco das proporções da original. A linha traz rounded, e sua nota informa
o que foi feito.
As fontes escrevem suas quantidades em seu próprio idioma, e uma linha é lida no idioma em que foi escrita. Os números são a aritmética deste servidor, portanto diga que foram recalculados quando os mostrar.
O que uma resposta informa sobre as fontes
Cada resposta presta contas de cada fonte separadamente. Um site que falhou, um que ninguém consultou e um que respondeu vazio são três coisas diferentes, e são relatados como três. Um total permanece ao lado da fonte que o publicou, com o que essa fonte conta ao informá-lo: um conta uma categoria inteira, outro conta as linhas que serviu, e um terceiro não publica nenhum total.
Configuração
Cada variável é opcional. Elas são definidas no bloco env da
configuração do cliente.
| Variável | Padrão | O que ela faz |
|---|---|---|
RECIPES_USER_AGENT | a identidade do projeto | Nomeia seu aplicativo junto aos sites, com um endereço para contatar uma pessoa. |
RECIPES_MIN_INTERVAL_MS | 1000 | Intervalo entre duas requisições ao mesmo site, de 500 a 60000. |
RECIPES_TIMEOUT_MS | 20000 | Tempo limite de uma requisição, de 1000 a 120000. |
RECIPES_MAX_RETRIES | 3 | Tentativas após uma falha temporária, de 0 a 8. |
RECIPES_CACHE_TTL_MS | 900000 | Duração durante a qual uma resposta permanece em memória, de 0 a 86400000. |
RECIPES_CACHE_MAX_ENTRIES | 200 | Respostas mantidas em memória por vez, de 1 a 5000. |
RECIPES_LOG_LEVEL | error | silent, error, info ou debug, escrito na saída de erro. |
Um valor fora do intervalo cai no padrão, e o motivo é escrito na saída de erro.
Erros
Cada falha carrega um dos seis códigos, uma mensagem e, quando ajuda, uma indicação do próximo passo.
| Código | O que aconteceu | O que fazer |
|---|---|---|
not_found | Uma fonte respondeu e não tem essa receita. | Verifique o identificador com search_recipes. |
invalid_input | Os argumentos foram recusados antes de qualquer requisição. | Leia a mensagem, que nomeia o argumento. |
rate_limited | Uma fonte pede que este cliente desacelere. | Aguarde e chame novamente com os mesmos argumentos. A receita ainda está lá. |
parse_failure | Uma página carregou e o conteúdo esperado está ausente. | Reporte em o rastreador de incidentes. |
network_error | A requisição não foi concluída. | Tente novamente em breve. |
timeout | A requisição excedeu o tempo limite. | Aumente RECIPES_TIMEOUT_MS, ou peça menos linhas. |
Uma fonte que falha é reportada fonte por fonte, em vez de fazer toda a resposta falhar, então um site silencioso nunca esconde outro.
Como biblioteca
A camada que lê os sites é publicada sozinha, com seu ritmo, seu cache e seus erros, sem protocolo anexado.
import { RecipesClient } from "mcp-recipes/client";
const client = new RecipesClient();
const { rows, reports } = await client.searchRecipes("carbonara", 3);
console.log(
rows.length,
reports.map((report) => report.status),
);
const { recipe } = await client.getRecipe(rows[0].id);
searchRecipes(query, limitPerSource, sources?, options?) responde
{ rows, reports }: um relatório por fonte, dizendo se ela respondeu e o que sua própria conta mede, para que uma fonte em falha nunca seja lida como uma fonte que não possui nada. getRecipe(id) responde { recipe, cached, read }, e
levanta um erro com um dos seis códigos. client.profiles enumera as fontes
que esta construção registra.
A escalabilidade é publicada separadamente, sob mcp-recipes/scale, e trabalha
offline em qualquer lista:
import { scaleIngredients } from "mcp-recipes/scale";
scaleIngredients(["200 g de harina", "4 oeufs", "1 cup milk"], { factor: 2 });
Cada site mantém seu próprio ritmo, e os mínimos também valem aqui.
Ritmo e atribuição
Cada site é ritmado por si mesmo, uma requisição por vez com pelo menos um
segundo entre duas, e o mínimo de meio segundo vale independentemente da
configuração. Dois dos sites pedem mais, três segundos entre duas
requisições, e eles conseguem: uma configuração definida para todas as fontes pode
ampliar o intervalo de um site, nunca reduzi-lo. Consultar todos ao mesmo tempo custa, portanto, uma requisição a cada um,
nunca duas. O User-Agent sempre termina com a identidade do projeto e um
endereço para contatar uma pessoa.
Cada linha carrega o endereço da página da receita e o nome do site que a publicou. As páginas do Cookbook são publicadas sob CC BY-SA 4.0, que exige que o que se constrói sobre elas seja compartilhado sob a mesma licença. Marmiton, Ptitchef, BBC Good Food, Supertoinette e Pequerecetas não declaram nenhuma condição sobre uma página de receita, e suas receitas pertencem a esses sites e aos cozinheiros que as escreveram. O silêncio não é uma autorização: credite o site e linke a página de onde vem a receita.
Uma receita que a BBC Good Food reserva aos seus assinantes retorna sem seus ingredientes nem seu método, nomeada como uma receita retida, com o endereço de sua página. Este servidor não reconstrói o que esse site escolheu vender.
Dois números que os sites publicam não são reproduzidos aqui. Uma dificuldade é uma palavra que cada site escreve à sua maneira, sem nenhuma escala publicada: ela não se assenta em nenhum eixo ao longo do qual duas versões se comparariam. Um custo é um preço em euros em um site e uma posição em sua própria lista em outro, e um único campo carregando ambos convidaria a compará-los.
Este MCP é um projeto não oficial, sem afiliação a nenhum dos sites que ele lê.
Privacidade
Este servidor não coleta nada sobre você e não envia nada ao seu autor. Ele roda na
sua máquina, junta apenas www.marmiton.org, api.wikimedia.org,
www.ptitchef.com, www.bbcgoodfood.com, www.supertoinette.com e
www.pequerecetas.com, mantém suas respostas em memória enquanto roda, e
não escreve nada no disco. PRIVACY.md diz o que uma requisição
carrega e quais configurações mudam isso.
Desenvolvimento
npm install
npm run build:fixtures
npm test
npm run check
Os testes são executados em fixtures geradas e não emitem nenhuma requisição.
A suíte ao vivo, npm run test:live, emite uma requisição por rota e roda
todas as noites contra os próprios sites.
Contribuindo
Anomalias, perguntas e ideias têm seu lugar em o rastreador de incidentes. As propostas de modificação são bem-vindas; abrir um ticket primeiro ajuda a concordar sobre a forma da mudança. Veja CONTRIBUTING.md.
Licença
MIT, veja LICENSE. As receitas pertencem aos sites que as publicaram e aos seus autores.