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 60 days
- Last Tested
- Transport
- Streamable HTTP · MCP 2025-06-18
- URL
TDQS
Scored across 44 tools
Each tool targets a distinct resource or action, and the detailed descriptions clarify edge cases well. With 44 tools there is mild potential confusion among retrieval/diagnosis tools (diagnose_preview vs diagnose_shot, get_dial_state vs suggest_next_step) and among the parallel list/register/update families.
Names are almost entirely consistent snake_case verb_noun patterns (list_*, register_*, update_*, set_*, log_*, etc.). A couple of noun-style names (grinder_math, kb_changelog) are minor deviations but still readable and predictable.
44 tools is far above the 3–15 well-scoped range and beyond the 25+ threshold in the rubric. Even for a complex coffee-dialing domain, the surface is heavy with many parallel CRUD families.
Core lifecycle coverage is strong: registration, listing, updating, and archiving for beans, equipment, waters, and scales; shots have log/update/delete; maintenance and diagnosis are covered. Minor gaps remain, such as no explicit recipe update/delete/unlock, no program list/update/delete beyond register, and no delete/update for logged recommendations.
Available Tools
44 toolscompute_ageCompute coffee ageARead-onlyIdempotentInspect
Compute a bag's age in days off roast and its resting/staling verdict — the coffee's current bag by default, or 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 | |
| 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 establish readOnlyHint=true, idempotentHint=true, destructiveHint=false, and openWorldHint=false, so the safety profile is fully carried by structured data. The description adds the substantive behavior (off-roast day count and a resting/staling verdict) but says nothing about failure modes or edge cases, so it only modestly exceeds 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?
A single front-loaded sentence with no padding; the output and the default-scope clause come in the right order. The trailing em-dash clause is slightly compressed but still readable.
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 structure need not be explained, and annotations cover the safety envelope. What remains thin is the undocumented required bean_id, but for a two-parameter read-only computation the description is nearly 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?
Schema coverage is 50%: bag_id is documented in-schema and its null default is reinforced by the description's 'current bag by default' phrasing, but bean_id has no description anywhere. The description helps for one parameter and leaves the required one implicit.
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 ('Compute a bag's age in days off roast') plus the secondary output ('resting/staling verdict'), which no sibling tool provides. An agent can distinguish this from list_beans, register_bag, or update_bag at a glance.
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 scope ('the coffee's current bag by default, or the bag named'), which guides the caller, but it never states when to reach for this tool versus alternatives or any prerequisite. Usage is inferable rather than explicit.
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 carry destructiveHint=true, idempotentHint=true, and readOnlyHint=false, so the bar is lower. The description still adds genuinely new behavioral info: the cascade side effect 'Restores the bean's remaining weight (which is derived from logged doses)' and the irreversibility warning 'Hard delete — there is no undo.' No contradiction with idempotentHint, since re-deleting an already-removed shot would simply no-op or fail.
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, each earning its place: purpose, side effect, and alternative routing. The hard-delete warning is front-loaded before the update_shot guidance, and there is zero fluff, repetition, or restatement of the title.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
The behavioral core is covered: purpose, weight-restoration side effect, irreversibility, and the preferred alternative. The output schema exists so return-value detail is not required. A minor gap is behavior for a non-existent or already-deleted shot_id, but idempotentHint and the output schema mitigate that. For a one-parameter tool, this is complete enough.
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% — the schema itself documents shot_id as 'ID of the shot to delete.' The description adds no parameter-level detail beyond that (no validation rules, no edge-case handling), so the baseline of 3 applies per the coverage rule.
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 ('Delete') with a precise object ('a logged shot from history'), clearly scoping the operation to shot history entries. It distinguishes itself from update_shot by implication, and the title is reinforced rather than merely restated.
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 agents away from destructive misuse: 'To fix a mistake on an otherwise-valid shot, prefer update_shot over delete-and-relog.' This names the exact alternative and the condition that should select it, giving clear when-to-use vs when-not-to-use guidance.
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 — 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 | |
| one_variable_only | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare readOnly/idempotent/non-destructive, and the description adds concrete effect-level context: no verdict and no recommendation-trail entry are written, it is sandbox-only, and with shot_id the metric params are ignored while the shot's own bean and pulled_at age are used. That is meaningful beyond the safety hints, though permissions/rate behavior are unaddressed.
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 key differentiator ('Sandbox-only diagnosis, writes nothing') and keeps to two dense sentences with no filler. It is information-heavy, but every clause carries load; a slight trim of the mode examples would tighten it further.
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 no explanation, and the description still notes the output matches diagnose_shot including bean_context. With optional-everything params (0 required), the two-mode contract is fully covered 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%, so the baseline is 3. The description earns above baseline by explaining cross-parameter semantics the schema does not: that shot_id ignores the metric params, that sensory_tags replaces stored tags in preview mode ([] = none), and that bean age at pulled_at is used.
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', dry-run preview) and immediately distinguishes it from the sibling diagnose_shot by noting it writes nothing and shares the same output shape. An agent can separate this from diagnose_shot and log_shot without opening a 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?
Clearly enumerates the two invocation modes and the condition selecting each (pass shot_id for a logged shot vs the full metric set for a hypothetical). It implies diagnose_shot is the non-preview counterpart but never names it as the alternative for a real run, so it stops short of full when/when-not routing.
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 | |
| one_variable_only | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already cover safety (readOnly, idempotent), but the description adds substantial behavioral context: the engine reads metrics and sensory tags rather than free-text notes, bean age is computed at pulled_at and echoed as bean_context, and never uses the active profile. These are non-obvious traits that materially affect correct invocation.
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 purpose and outputs, followed by the bean-resolution guarantee and the critical sensory_tags prerequisite. Dense but each clause carries real information; the final sentence is long yet justified.
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 covers the preconditions and the bean-context behavior an agent needs. Nothing required to call this correctly is missing.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
With a single parameter at 100% schema coverage, the schema already documents that shot_id defaults to the last pulled shot. The description adds no syntax or format detail beyond that, so the baseline of 3 applies.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
States a specific verb and resource ('Evaluate shot metrics') plus the concrete outputs (ranked hypotheses C6, flip-flop/fatigue warnings). An agent can distinguish this from list_shots or get_stats 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?
Gives an explicit prerequisite chain: taste feedback must be recorded as sensory_tags via log_shot or update_shot before diagnosing, otherwise results are wrong. It also reassures that diagnosing older or differently-filed shots is safe, covering the main decision points.
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 declare readOnlyHint=true, idempotentHint=true, destructiveHint=false, and openWorldHint=false, so the safety profile is fully covered structurally. The description adds that this is a composite read returning several related collections, which is mild value beyond the annotations, but it says nothing about freshness, scope (per-machine? per-user?), or when the data might be empty.
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 sentence, front-loaded with the verb and resource, then the payload list. No filler, no redundancy with the title beyond the unavoidable overlap.
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 document return values in detail, and zero params plus rich annotations leave little to compensate for. What remains under-specified is scope (whose dial state) and freshness, which for a state-dependent composite read could matter to an agent.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
The tool takes zero parameters, so the baseline is 4; the description correctly implies a no-argument current-state read by specifying 'current dialing state' rather than any filtered variant.
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 (Retrieve) and resource (current dialing state) and enumerates the composite payload: active context, recent shots, recommendations, locked recipes. That enumeration distinguishes it from single-resource siblings like list_shots or get_stats, though it never names them 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?
No guidance on when to use this snapshot versus list_shots, get_stats, or suggest_next_step, and no prerequisites or exclusions stated. The agent must infer its role as an aggregated dashboard call from the output list alone.
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 declare the safe read-only and idempotent profile, so the description's job is supplementary. It adds genuinely useful behavior: unmatched ids are surfaced under 'missing', and the content's provenance ('our own words with the maker's documents as sources') is disclosed. It stops short of 5 only because it does not discuss scope limits like per-guide size or pagination.
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 first sentence front-loads what the tool returns, followed by the two invocation modes. It is efficient with no filler, though the first sentence is dense with enumerated content types and the id-provenance clause is packed into the second sentence.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
With an output schema present, return values need not be explained, and the description covers both call modes, the id source, and the 'missing' edge case. Nothing an agent needs to call it correctly is absent.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is 100%, so the baseline is 3, but the description goes further by explaining where the ids originate (maintenance.tasks[].guide.id from list_grinders and list_machines) and by restating the omit-for-all behavior in domain terms. That provenance meaningfully exceeds the schema text.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description states a specific verb and resource — step-by-step maintenance guides — and enumerates exactly what they contain (tools, supplies, steps, warnings, and that content is authored in-house with maker documents as sources). An agent can tell it apart from siblings like list_maintenance_due 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?
It clearly distinguishes the two invocation modes: no arguments returns every guide for the user's current grinders, machines, and fitted water filters, while guide_ids fetches specific guides. It does not name explicit alternatives (e.g., list_maintenance_due) or when-not-to-use cases, so it stops short of a 5.
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 cover the read-only/idempotent/destructive safety profile, so the bar is lower, yet the description adds real un-annotated context: bag nesting, that top-level roast_date/state/grams_remaining/age belong to the current bag, and that row `id` is an account-local numbering distinct from bag ids. It stops short of describing 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?
Front-loaded with purpose, then dense but useful data-shape clarifications. No filler sentences, though the middle sentence packs several field relationships that could be marginally tighter.
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 returns, and rich annotations cover safety; the remaining ambiguity it resolves (id vs bag id series) is the one an agent would plausibly get wrong. Minor gaps: no pagination/ordering or archived-vs-all behavior detail.
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 enum parameter already documents its values and default, so the schema does the heavy lifting. The description's mention of the status filter adds no syntax or meaning beyond the enum.
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?
Specific verb+resource: 'List the coffees registered for the account', clearly separable from sibling list_* tools (list_shots, list_grinders, list_recipes). The status-filter scoping is stated up front.
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?
No when-to-use, when-not, or alternative routing is given. The description never says whether this is the read path before update_bean/register_bag/merge_beans, nor when an agent should prefer this over searching shots. Only the implicit 'list to find ids' is conveyed.
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 readOnly, idempotent, non-destructive and closed-world, so safety is covered. The description adds real behavioral context beyond that: the per-account 1-based id is stable and safe to display, and each row carries a maintenance block with task classes and due state. It stops short of describing ordering, pagination or row count.
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 the id semantics are front-loaded in the first two clauses, which is exactly what an agent needs. The trailing class legend (S/H/Y/A/T/N/U/E) is dense and slightly list-like, but each element is load-bearing for interpreting the returned rows.
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 annotations covering the safety profile and an output schema covering return shape, the description only needs to explain the id contract and the maintenance block, and it does both. The absence of any note on ordering, tie-breaking or result volume is a minor remaining gap for a list tool.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 100% and both enums are documented in the schema, so the baseline is 3. The description's mention of the maintenance block and the class legend reinforces the `maintenance` parameter's meaning but adds little syntax or default behavior beyond what the schema already states (compact default, full = maker's words).
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 ('List grinders registered for the account') and scopes it with the status filter, and it goes further by describing what each row contains. It does not explicitly differentiate itself from the near-neighbor list_maintenance_due, which is the one meaningful ambiguity among the 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?
Usage is implied rather than stated: the note that the `id` is 'what other tools expect back' hints that this is the lookup step before update_grinder / set_grinder_position, but there is no explicit when-to-use, when-not, or named alternative. An agent can infer the workflow but is not told it.
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 cover the safety profile (readOnly, idempotent, non-destructive), so the description is free to add data-shape context instead: the per-account ordinal `id`, the researched maintenance block, and the null semantics of `settings`. That is genuinely useful context beyond the structured fields, though it says nothing about pagination or result size 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?
Front-loaded purpose in the first clause, then progressively deeper return-shape detail; no filler sentences. It is dense but every sentence conveys a distinct fact, with only mild overlap against the output schema.
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 two-param, zero-required list tool with an output schema, the definition is nearly sufficient: it covers scope, filtering, and the meaning of the two most confusing return fields. It stops short of full completeness by omitting any ordering, paging, or empty-result behavior.
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 enums are fully documented with defaults in the schema, so the schema carries parameter meaning. The description only echoes the status filter and says nothing about how compact vs full changes cost or payload, so baseline 3 is right.
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 ('List machines registered for the account') and scopes it with the status filter. The resource is distinct from the many list_* siblings (list_beans, list_grinders, list_shots), so an agent can pick it 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?
Implied usage only: it notes the status filter and defaults to current, and hints that the returned `id` is 'what other tools expect back', which implies chaining. But it never states when to prefer this over list_grinders/list_shots or when to use status=all, so guidance is inferred 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_maintenance_dueList maintenance dueARead-onlyIdempotentInspect
What maintenance is due across the user's current grinders and machines, most urgent first — 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?
Beyond the readOnly/idempotent annotations, the description discloses the inclusion rule (only interval-based tasks qualify) and enumerates the excluded categories, plus what each result item reports (progress ratio, basis, upcoming flag, interval owner). That is substantive behavioral context an agent cannot get from annotations or the schema.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Front-loaded with the core question and the ordering guarantee, then the inclusion rule, then result shape. Dense but waste-free; the mid-sentence clause listing exclusions via a double negative ('never appear') is slightly harder to parse than it needs to be.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
With annotations covering the safety profile, a fully documented parameter, and an output schema covering return structure, the description supplies exactly the missing pieces: what counts as due, what is filtered out, and what each item conveys. Nothing an agent needs to call it correctly is absent.
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 is fully documented in the schema, including the 'due' default and mute ordering. The description adds no syntax or format detail about the status parameter, so the baseline 3 applies.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
States a specific verb+resource (what maintenance is due across the user's current grinders and machines) and scopes it to the 'is anything due?' question, which clearly separates it from siblings like log_maintenance, set_maintenance_schedule, and get_maintenance_guides.
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 framing 'for "is anything due?"' gives a clear usage context and implies when to reach for this tool rather than scheduling or logging siblings. It never names an alternative explicitly or states when NOT to use it, so it falls short of a 5.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
list_recipesList locked recipesBRead-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, so the safety profile is covered. The description adds genuinely new behavior: the row `id` is account-relative counting from 1, safe to surface, and is the identifier other tools expect back — useful context not present in the structured fields.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Two tight sentences with the core action front-loaded and no filler. The second sentence is dense but earns its place by carrying the id semantics the agent needs downstream.
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 re-explained, and the description wisely adds only the non-obvious id detail. For a zero-required-param list tool this is nearly complete, with filtering semantics the main omission.
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% (only `status` is documented), so the description must compensate and largely doesn't. It gestures at 'filtered by equipment and status', loosely grouping bean_id/grinder_id/machine_id as 'equipment', but never clarifies these params or how the filters combine.
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 ('List recipes') and notes the filtering dimensions (equipment and status), which is more than a tautology. The gap is the mismatch with the title ('List locked recipes') and the absence of differentiation from the many list_* siblings, so an agent gets the resource but not the precise scope.
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?
No when-to-use, when-not-to-use, or alternative is stated. A sibling lock_recipe exists and the title implies 'locked recipes', yet the description never explains the relationship or when this list is the right call versus other lookups.
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=true, idempotentHint=true, destructiveHint=false and openWorldHint=false, so the safety profile is fully covered. The description adds the id semantics (1-based, safe to display, expected by other tools), which is genuine cross-tool context, but says nothing about ordering, pagination, or result size limits.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Two tight sentences with zero filler; the purpose is front-loaded and the id clarification follows it naturally.
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, and the description covers purpose plus the one non-obvious output detail (id numbering). For a simple read-only list tool with full annotations, this is nearly 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?
Schema description coverage is 100% and the single status enum is fully documented in the schema, including the 'Defaults to current' behavior. The description adds nothing about the status filter, so the schema does all the work — baseline 3.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
States a specific verb and resource ('List registered scales for the account'), which distinguishes it from siblings like list_beans and list_shots by resource alone. It does not explicitly name an alternative tool, so it stops short of a 5.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
There is no explicit when-to-use or when-not-to-use guidance versus register_scale or update_scale. The clause 'what other tools expect back' implicitly tells the agent this is the lookup that supplies ids to other tools, which is useful implied usage but not a stated rule.
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 readOnlyHint, idempotentHint, non-destructive and closed-world, so the safety profile is fully covered by structured data. The description adds the semantics of the derived taste_pending flag, but that same definition already appears in the schema's taste_pending filter description, so the added value is modest.
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, purpose front-loaded before the derived-flag detail, with no filler. Slightly long on the taste_pending aside, which duplicates schema 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?
An output schema exists, so return shape need not be described. For a zero-required-parameter read-only list tool, purpose, pagination, filtering and the one non-obvious derived field are all covered; only the absence of guidance on choosing between list tools leaves a 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 67%, with limit/offset and all filter fields self-documented in the schema. The description adds nothing about filter syntax, date-format edge cases, or how limit/offset interact, so it does not compensate for the remaining uncovered 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?
States a specific verb+resource ('List shot history') and names its two capabilities (pagination, filtering), which cleanly separates it from mutation siblings like log_shot/update_shot and from aggregate tools like get_stats. It stops short of explicitly contrasting with the closest alternatives (get_dial_state, list_recipes), so it is not a 5.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description implies usage through the taste_pending explanation and points to update_shot for backfilling owed tastings, which is genuinely useful routing. However it never states when to prefer this over get_stats or get_dial_state, and gives no exclusions or prerequisites.
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 cover the safety profile (readOnly, idempotent, non-destructive, closed-world), so the bar is lower. The description adds genuinely non-obvious behavior: row ids are account-scoped ordinals counting from 1, safe to expose, and interoperable with other tools — context an agent could not infer from the schema.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Two short sentences, the core operation front-loaded and the id semantics immediately after. Every clause carries information; no filler or repetition of the title.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
An output schema exists, so return values need not be described, and the one input parameter is fully specified in the schema. The description covers what matters most for a list tool — the identity semantics of each row — though it omits whether the list is paginated or ordered.
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%: the single enum parameter `status` is fully documented (current/archived/all, defaults to current). The description adds nothing about the status filter, so baseline 3 applies.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
States a specific verb and resource ('List registered waters for the account'), which is clearly distinguishable from the many list_* siblings by resource type. It does not explicitly contrast with nearest sibling list_recipes/register_water, but the resource noun does the differentiating work.
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 — the note that the id is 'what other tools expect back' hints that this tool is the lookup step before update_water or similar, but no when-to-use / when-not-to-use condition or alternative is stated. Nothing tells the agent why to pick this over directly registering or updating.
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 — so 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?
Annotations mark this as a non-read-only, non-destructive, non-idempotent write, and the description adds substantial domain behavior beyond that: disassembly opens a calibration epoch, locked recipes are re-read through the epoch offset, and omitting offset_value leaves the epoch unmeasured rather than zero. It doesn't spell out reversibility or duplicate-log behavior, 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?
The purpose is front-loaded and the first sentence is efficient, but the middle sentences are prose-heavy with filler ('which is the one moment anybody actually knows it') and take multiple reads to parse the epoch mechanics. It is adequately sized for a complex domain but not tightly written.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
With an output schema present, return values need not be described. The description covers the epoch/offset model, the vocabulary scope, task-specific details fields, and the read-prerequisite tools, which is substantial for an 11-parameter tool. Remaining gaps (e.g. duplicate logs, guide_id mismatches) are minor.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is 100%, so the baseline is 3, but the description adds genuine meaning: it explains why offset_value is available at this moment (reassembly), how disturbs_zero relates to a wipe-down that leaves the collar alone, and the unmeasured-epoch default. This contextualizes the numeric and enum parameters beyond their schema text.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The opening sentence gives a specific verb and resource: 'Log a cleaning or maintenance job against a piece of equipment.' It is distinct from siblings like list_maintenance_due (read due state) and set_maintenance_offset (write an offset directly), and the follow-on sentences further clarify scope. An agent can identify the operation 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?
It routes the agent to list_grinders and list_machines to read tasks, intervals and due state before logging, which establishes the read-then-write workflow. It also clarifies that any vocabulary task may be logged, even maker-discouraged ones. It does not explicitly contrast use against set_maintenance_offset or set_maintenance_schedule, but context is largely clear.
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 — 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. missed the timer — "~25s") | |
| 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?
Annotations only declare it is a non-idempotent, non-destructive write. The description adds real behavioral context beyond that: a tag-less, rating-less shot is filed 'taste-pending', the diagnosis engine reads tags/metrics not flavor_notes, and backdating changes the default diagnose_shot target. This is exactly the kind of hidden behavior an agent needs.
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, then each sentence carries a distinct usage rule with no filler. The sentences are dense and long, but each earns its place rather than padding.
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 and safety annotations, the description covers the decisive behaviors (override semantics, backdating, taste recording) completely. Return values are handled by the output schema, so nothing critical 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 moderate (67%) over 33 params, and the description adds meaning for the highest-risk ones (bean_id override rule, pulled_at backdating consequence, sensory_tags vs flavor_notes, tasted semantics) and cross-references list_beans' bags[]. It does not cover the many numeric/mechanical params, but compensates where it matters.
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 (log) and resource (shot/brew attempt), and the scope ('espresso or alternative') distinguishes it from siblings like update_shot and delete_shot. An agent can identify the operation 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?
Gives explicit when-to-use rules: ALWAYS pass bean_id when the user names a specific coffee, backdate with pulled_at, include sensory_tags when taste is reported, and pass tasted=1 for clean shots. These conditionals directly route correct invocation.
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?
Annotations already mark this destructive and non-idempotent, but the description goes far beyond them: it enumerates what migrates (bags, shots, recipes, recommendations), the special-case rules for the active coffee, origins moving only when the target has none, and the lock conflict resolution ('the newer lock wins and the older is deleted'). It also clarifies that the source is archived and never deleted, and warns 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?
Two dense sentences, front-loaded with the action and the condition, followed by the behavioral rules. Given the destructive and conflict-sensitive nature of the operation, every clause carries useful information and none 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 destructive merge with an output schema already covering the return value, the description supplies everything an agent needs: trigger condition, data migration rules, conflict resolution, archive-not-delete reassurance, irreversibility warning, and a verification path via list_beans.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is 100%, so all three parameters are already documented, giving a baseline of 3. The description nevertheless adds meaning beyond the schema by stating the direction of data flow ('of from_bean_id moves to into_bean_id') and clarifying the archive semantics of the emptied coffee.
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 situation that triggers it ('the same coffee was registered twice'). An agent can immediately distinguish this from siblings like update_bean or register_coffee 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?
The triggering condition is explicit ('when the same coffee was registered twice') and it names list_beans as the way to obtain and verify the two IDs, plus a prerequisite to confirm with the user. It does not, however, state when NOT to use it or contrast it against a plausible alternative such as update_bean.
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. | |
| 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 |
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 cover the safety profile (readOnlyHint=false, destructiveHint=false), so the description credits itself by adding non-obvious behavior: the existing coffee's recipes, notes and history are preserved, only purchase facts are new, the active coffee is untouched, and a bag_id is returned from a separate numbering series. It stops short of stating the practical consequence of idempotentHint=false (repeated calls create separate bags), which would be the natural next disclosure.
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 identity of the tool, then inheritance behavior, then the no-side-effect note, then the routing alternative. No filler or repetition of schema content; 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?
An output schema exists so return values need not be detailed, yet the description still explains the one surprising part of the return (bag_id belongs to its own series). Together with the routing rule and inheritance semantics, an agent has everything needed to invoke this correctly among the register_*/update_* 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?
With 62% schema coverage and 13 parameters, the schema already documents required formats and field meanings. The description adds a useful mental model by enumerating which inputs belong to the bag ('roast date, weight, price, state') versus the inherited coffee, and reinforces that bag_notes is about this bag only. It does not clarify the remaining fields like ean, qr_code, storage, or currency.
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 explicitly scopes it to a re-purchase of an existing coffee. It distinguishes itself from the closest sibling, register_coffee, without the agent needing to open either schema, and clarifies that bag numbers are a separate series from bean numbers.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Gives both the when ('a coffee that is already in list_beans — the same roaster's product, bought again') and the when-not with the alternative named ('For a coffee that is not in list_beans yet, call register_coffee instead'). It also notes the side effect that it does not change the active coffee, which is a routing-relevant condition.
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 | |
| 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 | ||
| 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?
Annotations declare non-readonly, non-destructive, non-idempotent, closed-world, but the description adds the crucial side-effect model: it does NOT switch the active coffee, becomes active only under stated conditions, and the reply's `active` field signals which happened. That's real behavioral disclosure 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?
Front-loads the core scope and sibling routing before the field taxonomy, and every sentence carries information. It is dense and slightly long, but for a 45-param registration tool the length is largely earned.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Covers the routing decision, active-state semantics, entity split, sibling alternative, and return identifiers (bean_id, bag_id), so an agent can call it correctly; the output schema carries the rest. The only gap is the long tail of optional coffee/bag attributes not addressed.
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 45 params at 44% schema coverage, the description compensates by grouping fields into coffee-level (roaster, origins, variety, process, roast level, roasting type, cupping score, aromatics, notes, rest window) versus bag-level (roast date, weight, price, state) — a semantic split the flat schema does not convey. It still leaves many optional params (ean, url, qr_code, arabica_pct, etc.) unexplained.
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+scope ('register a coffee that is NOT yet in list_beans, together with its first bag') and explicitly separates the coffee (roaster's product) from the bag (this purchase). This lets an agent distinguish it from register_bag and update_bean without opening schemas.
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 states when not to use it ('NOT yet in list_beans'), names the alternative for the existing-coffee case (register_bag, which keeps recipes/notes), and gives the routing rule to set_active 'when the user starts brewing it'. Covers when, when-not and alternative in one pass.
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 already declare the write/safety profile (readOnlyHint=false, destructiveHint=false, idempotentHint=false). The description adds genuine non-obvious behavior beyond that: registration does NOT force activation, and the reply's `active` field reveals which grinder is active. It does not cover auth requirements or side effects on existing grinders, so not a 5.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Three tightly scoped sentences, each earning its place: what it creates, the conditional activation behavior, and the fallback action. Front-loaded with the core action.
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-value explanation is not needed, yet the description still points to the meaningful `active` field of the reply. Combined with annotations covering write safety, the description is complete for the call, though it is silent on required-permission context for a 14-param mutation.
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 79%, so the schema already documents most of the 14 parameters. The description only obliquely touches parameter meaning ('manual or electric' -> motor_type, 'dial settings scheme' -> setting_scheme) and adds no syntax or format detail beyond structured data. Baseline 3 is appropriate.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
States a specific verb and resource ('Register a manual or electric grinder with its dial settings scheme') and clearly distinguishes itself from the sibling set_active by contrast. An agent can tell it apart from update_grinder/list_grinders 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?
Explicitly states the condition under which the new grinder becomes active (none active, or the active one archived) and names the alternative action (call set_active with its grinder_id) for the other case. This is prescriptive when-to-use guidance, not inference.
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 already declare the safety profile (readOnly=false, destructive=false, idempotent=false), so the bar is lower. The description adds genuine behavioral context beyond that: the conditional activation side-effect (only active when none active or the active one archived) and the resulting need to call set_active otherwise. It does not cover auth or error behavior, but the side-effect disclosure is the important one.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Three tight, front-loaded sentences with no filler, and the activation condition is stated before the alternative route to set_active. The closing sentence about the reply's 'active' field is mildly redundant given an output schema exists, but it is still useful signaling.
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 write tool with an output schema and annotations, the description supplies the critical missing piece — conditional activation and the set_active fallback — while the schema covers the bulk of parameter documentation. Auth and validation behavior are left implicit, but 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 coverage is 71%, so the schema largely documents the 14 parameters itself. The description adds no input-parameter meaning beyond the schema; its only field reference ('active') is an output field. Baseline 3 is appropriate when structured fields carry the parameter load.
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 ('Register') and resource ('espresso or alternative preparation machine'), and distinguishes itself from the sibling set_active by name. An agent can tell it apart from update_machine, register_grinder, and set_active 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?
Explicitly states the when ('becomes the active machine only when no machine is in use') and the when-not with a named alternative ('otherwise call set_active with its machine_id to switch to it'). This is textbook routing guidance.
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 scaleBInspect
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 are all negative hints (readOnlyHint=false, idempotentHint=false) and provide no positive behavioral profile. The description adds no side-effect transparency: it does not explain duplicate-name handling, whether registration overwrites, what the response contains, or whether the operation is reversible. For a write operation this is a notable gap.
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 and a useful clarifying clause. It is efficient and readable, though it leaves room for more substantive guidance.
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 input schema and output schema are comprehensive, so much of the operational detail is already structured. However, given the number of parameters and the sibling toolset, the description itself is thin on when to use it and what registering entails behaviorally. A little more context would make the tool fully self-explanatory.
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 carries rich, actionable descriptions, so the schema does the heavy lifting. The description adds only contextual flavor about what a brewing scale is; no additional parameter semantics are needed.
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 ('Register') and a clear resource ('brewing scale'), and adds domain context by defining the scale as 'the instrument that weighs the dose and the yield.' It is identifiable among siblings by object type, though it does not explicitly distinguish itself from other register_* tools.
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 implied by the name and description: use this when registering a new scale. However, there is no explicit guidance about when to prefer this over list_scales, register_grinder, or other sibling tools, and no mention of prerequisites or exclusions.
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?
Annotations already declare write (readOnlyHint false), destructiveHint true, and idempotentHint true. The description adds non-obvious behavioral context beyond that: zero is a legitimate recorded measurement distinct from omission, and omission clears the measurement back to unmeasured — which is exactly the destructive-ish overwrite an agent needs to understand before calling. No auth or rate-limit notes, so short of a 5.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Purpose and scope are front-loaded in the first clause, and each sentence carries information. The middle sentence about offsets composing 'for a recipe locked before all of them' is somewhat dense/indirect, costing a point.
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 annotations plus the 100%-covered schema carry most of the load. The description supplies the key domain caveats (entry-scoping, zero vs omission), leaving only explicit sibling routing as a minor 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 all four parameters are already documented in the schema, including the zero/omit semantics of offset_value. The description largely reframes rather than extends that (entry_id as 'the event that caused it', which enables composition), so the baseline of 3 applies.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
States a specific verb+resource: recording the calibration offset a maintenance job introduced, keyed to the epoch-opening entry. It also distinguishes scope from equipment-oriented siblings with 'Takes an ENTRY, not a piece of equipment.' Clear, though the prose is abstract enough that an agent must read a full sentence to extract the verb.
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 establishes the condition of applicability (an entry that opened a calibration epoch) and gives a concrete mode-selection rule: zero to record 'unchanged', omit offset_value to clear back to unmeasured. The 'entry, not equipment' line implicitly routes away from set_grinder_position, but no sibling tool is named explicitly and there is no explicit when-not.
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?
Annotations declare non-readOnly, destructive and idempotent, but the description adds real behavior beyond them: partial-update semantics ('only the keys you send in fields change'), reset-to-default via null, and stale-write protection ('an older edit never overwrites a newer one; it is then answered with applied: false'). It could say more about what is discarded when every:null is sent, but coverage is strong.
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, then mutation semantics, then usage guidance; each sentence carries weight and none is filler. It is dense but coherent, with only the final read-back sentence feeling slightly tacked on.
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 5-parameter nested mutation tool with an output schema and annotations, the description covers behavior, defaults, and usage. Output/return values need not be explained, though error or permission conditions are not addressed, leaving a small 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?
With 80% schema description coverage, the schema already documents every/muted_until null semantics and changed_at queuing, and the description largely restates those. It does consolidate the interval-basis rule ('whichever basis arrives first makes it due'), but adds little that isn't already structured.
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 ('Set the user's own schedule for one maintenance task on one grinder or machine') and enumerates the three modes: custom interval, disabling, muting. This clearly distinguishes it from siblings like set_maintenance_offset, list_maintenance_due and log_maintenance without opening a 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 a clear trigger ('when the user states how often they do a task or asks to be left alone about one') and an explicit exclusion ('never to invent an interval'), plus points to list_grinders/list_machines as the read source. It does not name a competing write sibling such as set_maintenance_offset, so it stops just short of full alternative routing.
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 |
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 description does not need to restate safety. It adds that the result is a 'single' step and comes 'from the reasoning engine,' which is useful, but it does not disclose anything about error behavior or the meaning of 'next.'
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The definition is a single, front-loaded sentence with no filler. 'Single' and 'reasoning engine' both earn their place by constraining the result.
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 one-parameter, read-only, idempotent tool with an output schema, the description is close to sufficient. However, it lacks any explanation of what a valid bean_id is, what 'next' means relative to, and when this tool should be selected, leaving some context for the agent to infer.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
The input schema has one required integer parameter, bean_id, with 0% schema description coverage, and the description never mentions bean_id or explains what values are valid. The name is somewhat self-explanatory, but the description adds no semantic 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 names a concrete operation ('Retrieve ... next experiment step') and a source ('reasoning engine'), so an agent can tell what the tool returns. It does not explicitly differentiate from sibling tools, but none has an obviously similar name.
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?
No guidance is given about when to call this tool versus alternatives such as diagnose_shot or log_recommendation, and no prerequisites or exclusions are mentioned. The intended use must be inferred from the name and one-line description.
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, idempotentHint=false and readOnlyHint=false, so the mutation/irreversibility profile is covered structurally. The description adds useful context beyond that: the enumeration of mutable bag-level facts and the scope boundary against update_bean. It does not, however, warn about downstream effects of state changes (freshness/age computation) or note that omitted fields are untouched.
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: what it changes, where bag numbers come from, and the sibling split. Front-loaded with the operation and 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 and annotations carrying the safety profile, the description supplies everything an agent needs to select and call this tool: scope, id provenance, field-level intent mapping, and the boundary against update_bean. Remaining per-field details (grams_remaining/weight_adjustment_g interactions) are already 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 coverage is 67% with a large nested fields object, and the description compensates by naming the concrete bag-level facts (roast date, weight, grams left, price) and by mapping user intent verbs (open/seal/freeze/thaw/finish) onto the underlying state field. That adds meaning beyond the raw schema, though it doesn't cover reason or weight_adjustment_g semantics.
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?
Specific verb ('change') plus a clearly scoped resource ('bag-level facts on one bag of a coffee'), and it enumerates the concrete operations (open, seal, freeze, thaw, finish, correct roast date/weight/grams/price). It explicitly distinguishes itself from update_bean for coffee-level attributes, so an agent can route 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 the alternative tool and the condition that selects it ('For the coffee itself — roaster, origin, roast level, rest window, notes — use update_bean'), and tells the agent where valid bag_ids come from (bags[] on list_beans or current_bag_id). Nothing is left to inference.
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 declare destructiveHint=true and idempotentHint=false, and the description adds the non-obvious behavioral consequence that changing dial_category alters the engine's advice (G5, C10) and that the routing of bag fields depends on bag count. It does not state that field updates replace stored values wholesale (that detail lives in the schema) nor discuss auth or reversibility.
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 'what' and followed by routing and side-effect warnings. No filler, though the parenthetical field lists are dense and the final sentence could be tighter.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Covers the essential call-time decisions: which fields belong here, where bag fields go, and the visible side effect of dial_category. Return values are omitted but an output schema exists, so that is acceptable. Missing: confirmation of whether unspecified fields are untouched and whether this is a partial update, which matters on a destructive, non-idempotent 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 33%, so the description must carry weight. It does: it explains which parameter keys are coffee-scoped versus bag-scoped and which are diverted to the current bag, plus a rationale for the optional reason note. It omits any interpretation of the reason append mechanic in field terms and the full field partition is left 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 and resource ('Update a coffee's own fields') and enumerates the coffee-scoped fields it accepts, which distinguishes it from update_bag. It stops short of a peerless 5 because the coffee/bag field split has to be inferred from examples rather than stated as a rule.
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 routing rule: bag-shaped fields sent here land on the CURRENT bag, and 'use update_bag when it has more than one' bag. That is explicit when-to-use guidance, but the guidance for non-current bags is incomplete and no guidance is given for shared fields that exist on both entities.
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?
Annotations already mark this destructive and non-idempotent, but the description adds substantial behavior beyond them: changes are recorded in the grinder's maintenance history, a locked recipe's setting move opens an unmeasured calibration epoch, the current setting is marked assumed or cleared, measured offsets are converted, and direction_convention is a non-numeric correction. These are exactly the side effects an agent must warn the user about.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Front-loaded with the core action, then the clearing rules, then the collar consequences. Every sentence carries information, but the paragraph is dense and several clauses run long, so it is efficient rather than crisp.
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 mutation tool with history, calibration-epoch, and offset side effects, the description covers the ripple effects thoroughly, and an output schema exists for dry_run's return shape. An agent has everything needed to invoke this 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?
Adds semantics the schema does not carry: null clears an optional field, an empty string clears a text field but not a number or closed list, required fields can be changed but not cleared, and fields may be omitted when only reason is sent. It also explains dry_run's returned keys, going beyond the schema's brief description.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
Starts with a specific verb and resource ("Correct a registered grinder") and enumerates exactly which attributes can be changed — name, burrs, collar scheme, nominal step, layout, range or notes. This distinguishes it from register_grinder and the other update_* siblings without needing to open a 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 a concrete workflow: call with dry_run first to see which recorded settings would shift, and tell the user before saving. Also states fields may be omitted when only reason is sent, and points to set_maintenance_offset for resolving an epoch. It stops short of explicitly naming sibling alternatives (e.g. update_machine) or exclusions, so it is strong context rather than full when/when-not routing.
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 already flag destructiveHint=true and idempotentHint=false, and the description adds the precise mechanics behind that: partial-update semantics ('only the keys you send in fields change'), null clears an optional field, empty string clears text but not numbers/closed lists, and required fields can be changed but not cleared. It also discloses that reason is appended to the record's own notes rather than stored separately.
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 operation and the change-application rule, then packs constraints and sibling routing into the closing sentences. Slight redundancy in restating that only 'espresso' is diagnosed after the schema already says so, but every sentence otherwise 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 partial-update mutation with an output schema and destructive annotations, the description covers the semantics an agent most needs: incremental change, clearing rules, and where adjacent operations live. It stops short of describing the response shape, which is acceptable given an output schema exists.
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 nested objects, so the schema carries much of the load, but the description adds cross-cutting meaning the schema cannot: the null-vs-empty-string clearing rule and the domain consequence of prep_style ('only espresso is diagnosed'). It explains the fields/omission interaction with reason, which is not expressible per-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?
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, settings). It further differentiates itself by naming siblings for adjacent operations (register_program, set_equipment_archived) rather than leaving the agent to guess.
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 states when fields may be omitted ('fields may be omitted when only reason is sent') and routes three separate concerns to other tools: programs to register_program, the built-in grinder link is 'not editable here', and archiving to set_equipment_archived. This is when-to-use plus when-not-to-use plus alternatives.
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?
Annotations already mark the call destructive and non-idempotent; the description goes further by explaining the exact destruction model — null clears optional fields, empty string clears only text, required fields cannot be cleared — and the meaning of the three capability integers. No annotation claims are contradicted.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The paragraph is front-loaded with purpose and then spends every sentence on a distinct rule (partial update, clearing, required fields, reason-only omission, capability encoding). 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?
For a destructive nested-update tool, the description covers what changes, how to clear values, and the special capability encoding; with an output schema present, return values need not be described. It omits permission/error behavior but is otherwise sufficient 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 67% schema description coverage, the description carries substantial weight and delivers: it explains partial-update semantics for fields, the null/empty-string clearing rules, and the 1/0/null encoding for capabilities. It does not document every nested property (e.g., resolution_g, water_resistance), so it stops short of 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?
The description opens with a specific verb ('Correct') and resource ('registered scale'), and enumerates the attribute groups that can be changed (type, resolution, capacity, capabilities, build, notes). It does not name sibling alternatives like register_scale, but the wording 'registered scale' implicitly scopes it to existing records.
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 rules for when a field should be sent, cleared, or omitted, which tells the agent how to use the tool. However, it never names an alternative tool or states a condition for choosing update_scale over register_scale or set_equipment_archived, so alternative selection is left implicit.
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 — 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 declare mutation/destructive/idempotent traits, and the description adds behavior beyond them: changing grind_label re-derives the numeric grind position, and changing yield/time/dose/tds keeps flow rate and extraction yield consistent automatically. These cascading side effects are exactly the non-obvious behavior an agent needs and cannot get from 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?
Front-loaded with the core operation, then use cases, then side effects—each sentence carries distinct information. Slightly dense, but no sentence is disposable.
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 needn't be described, and with 100% schema coverage the field list is covered. The description supplies the cascading-behavior context a correct invocation depends on, leaving nothing material missing.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is 100%, so the baseline is 3, but the description adds cross-field semantics: bean_id re-filing and the automatic re-derivation triggered by grind_label vs the consistency-keeping of yield/time/dose/tds. This goes beyond the per-field schema text without fully restating every 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+resource ('Correct fields on an already-logged shot in place') and immediately distinguishes itself from the delete-and-re-log workflow. An agent can tell it apart from sibling delete_shot and log_shot without opening a 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 when-to-use cases: fixing a wrong dose/yield/time or grind label, re-filing onto the right bean, backfilling rating/tasting notes, or correcting the timestamp. The 'no need to delete and re-log' clause routes the agent away from delete_shot, functioning as an explicit alternative.
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?
Goes well beyond the annotations (destructiveHint=true, idempotentHint=false) by spelling out the mutation contract: partial updates touch only supplied keys, null clears an optional field, empty string clears text but not numbers or closed lists, and required fields can be changed but not cleared. That is exactly the behavioral detail an agent needs to avoid unintentionally wiping a water recipe's mineral figures.
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, and the following sentences are dense but each one carries a distinct, necessary rule about clearing and omission. No filler or restatement of the title.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a mutation tool with annotations covering safety and a present output schema, the description covers the update contract, clearing rules and the reason-only case. It omits permission/error expectations, but nothing that would cause an agent to mis-invoke the 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?
With 67% schema coverage the description carries real weight: it defines the semantics of the nested fields object (which keys change, how to clear values) rather than just listing them, and clarifies the reason parameter's effect. The water_id parameter is already well documented in the schema, so the description adds little there.
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/update) and resource (a registered water) and enumerates the mutable surface — name, type, mineral figures, notes. The word 'registered' implicitly separates it from register_water, so an agent can route correctly without opening a 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?
Usage is implied by the partial-update semantics ('only the keys you send change') and the note that fields may be omitted when only reason is sent, which tells the agent this is an edit-existing-record tool. However, it never names an alternative (register_water, delete_shot-style removal, list_waters for lookup) or states prerequisites such as needing a valid water_id from list_waters beyond the schema's own note.
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.
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" +]
34 tool updates
- Changed
compute_age1 field changed- changed
Output schema / (root)Previous value: -nullNew value: +{ + "additionalProperties": true, + "properties": { + "age_days": { + "type": "integer" + }, + "bean_id": { + "type": "integer" + }, + "days_off_roast": { + "type": "integer" + }, + "days_since_opened": { + "type": "null" + }, + "effective_age_days": { + "type": "integer" + }, + "frozen_days_excluded": { + "type": "integer" + }, + "grams_remaining": { + "type": "null" + }, + "rest_window": { + "type": "string" + }, + "roast_date": { + "type": "string" + }, + "verdict": { + "type": "string" + }, + "warnings": { + "type": "array" + } + }, + "required": [ + "bean_id", + "roast_date", + "age_days", + "days_off_roast", + "days_since_opened", + "frozen_days_excluded", + "effective_age_days", + "rest_window", + "verdict", + "grams_remaining", + "warnings" + ], + "type": "object" +}
- Changed
delete_shot1 field changed- changed
Output schema / (root)Previous value: -nullNew value: +{ + "additionalProperties": true, + "properties": { + "deleted_shot_id": { + "type": "integer" + }, + "message": { + "type": "string" + }, + "status": { + "type": "string" + } + }, + "required": [ + "status", + "deleted_shot_id", + "message" + ], + "type": "object" +}
- Changed
diagnose_preview1 field changed- changed
Output schema / (root)Previous value: -nullNew value: +{ + "additionalProperties": true, + "properties": { + "bean_context": { + "additionalProperties": true, + "properties": { + "bean_id": { + "type": "integer" + }, + "bean_name": { + "type": "string" + }, + "dial_category": { + "type": "string" + }, + "effective_age_days": { + "type": "integer" + }, + "roast_level": { + "type": "string" + } + }, + "required": [ + "bean_id", + "bean_name", + "roast_level", + "effective_age_days", + "dial_category" + ], + "type": "object" + }, + "category": { + "type": "string" + }, + "facts": { + "items": { + "additionalProperties": true, + "properties": { + "source": { + "type": "string" + }, + "text": { + "type": "string" + } + }, + "required": [ + "text", + "source" + ], + "type": "object" + }, + "type": "array" + }, + "hypotheses": { + "items": { + "additionalProperties": true, + "properties": { + "cause": { + "type": "string" + }, + "cited_rules": { + "items": { + "type": "string" + }, + "type": "array" + }, + "confidence": { + "type": "string" + }, + "direction": { + "type": "string" + }, + "experiment": { + "type": "string" + }, + "lever": { + "type": "string" + }, + "target_label": { + "type": "string" + } + }, + "required": [ + "cause", + "lever", + "direction", + "confidence", + "experiment", + "cited_rules" + ], + "type": "object" + }, + "type": "array" + }, + "kb_version": { + "type": "string" + }, + "one_variable_only": { + "type": "boolean" + }, + "warnings": { + "items": { + "type": "string" + }, + "type": "array" + } + }, + "required": [ + "category", + "facts", + "hypotheses", + "warnings", + "one_variable_only", + "kb_version", + "bean_context" + ], + "type": "object" +}
- Changed
diagnose_shot1 field changed- changed
Output schema / (root)Previous value: -nullNew value: +{ + "additionalProperties": true, + "properties": { + "bean_context": { + "additionalProperties": true, + "properties": { + "bean_id": { + "type": "integer" + }, + "bean_name": { + "type": "string" + }, + "dial_category": { + "type": "string" + }, + "effective_age_days": { + "type": "integer" + }, + "roast_level": { + "type": "string" + } + }, + "required": [ + "bean_id", + "bean_name", + "roast_level", + "effective_age_days", + "dial_category" + ], + "type": "object" + }, + "category": { + "type": "string" + }, + "facts": { + "items": { + "additionalProperties": true, + "properties": { + "source": { + "type": "string" + }, + "text": { + "type": "string" + } + }, + "required": [ + "text", + "source" + ], + "type": "object" + }, + "type": "array" + }, + "hypotheses": { + "items": { + "additionalProperties": true, + "properties": { + "cause": { + "type": "string" + }, + "cited_rules": { + "items": { + "type": "string" + }, + "type": "array" + }, + "confidence": { + "type": "string" + }, + "direction": { + "type": "string" + }, + "experiment": { + "type": "string" + }, + "lever": { + "type": "string" + }, + "target_label": { + "type": "string" + } + }, + "required": [ + "cause", + "lever", + "direction", + "confidence", + "experiment", + "cited_rules" + ], + "type": "object" + }, + "type": "array" + }, + "kb_version": { + "type": "string" + }, + "one_variable_only": { + "type": "boolean" + }, + "warnings": { + "items": { + "type": "string" + }, + "type": "array" + } + }, + "required": [ + "category", + "facts", + "hypotheses", + "warnings", + "one_variable_only", + "kb_version", + "bean_context" + ], + "type": "object" +}
- Changed
get_dial_state1 field changed- changed
Output schema / (root)Previous value: -nullNew value: +{ + "additionalProperties": true, + "properties": { + "active_coffee": { + "additionalProperties": true, + "properties": { + "age_days": { + "type": "integer" + }, + "age_verdict": { + "type": "string" + }, + "archived": { + "type": "integer" + }, + "aromatics": { + "type": "null" + }, + "attachments": { + "type": "null" + }, + "bag_notes": { + "type": "string" + }, + "bag_weight_g": { + "type": "null" + }, + "bean_mix": { + "type": "null" + }, + "best_by_date": { + "type": "null" + }, + "buy_date": { + "type": "null" + }, + "co2e_kg": { + "type": "null" + }, + "cost": { + "type": "null" + }, + "cupping_points": { + "type": "null" + }, + "currency": { + "type": "null" + }, + "days_off_roast": { + "type": "integer" + }, + "days_since_opened": { + "type": "null" + }, + "decaffeinated": { + "type": "null" + }, + "dial_category": { + "type": "string" + }, + "ean": { + "type": "null" + }, + "effective_age_days": { + "type": "integer" + }, + "favourite": { + "type": "null" + }, + "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" + }, + "is_active": { + "type": "integer" + }, + "name": { + "type": "string" + }, + "opened_date": { + "type": "null" + }, + "origin": { + "type": "null" + }, + "process_type": { + "type": "string" + }, + "qr_code": { + "type": "null" + }, + "rating": { + "type": "null" + }, + "rest_window_days_max": { + "type": "null" + }, + "rest_window_days_min": { + "type": "null" + }, + "roast_custom": { + "type": "null" + }, + "roast_date": { + "type": "string" + }, + "roast_level": { + "type": "string" + }, + "roast_range": { + "type": "null" + }, + "roaster": { + "type": "string" + }, + "roasting_type": { + "type": "null" + }, + "state": { + "type": "string" + }, + "storage": { + "type": "null" + }, + "unfrozen_at": { + "type": "null" + }, + "url": { + "type": "null" + }, + "variety": { + "type": "null" + }, + "weight_adjustment_g": { + "type": "integer" + } + }, + "required": [ + "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" + ], + "type": "object" + }, + "active_grinder": { + "additionalProperties": true, + "properties": { + "archived": { + "type": "integer" + }, + "built_in_machine_id": { + "type": "null" + }, + "burr_type": { + "type": "string" + }, + "components_spec": { + "type": "string" + }, + "direction_convention": { + "type": "string" + }, + "id": { + "type": "integer" + }, + "is_active": { + "type": "integer" + }, + "max_value": { + "type": "null" + }, + "microns_per_step": { + "type": "integer" + }, + "min_value": { + "type": "null" + }, + "motor_type": { + "type": "string" + }, + "name": { + "type": "string" + }, + "nominal_step": { + "type": "integer" + }, + "notes": { + "type": "null" + }, + "photo": { + "type": "null" + }, + "position_value": { + "type": "integer" + }, + "setting_components": { + "type": "string" + }, + "setting_label": { + "type": "string" + }, + "setting_scheme": { + "type": "string" + }, + "source": { + "type": "string" + }, + "verified_at": { + "type": "string" + } + }, + "required": [ + "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" + ], + "type": "object" + }, + "active_machine": { + "additionalProperties": true, + "properties": { + "archived": { + "type": "integer" + }, + "basket_size_grams": { + "type": "integer" + }, + "boiler_type": { + "type": "string" + }, + "built_in_grinder_id": { + "type": "null" + }, + "connected_device": { + "type": "null" + }, + "control_type": { + "type": "string" + }, + "id": { + "type": "integer" + }, + "is_active": { + "type": "integer" + }, + "name": { + "type": "string" + }, + "notes": { + "type": "null" + }, + "photo": { + "type": "null" + }, + "prep_style": { + "type": "null" + }, + "prep_type": { + "type": "null" + }, + "tools": { + "type": "null" + } + }, + "required": [ + "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" + ], + "type": "object" + }, + "active_program": { + "type": "null" + }, + "locked_recipe": { + "type": "null" + }, + "recent_recommendations": { + "type": "array" + }, + "recent_shots": { + "type": "array" + } + }, + "required": [ + "active_coffee", + "active_grinder", + "active_machine", + "active_program", + "recent_shots", + "recent_recommendations", + "locked_recipe" + ], + "type": "object" +}
- Changed
get_kb_version1 field changed- changed
Output schema / (root)Previous value: -nullNew value: +{ + "additionalProperties": true, + "properties": { + "kb_version": { + "type": "string" + } + }, + "required": [ + "kb_version" + ], + "type": "object" +}
- Changed
get_rule1 field changed- changed
Output schema / (root)Previous value: -nullNew value: +{ + "additionalProperties": true, + "properties": { + "rule_id": { + "type": "string" + }, + "text": { + "type": "string" + } + }, + "required": [ + "rule_id", + "text" + ], + "type": "object" +}
- Changed
get_stats1 field changed- changed
Output schema / (root)Previous value: -nullNew value: +{ + "additionalProperties": true, + "properties": { + "beans_consumed": { + "type": "integer" + }, + "brews": { + "type": "integer" + }, + "effective_age": { + "type": "integer" + }, + "grams_consumed": { + "type": "integer" + }, + "grams_ground": { + "type": "integer" + }, + "grams_remaining": { + "type": "integer" + }, + "last_bean": { + "type": "null" + }, + "last_grind_setting": { + "type": "null" + }, + "last_used": { + "type": "null" + } + }, + "required": [ + "brews" + ], + "type": "object" +}
- Changed
grinder_math1 field changed- changed
Output schema / (root)Previous value: -nullNew value: +{ + "additionalProperties": true, + "properties": { + "burr_gap_travel_microns": { + "type": "integer" + }, + "direction": { + "type": "string" + }, + "relative_coarseness_note": { + "type": "string" + }, + "step_unit": { + "type": "string" + }, + "steps": { + "type": "integer" + } + }, + "required": [ + "direction", + "steps", + "step_unit", + "burr_gap_travel_microns", + "relative_coarseness_note" + ], + "type": "object" +}
- Changed
kb_changelog1 field changed- changed
Output schema / (root)Previous value: -nullNew value: +{ + "additionalProperties": true, + "properties": { + "changelog": { + "type": "string" + } + }, + "required": [ + "changelog" + ], + "type": "object" +}
- Changed
list_beans1 field changed- changed
Output schema / (root)Previous value: -nullNew value: +{ + "additionalProperties": true, + "properties": { + "beans": { + "items": { + "additionalProperties": true, + "properties": { + "age_verdict": { + "type": "string" + }, + "archived": { + "type": "integer" + }, + "bag_notes": { + "type": "string" + }, + "bag_weight_g": { + "type": "null" + }, + "cost": { + "type": "null" + }, + "currency": { + "type": "null" + }, + "days_off_roast": { + "type": "integer" + }, + "days_since_opened": { + "type": "null" + }, + "decaffeinated": { + "type": "null" + }, + "dial_category": { + "type": "string" + }, + "effective_age_days": { + "type": "integer" + }, + "favourite": { + "type": "null" + }, + "finished": { + "type": "integer" + }, + "frozen_days_excluded": { + "type": "integer" + }, + "grams_remaining": { + "type": [ + "null", + "integer" + ] + }, + "id": { + "type": "integer" + }, + "name": { + "type": "string" + }, + "opened_date": { + "type": "null" + }, + "origins": { + "type": "array" + }, + "process_type": { + "type": "string" + }, + "rating": { + "type": "null" + }, + "rest_window_days_max": { + "type": "null" + }, + "rest_window_days_min": { + "type": "null" + }, + "roast_date": { + "type": "string" + }, + "roast_level": { + "type": "string" + }, + "roaster": { + "type": "string" + }, + "shots_remaining": { + "type": "integer" + }, + "shots_remaining_basis": { + "type": "string" + }, + "shots_remaining_dose_g": { + "type": "number" + }, + "shots_remaining_sample": { + "type": "null" + }, + "state": { + "type": "string" + }, + "storage": { + "type": "null" + } + }, + "required": [ + "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" + ], + "type": "object" + }, + "type": "array" + } + }, + "required": [ + "beans" + ], + "type": "object" +}
- Changed
list_grinders1 field changed- changed
Output schema / (root)Previous value: -nullNew value: +{ + "additionalProperties": true, + "properties": { + "grinders": { + "items": { + "additionalProperties": true, + "properties": { + "archived": { + "type": "integer" + }, + "built_in_machine_id": { + "type": "null" + }, + "burr_type": { + "type": "string" + }, + "components_spec": { + "type": "string" + }, + "direction_convention": { + "type": "string" + }, + "id": { + "type": "integer" + }, + "maintenance": { + "additionalProperties": true, + "properties": { + "calibration": { + "additionalProperties": true, + "properties": { + "epoch_at": { + "type": "string" + }, + "epoch_id": { + "type": "integer" + }, + "evidence": { + "type": "null" + }, + "offset_at": { + "type": "null" + }, + "offset_source": { + "type": "null" + }, + "offset_unit": { + "type": "string" + }, + "offset_value": { + "type": "null" + }, + "stale_recipe_count": { + "type": "integer" + }, + "state": { + "type": "string" + } + }, + "required": [ + "stale_recipe_count", + "state", + "epoch_id", + "epoch_at", + "offset_value", + "offset_unit", + "offset_source", + "offset_at", + "evidence" + ], + "type": "object" + }, + "due": { + "additionalProperties": true, + "properties": { + "burr_clean": { + "additionalProperties": true, + "properties": { + "basis": { + "type": "string" + }, + "done": { + "type": "integer" + }, + "every": { + "type": "integer" + }, + "last_at": { + "type": "string" + }, + "ratio": { + "type": "number" + }, + "remaining": { + "type": "integer" + }, + "state": { + "type": "string" + } + }, + "required": [ + "state", + "ratio", + "basis", + "every", + "done", + "remaining", + "last_at" + ], + "type": "object" + } + }, + "required": [ + "burr_clean" + ], + "type": "object" + }, + "entries": { + "items": { + "additionalProperties": true, + "properties": { + "created_at": { + "type": "string" + }, + "details": { + "type": "null" + }, + "details_known": { + "type": "boolean" + }, + "details_version": { + "type": "integer" + }, + "disturbs_zero": { + "type": "integer" + }, + "equipment_id": { + "type": "integer" + }, + "equipment_kind": { + "type": "string" + }, + "evidence": { + "type": [ + "null", + "string" + ] + }, + "id": { + "type": "integer" + }, + "note": { + "type": [ + "string", + "null" + ] + }, + "offset_at": { + "type": [ + "null", + "string" + ] + }, + "offset_source": { + "type": [ + "null", + "string" + ] + }, + "offset_value": { + "type": [ + "null", + "integer" + ] + }, + "performed_at": { + "type": "string" + }, + "task": { + "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", + "details_known" + ], + "type": "object" + }, + "type": "array" + }, + "sensitivity": { + "type": "null" + }, + "tasks": { + "items": { + "additionalProperties": true, + "properties": { + "details_fields": { + "type": "array" + }, + "details_version": { + "type": "integer" + }, + "disturbs_note": { + "type": "string" + }, + "disturbs_zero": { + "type": "boolean" + }, + "every": { + "additionalProperties": true, + "properties": { + "days": { + "type": "integer" + }, + "grams": { + "type": "integer" + }, + "shots": { + "type": "integer" + } + }, + "required": [ + "days", + "shots", + "grams" + ], + "type": "object" + }, + "kind": { + "type": "string" + }, + "label": { + "type": "string" + }, + "offset_integral": { + "type": "boolean" + }, + "offset_unit": { + "type": "string" + }, + "sub": { + "type": "string" + }, + "value": { + "type": "string" + }, + "why": { + "type": "string" + } + }, + "required": [ + "value", + "kind", + "label", + "sub", + "disturbs_zero", + "every", + "why", + "disturbs_note", + "offset_unit", + "offset_integral", + "details_version", + "details_fields" + ], + "type": "object" + }, + "type": "array" + } + }, + "required": [ + "tasks", + "due", + "calibration", + "sensitivity", + "entries" + ], + "type": "object" + }, + "max_value": { + "type": "null" + }, + "microns_per_step": { + "type": "integer" + }, + "min_value": { + "type": "null" + }, + "motor_type": { + "type": "string" + }, + "name": { + "type": "string" + }, + "nominal_step": { + "type": "integer" + }, + "notes": { + "type": "null" + }, + "position_value": { + "type": "integer" + }, + "setting_components": { + "type": "string" + }, + "setting_label": { + "type": "string" + }, + "setting_scheme": { + "type": "string" + }, + "source": { + "type": "string" + }, + "verified_at": { + "type": "string" + } + }, + "required": [ + "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" + ], + "type": "object" + }, + "type": "array" + } + }, + "required": [ + "grinders" + ], + "type": "object" +}
- Changed
list_machines1 field changed- changed
Output schema / (root)Previous value: -nullNew value: +{ + "additionalProperties": true, + "properties": { + "machines": { + "items": { + "additionalProperties": true, + "properties": { + "archived": { + "type": "integer" + }, + "basket_size_grams": { + "type": "integer" + }, + "boiler_type": { + "type": "string" + }, + "built_in_grinder_id": { + "type": "null" + }, + "control_type": { + "type": "string" + }, + "id": { + "type": "integer" + }, + "name": { + "type": "string" + }, + "notes": { + "type": "null" + }, + "prep_style": { + "type": "null" + }, + "prep_type": { + "type": "null" + }, + "programs": { + "items": { + "additionalProperties": true, + "properties": { + "description": { + "type": "string" + }, + "id": { + "type": "integer" + }, + "is_active": { + "type": "integer" + }, + "program_number": { + "type": "integer" + }, + "program_type": { + "type": "string" + }, + "target_time_s": { + "type": "null" + }, + "target_volume_g": { + "type": "integer" + }, + "volume_source": { + "type": "string" + } + }, + "required": [ + "id", + "program_number", + "program_type", + "target_volume_g", + "target_time_s", + "volume_source", + "description", + "is_active" + ], + "type": "object" + }, + "type": "array" + }, + "tools_list": { + "type": "array" + } + }, + "required": [ + "id", + "name", + "control_type", + "basket_size_grams", + "boiler_type", + "notes", + "prep_type", + "prep_style", + "archived", + "built_in_grinder_id", + "tools_list", + "programs" + ], + "type": "object" + }, + "type": "array" + } + }, + "required": [ + "machines" + ], + "type": "object" +}
- Changed
list_recipes1 field changed- changed
Output schema / (root)Previous value: -nullNew value: +{ + "additionalProperties": true, + "properties": { + "recipes": { + "items": { + "additionalProperties": true, + "properties": { + "bean_id": { + "type": "integer" + }, + "bean_name": { + "type": "string" + }, + "dose_g": { + "type": "number" + }, + "drink_intent": { + "type": "string" + }, + "finish_action": { + "type": "string" + }, + "grind_label": { + "type": "string" + }, + "grind_position_value": { + "type": "integer" + }, + "grind_reading": { + "additionalProperties": true, + "properties": { + "epochs_since": { + "type": "integer" + }, + "label": { + "type": "null" + }, + "offset_clicks": { + "type": "null" + }, + "offset_direction": { + "type": "null" + }, + "unmeasured": { + "type": "integer" + } + }, + "required": [ + "label", + "offset_clicks", + "offset_direction", + "epochs_since", + "unmeasured" + ], + "type": "object" + }, + "grinder_id": { + "type": "integer" + }, + "grinder_name": { + "type": "string" + }, + "id": { + "type": "integer" + }, + "locked_at": { + "type": "string" + }, + "machine_id": { + "type": "integer" + }, + "machine_name": { + "type": "string" + }, + "profile": { + "type": "string" + }, + "program_id": { + "type": "integer" + }, + "status": { + "type": "string" + }, + "target_time_s": { + "type": "integer" + }, + "target_yield_g": { + "type": [ + "number", + "integer" + ] + } + }, + "required": [ + "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" + ], + "type": "object" + }, + "type": "array" + } + }, + "required": [ + "recipes" + ], + "type": "object" +}
- Changed
list_scales1 field changed- changed
Output schema / (root)Previous value: -nullNew value: +{ + "additionalProperties": true, + "properties": { + "scales": { + "type": "array" + } + }, + "required": [ + "scales" + ], + "type": "object" +}
- Changed
list_shots1 field changed- changed
Output schema / (root)Previous value: -nullNew value: +{ + "additionalProperties": true, + "properties": { + "shots": { + "type": "array" + }, + "total": { + "type": "integer" + } + }, + "required": [ + "shots", + "total" + ], + "type": "object" +}
- Changed
list_waters1 field changed- changed
Output schema / (root)Previous value: -nullNew value: +{ + "additionalProperties": true, + "properties": { + "waters": { + "type": "array" + } + }, + "required": [ + "waters" + ], + "type": "object" +}
- Changed
lock_recipe1 field changed- changed
Output schema / (root)Previous value: -nullNew value: +{ + "additionalProperties": true, + "properties": { + "message": { + "type": "string" + }, + "status": { + "type": "string" + } + }, + "required": [ + "status", + "message" + ], + "type": "object" +}
- Added
log_maintenance - Changed
log_recommendation1 field changed- changed
Output schema / (root)Previous value: -nullNew value: +{ + "additionalProperties": true, + "properties": { + "message": { + "type": "string" + }, + "status": { + "type": "string" + } + }, + "required": [ + "status", + "message" + ], + "type": "object" +}
- Changed
log_shot1 field changed- changed
Output schema / (root)Previous value: -nullNew value: +{ + "additionalProperties": true, + "properties": { + "message": { + "type": "string" + }, + "shot_id": { + "type": "integer" + }, + "status": { + "type": "string" + } + }, + "required": [ + "status", + "shot_id", + "message" + ], + "type": "object" +}
- Changed
register_coffee7 fields changed- changed
Input schema / properties / best_by_date / descriptionPrevious value: -"Date in YYYY-MM-DD format"New value: +"Calendar day in YYYY-MM-DD format — a day, not a timestamp" - changed
Input schema / properties / buy_date / descriptionPrevious value: -"Date in YYYY-MM-DD format"New value: +"Calendar day in YYYY-MM-DD format — a day, not a timestamp" - changed
Input schema / properties / frozen_at / descriptionPrevious value: -"Datetime in YYYY-MM-DD HH:MM:SS format"New value: +"Calendar day the bag went into the freezer, YYYY-MM-DD — a day, not a timestamp" - added
Input schema / properties / opened_date / descriptionAdded value: +"Calendar day in YYYY-MM-DD format — a day, not a timestamp" - changed
Input schema / properties / roast_date / descriptionPrevious value: -"Date in YYYY-MM-DD format"New value: +"Calendar day in YYYY-MM-DD format — a day, not a timestamp" - changed
Input schema / properties / unfrozen_at / descriptionPrevious value: -"Datetime in YYYY-MM-DD HH:MM:SS format"New value: +"Calendar day the bag came out, YYYY-MM-DD — a day, not a timestamp" - changed
Output schema / (root)Previous value: -nullNew value: +{ + "additionalProperties": true, + "properties": { + "bean_id": { + "type": "integer" + }, + "message": { + "type": "string" + }, + "status": { + "type": "string" + } + }, + "required": [ + "status", + "bean_id", + "message" + ], + "type": "object" +}
- Changed
register_grinder1 field changed- changed
Output schema / (root)Previous value: -nullNew value: +{ + "additionalProperties": true, + "properties": { + "grinder_id": { + "type": "integer" + }, + "message": { + "type": "string" + }, + "status": { + "type": "string" + } + }, + "required": [ + "status", + "grinder_id", + "message" + ], + "type": "object" +}
- Changed
register_machine3 fields changed- changed
Input schema / properties / prep_style / descriptionPrevious value: -"Preparation style category, e.g., espresso, filter, immersion"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
Input schema / properties / prep_type / descriptionPrevious value: -"Preparation equipment type, e.g., espresso_machine, v60_dripper, French_press"New value: +"Preparation equipment type. One of: espresso_machine, lever_press, moka_pot, aeropress, french_press, v60_dripper, cold_brew. Lower snake_case." - changed
Output schema / (root)Previous value: -nullNew value: +{ + "additionalProperties": true, + "properties": { + "machine_id": { + "type": "integer" + }, + "message": { + "type": "string" + }, + "status": { + "type": "string" + } + }, + "required": [ + "status", + "machine_id", + "message" + ], + "type": "object" +}
- Changed
register_program1 field changed- changed
Output schema / (root)Previous value: -nullNew value: +{ + "additionalProperties": true, + "properties": { + "message": { + "type": "string" + }, + "program_id": { + "type": "integer" + }, + "status": { + "type": "string" + } + }, + "required": [ + "status", + "program_id", + "message" + ], + "type": "object" +}
- Changed
register_scale1 field changed- changed
Output schema / (root)Previous value: -nullNew value: +{ + "additionalProperties": true, + "properties": { + "message": { + "type": "string" + }, + "scale_id": { + "type": "integer" + }, + "status": { + "type": "string" + } + }, + "required": [ + "status", + "scale_id", + "message" + ], + "type": "object" +}
- Changed
register_water1 field changed- changed
Output schema / (root)Previous value: -nullNew value: +{ + "additionalProperties": true, + "properties": { + "message": { + "type": "string" + }, + "status": { + "type": "string" + }, + "water_id": { + "type": "integer" + } + }, + "required": [ + "status", + "water_id", + "message" + ], + "type": "object" +}
- Changed
set_active1 field changed- changed
Output schema / (root)Previous value: -nullNew value: +{ + "additionalProperties": true, + "properties": { + "message": { + "type": "string" + }, + "status": { + "type": "string" + } + }, + "required": [ + "status", + "message" + ], + "type": "object" +}
- Changed
set_equipment_archived1 field changed- changed
Output schema / (root)Previous value: -nullNew value: +{ + "additionalProperties": true, + "properties": { + "message": { + "type": "string" + }, + "status": { + "type": "string" + } + }, + "required": [ + "status", + "message" + ], + "type": "object" +}
- Changed
set_grinder_position1 field changed- changed
Output schema / (root)Previous value: -nullNew value: +{ + "additionalProperties": true, + "properties": { + "grinder_id": { + "type": "integer" + }, + "message": { + "type": "string" + }, + "position_value": { + "type": "integer" + }, + "setting_label": { + "type": "string" + }, + "source": { + "type": "string" + }, + "status": { + "type": "string" + } + }, + "required": [ + "status", + "grinder_id", + "setting_label", + "position_value", + "source", + "message" + ], + "type": "object" +}
- Added
set_maintenance_offset - Changed
suggest_next_step1 field changed- changed
Output schema / (root)Previous value: -nullNew value: +{ + "additionalProperties": true, + "properties": { + "category": { + "type": "string" + }, + "next_step": { + "type": "string" + }, + "warnings": { + "items": { + "type": "string" + }, + "type": "array" + } + }, + "required": [ + "next_step", + "category", + "warnings" + ], + "type": "object" +}
- Changed
update_bean9 fields changed- changed
Input schema / properties / fields / properties / best_by_date / descriptionPrevious value: -"Date in YYYY-MM-DD format"New value: +"Calendar day in YYYY-MM-DD format — a day, not a timestamp" - changed
Input schema / properties / fields / properties / buy_date / descriptionPrevious value: -"Date in YYYY-MM-DD format"New value: +"Calendar day in YYYY-MM-DD format — a day, not a timestamp" - changed
Input schema / properties / fields / properties / frozen_at / descriptionPrevious value: -"Datetime in YYYY-MM-DD HH:MM:SS format"New value: +"Calendar day the bag went into the freezer, YYYY-MM-DD — a day, not a timestamp" - added
Input schema / properties / fields / properties / opened_date / descriptionAdded value: +"Calendar day in YYYY-MM-DD format — a day, not a timestamp" - changed
Input schema / properties / fields / properties / roast_date / descriptionPrevious value: -"Date in YYYY-MM-DD format"New value: +"Calendar day in YYYY-MM-DD format — a day, not a timestamp" - changed
Input schema / properties / fields / properties / unfrozen_at / descriptionPrevious value: -"Datetime in YYYY-MM-DD HH:MM:SS format"New value: +"Calendar day the bag came out, YYYY-MM-DD — a day, not a timestamp" - changed
Input schema / properties / reason / descriptionPrevious value: -"A clear justification why this category/roast level is updated."New value: +"Optional free-text note, appended to the bag notes as an ordinary line. Omit it and nothing is written." - changed
Input schema / requiredPrevious value: -[ - "bean_id", - "fields", - "reason" -]New value: +[ + "bean_id", + "fields" +] - changed
Output schema / (root)Previous value: -nullNew value: +{ + "additionalProperties": true, + "properties": { + "message": { + "type": "string" + }, + "status": { + "type": "string" + } + }, + "required": [ + "status", + "message" + ], + "type": "object" +}
- Changed
update_shot1 field changed- changed
Output schema / (root)Previous value: -nullNew value: +{ + "additionalProperties": true, + "properties": { + "message": { + "type": "string" + }, + "shot_id": { + "type": "integer" + }, + "status": { + "type": "string" + }, + "updated_fields": { + "items": { + "type": "string" + }, + "type": "array" + } + }, + "required": [ + "status", + "shot_id", + "updated_fields", + "message" + ], + "type": "object" +}
3 tool updates
- Added
list_scales - Added
register_scale - Changed
set_equipment_archived1 field changed- changed
Input schema / properties / kind / enumPrevious value: -[ - "grinder", - "machine", - "water" -]New value: +[ + "grinder", + "machine", + "water", + "scale" +]
1 tool update
- Changed
register_machine1 field changed- added
Input schema / properties / built_in_grinder_idAdded value: +{ + "description": "id of a grinder built into this machine (bean-to-cup / integrated grinder)", + "type": "integer" +}
Related MCP Servers
- 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.1611 npm1MIT
- AlicenseCqualityBmaintenanceCompetitor Monitor AI - MCP server providing AI-powered tools and automation by MEOK AI Labs117 npm54 PyPIMIT
- AlicenseAqualityCmaintenanceRevnuvo Company Intelligence tells AI agents what changed at a company, with evidence. It observes company websites, technologies, and DNS over time and returns timestamped, confidence-aware changes, signals, and monitoring.9MIT

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.