BBC Good Food

Pesquise receitas do BBC Good Food, leia uma e ajuste a proporção dos ingredientes. Sem chave de API.

Documentação

mcp-bbc-goodfood

npm CI license MCP Registry Glama M8ven Install in Cursor Install in VS Code

BBC Good Food é um site britânico de culinária, a versão online da revista de mesmo nome. Suas receitas são escritas e testadas pelos próprios cozinheiros do site, e cada uma traz seus ingredientes, seu modo de preparo, seus tempos de preparo e cozimento, sua dificuldade, as dietas às quais atende, suas informações nutricionais por porção e as estrelas que seus leitores atribuíram. O site filtra suas receitas segundo seus próprios eixos: uma dieta, uma culinária, um tipo de refeição, uma dificuldade. Parte do acervo fica atrás de uma assinatura.

Este servidor conecta um cliente de chat a esse site. Você pode ler os valores que cada eixo assume, buscar as receitas ao longo deles, ler uma receita com seus ingredientes reescalados para o número de pessoas à sua mesa e alternar suas quantidades entre unidades métricas e americanas. Não exige chave de API nem conta.

Versão em francês


Instalação

Instalação em um clique

Install in Cursor Install in VS Code

Claude Code

claude mcp add bbc-goodfood -- npx -y mcp-bbc-goodfood

Claude Desktop, Cursor e qualquer cliente que use o formato de configuração padrão

{
  "mcpServers": {
    "bbc-goodfood": {
      "command": "npx",
      "args": ["-y", "mcp-bbc-goodfood"]
    }
  }
}

É necessário o Node 24 ou posterior, e nenhuma variável de ambiente precisa ser definida.

Com Docker

{
  "mcpServers": {
    "bbc-goodfood": {
      "command": "docker",
      "args": ["run", "-i", "--rm", "ghcr.io/smeet666/mcp-bbc-goodfood:1.0.1"]
    }
  }
}

-i mantém o stdin aberto, que é por onde o protocolo trafega, e -t fica de fora porque um TTY reescreve o fluxo. O contêiner precisa de HTTPS de saída para www.bbcgoodfood.com, e nada mais: sem volume, sem porta, sem credencial.

Pacote, sem npm

Baixe mcp-bbc-goodfood-1.0.1.mcpb de a versão mais recente e abra-o. Um cliente que suporte 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 um curry vegetariano que leve menos de 40 minutos."
  • "Quais dietas posso usar como filtro?"
  • "Leia essa receita para seis pessoas, em xícaras americanas."
  • "Quais destas têm avaliação de quatro estrelas ou mais?"
  • "Reescala esta lista de ingredientes de uma revista por 1,5."

O caminho comum executa list_filters, depois search_recipes, depois get_recipe no caminho que uma linha carrega.

Ferramentas

FerramentaO que faz
list_filtersLê os valores que cada eixo do site assume.
search_recipesEncontra receitas, filtradas ao longo desses eixos.
get_recipeLê uma receita, reescalada ou em outras unidades, sob pedido.
scale_ingredientsReescala qualquer lista de ingredientes, sem consultar o site.

Chame list_filters antes de filtrar uma busca. O site aceita qualquer valor em um eixo e responde a um que não conhece com um total de zero, então uma grafia adivinhada volta como uma ausência confiante em vez de uma recusa.

list_filters

Lê os eixos pelos quais o site filtra e os valores que cada um assume.

ArgumentoTipoObrigatórioO que faz
querystring, de 1 a 80 caracteresnãoConta os valores dentro de uma busca em vez de em toda a listagem.

Em retorno: filters, uma entrada por eixo carregando name e label na própria redação do site, argument, que nomeia o argumento que search_recipes aceita para ele, e options com cada value, seu label e seu count. Um count para o qual o site não publicou nada é null. option_count diz quantas opções estão listadas aqui, o que é menos do que o site aceita: os valores retornados são os mais frequentes, e uma opção ausente da lista ainda é utilizável. As contagens são medidas dentro de um escopo, então passar query conta dentro de uma busca e deixá-lo de fora conta em toda a listagem; os dois respondem a perguntas diferentes.

search_recipes

Busca as receitas, filtradas ao longo dos eixos do próprio site e ao longo de restrições que este servidor aplica às linhas que leu.

ArgumentoTipoObrigatórioO que faz
querystring, de 1 a 80 caracteressimUm prato, um ingrediente, uma técnica.
limitinteiro, de 1 a 30, padrão 30nãoLinhas a servir.
pageinteiro, de 1 a 334, padrão 1nãoQual página de linhas.
sortrelevant, rating, published ou quickest, padrão relevantnãoComo o site ordena as linhas.
dietstring, de 1 a 60 caracteresnãoUm valor que list_filters publica.
cuisinestring, de 1 a 60 caracteresnãoUm valor que list_filters publica.
meal_typestring, de 1 a 60 caracteresnãoUm valor que list_filters publica.
difficultystring, de 1 a 60 caracteresnãoUm valor que list_filters publica.
max_total_minutesinteiro, de 1 a 1440nãoA receita inteira, em minutos.
max_caloriesinteiro, de 1 a 10000nãoCalorias por porção.
min_servingsinteiro, de 1 a 50nãoPelo menos este número de porções.
min_ratingnúmero, de 1 a 5nãoPelo menos este número de estrelas.
exclude_premiumbooleanonãoRemove as linhas atrás da assinatura do site.

Em retorno: linhas carregando id, que get_recipe aceita; title; url; image_url; e rating, que é null quando o site não publicou nenhum. Junto vêm result_count, rows_seen para as linhas que o site serviu antes de qualquer coisa ser posta de lado, e total_available. Um total marcado como total_is_ceiling assenta no maior número de linhas que uma busca servirá, então ele afirma um piso em vez de uma contagem. restrictions_lifted nomeia o que foi posto de lado quando o filtro fez a busca falhar, e premium_dropped conta as linhas de assinatura removidas. O site não oferece restrição sobre linhas de assinatura, então exclude_premium as remove depois que a página chega: uma página então volta mais curta do que o limite pedido, e uma página curta não é o fim dos resultados.

get_recipe

Lê uma receita, reescalada para um número de porções e no sistema de unidades pedido.

ArgumentoTipoObrigatórioO que faz
idstring, de 1 a 200 caracteressimO caminho próprio da página, como uma linha de search_recipes o carrega.
servingsinteiro, de 1 a 100nãoReescala os ingredientes para este número de porções.
unit_systemmetric ou usnãoAs unidades em que as quantidades são escritas.

Em retorno: title, url, premium, yield_text na própria redação do site, como Serves 4 - 6, yield_count, prep_minutes, cook_minutes, total_minutes, difficulty, diets, author, rating, rating_count, description, ingredients, steps, nutrition com nutrition_per nomeando a porção que descreve, e unit_system. Um valor que a página não declara é null. Uma receita atrás da assinatura do site volta com premium verdadeiro, sem ingredientes e sem passos: envie o leitor para a página dela em vez de reconstruí-los. Cada ingrediente carrega scaling, lendo scaled, rounded ou unscaled.

scale_ingredients

Aplica a mesma aritmética a qualquer lista de linhas de ingredientes, sem consultar o site.

ArgumentoTipoObrigatórioO que faz
ingredientsarray de 1 a 100 strings, de 1 a 300 caracteressimAs linhas a reescalar, como uma receita as escreve.
factornúmero, de 0,001 a 1000um de doisPor quanto multiplicar cada quantidade.
from_servingsinteiro, de 1 a 100um de doisQuantas pessoas a lista alimenta como escrita.
to_servingsinteiro, de 1 a 100um de doisQuantas pessoas ela deve alimentar.

Passe factor, ou o par from_servings e to_servings.

Em retorno: as linhas reescaladas na forma que get_recipe retorna, cada uma com seu original, seu text, seu amount, amount_max e unit, e seu scaling.

Reescalando as quantidades

Uma quantidade é declarada na unidade que lhe convém, então uma linha pode voltar em uma unidade diferente da que a receita usou: 200 g multiplicado por vinte lê-se 4 kg, e 2 g dividido por dez lê-se 200 mg.

O quão finamente um ingrediente pode ser dividido depende do que ele é. Um pão pode ser cortado em dois, em três ou em quatro; um ovo não pode ser repartido. Uma quantidade que cai entre os dois é arredondada, e a receita reescalada então se afasta um pouco das proporções da original. A linha carrega rounded, e sua nota diz o que foi feito.

Os valores são aritmética deste servidor, então diga que foram recalculados quando você os mostrar. Uma receita cuja página não declara número de porções não pode ser adaptada a um número de pessoas, e a resposta diz isso.

Configuração

Toda variável é opcional. Defina-as no bloco env da configuração do seu cliente.

VariávelPadrãoO que faz
BGF_USER_AGENTa identidade do projetoNomeia seu aplicativo para o site, com um endereço onde uma pessoa pode ser contatada.
BGF_MIN_INTERVAL_MS1500Intervalo entre duas solicitações, de 1000 a 60000.
BGF_TIMEOUT_MS20000Prazo para uma solicitação, de 1000 a 120000.
BGF_MAX_RETRIES3Tentativas após uma falha transitória, de 0 a 8.
BGF_CACHE_TTL_MS900000Quanto tempo uma página permanece na memória, de 0 a 86400000.
BGF_CACHE_MAX_ENTRIES200Páginas mantidas na memória de uma vez, de 1 a 5000.
BGF_LOG_LEVELerrorsilent, error, info ou debug, escrito em stderr.

Um valor fora do intervalo retorna ao padrão, e o motivo é escrito em stderr.

Erros

Cada falha carrega um dos seis códigos, uma mensagem e, quando ajuda, uma dica indicando o próximo passo.

CódigoO que aconteceuO que fazer
not_foundO site respondeu e não contém tal receita.Verifique o caminho com search_recipes.
invalid_inputOs argumentos foram recusados antes de qualquer solicitação ser enviada.Leia a mensagem, que nomeia o argumento.
rate_limitedO site pediu que este cliente diminuísse o ritmo.Aguarde o número de segundos que a dica indica e chame novamente com os mesmos argumentos. A receita ainda está lá.
parse_failureA página carregou e o conteúdo esperado estava ausente.Reporte em o rastreador de problemas.
network_errorA solicitação não foi concluída.Tente novamente em breve.
timeoutA solicitação passou do prazo.Aumente BGF_TIMEOUT_MS, ou peça menos linhas.

Como biblioteca

A camada que lê o site é publicada separadamente, com seu ritmo, seu cache e seus erros, e sem protocolo anexado.

import { BbcGoodFoodClient } from "mcp-bbc-goodfood/client";

const client = new BbcGoodFoodClient();
const { data, cached } = await client.searchRecipes({ query: "lasagne" });
console.log(data.rows.length, cached);

listFilters, searchRecipes e getRecipe cada um responde a { data, cached }, e lançam um erro carregando um dos seis códigos. O intervalo mínimo entre duas solicitações também se aplica aqui.

Ritmo e atribuição

As solicitações saem uma de cada vez com pelo menos um segundo e meio entre elas, e o mínimo de um segundo se mantém independentemente de como o servidor está configurado. O User-Agent sempre termina com a identidade do projeto e um endereço onde uma pessoa pode ser contatada.

Cada resultado carrega o endereço da página de onde foi lido, e source nomeia o site. As receitas pertencem ao BBC Good Food e aos cozinheiros que as escreveram.

Este servidor MCP é um projeto não oficial, sem afiliação ao BBC Good Food.

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.bbcgoodfood.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 o próprio site.

Contribuindo

Bugs, perguntas e ideias pertencem a o rastreador de problemas. Pull requests são bem-vindos; abrir um problema primeiro ajuda a concordar sobre a forma da mudança. Veja CONTRIBUTING.md.

Licença

MIT, veja LICENSE. As receitas pertencem ao BBC Good Food e aos seus autores.


mcp-bbc-goodfood (francês)

Versão em inglês

BBC Good Food é um site de culinária britânico, a casa online da revista de mesmo nome. Suas receitas são escritas e testadas por seus próprios cozinheiros, e cada uma traz seus ingredientes, seu método, seus tempos de preparo e cozimento, sua dificuldade, as dietas às quais se adequa, seus valores nutricionais por porção e as estrelas que seus leitores lhe deram. O site organiza suas receitas segundo eixos próprios: uma dieta, uma culinária, um tipo de refeição, uma dificuldade. Uma parte da coleção é reservada aos assinantes.

Este servidor conecta um cliente de conversa a este site. Pode-se ler os valores que cada eixo assume, buscar receitas ao longo desses eixos, ler uma receita com seus ingredientes adaptados ao número de convidados e alternar suas quantidades entre unidades métricas e americanas. Nenhuma chave de API, nenhuma conta.

Instalação

Instalação em um clique

Install in Cursor Install in VS Code

Claude Code

claude mcp add bbc-goodfood -- npx -y mcp-bbc-goodfood

Claude Desktop, Cursor e qualquer cliente no formato de configuração padrão

{
  "mcpServers": {
    "bbc-goodfood": {
      "command": "npx",
      "args": ["-y", "mcp-bbc-goodfood"]
    }
  }
}

Node 24 ou mais recente é necessário, e nenhuma variável de ambiente precisa ser preenchida.

Com Docker

{
  "mcpServers": {
    "bbc-goodfood": {
      "command": "docker",
      "args": ["run", "-i", "--rm", "ghcr.io/smeet666/mcp-bbc-goodfood:1.0.1"]
    }
  }
}

-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.bbcgoodfood.com, e nada mais: nenhum volume, nenhuma porta, nenhum identificador.

Bundle, sem npm

Baixe mcp-bbc-goodfood-1.0.1.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, portanto nada é baixado na instalação.

O que se pode pedir

  • « Encontre-me um curry vegetariano que leva menos de 40 minutos. »
  • « Em quais dietas posso filtrar? »
  • « Leia-me esta receita para seis, em xícaras americanas. »
  • « Quais são avaliadas com quatro estrelas ou mais? »
  • « Multiplique por 1,5 esta lista de ingredientes tirada de uma revista. »

O caminho comum vai de list_filters a search_recipes, e depois a get_recipe no caminho que uma linha carrega.

As ferramentas

FerramentaO que faz
list_filtersLê os valores que cada eixo do site assume.
search_recipesEncontra receitas, organizadas segundo esses eixos.
get_recipeLê uma receita, adaptada ou em outras unidades sob demanda.
scale_ingredientsAdapta qualquer lista de ingredientes, sem consulta ao site.

Chame list_filters antes de refinar uma busca. O site aceita qualquer valor em um eixo e responde ao que não conhece com um total de zero, portanto uma grafia adivinhada retorna como uma ausência garantida em vez de uma recusa.

list_filters

Lê os eixos segundo os quais o site organiza, e os valores que cada um assume.

ArgumentoTipoObrigatórioO que faz
querystring, 1 a 80 caracteresnãoConta os valores em uma busca em vez de em toda a lista.

Em retorno: filters, uma entrada por eixo carregando name e label nos termos do site, argument, que nomeia o argumento que search_recipes aceita para ele, e options com cada value, seu label e seu count. Um count que o site não publicou vale null. option_count diz quantas opções estão listadas aqui, o que é menos do que o site aceita: os valores retornados são os mais frequentes, e uma opção ausente da lista permanece utilizável. Os contadores são medidos em um escopo, portanto passar query conta em uma busca e omiti-lo conta em toda a lista; ambos respondem a perguntas diferentes.

search_recipes

Busca receitas, organizadas segundo os eixos do site e segundo restrições que este servidor aplica às linhas que leu.

ArgumentoTipoObrigatórioO que faz
querystring, 1 a 80 caracteressimUm prato, um ingrediente, uma técnica.
limitinteiro, 1 a 30, padrão 30nãoLinhas a servir.
pageinteiro, 1 a 334, padrão 1nãoQual página de linhas.
sortrelevant, rating, published ou quickest, padrão relevantnãoA ordem na qual o site organiza as linhas.
dietstring, 1 a 60 caracteresnãoUm valor publicado por list_filters.
cuisinestring, 1 a 60 caracteresnãoUm valor publicado por list_filters.
meal_typestring, 1 a 60 caracteresnãoUm valor publicado por list_filters.
difficultystring, 1 a 60 caracteresnãoUm valor publicado por list_filters.
max_total_minutesinteiro, 1 a 1440nãoA receita inteira, em minutos.
max_caloriesinteiro, 1 a 10000nãoCalorias por porção.
min_servingsinteiro, 1 a 50nãoPelo menos este número de porções.
min_ratingnúmero, 1 a 5nãoPelo menos este número de estrelas.
exclude_premiumbooleanonãoRemove as linhas reservadas aos assinantes.
Em retorno: linhas com id, que get_recipe retoma; title;
url; image_url; e rating, null onde o site não publicou nenhuma.
Também vêm result_count, rows_seen para as linhas servidas pelo site
antes de qualquer descarte, e total_available. Um total marcado como total_is_ceiling
se aplica ao maior número de linhas que uma busca retornará, portanto
ele indica um piso, não uma contagem. restrictions_lifted nomeia o que foi
descartado quando o ajuste fazia a busca falhar, e premium_dropped
conta as linhas de assinantes removidas. O site não oferece nenhuma restrição sobre
linhas de assinantes, então exclude_premium as remove assim que a página chega:
uma página então retorna mais curta que o limite solicitado, e uma página curta
não é o fim dos resultados.

get_recipe

Lê uma receita, adaptada a um número de porções e no sistema de unidades solicitado.

ArgumentoTipoObrigatórioO que faz
idstring, 1 a 200 caracteressimO caminho da página, como uma linha o carrega.
servingsinteiro, 1 a 100nãoAdapta os ingredientes a esse número de porções.
unit_systemmetric ou usnãoAs unidades nas quais as quantidades são escritas.

Em retorno: title, url, premium, yield_text nos termos do site como Serves 4 - 6, yield_count, prep_minutes, cook_minutes, total_minutes, difficulty, diets, author, rating, rating_count, description, ingredients, steps, nutrition com nutrition_per que nomeia a porção descrita, e unit_system. Um número que a página não indica vale null. Uma receita reservada a assinantes retorna com premium como verdadeiro, sem ingredientes e sem etapas: envie o leitor de volta à página em vez de reconstituí-los. Cada ingrediente carrega scaling, valendo scaled, rounded ou unscaled.

scale_ingredients

Aplica a mesma aritmética a qualquer lista de ingredientes, sem consulta ao site.

ArgumentoTipoObrigatórioO que faz
ingredientsarray de 1 a 100 strings, 1 a 300 caracteressimAs linhas a adaptar, como uma receita as escreve.
factornúmero, 0.001 a 1000um dos doisO fator pelo qual multiplicar cada quantidade.
from_servingsinteiro, 1 a 100um dos doisO número de porções da lista original.
to_servingsinteiro, 1 a 100um dos doisO número de porções desejado.

Passe factor, ou o par from_servings e to_servings.

Em retorno: as linhas adaptadas na forma que get_recipe retorna, cada uma com seu original, seu text, seu amount, amount_max e unit, e seu scaling.

A adaptação das quantidades

Uma quantidade é expressa na unidade que lhe convém. Após a adaptação, uma linha pode aparecer em outra unidade que não a da receita: 200 g multiplicados por vinte dão 4 kg, e 2 g divididos por dez dão 200 mg.

A fineza com que um ingrediente se divide depende de sua natureza. Um pão se divide em dois, em três ou em quatro; um ovo não se reparte. Uma quantidade que cai entre os dois é então arredondada, e a receita adaptada se afasta então um pouco das proporções da original. A linha carrega rounded, e sua nota diz o que foi feito.

Os números são a aritmética deste servidor, então diga que foram recalculados quando você os mostrar. Uma receita cuja página não indica nenhum número de porções não pode ser levada a um número de convidados, e a resposta o diz.

Configuração

Cada variável é opcional. Elas se colocam no bloco env da configuração do cliente.

VariávelPadrãoO que faz
BGF_USER_AGENTa identidade do projetoNomeia seu aplicativo junto ao site, com um endereço para contato.
BGF_MIN_INTERVAL_MS1500Intervalo entre duas requisições, de 1000 a 60000.
BGF_TIMEOUT_MS20000Tempo limite de uma requisição, de 1000 a 120000.
BGF_MAX_RETRIES3Tentativas após uma falha temporária, de 0 a 8.
BGF_CACHE_TTL_MS900000Duração durante a qual uma página permanece em memória, de 0 a 86400000.
BGF_CACHE_MAX_ENTRIES200Páginas mantidas em memória por vez, de 1 a 5000.
BGF_LOG_LEVELerrorsilent, error, info ou debug, escrito na saída de erro.

Um valor fora de sua faixa 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ódigoO que aconteceuO que fazer
not_foundO site respondeu e não tem essa receita.Verifique o caminho com search_recipes.
invalid_inputOs argumentos foram recusados antes de qualquer requisição.Leia a mensagem, que nomeia o argumento.
rate_limitedO site pede que este cliente desacelere.Aguarde os segundos indicados e chame novamente com os mesmos argumentos. A receita ainda está lá.
parse_failureA página carregou e o conteúdo esperado está ausente.Reporte em o rastreador de incidentes.
network_errorA requisição não foi concluída.Tente novamente em breve.
timeoutA requisição excedeu seu tempo limite.Aumente BGF_TIMEOUT_MS, ou peça menos linhas.

Como biblioteca

A camada que lê o site é publicada sozinha, com seu ritmo, seu cache e seus erros, sem protocolo anexado.

import { BbcGoodFoodClient } from "mcp-bbc-goodfood/client";

const client = new BbcGoodFoodClient();
const { data, cached } = await client.searchRecipes({ query: "lasagne" });
console.log(data.rows.length, cached);

listFilters, searchRecipes e getRecipe respondem cada um { data, cached }, e levantam um erro com um dos seis códigos. O piso entre duas requisições também se aplica aqui.

Ritmo e atribuição

As requisições partem uma a uma com pelo menos um segundo e meio entre elas, e o piso de um segundo se mantém independentemente da configuração. O User-Agent sempre termina com a identidade do projeto e um endereço para contato.

Cada resultado carrega o endereço da página de onde foi lido, e source nomeia o site. As receitas pertencem à BBC Good Food e aos cozinheiros que as escreveram.

Este MCP é um projeto não oficial, sem afiliação à BBC Good Food.

Privacidade

Este servidor não coleta nada sobre você e não envia nada ao seu autor. Ele roda na sua máquina, apenas junta www.bbcgoodfood.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 ajustes 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 o próprio site.

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 à BBC Good Food e a seus autores.