mcp-ptitchef
mcp-ptitchef
Ptitchef의 레시피를 읽는 MCP 서버입니다. 읽기 전용이며, API 키도 계정도 필요 없습니다.
존재 이유
Ptitchef는 재료군(ingredient family) 트리로 레시피를 탐색하며, 각 카테고리의 주소를 자유롭게 씁니다. 같은 종류의 것이 한 줄에서는 chou-kale로, 다음 줄에서는 recette-de-petits-pois로, 또 다른 줄에서는 recettes-aux-feves로 나타납니다. 재료 이름에서 주소를 유도하는 규칙은 없습니다.
따라서 손으로 만든 주소는 빗나가며, 사이트는 빗나간 요청에 HTTP 200과 루트 자신의 카테고리들을 보내며 독자를 트리 루트로 안내합니다. 슬러그를 추측한 모델은 요청한 적 없는 단계에 대해 완전하고 자신만만한 답변을 받게 됩니다.
이 서버는 트리를 공개하므로, 카테고리는 사이트가 붙인 이름으로 열립니다.
Related MCP server: France BOAMP MCP
도구
list_categories
레시피를 탐색하는 데 쓰이는 카테고리를 나열합니다. 인수 없이 호출하면 재료군(family)을 반환하며, 이전 호출에서 얻은 family 슬러그를 넘기면 그 안에 든 항목을 나열합니다.
인수 | 타입 | 의미 |
| string, optional | 이전 호출에서 얻은, 열어볼 family의 슬러그. 생략하면 루트를 읽습니다. |
| integer, optional | 렌더링할 항목 수. 기본 50, 최대 200. |
{
"family": null,
"family_title": "Recettes de cuisine sur Ptitchef",
"categories": [
{
"slug": "legume",
"title": "Légume",
"url": "https://www.ptitchef.com/recettes/cat/legume",
"description": null,
"sample_children": [
{
"slug": "pois-mange-tout",
"title": "Pois mange-tout",
"url": "https://www.ptitchef.com/recettes/pois-mange-tout"
}
],
"is_family": true
}
],
"category_count": 15,
"categories_published": 15,
"url": "https://www.ptitchef.com/recettes",
"source": "Ptitchef",
"notes": ["…"]
}search_recipes
요리 또는 재료로 검색합니다. 사이트는 두 가지 방식 중 하나로 응답하며, kind가 어느 쪽인지 알려줍니다.
인수 | 타입 | 의미 |
| string | 프랑스어로 된 요리 또는 재료. |
| integer, optional | 렌더링할 행 수. 기본 20, 최대 100. |
puree de patate douce를 검색하면 kind: "topic"과 topic_slug: "puree-de-patates-douces"로 응답이 옵니다. 사이트가 그에 대한 페이지를 갖고 있어 검색을 그쪽으로 보냈고, 합계는 그 페이지가 담은 수를 셉니다. soupe froide concombre menthe를 검색하면 kind: "free_text"로 응답이 옵니다. 사이트에는 그런 페이지가 없어 자체 방식대로 응답했고, 합계는 서비스된 행 수입니다.
browse_recipes
카테고리를 페이지 단위로 읽거나, 사이트가 상시 유지하는 세 목록 중 하나를 읽습니다.
인수 | 타입 | 의미 |
| string, optional |
|
|
| 사이트의 상시 목록 중 하나. |
| integer, optional | 읽을 카테고리의 페이지. |
| integer, optional | 렌더링할 행 수. 기본 20. |
search_by_ingredients
사이트 자체의 냉장고 검색을 읽습니다. 재료 하나에서 다섯 개를 넣으면, 그 재료를 담은 레시피가 나옵니다.
인수 | 타입 | 의미 |
| string[] | 프랑스어로 된 재료 하나에서 다섯 개. |
| integer, optional | 렌더링할 행 수. 기본 20. |
get_recipe
레시피 하나를 읽고, 요청 시 재료의 분량을 다시 조정합니다.
인수 | 타입 | 의미 |
| string | 검색 또는 목록에서 얻은 행의 |
| integer, optional | 이 인분 수에 맞게 재료 분량을 다시 조정합니다. |
모든 줄에는 연산이 무엇을 했는지 알려주는 scaling이 붙습니다. scaled는 정확하고, rounded는 사용 가능하도록 조정된 것이며, unscaled는 곱할 수 있는 것이 없는 경우입니다. 1 oeuf를 두 배로 하면 2 oeufs가 되고, 절반으로 하면 rounded로 표시된 1 oeuf가 됩니다. 달걀 반 개는 주방에서 계량하는 양이 아니기 때문입니다.
scale_ingredients
동일한 연산을 오프라인에서, 출처를 막론한 프랑스어 재료 목록에 적용합니다.
인수 | 타입 | 의미 |
| string[] | 다시 조정할 줄들. |
| number | 적용할 배수. |
| numbers | 배수를 읽어낼 쌍. |
get_recipe_translations
레시피가 게시된 다른 언어들을 나열합니다. Ptitchef는 같은 레시피를 게시하는 사이트 네트워크의 프랑스어 판이며, 각 페이지는 대응 사이트들을 이름으로 밝힙니다. 그 수가 몇 개인지는 레시피마다 다릅니다. 최근 레시피는 스무 개 이상을 밝히고, 오래된 레시피는 하나도 밝히지 않으며, 답변은 여기서 고정된 숫자 대신 페이지가 담고 있는 내용을 진술합니다.
답변이 과장하기를 거부하는 것들
사이트가 대신 응답한 단계는 요청된 단계가 아닙니다. 알 수 없는 family는 HTTP 200과 트리 루트로 응답되므로, 답변이 돌아온 주소가 어느 단계인지를 결정합니다. 보유하지 않은 family는 사이트가 대신 제공한 카테고리들로 렌더링되지 않고 not_found로 보고됩니다.
family 옆의 항목들은 발췌입니다. 루트는 그중 세 개를 보여주고, 이어서 사이트가 직접 출력하는 줄임표가 따라옵니다. 이 항목들은 sample_children 아래로 반환되며, 그것이 무엇인지 주석이 말해줍니다. 그것들을 family의 내용물로 렌더링하면 아흔 개짜리 family를 세 개짜리로 제공하게 되기 때문입니다.
두 개의 개수, 두 가지 질문에 답하기 때문입니다. categories_published는 페이지가 나열한 것이고 category_count는 답변이 렌더링한 것입니다. limit이 목록을 잘라낼 때마다 둘은 달라지며, 주석은 상한이 적용된 목록이 완전한 목록으로 읽히지 않도록 얼마나 잘렸는지를 말해줍니다.
주소가 없는 항목은 렌더링되지 않고 따로 분류됩니다. 사이트가 링크 없이 게시한 제목은 돌려줄 슬러그가 없으므로, 버려지고, 개수에 포함되며, 주석에서 이름이 언급됩니다.
페이지가 담고 있지 않은 소개문은 빈 문자열이 아니라 null입니다. 빈 설명은 게시된 적 없는 문구를 제공하는 셈이 됩니다.
목록에는 서로 다른 것을 세는 두 합계가 있으며, 답변은 어느 쪽이 도착했는지 말해줍니다. 사이트가 카테고리 페이지로 보내는 검색은 그 카테고리의 합계를 보고하고, 사이트가 직접 응답하는 검색은 서비스한 행 수를 보고합니다. 둘을 더하면 페이지에 카탈로그를 얹는 꼴이 됩니다.
평점은 사이트가 계산한 수치입니다. 어떤 행은 페이로드에 3.8이라고 명시하고 별 네 개를 그립니다. 그려진 수치는 그대로 둡니다.
마지막 페이지를 지난 페이지는 사이트가 서비스한 페이지로 돌아옵니다. 사이트는 첫 페이지로 응답하므로, 요청된 번호를 보고하면 호출자가 같은 행들을 영원히 맴돌게 됩니다.
냉장고 검색은 서비스하는 것보다 훨씬 많은 수를 셉니다. 재료 세 개로 레시피 여든아홉 개를 찾아내고, 그중 스물네 개를 한 페이지에 제공하며, 다른 페이지 링크는 없습니다. 답변은 두 수치를 모두 진술하고 나머지는 읽을 수 없다고 말합니다.
가이드는 목록이 아니며, 답변은 어느 쪽이 도착했는지 말해줍니다. 일부 토픽은 사이트가 작성한 가이드로 서비스됩니다. 사이트 자체의 제목 아래에 레시피를 묶어 놓은 것으로, 합계가 없고 행에는 이름과 주소만 담깁니다. 그 경우 kind는 guide라고 말하며, 같은 슬러그에 browse_recipes를 호출하면 합계와 함께 토픽의 전체 목록을 읽습니다. épinards는 32개의 가이드로 돌아오고, 그 목록은 736개를 담고 있습니다.
다른 레시피가 대신 서비스되면 부재로 렌더링됩니다. 레시피 주소의 단어들은 장식일 뿐이고 숫자는 장식이 아닙니다. 사이트가 보유하지 않은 숫자를 요청하면 관련 없는 레시피가 HTTP 200과 전체 상세 정보로 돌아옵니다. 돌아온 숫자는 요청된 숫자와 비교됩니다.
어떤 것도 맹목적으로 곱해지지 않습니다. 셀 수 있는 것은 요리사가 하나에서 꺼내는 가장 작은 몫에 도달합니다. 절반을 계량할 수 없는 것은 통째로, 예를 들어 달걀. 절반이 부어지거나 나뉘는 것은 절반으로, 예를 들어 봉지. 질량은 반올림 전에 더 작은 단위로 이동하므로 1 미만의 양이 0으로 반올림되지 않습니다. 꼬집은 고유한 표현을 유지한 채 개수만 곱해집니다. 하나의 크기는 요리사의 몫이기 때문입니다.
재조정 없이 돌려받은 목록은 줄마다가 아니라 한 번에 그렇게 말합니다. 인분 수를 요청하지 않으면 연산이 없으며, 모든 줄을 unscaled로 표시하면 그중 어느 것에도 곱할 것이 없다고 주장하는 셈이 됩니다.
사이트가 추산한 비용은 다시 계산되지 않고 그대로 전달됩니다. 그것은 사이트 자체의 수치이며, 사이트 독자들은 너무 낮다고 이의를 제기합니다. 답변은 조용히 넘기거나 조용히 버리지 않고 그 사실을 말해줍니다.
설치
npx mcp-ptitchefClaude Code
claude mcp add ptitchef -- npx -y mcp-ptitchef모든 MCP 클라이언트
{
"mcpServers": {
"ptitchef": {
"command": "npx",
"args": ["-y", "mcp-ptitchef"]
}
}
}컨테이너
docker build -t mcp-ptitchef .
docker run -i --rm mcp-ptitchef컨테이너는 www.ptitchef.com에만 도달할 수 있으면 되고 그 외에는 아무것도 필요하지 않습니다. 자격 증명을 받지 않습니다. 받을 자격 증명이 없기 때문입니다.
설정
모든 설정은 환경 변수이며, 필수인 것은 없습니다. 범위를 벗어난 값은 stderr에 한 줄을 출력하고 거부되며 기본값이 유지됩니다. 적용될 수 없는 설정은 조용히 잘려나가지 않고 그 사실을 말해줍니다.
변수 | 기본값 | 범위 |
| — | 본인을 식별하는 값. 이 프로젝트의 것은 뒤에 계속 붙어 있어, 사이트가 사람에게 닿을 수 있습니다. |
| 1500 | 1000~60000 |
| 20000 | 1000~120000 |
| 3 | 0~8 |
| 900000 | 0~86400000, 0이면 저장을 끕니다 |
| 200 | 1~5000 |
| 8000000 | 100000~64000000. 이를 넘으면 페이지는 통째로 보관되지 않고 버려집니다 |
| 60000 | 5000~600000. 한 번 읽기의 전체, 재시도와 대기 시간을 포함합니다 |
|
|
|
페이싱 하한선은 외부에서 낮출 수 없습니다. 이 사이트는 무료로 읽을 수 있고 크롤 지연을 공개하지 않으며, 이는 빠르게 해도 된다는 면허가 아니라 조심해야 할 이유입니다.
라이브러리로 사용하기
읽기 계층은 자체 페이싱, 저장소, 오류 용어를 갖추고 프로토콜 없이 단독으로 공개됩니다:
import { PtitchefClient } from "mcp-ptitchef/client";오류
코드는 여섯 개이며 그 이상은 없습니다. 호출자는 메시지를 여는 코드로 분기합니다.
코드 | 의미 |
| 해당 주소에 사이트가 가진 것이 없다 |
| 인자들로 요청을 만들어낼 수 없었다 |
| 사이트가 이 클라이언트에게 속도를 늦추라고 요청했다. 무엇이 일치했는지에 대해서는 아무것도 말하지 않는다 |
| 이 서버가 읽을 수 없는 형태로 답변이 도착했다 |
| 요청을 완료할 수 없었다 |
| 마감 시간 안에 답변이 도착하지 않았다 |
출처 표기
레시피, 제목, 카테고리는 Ptitchef에 속한다. 모든 답변은 출처를 담고 있으며, 독자에게 보여지는 목록은 사이트를 밝히고 페이지에 링크해야 한다.
기여하기
CONTRIBUTING.md를 보라. 테스트가 우선이고, 커버리지는 100%가 하한이며, 모든 것이 따르는 규칙은 서버가 데이터가 담고 있지 않은 어떤 것도 말하지 않는다는 것이다.
MIT에 따라 사용 허가된다.
mcp-ptitchef (프랑스어)
Ptitchef의 레시피를 읽는 MCP 서버. 읽기 전용이며, API 키도 계정도 없다.
존재 이유
Ptitchef는 재료군 트리로 레시피를 탐색하며, 각 카테고리의 주소를 자유롭게 쓴다. 같은 종류의 것이 한 줄에서는 chou-kale, 다음 줄에서는 recette-de-petits-pois, 세 번째 줄에서는 recettes-aux-feves라고 불린다. 어떤 규칙도 재료 이름에서 하나를 추론할 수 있게 해주지 않는다.
그래서 손으로 만든 주소는 빗나가고, 사이트는 HTTP 200으로 트리 루트의 카테고리들을 담아 독자를 루트로 되돌려 보내는 식으로 빗나간 응답을 한다. slug를 추측한 모델은 요청한 적 없는 수준에 대해 완전하고 확신에 찬 응답을 받는다.
이 서버는 트리를 공개해서, 카테고리가 사이트가 붙인 이름으로 열리게 한다.
도구들
list_categories
레시피를 탐색하는 데 쓰는 카테고리들을 나열한다. 인자 없이 호출하면 재료군들을 돌려주고, 어떤 군의 slug를 다시 넘기면 그 군이 담고 있는 것을 돌려준다.
인자 | 유형 | 의미 |
| 문자열, 선택 사항 | 열어볼 군의 slug. 이전 호출에서 얻은 값. 없으면 트리가 루트에서 읽힌다. |
| 정수, 선택 사항 | 반환되는 항목 수. 기본 20, 최대 200. |
search_recipes
요리나 재료로 검색한다. 사이트는 다섯 가지 방식으로 응답하며, kind가 어느 쪽인지 말해준다. 검색을 자체 카테고리 페이지로 보낼 때는 topic, 자체 조건으로 응답할 때는 free_text, 그 주제에 대해 가이드를 작성했을 때는 guide, 단어가 충분히 정확해 카드를 열 수 있다고 판단할 때는 recipe, 이해하지 못해 홈페이지를 제공할 때는 unmatched이다.
인자 | 유형 | 의미 |
| 문자열 | 프랑스어로 된 요리 또는 재료. |
| 정수, 선택 사항 | 반환되는 줄 수. 기본 20, 최대 100. |
browse_recipes
카테고리를 페이지별로, 또는 사이트가 유지하는 세 목록 중 하나를 탐색한다.
인자 | 유형 | 의미 |
| 문자열, 선택 사항 |
|
|
| 사이트의 상설 목록 중 하나. |
| 정수, 선택 사항 | 읽을 카테고리의 페이지. |
| 정수, 선택 사항 | 반환되는 줄 수. 기본 20. |
search_by_ingredients
사이트의 냉장고 검색을 읽는다. 입력은 한 가지에서 다섯 가지 재료, 출력은 그 재료들을 담은 레시피들.
인자 | 유형 | 의미 |
| 문자열[] | 프랑스어로 된 한 가지에서 다섯 가지 재료. |
| 정수, 선택 사항 | 반환되는 줄 수. 기본 20. |
get_recipe
레시피를 읽고, 요청이 있으면 재료를 배율에 맞게 조정한다.
인자 | 유형 | 의미 |
| 문자열 | 검색이나 목록이 반환한 줄의 |
| 정수, 선택 사항 | 이 인분 수에 맞게 재료를 배율 조정한다. |
각 줄은 산술이 무엇을 했는지 말해주는 scaling을 담고 있다. scaled는 정확하고, rounded는 사용 가능하도록 조정되었으며, unscaled는 곱할 것이 없었다. 1 oeuf를 두 배로 하면 2 oeufs가 된다. 반으로 나누면 rounded로 표시된 1 oeuf가 되는데, 반 개의 달걀은 주방에서 재는 양이 아니기 때문이다.
scale_ingredients
같은 산술을, 출처가 무엇이든 임의의 프랑스어 목록에 대해 오프라인으로 수행한다.
인자 | 유형 | 의미 |
| 문자열[] | 배율 조정할 줄들. |
| 숫자 | 적용할 배수. |
| 숫자들 | 또는 배수가 도출되는 쌍. |
get_recipe_translations
레시피가 출판된 다른 언어들을 나열한다. Ptitchef는 같은 레시피들을 출판하는 사이트 네트워크의 프랑스어 판이며, 각 페이지는 자매판들을 이름으로 가리킨다. 그 수가 얼마인지는 레시피에 달려 있다. 최근 것은 스무 개 이상을, 오래된 것은 하나도 이름을 대지 않는다.
응답이 단언하지 않는 것들
가이드는 목록이 아니며, 응답은 어느 쪽이 도착했는지 말해준다. 어떤 주제들은 사이트가 작성한 가이드로 제공되는데, 총계가 없고 그 줄들은 이름, 주소, 이미지, 투표 수를 담는다. 그 경우 kind는 guide이며, 같은 slug에 대한 browse_recipes는 주제의 전체 목록을 총계와 함께 돌려준다. épinards는 32개 레시피의 가이드를 돌려주고, 그 목록은 736개를 담는다.
다른 레시피 대신 제공된 레시피는 부재로 처리된다. 레시피 주소의 단어들은 장식일 뿐이고 번호는 장식이 아니다. 사이트가 갖고 있지 않은 번호를 요청하면 관련 없는 레시피가 HTTP 200과 완전한 상세 정보로 돌아온다. 돌아온 번호는 요청한 번호와 비교된다.
목록을 읽을 수 없는 페이지는 부재가 아니다. 개수를 담은 제목과 읽을 수 있는 목록이 없는 페이지는 이 서버가 읽을 줄 모르는 페이지이며, 서버는 « 레시피 없음, 사이트는 3200개를 보유한다고 말함 » 대신 그 사실을 돌려준다.
평점은 사이트가 계산한 숫자다. 어떤 줄은 페이로드에 3,8을 알리면서 별 네 개를 그린다. 게시되는 것은 계산된 숫자이며, 아무것도 계산하지 않는 가이드는 아무것도 게시하지 않는다.
총계가 무엇을 세는지는 응답에서 읽힌다. 사이트가 카테고리 페이지로 보내는 검색은 그 카테고리의 총계를 돌려준다. 사이트가 직접 처리하는 검색은 사이트가 센 값을 돌려주는데, 때로는 제공된 줄 수를 넘는다. 주석은 두 숫자가 그것을 확립하는 경우에만 그렇게 말한다.
아무것도 맹목적으로 곱해지지 않는다. 셀 수 있는 것은 요리사가 하나에서 취하는 가장 작은 분량으로 떨어진다. 하나의 절반을 잴 수 없는 곳에서는 정수, 예를 들어 달걀 하나. 붓거나 자를 수 있는 곳에서는 절반, 예를 들어 봉지 하나. 질량은 반올림되기 전에 단위를 내려가므로, 단위 미만의 양은 결코 0으로 떨어지지 않는다. 한 꼬집은 그 자체의 어휘를 유지하고 그 개수가 곱해지는데, 한 꼬집의 크기는 요리사의 것이기 때문이다.
배율 조정 없이 반환된 목록은 줄마다가 아니라 한 번에 그것을 말한다. servings가 없으면 산술이 없으며, 각 줄을 unscaled로 표시하는 것은 어떤 줄도 곱할 것을 담고 있지 않다고 단언하는 셈이 된다.
추정 비용은 반복될 뿐, 다시 계산되지 않는다. 그것은 사이트의 숫자이며, 페이지가 알리는 인분 수에 대해 게시된 것이고, 응답은 어느 것인지 말해준다.
페이지에서 읽은 주소는 그 사이트를 벗어나지 않는다. 다른 곳을 가리키는 줄은 « 레시피의 공개 페이지 »라는 라벨로 게시되는 대신 제외된다.
설치
npx mcp-ptitchefClaude Code
claude mcp add ptitchef -- npx -y mcp-ptitchef아무 MCP 클라이언트나
{
"mcpServers": {
"ptitchef": {
"command": "npx",
"args": ["-y", "mcp-ptitchef"]
}
}
}컨테이너
docker build -t mcp-ptitchef .
docker run -i --rm mcp-ptitchef컨테이너는 www.ptitchef.com에만 접속해야 하며 다른 곳에는 접속하지 않아야 한다. 컨테이너는 어떤 자격 증명도 받지 않는데, 받을 자격 증명이 없기 때문이다.
설정
각 설정은 환경 변수이며, 어느 것도 필수는 아니다. 범위를 벗어난 값은 stderr에 한 줄을 출력해 거부되고 기본값이 유지된다. 적용할 수 없는 설정은 조용히 범위 안으로 되돌려지기보다 그 사실을 말한다.
변수 | 기본값 | 범위 |
| — | 사용자 식별자. 프로젝트의 것은 계속 추가되어, 사이트가 사람에게 연락할 수 있게 한다. |
| 1500 | 1000~60000 |
| 20000 | 1000~120000 |
| 3 | 0~8 |
| 900000 | 0~86400000, 0은 저장을 끈다 |
| 200 | 1~5000 |
|
|
|
요청 간격 하한은 외부에서 낮출 수 없다. 사이트는 읽기에 자유롭고 어떤 크롤링 지연도 공개하지 않는데, 그것이 조심해야 할 이유다.
라이브러리로
읽기 계층은 프로토콜을 붙이지 않은 채, 자체 요청 간격, 저장소, 오류 어휘와 함께 단독으로 공개된다:
import { PtitchefClient } from "mcp-ptitchef/client";오류
여섯 개 코드, 그 이상도 없다. 호출자는 메시지를 여는 코드에 연결한다.
Code | 의미 |
| 사이트가 이 주소에 아무것도 가지고 있지 않음 |
| 인수가 요청을 생성할 수 없음 |
| 사이트가 이 클라이언트에게 속도를 늦추라고 요청함. 이것은 사이트가 가진 것에 대해 아무것도 말해 주지 않음 |
| 이 서버가 읽을 수 없는 형태로 응답이 도착함 |
| 요청이 완료될 수 없음 |
| 제한 시간 내에 응답이 도착하지 않음 |
출처 표시
레시피, 제목, 카테고리는 Ptitchef에 속합니다. 각 응답은 출처를 담고 있으며, 독자에게 보여지는 목록은 사이트를 표시하고 페이지에 링크해야 합니다.
기여
CONTRIBUTING.md를 참조하세요. 테스트 우선, 커버리지 하한선은 100%이며, 모든 것이 따르는 규칙은 서버가 데이터가 담고 있지 않은 것을 절대 말하지 않는다는 것입니다.
MIT 라이선스에 따라 사용이 허가됩니다.
Available Tools
7 toolsbrowse_recipesBrowse a category or a standing listARead-onlyIdempotent
Read the recipes under one category of Ptitchef, page by page, or one of the lists the site keeps standing. Pass 'category' with a slug from list_categories or from a search's 'topic_slug', or pass 'listing' for one of: latest, top_rated, most_viewed. Never build a category slug by hand: the site writes them freely and answers an address it does not hold by serving another page. The page in the answer is the one the site served, which is the first page again when the page asked for is past the last one.
| Name | Required | Description | Default |
|---|---|---|---|
| page | No | The page of a category to read. A standing list has one page only. | |
| limit | No | Rows to render, 20 by default. | |
| listing | No | One of the site's standing lists, read instead of a category. | |
| category | No | A category slug: one from list_categories whose 'is_family' is false, or the 'topic_slug' a search answered with. A family's slug belongs to list_categories instead. |
Output Schema
| Name | Required | Description |
|---|---|---|
| url | Yes | The address the listing was read from. |
| kind | Yes | How the listing came to be, which decides what its total counts. 'topic' means the site answered a search from a page of its own; 'free_text' means it answered on its own terms. |
| page | Yes | The page that was read, which is the one the site served. |
| asked | Yes | What was asked for: a search, a category, or a list of ingredients. 'query' carries the same value under the name every source of recipes publishes it in. |
| notes | Yes | What qualifies this answer: what its total counts, what it left out, and where the site answered from an address other than the one asked for. Read these before quoting a figure. |
| query | Yes | What was asked for, under the name a search publishes it in. |
| title | Yes | The site's own heading for the listing. |
| folded | Yes | Rows naming a recipe already held. A guide lists one recipe under two headings where it belongs to both; such a row is counted in 'rows_seen' and rendered once. |
| source | Yes | The site this answer was read from. Credit it when showing a row. |
| results | Yes | |
| rows_seen | Yes | Rows the site served on this page, before any were set aside. |
| topic_slug | Yes | The category page this listing was served from. Pass it to browse_recipes as 'category' to read the topic's further pages, and its total where this answer carries none. |
| single_page | Yes | True when the site serves this listing on one page and offers no further one. |
| result_count | Yes | Rows rendered here. |
| total_available | Yes | Recipes the site says this listing holds. Null when it published no figure. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Beyond the readOnly/idempotent/non-destructive annotations, the description discloses a non-obvious behavioral quirk: the site serves another page when it does not hold the address, and pages past the last one silently return the first page. This is exactly the kind of edge-case behavior an agent needs before invoking the tool.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Four sentences, and each earns its place: the core operation, the two input modes, the slug-authoring warning, and the pagination fallback behavior. The main purpose is front-loaded and the caveats are placed after the primary semantics.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a read-only paginated browsing tool with rich schema descriptions and an output schema, the definition covers the dangerous non-obvious behaviors that could otherwise cause an agent to misread results: slug tolerance and page wrapping. Nothing essential for correct invocation is missing.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
The schema already documents all parameters at 100% coverage, but the description adds usable guidance about where category slugs come from, that listing values are mutually exclusive with category, and the warning against hand-built slugs. It reinforces but does not deeply extend the schema's parameter descriptions, so a 4 is appropriate.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description opens with a specific verb and resource: 'Read the recipes under one category of Ptitchef, page by page, or one of the lists the site keeps standing.' It clearly states both operating modes and distinguishes this from siblings like list_categories (which returns categories) and search_recipes (which returns search results).
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description gives explicit input-selection rules: pass 'category' with a slug from list_categories or a search's 'topic_slug', or pass 'listing' with one of the named standing lists. It also gives a strong exclusion: never hand-build a category slug. It does not explicitly name the sibling tools to use instead, but the context is clear.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
get_recipeRead one recipeARead-onlyIdempotent
Read one Ptitchef recipe: its ingredients, method, times, rating, nutrition and the cost the site estimates for it. Pass the 'id' of a row from search_recipes, browse_recipes or search_by_ingredients. Give 'servings' to rescale the ingredients, and read each line's 'scaling' before quoting a quantity: 'scaled' is exact arithmetic, 'rounded' was moved to stay usable, and 'unscaled' carries nothing that could be multiplied. A time or a figure the site publishes none of comes back null, never zero.
| Name | Required | Description | Default |
|---|---|---|---|
| id | Yes | The 'id' of a row from a search or a listing, which is the recipe's own page path. | |
| servings | No | Rescale the ingredients to this many servings. Left out, the ingredients come back as published. |
Output Schema
| Name | Required | Description |
|---|---|---|
| id | Yes | |
| faq | Yes | |
| url | Yes | The public page. Show this when citing the recipe. |
| notes | Yes | What qualifies this answer: what the arithmetic did, what it could not do, and what the site states rather than this server. Read these before quoting a quantity or a cost. |
| steps | Yes | The method, one line per step, in the shape every source of recipes publishes it in. 'illustrated_steps' carries the same lines beside the photograph the site took of each. |
| title | Yes | |
| yield | Yes | |
| author | Yes | |
| rating | Yes | 1 to 5, as the site states it. |
| source | Yes | The site this recipe was read from. Credit it when showing it. |
| cuisine | Yes | |
| category | Yes | |
| keywords | Yes | |
| modified | Yes | |
| image_url | Yes | |
| nutrition | Yes | As published, per the serving size it names. |
| published | Yes | |
| author_url | Yes | |
| difficulty | Yes | The site's own wording, such as 'facile'. |
| attribution | Yes | |
| description | Yes | |
| ingredients | Yes | The lines as published where no servings were asked for, in which case 'yield.factor' is null and each line's 'scaling' describes no arithmetic. Pass 'servings' to rescale them. |
| cook_minutes | Yes | |
| prep_minutes | Yes | |
| rating_count | Yes | |
| review_count | Yes | |
| translations | Yes | The other languages this recipe was published in, which get_recipe_translations answers on its own for a caller who wants nothing else. |
| total_minutes | Yes | |
| estimated_cost | Yes | What the site estimates the ingredients cost, with the currency it names. Repeated as published: it is the site's figure and readers of the site dispute it. |
| illustrated_steps | Yes | |
| steps_are_one_block | Yes | True when the site published its method as one block of prose, so the single step above is that block rather than the first of several. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already cover read-only, open-world, idempotent, and non-destructive behavior. The description adds valuable behavioral detail beyond that: it explains the 'scaling' field's values ('scaled', 'rounded', 'unscaled') and their meaning for quoting quantities, and states that absent site figures come back null, never zero. No contradiction with annotations.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Four sentences, each earning its place: scope, id sourcing, servings, and output semantics. It is dense but front-loaded with the core purpose, and no sentence is filler.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
With an output schema present and annotations covering the safety profile, the description provides enough context for correct invocation. It handles id provenance, optional servings, scaling nuances, and null semantics; minor omissions like invalid-id behavior are not critical.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is 100%, so the schema already documents both parameters. The description adds value by specifying that valid 'id' values come from rows of three sibling tools and clarifies that 'servings' rescales ingredients, echoing the schema in more actionable terms.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description states a specific verb ('Read'), a unique resource ('one Ptitchef recipe'), and enumerates what is returned (ingredients, method, times, rating, nutrition, cost). It also differentiates from search siblings by instructing the agent to pass an id from search_recipes, browse_recipes, or search_by_ingredients.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
It gives clear context: use with an id coming from the three listed search tools, and optionally pass servings to rescale. It names the upstream tools that produce valid ids, but doesn't explicitly state when not to use it (e.g., when scale_ingredients might be more appropriate), so it stops short of full exclusion guidance.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
get_recipe_translationsFind a recipe in the other languages it was published inARead-onlyIdempotent
List the other languages a Ptitchef recipe was published in, with the page of each. get_recipe already carries this list under 'translations', so call this one only where the rest of the recipe is not wanted. Pass the 'id' of a row from a search or a listing. The pairing is the site's own: each page names its counterparts, and this repeats those names rather than matching titles. How many there are belongs to the recipe: a recent one names more than twenty, from German to Hindi, and an older one names none. An empty list is what the site published, and the read succeeded.
| Name | Required | Description | Default |
|---|---|---|---|
| id | Yes | The 'id' of a row from a search or a listing, which is the recipe's own page path. |
Output Schema
| Name | Required | Description |
|---|---|---|
| id | Yes | |
| url | Yes | The French page these counterparts were read from. |
| notes | Yes | |
| title | Yes | |
| source | Yes | |
| translations | Yes | |
| translation_count | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already indicate read-only, idempotent, open-world, and non-destructive behavior. The description adds meaningful nuanced behavior: the translation pairing is site-defined and repeated rather than title-matched, the count varies by recipe, and an empty list still means the read succeeded. This goes well beyond the annotation hints.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is front-loaded with the core purpose and is not padded. A few repeated details from the schema and the illustrative language examples add length, but each sentence contributes useful operational or interpretive context for an agent.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a single-parameter read tool with an output schema and strong annotations, the description is complete: it explains when to use this tool instead of get_recipe, how to source the id, what the result represents, how size varies, and how to interpret an empty list.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is 100%, and the schema already explains that 'id' is 'The id of a row from a search or a listing, which is the recipe's own page path.' The description repeats this same guidance without adding substantial new parameter semantics, so the baseline of 3 is appropriate.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
Description names a specific verb and resource: 'List the other languages a Ptitchef recipe was published in, with the page of each.' It explicitly contrasts with the sibling get_recipe, which already contains this list, so an agent can immediately distinguish this tool from the main recipe-fetching tool.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description gives a clear when-to-use rule: call this only when the rest of the recipe is not wanted, because get_recipe already carries the translations list. It also tells the agent exactly what input to pass: the 'id' of a row from a search or listing.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
list_categoriesList the categories recipes are browsed byARead-onlyIdempotent
List the categories Ptitchef browses its recipes by. Called without arguments it returns the families of ingredients; pass a family's slug as 'family' to list the categories it holds. Read this before building an address by hand: the site writes its slugs freely, so the same vegetable appears as 'chou-kale' on one line and as 'recette-de-petits-pois' on the next, and a slug that was guessed lands on a page the site does not hold. Each entry carries the slug to pass back and the page to open.
| Name | Required | Description | Default |
|---|---|---|---|
| limit | No | Entries to render, 20 by default and 200 at most. A level holding more than this says so, and 'categories_published' always states what the page listed. | |
| family | No | The slug of a family to open, taken from a previous call. Leave it out to read the families themselves, which is where the tree starts. |
Output Schema
| Name | Required | Description |
|---|---|---|
| url | Yes | The page these categories were read from. |
| notes | Yes | |
| family | Yes | The family that was opened, or null for the root. |
| source | Yes | |
| categories | Yes | |
| family_title | Yes | The site's own heading for this level. Null when the page carries none. |
| category_count | Yes | Entries rendered here. |
| categories_published | Yes | Entries the page listed, before any were rendered. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already establish that this is read-only, idempotent, non-destructive, and open-world. The description adds valuable behavioral context beyond those annotations by warning that slugs are written freely by the site, that guessed slugs land on non-existent pages, and that entries carry the slug to pass back. This directly addresses the open-world nature of the catalog and prevents a common failure mode.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is compact and front-loaded: the core action and the two-mode behavior appear first, followed by a necessary warning about slug instability. Every sentence contributes either to correct invocation or to avoiding an error, with no filler or repetition of schema content.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Given the tool's two-level hierarchy, optional parameters, rich annotations, and existing output schema, the description covers everything an agent needs: how to start, how to descend, and why slug guessing is unsafe. Pagination and return details are already handled by the schema and output schema, so nothing essential is missing.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 100%, so the schema fully documents 'limit' and 'family.' The description reinforces that 'family' should come from a previous call and that omitting it reads the families, but it does not add meaning significantly beyond the schema. Baseline 3 is appropriate because the schema carries the parameter documentation burden.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description states a specific verb and resource: 'List the categories Ptitchef browses its recipes by.' It also clarifies the hierarchical relationship between families of ingredients and categories, which separates it from sibling tools like search_recipes, browse_recipes, and get_recipe. The two-call pattern (no argument for families, family slug for categories) makes the tool's purpose unambiguous.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description gives explicit instructions for both usage modes: called without arguments it returns families, and passing a family's slug as 'family' returns its categories. It also warns against hand-building slugs. It does not explicitly name sibling alternatives or state when to prefer this tool over search/browse tools, but the context is clear enough for an agent to select it for category-tree navigation.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
scale_ingredientsRescale an ingredient listARead-onlyIdempotent
Rescale a list of ingredient lines to a different number of servings, without contacting any website. Give either 'factor' directly, or 'from_servings' and 'to_servings' and the factor is computed. Works on any French ingredient list, whatever its source, so it also serves a recipe pasted in by hand. Quantities in grams or millilitres are multiplied and rounded to readable values; a countable thing lands on a half when half of one can be poured, weighed or cut, as a boîte, a sachet, a feuille de gélatine or a cuillère can, and on a whole one when it cannot, as an oeuf, a jaune or a blanc; approximate measures such as a pinch or a handful have their count multiplied in whole units and stay in their own vocabulary. A line writing an article where a digit would go, as in 'un bouchon de rhum' or 'une pincée de sel', is read as one of that measure. Lines carrying no quantity are returned untouched and flagged. Prefer this over doing the arithmetic yourself.
| Name | Required | Description | Default |
|---|---|---|---|
| factor | No | Multiplier to apply. Use this or the from/to pair. | |
| ingredients | Yes | Ingredient lines, for example ['200 g de farine', '3 oeufs', 'sel']. | |
| to_servings | No | How many servings are wanted. | |
| from_servings | No | How many servings the list is written for. |
Output Schema
| Name | Required | Description |
|---|---|---|
| notes | Yes | |
| factor | Yes | |
| ingredients | Yes | |
| scaled_count | Yes | |
| rounded_count | Yes | Lines whose value rounding moved away from the exact product, not lines that could have been rounded. |
| unscaled_count | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
The annotations already declare readOnly, idempotent, and non-destructive behavior, but the description goes far beyond them: it explains rounding to readable values, the half/whole rounding rule based on countable items, treatment of approximate measures, parsing of articles as one unit, and that unquantified lines are returned untouched and flagged. This is rich behavioral disclosure with no contradiction to the annotations.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The opening sentence front-loads the core purpose and the no-network constraint. The following sentences pack dense but relevant detail: parameter alternatives, French-list applicability, rounding rules with concrete examples, edge-case handling, and a closing usage preference. Every clause earns its place; there is no filler.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Given the tool's complexity, the description covers domain scope, parameter alternatives, rounding rules, approximate measures, and unquantified lines. An output schema exists, so return-value details are not required. The only notable omission is the fallback or error behavior when no scale parameter is provided, since the schema does not enforce one of factor/from_servings/to_servings.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
The schema already describes every parameter, so the baseline is 3. The description adds meaning by explaining the relationship between factor and from_servings/to_servings, stating that the factor is computed from the serving pair. It also gives concrete ingredient-line examples. A minor gap is that it does not explicitly state what happens if neither factor nor the from/to pair is supplied, though the schema only requires ingredients.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
States a specific verb and resource: 'Rescale a list of ingredient lines to a different number of servings,' and adds the key constraint 'without contacting any website.' This clearly distinguishes it from sibling recipe browsing and search tools, which focus on finding or retrieving recipes rather than transforming ingredient lines.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Gives clear context: it works on any French ingredient list, including pasted recipes, and explicitly says 'Prefer this over doing the arithmetic yourself.' It does not name a competing sibling tool or state explicit exclusions, but no sibling targets the same operation, so the guidance is adequate.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
search_by_ingredientsFind recipes from the ingredients a cook hasARead-onlyIdempotent
Find Ptitchef recipes from the ingredients a cook already has. Give one to 5 ingredients in French, as a cook would name them ("poulet", "citron"). The site counts every recipe it finds and serves one page of them, so 'total_available' can be far larger than the rows returned, and the rest cannot be reached. A longer list than the site's own form reads is refused rather than sent and silently cut.
| Name | Required | Description | Default |
|---|---|---|---|
| limit | No | Rows to render, 20 by default. | |
| ingredients | Yes | One to 5 ingredients, in French. The site reads no more than that. |
Output Schema
| Name | Required | Description |
|---|---|---|
| url | Yes | The address the listing was read from. |
| kind | Yes | How the listing came to be, which decides what its total counts. 'topic' means the site answered a search from a page of its own; 'free_text' means it answered on its own terms. |
| page | Yes | The page that was read, which is the one the site served. |
| asked | Yes | What was asked for: a search, a category, or a list of ingredients. 'query' carries the same value under the name every source of recipes publishes it in. |
| notes | Yes | What qualifies this answer: what its total counts, what it left out, and where the site answered from an address other than the one asked for. Read these before quoting a figure. |
| query | Yes | What was asked for, under the name a search publishes it in. |
| title | Yes | The site's own heading for the listing. |
| folded | Yes | Rows naming a recipe already held. A guide lists one recipe under two headings where it belongs to both; such a row is counted in 'rows_seen' and rendered once. |
| source | Yes | The site this answer was read from. Credit it when showing a row. |
| results | Yes | |
| rows_seen | Yes | Rows the site served on this page, before any were set aside. |
| topic_slug | Yes | The category page this listing was served from. Pass it to browse_recipes as 'category' to read the topic's further pages, and its total where this answer carries none. |
| single_page | Yes | True when the site serves this listing on one page and offers no further one. |
| result_count | Yes | Rows rendered here. |
| total_available | Yes | Recipes the site says this listing holds. Null when it published no figure. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Beyond the readOnlyHint, openWorldHint, and idempotentHint annotations, it discloses non-obvious behaviors: the site counts all matches but serves only one page, the rest cannot be reached, and an over-long ingredient list is refused rather than silently truncated. This is exactly the kind of behavioral context annotations do not capture.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Three short sentences with the purpose first, then instructions, then boundary behaviors. Every sentence earns its place and there is no filler or repetition of annotation data.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Given the rich annotations and output schema, the description covers everything an agent needs to invoke it correctly: ingredient count, language, refusal behavior, and pagination limitations. The only minor gap is not explicitly routing to sibling search_recipes, but the ingredient-based purpose makes that choice obvious.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
The input schema already has 100% coverage, including the French requirement, one-to-five item bounds, and per-string length limits. The description adds helpful cook-friendly examples, but it largely restates the schema rather than adding deeper semantic meaning, so the baseline 3 is appropriate.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description opens with a specific verb-resource pair ('Find Ptitchef recipes') and narrows the scope to ingredients a cook already has, which distinguishes it from sibling search_recipes, browse_recipes, and list_categories. It also clarifies the input language and gives examples, making the tool's identity unmistakable.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
It gives actionable usage instructions: one to five ingredients, in French, using natural cook phrasing with examples. It doesn't explicitly say when not to use this tool or name an alternative, so it stops short of a 5, but the context is clear enough for an agent to select it appropriately.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
search_recipesSearch recipesARead-onlyIdempotent
Search recipes on Ptitchef by dish or ingredient. The site answers in one of two ways and the answer says which: it either sends the search to a category page of its own, whose total counts what that category holds, or it answers on its own terms on a single page whose total is the number of rows served. When a category answered, 'topic_slug' names it and browse_recipes reads its further pages. Some topics come back as a guide the site wrote instead, grouped under headings of its own and carrying no total; browse_recipes on the same 'topic_slug' reads their full listing. A search the site matched nothing for comes back with no row and a total of zero, which is an absence the site stated.
| Name | Required | Description | Default |
|---|---|---|---|
| limit | No | Rows to render, 20 by default. 'rows_seen' states what the page served. | |
| query | Yes | A dish or an ingredient, in French, as a reader of the site would type it. |
Output Schema
| Name | Required | Description |
|---|---|---|
| url | Yes | The address the listing was read from. |
| kind | Yes | How the listing came to be, which decides what its total counts. 'topic' means the site answered a search from a page of its own; 'free_text' means it answered on its own terms. |
| page | Yes | The page that was read, which is the one the site served. |
| asked | Yes | What was asked for: a search, a category, or a list of ingredients. 'query' carries the same value under the name every source of recipes publishes it in. |
| notes | Yes | What qualifies this answer: what its total counts, what it left out, and where the site answered from an address other than the one asked for. Read these before quoting a figure. |
| query | Yes | What was asked for, under the name a search publishes it in. |
| title | Yes | The site's own heading for the listing. |
| folded | Yes | Rows naming a recipe already held. A guide lists one recipe under two headings where it belongs to both; such a row is counted in 'rows_seen' and rendered once. |
| source | Yes | The site this answer was read from. Credit it when showing a row. |
| results | Yes | |
| rows_seen | Yes | Rows the site served on this page, before any were set aside. |
| topic_slug | Yes | The category page this listing was served from. Pass it to browse_recipes as 'category' to read the topic's further pages, and its total where this answer carries none. |
| single_page | Yes | True when the site serves this listing on one page and offers no further one. |
| result_count | Yes | Rows rendered here. |
| total_available | Yes | Recipes the site says this listing holds. Null when it published no figure. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
The description discloses a wealth of behavioral detail far beyond what annotations provide. It explains the two distinct response modes (category pages vs. single pages), the meaning of the total (category count vs. row count), the existence of topic_slug, the guide case with no total, and the zero-result case as an explicit absence. This is precisely the kind of non-obvious behavior an agent needs to know before calling the tool.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
While the purpose is front-loaded in the opening sentence, the remainder is a long, winding explanation of response behavior packed into a single run-on paragraph. It lacks clear structure and could be shortened or bullet-pointed. The complexity is high, but the description is not concise; several sentences could be consolidated without losing information. This makes it harder for an agent to quickly extract the key points.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a search tool with rich behavioral nuances, the description covers all essential aspects: response variants, total semantics, topic_slug usage, guides, and the no-result case. It also routes to browse_recipes for pagination. Since an output schema exists, the description need not explain return values, and it already explains the meaning of fields like rows_seen and total as they appear in responses. No critical missing context is apparent.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
The input schema already covers both parameters with clear descriptions (query in French, limit with default and meaning of rows_seen). The description adds no additional parameter-specific meaning, which is acceptable given 100% schema coverage. Baseline 3 is appropriate; the description does not need to repeat schema content.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The first sentence clearly states a specific verb and resource: 'Search recipes on Ptitchef by dish or ingredient.' It also distinguishes itself from the sibling 'browse_recipes' by explaining that browse_recipes reads further pages of a category topic. This gives an agent a precise initial understanding of what the tool does and how it differs from a closely related tool.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description provides explicit guidance on when to follow up with 'browse_recipes' (when a category answers or a guide is returned), which is a form of usage routing. However, it never mentions the alternative 'search_by_ingredients' or states when to choose this tool over it. It also does not explicitly state when NOT to use search_recipes, so the guidance is partial and relies on inference.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
Tool Schema Changelog
Recent tool additions, removals, and schema changes observed during successful MCP inspections.
7 tool updates
v1.0.0- First observed
browse_recipes - First observed
get_recipe - First observed
get_recipe_translations - First observed
list_categories - First observed
scale_ingredients - First observed
search_by_ingredients - First observed
search_recipes
TDQS
Scored across 7 tools
Each tool targets a distinct action—listing, searching, browsing, reading, scaling, translating—but search_recipes and search_by_ingredients overlap conceptually, and get_recipe's built-in rescaling partially duplicates scale_ingredients. The descriptions are detailed enough to separate them, though an agent could still pause between those pairs.
All tool names follow a clear snake_case verb_noun pattern: list_, search_, browse_, get_, scale_. The one longer name, search_by_ingredients, still fits predictably and does not break the convention.
Seven tools is a well-scoped set for a recipe site: discovery, browsing, retrieval, scaling, and translations are each represented without unnecessary duplication. Each tool earns its place in the workflow.
The read-side recipe workflow is fully covered: find categories, search, browse, search by ingredients, read a recipe, rescale ingredients, and access translations. There are no dead ends, and CRUD operations are not relevant to this domain.
Maintenance
Related MCP Connectors
Read-only Danish recipes, ingredients and categories from ullasopskrifter.dk: search and browse.
Recipes MCP — wraps TheMealDB API (free tier, no auth)
Canadian grocery flyer deals and recipes by item, store, postal code, cuisine, or diet. No auth.
Unofficial read-only MCP server for VeryChic hotel offers
Related MCP Servers
- FlicenseCqualityDmaintenanceEnables management of culinary recipes through web scraping from sites like Marmiton.org, recipe generation, ingredient management, and querying a MongoDB database of recipes, comments, users, and utensils.18-
- AlicenseNot gradedqualityBmaintenanceEnables querying French government public procurement notices (BOAMP) without an API key.29 npmMIT
- AlicenseAqualityBmaintenanceMCP server that searches French recipes from Marmiton, reads ingredients and steps, and rescales quantities to any number of servings without requiring an API key.3136 npm1MIT
- AlicenseAqualityAmaintenanceEnables read-only recipe search and filtering on BBC Good Food by exposing available filter axes with counts, requiring no API key.4114 npmMIT