kobox defines 9 tools with complete input schemas and descriptions. Naming follows verb_noun convention (list_ports, connect, trigger_pad, play_note, play_pattern, play_scale, list_scales, device_info). Descriptions are present and contextual (avg ~120 chars), exceeding the 10-char minimum. However, descriptions lack actionable guidance on when to use each tool vs. alternatives, and error handling is generic ('Error: {e}' strings). Output schemas are not formally documented, responses are inferred from code (list_ports returns List[str], device_info returns Dict). Parameters have types and defaults but lack constraint documentation (e.g., velocity 0-127, channel 1-16 are stated in descriptions but not as JSON Schema constraints). No tool annotations (readOnlyHint, destructiveHint) despite clear read/write semantics. Error messages do not guide recovery (e.g., 'Error: Not connected' should suggest 'Call connect() first'). Composition is sound, each tool has one responsibility, and output IDs chain correctly (e.g., connect returns port_name, which is stored for later use).
Connect to a MIDI device. With no arguments, auto-detects the EP-133 K.O. II.
Return grounded device facts: pad-group note ranges and channel behavior.
Disconnect from the current MIDI device.
List all available MIDI output ports.
List supported scales and their semitone patterns.
Play a single MIDI note (0-127) or note name like 'C3'/'F#4'.
Play a sequence of hits. Each event is {pad|note, velocity?, duration?}. Example: [{"pad": "A1", "duration": 0.1}, {"note": "C3"}]
Output schemas not formally documented. Responses are inferred from code (list_ports → List[str], device_info → Dict). LLMs cannot plan downstream calls without knowing field names and types.
Error handling is generic. All tools catch exceptions and return 'Error: {e}' strings. LLMs receive no guidance on recovery (e.g., 'Not connected' should suggest 'Call connect() first').
No tool annotations despite clear semantics. list_ports, list_scales, device_info are read-only; connect, disconnect, trigger_pad, play_note, play_pattern, play_scale are destructive/write. Annotations (readOnlyHint, destructiveHint) enable agents to reason about side effects.
| Scored | Grade | Overall | Spec posture | Rubric |
|---|---|---|---|---|
| 2026-09-23 | D | 58 | 2026-07-28+ | v2 |
Play a melody as scale degrees (1-based; 0 = rest; negatives go down an octave). Example: root='C', scale='major', sequence=[1,2,3,4,5,6,7,8] plays an ascending C major scale.
Trigger a pad by group + printed keypad label, e.g. 'A.', 'A0', 'Aenter', 'A1'..'A9', 'D9'. The label is the symbol printed on the K.O. II keypad, NOT a 1-12 index. In a group the labels run . 0 enter 1 2 3 4 5 6 7 8 9 from lowest note upward, so 'A1' is the pad printed "1" (the 4th pad), and 'A.' is the lowest.
Parameter constraints not formalized in JSON Schema. velocity (0-127), channel (1-16), duration (>0), and octave ranges are documented in descriptions but not as minValue/maxValue in schema. LLMs cannot validate before calling.
Descriptions lack actionable guidance on tool selection. 'Play a single MIDI note' does not explain when to use play_note vs trigger_pad vs play_pattern. LLMs must infer intent from context alone.