Loafy: Sourdough Bread Baking
Server Details
Sourdough baking: dough calculators, a bake planner, The Sourdough Framework and your bake journal
- Status
- Healthy
- Uptime
- 99.6% over 21 days
- Last Tested
- Transport
- Streamable HTTP · MCP 2025-11-25
- URL
- ChatGPT
- –
- Claude
- loafy.ai
TDQS
Scored across 20 tools
Each tool has a clearly distinct purpose, and the descriptions actively cross-reference the nearest neighbor (bread vs. pizza dough, plan_sourdough_bake vs. estimate_bulk_fermentation, find_sourdough_answer vs. search_sourdough_book vs. read_sourdough_book). The add/list/update triplets per resource (starter, container, bake) are trivially distinguishable by verb and resource. An agent should have no trouble selecting the right tool.
All 20 tools use snake_case with a leading verb (add_, list_, update_, get_, calculate_, plan_, estimate_, find_, search_, read_, log_, start_). The 'list_my_*' prefix for personal data is applied uniformly across bakes, starters, and containers, so even that quirk is predictable rather than inconsistent.
20 tools is at the upper edge of a well-scoped set, but the server genuinely spans several sub-domains: dough calculators, bake planning, book search/reading, journals, and guided journeys. Each tool covers a distinct operation, though the starter/container management triplets add surface area that could be consolidated.
Coverage is broad and coherent—calculation, planning, guidance, journaling, and starter/container tracking all have create/list/update paths, documented with explicit lifecycle hints. The only notable gap is deletion: starters, containers, and bakes can never be removed, which is stated but leaves a dead end for correcting mistakes.
Available Tools
20 toolsadd_containerAdd a container to LoafyAInspect
Add a container to the baker's Loafy account with its empty weight in grams, so Loafy can take it off when dough is weighed in it. Returns it with its id and a link. A name the baker already uses is not added again; that container comes back, and update_container changes it. Needs the baker's Loafy account.
| Name | Required | Description | Default |
|---|---|---|---|
| name | Yes | The container's name, e.g. "Glass bowl". | |
| notes | No | Notes on the container. | |
| weight_grams | Yes | The empty container's weight in grams. |
Output Schema
| Name | Required | Description |
|---|---|---|
| url | No | The same answer, recipe or entry on loafy.ai. |
| note | No | A remark on the whole result, such as why nothing was found. |
| tool | No | The tool that answered. |
| input | No | The arguments as the tool used them, after any correction. |
| notes | No | What was corrected or left out, such as a value outside its range. |
| saved | No | What was saved, in one sentence. |
| container | No | One of the baker's containers. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Goes beyond the annotations by disclosing the name-collision dedup behavior (existing container is returned instead of a duplicate being created) and the auth prerequisite. Annotations already cover the safety profile (readOnly=false, destructive=false, openWorld=false). The dedup-on-name detail is a genuine behavioral nuance, though it sits in slight tension with idempotentHint=false.
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?
Roughly four short sentences, front-loaded with the core action and purpose, then the return value, then the dedup/alternative behavior. Mostly earns its place, though the "so Loafy can take it off..." clause is somewhat verbose.
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?
Covers the action, auth requirement, dedup edge case, and routing to update_container; return details are backed by an output schema so need not be restated. Adequate for a low-complexity 3-param tool, with only minor room for richer context.
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 already documents name, notes, and weight_grams with units and ranges. The description reinforces the meaning of the weight (empty weight subtracted when dough is weighed) but adds no syntax or format detail beyond the schema. 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?
States a specific verb and resource ("Add a container to the baker's Loafy account") and clarifies its purpose (recording empty weight so Loafy can subtract it during dough weighing). It also explicitly distinguishes itself from the sibling update_container for changing an existing container.
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?
Explains the condition for use and the key when-not case: a name the baker already uses will not be added again, and update_container is named as the alternative for changing an existing container. Prerequisite ("Needs the baker's Loafy account") is also stated. Lacks a broader statement of when a container should be registered versus other workflows.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
add_starterAdd a starter to LoafyAInspect
Add a sourdough starter to the baker's Loafy account: its name, the day it was started, notes and its story. Returns it with its id and a link, where photos are added. A name the baker already uses is not added again; that starter comes back, and update_starter changes it. Needs the baker's Loafy account.
| Name | Required | Description | Default |
|---|---|---|---|
| name | Yes | The starter's name. | |
| notes | No | Notes on the starter, e.g. its flour and how it is fed. | |
| story | No | Where the starter comes from, in the baker's words. | |
| birthday | No | The day the starter was started, as YYYY-MM-DD; today if left out. |
Output Schema
| Name | Required | Description |
|---|---|---|
| url | No | The same answer, recipe or entry on loafy.ai. |
| note | No | A remark on the whole result, such as why nothing was found. |
| tool | No | The tool that answered. |
| input | No | The arguments as the tool used them, after any correction. |
| notes | No | What was corrected or left out, such as a value outside its range. |
| saved | No | What was saved, in one sentence. |
| starter | No | One of the baker's starters. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already cover the safety profile (non-read-only, non-destructive, non-idempotent), so the bar is lower. The description adds genuinely useful context beyond them: the return value (id and link for adding photos) and the duplicate-name semantics where an existing starter is returned instead of creating a new one.
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 definition is front-loaded with the core action and keeps each sentence purposeful, covering fields, return, duplicate handling, and prerequisites without filler. It is slightly dense but well-structured.
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, return values need not be detailed, yet the description still notes the id/link return and duplicate-name behavior. Prerequisites and the update_starter route are covered, leaving little an agent needs that 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 already documents all four parameters including the YYYY-MM-DD birthday default. The description echoes the field set but adds no syntax or format detail beyond the schema, matching the baseline 3.
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: 'Add a sourdough starter to the baker's Loafy account,' and enumerates the fields it carries (name, start day, notes, story). It also distinguishes itself from the sibling update_starter, so an agent can tell the two apart without opening either schema.
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 a clear when-not case ('A name the baker already uses is not added again') and names the alternative (update_starter) for that scenario. The prerequisite 'Needs the baker's Loafy account' is stated, though general positive guidance for when to reach for this vs other add_* siblings is only implied.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
calculate_bread_doughBread dough calculatorARead-onlyIdempotentInspect
Calculate a sourdough bread recipe in grams from loaf count, loaf size and hydration. Returns flour, water, starter and salt, plus a link to the same recipe on loafy.ai where the baker can adjust it and run the timers. Pizza dough is calculate_pizza_dough, and when to start a bake is plan_sourdough_bake. A value outside its range is corrected, and notes name it.
| Name | Required | Description | Default |
|---|---|---|---|
| loaves | No | How many loaves to bake. | |
| loaf_size_g | No | Flour per loaf in grams, not the dough weight: 500 g of flour makes one standard loaf of about 860 g of dough. For a loaf of a given dough weight, the flour is about 58 % of it at 60 % hydration. | |
| hydration_percent | No | Water as a percentage of flour. The book recommends around 60 % for most flours; higher is more open but stickier. | |
| whole_grain_percent | No | Share of the flour that is whole grain, the rest is bread flour. |
Output Schema
| Name | Required | Description |
|---|---|---|
| url | No | The same answer, recipe or entry on loafy.ai. |
| note | No | A remark on the whole result, such as why nothing was found. |
| tool | No | The tool that answered. |
| input | No | The arguments as the tool used them, after any correction. |
| notes | No | What was corrected or left out, such as a value outside its range. |
| ingredients | No | |
| total_dough_g | No | All the dough, in grams. |
| dough_per_loaf_g | No | The dough of one loaf, in grams. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare readOnly, idempotent, and non-destructive, so the safety profile is covered. The description still contributes non-obvious behavior: out-of-range values are silently corrected rather than rejected, and the correction is named in the notes — information an agent cannot get from the schema's min/max alone.
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?
Front-loaded with the core purpose and return values in the first sentence, then sibling routing, then edge-case behavior. Three sentences with no filler, though the loafy.ai link clause is slightly longer than it needs to be.
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?
An output schema exists, so return values need not be re-explained, and annotations cover the safety profile; the description covers purpose, alternatives, and the clamping edge case. What remains unstated — whether warnings exist for extreme hydration or how rounding is handled — is minor for a pure calculation tool.
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% and the schema already explains the flour-vs-dough-weight nuance and hydration tradeoffs in more detail than the description does. The description names three of the four inputs and omits whole_grain_percent entirely, so it adds little beyond the structured fields — baseline 3.
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 (calculate), a specific resource (sourdough bread recipe in grams), and the exact inputs driving it (loaf count, loaf size, hydration). It also enumerates the outputs (flour, water, starter, salt, recipe link), which distinguishes it unambiguously from the pizza and scheduling siblings.
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?
Explicitly routes two adjacent tasks to their siblings: pizza dough goes to calculate_pizza_dough and bake timing goes to plan_sourdough_bake. That is strong negative guidance, though it never states its own trigger condition in the same explicit when-to-use form.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
calculate_pizza_doughPizza dough calculatorARead-onlyIdempotentInspect
Calculate pizza dough in grams from the number of pizzas, the ball weight and hydration, with either fresh yeast or sourdough starter. Returns flour, water, salt, leavening and toppings, plus a link to the same recipe on loafy.ai. A loaf of bread is calculate_bread_dough. A value outside its range is corrected, and notes name it.
| Name | Required | Description | Default |
|---|---|---|---|
| oven | No | home is a domestic oven, pizza an Ooni or Roccbox, wood a wood-fired oven. | home |
| pizzas | No | How many pizzas. | |
| dough_type | No | Leavened with fresh yeast or with sourdough starter. | yeast |
| hydration_percent | No | Water as a percentage of flour. 55-65 is easy to handle, above 70 is expert. | |
| weight_per_pizza_g | No | Dough ball weight in grams. Left out, it follows the oven: 250 g home, 270 g pizza oven, 280 g wood-fired. |
Output Schema
| Name | Required | Description |
|---|---|---|
| url | No | The same answer, recipe or entry on loafy.ai. |
| note | No | A remark on the whole result, such as why nothing was found. |
| tool | No | The tool that answered. |
| input | No | The arguments as the tool used them, after any correction. |
| notes | No | What was corrected or left out, such as a value outside its range. |
| toppings | No | Toppings for all the pizzas: grams, and basil as leaves and pots. |
| ingredients | No | Flour, water, salt and the leavening (fresh yeast or starter), in grams. |
| total_dough_g | No | All the dough, in grams. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare readOnly, idempotent, and non-destructive, so the safety profile is covered. The description adds genuinely useful behavior beyond that: it enumerates the returned components (flour, water, salt, leavening, toppings) plus a recipe link, and discloses that out-of-range inputs are silently corrected and reported in notes.
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 compact sentences, front-loaded with what it computes and its outputs before the routing hint and the input-correction note. No filler or repetition of structured fields.
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?
An output schema exists, yet the description still summarizes the return shape and the recipe link, plus the correction behavior for valid ranges. Between the annotations, full schema coverage, and this text, an agent has everything needed to call it correctly.
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% with defaults, enums, and ranges already documented per-parameter (including the oven-dependent default ball weight). The description only restates the high-level inputs and adds no syntax or format detail beyond the schema, 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?
States a specific verb (calculate) and resource (pizza dough), lists the driving inputs (number of pizzas, ball weight, hydration, yeast vs sourdough), and explicitly distinguishes itself from the bread sibling: 'A loaf of bread is calculate_bread_dough.' An agent can route correctly without opening any schema.
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 clearly frames the context (gram-based dough calculation with two leavening options) and names the alternative for the adjacent use case (calculate_bread_dough). It stops short of explicit when-not guidance or exclusion against other siblings like plan_sourdough_bake, so it is clear context rather than full routing advice.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
estimate_bulk_fermentationBake Planner: bulk fermentation estimateARead-onlyIdempotentInspect
Loafy's Bake Planner. Estimate how long the bulk fermentation of a sourdough bread dough (from mixing until shaping) takes at a given dough temperature and starter amount. Returns a range from several models with each model's figure and source: Bill Wraith's rise-time model (2007/08), the Loafy bakers (his model scaled by how long the bulk fermentations Loafy's bakers logged took) and, where the book names one, the figure from The Sourdough Framework. Every time is theoretical: the dough is done when it has grown, as the result's note says. For a whole bake planned backwards from when the bread should be ready, use plan_sourdough_bake.
| Name | Required | Description | Default |
|---|---|---|---|
| salt | No | "yes" for a bread dough with about 2 % salt, "no" for a levain or the starter itself. | yes |
| starter_percent | Yes | Starter as a percentage of the flour weight: 100 g of starter on 500 g of flour is 20. | |
| dough_temperature_c | Yes | The dough's temperature in °C, measured in the dough. Convert °F: 72 °F is 22 °C. | |
| starter_hydration_percent | No | The starter's hydration in %: 100 for equal flour and water, 50 for a stiff one. |
Output Schema
| Name | Required | Description |
|---|---|---|
| url | No | The same answer, recipe or entry on loafy.ai. |
| note | No | A remark on the whole result, such as why nothing was found. |
| salt | No | Whether the dough has salt. |
| tool | No | The tool that answered. |
| input | No | The arguments as the tool used them, after any correction. |
| notes | No | What was corrected or left out, such as a value outside its range. |
| range | No | The range in words, such as "6 h 30 min to 10 h". |
| models | No | Every model that has a figure for this dough. |
| to_hours | No | The longest time any model gives: when it should be done. |
| from_hours | No | The shortest time any model gives: when to start checking the dough. |
| starter_percent | No | Starter as a share of the flour, in %. |
| dough_temperature_c | No | The dough temperature the estimate is for, in °C. |
| inoculation_percent | No | The flour already fermented, the flour in the starter, as a share of all the flour: what Bill Wraith's model counts. |
| starter_hydration_percent | No | The starter's hydration, in %. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already establish that this is a read-only, idempotent, non-destructive, closed-world calculation. The description adds useful behavioral context: the result is a range from several models, includes each model's figure and source, and the times are theoretical because dough is done when it has grown, as noted in the result.
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 purpose and scope, then adds model-source and theoretical caveats. It is somewhat long but every sentence contributes to interpretation or transparency, with no obvious 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 rich annotations, full schema descriptions, and an output schema, the remaining burden on the description is low. The description still supplies the essential caveat about theoretical times and the range-of-models return structure, making it complete for correct invocation and interpretation.
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 already documents dough_temperature_c, starter_percent, salt, and starter_hydration_percent in detail. The description mentions dough temperature and starter amount but adds little parameter detail beyond the schema, so the high-coverage baseline of 3 applies.
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: estimate bulk fermentation duration for sourdough dough from mixing until shaping, given dough temperature and starter amount. It also distinguishes itself from the sibling plan_sourdough_bake by naming that tool for whole-bake planning.
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 clearly states when to use this tool and explicitly routes the whole-bake backward-planning case to plan_sourdough_bake. The scope 'from mixing until shaping' also helps prevent use for other fermentation stages.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
find_sourdough_answerFind a sourdough answerARead-onlyIdempotentInspect
Search Loafy's library of answers to real questions from bakers, written by Hendrik Kleinwächter of The Bread Code and grounded in his book The Sourdough Framework. Returns the answers that match, each with the book chapter behind it and a link. When none matches, returns the closest passages from the book instead. The library covers starters, fermentation, dough, flour, baking and storage, and it is in English. The book itself is search_sourdough_book for passages and read_sourdough_book for a whole chapter. Without a Loafy account, reading and searching the book and the answers is limited to 3 questions a day, every lookup within 15 minutes counting as one question; with an account it has no limit. The calculators, the guides and the book's table of contents need no account.
| Name | Required | Description | Default |
|---|---|---|---|
| limit | No | How many answers to return. Defaults to 3. | |
| query | Yes | What the baker wants to know, in English, e.g. "my starter smells like vinegar". |
Output Schema
| Name | Required | Description |
|---|---|---|
| url | No | The same answer, recipe or entry on loafy.ai. |
| note | No | A remark on the whole result, such as why nothing was found. |
| tool | No | The tool that answered. |
| input | No | The arguments as the tool used them, after any correction. |
| notes | No | What was corrected or left out, such as a value outside its range. |
| answers | No | The answers that match. |
| license | No | The licence of the book's text: CC BY-SA 4.0, with attribution. |
| passages | No | When no answer matches, the closest passages from the book. |
| suggestion | No | Where to look next when nothing fits. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already cover the safety profile (readOnly, idempotent, non-destructive, closed-world), but the description adds substantial context beyond them: the no-match fallback to closest book passages, the daily quota and 15-minute dedup window, and the English-only limitation. These are exactly the behavioral traits an agent needs and cannot infer from structured fields.
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 paragraph is dense but every clause carries distinct information (source, return shape, fallback, coverage, sibling routing, quota). It is front-loaded with the core purpose, though the quota/account detail could be tightened.
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, return values need not be re-explained, yet the description still clarifies the matched-answer vs fallback-passage distinction. Combined with annotations and full schema coverage, nothing an agent needs to invoke this correctly 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 coverage is 100%, and the schema already documents both parameters, including that the query must be in English. The description only reinforces the English constraint and says nothing new about the 'limit' parameter, so the baseline 3 applies.
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 ('search') and resource ('Loafy's library of answers to real questions from bakers'), with the author and grounding source named. It explicitly distinguishes itself from the siblings that operate on the book itself (search_sourdough_book, read_sourdough_book).
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?
Explicitly routes the agent: 'The book itself is search_sourdough_book for passages and read_sourdough_book for a whole chapter.' It also states when the fallback behavior kicks in ('When none matches') and what account status allows (3 questions/day unauthenticated vs unlimited with an account).
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
get_sourdough_book_contentsContents of The Sourdough FrameworkARead-onlyIdempotentInspect
The table of contents of Hendrik Kleinwächter's open-source book The Sourdough Framework: every chapter and section with its number and each chapter's length in words. read_sourdough_book returns any of them in full. The book covers starters, fermentation, flour, hydration, shaping, baking and troubleshooting.
| Name | Required | Description | Default |
|---|---|---|---|
No parameters | |||
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare readOnlyHint, idempotentHint, and destructiveHint=false, so the safety profile is covered. The description adds valuable payload context (per-chapter word lengths, chapter/section numbering) that the annotations do not convey, though it says nothing about pagination or format of the returned structure.
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 tight sentences, front-loaded with the core purpose, then the routing hint, then the topical scope. Nothing is redundant and each sentence carries information.
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 no output schema, the description carries the burden of describing the return value and does so (chapters, sections, numbers, word counts). For a zero-param, read-only browse tool, this is sufficient.
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 tool takes zero parameters, so the baseline is 4; there are no parameter semantics for the description to compensate for.
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 resource (the table of contents of a named book) and what it contains (chapters, sections, numbers, word lengths). An agent can distinguish it from read_sourdough_book and search_sourdough_book without opening either schema.
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 sentence 'read_sourdough_book returns any of them in full' implicitly routes the agent: use this to browse/select, use read_sourdough_book to fetch full text. It names the alternative but does not state an explicit when-to-use condition or exclusion beyond that.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
get_sourdough_journey_stepLook up a journey stepARead-onlyIdempotentInspect
Look up one step of a guided journey by its id, its title or its position: its title, where it sits in the journey, its timer in minutes when the step has one, and the link that opens it. The instructions themselves are on the page, where the timer for that step runs.
| Name | Required | Description | Default |
|---|---|---|---|
| slug | Yes | Journey identifier, e.g. "sourdough-bread", or the journey's title. | |
| step | No | Step identifier (e.g. "mix"), its title, or position ("5" is the fifth step). Left out, the first step is returned. |
Output Schema
| Name | Required | Description |
|---|---|---|
| url | No | The same answer, recipe or entry on loafy.ai. |
| note | No | A remark on the whole result, such as why nothing was found. |
| step | No | |
| tool | No | The tool that answered. |
| input | No | The arguments as the tool used them, after any correction. |
| notes | No | What was corrected or left out, such as a value outside its range. |
| journey | No |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare readOnly, idempotent, and non-destructive, so the safety profile is covered. The description adds genuinely useful behavior beyond that: the returned payload shape (title, position, timer-in-minutes when present, opening link) and the key caveat that instructions live on the page, not in the response.
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?
Two sentences, purpose front-loaded, with the payload fields listed compactly. Minor redundancy between "by its id, its title or its position" and the later "its title, where it sits in the journey," but no filler sentences.
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, return values need not be enumerated, yet the description still orients the agent and explains the instructions/timer split. Complete enough for a two-parameter read tool; only the absence of explicit sibling routing holds it back.
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 already documents both parameters including the first-step default. The description restates the id/title/position addressing but adds no format or syntax detail the schema lacks; baseline 3 applies.
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 ("Look up one step of a guided journey") and enumerates the lookup keys (id, title, position). An agent can distinguish it from list_sourdough_journeys or get_sourdough_book_contents by resource, though no sibling is named explicitly.
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 implies usage by explaining that the step can be addressed by id, title, or position, and that omitting it returns the first step (via the schema). It never states when to prefer this over start_sourdough_journey or list_sourdough_journeys, so the selection guidance is only implied.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
list_my_bakesMy Loafy bake journalARead-onlyIdempotentInspect
The baker's own bakes from their Loafy bake journal, newest first: what was baked and when, the recipe figures, rating, problems and notes, each with its id and a link. A new bake is log_bake, a change to one is update_bake with its id. Needs the baker's Loafy account.
| Name | Required | Description | Default |
|---|---|---|---|
| limit | No | How many bakes, newest first. | |
| bake_type | No | Only bakes of this kind, e.g. sourdough_bread or pizza. |
Output Schema
| Name | Required | Description |
|---|---|---|
| url | No | The same answer, recipe or entry on loafy.ai. |
| note | No | A remark on the whole result, such as why nothing was found. |
| tool | No | The tool that answered. |
| bakes | No | Newest first. |
| input | No | The arguments as the tool used them, after any correction. |
| notes | No | What was corrected or left out, such as a value outside its range. |
| in_journal | No | All bakes in the journal. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare this is a read-only, idempotent, non-destructive, non-open-world operation. The description adds useful context beyond annotations: newest-first ordering, returned fields including id and link, and the requirement for the baker's Loafy account.
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 short, front-loaded, and composed of three purposeful sentences. It avoids repetition and includes only information that helps an agent understand the tool's role and prerequisites.
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 simple two-parameter read operation, existing annotations, and output schema, the description supplies everything an agent needs: purpose, ordering, alternatives, account requirement, and a sense of returned data. No critical context 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%, with both limit and bake_type documented in the schema, including the enum for bake types. The description reinforces newest-first ordering but adds no meaningful constraints beyond what the schema already provides, so the baseline 3 applies.
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 clearly identifies the resource as the baker's own Loafy bake journal entries, specifies ordering (newest first), and summarizes the returned fields. It distinguishes the read/list operation from the sibling write tools log_bake and update_bake.
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 explicitly routes new bakes to log_bake and changes to update_bake with an id, making the read-only listing role clear. The account prerequisite is also stated, leaving little ambiguity about when this tool applies.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
list_my_containersMy Loafy containersARead-onlyIdempotentInspect
The baker's own containers in Loafy: name and empty weight in grams, which Loafy takes off when dough is weighed in them, with notes, each with its id and a link. A new container is add_container, a change to one is update_container. Needs the baker's Loafy account.
| Name | Required | Description | Default |
|---|---|---|---|
No parameters | |||
Output Schema
| Name | Required | Description |
|---|---|---|
| url | No | The same answer, recipe or entry on loafy.ai. |
| note | No | A remark on the whole result, such as why nothing was found. |
| tool | No | The tool that answered. |
| input | No | The arguments as the tool used them, after any correction. |
| notes | No | What was corrected or left out, such as a value outside its range. |
| containers | No | By name. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare readOnlyHint, idempotentHint, destructiveHint=false, and openWorldHint=false. The description adds real context beyond them: the empty-weight tare semantics ('which Loafy takes off when dough is weighed in them') and the account prerequisite.
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?
Compact at three sentences, with the resource and its fields leading before the sibling routing and the auth note. The first sentence is dense and slightly run-on, but nothing is wasted.
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, return structure need not be restated; the description still covers purpose, sibling routing, tare behavior, and the Loafy-account requirement. No notable gap remains for a parameterless read tool.
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?
Zero parameters, so the baseline is 4. The description uses the space to characterize the returned record shape (id, link, notes, weight in grams), which is useful even though an output schema exists.
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?
Names a specific resource ('the baker's own containers in Loafy') and enumerates the payload fields (name, empty weight in grams, notes, id, link). It is clearly distinguishable from list_my_bakes and list_my_starters by both scope and content.
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?
Explicitly routes related operations: 'A new container is add_container, a change to one is update_container.' That covers the create/update alternatives, but there is no statement of when this list is the right call versus other list tools or any exclusion condition.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
list_my_startersMy Loafy startersARead-onlyIdempotentInspect
The baker's own sourdough starters in Loafy: name, birthday and age, notes and story, how many bakes each went into and when last, each with its id and a link. A new starter is add_starter, a change to one is update_starter. Needs the baker's Loafy account.
| Name | Required | Description | Default |
|---|---|---|---|
No parameters | |||
Output Schema
| Name | Required | Description |
|---|---|---|
| url | No | The same answer, recipe or entry on loafy.ai. |
| note | No | A remark on the whole result, such as why nothing was found. |
| tool | No | The tool that answered. |
| input | No | The arguments as the tool used them, after any correction. |
| notes | No | What was corrected or left out, such as a value outside its range. |
| starters | No | By name. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare the safe read profile (readOnly, idempotent, non-destructive, closed-world), so the description only needs to add context. It does: the tool is scoped to the baker's own starters (not community/shared ones) and it discloses the auth prerequisite, 'Needs the baker's Loafy account.' It adds no rate-limit or freshness/pagination detail, but that is minor here.
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?
Front-loaded with the resource and its contents, then alternatives, then the auth note. The field enumeration is slightly long but each item is substantive information for selection, no filler sentences.
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?
An output schema exists, so return values need not be explained, and the annotations fully cover the safety profile. Combined with the stated auth requirement and the sibling routing, an agent has everything needed to select and call this correctly.
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 tool takes zero parameters, so there is nothing for the description to disambiguate and the schema coverage is moot. Baseline for a 0-param tool applies.
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+resource (the baker's own sourdough starters) and enumerates exactly what each entry contains: name, birthday/age, notes/story, bake counts, timestamps, id and link. It is immediately distinguishable from sibling readers like list_my_bakes or list_my_containers.
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?
Explicitly routes the agent to the mutation siblings: 'A new starter is add_starter, a change to one is update_starter.' This makes the read-vs-write boundary clear, though it never states an explicit 'use this when you need to view starters' condition or any exclusion.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
list_sourdough_journeysList guided journeysARead-onlyIdempotentInspect
List Loafy's guided sourdough journeys: making a starter, baking a loaf, scoring, and more. Each one is a timed, step-by-step walkthrough on loafy.ai. Returns each journey's slug, title, duration, difficulty, number of steps and link.
| Name | Required | Description | Default |
|---|---|---|---|
No parameters | |||
Output Schema
| Name | Required | Description |
|---|---|---|
| url | No | The same answer, recipe or entry on loafy.ai. |
| note | No | A remark on the whole result, such as why nothing was found. |
| tool | No | The tool that answered. |
| input | No | The arguments as the tool used them, after any correction. |
| notes | No | What was corrected or left out, such as a value outside its range. |
| journeys | No | Every guided journey. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already establish that this is a read-only, idempotent, non-destructive operation. The description adds useful domain context that journeys are timed step-by-step walkthroughs, but the return-field list largely duplicates the output schema and it does not discuss ordering or result limits.
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?
Two tight sentences front-load the purpose and then describe the return shape. Every clause carries useful information with 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?
For a zero-parameter list tool with rich annotations and an output schema, the description is sufficiently complete. It explains what the collection contains and what each result provides.
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 tool takes no parameters, so there are no parameter semantics to clarify. This earns the baseline score for zero-parameter tools.
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 names a specific verb and resource: listing Loafy's guided sourdough journeys. It also gives examples of journeys and summarizes the returned fields, making it clearly distinguishable from siblings like get_sourdough_journey_step or start_sourdough_journey.
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 listing purpose implies when to use it: discovering available guided journeys. However, it does not explicitly compare against alternatives such as get_sourdough_journey_step or start_sourdough_journey, so the guidance is implied rather than stated.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
log_bakeAdd a bake to my Loafy journalAInspect
Add a bake to the baker's Loafy bake journal: what was baked and when, the recipe figures, how it went and what to try next time. Returns the new entry with a link, where photos are added. The same bake sent again within two minutes returns the first entry instead of a second one, and a bake already in the journal changes with update_bake. Needs the baker's Loafy account.
| Name | Required | Description | Default |
|---|---|---|---|
| notes | No | How the bake went, in the baker's words: only what no other parameter takes. | |
| flours | No | The flours, comma-separated, each as its kind and grams, such as "bread_flour 450, rye 50", or its kind alone when no grams were given; kinds: bread_flour, all_purpose, whole_wheat, rye, spelt, einkorn, durum, tipo_00, other. | |
| pieces | No | How many pieces the dough was divided into: loaves, rolls or pizza balls. | |
| rating | No | How it turned out, 1 to 5 stars. | |
| starter | No | The name of the baker's starter that went in, if any. | |
| baked_on | No | The day of the bake, as YYYY-MM-DD; today if left out. | |
| pre_rest | No | That rest: an autolyse, flour and water only, or a fermentolyse, with the starter in. | |
| problems | No | What went wrong, comma-separated, from: dense_crumb, gummy_interior, no_oven_spring, flat_loaf, burnt_crust, pale_crust, bland_flavor, too_sour, didnt_rise, sticky_dough; anything else goes in the notes. | |
| bake_type | No | What was baked. | sourdough_bread |
| bake_level | No | On a stove: the dial's level while baking. | |
| bulk_hours | No | Hours of bulk fermentation. | |
| loaf_shape | No | How a sourdough bread was shaped: boule (round) or batard (oval). A baguette or a loaf pan bread is a bake_type of its own. | |
| ph_readings | No | What the baker's pH meter read, comma-separated, each as its step and value, such as "end_of_bulk 4.1, starter_ready 4.2"; steps: starter_ready, mixing, end_of_bulk, shaping, before_proof, after_proof, after_bake. A change names only the steps it adds or corrects; the others keep their readings. | |
| bake_minutes | No | Minutes in the oven, whole minutes (90 seconds is 2); with two phases, the first. | |
| salt_percent | No | Salt as a percentage of flour. | |
| baking_method | No | What it was baked in: home_oven also for a Dutch oven, a stone or a tray in it. | |
| preheat_level | No | On a stove: the dial's level while the pan heated. | |
| next_time_notes | No | What to try differently next time. | |
| starter_percent | No | Starter as a percentage of flour. | |
| autolyse_minutes | No | Minutes the flour and water rested before mixing, with the starter in for a fermentolyse. | |
| bake_temp_celsius | No | Oven temperature in °C; with two phases, the first (in a Dutch oven, with the lid on). A value above 300 °C is only plausible in a pizza or wood-fired oven. | |
| bulk_temp_celsius | No | Dough or room temperature during bulk, in °C. | |
| dry_yeast_percent | No | Dry or instant yeast as a percentage of flour. | |
| hydration_percent | No | Water as a percentage of flour. | |
| dough_rise_percent | No | How much the dough grew during bulk fermentation, in percent. | |
| fridge_proof_hours | No | Hours the shaped dough proofed in the fridge. | |
| piece_weight_grams | No | What one piece weighed when it was divided, in grams. | |
| proof_rise_percent | No | How much more the shaped dough grew during the proof, in percent. | |
| stretch_fold_count | No | Sets of stretch and folds during bulk. | |
| fresh_yeast_percent | No | Fresh yeast as a percentage of flour. | |
| second_bake_minutes | No | Minutes of that second phase, whole minutes. | |
| preheat_temp_celsius | No | How hot the oven was preheated, in °C. A value above 300 °C is only plausible in a pizza or wood-fired oven. | |
| room_temp_proof_hours | No | Hours the shaped dough proofed at room temperature. | |
| second_bake_temp_celsius | No | Oven temperature in °C of a second phase: with the lid off, or turned down. A value above 300 °C is only plausible in a pizza or wood-fired oven. | |
| other_bake_type_description | No | What was baked, in the baker's words, when bake_type is other. |
Output Schema
| Name | Required | Description |
|---|---|---|
| url | No | The same answer, recipe or entry on loafy.ai. |
| bake | No | A bake in the baker's journal. |
| card | No | The figures the bake card in Claude shows (ui://loafy/bake-card). |
| note | No | A remark on the whole result, such as why nothing was found. |
| tool | No | The tool that answered. |
| input | No | The arguments as the tool used them, after any correction. |
| notes | No | What was corrected or left out, such as a value outside its range. |
| saved | No | What was saved, in one sentence. |
| photos | No | Where photos are added. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare readOnlyHint=false, destructiveHint=false, openWorldHint=false, so the safety profile is covered; the description adds real value on top by disclosing the account requirement, the two-minute duplicate-suppression window (a nuance beyond idempotentHint=false), and that the response carries a link where photos are added. It stops short of describing failure behavior for malformed or rejected fields, which keeps it at 4 rather than 5.
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 tight sentences that front-load the action, then layer in return value, duplicate handling with the named alternative, and the auth prerequisite. No filler and no repetition of schema detail; each sentence carries a distinct decision the agent needs.
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 35 optional parameters, full schema coverage, an output schema, and annotations, the description covers the identity, dedupe semantics, alternative tool, and prerequisite well. The one gap is that it never notes that everything is optional or what the minimum viable entry looks like (e.g., bake_type defaulting to sourdough_bread), which would help an agent decide how much to fill in.
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% across all 35 properties, including enum values, ranges, and units, so the schema does the heavy lifting and the baseline is 3. The description only loosely groups the fields ("what was baked and when, the recipe figures, how it went and what to try next time") without adding syntax, defaults, or precedence rules beyond what the schema states.
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?
Starts with a specific verb+resource ("Add a bake to the baker's Loafy bake journal") and immediately scopes what an entry contains: what was baked and when, recipe figures, how it went, what to try next. It also explicitly distinguishes itself from update_bake, so an agent can tell creation from amendment without opening either schema.
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?
Names the alternative and the condition that selects it: "a bake already in the journal changes with update_bake." It also states the duplicate-send rule ("the same bake sent again within two minutes returns the first entry instead of a second one") and the prerequisite ("Needs the baker's Loafy account"), leaving little to inference.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
plan_sourdough_bakeBake PlannerARead-onlyIdempotentInspect
Loafy's Bake Planner. Plan a sourdough bake backwards from when the bread should come out of the oven: when to feed the starter, mix, shape, proof in the fridge, preheat and bake, and how much starter suits the kitchen's temperature according to The Sourdough Framework. Returns the times and a link to the same plan in the Bake Planner on loafy.ai. The time is the baker's local date and time, such as 2026-10-24T10:00. The amounts of flour, water and starter are calculate_bread_dough; how long bulk fermentation takes at a given dough temperature and starter amount is estimate_bulk_fermentation.
| Name | Required | Description | Default |
|---|---|---|---|
| ready_at | Yes | When the bread should come out of the oven, as the baker's local date and time, e.g. "2026-10-24T10:00". | |
| bulk_hours | No | Hours of bulk fermentation, if the baker knows their dough. Without it, the book's figure for the kitchen's temperature. | |
| cold_proof_hours | No | Hours the shaped loaf proofs in the fridge. The book says 8 to 12. | |
| kitchen_temperature_c | No | Kitchen temperature in °C, which sets how much starter to use. |
Output Schema
| Name | Required | Description |
|---|---|---|
| url | No | The same answer, recipe or entry on loafy.ai. |
| note | No | A remark on the whole result, such as why nothing was found. |
| tool | No | The tool that answered. |
| input | No | The arguments as the tool used them, after any correction. |
| notes | No | What was corrected or left out, such as a value outside its range. |
| steps | No | The bake, step by step, in order. |
| starter | No | |
| ready_at | No | When the bread comes out of the oven. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare read-only, idempotent, non-destructive behavior, so the description's remaining job is to add context — it does, disclosing the planning method (backwards from ready_at, per The Sourdough Framework), the returned artifact, and a link to the web plan. It doesn't discuss edge cases such as infeasible timelines or how out-of-range inputs are handled, which keeps it from a 5.
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?
Purpose and scope are front-loaded in the first sentence, and the final sentence is a useful routing pointer rather than filler. Minor redundancy in restating the product name twice ('Loafy's Bake Planner' / 'Bake Planner on loafy.ai').
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, annotations covering the safety profile, and full parameter coverage, an agent has everything needed: what it computes, which inputs matter, what comes back, and which siblings cover the adjacent calculations.
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 all four parameters are already documented, and the description largely restates the ready_at local-time convention already in the schema. It adds a small amount of framing (kitchen temperature driving starter amount) but no new syntax or fallback semantics beyond what the schema states.
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 — 'Plan a sourdough bake backwards from when the bread should come out of the oven' — and enumerates the milestones produced (feed, mix, shape, cold proof, preheat, bake). It explicitly differentiates from siblings by assigning dough amounts to calculate_bread_dough and bulk timing to estimate_bulk_fermentation.
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?
Names both alternatives and the exact condition that selects them: amounts go to calculate_bread_dough, bulk duration at a given dough temperature goes to estimate_bulk_fermentation. An agent knows when this tool is the right one and where to hand off the sub-questions.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
read_sourdough_bookRead The Sourdough FrameworkARead-onlyIdempotentInspect
Read a chapter or section of Hendrik Kleinwächter's open-source book The Sourdough Framework in full, by its number from get_sourdough_book_contents or by its title. Returns the text with its chapter, link and licence; a chapter longer than about 40,000 characters comes in pages. Without a Loafy account, reading and searching the book and the answers is limited to 3 questions a day, every lookup within 15 minutes counting as one question; with an account it has no limit. The calculators, the guides and the book's table of contents need no account.
| Name | Required | Description | Default |
|---|---|---|---|
| page | No | Which page of a long chapter. Most parts have one. | |
| part | Yes | A chapter or section: its number from get_sourdough_book_contents, e.g. "8" or "8.3", or its title, e.g. "Bulk fermentation". |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Despite annotations covering the safety profile, the description adds substantial context: the return payload (chapter text with link and licence), the ~40,000-character pagination rule, and detailed rate limits (3 questions/day unauthenticated, 15-minute coalescing window, unlimited with an account, exempt calculators/guides/TOC). This is exactly what an agent needs to avoid surprise throttling.
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?
Front-loads the core action and return behavior, then adds operational constraints. Mostly every sentence earns its place, though the account/limit clause is dense enough to be slightly effortful in one breath.
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 no output schema, the description still explains what comes back, how long chapters paginate, and the auth/rate-limit environment. Nothing material for a 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?
Schema description coverage is 100% and already documents both 'part' (number or title) and 'page'. The description restates the same semantics without adding syntax or edge-case detail beyond what the schema provides, so baseline 3 applies.
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 (read) and resource (a chapter/section of a named book), plus the scope 'in full'. It clearly separates itself from search_sourdough_book and get_sourdough_book_contents by naming the latter as the source of valid part numbers.
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?
Tells the agent to obtain the part identifier from get_sourdough_book_contents and implies reading versus searching (mentioning search limits alongside). It gives clear context for when to use this tool but never explicitly names search_sourdough_book as the alternative for lookup-style access.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
search_sourdough_bookSearch The Sourdough FrameworkARead-onlyIdempotentInspect
Search Hendrik Kleinwächter's open-source book The Sourdough Framework and get the passages that answer a question, each with its chapter, a link and the part of the book it comes from, which read_sourdough_book returns in full. The book covers starters, fermentation, flour, hydration, shaping, baking and troubleshooting. It is written in English, and the search matches English words. Hendrik's published answers to common questions are find_sourdough_answer, and a whole chapter is read_sourdough_book. Without a Loafy account, reading and searching the book and the answers is limited to 3 questions a day, every lookup within 15 minutes counting as one question; with an account it has no limit. The calculators, the guides and the book's table of contents need no account.
| Name | Required | Description | Default |
|---|---|---|---|
| limit | No | How many passages to return. Defaults to 3. | |
| query | Yes | What to look up, in English, e.g. "starter smells like acetone" or "bulk fermentation temperature". |
Output Schema
| Name | Required | Description |
|---|---|---|
| url | No | The same answer, recipe or entry on loafy.ai. |
| note | No | A remark on the whole result, such as why nothing was found. |
| tool | No | The tool that answered. |
| input | No | The arguments as the tool used them, after any correction. |
| notes | No | What was corrected or left out, such as a value outside its range. |
| license | No | The licence of the book's text: CC BY-SA 4.0, with attribution. |
| passages | No | The passages that answer the question. |
| suggestion | No | Where to look next when nothing fits. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations declare readOnly/idempotent/non-destructive, and the description adds substantial context beyond them: per-day question quotas, the account/no-account distinction, and which resources are free. This is the rare case where the prose meaningfully extends the safety profile.
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 dense but front-loaded with the core purpose before the alternatives and quota caveats. Almost every sentence earns its place, though the quota details could be tightened slightly.
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, return values need not be documented yet are described anyway. Alternatives, language constraints, and access limits are all covered, leaving nothing material an agent needs 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 coverage is 100%, so the baseline is 3, but the description adds the constraint that the book and matching are English-only, which informs how the query parameter should be phrased. The limit parameter is left to the schema, so it does not reach a full 5.
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 (search) and resource (The Sourdough Framework book) and describes the return shape (passages with chapter, link, source part). It explicitly distinguishes itself from read_sourdough_book (returns full chapter) and find_sourdough_answer (published answers), so an agent can select it without opening another schema.
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?
Provides explicit routing: use read_sourdough_book for full chapters and find_sourdough_answer for published answers. It also states when access is limited (3 questions/day without a Loafy account, 15-minute window counting as one question) and what needs no account, which is exactly the operational context an agent needs.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
start_sourdough_journeyStart a guided journeyARead-onlyIdempotentInspect
Start one of Loafy's guided journeys and get the link that opens it at the first step. The journey runs on loafy.ai, where each fold, proof and bake is timed for the baker.
| Name | Required | Description | Default |
|---|---|---|---|
| slug | Yes | Journey identifier from list_sourdough_journeys, e.g. "sourdough-bread", or the journey's title. |
Output Schema
| Name | Required | Description |
|---|---|---|
| url | No | The same answer, recipe or entry on loafy.ai. |
| note | No | A remark on the whole result, such as why nothing was found. |
| tool | No | The tool that answered. |
| input | No | The arguments as the tool used them, after any correction. |
| notes | No | What was corrected or left out, such as a value outside its range. |
| journey | No | |
| first_step | No |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare readOnly, idempotent, non-destructive, closed-world behavior, so the safety profile is covered. The description adds that the result is a link anchored at the first step and that the journey is time-driven on loafy.ai, which is useful context but not deep behavioral disclosure (no note on what starting actually creates or whether the link expires).
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?
Two short sentences, front-loaded with the action and the returned link. The closing clause about folds, proof and bake being 'timed for the baker' is atmospheric rather than operational, slightly diluting an otherwise tight description.
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, the description needn't explain return values, and annotations carry the safety profile, so the essentials are covered. The remaining gap is routing guidance versus the journey-step and journey-list siblings, which an agent must infer.
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% for the single required 'slug' parameter, and the schema itself tells the agent where the slug comes from (list_sourdough_journeys) and gives an example. The description adds nothing about the parameter, so the baseline 3 applies.
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 ('Start one of Loafy's guided journeys') and even describes the returned artifact ('the link that opens it at the first step'), so the action is unambiguous. It does not, however, explicitly differentiate itself from sibling get_sourdough_journey_step or list_sourdough_journeys, so it stops short of a 5.
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?
Usage is only implied: an agent can infer you call this to begin a journey rather than read a step, but the description never says when to prefer this over get_sourdough_journey_step or plan_sourdough_bake. The prerequisite (obtain a slug from list_sourdough_journeys) appears only in the schema, not the description.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
update_bakeChange a bake in my Loafy journalADestructiveIdempotentInspect
Change a bake in the baker's Loafy bake journal, by its id from list_my_bakes or log_bake: only the figures and notes given change, the rest stays, and a text given replaces the old text. No bake is deleted. Returns the bake with a link. Needs the baker's Loafy account.
| Name | Required | Description | Default |
|---|---|---|---|
| id | Yes | The bake's id, from list_my_bakes or log_bake. | |
| notes | No | How the bake went, in the baker's words: only what no other parameter takes. | |
| flours | No | The flours, comma-separated, each as its kind and grams, such as "bread_flour 450, rye 50", or its kind alone when no grams were given; kinds: bread_flour, all_purpose, whole_wheat, rye, spelt, einkorn, durum, tipo_00, other. | |
| pieces | No | How many pieces the dough was divided into: loaves, rolls or pizza balls. | |
| rating | No | How it turned out, 1 to 5 stars. | |
| starter | No | The name of the baker's starter that went in, if any. | |
| baked_on | No | The day of the bake, as YYYY-MM-DD. | |
| pre_rest | No | That rest: an autolyse, flour and water only, or a fermentolyse, with the starter in. | |
| problems | No | What went wrong, comma-separated, from: dense_crumb, gummy_interior, no_oven_spring, flat_loaf, burnt_crust, pale_crust, bland_flavor, too_sour, didnt_rise, sticky_dough; anything else goes in the notes. | |
| bake_type | No | What was baked. | |
| bake_level | No | On a stove: the dial's level while baking. | |
| bulk_hours | No | Hours of bulk fermentation. | |
| loaf_shape | No | How a sourdough bread was shaped: boule (round) or batard (oval). A baguette or a loaf pan bread is a bake_type of its own. | |
| ph_readings | No | What the baker's pH meter read, comma-separated, each as its step and value, such as "end_of_bulk 4.1, starter_ready 4.2"; steps: starter_ready, mixing, end_of_bulk, shaping, before_proof, after_proof, after_bake. A change names only the steps it adds or corrects; the others keep their readings. | |
| bake_minutes | No | Minutes in the oven, whole minutes (90 seconds is 2); with two phases, the first. | |
| salt_percent | No | Salt as a percentage of flour. | |
| baking_method | No | What it was baked in: home_oven also for a Dutch oven, a stone or a tray in it. | |
| preheat_level | No | On a stove: the dial's level while the pan heated. | |
| next_time_notes | No | What to try differently next time. | |
| starter_percent | No | Starter as a percentage of flour. | |
| autolyse_minutes | No | Minutes the flour and water rested before mixing, with the starter in for a fermentolyse. | |
| bake_temp_celsius | No | Oven temperature in °C; with two phases, the first (in a Dutch oven, with the lid on). A value above 300 °C is only plausible in a pizza or wood-fired oven. | |
| bulk_temp_celsius | No | Dough or room temperature during bulk, in °C. | |
| dry_yeast_percent | No | Dry or instant yeast as a percentage of flour. | |
| hydration_percent | No | Water as a percentage of flour. | |
| dough_rise_percent | No | How much the dough grew during bulk fermentation, in percent. | |
| fridge_proof_hours | No | Hours the shaped dough proofed in the fridge. | |
| piece_weight_grams | No | What one piece weighed when it was divided, in grams. | |
| proof_rise_percent | No | How much more the shaped dough grew during the proof, in percent. | |
| stretch_fold_count | No | Sets of stretch and folds during bulk. | |
| fresh_yeast_percent | No | Fresh yeast as a percentage of flour. | |
| second_bake_minutes | No | Minutes of that second phase, whole minutes. | |
| preheat_temp_celsius | No | How hot the oven was preheated, in °C. A value above 300 °C is only plausible in a pizza or wood-fired oven. | |
| room_temp_proof_hours | No | Hours the shaped dough proofed at room temperature. | |
| second_bake_temp_celsius | No | Oven temperature in °C of a second phase: with the lid off, or turned down. A value above 300 °C is only plausible in a pizza or wood-fired oven. | |
| other_bake_type_description | No | What was baked, in the baker's words, when bake_type is other. |
Output Schema
| Name | Required | Description |
|---|---|---|
| url | No | The same answer, recipe or entry on loafy.ai. |
| bake | No | A bake in the baker's journal. |
| card | No | The figures the bake card in Claude shows (ui://loafy/bake-card). |
| note | No | A remark on the whole result, such as why nothing was found. |
| tool | No | The tool that answered. |
| input | No | The arguments as the tool used them, after any correction. |
| notes | No | What was corrected or left out, such as a value outside its range. |
| saved | No | What was saved, in one sentence. |
| photos | No | Where photos are added. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Goes well beyond the annotations: it declares partial-update semantics ('only the figures and notes given change, the rest stays'), string replacement behavior, that nothing is deleted, that a link is returned, and that the baker's account is required for auth. There is mild tension with destructiveHint=true, but 'a text given replaces the old text' is a real field-level overwrite, so the two are reconcilable rather than contradictory.
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?
Front-loaded with verb and resource, then the id source, then update semantics, then return value and auth requirement in one tight sentence each. Every clause carries new information and nothing is repeated from the title.
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 36-parameter mutation, the description covers the essentials an agent needs: how to identify the target, that unspecified fields survive, that field text is overwritten, and that output includes a link (the output schema covers the rest). It leaves validation constraints entirely to the schema, which is acceptable at 100% coverage.
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 baseline is 3, and the description earns a bump by explaining merge-vs-replace semantics for the 36 parameters as a whole, which the schema documents per-field but not as a policy. It doesn't enumerate individual fields, but that would be wasteful given the schema.
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 (change) on a specific resource (a bake in the Loafy bake journal) identified by id, and names where ids come from (list_my_bakes or log_bake). This separates it cleanly from log_bake and list_my_bakes among the siblings.
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: use this on an existing bake whose id came from list_my_bakes or log_bake, i.e. after logging. It doesn't state explicit when-not conditions (e.g. use log_bake to create a new bake instead of updating), but the create-vs-update split is strongly implied by the id requirement.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
update_containerChange a container in LoafyADestructiveIdempotentInspect
Change one of the baker's containers, by its id from list_my_containers: only the name, weight or notes given change, and a text given replaces the old text. No container is deleted. Needs the baker's Loafy account.
| Name | Required | Description | Default |
|---|---|---|---|
| id | Yes | The container's id, from list_my_containers or add_container. | |
| name | No | The container's name, e.g. "Glass bowl". | |
| notes | No | Notes on the container. | |
| weight_grams | No | The empty container's weight in grams. |
Output Schema
| Name | Required | Description |
|---|---|---|
| url | No | The same answer, recipe or entry on loafy.ai. |
| note | No | A remark on the whole result, such as why nothing was found. |
| tool | No | The tool that answered. |
| input | No | The arguments as the tool used them, after any correction. |
| notes | No | What was corrected or left out, such as a value outside its range. |
| saved | No | What was saved, in one sentence. |
| container | No | One of the baker's containers. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations declare destructiveHint=true and idempotentHint=true, and the description adds the crucial nuance: only supplied fields change, a supplied text overwrites the old text, and no container itself is deleted. It also states the authentication requirement (the baker's Loafy account), which annotations do not cover.
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?
Compact and front-loaded, leading with the verb and the id source before the update semantics. The phrasing of 'a text given replaces the old text' is slightly clumsy, but every clause carries information.
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 safety hints, the description supplies what remains: partial-update behavior, overwrite semantics, no-deletion guarantee, and auth needs. The mild tension between 'No container is deleted' and destructiveHint=true could have been disambiguated further (e.g., that notes text is the thing lost).
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 baseline is 3, but the description adds real semantics beyond the field list: unspecified fields are left untouched and supplied text replaces existing text. It maps loosely to name/weight/notes ('weight' for weight_grams), though it never gives id or unit/range detail beyond the schema.
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 ('Change') and resource ('one of the baker's containers'), and scopes it by id sourced from list_my_containers. The partial-update phrasing ('only the name, weight or notes given change') and 'No container is deleted' clearly separate it from add_container and any delete semantics.
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?
Usage is implied rather than stated: use this to modify an existing container whose id comes from list_my_containers or add_container. There is no explicit when-not guidance and no alternative named (e.g., add_container for new containers), so the agent must infer the boundary.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
update_starterChange a starter in LoafyADestructiveIdempotentInspect
Change one of the baker's starters, by its id from list_my_starters: only the name, birthday, notes or story given change, and a text given replaces the old text. No starter is deleted. Needs the baker's Loafy account.
| Name | Required | Description | Default |
|---|---|---|---|
| id | Yes | The starter's id, from list_my_starters or add_starter. | |
| name | No | The starter's name. | |
| notes | No | Notes on the starter, e.g. its flour and how it is fed. | |
| story | No | Where the starter comes from, in the baker's words. | |
| birthday | No | The day the starter was started, as YYYY-MM-DD. |
Output Schema
| Name | Required | Description |
|---|---|---|
| url | No | The same answer, recipe or entry on loafy.ai. |
| note | No | A remark on the whole result, such as why nothing was found. |
| tool | No | The tool that answered. |
| input | No | The arguments as the tool used them, after any correction. |
| notes | No | What was corrected or left out, such as a value outside its range. |
| saved | No | What was saved, in one sentence. |
| starter | No | One of the baker's starters. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare this is a non-readonly, idempotent, destructive update, and the description adds useful behavior: only the supplied fields change, provided text replaces old text, no starter is deleted, and a Loafy account is required. The deletion statement clarifies entity preservation but does not fully explain the destructiveHint nuance around overwriting text.
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 one compact sentence, front-loaded with the action and resource. Every clause contributes scope, field behavior, or prerequisite information without waste.
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 a low-complexity update tool, a fully described schema, rich annotations, and an output schema, the description covers the remaining agent-relevant details: id source, partial-update semantics, replacement behavior, no deletion, and account requirement.
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 all five parameters are already documented. The description adds meaning beyond the schema by saying the id comes from list_my_starters and that unchanged fields remain untouched, while provided text replaces existing text.
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 names a specific verb and resource: changing a starter, identified by id from list_my_starters. It also scopes exactly which fields can change, so an agent can distinguish it from add_starter and list_my_starters.
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 tells the agent where the id comes from (list_my_starters) and states the account prerequisite. It clearly implies use for modifying an existing starter, but it does not explicitly name when to prefer a sibling tool or when not to use this one.
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.
3 tool updates
- Changed
list_my_bakes1 field changed- added
Output schema / properties / bakes / items / properties / ph_readingsAdded value: +{ + "description": "What the baker's pH meter read, in the order of the dough's day.", + "items": { + "properties": { + "step": { + "description": "Where it was read, such as starter_ready or end_of_bulk.", + "type": "string" + }, + "value": { + "description": "The pH.", + "type": "number" + } + }, + "type": "object" + }, + "type": "array" +}
- Changed
log_bake2 fields changed- added
Input schema / properties / ph_readingsAdded value: +{ + "description": "What the baker's pH meter read, comma-separated, each as its step and value, such as \"end_of_bulk 4.1, starter_ready 4.2\"; steps: starter_ready, mixing, end_of_bulk, shaping, before_proof, after_proof, after_bake. A change names only the steps it adds or corrects; the others keep their readings.", + "type": "string" +} - added
Output schema / properties / bake / properties / ph_readingsAdded value: +{ + "description": "What the baker's pH meter read, in the order of the dough's day.", + "items": { + "properties": { + "step": { + "description": "Where it was read, such as starter_ready or end_of_bulk.", + "type": "string" + }, + "value": { + "description": "The pH.", + "type": "number" + } + }, + "type": "object" + }, + "type": "array" +}
- Changed
update_bake2 fields changed- added
Input schema / properties / ph_readingsAdded value: +{ + "description": "What the baker's pH meter read, comma-separated, each as its step and value, such as \"end_of_bulk 4.1, starter_ready 4.2\"; steps: starter_ready, mixing, end_of_bulk, shaping, before_proof, after_proof, after_bake. A change names only the steps it adds or corrects; the others keep their readings.", + "type": "string" +} - added
Output schema / properties / bake / properties / ph_readingsAdded value: +{ + "description": "What the baker's pH meter read, in the order of the dough's day.", + "items": { + "properties": { + "step": { + "description": "Where it was read, such as starter_ready or end_of_bulk.", + "type": "string" + }, + "value": { + "description": "The pH.", + "type": "number" + } + }, + "type": "object" + }, + "type": "array" +}
2 tool updates
- Changed
log_bake1 field changed- added
Input schema / properties / loaf_shapeAdded value: +{ + "description": "How a sourdough bread was shaped: boule (round) or batard (oval). A baguette or a loaf pan bread is a bake_type of its own.", + "enum": [ + "boule", + "batard" + ], + "type": "string" +}
- Changed
update_bake1 field changed- added
Input schema / properties / loaf_shapeAdded value: +{ + "description": "How a sourdough bread was shaped: boule (round) or batard (oval). A baguette or a loaf pan bread is a bake_type of its own.", + "enum": [ + "boule", + "batard" + ], + "type": "string" +}
1 tool update
- Changed
estimate_bulk_fermentation3 fields changed- added
Output schema / properties / models / items / properties / bakersAdded value: +{ + "description": "The bakers behind the Loafy bakers' figure.", + "type": "integer" +} - changed
Output schema / properties / models / items / properties / bakes / descriptionPrevious value: -"The bakes behind the baker's own figure."New value: +"The bakes behind the Loafy bakers' or the baker's own figure." - changed
Output schema / properties / models / items / properties / model / descriptionPrevious value: -"wraith, book or journal."New value: +"wraith, bakers, book or journal."
3 tool updates
- Changed
list_my_bakes20 fields changed- added
Output schema / properties / bakes / items / properties / autolyse_minutesAdded value: +{ + "description": "Minutes of rest before mixing.", + "type": "integer" +} - added
Output schema / properties / bakes / items / properties / bake_levelAdded value: +{ + "description": "A stove's dial while baking.", + "type": "integer" +} - changed
Output schema / properties / bakes / items / properties / bake_minutes / descriptionPrevious value: -"Minutes in the oven."New value: +"Minutes in the oven; with two phases, the first." - changed
Output schema / properties / bakes / items / properties / bake_temp_celsius / descriptionPrevious value: -"Oven temperature, °C."New value: +"Oven temperature, °C; with two phases, the first." - added
Output schema / properties / bakes / items / properties / baking_methodAdded value: +{ + "description": "What it was baked in.", + "type": "string" +} - added
Output schema / properties / bakes / items / properties / dough_rise_percentAdded value: +{ + "description": "How much the dough grew in bulk, %.", + "type": "integer" +} - added
Output schema / properties / bakes / items / properties / dry_yeast_percentAdded value: +{ + "description": "Dry yeast as a share.", + "type": "number" +} - added
Output schema / properties / bakes / items / properties / fermentolyseAdded value: +{ + "description": "The rest was a fermentolyse, with the starter in.", + "type": "boolean" +} - added
Output schema / properties / bakes / items / properties / flour_amountsAdded value: +{ + "description": "The flours, with their grams.", + "items": { + "properties": { + "grams": { + "description": "Its grams.", + "type": "integer" + }, + "name": { + "description": "The flour's kind.", + "type": "string" + } + }, + "type": "object" + }, + "type": "array" +} - added
Output schema / properties / bakes / items / properties / floursAdded value: +{ + "description": "The flours used, without grams.", + "items": { + "description": "A flour's kind.", + "type": "string" + }, + "type": "array" +} - added
Output schema / properties / bakes / items / properties / fresh_yeast_percentAdded value: +{ + "description": "Fresh yeast as a share.", + "type": "number" +} - added
Output schema / properties / bakes / items / properties / other_bake_type_descriptionAdded value: +{ + "description": "What was baked, when bake_type is other.", + "type": "string" +} - added
Output schema / properties / bakes / items / properties / piece_weight_gramsAdded value: +{ + "description": "What one piece weighed, in grams.", + "type": "integer" +} - added
Output schema / properties / bakes / items / properties / piecesAdded value: +{ + "description": "How many pieces the dough made.", + "type": "integer" +} - added
Output schema / properties / bakes / items / properties / preheat_levelAdded value: +{ + "description": "A stove's dial while heating.", + "type": "integer" +} - added
Output schema / properties / bakes / items / properties / preheat_temp_celsiusAdded value: +{ + "description": "Preheat temperature, °C.", + "type": "number" +} - added
Output schema / properties / bakes / items / properties / proof_rise_percentAdded value: +{ + "description": "How much more it grew in the proof, %.", + "type": "integer" +} - added
Output schema / properties / bakes / items / properties / second_bake_minutesAdded value: +{ + "description": "Minutes of the second phase.", + "type": "integer" +} - added
Output schema / properties / bakes / items / properties / second_bake_temp_celsiusAdded value: +{ + "description": "Oven temperature of the second phase, °C.", + "type": "number" +} - added
Output schema / properties / bakes / items / properties / stretch_fold_countAdded value: +{ + "description": "Sets of stretch and folds.", + "type": "integer" +}
- Changed
log_bake42 fields changed- added
Input schema / properties / autolyse_minutesAdded value: +{ + "description": "Minutes the flour and water rested before mixing, with the starter in for a fermentolyse.", + "maximum": 1440, + "minimum": 0, + "type": "integer" +} - added
Input schema / properties / bake_levelAdded value: +{ + "description": "On a stove: the dial's level while baking.", + "maximum": 12, + "minimum": 1, + "type": "integer" +} - changed
Input schema / properties / bake_minutes / descriptionPrevious value: -"Minutes in the oven."New value: +"Minutes in the oven, whole minutes (90 seconds is 2); with two phases, the first." - changed
Input schema / properties / bake_temp_celsius / descriptionPrevious value: -"Oven temperature in °C."New value: +"Oven temperature in °C; with two phases, the first (in a Dutch oven, with the lid on). A value above 300 °C is only plausible in a pizza or wood-fired oven." - changed
Input schema / properties / bake_temp_celsius / maximumPrevious value: -350New value: +550 - added
Input schema / properties / baking_methodAdded value: +{ + "description": "What it was baked in: home_oven also for a Dutch oven, a stone or a tray in it.", + "enum": [ + "home_oven", + "pizza_oven", + "wood_fired", + "stove" + ], + "type": "string" +} - added
Input schema / properties / dough_rise_percentAdded value: +{ + "description": "How much the dough grew during bulk fermentation, in percent.", + "maximum": 300, + "minimum": 0, + "type": "integer" +} - added
Input schema / properties / dry_yeast_percentAdded value: +{ + "description": "Dry or instant yeast as a percentage of flour.", + "maximum": 10, + "minimum": 0, + "type": "number" +} - added
Input schema / properties / floursAdded value: +{ + "description": "The flours, comma-separated, each as its kind and grams, such as \"bread_flour 450, rye 50\", or its kind alone when no grams were given; kinds: bread_flour, all_purpose, whole_wheat, rye, spelt, einkorn, durum, tipo_00, other.", + "type": "string" +} - added
Input schema / properties / fresh_yeast_percentAdded value: +{ + "description": "Fresh yeast as a percentage of flour.", + "maximum": 10, + "minimum": 0, + "type": "number" +} - changed
Input schema / properties / notes / descriptionPrevious value: -"How the bake went, in the baker's words."New value: +"How the bake went, in the baker's words: only what no other parameter takes." - added
Input schema / properties / other_bake_type_descriptionAdded value: +{ + "description": "What was baked, in the baker's words, when bake_type is other.", + "type": "string" +} - added
Input schema / properties / piece_weight_gramsAdded value: +{ + "description": "What one piece weighed when it was divided, in grams.", + "maximum": 10000, + "minimum": 1, + "type": "integer" +} - added
Input schema / properties / piecesAdded value: +{ + "description": "How many pieces the dough was divided into: loaves, rolls or pizza balls.", + "maximum": 500, + "minimum": 1, + "type": "integer" +} - added
Input schema / properties / pre_restAdded value: +{ + "description": "That rest: an autolyse, flour and water only, or a fermentolyse, with the starter in.", + "enum": [ + "autolyse", + "fermentolyse" + ], + "type": "string" +} - added
Input schema / properties / preheat_levelAdded value: +{ + "description": "On a stove: the dial's level while the pan heated.", + "maximum": 12, + "minimum": 1, + "type": "integer" +} - added
Input schema / properties / preheat_temp_celsiusAdded value: +{ + "description": "How hot the oven was preheated, in °C. A value above 300 °C is only plausible in a pizza or wood-fired oven.", + "maximum": 550, + "minimum": 50, + "type": "integer" +} - changed
Input schema / properties / problems / descriptionPrevious value: -"What went wrong, comma-separated, from: dense_crumb, gummy_interior, no_oven_spring, flat_loaf, burnt_crust, pale_crust, bland_flavor, too_sour, didnt_rise, sticky_dough."New value: +"What went wrong, comma-separated, from: dense_crumb, gummy_interior, no_oven_spring, flat_loaf, burnt_crust, pale_crust, bland_flavor, too_sour, didnt_rise, sticky_dough; anything else goes in the notes." - added
Input schema / properties / proof_rise_percentAdded value: +{ + "description": "How much more the shaped dough grew during the proof, in percent.", + "maximum": 300, + "minimum": 0, + "type": "integer" +} - added
Input schema / properties / second_bake_minutesAdded value: +{ + "description": "Minutes of that second phase, whole minutes.", + "maximum": 300, + "minimum": 1, + "type": "integer" +} - added
Input schema / properties / second_bake_temp_celsiusAdded value: +{ + "description": "Oven temperature in °C of a second phase: with the lid off, or turned down. A value above 300 °C is only plausible in a pizza or wood-fired oven.", + "maximum": 550, + "minimum": 50, + "type": "integer" +} - added
Input schema / properties / stretch_fold_countAdded value: +{ + "description": "Sets of stretch and folds during bulk.", + "maximum": 10, + "minimum": 0, + "type": "integer" +} - added
Output schema / properties / bake / properties / autolyse_minutesAdded value: +{ + "description": "Minutes of rest before mixing.", + "type": "integer" +} - added
Output schema / properties / bake / properties / bake_levelAdded value: +{ + "description": "A stove's dial while baking.", + "type": "integer" +} - changed
Output schema / properties / bake / properties / bake_minutes / descriptionPrevious value: -"Minutes in the oven."New value: +"Minutes in the oven; with two phases, the first." - changed
Output schema / properties / bake / properties / bake_temp_celsius / descriptionPrevious value: -"Oven temperature, °C."New value: +"Oven temperature, °C; with two phases, the first." - added
Output schema / properties / bake / properties / baking_methodAdded value: +{ + "description": "What it was baked in.", + "type": "string" +} - added
Output schema / properties / bake / properties / dough_rise_percentAdded value: +{ + "description": "How much the dough grew in bulk, %.", + "type": "integer" +} - added
Output schema / properties / bake / properties / dry_yeast_percentAdded value: +{ + "description": "Dry yeast as a share.", + "type": "number" +} - added
Output schema / properties / bake / properties / fermentolyseAdded value: +{ + "description": "The rest was a fermentolyse, with the starter in.", + "type": "boolean" +} - added
Output schema / properties / bake / properties / flour_amountsAdded value: +{ + "description": "The flours, with their grams.", + "items": { + "properties": { + "grams": { + "description": "Its grams.", + "type": "integer" + }, + "name": { + "description": "The flour's kind.", + "type": "string" + } + }, + "type": "object" + }, + "type": "array" +} - added
Output schema / properties / bake / properties / floursAdded value: +{ + "description": "The flours used, without grams.", + "items": { + "description": "A flour's kind.", + "type": "string" + }, + "type": "array" +} - added
Output schema / properties / bake / properties / fresh_yeast_percentAdded value: +{ + "description": "Fresh yeast as a share.", + "type": "number" +} - added
Output schema / properties / bake / properties / other_bake_type_descriptionAdded value: +{ + "description": "What was baked, when bake_type is other.", + "type": "string" +} - added
Output schema / properties / bake / properties / piece_weight_gramsAdded value: +{ + "description": "What one piece weighed, in grams.", + "type": "integer" +} - added
Output schema / properties / bake / properties / piecesAdded value: +{ + "description": "How many pieces the dough made.", + "type": "integer" +} - added
Output schema / properties / bake / properties / preheat_levelAdded value: +{ + "description": "A stove's dial while heating.", + "type": "integer" +} - added
Output schema / properties / bake / properties / preheat_temp_celsiusAdded value: +{ + "description": "Preheat temperature, °C.", + "type": "number" +} - added
Output schema / properties / bake / properties / proof_rise_percentAdded value: +{ + "description": "How much more it grew in the proof, %.", + "type": "integer" +} - added
Output schema / properties / bake / properties / second_bake_minutesAdded value: +{ + "description": "Minutes of the second phase.", + "type": "integer" +} - added
Output schema / properties / bake / properties / second_bake_temp_celsiusAdded value: +{ + "description": "Oven temperature of the second phase, °C.", + "type": "number" +} - added
Output schema / properties / bake / properties / stretch_fold_countAdded value: +{ + "description": "Sets of stretch and folds.", + "type": "integer" +}
- Changed
update_bake42 fields changed- added
Input schema / properties / autolyse_minutesAdded value: +{ + "description": "Minutes the flour and water rested before mixing, with the starter in for a fermentolyse.", + "maximum": 1440, + "minimum": 0, + "type": "integer" +} - added
Input schema / properties / bake_levelAdded value: +{ + "description": "On a stove: the dial's level while baking.", + "maximum": 12, + "minimum": 1, + "type": "integer" +} - changed
Input schema / properties / bake_minutes / descriptionPrevious value: -"Minutes in the oven."New value: +"Minutes in the oven, whole minutes (90 seconds is 2); with two phases, the first." - changed
Input schema / properties / bake_temp_celsius / descriptionPrevious value: -"Oven temperature in °C."New value: +"Oven temperature in °C; with two phases, the first (in a Dutch oven, with the lid on). A value above 300 °C is only plausible in a pizza or wood-fired oven." - changed
Input schema / properties / bake_temp_celsius / maximumPrevious value: -350New value: +550 - added
Input schema / properties / baking_methodAdded value: +{ + "description": "What it was baked in: home_oven also for a Dutch oven, a stone or a tray in it.", + "enum": [ + "home_oven", + "pizza_oven", + "wood_fired", + "stove" + ], + "type": "string" +} - added
Input schema / properties / dough_rise_percentAdded value: +{ + "description": "How much the dough grew during bulk fermentation, in percent.", + "maximum": 300, + "minimum": 0, + "type": "integer" +} - added
Input schema / properties / dry_yeast_percentAdded value: +{ + "description": "Dry or instant yeast as a percentage of flour.", + "maximum": 10, + "minimum": 0, + "type": "number" +} - added
Input schema / properties / floursAdded value: +{ + "description": "The flours, comma-separated, each as its kind and grams, such as \"bread_flour 450, rye 50\", or its kind alone when no grams were given; kinds: bread_flour, all_purpose, whole_wheat, rye, spelt, einkorn, durum, tipo_00, other.", + "type": "string" +} - added
Input schema / properties / fresh_yeast_percentAdded value: +{ + "description": "Fresh yeast as a percentage of flour.", + "maximum": 10, + "minimum": 0, + "type": "number" +} - changed
Input schema / properties / notes / descriptionPrevious value: -"How the bake went, in the baker's words."New value: +"How the bake went, in the baker's words: only what no other parameter takes." - added
Input schema / properties / other_bake_type_descriptionAdded value: +{ + "description": "What was baked, in the baker's words, when bake_type is other.", + "type": "string" +} - added
Input schema / properties / piece_weight_gramsAdded value: +{ + "description": "What one piece weighed when it was divided, in grams.", + "maximum": 10000, + "minimum": 1, + "type": "integer" +} - added
Input schema / properties / piecesAdded value: +{ + "description": "How many pieces the dough was divided into: loaves, rolls or pizza balls.", + "maximum": 500, + "minimum": 1, + "type": "integer" +} - added
Input schema / properties / pre_restAdded value: +{ + "description": "That rest: an autolyse, flour and water only, or a fermentolyse, with the starter in.", + "enum": [ + "autolyse", + "fermentolyse" + ], + "type": "string" +} - added
Input schema / properties / preheat_levelAdded value: +{ + "description": "On a stove: the dial's level while the pan heated.", + "maximum": 12, + "minimum": 1, + "type": "integer" +} - added
Input schema / properties / preheat_temp_celsiusAdded value: +{ + "description": "How hot the oven was preheated, in °C. A value above 300 °C is only plausible in a pizza or wood-fired oven.", + "maximum": 550, + "minimum": 50, + "type": "integer" +} - changed
Input schema / properties / problems / descriptionPrevious value: -"What went wrong, comma-separated, from: dense_crumb, gummy_interior, no_oven_spring, flat_loaf, burnt_crust, pale_crust, bland_flavor, too_sour, didnt_rise, sticky_dough."New value: +"What went wrong, comma-separated, from: dense_crumb, gummy_interior, no_oven_spring, flat_loaf, burnt_crust, pale_crust, bland_flavor, too_sour, didnt_rise, sticky_dough; anything else goes in the notes." - added
Input schema / properties / proof_rise_percentAdded value: +{ + "description": "How much more the shaped dough grew during the proof, in percent.", + "maximum": 300, + "minimum": 0, + "type": "integer" +} - added
Input schema / properties / second_bake_minutesAdded value: +{ + "description": "Minutes of that second phase, whole minutes.", + "maximum": 300, + "minimum": 1, + "type": "integer" +} - added
Input schema / properties / second_bake_temp_celsiusAdded value: +{ + "description": "Oven temperature in °C of a second phase: with the lid off, or turned down. A value above 300 °C is only plausible in a pizza or wood-fired oven.", + "maximum": 550, + "minimum": 50, + "type": "integer" +} - added
Input schema / properties / stretch_fold_countAdded value: +{ + "description": "Sets of stretch and folds during bulk.", + "maximum": 10, + "minimum": 0, + "type": "integer" +} - added
Output schema / properties / bake / properties / autolyse_minutesAdded value: +{ + "description": "Minutes of rest before mixing.", + "type": "integer" +} - added
Output schema / properties / bake / properties / bake_levelAdded value: +{ + "description": "A stove's dial while baking.", + "type": "integer" +} - changed
Output schema / properties / bake / properties / bake_minutes / descriptionPrevious value: -"Minutes in the oven."New value: +"Minutes in the oven; with two phases, the first." - changed
Output schema / properties / bake / properties / bake_temp_celsius / descriptionPrevious value: -"Oven temperature, °C."New value: +"Oven temperature, °C; with two phases, the first." - added
Output schema / properties / bake / properties / baking_methodAdded value: +{ + "description": "What it was baked in.", + "type": "string" +} - added
Output schema / properties / bake / properties / dough_rise_percentAdded value: +{ + "description": "How much the dough grew in bulk, %.", + "type": "integer" +} - added
Output schema / properties / bake / properties / dry_yeast_percentAdded value: +{ + "description": "Dry yeast as a share.", + "type": "number" +} - added
Output schema / properties / bake / properties / fermentolyseAdded value: +{ + "description": "The rest was a fermentolyse, with the starter in.", + "type": "boolean" +} - added
Output schema / properties / bake / properties / flour_amountsAdded value: +{ + "description": "The flours, with their grams.", + "items": { + "properties": { + "grams": { + "description": "Its grams.", + "type": "integer" + }, + "name": { + "description": "The flour's kind.", + "type": "string" + } + }, + "type": "object" + }, + "type": "array" +} - added
Output schema / properties / bake / properties / floursAdded value: +{ + "description": "The flours used, without grams.", + "items": { + "description": "A flour's kind.", + "type": "string" + }, + "type": "array" +} - added
Output schema / properties / bake / properties / fresh_yeast_percentAdded value: +{ + "description": "Fresh yeast as a share.", + "type": "number" +} - added
Output schema / properties / bake / properties / other_bake_type_descriptionAdded value: +{ + "description": "What was baked, when bake_type is other.", + "type": "string" +} - added
Output schema / properties / bake / properties / piece_weight_gramsAdded value: +{ + "description": "What one piece weighed, in grams.", + "type": "integer" +} - added
Output schema / properties / bake / properties / piecesAdded value: +{ + "description": "How many pieces the dough made.", + "type": "integer" +} - added
Output schema / properties / bake / properties / preheat_levelAdded value: +{ + "description": "A stove's dial while heating.", + "type": "integer" +} - added
Output schema / properties / bake / properties / preheat_temp_celsiusAdded value: +{ + "description": "Preheat temperature, °C.", + "type": "number" +} - added
Output schema / properties / bake / properties / proof_rise_percentAdded value: +{ + "description": "How much more it grew in the proof, %.", + "type": "integer" +} - added
Output schema / properties / bake / properties / second_bake_minutesAdded value: +{ + "description": "Minutes of the second phase.", + "type": "integer" +} - added
Output schema / properties / bake / properties / second_bake_temp_celsiusAdded value: +{ + "description": "Oven temperature of the second phase, °C.", + "type": "number" +} - added
Output schema / properties / bake / properties / stretch_fold_countAdded value: +{ + "description": "Sets of stretch and folds.", + "type": "integer" +}
1 tool update
- Added
estimate_bulk_fermentation
1 tool update
- Changed
calculate_bread_dough1 field changed- changed
Input schema / properties / loaf_size_g / minimumPrevious value: -100New value: +50
17 tool updates
- Changed
add_container1 field changed- changed
Output schema / (root)Previous value: -nullNew value: +{ + "description": "The container as saved.", + "properties": { + "container": { + "description": "One of the baker's containers.", + "properties": { + "id": { + "description": "The container's id, which update_container takes.", + "type": "string" + }, + "name": { + "description": "Its name.", + "type": "string" + }, + "notes": { + "description": "Notes on it.", + "type": "string" + }, + "url": { + "description": "The container on loafy.ai.", + "type": "string" + }, + "weight_grams": { + "description": "Its empty weight, in grams.", + "type": "number" + } + }, + "type": "object" + }, + "input": { + "description": "The arguments as the tool used them, after any correction.", + "properties": {}, + "type": "object" + }, + "note": { + "description": "A remark on the whole result, such as why nothing was found.", + "type": "string" + }, + "notes": { + "description": "What was corrected or left out, such as a value outside its range.", + "items": { + "description": "A correction or remark.", + "type": "string" + }, + "type": "array" + }, + "saved": { + "description": "What was saved, in one sentence.", + "type": "string" + }, + "tool": { + "description": "The tool that answered.", + "type": "string" + }, + "url": { + "description": "The same answer, recipe or entry on loafy.ai.", + "type": "string" + } + }, + "type": "object" +}
- Changed
add_starter1 field changed- changed
Output schema / (root)Previous value: -nullNew value: +{ + "description": "The starter as saved.", + "properties": { + "input": { + "description": "The arguments as the tool used them, after any correction.", + "properties": {}, + "type": "object" + }, + "note": { + "description": "A remark on the whole result, such as why nothing was found.", + "type": "string" + }, + "notes": { + "description": "What was corrected or left out, such as a value outside its range.", + "items": { + "description": "A correction or remark.", + "type": "string" + }, + "type": "array" + }, + "saved": { + "description": "What was saved, in one sentence.", + "type": "string" + }, + "starter": { + "description": "One of the baker's starters.", + "properties": { + "age_days": { + "description": "Its age in days.", + "type": "integer" + }, + "bakes": { + "description": "How many bakes it went into.", + "type": "integer" + }, + "birthday": { + "description": "The day it was started, YYYY-MM-DD.", + "type": "string" + }, + "id": { + "description": "The starter's id, which update_starter takes.", + "type": "string" + }, + "last_baked_on": { + "description": "Its last bake, YYYY-MM-DD.", + "type": "string" + }, + "name": { + "description": "Its name.", + "type": "string" + }, + "notes": { + "description": "Notes on it.", + "type": "string" + }, + "story": { + "description": "Its story.", + "type": "string" + }, + "url": { + "description": "The starter on loafy.ai.", + "type": "string" + } + }, + "type": "object" + }, + "tool": { + "description": "The tool that answered.", + "type": "string" + }, + "url": { + "description": "The same answer, recipe or entry on loafy.ai.", + "type": "string" + } + }, + "type": "object" +}
- Changed
calculate_bread_dough1 field changed- changed
Output schema / (root)Previous value: -nullNew value: +{ + "description": "A sourdough bread recipe in grams.", + "properties": { + "dough_per_loaf_g": { + "description": "The dough of one loaf, in grams.", + "type": "number" + }, + "ingredients": { + "properties": { + "bread_flour_g": { + "description": "Bread flour, in grams.", + "type": "number" + }, + "salt_g": { + "description": "Salt, in grams.", + "type": "number" + }, + "starter_g": { + "description": "Starter, in grams.", + "type": "number" + }, + "total_flour_g": { + "description": "All flour, in grams.", + "type": "number" + }, + "water_g": { + "description": "Water, in grams.", + "type": "number" + }, + "whole_grain_flour_g": { + "description": "Whole grain flour, in grams.", + "type": "number" + } + }, + "type": "object" + }, + "input": { + "description": "The arguments as the tool used them, after any correction.", + "properties": {}, + "type": "object" + }, + "note": { + "description": "A remark on the whole result, such as why nothing was found.", + "type": "string" + }, + "notes": { + "description": "What was corrected or left out, such as a value outside its range.", + "items": { + "description": "A correction or remark.", + "type": "string" + }, + "type": "array" + }, + "tool": { + "description": "The tool that answered.", + "type": "string" + }, + "total_dough_g": { + "description": "All the dough, in grams.", + "type": "number" + }, + "url": { + "description": "The same answer, recipe or entry on loafy.ai.", + "type": "string" + } + }, + "type": "object" +}
- Changed
calculate_pizza_dough1 field changed- changed
Output schema / (root)Previous value: -nullNew value: +{ + "description": "Pizza dough in grams.", + "properties": { + "ingredients": { + "additionalProperties": { + "type": "number" + }, + "description": "Flour, water, salt and the leavening (fresh yeast or starter), in grams.", + "type": "object" + }, + "input": { + "description": "The arguments as the tool used them, after any correction.", + "properties": {}, + "type": "object" + }, + "note": { + "description": "A remark on the whole result, such as why nothing was found.", + "type": "string" + }, + "notes": { + "description": "What was corrected or left out, such as a value outside its range.", + "items": { + "description": "A correction or remark.", + "type": "string" + }, + "type": "array" + }, + "tool": { + "description": "The tool that answered.", + "type": "string" + }, + "toppings": { + "additionalProperties": { + "type": "number" + }, + "description": "Toppings for all the pizzas: grams, and basil as leaves and pots.", + "type": "object" + }, + "total_dough_g": { + "description": "All the dough, in grams.", + "type": "number" + }, + "url": { + "description": "The same answer, recipe or entry on loafy.ai.", + "type": "string" + } + }, + "type": "object" +}
- Changed
find_sourdough_answer1 field changed- changed
Output schema / (root)Previous value: -nullNew value: +{ + "description": "Answers to real questions from bakers.", + "properties": { + "answers": { + "description": "The answers that match.", + "items": { + "properties": { + "answer": { + "description": "Hendrik's answer.", + "type": "string" + }, + "question": { + "description": "The baker's question.", + "type": "string" + }, + "source": { + "properties": { + "title": { + "description": "The book chapter behind it.", + "type": "string" + }, + "url": { + "description": "Its link.", + "type": "string" + } + }, + "type": "object" + }, + "url": { + "description": "The answer's page on loafy.ai.", + "type": "string" + } + }, + "type": "object" + }, + "type": "array" + }, + "input": { + "description": "The arguments as the tool used them, after any correction.", + "properties": {}, + "type": "object" + }, + "license": { + "description": "The licence of the book's text: CC BY-SA 4.0, with attribution.", + "type": "string" + }, + "note": { + "description": "A remark on the whole result, such as why nothing was found.", + "type": "string" + }, + "notes": { + "description": "What was corrected or left out, such as a value outside its range.", + "items": { + "description": "A correction or remark.", + "type": "string" + }, + "type": "array" + }, + "passages": { + "description": "When no answer matches, the closest passages from the book.", + "items": { + "properties": { + "chapter": { + "description": "The chapter.", + "type": "string" + }, + "part": { + "description": "Its number and title, which read_sourdough_book takes.", + "type": "string" + }, + "section": { + "description": "The section within it.", + "type": "string" + }, + "text": { + "description": "The passage.", + "type": "string" + }, + "url": { + "description": "The chapter on the book's website.", + "type": "string" + } + }, + "type": "object" + }, + "type": "array" + }, + "suggestion": { + "description": "Where to look next when nothing fits.", + "type": "string" + }, + "tool": { + "description": "The tool that answered.", + "type": "string" + }, + "url": { + "description": "The same answer, recipe or entry on loafy.ai.", + "type": "string" + } + }, + "type": "object" +}
- Changed
get_sourdough_journey_step3 fields changed- changed
Input schema / properties / slug / descriptionPrevious value: -"Journey identifier, e.g. \"sourdough-bread\"."New value: +"Journey identifier, e.g. \"sourdough-bread\", or the journey's title." - changed
Input schema / properties / step / descriptionPrevious value: -"Step identifier (e.g. \"mix\") or position (\"5\" is the fifth step). Left out, the first step is returned."New value: +"Step identifier (e.g. \"mix\"), its title, or position (\"5\" is the fifth step). Left out, the first step is returned." - changed
Output schema / (root)Previous value: -nullNew value: +{ + "description": "One step of a guided journey.", + "properties": { + "input": { + "description": "The arguments as the tool used them, after any correction.", + "properties": {}, + "type": "object" + }, + "journey": { + "properties": { + "description": { + "description": "What it covers.", + "type": "string" + }, + "difficulty": { + "description": "How hard it is.", + "type": "string" + }, + "duration": { + "description": "How long it takes.", + "type": "string" + }, + "slug": { + "description": "The journey's identifier.", + "type": "string" + }, + "steps": { + "description": "How many steps it has.", + "type": "integer" + }, + "title": { + "description": "Its title.", + "type": "string" + }, + "url": { + "description": "The journey on loafy.ai.", + "type": "string" + } + }, + "type": "object" + }, + "note": { + "description": "A remark on the whole result, such as why nothing was found.", + "type": "string" + }, + "notes": { + "description": "What was corrected or left out, such as a value outside its range.", + "items": { + "description": "A correction or remark.", + "type": "string" + }, + "type": "array" + }, + "step": { + "properties": { + "id": { + "description": "The step's identifier.", + "type": "string" + }, + "next_step": { + "description": "The next step's identifier.", + "type": [ + "string", + "null" + ] + }, + "position": { + "description": "Where it sits, such as \"3 of 14\".", + "type": "string" + }, + "timer_minutes": { + "description": "Its timer, when the step has one.", + "type": "integer" + }, + "title": { + "description": "Its title.", + "type": "string" + } + }, + "type": "object" + }, + "tool": { + "description": "The tool that answered.", + "type": "string" + }, + "url": { + "description": "The same answer, recipe or entry on loafy.ai.", + "type": "string" + } + }, + "type": "object" +}
- Changed
list_my_bakes1 field changed- changed
Output schema / (root)Previous value: -nullNew value: +{ + "description": "The baker's bakes.", + "properties": { + "bakes": { + "description": "Newest first.", + "items": { + "description": "A bake in the baker's journal.", + "properties": { + "bake_minutes": { + "description": "Minutes in the oven.", + "type": "number" + }, + "bake_temp_celsius": { + "description": "Oven temperature, °C.", + "type": "number" + }, + "bake_type": { + "description": "What was baked.", + "type": "string" + }, + "baked_on": { + "description": "The day, YYYY-MM-DD.", + "type": "string" + }, + "bulk_hours": { + "description": "Hours of bulk fermentation.", + "type": "number" + }, + "bulk_temp_celsius": { + "description": "Temperature during bulk, °C.", + "type": "number" + }, + "fridge_proof_hours": { + "description": "Hours in the fridge.", + "type": "number" + }, + "hydration_percent": { + "description": "Water as a share of the flour.", + "type": "number" + }, + "id": { + "description": "The bake's id, which update_bake takes.", + "type": "string" + }, + "next_time_notes": { + "description": "What to try next time.", + "type": "string" + }, + "notes": { + "description": "The baker's notes.", + "type": "string" + }, + "photos": { + "description": "How many photos it has.", + "type": "integer" + }, + "problems": { + "description": "What went wrong.", + "items": { + "description": "A problem, such as flat or dense.", + "type": "string" + }, + "type": "array" + }, + "rating": { + "description": "Stars, 1 to 5.", + "type": "integer" + }, + "room_temp_proof_hours": { + "description": "Hours of proof at room temperature.", + "type": "number" + }, + "salt_percent": { + "description": "Salt as a share.", + "type": "number" + }, + "starter": { + "description": "The starter it was made with.", + "type": "string" + }, + "starter_percent": { + "description": "Starter as a share.", + "type": "number" + }, + "url": { + "description": "The bake on loafy.ai.", + "type": "string" + } + }, + "type": "object" + }, + "type": "array" + }, + "in_journal": { + "description": "All bakes in the journal.", + "type": "integer" + }, + "input": { + "description": "The arguments as the tool used them, after any correction.", + "properties": {}, + "type": "object" + }, + "note": { + "description": "A remark on the whole result, such as why nothing was found.", + "type": "string" + }, + "notes": { + "description": "What was corrected or left out, such as a value outside its range.", + "items": { + "description": "A correction or remark.", + "type": "string" + }, + "type": "array" + }, + "tool": { + "description": "The tool that answered.", + "type": "string" + }, + "url": { + "description": "The same answer, recipe or entry on loafy.ai.", + "type": "string" + } + }, + "type": "object" +}
- Changed
list_my_containers1 field changed- changed
Output schema / (root)Previous value: -nullNew value: +{ + "description": "The baker's containers.", + "properties": { + "containers": { + "description": "By name.", + "items": { + "description": "One of the baker's containers.", + "properties": { + "id": { + "description": "The container's id, which update_container takes.", + "type": "string" + }, + "name": { + "description": "Its name.", + "type": "string" + }, + "notes": { + "description": "Notes on it.", + "type": "string" + }, + "url": { + "description": "The container on loafy.ai.", + "type": "string" + }, + "weight_grams": { + "description": "Its empty weight, in grams.", + "type": "number" + } + }, + "type": "object" + }, + "type": "array" + }, + "input": { + "description": "The arguments as the tool used them, after any correction.", + "properties": {}, + "type": "object" + }, + "note": { + "description": "A remark on the whole result, such as why nothing was found.", + "type": "string" + }, + "notes": { + "description": "What was corrected or left out, such as a value outside its range.", + "items": { + "description": "A correction or remark.", + "type": "string" + }, + "type": "array" + }, + "tool": { + "description": "The tool that answered.", + "type": "string" + }, + "url": { + "description": "The same answer, recipe or entry on loafy.ai.", + "type": "string" + } + }, + "type": "object" +}
- Changed
list_my_starters1 field changed- changed
Output schema / (root)Previous value: -nullNew value: +{ + "description": "The baker's starters.", + "properties": { + "input": { + "description": "The arguments as the tool used them, after any correction.", + "properties": {}, + "type": "object" + }, + "note": { + "description": "A remark on the whole result, such as why nothing was found.", + "type": "string" + }, + "notes": { + "description": "What was corrected or left out, such as a value outside its range.", + "items": { + "description": "A correction or remark.", + "type": "string" + }, + "type": "array" + }, + "starters": { + "description": "By name.", + "items": { + "description": "One of the baker's starters.", + "properties": { + "age_days": { + "description": "Its age in days.", + "type": "integer" + }, + "bakes": { + "description": "How many bakes it went into.", + "type": "integer" + }, + "birthday": { + "description": "The day it was started, YYYY-MM-DD.", + "type": "string" + }, + "id": { + "description": "The starter's id, which update_starter takes.", + "type": "string" + }, + "last_baked_on": { + "description": "Its last bake, YYYY-MM-DD.", + "type": "string" + }, + "name": { + "description": "Its name.", + "type": "string" + }, + "notes": { + "description": "Notes on it.", + "type": "string" + }, + "story": { + "description": "Its story.", + "type": "string" + }, + "url": { + "description": "The starter on loafy.ai.", + "type": "string" + } + }, + "type": "object" + }, + "type": "array" + }, + "tool": { + "description": "The tool that answered.", + "type": "string" + }, + "url": { + "description": "The same answer, recipe or entry on loafy.ai.", + "type": "string" + } + }, + "type": "object" +}
- Changed
list_sourdough_journeys1 field changed- changed
Output schema / (root)Previous value: -nullNew value: +{ + "description": "Loafy's guided journeys.", + "properties": { + "input": { + "description": "The arguments as the tool used them, after any correction.", + "properties": {}, + "type": "object" + }, + "journeys": { + "description": "Every guided journey.", + "items": { + "properties": { + "description": { + "description": "What it covers.", + "type": "string" + }, + "difficulty": { + "description": "How hard it is.", + "type": "string" + }, + "duration": { + "description": "How long it takes.", + "type": "string" + }, + "slug": { + "description": "The journey's identifier.", + "type": "string" + }, + "steps": { + "description": "How many steps it has.", + "type": "integer" + }, + "title": { + "description": "Its title.", + "type": "string" + }, + "url": { + "description": "The journey on loafy.ai.", + "type": "string" + } + }, + "type": "object" + }, + "type": "array" + }, + "note": { + "description": "A remark on the whole result, such as why nothing was found.", + "type": "string" + }, + "notes": { + "description": "What was corrected or left out, such as a value outside its range.", + "items": { + "description": "A correction or remark.", + "type": "string" + }, + "type": "array" + }, + "tool": { + "description": "The tool that answered.", + "type": "string" + }, + "url": { + "description": "The same answer, recipe or entry on loafy.ai.", + "type": "string" + } + }, + "type": "object" +}
- Changed
log_bake1 field changed- changed
Output schema / (root)Previous value: -nullNew value: +{ + "description": "The bake as saved in the journal.", + "properties": { + "bake": { + "description": "A bake in the baker's journal.", + "properties": { + "bake_minutes": { + "description": "Minutes in the oven.", + "type": "number" + }, + "bake_temp_celsius": { + "description": "Oven temperature, °C.", + "type": "number" + }, + "bake_type": { + "description": "What was baked.", + "type": "string" + }, + "baked_on": { + "description": "The day, YYYY-MM-DD.", + "type": "string" + }, + "bulk_hours": { + "description": "Hours of bulk fermentation.", + "type": "number" + }, + "bulk_temp_celsius": { + "description": "Temperature during bulk, °C.", + "type": "number" + }, + "fridge_proof_hours": { + "description": "Hours in the fridge.", + "type": "number" + }, + "hydration_percent": { + "description": "Water as a share of the flour.", + "type": "number" + }, + "id": { + "description": "The bake's id, which update_bake takes.", + "type": "string" + }, + "next_time_notes": { + "description": "What to try next time.", + "type": "string" + }, + "notes": { + "description": "The baker's notes.", + "type": "string" + }, + "photos": { + "description": "How many photos it has.", + "type": "integer" + }, + "problems": { + "description": "What went wrong.", + "items": { + "description": "A problem, such as flat or dense.", + "type": "string" + }, + "type": "array" + }, + "rating": { + "description": "Stars, 1 to 5.", + "type": "integer" + }, + "room_temp_proof_hours": { + "description": "Hours of proof at room temperature.", + "type": "number" + }, + "salt_percent": { + "description": "Salt as a share.", + "type": "number" + }, + "starter": { + "description": "The starter it was made with.", + "type": "string" + }, + "starter_percent": { + "description": "Starter as a share.", + "type": "number" + }, + "url": { + "description": "The bake on loafy.ai.", + "type": "string" + } + }, + "type": "object" + }, + "card": { + "description": "The figures the bake card in Claude shows (ui://loafy/bake-card).", + "properties": { + "add_photos": { + "description": "The photo button's label.", + "type": "string" + }, + "best": { + "description": "The best bake so far.", + "type": "string" + }, + "facts": { + "description": "The bake's main figures.", + "items": { + "description": "A figure, such as 75 % hydration.", + "type": "string" + }, + "type": "array" + }, + "open": { + "description": "The open button's label.", + "type": "string" + }, + "photos_url": { + "description": "Where its photos are added.", + "type": "string" + }, + "subtitle": { + "description": "Under the title.", + "type": "string" + }, + "title": { + "description": "Its title.", + "type": "string" + }, + "trail": { + "description": "The last bakes.", + "items": { + "properties": { + "label": { + "description": "Stars or today.", + "type": "string" + }, + "now": { + "description": "This bake.", + "type": "boolean" + }, + "rating": { + "description": "Stars.", + "type": "integer" + } + }, + "type": "object" + }, + "type": "array" + }, + "url": { + "description": "The bake on loafy.ai.", + "type": "string" + } + }, + "type": "object" + }, + "input": { + "description": "The arguments as the tool used them, after any correction.", + "properties": {}, + "type": "object" + }, + "note": { + "description": "A remark on the whole result, such as why nothing was found.", + "type": "string" + }, + "notes": { + "description": "What was corrected or left out, such as a value outside its range.", + "items": { + "description": "A correction or remark.", + "type": "string" + }, + "type": "array" + }, + "photos": { + "description": "Where photos are added.", + "type": "string" + }, + "saved": { + "description": "What was saved, in one sentence.", + "type": "string" + }, + "tool": { + "description": "The tool that answered.", + "type": "string" + }, + "url": { + "description": "The same answer, recipe or entry on loafy.ai.", + "type": "string" + } + }, + "type": "object" +}
- Changed
plan_sourdough_bake1 field changed- changed
Output schema / (root)Previous value: -nullNew value: +{ + "description": "A sourdough bake planned backwards from when the bread should be ready.", + "properties": { + "input": { + "description": "The arguments as the tool used them, after any correction.", + "properties": {}, + "type": "object" + }, + "note": { + "description": "A remark on the whole result, such as why nothing was found.", + "type": "string" + }, + "notes": { + "description": "What was corrected or left out, such as a value outside its range.", + "items": { + "description": "A correction or remark.", + "type": "string" + }, + "type": "array" + }, + "ready_at": { + "description": "When the bread comes out of the oven.", + "type": "string" + }, + "starter": { + "properties": { + "bulk": { + "description": "The bulk fermentation that goes with it.", + "type": "string" + }, + "for_kitchen": { + "description": "The kitchen temperature the figures are for.", + "type": "string" + }, + "note": { + "description": "How to read the figures.", + "type": "string" + }, + "percent_of_flour": { + "description": "Starter as a share of the flour.", + "type": "string" + }, + "source": { + "description": "Where in the book they come from.", + "type": "string" + } + }, + "type": "object" + }, + "steps": { + "description": "The bake, step by step, in order.", + "items": { + "properties": { + "at": { + "description": "When.", + "type": "string" + }, + "from": { + "description": "From when, for a window.", + "type": "string" + }, + "hours": { + "description": "How long it takes.", + "type": "number" + }, + "note": { + "description": "What to look for.", + "type": "string" + }, + "step": { + "description": "What to do.", + "type": "string" + }, + "until": { + "description": "Until when, for a window.", + "type": "string" + } + }, + "type": "object" + }, + "type": "array" + }, + "tool": { + "description": "The tool that answered.", + "type": "string" + }, + "url": { + "description": "The same answer, recipe or entry on loafy.ai.", + "type": "string" + } + }, + "type": "object" +}
- Changed
search_sourdough_book1 field changed- changed
Output schema / (root)Previous value: -nullNew value: +{ + "description": "Passages from The Sourdough Framework.", + "properties": { + "input": { + "description": "The arguments as the tool used them, after any correction.", + "properties": {}, + "type": "object" + }, + "license": { + "description": "The licence of the book's text: CC BY-SA 4.0, with attribution.", + "type": "string" + }, + "note": { + "description": "A remark on the whole result, such as why nothing was found.", + "type": "string" + }, + "notes": { + "description": "What was corrected or left out, such as a value outside its range.", + "items": { + "description": "A correction or remark.", + "type": "string" + }, + "type": "array" + }, + "passages": { + "description": "The passages that answer the question.", + "items": { + "properties": { + "chapter": { + "description": "The chapter.", + "type": "string" + }, + "part": { + "description": "Its number and title, which read_sourdough_book takes.", + "type": "string" + }, + "section": { + "description": "The section within it.", + "type": "string" + }, + "text": { + "description": "The passage.", + "type": "string" + }, + "url": { + "description": "The chapter on the book's website.", + "type": "string" + } + }, + "type": "object" + }, + "type": "array" + }, + "suggestion": { + "description": "Where to look next when nothing fits.", + "type": "string" + }, + "tool": { + "description": "The tool that answered.", + "type": "string" + }, + "url": { + "description": "The same answer, recipe or entry on loafy.ai.", + "type": "string" + } + }, + "type": "object" +}
- Changed
start_sourdough_journey2 fields changed- changed
Input schema / properties / slug / descriptionPrevious value: -"Journey identifier from list_sourdough_journeys, e.g. \"sourdough-bread\"."New value: +"Journey identifier from list_sourdough_journeys, e.g. \"sourdough-bread\", or the journey's title." - changed
Output schema / (root)Previous value: -nullNew value: +{ + "description": "A guided journey and its first step.", + "properties": { + "first_step": { + "properties": { + "id": { + "description": "The step's identifier.", + "type": "string" + }, + "timer_minutes": { + "description": "Its timer, when the step has one.", + "type": "integer" + }, + "title": { + "description": "Its title.", + "type": "string" + } + }, + "type": "object" + }, + "input": { + "description": "The arguments as the tool used them, after any correction.", + "properties": {}, + "type": "object" + }, + "journey": { + "properties": { + "description": { + "description": "What it covers.", + "type": "string" + }, + "difficulty": { + "description": "How hard it is.", + "type": "string" + }, + "duration": { + "description": "How long it takes.", + "type": "string" + }, + "slug": { + "description": "The journey's identifier.", + "type": "string" + }, + "steps": { + "description": "How many steps it has.", + "type": "integer" + }, + "title": { + "description": "Its title.", + "type": "string" + }, + "url": { + "description": "The journey on loafy.ai.", + "type": "string" + } + }, + "type": "object" + }, + "note": { + "description": "A remark on the whole result, such as why nothing was found.", + "type": "string" + }, + "notes": { + "description": "What was corrected or left out, such as a value outside its range.", + "items": { + "description": "A correction or remark.", + "type": "string" + }, + "type": "array" + }, + "tool": { + "description": "The tool that answered.", + "type": "string" + }, + "url": { + "description": "The same answer, recipe or entry on loafy.ai.", + "type": "string" + } + }, + "type": "object" +}
- Changed
update_bake1 field changed- changed
Output schema / (root)Previous value: -nullNew value: +{ + "description": "The bake as saved in the journal.", + "properties": { + "bake": { + "description": "A bake in the baker's journal.", + "properties": { + "bake_minutes": { + "description": "Minutes in the oven.", + "type": "number" + }, + "bake_temp_celsius": { + "description": "Oven temperature, °C.", + "type": "number" + }, + "bake_type": { + "description": "What was baked.", + "type": "string" + }, + "baked_on": { + "description": "The day, YYYY-MM-DD.", + "type": "string" + }, + "bulk_hours": { + "description": "Hours of bulk fermentation.", + "type": "number" + }, + "bulk_temp_celsius": { + "description": "Temperature during bulk, °C.", + "type": "number" + }, + "fridge_proof_hours": { + "description": "Hours in the fridge.", + "type": "number" + }, + "hydration_percent": { + "description": "Water as a share of the flour.", + "type": "number" + }, + "id": { + "description": "The bake's id, which update_bake takes.", + "type": "string" + }, + "next_time_notes": { + "description": "What to try next time.", + "type": "string" + }, + "notes": { + "description": "The baker's notes.", + "type": "string" + }, + "photos": { + "description": "How many photos it has.", + "type": "integer" + }, + "problems": { + "description": "What went wrong.", + "items": { + "description": "A problem, such as flat or dense.", + "type": "string" + }, + "type": "array" + }, + "rating": { + "description": "Stars, 1 to 5.", + "type": "integer" + }, + "room_temp_proof_hours": { + "description": "Hours of proof at room temperature.", + "type": "number" + }, + "salt_percent": { + "description": "Salt as a share.", + "type": "number" + }, + "starter": { + "description": "The starter it was made with.", + "type": "string" + }, + "starter_percent": { + "description": "Starter as a share.", + "type": "number" + }, + "url": { + "description": "The bake on loafy.ai.", + "type": "string" + } + }, + "type": "object" + }, + "card": { + "description": "The figures the bake card in Claude shows (ui://loafy/bake-card).", + "properties": { + "add_photos": { + "description": "The photo button's label.", + "type": "string" + }, + "best": { + "description": "The best bake so far.", + "type": "string" + }, + "facts": { + "description": "The bake's main figures.", + "items": { + "description": "A figure, such as 75 % hydration.", + "type": "string" + }, + "type": "array" + }, + "open": { + "description": "The open button's label.", + "type": "string" + }, + "photos_url": { + "description": "Where its photos are added.", + "type": "string" + }, + "subtitle": { + "description": "Under the title.", + "type": "string" + }, + "title": { + "description": "Its title.", + "type": "string" + }, + "trail": { + "description": "The last bakes.", + "items": { + "properties": { + "label": { + "description": "Stars or today.", + "type": "string" + }, + "now": { + "description": "This bake.", + "type": "boolean" + }, + "rating": { + "description": "Stars.", + "type": "integer" + } + }, + "type": "object" + }, + "type": "array" + }, + "url": { + "description": "The bake on loafy.ai.", + "type": "string" + } + }, + "type": "object" + }, + "input": { + "description": "The arguments as the tool used them, after any correction.", + "properties": {}, + "type": "object" + }, + "note": { + "description": "A remark on the whole result, such as why nothing was found.", + "type": "string" + }, + "notes": { + "description": "What was corrected or left out, such as a value outside its range.", + "items": { + "description": "A correction or remark.", + "type": "string" + }, + "type": "array" + }, + "photos": { + "description": "Where photos are added.", + "type": "string" + }, + "saved": { + "description": "What was saved, in one sentence.", + "type": "string" + }, + "tool": { + "description": "The tool that answered.", + "type": "string" + }, + "url": { + "description": "The same answer, recipe or entry on loafy.ai.", + "type": "string" + } + }, + "type": "object" +}
- Changed
update_container1 field changed- changed
Output schema / (root)Previous value: -nullNew value: +{ + "description": "The container as saved.", + "properties": { + "container": { + "description": "One of the baker's containers.", + "properties": { + "id": { + "description": "The container's id, which update_container takes.", + "type": "string" + }, + "name": { + "description": "Its name.", + "type": "string" + }, + "notes": { + "description": "Notes on it.", + "type": "string" + }, + "url": { + "description": "The container on loafy.ai.", + "type": "string" + }, + "weight_grams": { + "description": "Its empty weight, in grams.", + "type": "number" + } + }, + "type": "object" + }, + "input": { + "description": "The arguments as the tool used them, after any correction.", + "properties": {}, + "type": "object" + }, + "note": { + "description": "A remark on the whole result, such as why nothing was found.", + "type": "string" + }, + "notes": { + "description": "What was corrected or left out, such as a value outside its range.", + "items": { + "description": "A correction or remark.", + "type": "string" + }, + "type": "array" + }, + "saved": { + "description": "What was saved, in one sentence.", + "type": "string" + }, + "tool": { + "description": "The tool that answered.", + "type": "string" + }, + "url": { + "description": "The same answer, recipe or entry on loafy.ai.", + "type": "string" + } + }, + "type": "object" +}
- Changed
update_starter1 field changed- changed
Output schema / (root)Previous value: -nullNew value: +{ + "description": "The starter as saved.", + "properties": { + "input": { + "description": "The arguments as the tool used them, after any correction.", + "properties": {}, + "type": "object" + }, + "note": { + "description": "A remark on the whole result, such as why nothing was found.", + "type": "string" + }, + "notes": { + "description": "What was corrected or left out, such as a value outside its range.", + "items": { + "description": "A correction or remark.", + "type": "string" + }, + "type": "array" + }, + "saved": { + "description": "What was saved, in one sentence.", + "type": "string" + }, + "starter": { + "description": "One of the baker's starters.", + "properties": { + "age_days": { + "description": "Its age in days.", + "type": "integer" + }, + "bakes": { + "description": "How many bakes it went into.", + "type": "integer" + }, + "birthday": { + "description": "The day it was started, YYYY-MM-DD.", + "type": "string" + }, + "id": { + "description": "The starter's id, which update_starter takes.", + "type": "string" + }, + "last_baked_on": { + "description": "Its last bake, YYYY-MM-DD.", + "type": "string" + }, + "name": { + "description": "Its name.", + "type": "string" + }, + "notes": { + "description": "Notes on it.", + "type": "string" + }, + "story": { + "description": "Its story.", + "type": "string" + }, + "url": { + "description": "The starter on loafy.ai.", + "type": "string" + } + }, + "type": "object" + }, + "tool": { + "description": "The tool that answered.", + "type": "string" + }, + "url": { + "description": "The same answer, recipe or entry on loafy.ai.", + "type": "string" + } + }, + "type": "object" +}
19 tool updates
- First observed
add_container - First observed
add_starter - First observed
calculate_bread_dough - First observed
calculate_pizza_dough - First observed
find_sourdough_answer - First observed
get_sourdough_book_contents - First observed
get_sourdough_journey_step - First observed
list_my_bakes - First observed
list_my_containers - First observed
list_my_starters - First observed
list_sourdough_journeys - First observed
log_bake - First observed
plan_sourdough_bake - First observed
read_sourdough_book - First observed
search_sourdough_book - First observed
start_sourdough_journey - First observed
update_bake - First observed
update_container - First observed
update_starter
Related MCP Connectors
Flour-first dough plans: yeast, hydration, schedule from flour you own. No API key for plan tools.
Cups to grams for 271 ingredients with USDA and King Arthur densities, recipe scaling, oven temps.
AI copilot for artisan food makers — stock, orders, HACCP and billing from your chat.
Read published house pizza facts and calculate dough and ingredient balance.
Related MCP Servers
- AlicenseAqualityCmaintenanceCalculates pizza dough ingredient quantities using baker's percentages from ball count, weight, hydration, flour blend, and fermentation schedule. Returns grams of each flour, water, salt, and yeast with a readable summary and structured JSON.1MIT
- FlicenseNot gradedqualityDmaintenanceMCP server for managing bakery recipe technical sheets with Postgres. Enables AI agents to search, create, update, approve, and compare recipe versions through secure tools.-
- AlicenseNot gradedqualityDmaintenanceYour digital kitchen, powered by AI. Track what you have, discover what you can cook, and get guided through every recipe — step by step, timer by timer.MIT
- FlicenseAqualityCmaintenanceRace nutrition planning for endurance athletes. Calculates carb, sodium and fluid targets for marathons, ultras, cycling and triathlons. Returns personalised Lecka product recommendations by race type, conditions and athlete weight.31-
Glama MCP Gateway
Add one secure layer between your agents and this server.