ShotPulled
Server Details
Connect your espresso routine to your AI assistant. This MCP server allows LLMs to act as a personal coffee coach by accessing your shot logs, grinder settings, and active bean inventory. Use it to automatically calculate extraction adjustments, track remaining coffee supply, and lock in winning recipes directly from your chat session.
- Status
- Healthy
- Uptime
- 99.9% over 79 days
- Last Tested
- Transport
- Streamable HTTP · MCP 2025-06-18
- URL
- ChatGPT
- ShotPulled
- Claude
- –
TDQS
Scored across 44 tools
Most tools target a distinct resource/action, and descriptions draw clear lines between close pairs such as diagnose_shot vs diagnose_preview and update_bean vs update_bag. With 44 tools there are still some boundary judgments, especially get_dial_state vs suggest_next_step, list_maintenance_due vs the maintenance blocks in list_grinders/list_machines, and log_recommendation vs suggest_next_step.
Almost all names use snake_case with a predictable verb_noun pattern such as list_*, register_*, update_*, set_*, and log_*. Minor inconsistencies remain: bean vs coffee appears across list_beans/register_coffee/update_bean, and grinder_math/kb_changelog are verbless outliers.
44 tools is far above the well-scoped 3-15 range and beyond the heavy 16-25 range, spanning beans, bags, grinders, machines, scales, waters, recipes, shots, maintenance, and knowledge-base operations. The breadth reflects a real domain, but the count still creates substantial selection overhead.
Core lifecycles are well covered: beans/bags, equipment, shots, recipes, maintenance, and KB operations have list/register/update/log/diagnose/archive coverage. Minor gaps exist, such as recipes having list+lock but no explicit unlock/delete/update, and programs being registerable/overwritable but not directly listable or deletable; agents can mostly work around these.
Available Tools
44 toolscompute_ageCompute coffee ageARead-onlyIdempotentInspect
Compute a bag's age in days off roast and its resting/staling verdict, for the coffee's current bag by default or for the bag named.
| Name | Required | Description | Default |
|---|---|---|---|
| bag_id | No | A bag of that coffee (from list_beans' bags[]); null = its current bag | |
| bean_id | Yes |
Output Schema
| Name | Required | Description |
|---|---|---|
| bag_id | Yes | |
| bean_id | Yes | |
| verdict | Yes | |
| age_days | Yes | |
| warnings | Yes | |
| roast_date | Yes | |
| rest_window | Yes | |
| verdict_code | Yes | |
| days_off_roast | Yes | |
| grams_remaining | Yes | |
| days_since_opened | Yes | |
| effective_age_days | Yes | |
| frozen_days_excluded | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare that this is a read-only, idempotent, non-destructive, closed-world operation. The description adds useful behavioral context by explaining that it computes age off roast and a resting/staling verdict, and that it resolves to the current bag unless a bag is specified.
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 a single front-loaded sentence with no filler. Every clause contributes either the computation performed, the verdict returned, or the bag-selection behavior.
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?
The tool is simple, an output schema exists, and annotations cover its safety profile, so the description does not need to explain return values or side effects. It is nearly complete, with only minor room to clarify the required bean_id parameter.
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 50%: bag_id is documented in the schema, but bean_id has no schema description. The description partially compensates by implying bean_id identifies the coffee and clarifying that bag_id defaults to the current bag, but it does not explicitly explain the required bean_id parameter or its role.
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 uses a specific verb and resource: it computes a bag's age in days off roast and its resting/staling verdict. It also distinguishes the default current-bag behavior from an explicitly named bag, so an agent can identify the tool's function without inspecting the 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 clear operational context: use the coffee's current bag by default or target a named bag. It does not explicitly state when to prefer this tool over siblings, but no sibling provides an equivalent age/verdict computation, so the usage is sufficiently clear.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
delete_shotDelete a shotADestructiveIdempotentInspect
Delete a logged shot from history. Restores the bean's remaining weight (which is derived from logged doses). Hard delete: there is no undo. To fix a mistake on an otherwise-valid shot, prefer update_shot over delete-and-relog.
| Name | Required | Description | Default |
|---|---|---|---|
| shot_id | Yes | ID of the shot to delete |
Output Schema
| Name | Required | Description |
|---|---|---|
| status | Yes | |
| message | Yes | |
| deleted_shot_id | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare destructiveHint=true, so the irreversibility itself is structured data — but the description adds real information beyond it: the bean's remaining weight is restored and is derived from logged doses. That side effect could not be inferred from annotations or schema. Minor gap: the idempotentHint=true annotation sits slightly awkwardly with a hard delete (a second call would target a missing row), and the description does not address repeat-call behavior.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Three short sentences, front-loaded with the action, then the non-obvious side effect, then the routing rule. Nothing is wasted and nothing important is buried.
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?
Output schema exists so return values need not be explained, and annotations cover the safety profile. Combined with the side-effect and alternative-tool guidance, an agent has everything needed to call this correctly and safely.
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 single parameter is documented as 'ID of the shot to delete'. The description adds no format, sourcing, or lookup guidance (e.g. where to get shot_id) beyond the schema, 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 and resource ('Delete a logged shot from history') and immediately separates it from the sibling that handles corrections ('prefer update_shot over delete-and-relog'). An agent can distinguish it from update_shot 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?
Gives an explicit when-to-use condition: only for removing a shot from history, not for fixing a mistake on a valid shot — in which case update_shot is named as the alternative. This is exactly the routing guidance the dimension asks for.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
diagnose_previewPreview a diagnosisARead-onlyIdempotentInspect
Sandbox-only diagnosis, writes nothing (no verdict, no recommendation-trail entry). Two modes: pass shot_id to dry-run a LOGGED shot (optionally overriding its sensory_tags, for the "what would this read as?" preview; the shot's own bean and its age at pulled_at are used), or pass the full metric set (bean_id, grinder_id, machine_id, grind_label, dose_g, yield_g, time_s, source) for a hypothetical shot. Identical output shape to diagnose_shot, including bean_context.
| Name | Required | Description | Default |
|---|---|---|---|
| dose_g | No | Dose in grams | |
| source | No | Grinder position source. Affects G1 warning (raw mode only) | |
| time_s | No | Extraction time in seconds | |
| bean_id | No | Coffee bean ID (must belong to this account) | |
| shot_id | No | Preview a logged shot by ID (dry-run; ignores the metric params below) | |
| yield_g | No | Yield in grams | |
| grinder_id | No | Grinder ID (must belong to this account) | |
| machine_id | No | Machine ID (must belong to this account) | |
| grind_label | No | Grinder setting label, e.g. "1.1.3" | |
| sensory_tags | No | Sensory observations, e.g. ["sour","bitter"]. With shot_id: replaces the stored tags for this preview (omit to use stored; [] = none). |
Output Schema
| Name | Required | Description |
|---|---|---|
| facts | Yes | |
| category | Yes | |
| warnings | Yes | |
| hypotheses | Yes | |
| kb_version | Yes | |
| bean_context | Yes | |
| warning_codes | Yes | |
| one_variable_only | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already cover read-only/idempotent/non-destructive, and the description adds real value on top: it names exactly what is not produced (no verdict, no recommendation-trail entry), clarifies which bean and which age snapshot are used in shot_id mode, and defines the sensory_tags override semantics including the empty-array case.
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 key fact (writes nothing), then the two modes in dependency order. Dense and mostly earned, though the single long parenthetical sentence could be split for scanability.
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 no explanation, yet the description still points at parity with diagnose_shot including bean_context. Mode selection, side-effect profile, and parameter grouping are all covered for a 10-parameter, all-optional 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 coverage is 100%, so a 3 is the floor, but the description earns more: with zero required parameters declared, saying that the hypothetical mode needs the full metric set (bean_id, grinder_id, machine_id, grind_label, dose_g, yield_g, time_s, source) tells the agent which subset to supply. It adds no format or unit detail beyond the schema, which is fine given full coverage.
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 (sandbox-only diagnosis preview) and immediately names its sibling diagnose_shot as the output-equivalent, so the agent can triangulate its role without opening another schema. The two operating modes are named concretely.
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 explains the two invocation paths and their conditions: shot_id to dry-run a logged shot, or the full metric set for a hypothetical shot. It stops short of an explicit when-not statement (e.g. 'use diagnose_shot to actually record a verdict'), leaving that contrast implied by naming the sibling.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
diagnose_shotDiagnose a shotARead-onlyIdempotentInspect
Evaluate shot metrics to provide ranked hypotheses (C6) and warn on flip-flops (G2) or fatigue (G6). Resolves the SHOT's own bean (age computed at the shot's pulled_at), never the active profile, and echoes it as bean_context, so diagnosing an older or differently-filed shot is always safe. The engine reads metrics and sensory tags, NOT free-text notes, so make sure taste feedback is recorded as sensory_tags on the shot (via log_shot or update_shot) before diagnosing; otherwise an in-range shot that tastes bad will come back "balanced".
| Name | Required | Description | Default |
|---|---|---|---|
| shot_id | No | Optional shot ID; defaults to last pulled shot. |
Output Schema
| Name | Required | Description |
|---|---|---|
| facts | Yes | |
| category | Yes | |
| warnings | Yes | |
| hypotheses | Yes | |
| kb_version | Yes | |
| bean_context | Yes | |
| warning_codes | Yes | |
| one_variable_only | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already cover the safety profile (readOnly, idempotent, non-destructive), and the description adds real substance beyond them: bean resolution semantics, the echo of bean_context, and the fact that the engine ignores free-text notes. It does not discuss output shape or confidence limits, but the added context is well above the annotation baseline.
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 function and warnings, then scope, then the prerequisite. The rule codes (C6/G2/G6) are opaque without KB context and occupy space that could be plainer, but there is no filler.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
An output schema exists, so return values need not be explained, and the description supplies the missing behavioral context: bean resolution, the sensory_tags requirement, and what warnings to expect. Adequate for a zero-required-param read tool, with only the sibling routing left implicit.
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 single parameter's default (last pulled shot) is documented in the schema itself. The description adds no independent detail about shot_id, 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 and resource: evaluate shot metrics and return ranked hypotheses plus flip-flop/fatigue warnings. The scope clarification (resolves the shot's own bean, not the active profile) helps separate it from a preview-style diagnosis, but it never explicitly names diagnose_preview as the alternative.
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 a concrete prerequisite: sensory feedback must be recorded as sensory_tags on the shot via log_shot/update_shot before calling, otherwise bad-tasting in-range shots come back 'balanced'. That is a clear use condition, though it stops short of stating when to prefer this over diagnose_preview.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
get_dial_stateGet current dial stateARead-onlyIdempotentInspect
Retrieve current dialing state, active context, recent shots, recommendations, and locked recipes.
| Name | Required | Description | Default |
|---|---|---|---|
No parameters | |||
Output Schema
| Name | Required | Description |
|---|---|---|
| recent_shots | Yes | |
| active_coffee | Yes | |
| locked_recipe | Yes | |
| active_grinder | Yes | |
| active_machine | Yes | |
| active_program | Yes | |
| maintenance_summary | Yes | |
| recent_recommendations | Yes |
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 operation. The description adds useful behavioral context by disclosing the aggregate contents returned, including active context, recent shots, recommendations, and locked recipes, though it does not discuss freshness or 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?
The description is a single front-loaded sentence with no wasted words. The action and the returned content are presented immediately.
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?
This is a zero-parameter, read-only aggregate tool with an output schema, so the description does not need to document parameters or return structure. It sufficiently states what the tool retrieves and what categories of data the agent should expect.
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 has zero parameters, so there are no parameter semantics for the description to explain. Per the baseline for zero-parameter tools, a 4 is appropriate.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description uses a specific verb (Retrieve) and a clear resource (current dialing state), then enumerates the bundled content: active context, recent shots, recommendations, and locked recipes. It distinguishes the tool from simple list tools by framing it as an aggregate current-state read, though it does not explicitly name sibling alternatives.
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 by the phrase 'current dialing state' and the listed outputs, suggesting the tool is for getting a consolidated dialing overview. However, the description gives no explicit when-to-use guidance, no prerequisites, and no comparison to siblings such as list_shots or suggest_next_step.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
get_kb_versionGet knowledge base versionARead-onlyIdempotentInspect
Retrieve the current version of the knowledge base.
| Name | Required | Description | Default |
|---|---|---|---|
No parameters | |||
Output Schema
| Name | Required | Description |
|---|---|---|
| kb_version | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare readOnlyHint, idempotentHint, and destructiveHint, so the safety profile is fully covered. The description adds no extra behavioral context beyond the basic retrieval action, but it does not contradict the annotations either. Given the low bar enabled by rich annotations, a neutral score of 3 is appropriate.
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 a single, well-structured sentence that states the exact operation and target. There is no redundant or filler content, and the key information is front-loaded. It earns its place by being perfectly compact and informative at a basic level.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Given the tool's simplicity, an output schema exists to define the return value, and annotations cover the operational behavior, nothing critical is missing from the description. It could have added a hint about what 'knowledge base version' refers to, but for a zero-parameter read-only getter, the description is sufficiently complete.
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 has zero parameters, so there is no parameter information to explain. Per the rubric, a 0-parameter tool gets a baseline of 4; the description does not need to compensate for any schema gaps because there are no parameters.
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 uses the specific verb 'Retrieve' and identifies the resource as 'the current version of the knowledge base,' making the tool's purpose immediately clear. It does not differentiate itself from siblings, but no sibling appears to handle the same operation, so the lack of explicit distinction is not a significant gap.
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 usage context is implied by the name and description: an agent would naturally use this to get the knowledge base version. However, the description gives no explicit guidance about when to prefer this over related tools like kb_changelog or get_stats, nor any conditions under which it should not be used.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
get_maintenance_guidesGet maintenance guidesARead-onlyIdempotentInspect
Step-by-step maintenance guides: tools, supplies, steps and warnings, in our own words with the maker's documents as sources. With no arguments, every guide for the user's current grinders and machines (and the water filter fitted in each). With guide_ids, those guides; the ids come from maintenance.tasks[].guide.id in list_grinders and list_machines. Ids that match no guide are listed under missing.
| Name | Required | Description | Default |
|---|---|---|---|
| guide_ids | No | Optional: the guides to fetch. Omit for every guide the user's equipment can use |
Output Schema
| Name | Required | Description |
|---|---|---|
| guides | Yes | |
| missing | Yes | |
| catalog_version | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already cover read-only, idempotent, non-destructive, closed-world behavior. The description adds meaningful operational context: default scope, id provenance, unmatched-id reporting under 'missing', and that guide content is synthesized from maker documents.
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 front-loaded sentences with no filler; each sentence carries either mode selection, scope, id provenance, or edge-case behavior. Dense but appropriately sized for a retrieval tool with default and filtered modes.
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 need not explain the return shape. It covers content type, default scope, id source, and unmatched-id handling, while annotations carry the safety profile, so nothing material is missing for correct invocation.
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%, but the description still adds substantial meaning beyond the schema: guide_ids should come from maintenance.tasks[].guide.id in list_grinders and list_machines, omitting the parameter fetches all guides for current equipment, and unmatched ids are reported under 'missing'.
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, enumerates the guide contents (tools, supplies, steps, warnings), and explains both invocation modes. It clearly distinguishes this retrieval tool from scheduling/due-list siblings by naming the sibling tools only as id sources.
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 no-argument behavior (all guides for current grinders, machines, and fitted water filters) and the guide_ids behavior, including where ids come from. It does not explicitly compare against siblings such as list_maintenance_due or log_maintenance, nor does it state when not to use this tool.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
get_ruleGet a dialing ruleARead-onlyIdempotentInspect
Retrieve the detailed text of a specific rule from the knowledge base by its rule ID.
| Name | Required | Description | Default |
|---|---|---|---|
| rule_id | Yes | The ID of the rule to fetch, e.g. CAT.DARK |
Output Schema
| Name | Required | Description |
|---|---|---|
| text | Yes | |
| rule_id | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare readOnlyHint=true, idempotentHint=true, and destructiveHint=false, so the safety profile is covered. The description adds minor behavioral context by promising 'detailed text' as the return content, but does not disclose error/not-found behavior. No contradiction exists.
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?
A single sentence with no filler; the core operation, resource, and identifier are stated immediately. Every word earns its place.
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 simple, idempotent, read-only lookup with one fully documented parameter and an output schema, the description provides sufficient context. It does not explain what kinds of rules exist or where rule IDs originate, but those are not necessary for correct invocation.
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 single parameter rule_id is fully described in the input schema (100% coverage), including an example value 'CAT.DARK'. The description only reinforces that lookup is by rule ID, adding no significant meaning 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?
The description identifies a specific action ('Retrieve the detailed text'), a specific resource ('a specific rule from the knowledge base'), and the lookup key ('by its rule ID'). It is clear, though it does not explicitly distinguish itself from sibling getters such as get_dial_state or get_kb_version.
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: when you have a rule ID and need the rule text. However, it provides no explicit guidance on when not to use this tool or which sibling tool to prefer for related lookups.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
get_statsGet statisticsARead-onlyIdempotentInspect
Get compact flat usage stats for a grinder, machine, or bean.
| Name | Required | Description | Default |
|---|---|---|---|
| id | Yes | The entity ID | |
| scope | Yes | The stats scope |
Output Schema
| Name | Required | Description |
|---|---|---|
| brews | Yes | |
| last_bean | No | |
| last_used | No | |
| grams_ground | No | |
| effective_age | No | |
| beans_consumed | No | |
| grams_consumed | No | |
| grams_remaining | No | |
| last_grind_setting | No |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
The annotations already declare readOnlyHint=true, idempotentHint=true, and destructiveHint=false, covering the safety profile. The description adds that stats are 'compact flat', which hints at the output shape, but it does not disclose aggregation details, time range, or any other behavioral nuances beyond what annotations provide.
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 a single, compact sentence that front-loads the essential information. Every word contributes: the action, the output type, and the supported scopes.
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 simple two-parameter read-only tool with an output schema and comprehensive annotations, the description is complete enough. The schema covers parameters, annotations cover behavior, and the output schema covers return structure, leaving no critical gaps.
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 fully. The description adds minimal parameter meaning beyond echoing the scope enum ('grinder', 'machine', 'bean') and the notion of usage stats, so a baseline score of 3 is appropriate.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description clearly identifies the action ('Get'), the resource type ('usage stats'), and the supported scopes ('grinder, machine, or bean'). This distinguishes it from sibling getters like get_dial_state and get_rule, which target different kinds of information.
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 when to use the tool: when you need usage statistics for one of the three entity types. However, it does not explicitly contrast with alternatives or state when not to use it, such as when listing entities or retrieving state information.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
grinder_mathGrinder mathBRead-onlyIdempotentInspect
Determine steps/clicks difference and directions between setting labels (C3).
| Name | Required | Description | Default |
|---|---|---|---|
| to_label | Yes | ||
| from_label | Yes | ||
| grinder_id | Yes |
Output Schema
| Name | Required | Description |
|---|---|---|
| steps | Yes | |
| direction | Yes | |
| step_unit | Yes | |
| burr_gap_travel_microns | Yes | |
| relative_coarseness_note | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare readOnlyHint, idempotentHint, and destructiveHint=false, and the description's 'Determine' is consistent with a safe computation. It adds that the result is a steps/clicks difference and direction, but does not reveal additional behavioral nuance such as label assumptions or failure behavior.
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?
A single sentence with no filler, and the key operation is front-loaded. The unexplained 'C3' parenthetical costs it a top score because it is cryptic rather than clarifying.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a read-only math utility with an output schema, the high-level purpose is enough for selection, but the agent must guess the labeling convention and why grinder_id is required. Combined with no usage routing, the definition is workable but not fully self-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?
With 0% schema description coverage, the description must carry the meaning, but it only loosely connects from_label/to_label as 'setting labels' and never explains the label syntax or the grinder_id parameter. It also doesn't state the mapping between labels and steps/clicks, which is the core semantic the agent needs.
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?
Clearly identifies a calculation: it determines the difference/direction in steps/clicks between two setting labels, so an agent knows what the tool computes. It does not explicitly distinguish itself from siblings like set_grinder_position, and the parenthetical 'C3' is unexplained.
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 no guidance on when to call this rather than a sibling such as set_grinder_position or suggest_next_step. It neither states prerequisites (e.g., a registered grinder) nor when the math should be used, so an agent must infer from context.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
kb_changelogKnowledge base changelogARead-onlyIdempotentInspect
Retrieve the changelog showing updates and version differences for the knowledge base.
| Name | Required | Description | Default |
|---|---|---|---|
No parameters | |||
Output Schema
| Name | Required | Description |
|---|---|---|
| changelog | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
The description is consistent with the annotations (readOnlyHint=true, idempotentHint=true, destructiveHint=false). It adds mild context by specifying the changelog content (updates and version differences), but it does not describe ordering, scope, or any additional behavioral detail. Given the annotations already cover safety, this is adequate but not rich.
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?
One clear sentence with no filler. The main action and content are front-loaded, and every word adds meaning.
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 simple, parameterless read-only tool with rich annotations and an output schema present, the description is sufficient. An agent can correctly infer what the tool returns and that invoking it is safe and non-mutating.
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 has zero parameters, so there is no parameter semantics to explain. The baseline of 4 applies here. The schema coverage is 100% trivially, and the description does not need to compensate for undocumented parameters.
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 ('Retrieve') and resource ('changelog') and clarifies what it contains ('updates and version differences for the knowledge base'). It distinguishes from the sibling get_kb_version by indicating full version history rather than the current version.
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 intended use is reasonably clear from the description: retrieve knowledge-base changelog/history. However, it does not explicitly mention when to use this tool over get_kb_version or other knowledge-related tools, nor does it state any exclusions. The usage context is implied rather than explicit.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
list_beansList coffeesARead-onlyIdempotentInspect
List the coffees registered for the account, with status filter. Each coffee carries its bags[] (every purchase, with its own freshness and grams left) and current_bag_id; the row's top-level roast_date, state, grams_remaining and age fields are the current bag's. The id on each row is the number this account knows that coffee by, counting from 1: safe to show, and what other tools expect back; bag ids are a separate series.
| Name | Required | Description | Default |
|---|---|---|---|
| status | No | Filter by status: current, archived, or all. Defaults to current. |
Output Schema
| Name | Required | Description |
|---|---|---|
| beans | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare this as a safe, read-only, idempotent operation. The description adds useful behavioral context beyond annotations by explaining that each coffee carries bags[], current_bag_id, and that top-level roast_date/state/grams_remaining/age fields belong to the current bag.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is front-loaded with the core purpose, then adds relevant data-model and ID clarifications. It is somewhat dense for a one-parameter list tool, but every sentence provides useful context rather than repeating 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?
Given the low complexity, full schema coverage, existing output schema, and annotations covering safety, the description is complete enough for correct invocation. It additionally resolves the potentially confusing distinction between coffee ids and bag ids.
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 status enum is fully documented in the schema, so the schema carries the parameter semantics. The description only restates that there is a status filter, without adding format or default behavior 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?
The description gives a specific verb and resource: listing coffees registered for the account, with a status filter. It clearly separates coffee rows from bag data, but it does not explicitly distinguish this tool from siblings such as register_coffee or update_bean.
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 by 'List the coffees registered for the account' with a status filter, so an agent can infer this is for browsing coffees. However, there is no explicit when-to-use guidance, no exclusions, and no named alternatives for cases such as creating or updating coffees.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
list_grindersList grindersARead-onlyIdempotentInspect
List grinders registered for the account, with status filter. The id on each row is the number this account knows that record by, counting from 1: safe to show, and what other tools expect back. Each row carries its maintenance block: every task with its class (S schedule, H habit, Y symptom, A the machine signals it, T technician, N never, U unstated, E event), due state, and the guide to follow.
| Name | Required | Description | Default |
|---|---|---|---|
| status | No | Filter by status: current, archived, or all. Defaults to current. | |
| maintenance | No | How much of each row's maintenance block to include. compact (default): every task with its class, due state, schedule and guide. full: also the maker's own words (quote, source, alternates, the interval as written). |
Output Schema
| Name | Required | Description |
|---|---|---|
| grinders | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare readOnlyHint, idempotentHint, and non-destructive, so safety is covered. The description adds genuinely useful non-obvious behavior: the `id` is a per-account ordinal counting from 1, safe to display, and the handle other tools expect back. It explains the row contents, but not pagination or ordering.
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 is front-loaded in the first clause, followed by the id contract and then the row shape. The class-code list (S/H/Y/A/T/N/U/E) is dense but each token is load-bearing for interpreting output, so it earns its space. Still one long sentence in the middle section.
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 don't need full explanation, yet the description still clarifies the non-obvious id semantics and class-code vocabulary, which are the main interpretation hazards. It omits ordering and pagination, which is the remaining gap.
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 both `status` and `maintenance` are fully documented in the schema. The description restates 'status filter' and the maintenance block contents but adds little parameter-level detail beyond the schema, which is the baseline-3 case.
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 with scope: 'List grinders registered for the account, with status filter.' An agent knows exactly what it returns. It does not, however, distinguish itself from siblings like list_maintenance_due or get_maintenance_guides, which also surface maintenance information.
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 by 'with status filter' and by the maintenance compaction choice. There is no explicit when-to-use or when-to-prefer-a-sibling guidance, no mention of list_maintenance_due for due-only queries, and no exclusions.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
list_machinesList espresso machinesARead-onlyIdempotentInspect
List machines registered for the account, with status filter. The id on each row is the number this account knows that record by, counting from 1: safe to show, and what other tools expect back. Each row carries its maintenance block, researched per model: every task with its class, due state, what the maker forbids, and the guide to follow. settings lists the selectors its model has and where each stands (null: unknown model, or none).
| Name | Required | Description | Default |
|---|---|---|---|
| status | No | Filter by status: current, archived, or all. Defaults to current. | |
| maintenance | No | How much of each row's maintenance block to include. compact (default): every task with its class, due state, schedule and guide. full: also the maker's own words (quote, source, alternates, the interval as written). |
Output Schema
| Name | Required | Description |
|---|---|---|
| machines | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare readOnly, idempotent, non-destructive behavior, so the bar is lower. The description nonetheless adds genuinely useful behavioral context: the `id` is account-relative and counts from 1 (safe to display, and what other tools expect back), and `settings` is null when the model is unknown or has no selectors. Those are non-obvious traits an agent would otherwise have to discover by trial.
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 core purpose and the ID semantics are front-loaded, and every sentence conveys information about the payload that the agent would need. The second and third sentences are dense and slightly overloaded, but no sentence is filler.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
An output schema exists, so return values need not be explained, yet the description still covers the two traps: account-relative IDs and null settings. Combined with annotation coverage, an agent has enough to call this correctly; only the relationship to sibling listing tools is left unaddressed.
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 both parameters are enums fully documented in the schema, so the baseline is 3. The description mentions the status filter but adds no syntax or default information beyond the schema, and the `maintenance` parameter's compact/full distinction is left entirely to 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?
The first sentence states a specific verb and resource: 'List machines registered for the account, with status filter.' That is unambiguous and distinguishable from register_machine and update_machine. It does not, however, explicitly separate itself from list_maintenance_due or list_grinders, which is what a 5 would require.
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 the listing and filtering use case via 'with status filter' and describes what the rows contain, but never says when to choose this tool over list_maintenance_due or when a full maintenance block is warranted. Usage must be inferred from the payload description rather than being stated.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
list_maintenance_dueList maintenance dueARead-onlyIdempotentInspect
What maintenance is due across the user's current grinders and machines, most urgent first. Use it for "is anything due?". Only tasks with an interval compete: a task the machine counts and signals itself, one done by habit or when a symptom shows, and one the maker advises against never appear. Each item says how far along it is (ratio, done of every, on which basis), whether it is coming up (soon), and whether the interval is the user's, the maker's or ShotPulled's default.
| Name | Required | Description | Default |
|---|---|---|---|
| status | No | due (default): due or overdue, and not muted. all: every scheduled task, muted ones last |
Output Schema
| Name | Required | Description |
|---|---|---|
| items | Yes | |
| computed_at | Yes | |
| catalog_version | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already establish read-only, idempotent, non-destructive behavior, so the bar is lower. The description nonetheless adds real behavioral context beyond the annotations: only interval-based tasks are considered, and machine-counted, habit-driven, and maker-discouraged tasks never appear — a meaningful scoping rule an agent could not guess.
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 is front-loaded in the first sentence, followed by usage context and then item-level semantics. Three sentences with little waste, though the final sentence overlaps with what the output schema presumably documents.
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 safety fully covered by annotations, a single enum parameter, and an output schema, the description supplies the pieces the structured fields cannot: ordering, inclusion/exclusion rules, and the provenance of each interval (user, maker, or ShotPulled default). Complete enough for correct invocation.
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 single enum parameter carries its own explanation (due = due/overdue and not muted; all = every task, muted last). The description never references the status parameter, so it adds no meaning beyond the schema; 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 query over a specific resource — what maintenance is due across the user's current grinders and machines — plus output ordering (most urgent first). It is clearly distinguishable from sibling tools like set_maintenance_schedule, log_maintenance, and get_maintenance_guides, which write or reference guidance rather than report current status.
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?
"Use it for 'is anything due?'" gives a concrete triggering question, and the exclusion rules clarify what the answer will and will not contain. However, it never names an alternative tool (e.g. get_maintenance_guides for how-to, log_maintenance for recording work), so the agent must infer when another sibling is the better call.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
list_recipesList locked recipesCRead-onlyIdempotentInspect
List recipes (all or filtered by equipment and status). The id on each row is the number this account knows that record by, counting from 1: safe to show, and what other tools expect back.
| Name | Required | Description | Default |
|---|---|---|---|
| status | No | Filter by status: current, archived, or all. Defaults to current. | |
| bean_id | No | ||
| grinder_id | No | ||
| machine_id | No |
Output Schema
| Name | Required | Description |
|---|---|---|
| recipes | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare readOnly, idempotent, non-destructive, and closed-world, so the safety profile is covered. The description adds one genuinely useful behavioral fact — the `id` is an account-local sequential number safe to display and usable as a key elsewhere — but says nothing about ordering, pagination, or empty results.
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, no filler, front-loaded with the core action. The second sentence is convoluted ("the number this account knows that record by, counting from 1") where "account-local sequential ID" would say it faster.
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 shape needn't be explained, and annotations cover safety. But with three of four parameters undocumented and no statement of filter-combination semantics or default behavior, the description does not close the gaps the structured data leaves.
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 only 25%: `status` is documented in the schema but bean_id, grinder_id, and machine_id have nothing. The phrase "filtered by equipment and status" implies those three IDs are equipment filters, but never says what each one selects or how multiple filters combine (AND vs OR).
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 ("List recipes") plus the two filtering axes (equipment and status), which is enough to distinguish it from mutation siblings like lock_recipe or update_shot. It stops short of differentiating it from other list_* tools (list_shots, list_beans), which share the same shape.
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?
There is no explicit when-to-use guidance and no named alternative. The only usage signal is the implicit hint that the returned `id` is "what other tools expect back," which suggests chaining but never states the condition that selects this tool over a sibling.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
list_scalesList scalesARead-onlyIdempotentInspect
List registered scales for the account. The id on each row is the number this account knows that record by, counting from 1: safe to show, and what other tools expect back.
| Name | Required | Description | Default |
|---|---|---|---|
| status | No | Filter by status: current (unarchived), archived, or all. Defaults to current. |
Output Schema
| Name | Required | Description |
|---|---|---|
| scales | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare readOnlyHint, idempotentHint, destructiveHint=false, and openWorldHint=false, so the description does not need to restate safety. It adds valuable behavioral context by explaining that the id is a stable, user-facing number counting from 1 and is what other tools expect back.
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, front-loaded with the purpose and then a useful clarification about the id field. Every sentence contributes without repetition or filler.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Given the simple one-parameter schema, rich annotations, and an existing output schema, the description is complete enough for correct invocation. It covers purpose and the non-obvious id semantics without needing to explain return values.
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%, including a fully documented status enum with default behavior, so the schema carries parameter semantics. The description adds no additional detail about the status parameter, making the baseline 3 appropriate.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description states a specific verb and resource ("List registered scales") and scopes it to the account, clearly distinguishing it from register_scale, update_scale, and the other list_* siblings by resource.
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 conveys the basic purpose but gives no explicit guidance on when to choose list_scales over alternatives, no prerequisites, and no exclusions. The note about id semantics is useful but does not tell an agent when to invoke the tool.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
list_shotsList shotsARead-onlyIdempotentInspect
List shot history with support for pagination and filtering. Every shot carries a derived taste_pending flag (1 = logged with no sensory tags, no rating, and no tasted flip: the tasting is still owed and can be backfilled with update_shot).
| Name | Required | Description | Default |
|---|---|---|---|
| limit | No | Number of records to return (1-500) | |
| offset | No | Offset for pagination | |
| filters | No |
Output Schema
| Name | Required | Description |
|---|---|---|
| shots | Yes | |
| total | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare a safe, idempotent read, so the description correctly spends its words elsewhere: it discloses that taste_pending is a derived flag and defines precisely what makes it 1. It does not state default sort order or whether filtering combines with AND, which are meaningful behavioral details for a list tool.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Two sentences, front-loaded with capability and then the derived-field explanation. The taste_pending parenthetical is dense but every clause adds information an agent cannot get from the name alone; 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?
With an output schema present, the description needn't explain return values, and annotations cover the safety profile. What remains thin is ordering and filter-composition behavior, but the core call-correctly information is present.
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 67%, so the schema already carries most parameter meaning, including a taste_pending definition nearly identical to the description's. The description adds the actionable consequence (backfill via update_shot) but says nothing about how limit/offset behave at boundaries or how multiple filters compose. Baseline 3 fits.
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 ("List shot history") plus the two capabilities that matter (pagination, filtering). It does not distinguish itself from neighbors like get_stats or diagnose_shot, but the resource is concrete enough that an agent can identify the tool's job.
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 for use (history retrieval with pagination/filtering) and explicitly names update_shot as the path for backfilling an owed tasting, which is real routing guidance. No exclusion rules tell the agent when to prefer get_stats or diagnose_shot instead, keeping it below a 5.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
list_watersList water recipesARead-onlyIdempotentInspect
List registered waters for the account. The id on each row is the number this account knows that record by, counting from 1: safe to show, and what other tools expect back.
| Name | Required | Description | Default |
|---|---|---|---|
| status | No | Filter by status: current (unarchived), archived, or all. Defaults to current. |
Output Schema
| Name | Required | Description |
|---|---|---|
| waters | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already establish that this is a safe, read-only, idempotent operation, so the bar is lower. The description adds useful return-value context: each row's id is account-scoped, starts at 1, is safe to expose, and is what other tools expect. It does not cover ordering or pagination, but adds meaningful behavioral detail beyond annotations.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Two tight sentences, front-loaded with purpose and followed by a relevant note about IDs. There is no wasted text.
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 simple list tool with full schema coverage, strong annotations, and an output schema, the description supplies what is needed and adds an important note about ID semantics. Nothing essential for correct invocation is missing.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 100%, and the only parameter is an enum with a clear description and default. The tool description does not add further meaning about the status filter, so baseline 3 is appropriate.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description states a clear verb and resource: 'List registered waters for the account.' It is easy to distinguish from register_water or update_water, but it does not explicitly differentiate itself from other list_* 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?
It says what the tool does but gives no guidance on when to use it versus related tools such as list_recipes or the register/update water tools. There are no exclusions, prerequisites, or alternative-selection hints.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
lock_recipeLock a recipeADestructiveIdempotentInspect
Lock a successful shot as the reference dialing recipe for this equipment profile. It overwrites the recipe already locked for the same coffee, grinder, machine, program and drink intent, which keeps its recipe_id.
| Name | Required | Description | Default |
|---|---|---|---|
| drink_intent | Yes | ||
| from_shot_id | Yes |
Output Schema
| Name | Required | Description |
|---|---|---|
| status | Yes | |
| message | Yes | |
| recipe_id | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare destructiveHint=true and idempotentHint=true, but the description adds the critical specifics beyond that: it overwrites only the recipe matching the same coffee/grinder/machine/program/drink-intent tuple, and preserves the existing recipe_id. That explains exactly what is destroyed and how identity is retained, which the annotations alone cannot convey.
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, no filler, and the definition of the action is front-loaded before the overwrite rule. Every clause earns its place.
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 the annotations cover the safety profile. It covers the mutation effect well; only minor gaps remain, such as failure behavior or why drink_intent (straight/milk) is a required selector.
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?
With 0% schema coverage the description must carry the load, and it does: it frames from_shot_id as the 'successful shot' source and names the composite key (coffee, grinder, machine, program, drink intent) that determines which record drink_intent selects. This meaningfully exceeds the bare enum/integer schema, though from_shot_id's exact semantics remain only implied.
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 (lock) and resource (recipe) and defines what locking means: promoting a successful shot to the reference dialing recipe for the equipment profile. This clearly separates it from list_recipes, update_shot, or log_shot.
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 phrase 'Lock a successful shot' implies you should have a successful shot to promote, which is implied usage context. However, it never states when-not to use it or points to any alternative (e.g., list_recipes or update_shot), leaving the routing to inference.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
log_maintenanceLog maintenanceAInspect
Log a cleaning or maintenance job against a piece of equipment. A task that takes the thing apart opens a calibration epoch, and every recipe locked before it is read through that epoch's offset. Record the offset here if you counted the clicks while reassembling, which is the one moment anybody actually knows it. Any task in the maintenance vocabulary can be logged against a grinder or machine it belongs to, including one the maker advises against, because the log records what was done. Read each piece of equipment's tasks, their intervals and their due state from list_grinders and list_machines.
| Name | Required | Description | Default |
|---|---|---|---|
| note | No | Optional: what you did, and anything that surprised you | |
| task | Yes | Which maintenance job was performed | |
| details | No | Fields specific to this task. Which ones a task takes is published as details_fields on each task; a burr clean takes none | |
| evidence | No | One line recording what the measurement rested on, e.g. "Counted 6 clicks coarser at reassembly." | |
| guide_id | No | Optional: the id of the maintenance guide that was followed. Must be a guide for this task | |
| equipment_id | Yes | The ID of that piece of equipment | |
| offset_value | No | The correction, if you measured it now: clicks to ADD to a pre-clean reading to get the same grind today, signed along the collar's own number direction. Omit it and the epoch stays unmeasured, which is a state the app shows rather than a zero it assumes | |
| performed_at | No | When it was done (ISO 8601 or YYYY-MM-DD HH:MM:SS, UTC). Defaults to now; backdating is fine | |
| disturbs_zero | No | Whether this job disturbed the reference the stored numbers are read against: for a burr clean, whether the burrs actually came out. Defaults to the task's own answer; send 0 for a wipe-down that left the collar alone | |
| offset_source | No | How the offset was arrived at: pull (a reference shot), counted (clicks counted at reassembly), typed (asserted directly) | |
| equipment_kind | Yes | Which kind of equipment this job was done on |
Output Schema
| Name | Required | Description |
|---|---|---|
| entry | Yes | |
| deduped | Yes | |
| message | Yes | |
| entry_id | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Adds substantial behavior beyond annotations: a disassembly task opens a calibration epoch, prior locked recipes are reinterpreted through that epoch's offset, and omitting offset_value leaves the epoch visibly unmeasured rather than assumed zero. These are consequential side effects not derivable from readOnly=false/destructive=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?
Purpose and epoch consequence are front-loaded and almost every sentence carries information. A few asides ('which is the one moment anybody actually knows it') add flavor at some cost to terseness.
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 an 11-parameter write tool with nested details and an output schema, the description covers the epoch mechanics, offset omission state, and evidence capture well. It does not address duplicate or repeated logging behavior, which matters given idempotentHint=false.
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 already 100%, but the description still adds meaning: offset_value is defined as a signed clicks-to-add correction along the collar's direction, offset_source enumerates pull/counted/typed, and details is tied to the per-task details_fields published elsewhere.
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?
Opens with a specific verb and resource: 'Log a cleaning or maintenance job against a piece of equipment.' It also distinguishes itself from read-side siblings by pointing at list_grinders/list_machines for due state and from set_maintenance_offset by owning the offset recorded at log time.
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 conditions: record the offset only if you counted clicks at reassembly; any vocabulary task may be logged even if the maker advises against it; read due state from list_grinders/list_machines. No explicit when-not guidance relative to list_maintenance_due or set_maintenance_offset, which leaves some sibling ambiguity.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
log_recommendationLog a recommendationCInspect
Log a recommended dialing change to allow contradiction/oscillation checking (G2).
| Name | Required | Description | Default |
|---|---|---|---|
| lever | Yes | ||
| direction | Yes | ||
| rationale | Yes | ||
| confidence | Yes | ||
| cited_rules | No | ||
| based_on_shot | No |
Output Schema
| Name | Required | Description |
|---|---|---|
| status | Yes | |
| message | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already carry the mutation and non-idempotency signals, so the description's job is lighter. It adds context that this records a recommendation rather than a definitive change and notes the G2 analysis purpose, but says nothing about repeated logging effects or return behavior.
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 tight sentence with no filler, and the key action is front-loaded. The parenthetical G2 is opaque but does not add bloat.
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 six-parameter write tool with four required fields and no schema descriptions, this single sentence is too sparse. The purpose is clear, but the agent still lacks guidance on how to fill parameters, especially cited_rules and based_on_shot, and when this tool should be preferred over siblings.
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 0%, and the description only hints at a 'dialing change,' which loosely covers lever and direction. It does not explain confidence, cited_rules, or based_on_shot, and does not compensate for the schema's lack of parameter documentation.
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—log—and a distinct object, a recommended dialing change, which separates it from sibling log tools like log_shot and log_maintenance. It does not explicitly name an alternative, so it stops short of full differentiation.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description gives a purpose ('to allow contradiction/oscillation checking') but no explicit when-to-use or when-not-to-use guidance. It does not point to any alternative tools or exclusions, leaving the agent to infer when logging is appropriate.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
log_shotLog a shotAInspect
Log an espresso or alternative shot/brew attempt. Uses the active context (bean/grinder/machine/program) unless overridden via bean_id/grinder_id/machine_id/program_id. ALWAYS pass bean_id explicitly when the user names a specific coffee, so the shot cannot land on the wrong bag. Backdate with pulled_at when the shot happened earlier. When the user reports taste (bitter, sour, harsh, hollow…), include matching sensory_tags: the diagnosis engine reads tags and metrics, not free-text flavor_notes. When the user tasted the shot and reports it as GOOD/clean (no defects), pass tasted=1 with no sensory_tags. Otherwise a tag-less, rating-less shot is filed taste-pending as if never tasted.
| Name | Required | Description | Default |
|---|---|---|---|
| tds | No | Total Dissolved Solids percentage (e.g. 9.1 or 1.35) | |
| bag_id | No | Which bag of the coffee the shot came from; defaults to its current (open) bag. Bag numbers are on list_beans' bags[] | |
| dose_g | Yes | ||
| rating | No | ||
| tasted | No | 1 = the shot was tasted at log time. The explicit way to record a CLEAN tasting: sensory tags all describe defects, so a good shot has none. Without this flag (or a rating) it would be filed taste-pending. Tags or a rating also mark a shot as tasted; 0 (default) = taste later. | |
| time_s | Yes | ||
| bean_id | No | Override: log against this bean instead of the active one (null = active) | |
| verdict | No | ||
| yield_g | Yes | ||
| water_id | No | Optional references to waters formulation | |
| best_brew | No | 1 if marked as best brew, 0 otherwise | |
| favourite | No | 1 if favourite, 0 otherwise | |
| pulled_at | No | When the shot was actually pulled (ISO 8601 or "YYYY-MM-DD HH:MM:SS"), for backdated entries. Defaults to now (null = now). When backdating, pass the returned shot_id to diagnose_shot explicitly, because the default diagnosis target is the chronologically latest shot. | |
| beverage_g | No | Yield mass excluding cup/vessel weight in grams | |
| grinder_id | No | Override: grinder used, if not the active one (null = active) | |
| machine_id | No | Override: machine used, if not the active one (null = active) | |
| program_id | No | Override: machine program used, if not the active one (null = active) | |
| temp_taste | No | ||
| vessel_name | No | Cup/vessel name | |
| bloom_time_s | No | Pre-wetting or bloom duration in seconds | |
| drink_intent | No | ||
| flavor_notes | No | ||
| flow_profile | No | Opaque flow profile data (JSON/TEXT) | |
| method_tools | No | JSON representation of method tools used (e.g., paper filters, screen) | |
| observations | No | ||
| sensory_tags | No | ||
| finish_action | Yes | ||
| temperature_c | No | Brew temperature in Celsius | |
| data_confidence | No | measured = weighed/timed live; recalled = from memory; estimated = a best guess (e.g. "~25s" after missing the timer) | |
| vessel_weight_g | No | Cup/vessel weight in grams | |
| machine_settings | No | Only when this one shot was pulled with a selector somewhere other than the machine's recorded settings: {key: position}. The shot is otherwise stamped with those automatically; a lasting change goes through update_machine. | |
| pressure_profile | No | Pressure profile description or values | |
| first_drip_time_s | No | Time to first drip in seconds |
Output Schema
| Name | Required | Description |
|---|---|---|
| status | Yes | |
| message | Yes | |
| shot_id | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Beyond annotations (write, non-idempotent, non-destructive) it discloses two non-obvious behaviors: shots with no tags/rating are filed as taste-pending, and the diagnosis engine reads sensory_tags rather than flavor_notes. It does not mention the backdating interaction with diagnose_shot's default target (that hint lives in the schema), so a small gap remains.
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 purpose and active-context semantics, then ordered by decision importance (bean override → backdating → tasting). Dense but nearly every clause carries an actionable rule; the closing sentence is long and could be split, but nothing is filler.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a 33-parameter mutation tool with an output schema, the description covers the risky/ambiguous decisions well, but the four required fields (dose_g, yield_g, time_s, finish_action) have no description in either schema or text, and the many optional fields get no framing. Adequate but not complete for this surface area.
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 67%, so the description must add meaning for high-stakes params – it does for bean_id (wrong-bag risk), pulled_at (backdating semantics) and the sensory_tags/tasted/flavor_notes relationship (tags are defect-oriented, so a clean shot has none). Many optional params (verdict, drink_intent, observations, the metric fields) are left to the schema alone.
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?
"Log an espresso or alternative shot/brew attempt" states a specific verb and resource, and the body makes the scope concrete (active-context stamping, overrides, tasting state). It is clearly distinguishable from siblings like update_shot (edits an existing shot), diagnose_shot (analysis) and log_recommendation.
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?
Explicit conditional rules are given for the three decisions that matter: pass bean_id when the user names a coffee, use pulled_at for backdating, and pass tasted=1 with no tags for a clean shot. It also names the alternative handling (rating or tags) and the consequence of doing neither.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
merge_beansMerge two coffeesADestructiveInspect
Fold one coffee into another when the same coffee was registered twice. Every bag, shot, recipe and recommendation of from_bean_id moves to into_bean_id; the active coffee follows if it was the one merged away; origins move only if the target has none. Where both hold a locked recipe for the same grinder, machine, program and drink, the newer lock wins and the older is deleted. The source coffee is archived, never deleted. Irreversible: confirm both numbers with the user first (list_beans shows them).
| Name | Required | Description | Default |
|---|---|---|---|
| reason | No | Optional note, recorded on the surviving coffee's notes with the merge | |
| from_bean_id | Yes | The duplicate: the coffee number that will be emptied and archived | |
| into_bean_id | Yes | The coffee number that keeps everything |
Output Schema
| Name | Required | Description |
|---|---|---|
| moved | Yes | |
| status | Yes | |
| message | Yes | |
| into_bean_id | Yes | |
| active_followed | Yes | |
| replaced_recipes | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Far exceeds what the annotations convey: annotations only flag destructive=true and idempotent=false, while the description explains exactly what moves (bags, shots, recipes, recommendations), the conditional behaviors (origins only if target has none, newer lock wins and older is deleted), that the source is archived not deleted, and that the operation is irreversible.
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?
Leads with the trigger, then the consequences, then the safety warning — all within four sentences with no filler. The dense lock-conflict clause is the only heavy sentence, but it is information the agent cannot get elsewhere.
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?
A destructive mutation with an output schema needs the description to cover data migration, edge cases and irreversibility; it does all three. Return values are covered by the output schema, so nothing material 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 labels from_bean_id as the duplicate to be archived and into_bean_id as the survivor, so the description is not the sole source. It still adds directional reinforcement and points the agent at list_beans to resolve the numbers before calling.
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 ('fold one coffee into another') plus the exact condition that motivates it ('when the same coffee was registered twice'). This clearly distinguishes merge_beans from update_bean and the register_* 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 an explicit trigger condition (duplicate registration) and a required pre-flight step: confirm both numbers with the user and look them up via list_beans. It does not name the non-duplicate alternative (update_bean) for cases where the coffees are genuinely distinct, so the when-not case is only implied.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
register_bagRegister a bagAInspect
Register another bag of a coffee that is already in list_beans: the same roaster's product, bought again. It keeps the coffee's recipes, notes and history; only the purchase facts (roast date, weight, price, state) are new. Does not change the active coffee. Returns a bag_id: bag numbers are their own series, separate from bean numbers. For a coffee that is not in list_beans yet, call register_coffee instead.
| Name | Required | Description | Default |
|---|---|---|---|
| ean | No | ||
| cost | No | ||
| state | No | Defaults to sealed; the first log_shot against it opens it | |
| bean_id | Yes | This account's own coffee number, from list_beans. Never guess one. | |
| qr_code | No | ||
| storage | No | ||
| buy_date | No | Calendar day in YYYY-MM-DD format: a day, not a timestamp | |
| currency | No | ||
| bag_notes | No | Notes about THIS bag (a batch note, where it was bought). The coffee's own description lives on the coffee, in notes. | |
| product_id | No | Set by the apps. Leave out. | |
| roast_date | Yes | Calendar day in YYYY-MM-DD format: a day, not a timestamp | |
| opened_date | No | Calendar day in YYYY-MM-DD format: a day, not a timestamp | |
| bag_weight_g | No | Bag weight in grams | |
| best_by_date | No | Calendar day in YYYY-MM-DD format: a day, not a timestamp | |
| lot_revision_id | No | Set by the apps. Leave out. | |
| catalog_coffee_id | No | Set by the apps. Leave out. |
Output Schema
| Name | Required | Description |
|---|---|---|
| bag_id | Yes | |
| status | Yes | |
| bean_id | Yes | |
| message | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations declare a non-readonly, non-idempotent, non-destructive create, and the description adds real behavioral context beyond that: what is inherited (recipes, notes, history) versus what is new (roast date, weight, price, state), plus the bag_id return and that bag numbers are a separate series from bean numbers. It stops short of covering failure modes or duplicate handling, but the inheritance/no-active-change details are the valuable part.
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 short sentences, front-loaded with the core action before the inheritance rule, the return-value caveat, and the alternative. Nothing repeats the name or the schema, and every sentence carries information an 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?
For a 16-parameter create tool with annotations and an output schema, the description covers the essential gap areas: which entity is being extended, what is conserved, the id semantics of the return, and the sibling to use instead. Remaining detail (formats, defaults, optional fields) is delegated correctly to the schema.
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 69% and the schema already documents the dates, state default, bag_notes scoping and product_id guidance, so the baseline is a 3. The description does add a useful partition by naming the 'purchase facts (roast date, weight, price, state)' that are new per bag, but it leaves the remaining undocumented fields (ean, cost, storage, currency) untouched.
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 ('Register another bag of a coffee that is already in list_beans') and pins the scope to a repeat purchase of the same roaster's product. It explicitly distinguishes itself from register_coffee, so an agent can choose 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?
Gives both the when ('coffee already in list_beans... bought again') and the when-not with a named alternative ('For a coffee that is not in list_beans yet, call register_coffee instead'). It also rules out a side effect an agent might assume ('Does not change the active coffee').
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
register_coffeeRegister a coffeeAInspect
Register a coffee that is NOT yet in list_beans, together with its first bag. It does not switch a coffee in use: it becomes active only when no coffee is in use (none active, or the active one archived or with every bag finished); otherwise call set_active with its bean_id when the user starts brewing it. The active field of the reply says which. The coffee is the roaster's product (roaster, origins, variety, process, roast level, roasting type, cupping score, aromatics, roaster notes, rest window); the bag is this purchase (roast date, weight, price, state). For another bag of a coffee already on file call register_bag instead: it keeps the recipes and notes. Returns bean_id and the first bag's bag_id.
| Name | Required | Description | Default |
|---|---|---|---|
| ean | No | ||
| url | No | ||
| body | No | Free text; roasters usually say low, medium or high | |
| cost | No | ||
| name | Yes | ||
| notes | No | The coffee's own description: the roaster's tasting notes, the dialing approach that worked. Per bag notes go in bag_notes. | |
| state | No | ||
| origin | No | ||
| rating | No | ||
| acidity | No | Free text; roasters usually say low, medium or high | |
| co2e_kg | No | ||
| origins | No | List of bean origin details | |
| qr_code | No | ||
| roaster | No | ||
| storage | No | ||
| variety | No | ||
| archived | No | 1 if archived, 0 otherwise | |
| bean_mix | No | E.g. blend details | |
| buy_date | No | Calendar day in YYYY-MM-DD format: a day, not a timestamp | |
| currency | No | ||
| finished | No | 1 if finished, 0 otherwise | |
| aromatics | No | ||
| bag_notes | No | ||
| favourite | No | 1 if favourite, 0 otherwise | |
| frozen_at | No | Calendar day the bag went into the freezer, YYYY-MM-DD: a day, not a timestamp | |
| sweetness | No | Free text; roasters usually say low, medium or high | |
| product_id | No | Set by the apps. Leave out. | |
| roast_date | Yes | Calendar day in YYYY-MM-DD format: a day, not a timestamp | |
| arabica_pct | No | Percent arabica, 100 for a pure arabica; the rest robusta | |
| attachments | No | JSON or comma-separated list of attachments | |
| frozen_note | No | ||
| opened_date | No | Calendar day in YYYY-MM-DD format: a day, not a timestamp | |
| roast_level | Yes | ||
| roast_range | No | ||
| unfrozen_at | No | Calendar day the bag came out, YYYY-MM-DD: a day, not a timestamp | |
| bag_weight_g | No | Bag weight in grams | |
| best_by_date | No | Calendar day in YYYY-MM-DD format: a day, not a timestamp | |
| process_type | Yes | ||
| roast_custom | No | ||
| decaffeinated | No | 1 if decaf, 0 if regular | |
| dial_category | No | Dialing behavior class: classic = medium/traditional espresso roasts (chocolate/nut, balanced); dark = genuinely dark/roasty; the light categories cover Nordic and ultra-light styles. | |
| roasting_type | No | ||
| cupping_points | No | ||
| frozen_storage | No | ||
| lot_revision_id | No | Set by the apps. Leave out. | |
| catalog_coffee_id | No | Set by the apps. Leave out. | |
| rest_window_days_max | No | ||
| rest_window_days_min | No |
Output Schema
| Name | Required | Description |
|---|---|---|
| active | Yes | |
| bag_id | Yes | |
| status | Yes | |
| bean_id | Yes | |
| message | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Goes well beyond the annotations by disclosing the activation side effect chain: the new coffee does not become active unless no coffee is in use (none active, active archived, or all bags finished), and the reply's `active` field reports which happened. Annotations only say non-readonly, non-idempotent, non-destructive; the active-state logic is the non-obvious behaviour an agent must know.
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 decisive constraint (NOT yet in list_beans) and the alternative routing. The parenthetical field enumerations are long but justified because they are what separates bean from bag fields; the text is dense with little 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 48-parameter creation tool, it covers the essentials an agent needs before calling: uniqueness requirement, the bean/bag split, the activation consequence, and the returned ids (bean_id, bag_id) even though an output schema exists. It leaves unclear how duplicates are detected (e.g. via ean) and what validation failures look like, which is a modest gap.
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?
Adds real meaning over the 48%-covered schema by partitioning the 48 parameters into coffee-level fields (roaster, origins, variety, process, roast level, roasting type, cupping score, aromatics, notes, rest window) versus bag-level fields (roast date, weight, price, state), which the schema does not do. Many parameters (ean, url, qr_code, currency, storage, attachments) remain unmentioned, so it stops short of full compensation.
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 plus a hard precondition: register a coffee NOT yet in list_beans, together with its first bag. It also names the sibling it is not (register_bag) and the neighbour it does not replace (set_active), so an agent can distinguish it from siblings 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?
Explicit when-to-use ('NOT yet in list_beans'), when-not ('For another bag of a coffee already on file call register_bag instead'), and what to do afterward ('call set_active with its bean_id when the user starts brewing it'). Exclusions and alternatives are spelled out rather than implied.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
register_grinderRegister a grinderAInspect
Register a manual or electric grinder with its dial settings scheme. It becomes the active grinder only when no grinder is in use (none active, or the active one archived); otherwise call set_active with its grinder_id to switch to it. The active field of the reply says which.
| Name | Required | Description | Default |
|---|---|---|---|
| name | Yes | The name/model of the grinder, e.g. Kinu M47 | |
| notes | No | Additional notes | |
| photo | No | Photo path or URL | |
| archived | No | 1 if archived, 0 if active | |
| burr_type | Yes | ||
| max_value | No | Optional travel max bounds | |
| min_value | No | Optional travel min bounds | |
| catalog_id | No | Optional: the maintenance catalog model this is (the `id` of a catalog row, e.g. rancilio-silvia), when it was registered from the catalog. Its maintenance then comes from that model's researched record. "none" says it is not in the catalog. | |
| motor_type | Yes | ||
| nominal_step | Yes | Smallest adjustment increment (e.g. 1 click or 0.1collar units) | |
| setting_scheme | Yes | Collar mark style: single clicks or compound (rotation.number.clicks) | |
| components_spec | No | JSON mapping string representing compound adjustment math | |
| microns_per_step | No | Optional mechanical burr travel microns per nominal step | |
| direction_convention | Yes |
Output Schema
| Name | Required | Description |
|---|---|---|
| active | Yes | |
| status | Yes | |
| message | Yes | |
| grinder_id | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations declare non-readOnly, non-idempotent, non-destructive, but the description adds the crucial side effect the annotations cannot express: activation is conditional on no active/archived grinder, and the reply's `active` field tells which. That is genuine behavioral disclosure beyond structured data.
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 with the core action front-loaded and the conditional-activation rule immediately after. No filler, though the final sentence about the `active` field is slightly compressed in wording.
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 detailed, yet the description still points to the `active` reply field, which is the one output an agent must act on. Combined with the activation rule, an agent has enough to call it correctly; only the post-creation edit path is offloaded to inference.
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 79%, so the schema already documents nearly all 14 parameters including the setting_scheme and catalog_id semantics. The description adds only the aggregate concept of a 'dial settings scheme' and does not clarify any individual parameter beyond what the schema provides.
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 ('Register a manual or electric grinder with its dial settings scheme'), which immediately separates it from update_grinder and set_active in the sibling list. The scope (creating a new grinder record vs. mutating state) is unambiguous.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Explicitly names the alternative for switching: 'otherwise call set_active with its grinder_id to switch to it,' and the condition under which this tool activates the grinder. It does not mention update_grinder for later edits, so it stops one step short of full routing guidance.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
register_machineRegister an espresso machineAInspect
Register an espresso or alternative preparation machine. It becomes the active machine only when no machine is in use (none active, or the active one archived); otherwise call set_active with its machine_id to switch to it. The active field of the reply says which.
| Name | Required | Description | Default |
|---|---|---|---|
| name | Yes | Machine name/model, e.g. Dedica EC685 | |
| notes | No | ||
| photo | No | Photo path or URL | |
| tools | No | JSON or comma-separated tools, e.g., paper filters, flow control, metal mesh | |
| archived | No | 1 if archived, 0 if active | |
| prep_type | No | Preparation equipment type. One of: espresso_machine, lever_press, moka_pot, aeropress, french_press, v60_dripper, cold_brew. Lower snake_case. | |
| catalog_id | No | Optional: the maintenance catalog model this is (the `id` of a catalog row, e.g. rancilio-silvia), when it was registered from the catalog. Its maintenance then comes from that model's researched record. "none" says it is not in the catalog. | |
| prep_style | No | Preparation style. One of: espresso, filter, immersion, percolation. Only "espresso" is diagnosed by the dialing engine (G8). Anything else is recorded but never dialed, so do not guess this field. | |
| boiler_type | No | ||
| hardness_dh | No | Optional: the TOTAL hardness (GH) of the water this machine runs on, in °dH (German degrees; ppm as CaCO3 ÷ 17.85), as a test strip reports it. Picks the band of a maker's hardness table for descaling and filter life | |
| control_type | Yes | ||
| connected_device | No | Metadata mapping to smart hardware APIs | |
| basket_size_grams | No | ||
| built_in_grinder_id | No | id of a grinder built into this machine (bean-to-cup / integrated grinder) |
Output Schema
| Name | Required | Description |
|---|---|---|
| active | Yes | |
| status | Yes | |
| message | Yes | |
| machine_id | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations declare a non-read-only, non-destructive, non-idempotent write, but say nothing about the side effect of activation state; the description adds that meaningful behavior and points at the reply's `active` field to confirm it. It does not cover duplicate-name handling or validation failures, which is the remaining gap for a creation tool.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Three tight sentences with zero filler; the activation condition, which is the only non-obvious consequence of the call, is front-loaded right after the purpose statement.
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 14-parameter, 2-required creation tool with an output schema, the description covers the one behavior an agent cannot infer from structured data: the conditional activation. Return values are covered by the output schema, so the remaining uncovered params (notes, boiler_type, basket_size_grams) are a minor omission rather than a blocking one.
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 71% and is unusually rich (catalog_id, hardness_dh, prep_style all carry their own semantics and warnings), so the baseline is a 3. The description itself adds no parameter-level meaning beyond what the schema already states, relying entirely on the structured fields.
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 verb (register) and resource (espresso or alternative preparation machine), and immediately scopes it against the neighbouring alternatives by naming set_active for the switch case. An agent can distinguish it from update_machine and register_grinder without opening the 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?
States the exact condition under which the new machine becomes active (none active, or the active one archived) and the explicit alternative when that condition fails: call set_active with its machine_id. This is the when/when-not/alternative triad in two sentences.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
register_programRegister a machine programADestructiveInspect
Register a programmed shot button on a machine. A program cuts the shot off either by weight (program_type "volumetric", set target_volume_g) or by time (program_type "timed", set target_time_s). One machine can have a mix of both. A program_number the machine already has is overwritten with these settings; shots logged on it keep pointing at it.
| Name | Required | Description | Default |
|---|---|---|---|
| machine_id | Yes | ||
| description | No | ||
| program_type | No | Cutoff method: "volumetric" (weight) or "timed" (duration). Defaults to volumetric. | |
| target_time_s | No | Target shot duration cutoff in seconds (required for timed programs) | |
| volume_source | No | Confidence in the stored cutoff value, for either type | |
| program_number | Yes | Program number / button index (e.g. 1 or 2) | |
| target_volume_g | No | Target yield cutoff in grams (required for volumetric programs) |
Output Schema
| Name | Required | Description |
|---|---|---|
| status | Yes | |
| message | Yes | |
| program_id | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare destructiveHint=true and openWorldHint=false, so the mutation profile is known. The description usefully adds what actually gets destroyed: an existing program_number is overwritten while previously logged shots keep pointing at it, which is valuable context beyond the annotations.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Three tight sentences, front-loaded with the core action and then the type semantics and overwrite consequence. Every sentence carries information, though it could be slightly terser.
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?
Output schema exists so return values need not be explained, and the description covers the two program types and overwrite behavior well. The omission of volume_source semantics and any error/permission notes keeps it from being fully complete for a 7-parameter mutation 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 coverage is 71%, and the description reinforces the key pairing (program_type "volumetric" → target_volume_g, "timed" → target_time_s), adding the relational logic the schema states per-field. However it says nothing about volume_source, description, or machine_id, so it only partially compensates for the coverage gap.
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 ("Register a programmed shot button on a machine") and immediately defines what a program is and how it terminates a shot. This clearly distinguishes it from sibling registration tools like register_machine or register_grinder, which target different resources.
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 distinguishes the two program modes (volumetric vs timed) and the fields each requires, which implies usage, but it never says when to call this versus update_machine or register_machine, nor any prerequisites. Usage 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.
register_scaleRegister a scaleCInspect
Register a brewing scale: the instrument that weighs the dose and the yield.
| Name | Required | Description | Default |
|---|---|---|---|
| name | Yes | Scale name/model, e.g. Acaia Lunar, Timemore Black Mirror Basic 2 | |
| notes | No | Additional notes | |
| power | No | How it is powered or recharged | |
| depth_mm | No | Platform depth in mm | |
| width_mm | No | Platform width in mm. Measure your drip tray | |
| auto_tare | No | 1 if it zeroes itself when a vessel is set down, 0 if not, null if unstated | |
| height_mm | No | Overall height in mm: the dimension that decides whether it fits under a group head | |
| auto_timer | No | 1 if the timer starts on first flow, 0 if not, null if unstated | |
| capacity_g | No | Maximum weight in grams. The cup or portafilter counts against it | |
| scale_type | Yes | What the scale is built for: espresso (drip-tray footprint), brew (pour-over platform), dual (both modes), connected (app/controller integration), dosing (gravimetric dispensing), training, bench (high capacity, coarse) | |
| connectivity | No | How the scale talks to an app or a machine controller | |
| resolution_g | No | Finest published readability in grams. Leave null unless the maker states it | |
| water_resistance | No | IEC 60529 ingress code as published, e.g. IPX4, IPX6, IP67, or none | |
| flow_rate_display | No | 1 if the scale shows live flow rate in g/s, 0 if it does not, null if the maker never said | |
| resolution_banded | No | 1 when resolution_g only holds in the lowest weight band and coarsens with load. Put the ladder in notes |
Output Schema
| Name | Required | Description |
|---|---|---|
| status | Yes | |
| message | Yes | |
| scale_id | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare readOnlyHint=false, idempotentHint=false and destructiveHint=false, so the description only needs to add context beyond that, and it adds almost none. It does not say what happens on a duplicate name, whether the call fails or merges, or what the response contains. The phrase about weighing dose and yield is a definition, not behavior.
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?
A single front-loaded sentence with no waste, but it is undersized for a 15-parameter creation tool; the brevity is under-specification rather than economy. Nothing in the sentence is wasted, yet it does not use its position to route the agent anywhere.
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 15-param create tool with a rich sibling set, the description omits duplicate handling, the update_scale alternative, and any note about which fields matter most (despite the schema hinting at fit under a group head). An output schema and annotations exist, so return values need not be explained, but the calling context is thin.
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 15 parameters are richly documented inline, including enum meanings and null conventions, so the schema does the heavy lifting. The description adds no parameter meaning at all. 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?
Names a specific verb and resource (register a scale) and glosses the resource as the weighing instrument for dose and yield, which distinguishes it from register_grinder/register_machine. It does not explicitly separate it from update_scale, but the create-vs-update distinction is carried by the verb 'register'.
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?
There is no when-to-use guidance at all: no mention of using update_scale for an existing scale, no pointer to list_scales to check for duplicates, and no prerequisites. The only signal is the implicit 'register = new record' reading of the verb.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
register_waterRegister a water recipeBInspect
Register a custom or commercial water formulation.
| Name | Required | Description | Default |
|---|---|---|---|
| gh | No | General hardness (GH) in ppm | |
| kh | No | Karbonate hardness (KH) in ppm | |
| tds | No | TDS in ppm | |
| name | Yes | Water formulation name, e.g. Lotus Light & Bright, Third Wave Water | |
| type | No | Type, e.g., mineralized, tap, distilled, RO | |
| notes | No | Additional notes | |
| sodium | No | Sodium concentration in ppm | |
| calcium | No | Calcium concentration in ppm | |
| magnesium | No | Magnesium concentration in ppm |
Output Schema
| Name | Required | Description |
|---|---|---|
| status | Yes | |
| message | Yes | |
| water_id | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already signal that this is not a read-only operation, but the description adds no behavioral detail beyond that, such as whether duplicate names overwrite, whether registration requires approval, or any side effects. It does not contradict the annotations.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is a single sentence with no filler, front-loading the core action and resource. It is appropriately sized for the simplicity of the tool.
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 registration tool, the description combined with full schema coverage, annotations, and an output schema provides enough context for an agent to select and invoke the tool. It is slightly incomplete only because it omits usage guidance relative to sibling tools, but that is covered under usage_guidelines.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
The input schema has 100% property description coverage, so the schema carries the parameter documentation burden. The description adds no additional parameter meaning beyond what is already in 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?
The description uses the specific verb 'Register' with the resource 'water formulation', which matches the title and clearly identifies the tool's purpose. It also distinguishes this tool from sibling register_* tools by naming water as the entity, and custom/commercial scope adds useful clarity.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description gives no guidance on when to use this tool over alternatives such as list_waters or update_* tools. No exclusions, prerequisites, or comparison with sibling tools are provided; usage context is only implied by the name and title.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
set_activeSet active equipmentAIdempotentInspect
Switch the active bean, grinder or machine for this account. The numbers come from list_beans, list_grinders and list_machines. Registering a coffee, grinder or machine makes it active only when nothing of that kind is in use (the active field of the reply says which), so call this to start using something new as well as to switch back.
| Name | Required | Description | Default |
|---|---|---|---|
| bean_id | No | This account's own bean number, as returned by list_beans. Never guess one; null = leave unchanged | |
| grinder_id | No | This account's own grinder number, as returned by list_grinders. Never guess one; null = leave unchanged | |
| machine_id | No | This account's own machine number, as returned by list_machines. Never guess one; null = leave unchanged | |
| program_id | No | A program number from the active machine's list; switching machines clears it. null = leave unchanged |
Output Schema
| Name | Required | Description |
|---|---|---|
| status | Yes | |
| message | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare idempotentHint=true and destructiveHint=false, so the safety profile is partly covered. The description adds useful behavioral context beyond them: partial updates leave fields unchanged (matching the null parameters) and the reply's `active` field reports what actually got activated, which is genuine non-obvious behavior.
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 sentences, front-loaded with the core action, then provenance, then the non-obvious activation caveat. Dense and mostly waste-free, though the final sentence is slightly long for what it conveys.
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-value docs aren't needed, and the description still hints at the reply's `active` field. Combined with full schema coverage and annotations, an agent has what it needs; only the absence of explicit alternative routing keeps it from a 5.
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 each parameter already documents 'null = leave unchanged' and 'Never guess one'. The description only adds the provenance of the numbers (list_beans/list_grinders/list_machines), which largely duplicates the schema, 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 ('switch the active') and resource (bean, grinder, machine) for this account, and explicitly sets it apart from the register_* siblings by noting that registration only activates when nothing of that kind is in use. An agent can tell this is the explicit activation setter, not a create/update tool.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Gives clear context for when to call it: to start using something new (after registering) as well as to switch back to an existing item. It also points to the list_* tools that supply valid numbers, but doesn't enumerate alternatives such as update_bean or set_grinder_position for other forms of change.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
set_equipment_archivedArchive or restore equipmentAIdempotentInspect
Archive or restore a grinder, machine, water, or scale.
| Name | Required | Description | Default |
|---|---|---|---|
| id | Yes | The ID of the equipment | |
| kind | Yes | The kind of equipment to archive/restore | |
| archived | Yes | 1 to archive, 0 to restore |
Output Schema
| Name | Required | Description |
|---|---|---|
| status | Yes | |
| message | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already indicate a non-read-only, non-destructive, idempotent operation. The description adds the useful behavioral nuance that the operation can both archive and restore, implying reversibility, but it does not disclose side effects, permissions, or what happens to equipment once archived.
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 a single, front-loaded sentence: action first, then the complete resource scope. Every word carries information, with no redundant 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 simple three-parameter tool with fully documented schema fields, enum constraints, safety annotations, and an output schema, the description provides sufficient context for correct invocation. Remaining details such as return format are already handled elsewhere.
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 each parameter already has a clear description, including enum values for kind and archived. The description only restates the equipment kinds from the schema and adds no new parameter-level meaning.
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 uses precise verbs ('Archive or restore') and explicitly names all supported resource kinds ('grinder, machine, water, or scale'), matching the kind enum exactly. This makes the tool's purpose immediately distinguishable from siblings like set_active or register_*.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description provides clear usage context: use this tool when you need to archive or restore one of the listed equipment types. It does not name alternatives or explicit when-not scenarios, but the action is unique among the sibling tools, so no routing conflict exists.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
set_grinder_positionSet grinder positionADestructiveIdempotentInspect
Set the current grinder collar position. source="measured" resets verification freshness. It replaces the stored position; no history of earlier positions is kept.
| Name | Required | Description | Default |
|---|---|---|---|
| source | Yes | Whether setting is verified ("measured") or guess ("recalled"/"assumed") | |
| grinder_id | Yes | ||
| setting_label | Yes | Verbatim display label, e.g. "1.1.2" |
Output Schema
| Name | Required | Description |
|---|---|---|
| source | Yes | |
| status | Yes | |
| message | Yes | |
| grinder_id | Yes | |
| setting_label | Yes | |
| position_value | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare destructiveHint=true and idempotentHint=true; the description adds real value by explaining what 'destructive' means here — the stored position is replaced and no history is retained — plus the side effect of a measured source on verification freshness. It stops short of describing permissions or the response shape.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Three short sentences, front-loaded with the core action, then the consequence of the source value, then the overwrite behavior. No filler, every 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?
An output schema exists so return values need no explanation, and the description covers the destructive overwrite semantics and the key source side effect. It is nearly complete for a 3-parameter mutation tool, with only minor gaps around permissions and freshness semantics.
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 67%, with source and setting_label documented in the schema. The description adds meaning to source="measured" by tying it to verification freshness, which the schema does not state, but it says nothing about grinder_id and only partially compensates for the coverage gap.
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 — setting the grinder collar position — which separates it from the generic update_grinder sibling. It does not explicitly name or contrast with alternatives, but the scope is unambiguous.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
There is no explicit 'use when / don't use when' guidance or named alternative, but the note that source="measured" resets verification freshness implies when a verified entry is warranted versus a guess. Usage is inferable rather than stated.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
set_maintenance_offsetSet calibration offsetADestructiveIdempotentInspect
Record how far a maintenance job moved the reference, on an entry that opened a calibration epoch. Takes an ENTRY, not a piece of equipment: the offset belongs to the event that caused it, which is what lets several of them compose for a recipe locked before all of them. Zero is a legitimate measurement and means "measured, and it had not moved". Omit offset_value entirely to clear it back to unmeasured.
| Name | Required | Description | Default |
|---|---|---|---|
| source | No | How it was arrived at: pull, counted, or typed | |
| entry_id | Yes | The maintenance entry that opened the epoch, from list_grinders | |
| evidence | No | One line recording what it rested on, e.g. "Reference pull 1.38 g/s against 1.74 g/s locked." | |
| offset_value | No | Clicks to ADD to a pre-clean reading to get the same grind today, signed along the collar's own number direction. 0 records "unchanged"; omit to clear the measurement |
Output Schema
| Name | Required | Description |
|---|---|---|
| entry | Yes | |
| message | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
It provides significant behavioral detail beyond the structured fields by defining the logical meaning of 0 (unchanged), the semantic implication of omitting offset_value (clearing measurement), and the relational context (offsets composing for a locked recipe). These details add substantial clarity.
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 prose is highly technical yet perfectly structured. Every sentence contributes vital, specific information (e.g., 'Zero is a legitimate measurement,' 'takes an ENTRY') and the flow is logical and dense.
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?
The description provides a comprehensive context for a highly technical tool. By explaining concepts like 'calibration epoch' and the dependency on the entry ID, it ensures the AI agent has the full necessary context for correct invocation.
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?
With 100% schema description coverage, the baseline is 3. The description elevates this by explaining the 'signed direction' of the offset and the context of the 'entry,' adding crucial meaning that transcends the formal type definitions.
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 is highly specific, stating that it records how a maintenance job moved the reference and attaches this data to the entry that opened a calibration epoch. This clearly defines the tool's domain within the overall system architecture.
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?
While it clarifies that the offset belongs to an 'ENTRY, not a piece of equipment,' which provides crucial scope guidance, it does not explicitly suggest alternatives like 'log_maintenance,' making it an implied usage scenario rather than a direct comparison.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
set_maintenance_scheduleSet a maintenance scheduleADestructiveIdempotentInspect
Set the user's own schedule for one maintenance task on one grinder or machine: their own interval, switching it off, or muting the reminder until a date. Only the keys you send in fields change; send every: null to go back to the maker's guidance and muted_until: null to unmute. Use it when the user states how often they do a task or asks to be left alone about one, never to invent an interval. The task's class, interval and due state are read back from list_grinders and list_machines.
| Name | Required | Description | Default |
|---|---|---|---|
| task | Yes | The task, as its value in that equipment's maintenance.tasks | |
| fields | No | ||
| changed_at | No | Optional: when the user made this change (ISO 8601, UTC). An app sending a queued edit passes it, so an older edit never overwrites a newer one; it is then answered with applied: false | |
| equipment_id | Yes | This account's own grinder or machine number, from list_grinders or list_machines | |
| equipment_kind | Yes | Which kind of equipment the task is on |
Output Schema
| Name | Required | Description |
|---|---|---|
| due | Yes | |
| task | Yes | |
| class | Yes | |
| every | Yes | |
| applied | Yes | |
| message | Yes | |
| schedule | Yes | |
| equipment_id | Yes | |
| every_source | Yes | |
| equipment_kind | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Despite annotations already declaring mutation and idempotency, the description adds substantial behavioral context: partial-update semantics ('Only the keys you send in fields change'), null-as-reset behavior for both every and muted_until, what enabled:false does without forgetting the interval, and how changed_at resolves queued-edit conflicts with applied:false. This is exactly the kind of detail annotations cannot convey.
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 sentences, front-loaded with the core action and then the partial-update rule and usage trigger. Dense but nearly every clause carries operational meaning; the final read-back sentence is slightly tangential but still useful.
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 complex nested-parameter mutation with an output schema and annotations, the description covers when to use it, how partial updates behave, reset semantics, and where to read task state. Nothing an agent needs in order to call it 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 description coverage is 80%, and the nested schema already documents the null-reset semantics for every and muted_until, enabled:false, and changed_at conflict handling. The description largely restates those same semantics rather than adding new meaning, 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?
Names a specific verb and resource (set the user's own schedule for one maintenance task on one grinder/machine) and enumerates the three modes: own interval, switch off, or mute. It is clearly distinguished from siblings like log_maintenance and set_maintenance_offset, which handle logging and offsets rather than a full schedule.
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 an explicit trigger ('when the user states how often they do a task or asks to be left alone about one') and an explicit prohibition ('never to invent an interval'). It also points to list_grinders and list_machines for reading back state, but does not explicitly contrast with set_maintenance_offset, so it falls just short of naming alternatives.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
suggest_next_stepSuggest the next stepBRead-onlyIdempotentInspect
Retrieve the single next experiment step from the reasoning engine.
| Name | Required | Description | Default |
|---|---|---|---|
| bean_id | Yes |
Output Schema
| Name | Required | Description |
|---|---|---|
| category | Yes | |
| warnings | Yes | |
| next_step | Yes | |
| warning_codes | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare readOnly, idempotent, non-destructive and closed-world, so the safety profile is covered. The description adds only that exactly one step is returned; it says nothing about what happens when no step is available, whether state must exist first, or how fresh the suggestion is.
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?
A single front-loaded sentence with no filler. It is efficient, though the terseness contributes to the missing context.
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 described. However, for a tool whose whole purpose is ambiguity-prone ('next step'), the bean_id semantics and the precondition for getting a suggestion are missing, leaving the definition only barely 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?
One required parameter with 0% schema description coverage, and the description never explains what bean_id identifies or that it comes from list_beans/register_bean. The description does nothing to compensate for the undocumented parameter.
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 verb ('Retrieve') and resource ('the single next experiment step from the reasoning engine'), which is enough to distinguish it from the CRUD/registration siblings. What an 'experiment step' actually is in this coffee-tooling domain is left implicit, so it stops short of full clarity.
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?
There is no statement of when to call this versus diagnose_shot, get_dial_state, get_rule or the other read-oriented siblings. An agent must guess that this is the recommendation/advice endpoint rather than a lookup.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
update_bagUpdate a bagADestructiveInspect
Change bag-level facts on one bag of a coffee: open, seal, freeze, thaw or finish it, correct its roast date, weight, grams left or price. Bag numbers come from the bags[] on list_beans (or current_bag_id). For the coffee itself (roaster, origin, roast level, rest window, notes), use update_bean.
| Name | Required | Description | Default |
|---|---|---|---|
| bag_id | Yes | This account's own bag number, from list_beans' bags[]. Never guess one. | |
| fields | Yes | ||
| reason | No | Optional free-text note, appended to this bag's notes as an ordinary line. Omit it and nothing is written. |
Output Schema
| Name | Required | Description |
|---|---|---|
| status | Yes | |
| message | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare destructiveHint=true and idempotentHint=false, so the safety profile is covered elsewhere. The description does convey that this mutates bag status (open/seal/freeze/thaw/finish), which is useful context, but it says nothing about whether omitted fields are preserved, whether changes are reversible, or what the response confirms.
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 dense sentences plus a single routing sentence, with the primary purpose front-loaded and the sibling disambiguation last. Every sentence carries distinct 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?
Output schema and annotations carry the return shape and safety profile, and the description covers purpose, identifier sourcing, and sibling routing. A mutation tool with a 19-field nested object would ideally state whether the fields object is a partial patch (unmentioned fields preserved) and confirm the destructive semantics, which is the main missing piece.
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 67% and rich field-level descriptions already explain grams_remaining and weight_adjustment_g. The description adds the mapping from plain-language fields (roast date, weight, grams left, price) to the fields object, but says nothing about ean, qr_code, storage, bag_notes, or the optional reason parameter.
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), resource (bag-level facts on one bag of a coffee), and enumerates the concrete operations (open, seal, freeze, thaw, finish, correct roast date/weight/grams left/price). It explicitly distinguishes itself from the sibling update_bean, which handles coffee-level attributes.
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 where bag identifiers come from (bags[] on list_beans or current_bag_id) and names the alternative tool (update_bean) for coffee-level edits. The only minor gap is that it does not spell out that state transitions happen by setting state = open/frozen/etc., but the operation verbs imply it.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
update_beanUpdate a coffeeADestructiveInspect
Update a coffee's own fields (roaster, origins, roast level, rest window, notes, rating…). Bag-shaped fields sent here (state, roast_date, bag_weight_g, grams_remaining, cost…) land on the coffee's CURRENT bag. Use update_bag when it has more than one. Changing dial_category changes what the engine advises (G5, C10), so say why in the optional note.
| Name | Required | Description | Default |
|---|---|---|---|
| fields | Yes | ||
| reason | No | Optional free-text note, appended as an ordinary line to the coffee's notes, or to the current bag's bag_notes when the call changed only bag fields. Omit it and nothing is written. | |
| bean_id | Yes |
Output Schema
| Name | Required | Description |
|---|---|---|
| status | Yes | |
| message | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare this a non-idempotent, destructive, closed-world mutation, so the safety profile is covered. The description still earns credit for disclosing a non-obvious cross-resource side effect: bag-shaped fields passed here mutate the coffee's CURRENT bag rather than the coffee. It does not explain partial-update semantics (whether omitted fields are preserved), merge behavior, or failure modes.
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 sentences, front-loaded with scope, then the routing rule, then the caution — nothing redundant. The '(G5, C10)' code references are opaque to an outside reader and cost a little clarity, and the parenthetical field lists are dense.
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 no explanation, and the annotations cover the destructive/non-idempotent profile. What remains thin is update semantics: whether this is a partial patch, how nested `origins` arrays are treated, and what happens when both coffee and bag fields are sent together.
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 only 33%, and the flat `fields` bag mixes coffee-level and bag-level keys with no structural distinction in the schema itself. The description supplies exactly that missing semantics by naming which fields land on the bag versus the coffee, and it explains the purpose of the `reason` note. It falls short of fully compensating because the field lists are truncated ('…') and replace-vs-append semantics for individual fields are only partially addressed.
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 ('Update a coffee's own fields') and enumerates representative fields so the scope is concrete. It immediately contrasts with the sibling update_bag, so an agent can pick between the two 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?
Explicitly routes the agent: 'Use update_bag when it has more than one' bag. It also flags the dial_category change as having downstream consequences on engine advice and asks for a rationale note, which is real decision guidance rather than restatement.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
update_grinderUpdate a grinderADestructiveInspect
Correct a registered grinder: its name, burrs, collar scheme, nominal step, layout, range or notes. Only the keys you send in fields change; send null to clear an optional field (an empty string also clears a text field, but not a number or a closed list). Required fields can be changed but not cleared. fields may be omitted when only reason is sent. setting_scheme, nominal_step and components_spec describe the collar every recorded grind label is read through: call with dry_run first to see which recorded settings would read as a different position, and tell the user before saving. Saving records the change in the grinder's maintenance history; when a locked recipe's setting moves it also opens an unmeasured calibration epoch (set_maintenance_offset resolves it). The collar's current setting is marked assumed when it reads differently, or cleared when the new collar cannot read it, and measured offsets are converted when a click changes worth. Changing direction_convention is a correction: it moves no number, but every finer/coarser said about this grinder was the wrong way round.
| Name | Required | Description | Default |
|---|---|---|---|
| fields | No | ||
| reason | No | Optional note, appended to this record's own notes as an ordinary line. Omit it and nothing is written. | |
| dry_run | No | true: write nothing, and answer with what the edit would do to the settings already recorded (moved[], checked, epoch, position_moved, position_cleared, rescaled_offsets, resigned_offsets, step_ignored, direction_flipped, recipe_count) | |
| grinder_id | Yes | This account's own grinder number, from list_grinders. Never guess one. |
Output Schema
| Name | Required | Description |
|---|---|---|
| epoch | Yes | |
| moved | Yes | |
| status | Yes | |
| checked | Yes | |
| dry_run | Yes | |
| message | Yes | |
| entry_id | Yes | |
| grinder_id | Yes | |
| unreadable | Yes | |
| moved_count | Yes | |
| changed_keys | Yes | |
| recipe_count | Yes | |
| step_ignored | Yes | |
| reads_changed | Yes | |
| position_moved | Yes | |
| untranslatable | Yes | |
| position_cleared | Yes | |
| rescaled_offsets | Yes | |
| resigned_offsets | Yes | |
| direction_flipped | Yes | |
| untranslatable_recipes | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Far exceeds the annotations: it explains that only sent keys change, that null (or empty string for text) clears, that required fields can be changed but not cleared, that saving writes maintenance history, opens an unmeasured calibration epoch for locked recipes, marks or clears the collar's current setting, converts measured offsets when a click changes worth, and that direction_convention flips all prior finer/coarser statements without moving a number. This is exactly the destructive/consequential context the destructiveHint flag cannot convey.
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 purpose and the clearing rule, then layers consequences. Dense and mostly earning its length, though the final sentence about direction_convention is long and the middle section packs several distinct behaviors into one sentence, which slightly hurts scannability.
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 destructive, non-idempotent nested-object mutation, it covers write semantics, clearing rules, side effects, dry-run behavior, and escalation to a sibling. An output schema exists and the dry_run parameter already enumerates returned fields, so return values need no further explanation.
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 75%, and the description adds genuine semantics the schema does not: partial-update/patch behavior, null-vs-empty-string clearing rules per type, the ability to omit fields when only reason is sent, and the shared meaning of setting_scheme/nominal_step/components_spec as the lens through which recorded grind labels are read. It does not individually explain every field, but the highest-risk ones are covered.
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?
Opens with a specific verb and resource ("Correct a registered grinder") and enumerates the mutable aspects (name, burrs, collar scheme, nominal step, layout, range, notes). It is clearly a mutation of an existing record, implicitly distinguished from register_grinder, but it never names a sibling 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?
Gives concrete operational guidance: call with dry_run first when changing setting_scheme/nominal_step/components_spec, and tell the user before saving. It also routes to set_maintenance_offset for resolving an opened calibration epoch. What's missing is an explicit boundary against register_grinder or update_machine for adjacent cases.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
update_machineUpdate a machineADestructiveInspect
Correct a registered machine (its name, control type, prep type and style, basket, boiler, accessories or notes), or record where its selectors stand (settings). Only the keys you send in fields change; send null to clear an optional field (an empty string also clears a text field, but not a number or a closed list). Required fields can be changed but not cleared. fields may be omitted when only reason is sent. prep_style decides whether shots on this machine are diagnosed at all: only "espresso" is. Programs are edited with register_program, the built-in grinder link is not editable here, and archiving is set_equipment_archived.
| Name | Required | Description | Default |
|---|---|---|---|
| fields | No | ||
| reason | No | Optional note, appended to this record's own notes as an ordinary line. Omit it and nothing is written. | |
| machine_id | Yes | This account's own machine number, from list_machines. Never guess one. |
Output Schema
| Name | Required | Description |
|---|---|---|
| status | Yes | |
| message | Yes | |
| machine_id | Yes | |
| changed_keys | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations give destructiveHint=true without explaining scope, and the description fills that gap precisely: partial-update semantics ('Only the keys you send in fields change'), the null-vs-empty-string clearing rule and its exception for numbers and closed lists, and the fact that required fields can be changed but not cleared. It also discloses a cross-system side effect not visible anywhere else — prep_style determines whether shots are diagnosed at all.
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?
Highly front-loaded: purpose, then update/clearing semantics, then exceptions, then sibling routing. The parenthetical field list and the dense closing sentence are efficient but pack several rules into single run-on clauses, which costs a little readability.
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 nested-object mutation with an output schema, the description covers what an agent actually needs: how partial updates work, how to clear values, what cannot be cleared, what is out of scope, and the domain consequence of prep_style. Return values are correctly left to the output schema.
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?
With 67% schema coverage the schema already documents most fields, but the description adds rules the schema does not: the null/empty-string clearing asymmetry, the distinction between changing versus clearing required fields, and the consequence of prep_style on diagnosis. It does not, however, restate which fields are required or optional, leaving that to 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?
Opens with a specific verb+resource ('Correct a registered machine') and enumerates the exact editable surface (name, control type, prep type/style, basket, boiler, accessories, notes) plus the secondary purpose of recording selector positions. It explicitly carves out what belongs to siblings: 'Programs are edited with register_program, the built-in grinder link is not editable here, and archiving is set_equipment_archived.'
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 three alternatives and the boundary condition for each (register_program for programs, set_equipment_archived for archiving, grinder link out of scope). It also states the degenerate call shape ('fields may be omitted when only reason is sent'), removing the main invocation ambiguity.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
update_scaleUpdate a scaleADestructiveInspect
Correct a registered scale: its type, resolution, capacity, capabilities, build or notes. Only the keys you send in fields change; send null to clear an optional field (an empty string also clears a text field, but not a number or a closed list). Required fields can be changed but not cleared. fields may be omitted when only reason is sent. The three capabilities are 1, 0, or null for "the maker never said"; leave one out rather than sending 0 when nobody knows.
| Name | Required | Description | Default |
|---|---|---|---|
| fields | No | ||
| reason | No | Optional note, appended to this record's own notes as an ordinary line. Omit it and nothing is written. | |
| scale_id | Yes | This account's own scale number, from list_scales. Never guess one. |
Output Schema
| Name | Required | Description |
|---|---|---|
| status | Yes | |
| message | Yes | |
| scale_id | Yes | |
| changed_keys | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
With destructiveHint=true and idempotentHint=false already declared, the description earns credit for explaining the actual destruction mechanism: sending null clears optional fields, an empty string clears text but not numbers or closed lists, and required fields can be changed but never cleared. The tri-state capability guidance (1 / 0 / null, and prefer omission over 0) is genuine behavioral context an agent could not infer from annotations.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Purpose is front-loaded in one clause, then every following sentence states a distinct rule with no restatement of the name or title. The density is warranted for a 16-field nested patch tool.
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 needn't be described, and annotations plus description together cover the mutation/clearing profile. What remains unaddressed is failure behavior on invalid or foreign scale_id values and any permission or ownership constraints beyond the schema's brief note.
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 67%, and the description compensates strongly: it explains patch semantics for the fields object, null-versus-empty-string clearing rules per type, and gives meaning to auto_tare, auto_timer and flow_rate_display, which the schema types only as integer|null with no description. This is meaning well beyond the structured 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?
The description states a specific verb and resource ("Correct a registered scale") and enumerates the editable aspects: type, resolution, capacity, capabilities, build, notes. The word "registered" and the corrective framing distinguish it from register_scale and list_scales without ambiguity.
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 concrete operating conditions: only keys sent in fields change, fields may be omitted when only reason is sent, and nullable versus required fields behave differently. It doesn't name a sibling alternative (e.g., register_scale for new records) or state prerequisites, so it stops short of full when/when-not guidance.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
update_shotUpdate a shotADestructiveIdempotentInspect
Correct fields on an already-logged shot in place, with no need to delete and re-log. Use for fixing a wrong dose/yield/time or grind label, re-filing a shot onto the right bean (bean_id), backfilling rating/tasting notes, or fixing the timestamp (pulled_at). Changing grind_label re-derives the numeric grind position from the shot's grinder; changing yield/time/dose/tds keeps flow rate and extraction yield consistent automatically.
| Name | Required | Description | Default |
|---|---|---|---|
| fields | Yes | Only the fields to change | |
| shot_id | Yes | ID of the shot to correct |
Output Schema
| Name | Required | Description |
|---|---|---|
| status | Yes | |
| message | Yes | |
| shot_id | Yes | |
| updated_fields | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare destructiveHint=true and idempotentHint=true, so the safety profile is known. The description adds valuable behavioral context beyond that: it clarifies this is an in-place correction (not a deletion), and it discloses automatic re-derivation of numeric grind position and consistency maintenance for flow rate and extraction yield when changing key fields. Permissions and error behaviors are not addressed, but the core behavioral traits are surfaced.
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 sentences with zero waste: first states purpose and scope, second lists common use cases, third covers derived-field behavior. The purpose is front-loaded and every sentence earns its place.
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 and annotations present, the description needn't explain return values or safety flags. It covers purpose, use cases, and key behavioral side effects. Minor gaps remain, such as validation constraints (e.g., bag_id must belong to the shot's bean), but those are documented in the schema.
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 baseline is 3. The description adds meaning beyond the schema by explaining that changing grind_label re-derives the numeric position and that changing yield/time/dose/tds keeps flow rate and extraction yield consistent. It also calls out bean_id for re-filing, though that is already described in 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 ('Correct') and resource ('already-logged shot') and immediately distinguishes itself from delete+re-log. An agent can tell it apart from delete_shot and log_shot 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?
Enumerates concrete scenarios for use: fixing dose/yield/time/grind, re-filing onto the right bean, backfilling rating/tasting notes, correcting timestamp. It also implies the alternative (delete and re-log) and asserts it is unnecessary, giving clear routing guidance.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
update_waterUpdate a water recipeADestructiveInspect
Correct a registered water: its name, type, mineral figures or notes. Only the keys you send in fields change; send null to clear an optional field (an empty string also clears a text field, but not a number or a closed list). Required fields can be changed but not cleared. fields may be omitted when only reason is sent.
| Name | Required | Description | Default |
|---|---|---|---|
| fields | No | ||
| reason | No | Optional note, appended to this record's own notes as an ordinary line. Omit it and nothing is written. | |
| water_id | Yes | This account's own water number, from list_waters. Never guess one. |
Output Schema
| Name | Required | Description |
|---|---|---|
| status | Yes | |
| message | Yes | |
| water_id | Yes | |
| changed_keys | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
The description adds substantial mutation semantics beyond the annotations: only supplied keys change, null clears optional fields, empty string clears text but not numbers or closed lists, and required fields can be changed but not cleared. These details are important for a destructive, non-idempotent update tool.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is compact and front-loaded: it first identifies the operation and updatable aspects, then immediately covers mutation and clearing rules. Every sentence adds actionable information without repetition.
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 annotations, nested parameters, and existing output schema, the description supplies the remaining critical mutation behavior an agent needs to call it correctly. Return values are covered by the output schema, so no description space is wasted there.
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?
With only 67% schema coverage and a nested fields object, the description compensates by explaining partial-update behavior, null-versus-empty-string semantics, required-field constraints, and when fields can be omitted. This meaningfully supplements the type-only nested 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?
The description states a specific verb and resource: correcting a registered water's name, type, mineral figures, or notes. It implies the record must already exist, which distinguishes it from register_water, but it does not explicitly name that sibling or other alternatives.
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 by 'Correct a registered water' and by the note that fields may be omitted when only reason is sent. However, it does not explicitly state when to use this versus register_water or list_waters, and the water_id guidance lives in the schema rather than the description.
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.
4 tool updates
- Changed
get_dial_state3 fields changed- changed
Output schema / properties / maintenance_summary / properties / most_urgent / properties / done / typePrevious value: -"integer"New value: +"number" - changed
Output schema / properties / maintenance_summary / properties / most_urgent / properties / every / typePrevious value: -"integer"New value: +"number" - changed
Output schema / properties / maintenance_summary / properties / most_urgent / properties / remaining / typePrevious value: -"integer"New value: +"number"
- Changed
list_machines5 fields changed- changed
Output schema / properties / machines / items / properties / maintenance / properties / due / additionalProperties / properties / done / typePrevious value: -[ - "null", - "integer" -]New value: +[ + "null", + "number", + "integer" +] - changed
Output schema / properties / machines / items / properties / maintenance / properties / due / additionalProperties / properties / every / typePrevious value: -[ - "null", - "integer" -]New value: +[ + "null", + "number", + "integer" +] - changed
Output schema / properties / machines / items / properties / maintenance / properties / due / additionalProperties / properties / remaining / typePrevious value: -[ - "null", - "integer" -]New value: +[ + "null", + "number", + "integer" +] - changed
Output schema / properties / machines / items / properties / maintenance / properties / tasks / items / properties / schedule / properties / every / requiredPrevious value: -[ - "days", - "litres" -]New value: +[ + "litres" +] - changed
Output schema / properties / machines / items / properties / maintenance / properties / tasks / items / properties / schedule / properties / muted_until / typePrevious value: -"string"New value: +[ + "string", + "null" +]
- Changed
list_maintenance_due3 fields changed- changed
Output schema / properties / items / items / properties / done / typePrevious value: -[ - "integer", - "null" -]New value: +[ + "number", + "integer", + "null" +] - changed
Output schema / properties / items / items / properties / every / typePrevious value: -[ - "integer", - "null" -]New value: +[ + "number", + "integer", + "null" +] - changed
Output schema / properties / items / items / properties / remaining / typePrevious value: -[ - "integer", - "null" -]New value: +[ + "number", + "integer", + "null" +]
- Changed
set_maintenance_schedule8 fields changed- changed
Output schema / properties / due / properties / done / typePrevious value: -"integer"New value: +[ + "integer", + "number" +] - changed
Output schema / properties / due / properties / due_at / typePrevious value: -"string"New value: +[ + "string", + "null" +] - changed
Output schema / properties / due / properties / every / typePrevious value: -"integer"New value: +[ + "integer", + "number" +] - changed
Output schema / properties / due / properties / last_at / typePrevious value: -"string"New value: +[ + "string", + "null" +] - changed
Output schema / properties / due / properties / overdue_at / typePrevious value: -"string"New value: +[ + "string", + "null" +] - changed
Output schema / properties / due / properties / ratio / typePrevious value: -"integer"New value: +[ + "integer", + "number" +] - changed
Output schema / properties / due / properties / remaining / typePrevious value: -"integer"New value: +[ + "integer", + "number" +] - changed
Output schema / properties / due / properties / soon_at / typePrevious value: -"string"New value: +[ + "string", + "null" +]
21 tool updates
- Changed
compute_age2 fields changed- added
Output schema / properties / verdict_codeAdded value: +{ + "type": "string" +} - changed
Output schema / requiredPrevious value: -[ - "bean_id", - "bag_id", - "roast_date", - "age_days", - "days_off_roast", - "days_since_opened", - "frozen_days_excluded", - "effective_age_days", - "rest_window", - "verdict", - "grams_remaining", - "warnings" -]New value: +[ + "bean_id", + "bag_id", + "roast_date", + "age_days", + "days_off_roast", + "days_since_opened", + "frozen_days_excluded", + "effective_age_days", + "rest_window", + "verdict", + "verdict_code", + "grams_remaining", + "warnings" +]
- Changed
diagnose_preview3 fields changed- changed
Input schema / properties / source / descriptionPrevious value: -"Grinder position source — affects G1 warning (raw mode only)"New value: +"Grinder position source. Affects G1 warning (raw mode only)" - added
Output schema / properties / warning_codesAdded value: +{ + "items": { + "type": "string" + }, + "type": "array" +} - changed
Output schema / requiredPrevious value: -[ - "category", - "facts", - "hypotheses", - "warnings", - "one_variable_only", - "kb_version", - "bean_context" -]New value: +[ + "category", + "facts", + "hypotheses", + "warnings", + "one_variable_only", + "kb_version", + "warning_codes", + "bean_context" +]
- Changed
diagnose_shot2 fields changed- added
Output schema / properties / warning_codesAdded value: +{ + "items": { + "type": "string" + }, + "type": "array" +} - changed
Output schema / requiredPrevious value: -[ - "category", - "facts", - "hypotheses", - "warnings", - "one_variable_only", - "kb_version", - "bean_context" -]New value: +[ + "category", + "facts", + "hypotheses", + "warnings", + "one_variable_only", + "kb_version", + "warning_codes", + "bean_context" +]
- Changed
get_dial_state10 fields changed- added
Output schema / properties / active_coffee / properties / age_verdict_codeAdded value: +{ + "type": "string" +} - added
Output schema / properties / active_coffee / properties / bag / properties / age_verdict_codeAdded value: +{ + "type": "string" +} - added
Output schema / properties / active_coffee / properties / bag / properties / lot_revision_idAdded value: +{ + "type": [ + "string", + "null" + ] +} - added
Output schema / properties / active_coffee / properties / bag / properties / product_idAdded value: +{ + "type": [ + "string", + "null" + ] +} - changed
Output schema / properties / active_coffee / properties / bag / requiredPrevious value: -[ - "id", - "bean_id", - "roast_date", - "buy_date", - "opened_date", - "best_by_date", - "bag_weight_g", - "weight_adjustment_g", - "cost", - "currency", - "state", - "finished", - "frozen_at", - "unfrozen_at", - "frozen_storage", - "frozen_note", - "storage", - "ean", - "qr_code", - "bag_notes", - "archived", - "days_off_roast", - "days_since_opened", - "frozen_days_excluded", - "effective_age_days", - "age_verdict", - "grams_remaining" -]New value: +[ + "id", + "bean_id", + "roast_date", + "buy_date", + "opened_date", + "best_by_date", + "bag_weight_g", + "weight_adjustment_g", + "cost", + "currency", + "state", + "finished", + "frozen_at", + "unfrozen_at", + "frozen_storage", + "frozen_note", + "storage", + "ean", + "qr_code", + "bag_notes", + "archived", + "product_id", + "lot_revision_id", + "days_off_roast", + "days_since_opened", + "frozen_days_excluded", + "effective_age_days", + "age_verdict", + "age_verdict_code", + "grams_remaining" +] - added
Output schema / properties / active_coffee / properties / catalog_coffee_idAdded value: +{ + "type": [ + "string", + "null" + ] +} - changed
Output schema / properties / active_coffee / properties / roaster / typePrevious value: -"string"New value: +[ + "string", + "null" +] - changed
Output schema / properties / active_coffee / requiredPrevious value: -[ - "id", - "name", - "roaster", - "origin", - "variety", - "roast_date", - "roast_level", - "process_type", - "dial_category", - "bag_notes", - "rest_window_days_min", - "rest_window_days_max", - "state", - "opened_date", - "storage", - "is_active", - "weight_adjustment_g", - "buy_date", - "bag_weight_g", - "cost", - "currency", - "decaffeinated", - "bean_mix", - "roast_range", - "roast_custom", - "roasting_type", - "aromatics", - "cupping_points", - "rating", - "favourite", - "url", - "ean", - "qr_code", - "co2e_kg", - "attachments", - "archived", - "frozen_at", - "unfrozen_at", - "frozen_storage", - "frozen_note", - "best_by_date", - "finished", - "notes", - "arabica_pct", - "body", - "acidity", - "sweetness", - "age_days", - "days_off_roast", - "days_since_opened", - "frozen_days_excluded", - "effective_age_days", - "age_verdict", - "grams_remaining", - "current_bag_id", - "bag" -]New value: +[ + "id", + "name", + "roaster", + "origin", + "variety", + "roast_date", + "roast_level", + "process_type", + "dial_category", + "bag_notes", + "rest_window_days_min", + "rest_window_days_max", + "state", + "opened_date", + "storage", + "is_active", + "weight_adjustment_g", + "buy_date", + "bag_weight_g", + "cost", + "currency", + "decaffeinated", + "bean_mix", + "roast_range", + "roast_custom", + "roasting_type", + "aromatics", + "cupping_points", + "rating", + "favourite", + "url", + "ean", + "qr_code", + "co2e_kg", + "attachments", + "archived", + "frozen_at", + "unfrozen_at", + "frozen_storage", + "frozen_note", + "best_by_date", + "finished", + "notes", + "arabica_pct", + "body", + "acidity", + "sweetness", + "catalog_coffee_id", + "age_days", + "days_off_roast", + "days_since_opened", + "frozen_days_excluded", + "effective_age_days", + "age_verdict", + "age_verdict_code", + "grams_remaining", + "current_bag_id", + "bag" +] - added
Output schema / properties / active_machine / properties / prep_style / typeAdded value: +"string" - added
Output schema / properties / active_machine / properties / prep_type / typeAdded value: +"string"
- Changed
get_maintenance_guides1 field changed- changed
Input schema / properties / guide_ids / descriptionPrevious value: -"Optional — the guides to fetch. Omit for every guide the user's equipment can use"New value: +"Optional: the guides to fetch. Omit for every guide the user's equipment can use"
- Changed
list_beans10 fields changed- added
Output schema / properties / beans / items / properties / age_verdict_codeAdded value: +{ + "type": "string" +} - added
Output schema / properties / beans / items / properties / bags / items / properties / age_verdict_codeAdded value: +{ + "type": "string" +} - added
Output schema / properties / beans / items / properties / bags / items / properties / lot_revision_idAdded value: +{ + "type": [ + "string", + "null" + ] +} - added
Output schema / properties / beans / items / properties / bags / items / properties / product_idAdded value: +{ + "type": [ + "string", + "null" + ] +} - changed
Output schema / properties / beans / items / properties / bags / items / requiredPrevious value: -[ - "id", - "bean_id", - "roast_date", - "buy_date", - "opened_date", - "best_by_date", - "bag_weight_g", - "weight_adjustment_g", - "cost", - "currency", - "state", - "finished", - "frozen_at", - "unfrozen_at", - "frozen_storage", - "frozen_note", - "storage", - "ean", - "qr_code", - "bag_notes", - "archived", - "effective_age_days", - "age_verdict", - "grams_remaining", - "days_since_opened", - "days_off_roast", - "frozen_days_excluded" -]New value: +[ + "id", + "bean_id", + "roast_date", + "buy_date", + "opened_date", + "best_by_date", + "bag_weight_g", + "weight_adjustment_g", + "cost", + "currency", + "state", + "finished", + "frozen_at", + "unfrozen_at", + "frozen_storage", + "frozen_note", + "storage", + "ean", + "qr_code", + "bag_notes", + "archived", + "product_id", + "lot_revision_id", + "effective_age_days", + "age_verdict", + "age_verdict_code", + "grams_remaining", + "days_since_opened", + "days_off_roast", + "frozen_days_excluded" +] - added
Output schema / properties / beans / items / properties / catalog_coffee_idAdded value: +{ + "type": [ + "string", + "null" + ] +} - added
Output schema / properties / beans / items / properties / origins / items / properties / country_codeAdded value: +{ + "type": [ + "string", + "null" + ] +} - changed
Output schema / properties / beans / items / properties / origins / items / requiredPrevious value: -[ - "country", - "region", - "farm", - "farmer", - "variety", - "processing", - "elevation_m", - "elevation_max_m", - "harvest", - "percentage" -]New value: +[ + "country", + "country_code", + "region", + "farm", + "farmer", + "variety", + "processing", + "elevation_m", + "elevation_max_m", + "harvest", + "percentage" +] - changed
Output schema / properties / beans / items / properties / roaster / typePrevious value: -"string"New value: +[ + "string", + "null" +] - changed
Output schema / properties / beans / items / requiredPrevious value: -[ - "id", - "name", - "roaster", - "roast_level", - "archived", - "favourite", - "decaffeinated", - "process_type", - "dial_category", - "rest_window_days_min", - "rest_window_days_max", - "rating", - "aromatics", - "cupping_points", - "roasting_type", - "variety", - "origin", - "url", - "notes", - "arabica_pct", - "body", - "acidity", - "sweetness", - "roast_date", - "buy_date", - "opened_date", - "best_by_date", - "bag_weight_g", - "weight_adjustment_g", - "cost", - "currency", - "state", - "finished", - "frozen_at", - "unfrozen_at", - "frozen_storage", - "frozen_note", - "storage", - "ean", - "qr_code", - "bag_notes", - "effective_age_days", - "age_verdict", - "grams_remaining", - "days_since_opened", - "days_off_roast", - "frozen_days_excluded", - "current_bag_id", - "bags", - "origins" -]New value: +[ + "id", + "name", + "roaster", + "catalog_coffee_id", + "roast_level", + "archived", + "favourite", + "decaffeinated", + "process_type", + "dial_category", + "rest_window_days_min", + "rest_window_days_max", + "rating", + "aromatics", + "cupping_points", + "roasting_type", + "variety", + "origin", + "url", + "notes", + "arabica_pct", + "body", + "acidity", + "sweetness", + "roast_date", + "buy_date", + "opened_date", + "best_by_date", + "bag_weight_g", + "weight_adjustment_g", + "cost", + "currency", + "state", + "finished", + "frozen_at", + "unfrozen_at", + "frozen_storage", + "frozen_note", + "storage", + "ean", + "qr_code", + "bag_notes", + "effective_age_days", + "age_verdict", + "age_verdict_code", + "grams_remaining", + "days_since_opened", + "days_off_roast", + "frozen_days_excluded", + "current_bag_id", + "bags", + "origins" +]
- Changed
list_grinders1 field changed- changed
Input schema / properties / maintenance / descriptionPrevious value: -"How much of each row's maintenance block to include. compact (default): every task with its class, due state, schedule and guide. full: also the maker's own words — quote, source, alternates, the interval as written."New value: +"How much of each row's maintenance block to include. compact (default): every task with its class, due state, schedule and guide. full: also the maker's own words (quote, source, alternates, the interval as written)."
- Changed
list_machines3 fields changed- changed
Input schema / properties / maintenance / descriptionPrevious value: -"How much of each row's maintenance block to include. compact (default): every task with its class, due state, schedule and guide. full: also the maker's own words — quote, source, alternates, the interval as written."New value: +"How much of each row's maintenance block to include. compact (default): every task with its class, due state, schedule and guide. full: also the maker's own words (quote, source, alternates, the interval as written)." - changed
Output schema / properties / machines / items / properties / prep_style / typePrevious value: -[ - "string", - "null" -]New value: +"string" - changed
Output schema / properties / machines / items / properties / prep_type / typePrevious value: -[ - "string", - "null" -]New value: +"string"
- Changed
list_recipes1 field changed- changed
Output schema / properties / recipes / items / properties / roaster_name / typePrevious value: -"string"New value: +[ + "string", + "null" +]
- Changed
log_maintenance3 fields changed- changed
Input schema / properties / disturbs_zero / descriptionPrevious value: -"Whether this job disturbed the reference the stored numbers are read against — for a burr clean, whether the burrs actually came out. Defaults to the task's own answer; send 0 for a wipe-down that left the collar alone"New value: +"Whether this job disturbed the reference the stored numbers are read against: for a burr clean, whether the burrs actually came out. Defaults to the task's own answer; send 0 for a wipe-down that left the collar alone" - changed
Input schema / properties / guide_id / descriptionPrevious value: -"Optional — the id of the maintenance guide that was followed. Must be a guide for this task"New value: +"Optional: the id of the maintenance guide that was followed. Must be a guide for this task" - changed
Input schema / properties / note / descriptionPrevious value: -"Optional — what you did, and anything that surprised you"New value: +"Optional: what you did, and anything that surprised you"
- Changed
log_shot3 fields changed- changed
Input schema / properties / data_confidence / descriptionPrevious value: -"measured = weighed/timed live; recalled = from memory; estimated = a best guess (e.g. missed the timer — \"~25s\")"New value: +"measured = weighed/timed live; recalled = from memory; estimated = a best guess (e.g. \"~25s\" after missing the timer)" - changed
Input schema / properties / pulled_at / descriptionPrevious value: -"When the shot was actually pulled (ISO 8601 or \"YYYY-MM-DD HH:MM:SS\"), for backdated entries. Defaults to now (null = now). When backdating, pass the returned shot_id to diagnose_shot explicitly — the default diagnosis target is the chronologically latest shot."New value: +"When the shot was actually pulled (ISO 8601 or \"YYYY-MM-DD HH:MM:SS\"), for backdated entries. Defaults to now (null = now). When backdating, pass the returned shot_id to diagnose_shot explicitly, because the default diagnosis target is the chronologically latest shot." - changed
Input schema / properties / tasted / descriptionPrevious value: -"1 = the shot was tasted at log time. The explicit way to record a CLEAN tasting: sensory tags all describe defects, so a good shot has none — without this flag (or a rating) it would be filed taste-pending. Tags or a rating also mark a shot as tasted; 0 (default) = taste later."New value: +"1 = the shot was tasted at log time. The explicit way to record a CLEAN tasting: sensory tags all describe defects, so a good shot has none. Without this flag (or a rating) it would be filed taste-pending. Tags or a rating also mark a shot as tasted; 0 (default) = taste later."
- Changed
register_bag7 fields changed- changed
Input schema / properties / best_by_date / descriptionPrevious value: -"Calendar day in YYYY-MM-DD format — a day, not a timestamp"New value: +"Calendar day in YYYY-MM-DD format: a day, not a timestamp" - changed
Input schema / properties / buy_date / descriptionPrevious value: -"Calendar day in YYYY-MM-DD format — a day, not a timestamp"New value: +"Calendar day in YYYY-MM-DD format: a day, not a timestamp" - added
Input schema / properties / catalog_coffee_idAdded value: +{ + "description": "Set by the apps. Leave out.", + "type": "string" +} - added
Input schema / properties / lot_revision_idAdded value: +{ + "description": "Set by the apps. Leave out.", + "type": "string" +} - changed
Input schema / properties / opened_date / descriptionPrevious value: -"Calendar day in YYYY-MM-DD format — a day, not a timestamp"New value: +"Calendar day in YYYY-MM-DD format: a day, not a timestamp" - added
Input schema / properties / product_idAdded value: +{ + "description": "Set by the apps. Leave out.", + "type": "string" +} - changed
Input schema / properties / roast_date / descriptionPrevious value: -"Calendar day in YYYY-MM-DD format — a day, not a timestamp"New value: +"Calendar day in YYYY-MM-DD format: a day, not a timestamp"
- Changed
register_coffee10 fields changed- changed
Input schema / properties / best_by_date / descriptionPrevious value: -"Calendar day in YYYY-MM-DD format — a day, not a timestamp"New value: +"Calendar day in YYYY-MM-DD format: a day, not a timestamp" - changed
Input schema / properties / buy_date / descriptionPrevious value: -"Calendar day in YYYY-MM-DD format — a day, not a timestamp"New value: +"Calendar day in YYYY-MM-DD format: a day, not a timestamp" - added
Input schema / properties / catalog_coffee_idAdded value: +{ + "description": "Set by the apps. Leave out.", + "type": "string" +} - changed
Input schema / properties / frozen_at / descriptionPrevious value: -"Calendar day the bag went into the freezer, YYYY-MM-DD — a day, not a timestamp"New value: +"Calendar day the bag went into the freezer, YYYY-MM-DD: a day, not a timestamp" - added
Input schema / properties / lot_revision_idAdded value: +{ + "description": "Set by the apps. Leave out.", + "type": "string" +} - changed
Input schema / properties / notes / descriptionPrevious value: -"The coffee's own description — the roaster's tasting notes, the dialing approach that worked. Per bag notes go in bag_notes."New value: +"The coffee's own description: the roaster's tasting notes, the dialing approach that worked. Per bag notes go in bag_notes." - changed
Input schema / properties / opened_date / descriptionPrevious value: -"Calendar day in YYYY-MM-DD format — a day, not a timestamp"New value: +"Calendar day in YYYY-MM-DD format: a day, not a timestamp" - added
Input schema / properties / product_idAdded value: +{ + "description": "Set by the apps. Leave out.", + "type": "string" +} - changed
Input schema / properties / roast_date / descriptionPrevious value: -"Calendar day in YYYY-MM-DD format — a day, not a timestamp"New value: +"Calendar day in YYYY-MM-DD format: a day, not a timestamp" - changed
Input schema / properties / unfrozen_at / descriptionPrevious value: -"Calendar day the bag came out, YYYY-MM-DD — a day, not a timestamp"New value: +"Calendar day the bag came out, YYYY-MM-DD: a day, not a timestamp"
- Changed
register_grinder1 field changed- changed
Input schema / properties / catalog_id / descriptionPrevious value: -"Optional — the maintenance catalog model this is (the `id` of a catalog row, e.g. rancilio-silvia), when it was registered from the catalog. Its maintenance then comes from that model's researched record. \"none\" says it is not in the catalog."New value: +"Optional: the maintenance catalog model this is (the `id` of a catalog row, e.g. rancilio-silvia), when it was registered from the catalog. Its maintenance then comes from that model's researched record. \"none\" says it is not in the catalog."
- Changed
register_machine3 fields changed- changed
Input schema / properties / catalog_id / descriptionPrevious value: -"Optional — the maintenance catalog model this is (the `id` of a catalog row, e.g. rancilio-silvia), when it was registered from the catalog. Its maintenance then comes from that model's researched record. \"none\" says it is not in the catalog."New value: +"Optional: the maintenance catalog model this is (the `id` of a catalog row, e.g. rancilio-silvia), when it was registered from the catalog. Its maintenance then comes from that model's researched record. \"none\" says it is not in the catalog." - changed
Input schema / properties / hardness_dh / descriptionPrevious value: -"Optional — the TOTAL hardness (GH) of the water this machine runs on, in °dH (German degrees; ppm as CaCO3 ÷ 17.85), as a test strip reports it. Picks the band of a maker's hardness table for descaling and filter life"New value: +"Optional: the TOTAL hardness (GH) of the water this machine runs on, in °dH (German degrees; ppm as CaCO3 ÷ 17.85), as a test strip reports it. Picks the band of a maker's hardness table for descaling and filter life" - changed
Input schema / properties / prep_style / descriptionPrevious value: -"Preparation style. One of: espresso, filter, immersion, percolation. Only \"espresso\" is diagnosed by the dialing engine (G8) — anything else is recorded but never dialed, so do not guess this field."New value: +"Preparation style. One of: espresso, filter, immersion, percolation. Only \"espresso\" is diagnosed by the dialing engine (G8). Anything else is recorded but never dialed, so do not guess this field."
- Changed
register_scale3 fields changed- changed
Input schema / properties / height_mm / descriptionPrevious value: -"Overall height in mm — the dimension that decides whether it fits under a group head"New value: +"Overall height in mm: the dimension that decides whether it fits under a group head" - changed
Input schema / properties / resolution_banded / descriptionPrevious value: -"1 when resolution_g only holds in the lowest weight band and coarsens with load — put the ladder in notes"New value: +"1 when resolution_g only holds in the lowest weight band and coarsens with load. Put the ladder in notes" - changed
Input schema / properties / width_mm / descriptionPrevious value: -"Platform width in mm — measure your drip tray"New value: +"Platform width in mm. Measure your drip tray"
- Changed
set_maintenance_schedule1 field changed- changed
Input schema / properties / changed_at / descriptionPrevious value: -"Optional — when the user made this change (ISO 8601, UTC). An app sending a queued edit passes it, so an older edit never overwrites a newer one; it is then answered with applied: false"New value: +"Optional: when the user made this change (ISO 8601, UTC). An app sending a queued edit passes it, so an older edit never overwrites a newer one; it is then answered with applied: false"
- Changed
suggest_next_step2 fields changed- added
Output schema / properties / warning_codesAdded value: +{ + "items": { + "type": "string" + }, + "type": "array" +} - changed
Output schema / requiredPrevious value: -[ - "next_step", - "category", - "warnings" -]New value: +[ + "next_step", + "category", + "warnings", + "warning_codes" +]
- Changed
update_bag6 fields changed- changed
Input schema / properties / fields / properties / best_by_date / descriptionPrevious value: -"Calendar day in YYYY-MM-DD format — a day, not a timestamp"New value: +"Calendar day in YYYY-MM-DD format: a day, not a timestamp" - changed
Input schema / properties / fields / properties / buy_date / descriptionPrevious value: -"Calendar day in YYYY-MM-DD format — a day, not a timestamp"New value: +"Calendar day in YYYY-MM-DD format: a day, not a timestamp" - changed
Input schema / properties / fields / properties / frozen_at / descriptionPrevious value: -"Calendar day the bag went into the freezer, YYYY-MM-DD — a day, not a timestamp"New value: +"Calendar day the bag went into the freezer, YYYY-MM-DD: a day, not a timestamp" - changed
Input schema / properties / fields / properties / opened_date / descriptionPrevious value: -"Calendar day in YYYY-MM-DD format — a day, not a timestamp"New value: +"Calendar day in YYYY-MM-DD format: a day, not a timestamp" - changed
Input schema / properties / fields / properties / roast_date / descriptionPrevious value: -"Calendar day in YYYY-MM-DD format — a day, not a timestamp"New value: +"Calendar day in YYYY-MM-DD format: a day, not a timestamp" - changed
Input schema / properties / fields / properties / unfrozen_at / descriptionPrevious value: -"Calendar day the bag came out, YYYY-MM-DD — a day, not a timestamp"New value: +"Calendar day the bag came out, YYYY-MM-DD: a day, not a timestamp"
- Changed
update_bean8 fields changed- changed
Input schema / properties / fields / properties / best_by_date / descriptionPrevious value: -"Calendar day in YYYY-MM-DD format — a day, not a timestamp"New value: +"Calendar day in YYYY-MM-DD format: a day, not a timestamp" - changed
Input schema / properties / fields / properties / buy_date / descriptionPrevious value: -"Calendar day in YYYY-MM-DD format — a day, not a timestamp"New value: +"Calendar day in YYYY-MM-DD format: a day, not a timestamp" - changed
Input schema / properties / fields / properties / frozen_at / descriptionPrevious value: -"Calendar day the bag went into the freezer, YYYY-MM-DD — a day, not a timestamp"New value: +"Calendar day the bag went into the freezer, YYYY-MM-DD: a day, not a timestamp" - changed
Input schema / properties / fields / properties / notes / descriptionPrevious value: -"The coffee's own description — roaster tasting notes, the dialing approach. Replaces the stored value; the optional reason is appended instead."New value: +"The coffee's own description: roaster tasting notes, the dialing approach. Replaces the stored value; the optional reason is appended instead." - changed
Input schema / properties / fields / properties / opened_date / descriptionPrevious value: -"Calendar day in YYYY-MM-DD format — a day, not a timestamp"New value: +"Calendar day in YYYY-MM-DD format: a day, not a timestamp" - changed
Input schema / properties / fields / properties / roast_date / descriptionPrevious value: -"Calendar day in YYYY-MM-DD format — a day, not a timestamp"New value: +"Calendar day in YYYY-MM-DD format: a day, not a timestamp" - changed
Input schema / properties / fields / properties / unfrozen_at / descriptionPrevious value: -"Calendar day the bag came out, YYYY-MM-DD — a day, not a timestamp"New value: +"Calendar day the bag came out, YYYY-MM-DD: a day, not a timestamp" - changed
Input schema / properties / reason / descriptionPrevious value: -"Optional free-text note, appended as an ordinary line to the coffee's notes — or to the current bag's bag_notes when the call changed only bag fields. Omit it and nothing is written."New value: +"Optional free-text note, appended as an ordinary line to the coffee's notes, or to the current bag's bag_notes when the call changed only bag fields. Omit it and nothing is written."
- Changed
update_grinder2 fields changed- changed
Input schema / properties / fields / properties / components_spec / descriptionPrevious value: -"JSON array of {name, per_step}, coarsest first — the ring arithmetic of a compound collar, or the ordered settings of a named one"New value: +"JSON array of {name, per_step}, coarsest first: the ring arithmetic of a compound collar, or the ordered settings of a named one" - changed
Input schema / properties / fields / properties / nominal_step / descriptionPrevious value: -"Smallest adjustment increment. On a numeric_stepless collar it is the precision labels are recorded in (0.1 records tenths) and the size of one click. numeric_stepped and clicks_single collars record whole steps whatever it says — to record tenths, set setting_scheme numeric_stepless as well"New value: +"Smallest adjustment increment. On a numeric_stepless collar it is the precision labels are recorded in (0.1 records tenths) and the size of one click. numeric_stepped and clicks_single collars record whole steps whatever it says. To record tenths, set setting_scheme numeric_stepless as well"
5 tool updates
- Changed
get_dial_state6 fields changed- added
Output schema / properties / active_machine / properties / settings / items / properties / provenanceAdded value: +{ + "additionalProperties": true, + "properties": { + "default_quote": { + "type": [ + "string", + "null" + ] + }, + "default_source": { + "type": [ + "string", + "null" + ] + }, + "quote": { + "type": [ + "string", + "null" + ] + }, + "source": { + "type": [ + "string", + "null" + ] + } + }, + "required": [ + "source", + "quote", + "default_source", + "default_quote" + ], + "type": [ + "object", + "null" + ] +} - changed
Output schema / properties / active_machine / properties / settings / items / requiredPrevious value: -[ - "key", - "label", - "type", - "options", - "min", - "max", - "step", - "unit", - "default", - "value" -]New value: +[ + "key", + "label", + "type", + "options", + "min", + "max", + "step", + "unit", + "default", + "value", + "provenance" +] - added
Output schema / properties / locked_recipe / properties / machine_settingsAdded value: +{ + "additionalProperties": true, + "type": [ + "object", + "null" + ] +} - changed
Output schema / properties / locked_recipe / requiredPrevious value: -[ - "id", - "bean_id", - "grinder_id", - "machine_id", - "program_id", - "status", - "grind_label", - "grind_position_value", - "dose_g", - "target_yield_g", - "target_time_s", - "finish_action", - "drink_intent", - "profile", - "kb_version", - "locked_at", - "grind_reading" -]New value: +[ + "id", + "bean_id", + "grinder_id", + "machine_id", + "program_id", + "status", + "grind_label", + "grind_position_value", + "dose_g", + "target_yield_g", + "target_time_s", + "finish_action", + "drink_intent", + "profile", + "kb_version", + "locked_at", + "machine_settings", + "grind_reading" +] - added
Output schema / properties / recent_shots / items / properties / machine_settings / additionalPropertiesAdded value: +true - added
Output schema / properties / recent_shots / items / properties / machine_settings / typeAdded value: +[ + "object", + "null" +]
- Changed
list_machines2 fields changed- added
Output schema / properties / machines / items / properties / settings / items / properties / provenanceAdded value: +{ + "additionalProperties": true, + "properties": { + "default_quote": { + "type": [ + "string", + "null" + ] + }, + "default_source": { + "type": [ + "string", + "null" + ] + }, + "quote": { + "type": [ + "string", + "null" + ] + }, + "source": { + "type": [ + "string", + "null" + ] + } + }, + "required": [ + "source", + "quote", + "default_source", + "default_quote" + ], + "type": [ + "object", + "null" + ] +} - changed
Output schema / properties / machines / items / properties / settings / items / requiredPrevious value: -[ - "key", - "label", - "type", - "options", - "min", - "max", - "step", - "unit", - "default", - "value" -]New value: +[ + "key", + "label", + "type", + "options", + "min", + "max", + "step", + "unit", + "default", + "value", + "provenance" +]
- Changed
list_recipes2 fields changed- added
Output schema / properties / recipes / items / properties / machine_settingsAdded value: +{ + "additionalProperties": true, + "type": [ + "object", + "null" + ] +} - changed
Output schema / properties / recipes / items / requiredPrevious value: -[ - "id", - "bean_id", - "grinder_id", - "machine_id", - "program_id", - "status", - "grind_label", - "grind_position_value", - "dose_g", - "target_yield_g", - "target_time_s", - "finish_action", - "drink_intent", - "profile", - "locked_at", - "bean_name", - "roaster_name", - "grinder_name", - "machine_name", - "grind_reading" -]New value: +[ + "id", + "bean_id", + "grinder_id", + "machine_id", + "program_id", + "status", + "grind_label", + "grind_position_value", + "dose_g", + "target_yield_g", + "target_time_s", + "finish_action", + "drink_intent", + "profile", + "locked_at", + "machine_settings", + "bean_name", + "roaster_name", + "grinder_name", + "machine_name", + "grind_reading" +]
- Changed
list_shots2 fields changed- added
Output schema / properties / shots / items / properties / machine_settings / additionalPropertiesAdded value: +true - changed
Output schema / properties / shots / items / properties / machine_settings / typePrevious value: -[ - "null", - "string" -]New value: +[ + "object", + "null" +]
- Changed
set_active1 field changed- changed
Input schema / properties / program_id / descriptionPrevious value: -"A program number from the active machine's list. null = leave unchanged"New value: +"A program number from the active machine's list; switching machines clears it. null = leave unchanged"
7 tool updates
- Changed
get_dial_state4 fields changed- added
Output schema / properties / active_machine / properties / settingsAdded value: +{ + "items": { + "additionalProperties": true, + "properties": { + "default": { + "type": [ + "number", + "null", + "string" + ] + }, + "key": { + "type": "string" + }, + "label": { + "type": "string" + }, + "max": { + "type": [ + "number", + "null" + ] + }, + "min": { + "type": [ + "number", + "null" + ] + }, + "options": { + "items": { + "additionalProperties": true, + "properties": { + "label": { + "type": "string" + }, + "meaning": { + "type": [ + "string", + "null" + ] + }, + "value": { + "type": "string" + } + }, + "required": [ + "value", + "label", + "meaning" + ], + "type": "object" + }, + "type": [ + "null", + "array" + ] + }, + "step": {}, + "type": { + "type": "string" + }, + "unit": { + "type": [ + "string", + "null" + ] + }, + "value": { + "type": [ + "number", + "null", + "string" + ] + } + }, + "required": [ + "key", + "label", + "type", + "options", + "min", + "max", + "step", + "unit", + "default", + "value" + ], + "type": "object" + }, + "type": [ + "array", + "null" + ] +} - changed
Output schema / properties / active_machine / requiredPrevious value: -[ - "id", - "name", - "control_type", - "basket_size_grams", - "boiler_type", - "notes", - "is_active", - "prep_type", - "prep_style", - "archived", - "photo", - "tools", - "connected_device", - "built_in_grinder_id", - "catalog_id", - "hardness_dh" -]New value: +[ + "id", + "name", + "control_type", + "basket_size_grams", + "boiler_type", + "notes", + "is_active", + "prep_type", + "prep_style", + "archived", + "photo", + "tools", + "connected_device", + "built_in_grinder_id", + "catalog_id", + "hardness_dh", + "settings" +] - added
Output schema / properties / recent_shots / items / properties / machine_settingsAdded value: +{} - changed
Output schema / properties / recent_shots / items / requiredPrevious value: -[ - "id", - "pulled_at", - "bean_id", - "grinder_id", - "machine_id", - "program_id", - "grind_label", - "grind_components", - "grind_position_value", - "dose_g", - "yield_g", - "time_s", - "flow_rate_gps", - "finish_action", - "drink_intent", - "flavor_notes", - "sensory_tags", - "observations", - "temp_taste", - "rating", - "verdict", - "data_confidence", - "temperature_c", - "bloom_time_s", - "first_drip_time_s", - "beverage_g", - "tds", - "ey_pct", - "water_id", - "vessel_name", - "vessel_weight_g", - "favourite", - "best_brew", - "tasted", - "bag_id", - "taste_pending" -]New value: +[ + "id", + "pulled_at", + "bean_id", + "grinder_id", + "machine_id", + "program_id", + "grind_label", + "grind_components", + "grind_position_value", + "dose_g", + "yield_g", + "time_s", + "flow_rate_gps", + "finish_action", + "drink_intent", + "flavor_notes", + "sensory_tags", + "observations", + "temp_taste", + "rating", + "verdict", + "data_confidence", + "temperature_c", + "bloom_time_s", + "first_drip_time_s", + "beverage_g", + "tds", + "ey_pct", + "water_id", + "vessel_name", + "vessel_weight_g", + "favourite", + "best_brew", + "tasted", + "bag_id", + "machine_settings", + "taste_pending" +]
- Changed
get_maintenance_guides1 field changed- added
Output schema / properties / guides / items / properties / steps / items / properties / repeatAdded value: +{ + "type": "integer" +}
- Changed
list_machines13 fields changed- changed
Output schema / properties / machines / items / properties / catalog_id / typePrevious value: -[ - "null", - "string" -]New value: +[ + "string", + "null" +] - changed
Output schema / properties / machines / items / properties / maintenance / properties / catalog / properties / brand / typePrevious value: -[ - "null", - "string" -]New value: +[ + "string", + "null" +] - changed
Output schema / properties / machines / items / properties / maintenance / properties / catalog / properties / id / typePrevious value: -[ - "null", - "string" -]New value: +[ + "string", + "null" +] - changed
Output schema / properties / machines / items / properties / maintenance / properties / catalog / properties / model / typePrevious value: -[ - "null", - "string" -]New value: +[ + "string", + "null" +] - changed
Output schema / properties / machines / items / properties / maintenance / properties / due / typePrevious value: -[ - "null", - "object" -]New value: +[ + "object", + "null" +] - added
Output schema / properties / machines / items / properties / maintenance / properties / tasks / items / properties / guide / properties / also_covers / itemsAdded value: +{ + "type": "string" +} - added
Output schema / properties / machines / items / properties / maintenance / properties / tasks / items / properties / guide / properties / also_covers / typeAdded value: +[ + "array", + "null" +] - changed
Output schema / properties / machines / items / properties / maintenance / properties / tasks / items / properties / guide / properties / duration_minutes / typePrevious value: -[ - "integer", - "null" -]New value: +[ + "null", + "integer" +] - changed
Output schema / properties / machines / items / properties / maintenance / properties / tasks / items / properties / guide / properties / machine_alert / typePrevious value: -[ - "object", - "null" -]New value: +[ + "null", + "object" +] - changed
Output schema / properties / machines / items / properties / maintenance / properties / tasks / items / properties / status / typePrevious value: -[ - "null", - "string" -]New value: +[ + "string", + "null" +] - changed
Output schema / properties / machines / items / properties / notes / typePrevious value: -[ - "string", - "null" -]New value: +[ + "null", + "string" +] - added
Output schema / properties / machines / items / properties / settingsAdded value: +{ + "items": { + "additionalProperties": true, + "properties": { + "default": { + "type": [ + "number", + "null", + "string" + ] + }, + "key": { + "type": "string" + }, + "label": { + "type": "string" + }, + "max": { + "type": [ + "number", + "null" + ] + }, + "min": { + "type": [ + "number", + "null" + ] + }, + "options": { + "items": { + "additionalProperties": true, + "properties": { + "label": { + "type": "string" + }, + "meaning": { + "type": [ + "string", + "null" + ] + }, + "value": { + "type": "string" + } + }, + "required": [ + "value", + "label", + "meaning" + ], + "type": "object" + }, + "type": [ + "null", + "array" + ] + }, + "step": {}, + "type": { + "type": "string" + }, + "unit": { + "type": [ + "string", + "null" + ] + }, + "value": { + "type": [ + "number", + "null", + "string" + ] + } + }, + "required": [ + "key", + "label", + "type", + "options", + "min", + "max", + "step", + "unit", + "default", + "value" + ], + "type": "object" + }, + "type": [ + "array", + "null" + ] +} - changed
Output schema / properties / machines / items / requiredPrevious value: -[ - "id", - "name", - "control_type", - "basket_size_grams", - "boiler_type", - "notes", - "prep_type", - "prep_style", - "archived", - "built_in_grinder_id", - "catalog_id", - "hardness_dh", - "tools_list", - "programs", - "maintenance" -]New value: +[ + "id", + "name", + "control_type", + "basket_size_grams", + "boiler_type", + "notes", + "prep_type", + "prep_style", + "archived", + "built_in_grinder_id", + "catalog_id", + "hardness_dh", + "tools_list", + "programs", + "maintenance", + "settings" +]
- Changed
list_shots2 fields changed- added
Output schema / properties / shots / items / properties / machine_settingsAdded value: +{ + "type": [ + "null", + "string" + ] +} - changed
Output schema / properties / shots / items / requiredPrevious value: -[ - "id", - "pulled_at", - "bean_id", - "grinder_id", - "machine_id", - "program_id", - "grind_label", - "grind_components", - "grind_position_value", - "dose_g", - "yield_g", - "time_s", - "flow_rate_gps", - "finish_action", - "drink_intent", - "flavor_notes", - "sensory_tags", - "observations", - "temp_taste", - "rating", - "verdict", - "data_confidence", - "temperature_c", - "bloom_time_s", - "first_drip_time_s", - "beverage_g", - "tds", - "ey_pct", - "water_id", - "vessel_name", - "vessel_weight_g", - "favourite", - "best_brew", - "tasted", - "bag_id", - "bean_name", - "taste_pending" -]New value: +[ + "id", + "pulled_at", + "bean_id", + "grinder_id", + "machine_id", + "program_id", + "grind_label", + "grind_components", + "grind_position_value", + "dose_g", + "yield_g", + "time_s", + "flow_rate_gps", + "finish_action", + "drink_intent", + "flavor_notes", + "sensory_tags", + "observations", + "temp_taste", + "rating", + "verdict", + "data_confidence", + "temperature_c", + "bloom_time_s", + "first_drip_time_s", + "beverage_g", + "tds", + "ey_pct", + "water_id", + "vessel_name", + "vessel_weight_g", + "favourite", + "best_brew", + "tasted", + "bag_id", + "machine_settings", + "bean_name", + "taste_pending" +]
- Changed
log_shot1 field changed- added
Input schema / properties / machine_settingsAdded value: +{ + "description": "Only when this one shot was pulled with a selector somewhere other than the machine's recorded settings: {key: position}. The shot is otherwise stamped with those automatically; a lasting change goes through update_machine.", + "maxProperties": 16, + "type": "object" +}
- Changed
update_machine1 field changed- added
Input schema / properties / fields / properties / settingsAdded value: +{ + "description": "Where the machine's selectors now stand, as {key: position} from list_machines settings, e.g. {\"brew_temperature\": \"ii\"}. Only the keys given change; a null position clears one, null clears all. Shots are stamped with these.", + "type": [ + "object", + "null" + ] +}
- Changed
update_shot1 field changed- added
Input schema / properties / fields / properties / machine_settingsAdded value: +{ + "description": "The machine's selector positions for this shot, {key: position}; replaces what was stamped, null clears it", + "maxProperties": 16, + "type": [ + "object", + "null" + ] +}
1 tool update
- Changed
get_maintenance_guides2 fields changed- added
Output schema / properties / guides / items / properties / steps / items / properties / anchorAdded value: +{ + "type": "string" +} - changed
Output schema / properties / guides / items / properties / steps / items / requiredPrevious value: -[ - "n", - "text", - "source" -]New value: +[ + "n", + "text", + "source", + "anchor" +]
1 tool update
- Changed
lock_recipe2 fields changed- added
Output schema / properties / recipe_idAdded value: +{ + "type": "integer" +} - changed
Output schema / requiredPrevious value: -[ - "status", - "message" -]New value: +[ + "status", + "recipe_id", + "message" +]
11 tool updates
- Changed
compute_age2 fields changed- removed
Output schema / properties / days_since_opened / typeRemoved value: -"null" - removed
Output schema / properties / grams_remaining / typeRemoved value: -"null"
- Changed
get_dial_state86 fields changed- removed
Output schema / properties / active_coffee / properties / acidity / typeRemoved value: -"null" - removed
Output schema / properties / active_coffee / properties / arabica_pct / typeRemoved value: -"null" - removed
Output schema / properties / active_coffee / properties / aromatics / typeRemoved value: -"null" - removed
Output schema / properties / active_coffee / properties / attachments / typeRemoved value: -"null" - removed
Output schema / properties / active_coffee / properties / bag / properties / bag_weight_g / typeRemoved value: -"null" - removed
Output schema / properties / active_coffee / properties / bag / properties / best_by_date / typeRemoved value: -"null" - removed
Output schema / properties / active_coffee / properties / bag / properties / buy_date / typeRemoved value: -"null" - removed
Output schema / properties / active_coffee / properties / bag / properties / cost / typeRemoved value: -"null" - removed
Output schema / properties / active_coffee / properties / bag / properties / currency / typeRemoved value: -"null" - removed
Output schema / properties / active_coffee / properties / bag / properties / days_since_opened / typeRemoved value: -"null" - removed
Output schema / properties / active_coffee / properties / bag / properties / ean / typeRemoved value: -"null" - removed
Output schema / properties / active_coffee / properties / bag / properties / frozen_at / typeRemoved value: -"null" - removed
Output schema / properties / active_coffee / properties / bag / properties / frozen_note / typeRemoved value: -"null" - removed
Output schema / properties / active_coffee / properties / bag / properties / frozen_storage / typeRemoved value: -"null" - removed
Output schema / properties / active_coffee / properties / bag / properties / grams_remaining / typeRemoved value: -"null" - removed
Output schema / properties / active_coffee / properties / bag / properties / opened_date / typeRemoved value: -"null" - removed
Output schema / properties / active_coffee / properties / bag / properties / qr_code / typeRemoved value: -"null" - removed
Output schema / properties / active_coffee / properties / bag / properties / storage / typeRemoved value: -"null" - removed
Output schema / properties / active_coffee / properties / bag / properties / unfrozen_at / typeRemoved value: -"null" - removed
Output schema / properties / active_coffee / properties / bag_weight_g / typeRemoved value: -"null" - removed
Output schema / properties / active_coffee / properties / bean_mix / typeRemoved value: -"null" - removed
Output schema / properties / active_coffee / properties / best_by_date / typeRemoved value: -"null" - removed
Output schema / properties / active_coffee / properties / body / typeRemoved value: -"null" - removed
Output schema / properties / active_coffee / properties / buy_date / typeRemoved value: -"null" - removed
Output schema / properties / active_coffee / properties / co2e_kg / typeRemoved value: -"null" - removed
Output schema / properties / active_coffee / properties / cost / typeRemoved value: -"null" - removed
Output schema / properties / active_coffee / properties / cupping_points / typeRemoved value: -"null" - removed
Output schema / properties / active_coffee / properties / currency / typeRemoved value: -"null" - removed
Output schema / properties / active_coffee / properties / days_since_opened / typeRemoved value: -"null" - removed
Output schema / properties / active_coffee / properties / decaffeinated / typeRemoved value: -"null" - removed
Output schema / properties / active_coffee / properties / ean / typeRemoved value: -"null" - removed
Output schema / properties / active_coffee / properties / favourite / typeRemoved value: -"null" - removed
Output schema / properties / active_coffee / properties / frozen_at / typeRemoved value: -"null" - removed
Output schema / properties / active_coffee / properties / frozen_note / typeRemoved value: -"null" - removed
Output schema / properties / active_coffee / properties / frozen_storage / typeRemoved value: -"null" - removed
Output schema / properties / active_coffee / properties / grams_remaining / typeRemoved value: -"null" - removed
Output schema / properties / active_coffee / properties / notes / typeRemoved value: -"null" - removed
Output schema / properties / active_coffee / properties / opened_date / typeRemoved value: -"null" - removed
Output schema / properties / active_coffee / properties / origin / typeRemoved value: -"null" - removed
Output schema / properties / active_coffee / properties / qr_code / typeRemoved value: -"null" - removed
Output schema / properties / active_coffee / properties / rating / typeRemoved value: -"null" - removed
Output schema / properties / active_coffee / properties / rest_window_days_max / typeRemoved value: -"null" - removed
Output schema / properties / active_coffee / properties / rest_window_days_min / typeRemoved value: -"null" - removed
Output schema / properties / active_coffee / properties / roast_custom / typeRemoved value: -"null" - removed
Output schema / properties / active_coffee / properties / roast_range / typeRemoved value: -"null" - removed
Output schema / properties / active_coffee / properties / roasting_type / typeRemoved value: -"null" - removed
Output schema / properties / active_coffee / properties / storage / typeRemoved value: -"null" - removed
Output schema / properties / active_coffee / properties / sweetness / typeRemoved value: -"null" - removed
Output schema / properties / active_coffee / properties / unfrozen_at / typeRemoved value: -"null" - removed
Output schema / properties / active_coffee / properties / url / typeRemoved value: -"null" - removed
Output schema / properties / active_coffee / properties / variety / typeRemoved value: -"null" - removed
Output schema / properties / active_grinder / properties / built_in_machine_id / typeRemoved value: -"null" - removed
Output schema / properties / active_grinder / properties / catalog_id / typeRemoved value: -"null" - removed
Output schema / properties / active_grinder / properties / max_value / typeRemoved value: -"null" - removed
Output schema / properties / active_grinder / properties / min_value / typeRemoved value: -"null" - removed
Output schema / properties / active_grinder / properties / notes / typeRemoved value: -"null" - removed
Output schema / properties / active_grinder / properties / photo / typeRemoved value: -"null" - removed
Output schema / properties / active_machine / properties / built_in_grinder_id / typeRemoved value: -"null" - removed
Output schema / properties / active_machine / properties / connected_device / typeRemoved value: -"null" - removed
Output schema / properties / active_machine / properties / hardness_dh / typeRemoved value: -"null" - removed
Output schema / properties / active_machine / properties / notes / typeRemoved value: -"null" - removed
Output schema / properties / active_machine / properties / photo / typeRemoved value: -"null" - removed
Output schema / properties / active_machine / properties / prep_style / typeRemoved value: -"null" - removed
Output schema / properties / active_machine / properties / prep_type / typeRemoved value: -"null" - removed
Output schema / properties / active_machine / properties / tools / typeRemoved value: -"null" - removed
Output schema / properties / active_program / typeRemoved value: -"null" - removed
Output schema / properties / locked_recipe / properties / grind_reading / typeRemoved value: -"null" - removed
Output schema / properties / locked_recipe / properties / program_id / typeRemoved value: -"null" - removed
Output schema / properties / maintenance_summary / properties / most_urgent / properties / due_at / typeRemoved value: -"null" - removed
Output schema / properties / maintenance_summary / properties / most_urgent / properties / last_at / typeRemoved value: -"null" - removed
Output schema / properties / maintenance_summary / properties / most_urgent / properties / muted_until / typeRemoved value: -"null" - removed
Output schema / properties / maintenance_summary / properties / most_urgent / properties / overdue_at / typeRemoved value: -"null" - removed
Output schema / properties / maintenance_summary / properties / most_urgent / properties / soon_at / typeRemoved value: -"null" - removed
Output schema / properties / recent_recommendations / items / properties / based_on_shot / typeRemoved value: -"null" - removed
Output schema / properties / recent_shots / items / properties / beverage_g / typeRemoved value: -"null" - removed
Output schema / properties / recent_shots / items / properties / bloom_time_s / typeRemoved value: -"null" - removed
Output schema / properties / recent_shots / items / properties / ey_pct / typeRemoved value: -"null" - removed
Output schema / properties / recent_shots / items / properties / first_drip_time_s / typeRemoved value: -"null" - removed
Output schema / properties / recent_shots / items / properties / program_id / typeRemoved value: -"null" - removed
Output schema / properties / recent_shots / items / properties / rating / typeRemoved value: -"null" - removed
Output schema / properties / recent_shots / items / properties / tds / typeRemoved value: -"null" - removed
Output schema / properties / recent_shots / items / properties / temperature_c / typeRemoved value: -"null" - removed
Output schema / properties / recent_shots / items / properties / verdict / typeRemoved value: -"null" - removed
Output schema / properties / recent_shots / items / properties / vessel_name / typeRemoved value: -"null" - removed
Output schema / properties / recent_shots / items / properties / vessel_weight_g / typeRemoved value: -"null" - removed
Output schema / properties / recent_shots / items / properties / water_id / typeRemoved value: -"null"
- Changed
get_maintenance_guides3 fields changed- removed
Output schema / properties / guides / items / properties / machine_alert / properties / can_disable / typeRemoved value: -"null" - removed
Output schema / properties / guides / items / properties / machine_alert / properties / depends_on_setting / typeRemoved value: -"null" - removed
Output schema / properties / guides / items / properties / machine_alert / properties / threshold / typeRemoved value: -"null"
- Changed
list_beans41 fields changed- removed
Output schema / properties / beans / items / properties / acidity / typeRemoved value: -"null" - removed
Output schema / properties / beans / items / properties / arabica_pct / typeRemoved value: -"null" - removed
Output schema / properties / beans / items / properties / aromatics / typeRemoved value: -"null" - removed
Output schema / properties / beans / items / properties / bags / items / properties / best_by_date / typeRemoved value: -"null" - removed
Output schema / properties / beans / items / properties / bags / items / properties / buy_date / typeRemoved value: -"null" - removed
Output schema / properties / beans / items / properties / bags / items / properties / days_since_opened / typeRemoved value: -"null" - removed
Output schema / properties / beans / items / properties / bags / items / properties / ean / typeRemoved value: -"null" - removed
Output schema / properties / beans / items / properties / bags / items / properties / frozen_at / typeRemoved value: -"null" - removed
Output schema / properties / beans / items / properties / bags / items / properties / frozen_note / typeRemoved value: -"null" - removed
Output schema / properties / beans / items / properties / bags / items / properties / frozen_storage / typeRemoved value: -"null" - removed
Output schema / properties / beans / items / properties / bags / items / properties / opened_date / typeRemoved value: -"null" - removed
Output schema / properties / beans / items / properties / bags / items / properties / qr_code / typeRemoved value: -"null" - removed
Output schema / properties / beans / items / properties / bags / items / properties / storage / typeRemoved value: -"null" - removed
Output schema / properties / beans / items / properties / bags / items / properties / unfrozen_at / typeRemoved value: -"null" - removed
Output schema / properties / beans / items / properties / best_by_date / typeRemoved value: -"null" - removed
Output schema / properties / beans / items / properties / body / typeRemoved value: -"null" - removed
Output schema / properties / beans / items / properties / buy_date / typeRemoved value: -"null" - removed
Output schema / properties / beans / items / properties / cost / typeRemoved value: -"null" - removed
Output schema / properties / beans / items / properties / cupping_points / typeRemoved value: -"null" - removed
Output schema / properties / beans / items / properties / currency / typeRemoved value: -"null" - removed
Output schema / properties / beans / items / properties / days_since_opened / typeRemoved value: -"null" - removed
Output schema / properties / beans / items / properties / ean / typeRemoved value: -"null" - removed
Output schema / properties / beans / items / properties / frozen_at / typeRemoved value: -"null" - removed
Output schema / properties / beans / items / properties / frozen_note / typeRemoved value: -"null" - removed
Output schema / properties / beans / items / properties / frozen_storage / typeRemoved value: -"null" - removed
Output schema / properties / beans / items / properties / opened_date / typeRemoved value: -"null" - removed
Output schema / properties / beans / items / properties / origin / typeRemoved value: -"null" - removed
Output schema / properties / beans / items / properties / origins / items / properties / elevation_m / typeRemoved value: -"null" - removed
Output schema / properties / beans / items / properties / origins / items / properties / elevation_max_m / typeRemoved value: -"null" - removed
Output schema / properties / beans / items / properties / origins / items / properties / farm / typeRemoved value: -"null" - removed
Output schema / properties / beans / items / properties / origins / items / properties / farmer / typeRemoved value: -"null" - removed
Output schema / properties / beans / items / properties / origins / items / properties / harvest / typeRemoved value: -"null" - removed
Output schema / properties / beans / items / properties / origins / items / properties / processing / typeRemoved value: -"null" - removed
Output schema / properties / beans / items / properties / qr_code / typeRemoved value: -"null" - removed
Output schema / properties / beans / items / properties / rating / typeRemoved value: -"null" - removed
Output schema / properties / beans / items / properties / roasting_type / typeRemoved value: -"null" - removed
Output schema / properties / beans / items / properties / storage / typeRemoved value: -"null" - removed
Output schema / properties / beans / items / properties / sweetness / typeRemoved value: -"null" - removed
Output schema / properties / beans / items / properties / unfrozen_at / typeRemoved value: -"null" - removed
Output schema / properties / beans / items / properties / url / typeRemoved value: -"null" - removed
Output schema / properties / beans / items / properties / variety / typeRemoved value: -"null"
- Changed
list_grinders11 fields changed- removed
Output schema / properties / grinders / items / properties / maintenance / properties / due / properties / burr_clean / properties / muted_until / typeRemoved value: -"null" - removed
Output schema / properties / grinders / items / properties / maintenance / properties / entries / items / properties / guide_id / typeRemoved value: -"null" - removed
Output schema / properties / grinders / items / properties / maintenance / properties / hardness / typeRemoved value: -"null" - removed
Output schema / properties / grinders / items / properties / maintenance / properties / sensitivity / typeRemoved value: -"null" - removed
Output schema / properties / grinders / items / properties / maintenance / properties / tasks / items / properties / guide / properties / also_covers / typeRemoved value: -"null" - removed
Output schema / properties / grinders / items / properties / maintenance / properties / tasks / items / properties / guide / properties / duration_minutes / typeRemoved value: -"null" - removed
Output schema / properties / grinders / items / properties / maintenance / properties / tasks / items / properties / guide / properties / duration_note / typeRemoved value: -"null" - removed
Output schema / properties / grinders / items / properties / maintenance / properties / tasks / items / properties / guide / properties / machine_alert / typeRemoved value: -"null" - removed
Output schema / properties / grinders / items / properties / maintenance / properties / tasks / items / properties / guide / properties / market / typeRemoved value: -"null" - removed
Output schema / properties / grinders / items / properties / maintenance / properties / tasks / items / properties / schedule / properties / every / typeRemoved value: -"null" - removed
Output schema / properties / grinders / items / properties / maintenance / properties / tasks / items / properties / schedule / properties / muted_until / typeRemoved value: -"null"
- Changed
list_machines29 fields changed- removed
Output schema / properties / machines / items / properties / maintenance / properties / calibration / properties / disturbs_note / typeRemoved value: -"null" - removed
Output schema / properties / machines / items / properties / maintenance / properties / calibration / properties / epoch_at / typeRemoved value: -"null" - removed
Output schema / properties / machines / items / properties / maintenance / properties / calibration / properties / epoch_id / typeRemoved value: -"null" - removed
Output schema / properties / machines / items / properties / maintenance / properties / calibration / properties / epoch_task / typeRemoved value: -"null" - removed
Output schema / properties / machines / items / properties / maintenance / properties / calibration / properties / evidence / typeRemoved value: -"null" - removed
Output schema / properties / machines / items / properties / maintenance / properties / calibration / properties / offset_at / typeRemoved value: -"null" - removed
Output schema / properties / machines / items / properties / maintenance / properties / calibration / properties / offset_source / typeRemoved value: -"null" - removed
Output schema / properties / machines / items / properties / maintenance / properties / calibration / properties / offset_unit / typeRemoved value: -"null" - removed
Output schema / properties / machines / items / properties / maintenance / properties / calibration / properties / offset_value / typeRemoved value: -"null" - removed
Output schema / properties / machines / items / properties / maintenance / properties / calibration / properties / reference_recipe_id / typeRemoved value: -"null" - removed
Output schema / properties / machines / items / properties / maintenance / properties / catalog / properties / match / typeRemoved value: -"null" - removed
Output schema / properties / machines / items / properties / maintenance / properties / catalog / properties / via / typeRemoved value: -"null" - changed
Output schema / properties / machines / items / properties / maintenance / properties / due / propertiesPrevious value: -[]New value: +{} - removed
Output schema / properties / machines / items / properties / maintenance / properties / entries / items / properties / evidence / typeRemoved value: -"null" - removed
Output schema / properties / machines / items / properties / maintenance / properties / entries / items / properties / note / typeRemoved value: -"null" - removed
Output schema / properties / machines / items / properties / maintenance / properties / entries / items / properties / offset_at / typeRemoved value: -"null" - removed
Output schema / properties / machines / items / properties / maintenance / properties / entries / items / properties / offset_source / typeRemoved value: -"null" - removed
Output schema / properties / machines / items / properties / maintenance / properties / entries / items / properties / offset_value / typeRemoved value: -"null" - removed
Output schema / properties / machines / items / properties / maintenance / properties / sensitivity / typeRemoved value: -"null" - removed
Output schema / properties / machines / items / properties / maintenance / properties / tasks / items / properties / disturbs_prompt / typeRemoved value: -"null" - removed
Output schema / properties / machines / items / properties / maintenance / properties / tasks / items / properties / guide / properties / also_covers / typeRemoved value: -"null" - removed
Output schema / properties / machines / items / properties / maintenance / properties / tasks / items / properties / guide / properties / duration_note / typeRemoved value: -"null" - removed
Output schema / properties / machines / items / properties / maintenance / properties / tasks / items / properties / guide / properties / machine_alert / properties / can_disable / typeRemoved value: -"null" - removed
Output schema / properties / machines / items / properties / maintenance / properties / tasks / items / properties / guide / properties / machine_alert / properties / depends_on_setting / typeRemoved value: -"null" - removed
Output schema / properties / machines / items / properties / maintenance / properties / tasks / items / properties / guide / properties / machine_alert / properties / threshold / typeRemoved value: -"null" - removed
Output schema / properties / machines / items / properties / maintenance / properties / tasks / items / properties / guide / properties / market / typeRemoved value: -"null" - removed
Output schema / properties / machines / items / properties / maintenance / properties / tasks / items / properties / guide / properties / variant / typeRemoved value: -"null" - removed
Output schema / properties / machines / items / properties / maintenance / properties / tasks / items / properties / opened_by / typeRemoved value: -"null" - removed
Output schema / properties / machines / items / properties / programs / items / properties / target_time_s / typeRemoved value: -"null"
- Changed
list_recipes3 fields changed- removed
Output schema / properties / recipes / items / properties / grind_reading / properties / label / typeRemoved value: -"null" - removed
Output schema / properties / recipes / items / properties / grind_reading / properties / offset_clicks / typeRemoved value: -"null" - removed
Output schema / properties / recipes / items / properties / grind_reading / properties / offset_direction / typeRemoved value: -"null"
- Changed
list_scales11 fields changed- removed
Output schema / properties / scales / items / properties / auto_tare / typeRemoved value: -"null" - removed
Output schema / properties / scales / items / properties / auto_timer / typeRemoved value: -"null" - removed
Output schema / properties / scales / items / properties / capacity_g / typeRemoved value: -"null" - removed
Output schema / properties / scales / items / properties / connectivity / typeRemoved value: -"null" - removed
Output schema / properties / scales / items / properties / depth_mm / typeRemoved value: -"null" - removed
Output schema / properties / scales / items / properties / flow_rate_display / typeRemoved value: -"null" - removed
Output schema / properties / scales / items / properties / height_mm / typeRemoved value: -"null" - removed
Output schema / properties / scales / items / properties / notes / typeRemoved value: -"null" - removed
Output schema / properties / scales / items / properties / power / typeRemoved value: -"null" - removed
Output schema / properties / scales / items / properties / water_resistance / typeRemoved value: -"null" - removed
Output schema / properties / scales / items / properties / width_mm / typeRemoved value: -"null"
- Changed
list_shots12 fields changed- removed
Output schema / properties / shots / items / properties / beverage_g / typeRemoved value: -"null" - removed
Output schema / properties / shots / items / properties / bloom_time_s / typeRemoved value: -"null" - removed
Output schema / properties / shots / items / properties / ey_pct / typeRemoved value: -"null" - removed
Output schema / properties / shots / items / properties / first_drip_time_s / typeRemoved value: -"null" - removed
Output schema / properties / shots / items / properties / program_id / typeRemoved value: -"null" - removed
Output schema / properties / shots / items / properties / rating / typeRemoved value: -"null" - removed
Output schema / properties / shots / items / properties / tds / typeRemoved value: -"null" - removed
Output schema / properties / shots / items / properties / temperature_c / typeRemoved value: -"null" - removed
Output schema / properties / shots / items / properties / verdict / typeRemoved value: -"null" - removed
Output schema / properties / shots / items / properties / vessel_name / typeRemoved value: -"null" - removed
Output schema / properties / shots / items / properties / vessel_weight_g / typeRemoved value: -"null" - removed
Output schema / properties / shots / items / properties / water_id / typeRemoved value: -"null"
- Changed
list_waters6 fields changed- removed
Output schema / properties / waters / items / properties / calcium / typeRemoved value: -"null" - removed
Output schema / properties / waters / items / properties / magnesium / typeRemoved value: -"null" - removed
Output schema / properties / waters / items / properties / notes / typeRemoved value: -"null" - removed
Output schema / properties / waters / items / properties / sodium / typeRemoved value: -"null" - removed
Output schema / properties / waters / items / properties / tds / typeRemoved value: -"null" - removed
Output schema / properties / waters / items / properties / type / typeRemoved value: -"null"
- Changed
set_maintenance_offset2 fields changed- removed
Output schema / properties / entry / properties / details / properties / to / properties / components_spec / typeRemoved value: -"null" - removed
Output schema / properties / entry / properties / guide_id / typeRemoved value: -"null"
5 tool updates
- Changed
get_dial_state5 fields changed- added
Output schema / properties / maintenance_summary / properties / most_urgent / properties / soonAdded value: +{ + "type": "boolean" +} - added
Output schema / properties / maintenance_summary / properties / most_urgent / properties / soon_atAdded value: +{ + "type": "null" +} - changed
Output schema / properties / maintenance_summary / properties / most_urgent / requiredPrevious value: -[ - "equipment_kind", - "equipment_id", - "equipment_name", - "task", - "label", - "class", - "state", - "ratio", - "basis", - "every", - "done", - "remaining", - "last_at", - "every_source", - "lower_bound", - "due_at", - "overdue_at", - "muted", - "muted_until" -]New value: +[ + "equipment_kind", + "equipment_id", + "equipment_name", + "task", + "label", + "class", + "state", + "ratio", + "basis", + "every", + "done", + "remaining", + "last_at", + "every_source", + "lower_bound", + "soon", + "soon_at", + "due_at", + "overdue_at", + "muted", + "muted_until" +] - added
Output schema / properties / maintenance_summary / properties / soon_countAdded value: +{ + "type": "integer" +} - changed
Output schema / properties / maintenance_summary / requiredPrevious value: -[ - "computed_at", - "catalog_version", - "most_urgent", - "due_count", - "overdue_count", - "calibration_state" -]New value: +[ + "computed_at", + "catalog_version", + "most_urgent", + "due_count", + "overdue_count", + "soon_count", + "calibration_state" +]
- Changed
list_grinders3 fields changed- added
Output schema / properties / grinders / items / properties / maintenance / properties / due / properties / burr_clean / properties / soonAdded value: +{ + "type": "boolean" +} - added
Output schema / properties / grinders / items / properties / maintenance / properties / due / properties / burr_clean / properties / soon_atAdded value: +{ + "type": [ + "null", + "string" + ] +} - changed
Output schema / properties / grinders / items / properties / maintenance / properties / due / properties / burr_clean / requiredPrevious value: -[ - "state", - "ratio", - "basis", - "every", - "done", - "remaining", - "lower_bound", - "due_at", - "overdue_at", - "last_at", - "every_source", - "muted", - "muted_until" -]New value: +[ + "state", + "ratio", + "basis", + "every", + "done", + "remaining", + "lower_bound", + "soon", + "soon_at", + "due_at", + "overdue_at", + "last_at", + "every_source", + "muted", + "muted_until" +]
- Changed
list_machines3 fields changed- added
Output schema / properties / machines / items / properties / maintenance / properties / due / additionalProperties / properties / soonAdded value: +{ + "type": "boolean" +} - added
Output schema / properties / machines / items / properties / maintenance / properties / due / additionalProperties / properties / soon_atAdded value: +{ + "type": [ + "null", + "string" + ] +} - changed
Output schema / properties / machines / items / properties / maintenance / properties / due / additionalProperties / requiredPrevious value: -[ - "state", - "ratio", - "basis", - "every", - "done", - "remaining", - "lower_bound", - "due_at", - "overdue_at", - "last_at", - "every_source", - "muted", - "muted_until" -]New value: +[ + "state", + "ratio", + "basis", + "every", + "done", + "remaining", + "lower_bound", + "soon", + "soon_at", + "due_at", + "overdue_at", + "last_at", + "every_source", + "muted", + "muted_until" +]
- Changed
list_maintenance_due3 fields changed- added
Output schema / properties / items / items / properties / soonAdded value: +{ + "type": "boolean" +} - added
Output schema / properties / items / items / properties / soon_atAdded value: +{ + "type": [ + "null", + "string" + ] +} - changed
Output schema / properties / items / items / requiredPrevious value: -[ - "equipment_kind", - "equipment_id", - "equipment_name", - "task", - "label", - "class", - "state", - "ratio", - "basis", - "every", - "done", - "remaining", - "last_at", - "every_source", - "lower_bound", - "due_at", - "overdue_at", - "muted", - "muted_until" -]New value: +[ + "equipment_kind", + "equipment_id", + "equipment_name", + "task", + "label", + "class", + "state", + "ratio", + "basis", + "every", + "done", + "remaining", + "last_at", + "every_source", + "lower_bound", + "soon", + "soon_at", + "due_at", + "overdue_at", + "muted", + "muted_until" +]
- Changed
set_maintenance_schedule2 fields changed- added
Output schema / properties / due / properties / soonAdded value: +{ + "type": "boolean" +} - added
Output schema / properties / due / properties / soon_atAdded value: +{ + "type": "string" +}
3 tool updates
- Changed
register_coffee2 fields changed- added
Output schema / properties / activeAdded value: +{ + "type": "boolean" +} - changed
Output schema / requiredPrevious value: -[ - "status", - "bean_id", - "bag_id", - "message" -]New value: +[ + "status", + "bean_id", + "bag_id", + "active", + "message" +]
- Changed
register_grinder2 fields changed- added
Output schema / properties / activeAdded value: +{ + "type": "boolean" +} - changed
Output schema / requiredPrevious value: -[ - "status", - "grinder_id", - "message" -]New value: +[ + "status", + "grinder_id", + "active", + "message" +]
- Changed
register_machine2 fields changed- added
Output schema / properties / activeAdded value: +{ + "type": "boolean" +} - changed
Output schema / requiredPrevious value: -[ - "status", - "machine_id", - "message" -]New value: +[ + "status", + "machine_id", + "active", + "message" +]
12 tool updates
- Changed
get_dial_state7 fields changed- added
Output schema / properties / active_grinder / properties / catalog_idAdded value: +{ + "type": "null" +} - changed
Output schema / properties / active_grinder / requiredPrevious value: -[ - "id", - "name", - "motor_type", - "burr_type", - "setting_scheme", - "direction_convention", - "nominal_step", - "components_spec", - "min_value", - "max_value", - "microns_per_step", - "notes", - "is_active", - "archived", - "photo", - "setting_label", - "setting_components", - "position_value", - "source", - "verified_at", - "built_in_machine_id" -]New value: +[ + "id", + "name", + "motor_type", + "burr_type", + "setting_scheme", + "direction_convention", + "nominal_step", + "components_spec", + "min_value", + "max_value", + "microns_per_step", + "notes", + "is_active", + "archived", + "photo", + "catalog_id", + "setting_label", + "setting_components", + "position_value", + "source", + "verified_at", + "built_in_machine_id" +] - added
Output schema / properties / active_machine / properties / catalog_idAdded value: +{ + "type": "string" +} - added
Output schema / properties / active_machine / properties / hardness_dhAdded value: +{ + "type": "null" +} - changed
Output schema / properties / active_machine / requiredPrevious value: -[ - "id", - "name", - "control_type", - "basket_size_grams", - "boiler_type", - "notes", - "is_active", - "prep_type", - "prep_style", - "archived", - "photo", - "tools", - "connected_device", - "built_in_grinder_id" -]New value: +[ + "id", + "name", + "control_type", + "basket_size_grams", + "boiler_type", + "notes", + "is_active", + "prep_type", + "prep_style", + "archived", + "photo", + "tools", + "connected_device", + "built_in_grinder_id", + "catalog_id", + "hardness_dh" +] - added
Output schema / properties / maintenance_summaryAdded value: +{ + "additionalProperties": true, + "properties": { + "calibration_state": { + "type": "string" + }, + "catalog_version": { + "type": "string" + }, + "computed_at": { + "type": "string" + }, + "due_count": { + "type": "integer" + }, + "most_urgent": { + "additionalProperties": true, + "properties": { + "basis": { + "type": "string" + }, + "class": { + "type": "string" + }, + "done": { + "type": "integer" + }, + "due_at": { + "type": "null" + }, + "equipment_id": { + "type": "integer" + }, + "equipment_kind": { + "type": "string" + }, + "equipment_name": { + "type": "string" + }, + "every": { + "type": "integer" + }, + "every_source": { + "type": "string" + }, + "label": { + "type": "string" + }, + "last_at": { + "type": "null" + }, + "lower_bound": { + "type": "boolean" + }, + "muted": { + "type": "boolean" + }, + "muted_until": { + "type": "null" + }, + "overdue_at": { + "type": "null" + }, + "ratio": { + "type": "number" + }, + "remaining": { + "type": "integer" + }, + "state": { + "type": "string" + }, + "task": { + "type": "string" + } + }, + "required": [ + "equipment_kind", + "equipment_id", + "equipment_name", + "task", + "label", + "class", + "state", + "ratio", + "basis", + "every", + "done", + "remaining", + "last_at", + "every_source", + "lower_bound", + "due_at", + "overdue_at", + "muted", + "muted_until" + ], + "type": "object" + }, + "overdue_count": { + "type": "integer" + } + }, + "required": [ + "computed_at", + "catalog_version", + "most_urgent", + "due_count", + "overdue_count", + "calibration_state" + ], + "type": "object" +} - changed
Output schema / requiredPrevious value: -[ - "active_coffee", - "active_grinder", - "active_machine", - "active_program", - "recent_shots", - "recent_recommendations", - "locked_recipe" -]New value: +[ + "active_coffee", + "active_grinder", + "active_machine", + "active_program", + "recent_shots", + "recent_recommendations", + "locked_recipe", + "maintenance_summary" +]
- Added
get_maintenance_guides - Changed
list_grinders45 fields changed- added
Input schema / properties / maintenanceAdded value: +{ + "description": "How much of each row's maintenance block to include. compact (default): every task with its class, due state, schedule and guide. full: also the maker's own words — quote, source, alternates, the interval as written.", + "enum": [ + "compact", + "full" + ], + "type": "string" +} - changed
Output schema / properties / grinders / items / properties / built_in_machine_id / typePrevious value: -"null"New value: +[ + "integer", + "null" +] - added
Output schema / properties / grinders / items / properties / catalog_idAdded value: +{ + "type": [ + "null", + "string" + ] +} - changed
Output schema / properties / grinders / items / properties / maintenance / properties / calibration / properties / disturbs_note / typePrevious value: -[ - "string", - "null" -]New value: +[ + "null", + "string" +] - changed
Output schema / properties / grinders / items / properties / maintenance / properties / calibration / properties / epoch_at / typePrevious value: -[ - "string", - "null" -]New value: +[ + "null", + "string" +] - changed
Output schema / properties / grinders / items / properties / maintenance / properties / calibration / properties / epoch_id / typePrevious value: -[ - "integer", - "null" -]New value: +[ + "null", + "integer" +] - changed
Output schema / properties / grinders / items / properties / maintenance / properties / calibration / properties / epoch_task / typePrevious value: -[ - "string", - "null" -]New value: +[ + "null", + "string" +] - changed
Output schema / properties / grinders / items / properties / maintenance / properties / calibration / properties / offset_at / typePrevious value: -[ - "string", - "null" -]New value: +[ + "null", + "string" +] - changed
Output schema / properties / grinders / items / properties / maintenance / properties / calibration / properties / offset_source / typePrevious value: -[ - "string", - "null" -]New value: +[ + "null", + "string" +] - changed
Output schema / properties / grinders / items / properties / maintenance / properties / calibration / properties / offset_value / typePrevious value: -[ - "integer", - "null" -]New value: +[ + "null", + "integer" +] - added
Output schema / properties / grinders / items / properties / maintenance / properties / catalogAdded value: +{ + "additionalProperties": true, + "properties": { + "brand": { + "type": [ + "string", + "null" + ] + }, + "declined": { + "type": "boolean" + }, + "id": { + "type": [ + "string", + "null" + ] + }, + "match": { + "additionalProperties": true, + "properties": { + "brand": { + "type": "string" + }, + "by": { + "type": "string" + }, + "id": { + "type": "string" + }, + "model": { + "type": "string" + } + }, + "required": [], + "type": [ + "null", + "object" + ] + }, + "model": { + "type": [ + "string", + "null" + ] + }, + "via": { + "type": [ + "string", + "null" + ] + } + }, + "required": [ + "id", + "brand", + "model", + "via", + "match", + "declined" + ], + "type": "object" +} - added
Output schema / properties / grinders / items / properties / maintenance / properties / catalog_versionAdded value: +{ + "type": "string" +} - added
Output schema / properties / grinders / items / properties / maintenance / properties / computed_atAdded value: +{ + "type": "string" +} - changed
Output schema / properties / grinders / items / properties / maintenance / properties / due / properties / burr_clean / properties / basis / typePrevious value: -[ - "string", - "null" -]New value: +[ + "null", + "string" +] - changed
Output schema / properties / grinders / items / properties / maintenance / properties / due / properties / burr_clean / properties / done / typePrevious value: -[ - "integer", - "null" -]New value: +[ + "null", + "integer" +] - added
Output schema / properties / grinders / items / properties / maintenance / properties / due / properties / burr_clean / properties / due_atAdded value: +{ + "type": [ + "null", + "string" + ] +} - changed
Output schema / properties / grinders / items / properties / maintenance / properties / due / properties / burr_clean / properties / every / typePrevious value: -[ - "integer", - "null" -]New value: +[ + "null", + "integer" +] - added
Output schema / properties / grinders / items / properties / maintenance / properties / due / properties / burr_clean / properties / every_sourceAdded value: +{ + "type": [ + "null", + "string" + ] +} - added
Output schema / properties / grinders / items / properties / maintenance / properties / due / properties / burr_clean / properties / lower_boundAdded value: +{ + "type": "boolean" +} - added
Output schema / properties / grinders / items / properties / maintenance / properties / due / properties / burr_clean / properties / mutedAdded value: +{ + "type": "boolean" +} - added
Output schema / properties / grinders / items / properties / maintenance / properties / due / properties / burr_clean / properties / muted_untilAdded value: +{ + "type": "null" +} - added
Output schema / properties / grinders / items / properties / maintenance / properties / due / properties / burr_clean / properties / overdue_atAdded value: +{ + "type": [ + "null", + "string" + ] +} - changed
Output schema / properties / grinders / items / properties / maintenance / properties / due / properties / burr_clean / properties / ratio / typePrevious value: -[ - "number", - "integer" -]New value: +[ + "integer", + "number" +] - changed
Output schema / properties / grinders / items / properties / maintenance / properties / due / properties / burr_clean / properties / remaining / typePrevious value: -[ - "integer", - "null" -]New value: +[ + "null", + "integer" +] - changed
Output schema / properties / grinders / items / properties / maintenance / properties / due / properties / burr_clean / requiredPrevious value: -[ - "state", - "ratio", - "basis", - "every", - "done", - "remaining", - "last_at" -]New value: +[ + "state", + "ratio", + "basis", + "every", + "done", + "remaining", + "lower_bound", + "due_at", + "overdue_at", + "last_at", + "every_source", + "muted", + "muted_until" +] - added
Output schema / properties / grinders / items / properties / maintenance / properties / entries / items / properties / guide_idAdded value: +{ + "type": "null" +} - added
Output schema / properties / grinders / items / properties / maintenance / properties / entries / items / properties / task_labelAdded value: +{ + "type": "string" +} - changed
Output schema / properties / grinders / items / properties / maintenance / properties / entries / items / requiredPrevious value: -[ - "id", - "equipment_kind", - "equipment_id", - "task", - "performed_at", - "disturbs_zero", - "note", - "offset_value", - "offset_source", - "offset_at", - "evidence", - "details", - "details_version", - "created_at", - "details_known" -]New value: +[ + "id", + "equipment_kind", + "equipment_id", + "task", + "performed_at", + "disturbs_zero", + "note", + "offset_value", + "offset_source", + "offset_at", + "evidence", + "details", + "details_version", + "created_at", + "guide_id", + "details_known", + "task_label" +] - added
Output schema / properties / grinders / items / properties / maintenance / properties / entries_totalAdded value: +{ + "type": "integer" +} - added
Output schema / properties / grinders / items / properties / maintenance / properties / hardnessAdded value: +{ + "type": "null" +} - added
Output schema / properties / grinders / items / properties / maintenance / properties / tasks / items / properties / classAdded value: +{ + "type": "string" +} - added
Output schema / properties / grinders / items / properties / maintenance / properties / tasks / items / properties / details_fields / itemsAdded value: +{ + "additionalProperties": true, + "properties": { + "hint": { + "type": "string" + }, + "key": { + "type": "string" + }, + "label": { + "type": "string" + }, + "required": { + "type": "boolean" + }, + "type": { + "type": "string" + } + }, + "required": [ + "key", + "type", + "label", + "hint", + "required" + ], + "type": "object" +} - added
Output schema / properties / grinders / items / properties / maintenance / properties / tasks / items / properties / disturbs_promptAdded value: +{ + "type": [ + "null", + "string" + ] +} - changed
Output schema / properties / grinders / items / properties / maintenance / properties / tasks / items / properties / every / typePrevious value: -[ - "object", - "null" -]New value: +[ + "null", + "object" +] - added
Output schema / properties / grinders / items / properties / maintenance / properties / tasks / items / properties / every_sourceAdded value: +{ + "additionalProperties": true, + "properties": { + "days": { + "type": "string" + }, + "grams": { + "type": "string" + }, + "shots": { + "type": "string" + } + }, + "required": [], + "type": [ + "null", + "object" + ] +} - added
Output schema / properties / grinders / items / properties / maintenance / properties / tasks / items / properties / guideAdded value: +{ + "additionalProperties": true, + "properties": { + "also_covers": { + "type": "null" + }, + "basis": { + "type": "string" + }, + "duration_minutes": { + "type": "null" + }, + "duration_note": { + "type": "null" + }, + "id": { + "type": "string" + }, + "machine_alert": { + "type": "null" + }, + "market": { + "type": "null" + }, + "scope": { + "type": "string" + }, + "steps": { + "type": "integer" + }, + "title": { + "type": "string" + }, + "variant": { + "type": "string" + }, + "warnings": { + "type": "integer" + } + }, + "required": [], + "type": [ + "object", + "null" + ] +} - added
Output schema / properties / grinders / items / properties / maintenance / properties / tasks / items / properties / scheduleAdded value: +{ + "additionalProperties": true, + "properties": { + "enabled": { + "type": "boolean" + }, + "every": { + "type": "null" + }, + "muted_until": { + "type": "null" + } + }, + "required": [], + "type": [ + "null", + "object" + ] +} - added
Output schema / properties / grinders / items / properties / maintenance / properties / tasks / items / properties / statusAdded value: +{ + "type": [ + "string", + "null" + ] +} - added
Output schema / properties / grinders / items / properties / maintenance / properties / tasks / items / properties / triggerAdded value: +{ + "type": [ + "string", + "null" + ] +} - changed
Output schema / properties / grinders / items / properties / maintenance / properties / tasks / items / requiredPrevious value: -[ - "value", - "kind", - "label", - "sub", - "disturbs_zero", - "every", - "why", - "disturbs_note", - "offset_unit", - "offset_integral", - "scheduled", - "opened_by", - "details_version", - "details_fields" -]New value: +[ + "value", + "kind", + "label", + "sub", + "disturbs_zero", + "every", + "why", + "disturbs_note", + "offset_unit", + "offset_integral", + "scheduled", + "opened_by", + "details_version", + "details_fields", + "class", + "status", + "trigger", + "every_source", + "disturbs_prompt", + "guide", + "schedule" +] - changed
Output schema / properties / grinders / items / properties / maintenance / requiredPrevious value: -[ - "tasks", - "due", - "calibration", - "sensitivity", - "entries" -]New value: +[ + "tasks", + "due", + "calibration", + "sensitivity", + "entries", + "entries_total", + "catalog_version", + "computed_at", + "catalog", + "hardness" +] - changed
Output schema / properties / grinders / items / properties / microns_per_step / typePrevious value: -[ - "integer", - "null" -]New value: +[ + "null", + "integer" +] - changed
Output schema / properties / grinders / items / properties / nominal_step / typePrevious value: -[ - "number", - "integer" -]New value: +[ + "integer", + "number" +] - changed
Output schema / properties / grinders / items / properties / notes / typePrevious value: -[ - "string", - "null" -]New value: +[ + "null", + "string" +] - changed
Output schema / properties / grinders / items / requiredPrevious value: -[ - "id", - "name", - "motor_type", - "burr_type", - "setting_scheme", - "direction_convention", - "nominal_step", - "components_spec", - "min_value", - "max_value", - "microns_per_step", - "notes", - "archived", - "setting_label", - "setting_components", - "position_value", - "source", - "verified_at", - "built_in_machine_id", - "maintenance" -]New value: +[ + "id", + "name", + "motor_type", + "burr_type", + "setting_scheme", + "direction_convention", + "nominal_step", + "components_spec", + "min_value", + "max_value", + "microns_per_step", + "notes", + "archived", + "catalog_id", + "setting_label", + "setting_components", + "position_value", + "source", + "verified_at", + "built_in_machine_id", + "maintenance" +]
- Changed
list_machines6 fields changed- added
Input schema / properties / maintenanceAdded value: +{ + "description": "How much of each row's maintenance block to include. compact (default): every task with its class, due state, schedule and guide. full: also the maker's own words — quote, source, alternates, the interval as written.", + "enum": [ + "compact", + "full" + ], + "type": "string" +} - changed
Output schema / properties / machines / items / properties / built_in_grinder_id / typePrevious value: -"null"New value: +[ + "null", + "integer" +] - added
Output schema / properties / machines / items / properties / catalog_idAdded value: +{ + "type": [ + "null", + "string" + ] +} - added
Output schema / properties / machines / items / properties / hardness_dhAdded value: +{ + "type": [ + "null", + "number" + ] +} - added
Output schema / properties / machines / items / properties / maintenanceAdded value: +{ + "additionalProperties": true, + "properties": { + "calibration": { + "additionalProperties": true, + "properties": { + "disturbs_note": { + "type": "null" + }, + "epoch_at": { + "type": "null" + }, + "epoch_id": { + "type": "null" + }, + "epoch_task": { + "type": "null" + }, + "evidence": { + "type": "null" + }, + "offset_at": { + "type": "null" + }, + "offset_source": { + "type": "null" + }, + "offset_unit": { + "type": "null" + }, + "offset_value": { + "type": "null" + }, + "reference_recipe_id": { + "type": "null" + }, + "stale_recipe_count": { + "type": "integer" + }, + "state": { + "type": "string" + }, + "untranslatable_recipe_count": { + "type": "integer" + } + }, + "required": [ + "stale_recipe_count", + "untranslatable_recipe_count", + "reference_recipe_id", + "state", + "epoch_id", + "epoch_task", + "disturbs_note", + "epoch_at", + "offset_value", + "offset_unit", + "offset_source", + "offset_at", + "evidence" + ], + "type": "object" + }, + "catalog": { + "additionalProperties": true, + "properties": { + "brand": { + "type": [ + "null", + "string" + ] + }, + "declined": { + "type": "boolean" + }, + "id": { + "type": [ + "null", + "string" + ] + }, + "match": { + "type": "null" + }, + "model": { + "type": [ + "null", + "string" + ] + }, + "via": { + "type": "null" + } + }, + "required": [ + "id", + "brand", + "model", + "via", + "match", + "declined" + ], + "type": "object" + }, + "catalog_version": { + "type": "string" + }, + "computed_at": { + "type": "string" + }, + "due": { + "additionalProperties": { + "additionalProperties": true, + "properties": { + "basis": { + "type": [ + "null", + "string" + ] + }, + "done": { + "type": [ + "null", + "integer" + ] + }, + "due_at": { + "type": [ + "null", + "string" + ] + }, + "every": { + "type": [ + "null", + "integer" + ] + }, + "every_source": { + "type": [ + "null", + "string" + ] + }, + "last_at": { + "type": [ + "null", + "string" + ] + }, + "lower_bound": { + "type": "boolean" + }, + "muted": { + "type": "boolean" + }, + "muted_until": { + "type": [ + "null", + "string" + ] + }, + "overdue_at": { + "type": [ + "null", + "string" + ] + }, + "ratio": { + "type": [ + "integer", + "number" + ] + }, + "remaining": { + "type": [ + "null", + "integer" + ] + }, + "state": { + "type": "string" + } + }, + "required": [ + "state", + "ratio", + "basis", + "every", + "done", + "remaining", + "lower_bound", + "due_at", + "overdue_at", + "last_at", + "every_source", + "muted", + "muted_until" + ], + "type": "object" + }, + "properties": [], + "required": [], + "type": [ + "null", + "object" + ] + }, + "entries": { + "items": { + "additionalProperties": true, + "properties": { + "created_at": { + "type": "string" + }, + "details": { + "additionalProperties": true, + "properties": { + "filter_id": { + "type": "string" + }, + "label": { + "type": "string" + }, + "product": { + "type": "string" + } + }, + "required": [], + "type": "object" + }, + "details_known": { + "type": "boolean" + }, + "details_version": { + "type": "integer" + }, + "disturbs_zero": { + "type": "integer" + }, + "equipment_id": { + "type": "integer" + }, + "equipment_kind": { + "type": "string" + }, + "evidence": { + "type": "null" + }, + "guide_id": { + "type": [ + "null", + "string" + ] + }, + "id": { + "type": "integer" + }, + "note": { + "type": "null" + }, + "offset_at": { + "type": "null" + }, + "offset_source": { + "type": "null" + }, + "offset_value": { + "type": "null" + }, + "performed_at": { + "type": "string" + }, + "task": { + "type": "string" + }, + "task_label": { + "type": "string" + } + }, + "required": [ + "id", + "equipment_kind", + "equipment_id", + "task", + "performed_at", + "disturbs_zero", + "note", + "offset_value", + "offset_source", + "offset_at", + "evidence", + "details", + "details_version", + "created_at", + "guide_id", + "details_known", + "task_label" + ], + "type": "object" + }, + "type": "array" + }, + "entries_total": { + "type": "integer" + }, + "hardness": { + "additionalProperties": true, + "properties": { + "dh": { + "type": [ + "null", + "number" + ] + }, + "dkh": { + "type": [ + "null", + "number" + ] + }, + "dkh_source": { + "type": [ + "null", + "string" + ] + }, + "source": { + "type": [ + "null", + "string" + ] + } + }, + "required": [ + "dh", + "dkh", + "source", + "dkh_source" + ], + "type": "object" + }, + "sensitivity": { + "type": "null" + }, + "tasks": { + "items": { + "additionalProperties": true, + "properties": { + "class": { + "type": "string" + }, + "details_fields": { + "items": { + "additionalProperties": true, + "properties": { + "hint": { + "type": [ + "string", + "null" + ] + }, + "key": { + "type": "string" + }, + "label": { + "type": "string" + }, + "options": { + "items": { + "additionalProperties": true, + "properties": { + "id": { + "type": "string" + }, + "label": { + "type": "string" + } + }, + "required": [ + "id", + "label" + ], + "type": "object" + }, + "type": "array" + }, + "required": { + "type": "boolean" + }, + "source": { + "type": "string" + }, + "type": { + "type": "string" + } + }, + "required": [ + "key", + "type", + "label", + "hint", + "required" + ], + "type": "object" + }, + "type": "array" + }, + "details_version": { + "type": "integer" + }, + "disturbs_note": { + "type": "string" + }, + "disturbs_prompt": { + "type": "null" + }, + "disturbs_zero": { + "type": "boolean" + }, + "every": { + "additionalProperties": true, + "properties": { + "days": { + "type": "integer" + }, + "litres": { + "type": [ + "integer", + "number" + ] + }, + "shots": { + "type": "integer" + } + }, + "required": [], + "type": [ + "null", + "object" + ] + }, + "every_source": { + "additionalProperties": true, + "properties": { + "days": { + "type": "string" + }, + "litres": { + "type": "string" + }, + "shots": { + "type": "string" + } + }, + "required": [], + "type": [ + "null", + "object" + ] + }, + "guide": { + "additionalProperties": true, + "properties": { + "also_covers": { + "type": "null" + }, + "basis": { + "type": "string" + }, + "duration_minutes": { + "type": [ + "integer", + "null" + ] + }, + "duration_note": { + "type": "null" + }, + "id": { + "type": "string" + }, + "machine_alert": { + "additionalProperties": true, + "properties": { + "can_disable": { + "type": "null" + }, + "clears": { + "type": [ + "null", + "string" + ] + }, + "counts": { + "type": "string" + }, + "depends_on_setting": { + "type": "null" + }, + "indicator": { + "type": "string" + }, + "shown_as": { + "type": "string" + }, + "source": { + "type": "string" + }, + "threshold": { + "type": "null" + } + }, + "required": [], + "type": [ + "object", + "null" + ] + }, + "market": { + "type": "null" + }, + "scope": { + "type": "string" + }, + "steps": { + "type": "integer" + }, + "title": { + "type": "string" + }, + "variant": { + "type": "null" + }, + "warnings": { + "type": "integer" + } + }, + "required": [], + "type": [ + "null", + "object" + ] + }, + "kind": { + "type": "string" + }, + "label": { + "type": "string" + }, + "offset_integral": { + "type": "boolean" + }, + "offset_unit": { + "type": "string" + }, + "opened_by": { + "type": "null" + }, + "schedule": { + "additionalProperties": true, + "properties": { + "enabled": { + "type": "boolean" + }, + "every": { + "additionalProperties": true, + "properties": { + "days": { + "type": "integer" + }, + "litres": { + "type": "number" + } + }, + "required": [ + "days", + "litres" + ], + "type": "object" + }, + "muted_until": { + "type": "string" + } + }, + "required": [], + "type": [ + "null", + "object" + ] + }, + "scheduled": { + "type": "boolean" + }, + "status": { + "type": [ + "null", + "string" + ] + }, + "sub": { + "type": "string" + }, + "trigger": { + "type": [ + "null", + "string" + ] + }, + "value": { + "type": "string" + }, + "why": { + "type": "string" + } + }, + "required": [ + "value", + "kind", + "label", + "sub", + "disturbs_zero", + "every", + "why", + "disturbs_note", + "offset_unit", + "offset_integral", + "scheduled", + "opened_by", + "details_version", + "details_fields", + "class", + "status", + "trigger", + "every_source", + "disturbs_prompt", + "guide", + "schedule" + ], + "type": "object" + }, + "type": "array" + } + }, + "required": [ + "tasks", + "due", + "calibration", + "sensitivity", + "entries", + "entries_total", + "catalog_version", + "computed_at", + "catalog", + "hardness" + ], + "type": "object" +} - changed
Output schema / properties / machines / items / requiredPrevious value: -[ - "id", - "name", - "control_type", - "basket_size_grams", - "boiler_type", - "notes", - "prep_type", - "prep_style", - "archived", - "built_in_grinder_id", - "tools_list", - "programs" -]New value: +[ + "id", + "name", + "control_type", + "basket_size_grams", + "boiler_type", + "notes", + "prep_type", + "prep_style", + "archived", + "built_in_grinder_id", + "catalog_id", + "hardness_dh", + "tools_list", + "programs", + "maintenance" +]
- Added
list_maintenance_due - Changed
log_maintenance12 fields changed- changed
Input schema / properties / details / descriptionPrevious value: -"Fields specific to this task. Which ones a task takes is published as details_fields in the task catalog on list_grinders; a burr clean takes none"New value: +"Fields specific to this task. Which ones a task takes is published as details_fields on each task; a burr clean takes none" - changed
Input schema / properties / equipment_kind / enumPrevious value: -[ - "grinder" -]New value: +[ + "grinder", + "machine" +] - added
Input schema / properties / guide_idAdded value: +{ + "description": "Optional — the id of the maintenance guide that was followed. Must be a guide for this task", + "type": "string" +} - changed
Input schema / properties / task / enumPrevious value: -[ - "burr_clean" -]New value: +[ + "burr_clean", + "backflush_water", + "backflush_detergent", + "descale", + "group_gasket_replace", + "shower_screen_clean", + "shower_screen_replace", + "group_head_wipe", + "basket_portafilter_soak", + "steam_wand_purge", + "steam_wand_soak", + "drip_tray_clean", + "water_tank_clean", + "water_filter_replace", + "boiler_water_change", + "lever_piston_seal_replace", + "lever_lubricate", + "milk_system_clean", + "professional_service", + "builtin_grinder_burr_clean", + "builtin_grinder_burr_replace", + "grinder_quick_clean", + "grinder_cleaning_tablets", + "burr_replace", + "hopper_clean", + "grounds_cup_clean", + "bearing_lubricate", + "gasket_seal_replace", + "idle_rinse", + "water_wash", + "dishwasher", + "filter_prime", + "softener_regenerate", + "other" +] - added
Output schema / properties / dedupedAdded value: +{ + "type": "boolean" +} - added
Output schema / properties / entry / properties / details / additionalPropertiesAdded value: +true - added
Output schema / properties / entry / properties / details / propertiesAdded value: +{ + "filter_id": { + "type": "string" + }, + "label": { + "type": "string" + }, + "product": { + "type": "string" + } +} - added
Output schema / properties / entry / properties / details / requiredAdded value: +[] - changed
Output schema / properties / entry / properties / details / typePrevious value: -"null"New value: +[ + "null", + "object" +] - added
Output schema / properties / entry / properties / guide_idAdded value: +{ + "type": [ + "null", + "string" + ] +} - changed
Output schema / properties / entry / requiredPrevious value: -[ - "id", - "equipment_kind", - "equipment_id", - "task", - "performed_at", - "disturbs_zero", - "note", - "offset_value", - "offset_source", - "offset_at", - "evidence", - "details", - "details_version", - "created_at", - "details_known" -]New value: +[ + "id", + "equipment_kind", + "equipment_id", + "task", + "performed_at", + "disturbs_zero", + "note", + "offset_value", + "offset_source", + "offset_at", + "evidence", + "details", + "details_version", + "created_at", + "guide_id", + "details_known" +] - changed
Output schema / requiredPrevious value: -[ - "entry_id", - "entry", - "message" -]New value: +[ + "entry_id", + "entry", + "deduped", + "message" +]
- Changed
register_grinder1 field changed- added
Input schema / properties / catalog_idAdded value: +{ + "description": "Optional — the maintenance catalog model this is (the `id` of a catalog row, e.g. rancilio-silvia), when it was registered from the catalog. Its maintenance then comes from that model's researched record. \"none\" says it is not in the catalog.", + "type": "string" +}
- Changed
register_machine2 fields changed- added
Input schema / properties / catalog_idAdded value: +{ + "description": "Optional — the maintenance catalog model this is (the `id` of a catalog row, e.g. rancilio-silvia), when it was registered from the catalog. Its maintenance then comes from that model's researched record. \"none\" says it is not in the catalog.", + "type": "string" +} - added
Input schema / properties / hardness_dhAdded value: +{ + "description": "Optional — the TOTAL hardness (GH) of the water this machine runs on, in °dH (German degrees; ppm as CaCO3 ÷ 17.85), as a test strip reports it. Picks the band of a maker's hardness table for descaling and filter life", + "type": [ + "number", + "null" + ] +}
- Changed
set_maintenance_offset2 fields changed- added
Output schema / properties / entry / properties / guide_idAdded value: +{ + "type": "null" +} - changed
Output schema / properties / entry / requiredPrevious value: -[ - "id", - "equipment_kind", - "equipment_id", - "task", - "performed_at", - "disturbs_zero", - "note", - "offset_value", - "offset_source", - "offset_at", - "evidence", - "details", - "details_version", - "created_at", - "details_known" -]New value: +[ + "id", + "equipment_kind", + "equipment_id", + "task", + "performed_at", + "disturbs_zero", + "note", + "offset_value", + "offset_source", + "offset_at", + "evidence", + "details", + "details_version", + "created_at", + "guide_id", + "details_known" +]
- Added
set_maintenance_schedule - Changed
update_grinder1 field changed- added
Input schema / properties / fields / properties / catalog_idAdded value: +{ + "description": "The maintenance catalog model this grinder is; \"none\" if it is not listed; null to unbind. list_grinders proposes one from the name under maintenance.catalog.match", + "type": [ + "string", + "null" + ] +}
- Changed
update_machine2 fields changed- added
Input schema / properties / fields / properties / catalog_idAdded value: +{ + "description": "The maintenance catalog model this machine is; \"none\" if it is not listed; null to unbind. list_machines proposes one from the name under maintenance.catalog.match", + "type": [ + "string", + "null" + ] +} - added
Input schema / properties / fields / properties / hardness_dhAdded value: +{ + "description": "The total hardness (GH) of the water this machine runs on, in °dH; null to fall back to the water of its last shot", + "type": [ + "number", + "null" + ] +}
10 tool updates
- Changed
list_grinders33 fields changed- added
Output schema / properties / grinders / items / properties / maintenance / properties / calibration / properties / disturbs_noteAdded value: +{ + "type": [ + "string", + "null" + ] +} - changed
Output schema / properties / grinders / items / properties / maintenance / properties / calibration / properties / epoch_at / typePrevious value: -[ - "null", - "string" -]New value: +[ + "string", + "null" +] - changed
Output schema / properties / grinders / items / properties / maintenance / properties / calibration / properties / epoch_id / typePrevious value: -[ - "null", - "integer" -]New value: +[ + "integer", + "null" +] - added
Output schema / properties / grinders / items / properties / maintenance / properties / calibration / properties / epoch_taskAdded value: +{ + "type": [ + "string", + "null" + ] +} - changed
Output schema / properties / grinders / items / properties / maintenance / properties / calibration / properties / offset_at / typePrevious value: -[ - "null", - "string" -]New value: +[ + "string", + "null" +] - changed
Output schema / properties / grinders / items / properties / maintenance / properties / calibration / properties / offset_source / typePrevious value: -[ - "null", - "string" -]New value: +[ + "string", + "null" +] - changed
Output schema / properties / grinders / items / properties / maintenance / properties / calibration / properties / offset_value / typePrevious value: -[ - "null", - "integer" -]New value: +[ + "integer", + "null" +] - added
Output schema / properties / grinders / items / properties / maintenance / properties / calibration / properties / untranslatable_recipe_countAdded value: +{ + "type": "integer" +} - changed
Output schema / properties / grinders / items / properties / maintenance / properties / calibration / requiredPrevious value: -[ - "stale_recipe_count", - "reference_recipe_id", - "state", - "epoch_id", - "epoch_at", - "offset_value", - "offset_unit", - "offset_source", - "offset_at", - "evidence" -]New value: +[ + "stale_recipe_count", + "untranslatable_recipe_count", + "reference_recipe_id", + "state", + "epoch_id", + "epoch_task", + "disturbs_note", + "epoch_at", + "offset_value", + "offset_unit", + "offset_source", + "offset_at", + "evidence" +] - changed
Output schema / properties / grinders / items / properties / maintenance / properties / due / properties / burr_clean / properties / basis / typePrevious value: -[ - "null", - "string" -]New value: +[ + "string", + "null" +] - changed
Output schema / properties / grinders / items / properties / maintenance / properties / due / properties / burr_clean / properties / done / typePrevious value: -[ - "null", - "integer" -]New value: +[ + "integer", + "null" +] - changed
Output schema / properties / grinders / items / properties / maintenance / properties / due / properties / burr_clean / properties / every / typePrevious value: -[ - "null", - "integer" -]New value: +[ + "integer", + "null" +] - changed
Output schema / properties / grinders / items / properties / maintenance / properties / due / properties / burr_clean / properties / ratio / typePrevious value: -"integer"New value: +[ + "number", + "integer" +] - changed
Output schema / properties / grinders / items / properties / maintenance / properties / due / properties / burr_clean / properties / remaining / typePrevious value: -[ - "null", - "integer" -]New value: +[ + "integer", + "null" +] - added
Output schema / properties / grinders / items / properties / maintenance / properties / entries / items / properties / details / additionalPropertiesAdded value: +true - added
Output schema / properties / grinders / items / properties / maintenance / properties / entries / items / properties / details / propertiesAdded value: +{ + "from": { + "additionalProperties": true, + "properties": { + "components_spec": { + "type": [ + "null", + "string" + ] + }, + "nominal_step": { + "type": [ + "number", + "integer" + ] + }, + "setting_scheme": { + "type": "string" + } + }, + "required": [ + "setting_scheme", + "nominal_step", + "components_spec" + ], + "type": "object" + }, + "to": { + "additionalProperties": true, + "properties": { + "components_spec": { + "type": [ + "null", + "string" + ] + }, + "nominal_step": { + "type": [ + "number", + "integer" + ] + }, + "setting_scheme": { + "type": "string" + } + }, + "required": [ + "setting_scheme", + "nominal_step", + "components_spec" + ], + "type": "object" + } +} - added
Output schema / properties / grinders / items / properties / maintenance / properties / entries / items / properties / details / requiredAdded value: +[] - changed
Output schema / properties / grinders / items / properties / maintenance / properties / entries / items / properties / details / typePrevious value: -"null"New value: +[ + "object", + "null" +] - changed
Output schema / properties / grinders / items / properties / maintenance / properties / entries / items / properties / evidence / typePrevious value: -[ - "string", - "null" -]New value: +[ + "null", + "string" +] - changed
Output schema / properties / grinders / items / properties / maintenance / properties / entries / items / properties / note / typePrevious value: -[ - "null", - "string" -]New value: +[ + "string", + "null" +] - changed
Output schema / properties / grinders / items / properties / maintenance / properties / entries / items / properties / offset_at / typePrevious value: -[ - "string", - "null" -]New value: +[ + "null", + "string" +] - changed
Output schema / properties / grinders / items / properties / maintenance / properties / entries / items / properties / offset_source / typePrevious value: -[ - "string", - "null" -]New value: +[ + "null", + "string" +] - changed
Output schema / properties / grinders / items / properties / maintenance / properties / entries / items / properties / offset_value / typePrevious value: -[ - "integer", - "null" -]New value: +[ + "null", + "integer" +] - changed
Output schema / properties / grinders / items / properties / maintenance / properties / tasks / items / properties / every / requiredPrevious value: -[ - "days", - "shots", - "grams" -]New value: +[] - changed
Output schema / properties / grinders / items / properties / maintenance / properties / tasks / items / properties / every / typePrevious value: -"object"New value: +[ + "object", + "null" +] - added
Output schema / properties / grinders / items / properties / maintenance / properties / tasks / items / properties / opened_byAdded value: +{ + "type": [ + "null", + "string" + ] +} - added
Output schema / properties / grinders / items / properties / maintenance / properties / tasks / items / properties / scheduledAdded value: +{ + "type": "boolean" +} - changed
Output schema / properties / grinders / items / properties / maintenance / properties / tasks / items / requiredPrevious value: -[ - "value", - "kind", - "label", - "sub", - "disturbs_zero", - "every", - "why", - "disturbs_note", - "offset_unit", - "offset_integral", - "details_version", - "details_fields" -]New value: +[ + "value", + "kind", + "label", + "sub", + "disturbs_zero", + "every", + "why", + "disturbs_note", + "offset_unit", + "offset_integral", + "scheduled", + "opened_by", + "details_version", + "details_fields" +] - changed
Output schema / properties / grinders / items / properties / max_value / typePrevious value: -[ - "integer", - "null" -]New value: +[ + "null", + "integer" +] - changed
Output schema / properties / grinders / items / properties / microns_per_step / typePrevious value: -[ - "null", - "integer" -]New value: +[ + "integer", + "null" +] - changed
Output schema / properties / grinders / items / properties / min_value / typePrevious value: -[ - "integer", - "null" -]New value: +[ + "null", + "integer" +] - changed
Output schema / properties / grinders / items / properties / nominal_step / typePrevious value: -"integer"New value: +[ + "number", + "integer" +] - changed
Output schema / properties / grinders / items / properties / notes / typePrevious value: -"null"New value: +[ + "string", + "null" +]
- Changed
list_machines2 fields changed- changed
Output schema / properties / machines / items / properties / notes / typePrevious value: -"null"New value: +[ + "string", + "null" +] - added
Output schema / properties / machines / items / properties / tools_list / itemsAdded value: +{ + "type": "string" +}
- Changed
list_recipes2 fields changed- added
Output schema / properties / recipes / items / properties / grind_reading / properties / epoch_tasksAdded value: +{ + "items": { + "type": "string" + }, + "type": "array" +} - added
Output schema / properties / recipes / items / properties / grind_reading / properties / untranslatableAdded value: +{ + "type": "boolean" +}
- Changed
list_shots1 field changed- changed
Output schema / properties / shots / items / properties / flavor_notes / typePrevious value: -"string"New value: +[ + "string", + "null" +]
- Changed
log_maintenance2 fields changed- added
Output schema / properties / entry / properties / details_knownAdded value: +{ + "type": "boolean" +} - changed
Output schema / properties / entry / requiredPrevious value: -[ - "id", - "equipment_kind", - "equipment_id", - "task", - "performed_at", - "disturbs_zero", - "note", - "offset_value", - "offset_source", - "offset_at", - "evidence", - "details", - "details_version", - "created_at" -]New value: +[ + "id", + "equipment_kind", + "equipment_id", + "task", + "performed_at", + "disturbs_zero", + "note", + "offset_value", + "offset_source", + "offset_at", + "evidence", + "details", + "details_version", + "created_at", + "details_known" +]
- Changed
set_maintenance_offset7 fields changed- added
Output schema / properties / entry / properties / details / additionalPropertiesAdded value: +true - added
Output schema / properties / entry / properties / details / propertiesAdded value: +{ + "from": { + "additionalProperties": true, + "properties": { + "components_spec": { + "type": "string" + }, + "nominal_step": { + "type": "integer" + }, + "setting_scheme": { + "type": "string" + } + }, + "required": [ + "setting_scheme", + "nominal_step", + "components_spec" + ], + "type": "object" + }, + "to": { + "additionalProperties": true, + "properties": { + "components_spec": { + "type": "null" + }, + "nominal_step": { + "type": "number" + }, + "setting_scheme": { + "type": "string" + } + }, + "required": [ + "setting_scheme", + "nominal_step", + "components_spec" + ], + "type": "object" + } +} - added
Output schema / properties / entry / properties / details / requiredAdded value: +[] - changed
Output schema / properties / entry / properties / details / typePrevious value: -"null"New value: +[ + "null", + "object" +] - added
Output schema / properties / entry / properties / details_knownAdded value: +{ + "type": "boolean" +} - changed
Output schema / properties / entry / properties / evidence / typePrevious value: -"string"New value: +[ + "string", + "null" +] - changed
Output schema / properties / entry / requiredPrevious value: -[ - "id", - "equipment_kind", - "equipment_id", - "task", - "performed_at", - "disturbs_zero", - "note", - "offset_value", - "offset_source", - "offset_at", - "evidence", - "details", - "details_version", - "created_at" -]New value: +[ + "id", + "equipment_kind", + "equipment_id", + "task", + "performed_at", + "disturbs_zero", + "note", + "offset_value", + "offset_source", + "offset_at", + "evidence", + "details", + "details_version", + "created_at", + "details_known" +]
- Added
update_grinder - Added
update_machine - Added
update_scale - Added
update_water
14 tool updates
- Changed
compute_age3 fields changed- added
Input schema / properties / bag_idAdded value: +{ + "description": "A bag of that coffee (from list_beans' bags[]); null = its current bag", + "type": [ + "integer", + "null" + ] +} - added
Output schema / properties / bag_idAdded value: +{ + "type": "integer" +} - changed
Output schema / requiredPrevious value: -[ - "bean_id", - "roast_date", - "age_days", - "days_off_roast", - "days_since_opened", - "frozen_days_excluded", - "effective_age_days", - "rest_window", - "verdict", - "grams_remaining", - "warnings" -]New value: +[ + "bean_id", + "bag_id", + "roast_date", + "age_days", + "days_off_roast", + "days_since_opened", + "frozen_days_excluded", + "effective_age_days", + "rest_window", + "verdict", + "grams_remaining", + "warnings" +]
- Changed
diagnose_preview2 fields changed- added
Output schema / properties / bean_context / properties / bag_idAdded value: +{ + "type": "integer" +} - changed
Output schema / properties / bean_context / requiredPrevious value: -[ - "bean_id", - "bean_name", - "roast_level", - "effective_age_days", - "dial_category" -]New value: +[ + "bean_id", + "bag_id", + "bean_name", + "roast_level", + "effective_age_days", + "dial_category" +]
- Changed
diagnose_shot2 fields changed- added
Output schema / properties / bean_context / properties / bag_idAdded value: +{ + "type": "integer" +} - changed
Output schema / properties / bean_context / requiredPrevious value: -[ - "bean_id", - "bean_name", - "roast_level", - "effective_age_days", - "dial_category" -]New value: +[ + "bean_id", + "bag_id", + "bean_name", + "roast_level", + "effective_age_days", + "dial_category" +]
- Changed
get_dial_state10 fields changed- added
Output schema / properties / active_coffee / properties / acidityAdded value: +{ + "type": "null" +} - added
Output schema / properties / active_coffee / properties / arabica_pctAdded value: +{ + "type": "null" +} - added
Output schema / properties / active_coffee / properties / bagAdded value: +{ + "additionalProperties": true, + "properties": { + "age_verdict": { + "type": "string" + }, + "archived": { + "type": "integer" + }, + "bag_notes": { + "type": "string" + }, + "bag_weight_g": { + "type": "null" + }, + "bean_id": { + "type": "integer" + }, + "best_by_date": { + "type": "null" + }, + "buy_date": { + "type": "null" + }, + "cost": { + "type": "null" + }, + "currency": { + "type": "null" + }, + "days_off_roast": { + "type": "integer" + }, + "days_since_opened": { + "type": "null" + }, + "ean": { + "type": "null" + }, + "effective_age_days": { + "type": "integer" + }, + "finished": { + "type": "integer" + }, + "frozen_at": { + "type": "null" + }, + "frozen_days_excluded": { + "type": "integer" + }, + "frozen_note": { + "type": "null" + }, + "frozen_storage": { + "type": "null" + }, + "grams_remaining": { + "type": "null" + }, + "id": { + "type": "integer" + }, + "opened_date": { + "type": "null" + }, + "qr_code": { + "type": "null" + }, + "roast_date": { + "type": "string" + }, + "state": { + "type": "string" + }, + "storage": { + "type": "null" + }, + "unfrozen_at": { + "type": "null" + }, + "weight_adjustment_g": { + "type": "integer" + } + }, + "required": [ + "id", + "bean_id", + "roast_date", + "buy_date", + "opened_date", + "best_by_date", + "bag_weight_g", + "weight_adjustment_g", + "cost", + "currency", + "state", + "finished", + "frozen_at", + "unfrozen_at", + "frozen_storage", + "frozen_note", + "storage", + "ean", + "qr_code", + "bag_notes", + "archived", + "days_off_roast", + "days_since_opened", + "frozen_days_excluded", + "effective_age_days", + "age_verdict", + "grams_remaining" + ], + "type": "object" +} - added
Output schema / properties / active_coffee / properties / bodyAdded value: +{ + "type": "null" +} - added
Output schema / properties / active_coffee / properties / current_bag_idAdded value: +{ + "type": "integer" +} - added
Output schema / properties / active_coffee / properties / notesAdded value: +{ + "type": "null" +} - added
Output schema / properties / active_coffee / properties / sweetnessAdded value: +{ + "type": "null" +} - changed
Output schema / properties / active_coffee / requiredPrevious value: -[ - "id", - "name", - "roaster", - "origin", - "variety", - "roast_date", - "roast_level", - "process_type", - "dial_category", - "bag_notes", - "rest_window_days_min", - "rest_window_days_max", - "state", - "opened_date", - "storage", - "is_active", - "weight_adjustment_g", - "buy_date", - "bag_weight_g", - "cost", - "currency", - "decaffeinated", - "bean_mix", - "roast_range", - "roast_custom", - "roasting_type", - "aromatics", - "cupping_points", - "rating", - "favourite", - "url", - "ean", - "qr_code", - "co2e_kg", - "attachments", - "archived", - "frozen_at", - "unfrozen_at", - "frozen_storage", - "frozen_note", - "best_by_date", - "finished", - "age_days", - "days_off_roast", - "days_since_opened", - "frozen_days_excluded", - "effective_age_days", - "age_verdict", - "grams_remaining" -]New value: +[ + "id", + "name", + "roaster", + "origin", + "variety", + "roast_date", + "roast_level", + "process_type", + "dial_category", + "bag_notes", + "rest_window_days_min", + "rest_window_days_max", + "state", + "opened_date", + "storage", + "is_active", + "weight_adjustment_g", + "buy_date", + "bag_weight_g", + "cost", + "currency", + "decaffeinated", + "bean_mix", + "roast_range", + "roast_custom", + "roasting_type", + "aromatics", + "cupping_points", + "rating", + "favourite", + "url", + "ean", + "qr_code", + "co2e_kg", + "attachments", + "archived", + "frozen_at", + "unfrozen_at", + "frozen_storage", + "frozen_note", + "best_by_date", + "finished", + "notes", + "arabica_pct", + "body", + "acidity", + "sweetness", + "age_days", + "days_off_roast", + "days_since_opened", + "frozen_days_excluded", + "effective_age_days", + "age_verdict", + "grams_remaining", + "current_bag_id", + "bag" +] - added
Output schema / properties / recent_shots / items / properties / bag_idAdded value: +{ + "type": "integer" +} - changed
Output schema / properties / recent_shots / items / requiredPrevious value: -[ - "id", - "pulled_at", - "bean_id", - "grinder_id", - "machine_id", - "program_id", - "grind_label", - "grind_components", - "grind_position_value", - "dose_g", - "yield_g", - "time_s", - "flow_rate_gps", - "finish_action", - "drink_intent", - "flavor_notes", - "sensory_tags", - "observations", - "temp_taste", - "rating", - "verdict", - "data_confidence", - "temperature_c", - "bloom_time_s", - "first_drip_time_s", - "beverage_g", - "tds", - "ey_pct", - "water_id", - "vessel_name", - "vessel_weight_g", - "favourite", - "best_brew", - "tasted", - "taste_pending" -]New value: +[ + "id", + "pulled_at", + "bean_id", + "grinder_id", + "machine_id", + "program_id", + "grind_label", + "grind_components", + "grind_position_value", + "dose_g", + "yield_g", + "time_s", + "flow_rate_gps", + "finish_action", + "drink_intent", + "flavor_notes", + "sensory_tags", + "observations", + "temp_taste", + "rating", + "verdict", + "data_confidence", + "temperature_c", + "bloom_time_s", + "first_drip_time_s", + "beverage_g", + "tds", + "ey_pct", + "water_id", + "vessel_name", + "vessel_weight_g", + "favourite", + "best_brew", + "tasted", + "bag_id", + "taste_pending" +]
- Changed
list_beans25 fields changed- added
Output schema / properties / beans / items / properties / acidityAdded value: +{ + "type": "null" +} - added
Output schema / properties / beans / items / properties / arabica_pctAdded value: +{ + "type": "null" +} - added
Output schema / properties / beans / items / properties / aromaticsAdded value: +{ + "type": "null" +} - added
Output schema / properties / beans / items / properties / bagsAdded value: +{ + "items": { + "additionalProperties": true, + "properties": { + "age_verdict": { + "type": "string" + }, + "archived": { + "type": "integer" + }, + "bag_notes": { + "type": [ + "null", + "string" + ] + }, + "bag_weight_g": { + "type": [ + "integer", + "null" + ] + }, + "bean_id": { + "type": "integer" + }, + "best_by_date": { + "type": "null" + }, + "buy_date": { + "type": "null" + }, + "cost": { + "type": [ + "null", + "integer" + ] + }, + "currency": { + "type": [ + "null", + "string" + ] + }, + "days_off_roast": { + "type": "integer" + }, + "days_since_opened": { + "type": "null" + }, + "ean": { + "type": "null" + }, + "effective_age_days": { + "type": "integer" + }, + "finished": { + "type": "integer" + }, + "frozen_at": { + "type": "null" + }, + "frozen_days_excluded": { + "type": "integer" + }, + "frozen_note": { + "type": "null" + }, + "frozen_storage": { + "type": "null" + }, + "grams_remaining": { + "type": [ + "integer", + "null" + ] + }, + "id": { + "type": "integer" + }, + "opened_date": { + "type": "null" + }, + "qr_code": { + "type": "null" + }, + "roast_date": { + "type": "string" + }, + "shots_remaining": { + "type": "integer" + }, + "shots_remaining_basis": { + "type": "string" + }, + "shots_remaining_dose_g": { + "type": [ + "integer", + "number" + ] + }, + "shots_remaining_sample": { + "type": [ + "integer", + "null" + ] + }, + "state": { + "type": "string" + }, + "storage": { + "type": "null" + }, + "unfrozen_at": { + "type": "null" + }, + "weight_adjustment_g": { + "type": "integer" + } + }, + "required": [ + "id", + "bean_id", + "roast_date", + "buy_date", + "opened_date", + "best_by_date", + "bag_weight_g", + "weight_adjustment_g", + "cost", + "currency", + "state", + "finished", + "frozen_at", + "unfrozen_at", + "frozen_storage", + "frozen_note", + "storage", + "ean", + "qr_code", + "bag_notes", + "archived", + "effective_age_days", + "age_verdict", + "grams_remaining", + "days_since_opened", + "days_off_roast", + "frozen_days_excluded" + ], + "type": "object" + }, + "type": "array" +} - added
Output schema / properties / beans / items / properties / best_by_dateAdded value: +{ + "type": "null" +} - added
Output schema / properties / beans / items / properties / bodyAdded value: +{ + "type": "null" +} - added
Output schema / properties / beans / items / properties / buy_dateAdded value: +{ + "type": "null" +} - added
Output schema / properties / beans / items / properties / cupping_pointsAdded value: +{ + "type": "null" +} - added
Output schema / properties / beans / items / properties / current_bag_idAdded value: +{ + "type": [ + "integer", + "null" + ] +} - added
Output schema / properties / beans / items / properties / eanAdded value: +{ + "type": "null" +} - added
Output schema / properties / beans / items / properties / frozen_atAdded value: +{ + "type": "null" +} - added
Output schema / properties / beans / items / properties / frozen_noteAdded value: +{ + "type": "null" +} - added
Output schema / properties / beans / items / properties / frozen_storageAdded value: +{ + "type": "null" +} - added
Output schema / properties / beans / items / properties / notesAdded value: +{ + "type": [ + "null", + "string" + ] +} - added
Output schema / properties / beans / items / properties / originAdded value: +{ + "type": "null" +} - added
Output schema / properties / beans / items / properties / origins / items / properties / elevation_max_mAdded value: +{ + "type": "null" +} - changed
Output schema / properties / beans / items / properties / origins / items / requiredPrevious value: -[ - "country", - "region", - "farm", - "farmer", - "variety", - "processing", - "elevation_m", - "harvest", - "percentage" -]New value: +[ + "country", + "region", + "farm", + "farmer", + "variety", + "processing", + "elevation_m", + "elevation_max_m", + "harvest", + "percentage" +] - added
Output schema / properties / beans / items / properties / qr_codeAdded value: +{ + "type": "null" +} - added
Output schema / properties / beans / items / properties / roasting_typeAdded value: +{ + "type": "null" +} - added
Output schema / properties / beans / items / properties / sweetnessAdded value: +{ + "type": "null" +} - added
Output schema / properties / beans / items / properties / unfrozen_atAdded value: +{ + "type": "null" +} - added
Output schema / properties / beans / items / properties / urlAdded value: +{ + "type": "null" +} - added
Output schema / properties / beans / items / properties / varietyAdded value: +{ + "type": "null" +} - added
Output schema / properties / beans / items / properties / weight_adjustment_gAdded value: +{ + "type": "integer" +} - changed
Output schema / properties / beans / items / requiredPrevious value: -[ - "id", - "name", - "roaster", - "roast_date", - "roast_level", - "state", - "opened_date", - "archived", - "finished", - "favourite", - "decaffeinated", - "bag_weight_g", - "process_type", - "dial_category", - "rest_window_days_min", - "rest_window_days_max", - "storage", - "bag_notes", - "cost", - "currency", - "rating", - "effective_age_days", - "age_verdict", - "grams_remaining", - "days_since_opened", - "days_off_roast", - "frozen_days_excluded", - "origins" -]New value: +[ + "id", + "name", + "roaster", + "roast_level", + "archived", + "favourite", + "decaffeinated", + "process_type", + "dial_category", + "rest_window_days_min", + "rest_window_days_max", + "rating", + "aromatics", + "cupping_points", + "roasting_type", + "variety", + "origin", + "url", + "notes", + "arabica_pct", + "body", + "acidity", + "sweetness", + "roast_date", + "buy_date", + "opened_date", + "best_by_date", + "bag_weight_g", + "weight_adjustment_g", + "cost", + "currency", + "state", + "finished", + "frozen_at", + "unfrozen_at", + "frozen_storage", + "frozen_note", + "storage", + "ean", + "qr_code", + "bag_notes", + "effective_age_days", + "age_verdict", + "grams_remaining", + "days_since_opened", + "days_off_roast", + "frozen_days_excluded", + "current_bag_id", + "bags", + "origins" +]
- Changed
list_recipes2 fields changed- added
Output schema / properties / recipes / items / properties / roaster_nameAdded value: +{ + "type": "string" +} - changed
Output schema / properties / recipes / items / requiredPrevious value: -[ - "id", - "bean_id", - "grinder_id", - "machine_id", - "program_id", - "status", - "grind_label", - "grind_position_value", - "dose_g", - "target_yield_g", - "target_time_s", - "finish_action", - "drink_intent", - "profile", - "locked_at", - "bean_name", - "grinder_name", - "machine_name", - "grind_reading" -]New value: +[ + "id", + "bean_id", + "grinder_id", + "machine_id", + "program_id", + "status", + "grind_label", + "grind_position_value", + "dose_g", + "target_yield_g", + "target_time_s", + "finish_action", + "drink_intent", + "profile", + "locked_at", + "bean_name", + "roaster_name", + "grinder_name", + "machine_name", + "grind_reading" +]
- Changed
list_shots3 fields changed- added
Input schema / properties / filters / properties / bag_idAdded value: +{ + "description": "Filter by bag number (one purchase of a coffee)", + "type": "integer" +} - added
Output schema / properties / shots / items / properties / bag_idAdded value: +{ + "type": "integer" +} - changed
Output schema / properties / shots / items / requiredPrevious value: -[ - "id", - "pulled_at", - "bean_id", - "grinder_id", - "machine_id", - "program_id", - "grind_label", - "grind_components", - "grind_position_value", - "dose_g", - "yield_g", - "time_s", - "flow_rate_gps", - "finish_action", - "drink_intent", - "flavor_notes", - "sensory_tags", - "observations", - "temp_taste", - "rating", - "verdict", - "data_confidence", - "temperature_c", - "bloom_time_s", - "first_drip_time_s", - "beverage_g", - "tds", - "ey_pct", - "water_id", - "vessel_name", - "vessel_weight_g", - "favourite", - "best_brew", - "tasted", - "bean_name", - "taste_pending" -]New value: +[ + "id", + "pulled_at", + "bean_id", + "grinder_id", + "machine_id", + "program_id", + "grind_label", + "grind_components", + "grind_position_value", + "dose_g", + "yield_g", + "time_s", + "flow_rate_gps", + "finish_action", + "drink_intent", + "flavor_notes", + "sensory_tags", + "observations", + "temp_taste", + "rating", + "verdict", + "data_confidence", + "temperature_c", + "bloom_time_s", + "first_drip_time_s", + "beverage_g", + "tds", + "ey_pct", + "water_id", + "vessel_name", + "vessel_weight_g", + "favourite", + "best_brew", + "tasted", + "bag_id", + "bean_name", + "taste_pending" +]
- Changed
log_shot1 field changed- added
Input schema / properties / bag_idAdded value: +{ + "description": "Which bag of the coffee the shot came from; defaults to its current (open) bag. Bag numbers are on list_beans' bags[]", + "type": [ + "integer", + "null" + ] +}
- Added
merge_beans - Added
register_bag - Changed
register_coffee8 fields changed- added
Input schema / properties / acidityAdded value: +{ + "description": "Free text; roasters usually say low, medium or high", + "type": "string" +} - added
Input schema / properties / arabica_pctAdded value: +{ + "description": "Percent arabica, 100 for a pure arabica; the rest robusta", + "maximum": 100, + "minimum": 0, + "type": "number" +} - added
Input schema / properties / bodyAdded value: +{ + "description": "Free text; roasters usually say low, medium or high", + "type": "string" +} - added
Input schema / properties / notesAdded value: +{ + "description": "The coffee's own description — the roaster's tasting notes, the dialing approach that worked. Per bag notes go in bag_notes.", + "maxLength": 4096, + "type": "string" +} - added
Input schema / properties / origins / items / properties / elevation_max_mAdded value: +{ + "description": "Upper end of an elevation range, e.g. 1980 for \"1800–1980 m\"; elevation_m is the lower end", + "type": "number" +} - added
Input schema / properties / sweetnessAdded value: +{ + "description": "Free text; roasters usually say low, medium or high", + "type": "string" +} - added
Output schema / properties / bag_idAdded value: +{ + "type": "integer" +} - changed
Output schema / requiredPrevious value: -[ - "status", - "bean_id", - "message" -]New value: +[ + "status", + "bean_id", + "bag_id", + "message" +]
- Added
update_bag - Changed
update_bean7 fields changed- added
Input schema / properties / fields / properties / acidityAdded value: +{ + "description": "Free text; roasters usually say low, medium or high", + "type": "string" +} - added
Input schema / properties / fields / properties / arabica_pctAdded value: +{ + "maximum": 100, + "minimum": 0, + "type": "number" +} - added
Input schema / properties / fields / properties / bodyAdded value: +{ + "description": "Free text; roasters usually say low, medium or high", + "type": "string" +} - added
Input schema / properties / fields / properties / notesAdded value: +{ + "description": "The coffee's own description — roaster tasting notes, the dialing approach. Replaces the stored value; the optional reason is appended instead.", + "maxLength": 4096, + "type": "string" +} - added
Input schema / properties / fields / properties / origins / items / properties / elevation_max_mAdded value: +{ + "description": "Upper end of an elevation range; elevation_m is the lower end", + "type": "number" +} - added
Input schema / properties / fields / properties / sweetnessAdded value: +{ + "description": "Free text; roasters usually say low, medium or high", + "type": "string" +} - changed
Input schema / properties / reason / descriptionPrevious value: -"Optional free-text note, appended to the bag notes as an ordinary line. Omit it and nothing is written."New value: +"Optional free-text note, appended as an ordinary line to the coffee's notes — or to the current bag's bag_notes when the call changed only bag fields. Omit it and nothing is written."
- Changed
update_shot2 fields changed- added
Input schema / properties / fields / properties / bag_idAdded value: +{ + "description": "Re-file the shot onto this bag; must be a bag of the shot's bean", + "type": "integer" +} - changed
Input schema / properties / fields / properties / bean_id / descriptionPrevious value: -"Re-file the shot onto this bean"New value: +"Re-file the shot onto this bean (its current bag, unless bag_id is also given)"
1 tool update
- Changed
set_active4 fields changed- changed
Input schema / properties / bean_id / descriptionPrevious value: -"null = leave unchanged"New value: +"This account's own bean number, as returned by list_beans. Never guess one; null = leave unchanged" - changed
Input schema / properties / grinder_id / descriptionPrevious value: -"null = leave unchanged"New value: +"This account's own grinder number, as returned by list_grinders. Never guess one; null = leave unchanged" - changed
Input schema / properties / machine_id / descriptionPrevious value: -"null = leave unchanged"New value: +"This account's own machine number, as returned by list_machines. Never guess one; null = leave unchanged" - changed
Input schema / properties / program_id / descriptionPrevious value: -"null = leave unchanged"New value: +"A program number from the active machine's list. null = leave unchanged"
9 tool updates
- Changed
get_dial_state6 fields changed- added
Output schema / properties / locked_recipe / additionalPropertiesAdded value: +true - added
Output schema / properties / locked_recipe / propertiesAdded value: +{ + "bean_id": { + "type": "integer" + }, + "dose_g": { + "type": "integer" + }, + "drink_intent": { + "type": "string" + }, + "finish_action": { + "type": "string" + }, + "grind_label": { + "type": "string" + }, + "grind_position_value": { + "type": "integer" + }, + "grind_reading": { + "type": "null" + }, + "grinder_id": { + "type": "integer" + }, + "id": { + "type": "integer" + }, + "kb_version": { + "type": "string" + }, + "locked_at": { + "type": "string" + }, + "machine_id": { + "type": "integer" + }, + "profile": { + "type": "string" + }, + "program_id": { + "type": "null" + }, + "status": { + "type": "string" + }, + "target_time_s": { + "type": "integer" + }, + "target_yield_g": { + "type": "integer" + } +} - added
Output schema / properties / locked_recipe / requiredAdded value: +[ + "id", + "bean_id", + "grinder_id", + "machine_id", + "program_id", + "status", + "grind_label", + "grind_position_value", + "dose_g", + "target_yield_g", + "target_time_s", + "finish_action", + "drink_intent", + "profile", + "kb_version", + "locked_at", + "grind_reading" +] - changed
Output schema / properties / locked_recipe / typePrevious value: -"null"New value: +"object" - added
Output schema / properties / recent_recommendations / itemsAdded value: +{ + "additionalProperties": true, + "properties": { + "based_on_shot": { + "type": "null" + }, + "bean_id": { + "type": "integer" + }, + "cited_rules": { + "type": "string" + }, + "confidence": { + "type": "string" + }, + "created_at": { + "type": "string" + }, + "direction": { + "type": "string" + }, + "grinder_id": { + "type": "integer" + }, + "kb_version": { + "type": "string" + }, + "lever": { + "type": "string" + }, + "machine_id": { + "type": "integer" + }, + "rationale": { + "type": "string" + } + }, + "required": [ + "created_at", + "bean_id", + "grinder_id", + "machine_id", + "based_on_shot", + "lever", + "direction", + "rationale", + "confidence", + "cited_rules", + "kb_version" + ], + "type": "object" +} - added
Output schema / properties / recent_shots / itemsAdded value: +{ + "additionalProperties": true, + "properties": { + "bean_id": { + "type": "integer" + }, + "best_brew": { + "type": "integer" + }, + "beverage_g": { + "type": "null" + }, + "bloom_time_s": { + "type": "null" + }, + "data_confidence": { + "type": "string" + }, + "dose_g": { + "type": "integer" + }, + "drink_intent": { + "type": "string" + }, + "ey_pct": { + "type": "null" + }, + "favourite": { + "type": "integer" + }, + "finish_action": { + "type": "string" + }, + "first_drip_time_s": { + "type": "null" + }, + "flavor_notes": { + "type": "string" + }, + "flow_rate_gps": { + "type": "number" + }, + "grind_components": { + "type": "string" + }, + "grind_label": { + "type": "string" + }, + "grind_position_value": { + "type": "integer" + }, + "grinder_id": { + "type": "integer" + }, + "id": { + "type": "integer" + }, + "machine_id": { + "type": "integer" + }, + "observations": { + "type": "string" + }, + "program_id": { + "type": "null" + }, + "pulled_at": { + "type": "string" + }, + "rating": { + "type": "null" + }, + "sensory_tags": { + "type": "string" + }, + "taste_pending": { + "type": "integer" + }, + "tasted": { + "type": "integer" + }, + "tds": { + "type": "null" + }, + "temp_taste": { + "type": "string" + }, + "temperature_c": { + "type": "null" + }, + "time_s": { + "type": "integer" + }, + "verdict": { + "type": "null" + }, + "vessel_name": { + "type": "null" + }, + "vessel_weight_g": { + "type": "null" + }, + "water_id": { + "type": "null" + }, + "yield_g": { + "type": "integer" + } + }, + "required": [ + "id", + "pulled_at", + "bean_id", + "grinder_id", + "machine_id", + "program_id", + "grind_label", + "grind_components", + "grind_position_value", + "dose_g", + "yield_g", + "time_s", + "flow_rate_gps", + "finish_action", + "drink_intent", + "flavor_notes", + "sensory_tags", + "observations", + "temp_taste", + "rating", + "verdict", + "data_confidence", + "temperature_c", + "bloom_time_s", + "first_drip_time_s", + "beverage_g", + "tds", + "ey_pct", + "water_id", + "vessel_name", + "vessel_weight_g", + "favourite", + "best_brew", + "tasted", + "taste_pending" + ], + "type": "object" +}
- Changed
get_stats3 fields changed- changed
Output schema / properties / last_bean / typePrevious value: -"null"New value: +"string" - changed
Output schema / properties / last_grind_setting / typePrevious value: -"null"New value: +"string" - changed
Output schema / properties / last_used / typePrevious value: -"null"New value: +"string"
- Changed
list_beans10 fields changed- changed
Output schema / properties / beans / items / properties / bag_notes / typePrevious value: -"string"New value: +[ + "null", + "string" +] - changed
Output schema / properties / beans / items / properties / bag_weight_g / typePrevious value: -"null"New value: +[ + "integer", + "null" +] - changed
Output schema / properties / beans / items / properties / decaffeinated / typePrevious value: -"null"New value: +[ + "integer", + "null" +] - changed
Output schema / properties / beans / items / properties / favourite / typePrevious value: -"null"New value: +[ + "integer", + "null" +] - changed
Output schema / properties / beans / items / properties / grams_remaining / typePrevious value: -[ - "null", - "integer" -]New value: +[ + "integer", + "null" +] - added
Output schema / properties / beans / items / properties / origins / itemsAdded value: +{ + "additionalProperties": true, + "properties": { + "country": { + "type": "string" + }, + "elevation_m": { + "type": "null" + }, + "farm": { + "type": "null" + }, + "farmer": { + "type": "null" + }, + "harvest": { + "type": "null" + }, + "percentage": { + "type": "integer" + }, + "processing": { + "type": "null" + }, + "region": { + "type": "string" + }, + "variety": { + "type": "string" + } + }, + "required": [ + "country", + "region", + "farm", + "farmer", + "variety", + "processing", + "elevation_m", + "harvest", + "percentage" + ], + "type": "object" +} - changed
Output schema / properties / beans / items / properties / rest_window_days_max / typePrevious value: -"null"New value: +[ + "integer", + "null" +] - changed
Output schema / properties / beans / items / properties / rest_window_days_min / typePrevious value: -"null"New value: +[ + "integer", + "null" +] - changed
Output schema / properties / beans / items / properties / shots_remaining_dose_g / typePrevious value: -"number"New value: +[ + "integer", + "number" +] - changed
Output schema / properties / beans / items / properties / shots_remaining_sample / typePrevious value: -"null"New value: +[ + "integer", + "null" +]
- Changed
list_grinders27 fields changed- changed
Output schema / properties / grinders / items / properties / components_spec / typePrevious value: -"string"New value: +[ + "null", + "string" +] - changed
Output schema / properties / grinders / items / properties / maintenance / properties / calibration / properties / epoch_at / typePrevious value: -"string"New value: +[ + "null", + "string" +] - changed
Output schema / properties / grinders / items / properties / maintenance / properties / calibration / properties / epoch_id / typePrevious value: -"integer"New value: +[ + "null", + "integer" +] - changed
Output schema / properties / grinders / items / properties / maintenance / properties / calibration / properties / evidence / typePrevious value: -"null"New value: +[ + "null", + "string" +] - changed
Output schema / properties / grinders / items / properties / maintenance / properties / calibration / properties / offset_at / typePrevious value: -"null"New value: +[ + "null", + "string" +] - changed
Output schema / properties / grinders / items / properties / maintenance / properties / calibration / properties / offset_source / typePrevious value: -"null"New value: +[ + "null", + "string" +] - changed
Output schema / properties / grinders / items / properties / maintenance / properties / calibration / properties / offset_value / typePrevious value: -"null"New value: +[ + "null", + "integer" +] - changed
Output schema / properties / grinders / items / properties / maintenance / properties / calibration / properties / reference_recipe_id / typePrevious value: -"integer"New value: +[ + "null", + "integer" +] - changed
Output schema / properties / grinders / items / properties / maintenance / properties / due / properties / burr_clean / properties / basis / typePrevious value: -"string"New value: +[ + "null", + "string" +] - changed
Output schema / properties / grinders / items / properties / maintenance / properties / due / properties / burr_clean / properties / done / typePrevious value: -"integer"New value: +[ + "null", + "integer" +] - changed
Output schema / properties / grinders / items / properties / maintenance / properties / due / properties / burr_clean / properties / every / typePrevious value: -"integer"New value: +[ + "null", + "integer" +] - changed
Output schema / properties / grinders / items / properties / maintenance / properties / due / properties / burr_clean / properties / last_at / typePrevious value: -"string"New value: +[ + "null", + "string" +] - changed
Output schema / properties / grinders / items / properties / maintenance / properties / due / properties / burr_clean / properties / ratio / typePrevious value: -"number"New value: +"integer" - changed
Output schema / properties / grinders / items / properties / maintenance / properties / due / properties / burr_clean / properties / remaining / typePrevious value: -"integer"New value: +[ + "null", + "integer" +] - changed
Output schema / properties / grinders / items / properties / maintenance / properties / entries / items / properties / evidence / typePrevious value: -[ - "null", - "string" -]New value: +[ + "string", + "null" +] - changed
Output schema / properties / grinders / items / properties / maintenance / properties / entries / items / properties / note / typePrevious value: -[ - "string", - "null" -]New value: +[ + "null", + "string" +] - changed
Output schema / properties / grinders / items / properties / maintenance / properties / entries / items / properties / offset_at / typePrevious value: -[ - "null", - "string" -]New value: +[ + "string", + "null" +] - changed
Output schema / properties / grinders / items / properties / maintenance / properties / entries / items / properties / offset_source / typePrevious value: -[ - "null", - "string" -]New value: +[ + "string", + "null" +] - changed
Output schema / properties / grinders / items / properties / maintenance / properties / entries / items / properties / offset_value / typePrevious value: -[ - "null", - "integer" -]New value: +[ + "integer", + "null" +] - changed
Output schema / properties / grinders / items / properties / max_value / typePrevious value: -"null"New value: +[ + "integer", + "null" +] - changed
Output schema / properties / grinders / items / properties / microns_per_step / typePrevious value: -"integer"New value: +[ + "null", + "integer" +] - changed
Output schema / properties / grinders / items / properties / min_value / typePrevious value: -"null"New value: +[ + "integer", + "null" +] - changed
Output schema / properties / grinders / items / properties / position_value / typePrevious value: -"integer"New value: +[ + "null", + "integer" +] - changed
Output schema / properties / grinders / items / properties / setting_components / typePrevious value: -"string"New value: +[ + "null", + "string" +] - changed
Output schema / properties / grinders / items / properties / setting_label / typePrevious value: -"string"New value: +[ + "null", + "string" +] - changed
Output schema / properties / grinders / items / properties / source / typePrevious value: -"string"New value: +[ + "null", + "string" +] - changed
Output schema / properties / grinders / items / properties / verified_at / typePrevious value: -"string"New value: +[ + "null", + "string" +]
- Changed
list_machines5 fields changed- changed
Output schema / properties / machines / items / properties / basket_size_grams / typePrevious value: -"integer"New value: +[ + "null", + "integer" +] - changed
Output schema / properties / machines / items / properties / boiler_type / typePrevious value: -"string"New value: +[ + "null", + "string" +] - changed
Output schema / properties / machines / items / properties / prep_style / typePrevious value: -"null"New value: +[ + "string", + "null" +] - changed
Output schema / properties / machines / items / properties / prep_type / typePrevious value: -"null"New value: +[ + "string", + "null" +] - changed
Output schema / properties / machines / items / properties / programs / items / properties / description / typePrevious value: -"string"New value: +[ + "string", + "null" +]
- Changed
list_recipes5 fields changed- changed
Output schema / properties / recipes / items / properties / dose_g / typePrevious value: -"number"New value: +[ + "integer", + "number" +] - changed
Output schema / properties / recipes / items / properties / grind_reading / requiredPrevious value: -[ - "label", - "offset_clicks", - "offset_direction", - "epochs_since", - "unmeasured" -]New value: +[] - changed
Output schema / properties / recipes / items / properties / grind_reading / typePrevious value: -"object"New value: +[ + "null", + "object" +] - changed
Output schema / properties / recipes / items / properties / program_id / typePrevious value: -"integer"New value: +[ + "null", + "integer" +] - changed
Output schema / properties / recipes / items / properties / target_yield_g / typePrevious value: -[ - "number", - "integer" -]New value: +[ + "integer", + "number" +]
- Changed
list_scales1 field changed- added
Output schema / properties / scales / itemsAdded value: +{ + "additionalProperties": true, + "properties": { + "archived": { + "type": "integer" + }, + "auto_tare": { + "type": "null" + }, + "auto_timer": { + "type": "null" + }, + "capacity_g": { + "type": "null" + }, + "connectivity": { + "type": "null" + }, + "depth_mm": { + "type": "null" + }, + "flow_rate_display": { + "type": "null" + }, + "height_mm": { + "type": "null" + }, + "id": { + "type": "integer" + }, + "name": { + "type": "string" + }, + "notes": { + "type": "null" + }, + "power": { + "type": "null" + }, + "resolution_banded": { + "type": "integer" + }, + "resolution_g": { + "type": "number" + }, + "scale_type": { + "type": "string" + }, + "water_resistance": { + "type": "null" + }, + "width_mm": { + "type": "null" + } + }, + "required": [ + "id", + "name", + "scale_type", + "resolution_g", + "resolution_banded", + "capacity_g", + "width_mm", + "depth_mm", + "height_mm", + "water_resistance", + "connectivity", + "flow_rate_display", + "auto_tare", + "auto_timer", + "power", + "notes", + "archived" + ], + "type": "object" +}
- Changed
list_shots1 field changed- added
Output schema / properties / shots / itemsAdded value: +{ + "additionalProperties": true, + "properties": { + "bean_id": { + "type": "integer" + }, + "bean_name": { + "type": "string" + }, + "best_brew": { + "type": "integer" + }, + "beverage_g": { + "type": "null" + }, + "bloom_time_s": { + "type": "null" + }, + "data_confidence": { + "type": "string" + }, + "dose_g": { + "type": "integer" + }, + "drink_intent": { + "type": "string" + }, + "ey_pct": { + "type": "null" + }, + "favourite": { + "type": "integer" + }, + "finish_action": { + "type": "string" + }, + "first_drip_time_s": { + "type": "null" + }, + "flavor_notes": { + "type": "string" + }, + "flow_rate_gps": { + "type": "number" + }, + "grind_components": { + "type": "string" + }, + "grind_label": { + "type": "string" + }, + "grind_position_value": { + "type": "integer" + }, + "grinder_id": { + "type": "integer" + }, + "id": { + "type": "integer" + }, + "machine_id": { + "type": "integer" + }, + "observations": { + "type": "string" + }, + "program_id": { + "type": "null" + }, + "pulled_at": { + "type": "string" + }, + "rating": { + "type": "null" + }, + "sensory_tags": { + "type": "string" + }, + "taste_pending": { + "type": "integer" + }, + "tasted": { + "type": "integer" + }, + "tds": { + "type": "null" + }, + "temp_taste": { + "type": "string" + }, + "temperature_c": { + "type": "null" + }, + "time_s": { + "type": "integer" + }, + "verdict": { + "type": "null" + }, + "vessel_name": { + "type": "null" + }, + "vessel_weight_g": { + "type": "null" + }, + "water_id": { + "type": "null" + }, + "yield_g": { + "type": "integer" + } + }, + "required": [ + "id", + "pulled_at", + "bean_id", + "grinder_id", + "machine_id", + "program_id", + "grind_label", + "grind_components", + "grind_position_value", + "dose_g", + "yield_g", + "time_s", + "flow_rate_gps", + "finish_action", + "drink_intent", + "flavor_notes", + "sensory_tags", + "observations", + "temp_taste", + "rating", + "verdict", + "data_confidence", + "temperature_c", + "bloom_time_s", + "first_drip_time_s", + "beverage_g", + "tds", + "ey_pct", + "water_id", + "vessel_name", + "vessel_weight_g", + "favourite", + "best_brew", + "tasted", + "bean_name", + "taste_pending" + ], + "type": "object" +}
- Changed
list_waters1 field changed- added
Output schema / properties / waters / itemsAdded value: +{ + "additionalProperties": true, + "properties": { + "archived": { + "type": "integer" + }, + "calcium": { + "type": "null" + }, + "gh": { + "type": "integer" + }, + "id": { + "type": "integer" + }, + "kh": { + "type": "integer" + }, + "magnesium": { + "type": "null" + }, + "name": { + "type": "string" + }, + "notes": { + "type": "null" + }, + "sodium": { + "type": "null" + }, + "tds": { + "type": "null" + }, + "type": { + "type": "null" + } + }, + "required": [ + "id", + "name", + "type", + "tds", + "gh", + "kh", + "sodium", + "calcium", + "magnesium", + "notes", + "archived" + ], + "type": "object" +}
1 tool update
- Changed
list_grinders2 fields changed- added
Output schema / properties / grinders / items / properties / maintenance / properties / calibration / properties / reference_recipe_idAdded value: +{ + "type": "integer" +} - changed
Output schema / properties / grinders / items / properties / maintenance / properties / calibration / requiredPrevious value: -[ - "stale_recipe_count", - "state", - "epoch_id", - "epoch_at", - "offset_value", - "offset_unit", - "offset_source", - "offset_at", - "evidence" -]New value: +[ + "stale_recipe_count", + "reference_recipe_id", + "state", + "epoch_id", + "epoch_at", + "offset_value", + "offset_unit", + "offset_source", + "offset_at", + "evidence" +]
Related MCP Servers
- AlicenseNot gradedqualityCmaintenanceRemote MCP server that lets AI assistants read tracked competitive intelligence — competitor news, reviews, website changes, social posts and ads — and act on it by managing projects, competitors, battle cards, reports and canvases. Every answer carries a source and a date, and write actions only publish when explicitly shared.MIT
- AlicenseCqualityBmaintenanceCompetitor Monitor AI - MCP server providing AI-powered tools and automation by MEOK AI Labs115 npm58 PyPIMIT
- AlicenseAqualityCmaintenanceEnables brand visibility monitoring across major AI platforms like ChatGPT, Claude, Gemini, and Perplexity. It allows users to track visibility scores, analyze competitor data, and receive actionable insights to improve AI-generated brand recommendations.1623 npm1MIT

industrylens-mcpofficial
AlicenseNot gradedqualityBmaintenanceBrowse IndustryLens's published competitive-intelligence reports and head-to-head competitor comparisons from any AI agent — real, source-backed data.MIT
Glama MCP Gateway
Add one secure layer between your agents and this server.